13. November 2023 By Marc Mezger
A brief introduction to the Rust programming language
What is Rust?
Rust is a modern, system-level programming language designed to offer high levels of performance, reliability and productivity. It grew out of a personal project of Mozilla employee Graydon Hoare. In 2009, Mozilla began sponsoring the project, which was officially announced in 2010 for the first time. That same year, the shift away from the initial compiler to a new one began. This compiler, which was written in Rust and goes by the name ‘rustc’, uses LLVM as its backend and has been able to successfully compile itself since 2011. The first stable version of the compiler and standard library, Rust 1.0, was released on 15 May 2015.
Rust was developed to create a language that avoids the security vulnerabilities and memory errors that are common in other system-level languages such as C or C++. It offers a variety of features that make it an excellent choice for a wide variety of software projects.
People who use the Rust programming language refer to themselves as Rustaceans, a pun on crustaceans. This community of Rust enthusiasts is known for their support for and collaboration in efforts to make Rust a more secure and efficient programming language.
What makes Rust so special?
Memory safety without a garbage collector
Rust offers a high degree of memory safety without the use of a garbage collector. This is made possible thanks to the concept of ‘ownership’, which establishes rules for borrowing and lifetimes. Rust is thus able to prevent memory access errors without the need for a runtime check, which improves application performance.
fn main() {
let s1 = String::from("hello");
let mut s2 = s1; // s1 ist hier nicht mehr gültig
s2.push_str(", world"); // s2 ist nun "hello, world"
println!("{}", s2);
// Wenn wir versuchen, s1 zu verwenden, wird der Compiler einen Fehler ausgeben
// println!("{}", s1); // Dieser Code verursacht einen Kompilierungsfehler
}
In this code, we first create the variable s1 with the value ‘hello’. We then assign s1 to s2. In Rust, this means that s1 is ‘borrowed’ from s2 and s1 is no longer valid from this point forward. If we try to use s1 after it has been assigned to s2, the Rust borrow checker outputs an error as s1 is no longer valid.
The borrow checker in Rust ensures that references are always valid. It also blocks data from being deleted or modified while it is still being referenced, which prevents a number of errors that often occur in other languages.
In a slightly more complex example, we could use the borrow checker to ensure that we do not change a data structure while we are reading it:
fn main() {
let mut s = String::from("hello");
let r1 = &s; // Kein Problem
let r2 = &s; // Kein Problem
println!("{} and {}", r1, r2);
let r3 = &mut s; // Problem!
println!("{}", r3);
}
In this code, we have two immutable references to s (r1 and r2). In the next step, we attempt to create a mutable reference to s (r3). The Rust borrow checker will not compile this code, because it blocks us from changing s while r1 and r2 reference it. This is another example of how the Rust borrow checker helps to prevent race conditions and other types of errors.
Zero-cost abstractions
Rust is a unique programming language that allows developers to work at a high level of abstraction without having to sacrifice performance. Known as zero-cost abstraction, this principle is at the core of Rust’s philosophy and is a key thing that sets this language apart from many others. The concept of zero-cost abstraction is a simple but powerful one. Under it, abstract constructs and higher-order programming concepts embedded in the language can be used without having a negative impact on execution speed or efficiency. In other words, the abstractions that Rust makes available have no additional runtime cost compared to their handwritten, less abstract counterparts. Rust allows developers to write code that is as fast and efficient as optimised low-level code, while also taking advantage of high-level abstractions that make programming easier and more secure. This lets them focus on solving the actual problem at hand without having to worry about how their high-level abstractions might affect performance.
Another advantage of Rust’s zero-cost abstractions is that they allow developers to maintain precise control over system resources, similar to low-level system programming languages. This makes Rust ideal for applications where performance is critical, as is the case with system programming, embedded systems and performance-critical web applications.
The ability to work at a high level of abstraction without sacrificing performance makes Rust an interesting option for developers who are looking to combine the control and efficiency of system-level programming with the simplicity and security of higher-level abstractions.
struct Point {
x: i32,
y: i32,
}
impl Point {
fn new(x: i32, y: i32) -> Point {
Point { x, y }
}
fn distance(&self, other: &Point) -> f64 {
let x_diff = other.x - self.x;
let y_diff = other.y - self.y;
((x_diff.pow(2) + y_diff.pow(2)) as f64).sqrt()
}
}
fn main() {
let p1 = Point::new(0, 0);
let p2 = Point::new(5, 3);
println!("Distance: {}", p1.distance(&p2));
}
In this code we define a ‘struct Point’ using the x and y fields. We implement one method (new) to create new point instances and another (distance) to calculate the distance between two points.
Although we work at a high level with points and methods, the resulting machine code is just as efficient as if we had performed the calculations by hand. This is an example of a zero-cost abstraction, which allows us to use abstract, easy-to-understand constructs without compromising performance.
This comes in really handy in large, complex codebases, where the use of abstractions can help to make the code cleaner and easier to understand without sacrificing execution speed.
Concurrency without race conditions
Rust’s type system and ownership concept help prevent race conditions, making it an excellent choice for systems that need to run concurrently or in parallel, two examples of this being operating systems and web servers.
Cargo package manager
Rust’s integrated package manager, Cargo, significantly improves project management, dependency tracking and the build process, helping produce a better, well-structured development workflow. Here is an interesting historical fact: Rust has the distinction of being the first system programming language to integrate a standardised package manager. This pioneering step has led to the development of an exceptionally robust and comprehensive Rust ecosystem.
[workspace]
resolver = "2"
members = [
"crates/*",
"credential/*",
"benches/benchsuite",
"benches/capture",
]
exclude = [
"target/", # exclude bench testing
]
[workspace.package]
rust-version = "1.73" # MSRV:1
edition = "2021"
license = "MIT OR Apache-2.0"
[workspace.dependencies]
anstream = "0.6.4"
anstyle = "1.0.4"
anyhow = "1.0.75"
base64 = "0.21.5"
bytesize = "1.3"
cargo = { path = "" }
Efficient C interoperability
Rust can easily interact with C, enabling developers to make existing C code more secure without having to rewrite the entire code. This is incredibly useful with systems that have already been written in C.
Active community and voted most admired language
Rust has an active and growing community. Rust was voted the most admired programming language in the Stack Overflow Developer Survey for several years in a row. The community offers a host of resources and libraries as well as excellent documentation.
These make Rust a very appealing option for developers looking for a secure, efficient and modern programming language.
Use cases for Rust
Known for its ability to deliver top performance while maintaining a high level of memory safety, Rust has proven to be a great choice for a variety of use cases over the years. Rust offers a combination of security, modern tooling and a dedicated community, making it a fantastic tool for many applications.
- System programming: Rust’s focus on zero-cost abstractions and direct hardware access makes it the perfect choice for system programming. It allows developers to write operating systems, file systems, browsers and more that are efficient, while at the same time providing the memory safety that such systems require.
- WebAssembly: Rust has proved to be an excellent option for working with WebAssembly (WASM), a binary format that enables fast, secure and portable applications on the web. Developers can use Rust and WASM to create powerful frontend applications that offer near-native speed.
- Embedded systems: Rust’s ability to manage system resources and operate without a garbage collector makes it a great choice for embedded systems. It allows developers to access the hardware directly and benefit from Rust’s memory safety guarantees.
- Web servers and network services: Rust offers performant concurrency and excellent security, making it a great choice for creating web servers and network services. Libraries such as Tokio and Actix make it easy to create secure, high-performance network applications.
Who uses Rust?
Rust is used by a number of major companies to meet their technological needs.
Amazon Web Services, Amazon’s cloud unit, uses Rust to develop high-performance/security infrastructure networks and other system software. Microsoft Corporation, one of the founding members of the Rust Foundation, uses Rust in its Rust for Windows project, which makes it possible to use any Windows API with the help of Rust. Meta, formerly known as Facebook, has used Rust in a number of projects, including the controversial Libra cryptocurrency and blockchain project.
Dropbox used Rust as part of a larger project to improve the efficiency of data centres, whereby several components of its core file storage system were also written in Rust. Mozilla Corporation, the first investor in Rust, built Stylo, its CSS engine, using Rust, whereas Cloudflare, a company specialising in web infrastructure and website security, uses Rust because it offers world-class WebAssembly support and a thriving ecosystem.
Other companies such as Coursera, Discord, Figma and npm have also recognised the advantages of Rust and use it in their tech stack. That Rust is so widely used at these leading companies highlights the performance and versatility offered by the language in real-world applications.
Outlook
In future blog posts, I will be taking a closer look at the topics of ‘Rewrite Everything in Rust’ and ‘Rust in Python’, as I look to demonstrate the versatility of Rust and highlight its integration with other commonly used languages such as Python.
I hope this short introduction to Rust has sparked your interest in learning more about the programming language. Regardless of whether you are an experienced developer or just getting started, Rust offers a unique perspective and a rewarding challenge for users of every skill level. I encourage you to explore the possibilities that Rust has to offer and look forward to accompanying you on this exciting journey.
Would you like to find out more about exciting topics from the world of adesso? Then take a look at our previous blog posts.