knowledge/technology/dev/programming/languages/Rust.md
2025-04-07 16:19:55 +02:00

80 KiB
Raw Blame History

website source mime extension obj rev
https://www.rust-lang.org https://doc.rust-lang.org/book text/rust rs concept 2024-09-03

Rust

Rust is a statically-typed programming language known for its emphasis on performance, safety, and concurrency. Originally developed by Mozilla, Rust has gained popularity for its ability to provide low-level control over system resources without sacrificing memory safety. Rust uses Cargo as its package manager and build tool.

Syntax

Your application starts within the main function, so the simplest application is this:

fn main() {

}

Variables

You can declare variables. Variables are immutable by default, if you need to change them you have to use the mut keyword. Every variable is strongly typed, but you can either ommit type information and let the compiler infer the type or explicitly state it. Constants which never change can be made as well.

let var = "Hello";
let mut mutable = "World";
let explicit_num: isize = 0;
const NINE_K: isize = 9000;

Data Types & Ownership

Every variable in Rust is strongly typed. You can define your own types and use the compiler together with an algebraic type system to your advantage.

In Rust, primitive types are classified into two categories: scalar types and compound types:

Scalar Types

  1. Integers:
    • i8: Signed 8-bit integer
    • i16: Signed 16-bit integer
    • i32: Signed 32-bit integer
    • i64: Signed 64-bit integer
    • i128: Signed 128-bit integer
    • u8: Unsigned 8-bit integer
    • u16: Unsigned 16-bit integer
    • u32: Unsigned 32-bit integer
    • u64: Unsigned 64-bit integer
    • u128: Unsigned 128-bit integer
    • isize: Platform-dependent signed integer
    • usize: Platform-dependent unsigned integer
  2. Floating-point:
    • f32: 32-bit floating-point number
    • f64: 64-bit floating-point number
  3. Characters:
    • char: A Unicode character (4 bytes)
  4. Booleans:
    • bool: Boolean type representing either true or false

Compound Types

  1. Arrays:
    • [T; N]: Fixed-size array of elements of type T and length N
  2. Tuples:
    • (T1, T2, ..., Tn): Heterogeneous collection of elements of different types

Pointer Types

  1. References:
    • &T: Immutable reference
    • &mut T: Mutable reference
  2. Raw Pointers:
    • *const T: Raw immutable pointer
    • *mut T: Raw mutable pointer

Rust enforces some rules on variables in order to be memory safe. So there are three kinds of variables you could have:

  • Owned Variable T: You are the owner of this variable with data type T
  • Reference &T: You have a read only reference of the variables content
  • Mutable Reference &mut T: You have a modifiable reference to the variable

Note: If a function does not need to mutate or own a variable, consider using a reference

Conditionals

Conditionals like if and match can be used, while match can do more powerful pattern matching than if.

let age = 20;
if age > 18 {
    println!("Adult");
} else if age == 18 {
    println!("Exactly 18");
} else {
    println!("Minor");
}

match age {
    18 => println!("Exactly 18"),
    _ => println!("Everything else")
}

Loops

There are three types of loops.

loop {
    println!("Going on until time ends");
}

for item in list {
    println!("This is {item}");
}

while condition {
    println!("While loop");
}

You can break out of a loop or continue to the next iteration:

for i in 0..10 {
    if i % 2 == 0 {
        continue
    }
    if i % 5 == 0 {
        break;
    }
    println!("{i}");
}

If you have nested loops you can label them and use break and continue on specific loops:

'outer_loop: for i in 0..10 {
    'inner_loop: for x in 0..10 {
        if (x*i) > 40 {
            continue 'outer_loop;
        }
        print("{x} {i}");
    }
}

Functions

One can use functions with optional arguments and return types. If you return on the last line, you can ommit the return keyword and ; to return the value.

fn printHello() {
    println!("Hello");
}

fn greet(name: &str) {
    println!("Hello {name}");
}

fn add_two(a: isize) -> isize {
    a + 2 // same as "return a + 2;"
}

The default return type of a function is the Unit Type (). You can also signal that a function will never return with !

fn infinity() -> ! {
    loop {}
}

Enums

Rust has enums which can even hold some data.

enum StatusCode {
    NOT_FOUND,
    OK,
    Err(String)
}

let err_response = StatusCode::Err(String::from("Internal Error"));

match err_response {
    StatusCode::Ok => println!("Everything is fine"),
    StatusCode::NOT_FOUND => println!("Not found");
    StatusCode::Err(err) => println!("Some error: {err}"); // will print "Some error: Internal Error"
}

// other way to pattern match for a single pattern
if let StatusCode::Err(msg) = err_response {
    println!("{msg}!");
}

Structs

Rust has some object-oriented features like structs.

struct Person {
    first_name: String,
    age: isize
}

impl Person {
    fn new(first_name: &str) -> Self {
        Self {
            first_name: first_name.to_string(),
            age: 0
        }
    }

    fn greet(&self) {
        println!("Hello {}", self.first_name);
    }

	fn get_older(&mut self) {
		self.age += 1;
	}
}

Comments

Rust has support for comments. There are regular comments, multiline comments and documentation comments. Documentation comments get used when generating documation via cargo doc and inside the IDE.

// This is a comment

/*
This
is multiline
comment
*/

/// This function does something.
/// Documentation comments can be styled with markdown as well.
/// 
/// # Example
///
/// If you place a rust code block here, you can provide examples on how to use this function and `cargo test` will automatically run this code block when testing.
/// If you don't want cargo to run the test inside doc comments, add "ignore" to the head of the code block.
fn do_something() {

}

Modules

You can split your code up into multiple modules for better organization.

// will search for `mymod.rs` or `mymod/mod.rs` beside the source file and include it as `mymod`;
mod mymod;

// inline module
mod processor {
    struct AMD {
        name: String
    }
}

fn main() {
    // full syntax
    let proc = processor::AMD{ name: "Ryzen".to_string() };

    // you can put often used symbols in scope
    use processor::AMD;
    let proc = AMD{ name: "Ryzen".to_string() };
}

Generics

Generics let you write code for multiple data types without repeating yourself. Instead of an explicit data type, you write your code around a generic type.

struct Point<T> {
    x: T,
    y: T,
}

impl<T> Point<T> {
    fn x(&self) -> &T {
        &self.x
    }
}

// you can declare methods which only work for specific data types.
impl Point<f32> {
    fn distance_from_origin(&self) -> f32 {
        (self.x.powi(2) + self.y.powi(2)).sqrt()
    }
}

impl<X1, Y1> Point<X1, Y1> {
    // define generic types on functions
    fn mixup<X2, Y2>(self, other: Point<X2, Y2>) -> Point<X1, Y2> {
        Point {
            x: self.x,
            y: other.y,
        }
    }
}

enum Option<T> {
    Some(T),
    None,
}

// you can have multiple generic types
enum Result<T, E> {
    Ok(T),
    Err(E),
}

Traits

Traits let you define shared behavior on structs. You define what methods a struct should have and it is up the the struct to implement them.

pub trait Summary {
    fn summarize(&self) -> String;
}

// you can define default behaviour
pub trait DefaultSummary {
    fn summarize(&self) -> String {
        String::from("(Read more...)")
    }
}

pub struct NewsArticle {
    pub headline: String,
    pub location: String,
    pub author: String,
    pub content: String,
}

impl Summary for NewsArticle {
    fn summarize(&self) -> String {
        format!("{}, by {} ({})", self.headline, self.author, self.location)
    }
}

pub struct Tweet {
    pub username: String,
    pub content: String,
    pub reply: bool,
    pub retweet: bool,
}

impl Summary for Tweet {
    fn summarize(&self) -> String {
        format!("{}: {}", self.username, self.content)
    }
}

// use traits as parameters
pub fn notify(item: &impl Summary) {
    println!("Breaking news! {}", item.summarize());
}

// you can also restrict generic types to only ones that implement certain traits
pub fn notify<T: Summary>(item: &T) {
    println!("Breaking news! {}", item.summarize());
}

// even multiple at once
pub fn notify<T: Summary + Display>(item: &T) {}

// another way to restrict types to traits
fn some_function<T, U>(t: &T, u: &U) -> i32
where
    T: Display + Clone,
    U: Clone + Debug,
{}

// you can restrict at impl level too
struct Pair<T> {
    x: T,
    y: T,
}

impl<T> Pair<T> {
    fn new(x: T, y: T) -> Self {
        Self { x, y }
    }
}

impl<T: Display + PartialOrd> Pair<T> {
    // this function is only available if T has Display and PartialOrd
    fn cmp_display(&self) {
        if self.x >= self.y {
            println!("The largest member is x = {}", self.x);
        } else {
            println!("The largest member is y = {}", self.y);
        }
    }
}

Common traits you can implement on your types are:

  • Clone: Allows creating a duplicate of an object.
pub trait Clone {
    fn clone(&self) -> Self;
}
  • Copy: Types that can be copied by simple bitwise copying.
pub trait Copy: Clone {}
  • Debug: Enables formatting a value for debugging purposes.
pub trait Debug {
    fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>;
}
  • Default: Provides a default value for a type.
pub trait Default {
    fn default() -> Self;
}
  • Eq and PartialEq: Enables equality comparisons.
pub trait Eq: PartialEq<Self> {}

pub trait PartialEq<Rhs: ?Sized = Self> {
    fn eq(&self, other: &Rhs) -> bool;
}
  • Ord and PartialOrd: Enables ordering comparisons.
pub trait Ord: Eq + PartialOrd<Self> {
    fn cmp(&self, other: &Self) -> Ordering;
}

pub trait PartialOrd<Rhs: ?Sized = Self>: PartialEq<Rhs> {
    fn partial_cmp(&self, other: &Rhs) -> Option<Ordering>;
}
  • Iterator: Represents a sequence of values.
pub trait Iterator {
    type Item;
    fn next(&mut self) -> Option<Self::Item>;
    // Other iterator methods...
}
  • Read and Write: For reading from and writing to a byte stream.
pub trait Read {
    fn read(&mut self, buf: &mut [u8]) -> Result<usize, Error>;
}

pub trait Write {
    fn write(&mut self, buf: &[u8]) -> Result<usize, Error>;
}
  • Fn, FnMut, and FnOnce: Traits for function types with different levels of mutability.
pub trait Fn<Args> {
    // function signature
}

pub trait FnMut<Args>: Fn<Args> {
    // function signature
}

pub trait FnOnce<Args>: FnMut<Args> {
    // function signature
}
  • Drop: Specifies what happens when a value goes out of scope.
pub trait Drop {
    fn drop(&mut self);
}
  • Deref and DerefMut: Used for overloading dereference operators.
pub trait Deref {
    type Target: ?Sized;
    fn deref(&self) -> &Self::Target;
}

pub trait DerefMut: Deref {
    fn deref_mut(&mut self) -> &mut Self::Target;
}
  • AsRef and AsMut: Allows types to be used as references.
pub trait AsRef<T: ?Sized> {
    fn as_ref(&self) -> &T;
}

pub trait AsMut<T: ?Sized>: AsRef<T> {
    fn as_mut(&mut self) -> &mut T;
}
  • Index and IndexMut: Enables indexing into a data structure.
pub trait Index<Idx: ?Sized> {
    type Output: ?Sized;
    fn index(&self, index: Idx) -> &Self::Output;
}

pub trait IndexMut<Idx: ?Sized>: Index<Idx> {
    fn index_mut(&mut self, index: Idx) -> &mut Self::Output;
}
  • Send and Sync: Indicate whether a type is safe to be transferred between threads (Send) or shared between threads (Sync).
unsafe trait Send {}
unsafe trait Sync {}
  • Into and From: Facilitates conversions between types.
pub trait Into<T> {
    fn into(self) -> T;
}

pub trait From<T> {
    fn from(T) -> Self;
}
  • Display: Formatting values for user display.
pub trait Display {
    fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>;
}
  • FromStr and ToString: Enables conversion between strings and other types.
pub trait FromStr {
    type Err;
    fn from_str(s: &str) -> Result<Self, Self::Err>;
}

pub trait ToString {
    fn to_string(&self) -> String;
}
  • Error: Represents errors that can occur during the execution of a program.
pub trait Error: Debug {
    fn source(&self) -> Option<&(dyn Error + 'static)>;
}
  • Add, Sub, Mul, and Div: Traits for arithmetic operations.
pub trait Add<RHS = Self> {
    type Output;
    fn add(self, rhs: RHS) -> Self::Output;
}

// Similar traits for Sub, Mul, and Div

Closures

Closures are anonymous functions. They can be assigned to variables, passed as parameters or returned from a function.

fn  add_one_v1   (x: u32) -> u32 { x + 1 }
let add_one_v2 = |x: u32| -> u32 { x + 1 };
let add_one_v3 = |x|             { x + 1 };
let add_one_v4 = |x|               x + 1  ;

// this function takes ownership over variables it uses as noted by `move`
thread::spawn(
    move || println!("From thread: {:?}", list)
    ).join().unwrap();

// To use closures as parameters, specify the type. It is one of the Fn traits
impl<T> Option<T> {
    pub fn unwrap_or_else<F>(self, f: F) -> T
    where
        F: FnOnce() -> T
    {
        match self {
            Some(x) => x,
            None => f(),
        }
    }
}

Iterators

The iterator pattern allows you to perform some task on a sequence of items in turn. An iterator is responsible for the logic of iterating over each item and determining when the sequence has finished. When you use iterators, you dont have to reimplement that logic yourself.

let v1 = vec![1, 2, 3];
let v1_iter = v1.iter();
let v2: Vec<_> = v1.iter().map(|x| x + 1).collect();

With this you can do functional programming with the iterators.

Some functions on them include:

  • chain(other): An iterator that links two iterators together, in a chain.
  • cloned(): An iterator that clones the elements of an underlying iterator.
  • copied(): An iterator that copies the elements of an underlying iterator.
  • cycle(): An iterator that repeats endlessly.
  • empty(): An iterator that yields nothing.
  • enumerate(): An iterator that yields the current count and the element during iteration.
  • filter(predicate): An iterator that filters the elements of iter with predicate.
  • filterMap(f): An iterator that uses f to both filter and map elements from iter.
  • flat_map(f): An iterator that maps each element to an iterator, and yields the elements of the produced iterators.
  • flatten(): An iterator that flattens one level of nesting in an iterator of things that can be turned into iterators.
  • from_fn(f): An iterator where each iteration calls the provided closure F: FnMut() -> Option<T>.
  • fuse(): An iterator that yields None forever after the underlying iterator yields None once.
  • inspect(f): An iterator that calls a function with a reference to each element before yielding it.
  • map(f): An iterator that maps the values of iter with f.
  • map_while(f): An iterator that only accepts elements while predicate returns Some(_).
  • once(value): An iterator that yields an element exactly once.
  • peekable(): An iterator with a peek() that returns an optional reference to the next element.
  • repeat(value): An iterator that repeats an element endlessly.
  • rev(): A double-ended iterator with the direction inverted.
  • skip(n): An iterator that skips over n elements of iter.
  • skip_while(f): An iterator that rejects elements while predicate returns true.
  • step_by(n): An iterator for stepping iterators by a custom amount.
  • successors(first, f): A new iterator where each successive item is computed based on the preceding one.
  • take(n): An iterator that only iterates over the first n iterations of iter.
  • take_while(f): An iterator that only accepts elements while predicate returns true.
  • zip(a, b): An iterator that iterates two other iterators simultaneously.
  • sum(): Sum up an iterators values

Standard Library

Rust, a systems programming language known for its focus on safety and performance, comes with a rich standard library that provides a wide range of modules to handle common tasks.

  1. std::collections: Data structures like Vec, HashMap, etc.
  2. std::fs: File system manipulation and I/O operations.
  3. std::thread: Facilities for concurrent programming with threads.
  4. std::time: Time-related types and functionality.
  5. std::io: Input and output facilities.
  6. std::path: Path manipulation utilities.
  7. std::env: Interface to the environment, command-line arguments, etc.
  8. std::string: String manipulation utilities.
  9. std::cmp: Comparison traits and functions.
  10. std::fmt: Formatting traits and utilities.
  11. std::result: Result type and related functions.
  12. std::error: Error handling utilities.
  13. std::sync: Synchronization primitives.
  14. std::net: Networking functionality.
  15. std::num: Numeric types and operations.
  16. std::char: Character manipulation utilities.
  17. std::mem: Memory manipulation utilities.
  18. std::slice: Slice manipulation operations.
  19. std::marker: Marker traits for influencing Rust's type system.

Macros

Weve used macros like println! before, but we havent fully explored what a macro is and how it works. The term macro refers to a family of features in Rust: declarative macros with macro_rules! and three kinds of procedural macros:

  • Custom #[derive] macros that specify code added with the derive attribute used on structs and enums
  • Attribute-like macros that define custom attributes usable on any item
  • Function-like macros that look like function calls but operate on the tokens specified as their argument

Fundamentally, macros are a way of writing code that writes other code, which is known as metaprogramming. All of these macros expand to produce more code than the code youve written manually.

Declarative macros work almost like a match statement.

macro_rules! mymacro {
	($expression:expr) => {
		println!("{}", $expression)
	};
	($expression:expr, $other:expr) => {
		println!("{} {}", $expression, $other)
	};
}

mymacro!("Hello World");
mymacro!("Hello", "World");

This macro gets expanded to the code inside the macro_rules! section with the provided arguments. For more information on macros, see the docs.

Macros work kind of like a match statement. In the matcher, $ name : fragment-specifier matches a Rust syntax fragment of the kind specified and binds it to the metavariable $name. Valid fragment specifiers are:

  • item: an Item
  • block: a BlockExpression
  • stmt: a Statement without the trailing semicolon (except for item statements that require semicolons)
  • pat_param: a PatternNoTopAlt
  • pat: at least any PatternNoTopAlt, and possibly more depending on edition
  • expr: an Expression
  • ty: a Type
  • ident: an IDENTIFIER_OR_KEYWORD or RAW_IDENTIFIER
  • path: a TypePath style path
  • tt: a TokenTree (a single token or tokens in matching delimiters (), [], or {})
  • meta: an Attr, the contents of an attribute
  • lifetime: a LIFETIME_TOKEN
  • vis: a possibly empty Visibility qualifier
  • literal: matches -?LiteralExpression

Common Rust Macros:

  • assert!(bool): Asserts that a boolean expression is true at runtime.
  • assert_eq!(a, b): Asserts that two expressions are equal to each other (using PartialEq).
  • assert_ne!(a, b): Asserts that two expressions are not equal to each other (using PartialEq).
  • debug_assert!(bool) Asserts that a boolean expression is true at runtime.
  • debug_assert_eq!(a, b): Asserts that two expressions are equal to each other.
  • debug_assert_ne!(a, b): Asserts that two expressions are not equal to each other.
  • module_path!(): Expands to a string that represents the current module path.
  • file!(): Expands to the file name in which it was invoked.
  • line!(): Expands to the line number on which it was invoked.
  • column!(): Expands to the column number at which it was invoked.
  • concat!(): Concatenates literals into a static string slice.
  • cfg!(): Evaluates boolean combinations of configuration flags at compile-time.
  • compile_error!(msg): Causes compilation to fail with the given error message when encountered.
  • panic!(): Panics the current thread.
  • dbg!(): Prints and returns the value of a given expression for quick and dirty debugging.
  • env!(var): Inspects an environment variable at compile time.
  • option_env!(var): Optionally inspects an environment variable at compile time.
  • print!(): Prints to the standard output.
  • println!(): Prints to the standard output, with a newline.
  • eprint!(): Prints to the standard error.
  • eprintln!(): Prints to the standard error, with a newline.
  • format!(): Creates a String using interpolation of runtime expressions.
  • write!(): Writes formatted data into a buffer.
  • writeln!(): Write formatted data into a buffer, with a newline appended.
  • include!(): Parses a file as an expression or an item according to the context.
  • include_bytes!(): Includes a file as a reference to a byte array.
  • include_str!(): Includes a UTF-8 encoded file as a string.
  • matches!(): Returns whether the given expression matches the provided pattern.
  • todo!(): Indicates unfinished code.
  • unimplemented!(): Indicates unimplemented code by panicking with a message of “not implemented”.
  • unreachable!(): Indicates unreachable code.
  • vec![]: Creates a Vec containing the arguments.

Procedural Macros

Procedural macros allow creating syntax extensions as execution of a function. Procedural macros come in one of three flavors:

  • Function-like macros - custom!(...)
  • Derive macros - #[derive(CustomDerive)]
  • Attribute macros - #[CustomAttribute]

Procedural macros allow you to run code at compile time that operates over Rust syntax, both consuming and producing Rust syntax. You can sort of think of procedural macros as functions from an AST to another AST.

As functions, they must either return syntax, panic, or loop endlessly. Returned syntax either replaces or adds the syntax depending on the kind of procedural macro. Panics are caught by the compiler and are turned into a compiler error. Endless loops are not caught by the compiler which hangs the compiler.

Procedural macros have two ways of reporting errors. The first is to panic. The second is to emit a compile_error! macro invocation.

Procedural macros must be in their own crate. Use this Cargo.toml as a start:

[lib]
proc-macro = true

[dependencies]
syn = "2.0"
quote = "1.0"

Defining the macro:

use proc_macro::TokenStream;
use quote::quote;

#[proc_macro_derive(HelloMacro)]
pub fn hello_macro_derive(input: TokenStream) -> TokenStream {
    // Construct a representation of Rust code as a syntax tree
    // that we can manipulate
    let ast = syn::parse(input).unwrap();

    // Build the trait implementation
    let name = &ast.ident;
    let gen = quote! {
        impl HelloMacro for #name {
            fn hello_macro() {
                println!("Hello, Macro! My name is {}!", stringify!(#name));
            }
        }
    };
    gen.into()
}

Weve introduced three new crates: proc_macro, syn, and quote. The proc_macro crate comes with Rust, so we didnt need to add that to the dependencies in Cargo.toml. The proc_macro crate is the compilers API that allows us to read and manipulate Rust code from our code. The syn crate parses Rust code from a string into a data structure that we can perform operations on. The quote crate turns syn data structures back into Rust code. These crates make it much simpler to parse any sort of Rust code we might want to handle.

The hello_macro_derive function will be called when a user of our library specifies #[derive(HelloMacro)] on a type. This is possible because weve annotated the hello_macro_derive function here with proc_macro_derive and specified the name HelloMacro, which matches our trait name; this is the convention most procedural macros follow.

The quote! macro lets us define the Rust code that we want to return. The compiler expects something different to the direct result of the quote! macros execution, so we need to convert it to a TokenStream. We do this by calling the .into() method, which consumes this intermediate representation and returns a value of the required TokenStream type.

The quote! macro also provides some very cool templating mechanics: we can enter #name, and quote! will replace it with the value in the variable name. You can even do some repetition similar to the way regular macros work. Check out the quote crates docs for a thorough introduction.

Attribute-like macros

Attribute-like macros are similar to custom derive macros, but instead of generating code for the derive attribute, they allow you to create new attributes. Theyre also more flexible: derive only works for structs and enums; attributes can be applied to other items as well, such as functions. Heres an example of using an attribute-like macro: say you have an attribute named route that annotates functions when using a web application framework:

#[route(GET, "/")]
fn index() {}

This #[route] attribute would be defined by the framework as a procedural macro. The signature of the macro definition function would look like this:

#[proc_macro_attribute]
pub fn route(attr: TokenStream, item: TokenStream) -> TokenStream {}

Here, we have two parameters of type TokenStream. The first is for the contents of the attribute: the GET, "/" part. The second is the body of the item the attribute is attached to: in this case, fn index() {} and the rest of the functions body.

Other than that, attribute-like macros work the same way as custom derive macros: you create a crate with the proc-macro crate type and implement a function that generates the code you want!

Function-like macros

Function-like macros define macros that look like function calls. Similarly to macro_rules! macros, theyre more flexible than functions; for example, they can take an unknown number of arguments. However, macro_rules! macros can be defined only using the match-like syntax. Function-like macros take a TokenStream parameter and their definition manipulates that TokenStream using Rust code as the other two types of procedural macros do. An example of a function-like macro is an sql! macro that might be called like so:

let sql = sql!(SELECT * FROM posts WHERE id=1);

This macro would parse the SQL statement inside it and check that its syntactically correct, which is much more complex processing than a macro_rules! macro can do. The sql! macro would be defined like this:

#[proc_macro]
pub fn sql(input: TokenStream) -> TokenStream {}

This definition is similar to the custom derive macros signature: we receive the tokens that are inside the parentheses and return the code we wanted to generate.

Conditional Compilation

Conditionally compiled source code is source code that may or may not be considered a part of the source code depending on certain conditions. Source code can be conditionally compiled using the attributes cfg and cfg_attr and the built-in cfg macro. These conditions are based on the target architecture of the compiled crate, arbitrary values passed to the compiler, and a few other miscellaneous things further described below in detail.

Each form of conditional compilation takes a configuration predicate that evaluates to true or false. The predicate is one of the following:

  • A configuration option. It is true if the option is set and false if it is unset.
  • all() with a comma separated list of configuration predicates. It is false if at least one predicate is false. If there are no predicates, it is true.
  • any() with a comma separated list of configuration predicates. It is true if at least one predicate is true. If there are no predicates, it is false.
  • not() with a configuration predicate. It is true if its predicate is false and false if its predicate is true.

Configuration options are names and key-value pairs that are either set or unset. Names are written as a single identifier such as, for example, unix. Key-value pairs are written as an identifier, =, and then a string. For example, target_arch = "x86_64" is a configuration option.

Note

: For rustc, arbitrary-set configuration options are set using the --cfg flag.

The cfg attribute conditionally includes the thing it is attached to based on a configuration predicate.
If the predicate is true, the thing is rewritten to not have the cfg attribute on it. If the predicate is false, the thing is removed from the source code.

Some examples on functions:

// The function is only included in the build when compiling for macOS
#[cfg(target_os = "macos")]
fn macos_only() {
  // ...
}

// This function is only included when either foo or bar is defined
#[cfg(any(foo, bar))]
fn needs_foo_or_bar() {
  // ...
}

// This function is only included when compiling for a unixish OS with a 32-bit
// architecture
#[cfg(all(unix, target_pointer_width = "32"))]
fn on_32bit_unix() {
  // ...
}

// This function is only included when foo is not defined
#[cfg(not(foo))]
fn needs_not_foo() {
  // ...
}

// This function is only included when the panic strategy is set to unwind
#[cfg(panic = "unwind")]
fn when_unwinding() {
  // ...
}

The cfg_attr attribute conditionally includes attributes based on a configuration predicate.
When the configuration predicate is true, this attribute expands out to the attributes listed after the predicate. For example, the following module will either be found at linux.rs or windows.rs based on the target.

#[cfg_attr(target_os = "linux", path = "linux.rs")]
#[cfg_attr(windows, path = "windows.rs")]
mod os;

Zero, one, or more attributes may be listed. Multiple attributes will each be expanded into separate attributes. For example:

#[cfg_attr(feature = "magic", sparkles, crackles)]
fn bewitched() {}

// When the `magic` feature flag is enabled, the above will expand to:
#[sparkles]
#[crackles]
fn bewitched() {}

Note

: The cfg_attr can expand to another cfg_attr. For example, #[cfg_attr(target_os = "linux", cfg_attr(feature = "multithreaded", some_other_attribute))] is valid. This example would be equivalent to #[cfg_attr(all(target_os = "linux", feature ="multithreaded"), some_other_attribute)].

The built-in cfg macro takes in a single configuration predicate and evaluates to the true literal when the predicate is true and the false literal when it is false.

For example:

let machine_kind = if cfg!(unix) {
  "unix"
} else if cfg!(windows) {
  "windows"
} else {
  "unknown"
};

println!("I'm running on a {} machine!", machine_kind);

unsafe Rust

Rust is focused strongly on safety, but sometimes doing something dangerous is necessary. In this case you can use the unsafe keyword. unsafe should be used only when needed as it may cause undefinied behaviour, but when debugging you can solely focus on your unsafe blocks as all potential dangerous operations are neatly packaged in them.

There are two types of using unsafe:

  • unsafe blocks lets you call dangerous code. With this you can wrap unsafe code in a safe function with checks to call.
fn write_to_serial(data: &[u8]) {
    assert!(data.is_valid());

    unsafe {
        // doing potentially unsafe things
        write_to_serial_unchecked(data);
    }
}
  • unsafe functions can only be called from unsafe blocks.
unsafe fn write_to_serial_unchecked(data: &[u8]) {
    // unsafe operation
}

Inline Assembly

Support for inline assembly is provided via the asm! and global_asm! macros. It can be used to embed handwritten assembly in the assembly output generated by the compiler.

use std::arch::asm;

// Multiply x by 6 using shifts and adds
let mut x: u64 = 4;
unsafe {
    asm!(
        "mov {tmp}, {x}",
        "shl {tmp}, 1",
        "shl {x}, 2",
        "add {x}, {tmp}",
        x = inout(reg) x,
        tmp = out(reg) _,
    );
}
assert_eq!(x, 4 * 6);

The assembler template uses the same syntax as format strings (i.e. placeholders are specified by curly braces). The corresponding arguments are accessed in order, by index, or by name. However, implicit named arguments (introduced by RFC #2795) are not supported.

An asm! invocation may have one or more template string arguments; an asm! with multiple template string arguments is treated as if all the strings were concatenated with a \n between them. The expected usage is for each template string argument to correspond to a line of assembly code. All template string arguments must appear before any other arguments.

As with format strings, positional arguments must appear before named arguments and explicit register operands.

Explicit register operands cannot be used by placeholders in the template string. All other named and positional operands must appear at least once in the template string, otherwise a compiler error is generated.

The exact assembly code syntax is target-specific and opaque to the compiler except for the way operands are substituted into the template string to form the code passed to the assembler.

Currently, all supported targets follow the assembly code syntax used by LLVM's internal assembler which usually corresponds to that of the GNU assembler (GAS). On x86, the .intel_syntax noprefix mode of GAS is used by default. On ARM, the .syntax unified mode is used. These targets impose an additional restriction on the assembly code: any assembler state (e.g. the current section which can be changed with .section) must be restored to its original value at the end of the asm string. Assembly code that does not conform to the GAS syntax will result in assembler-specific behavior. Further constraints on the directives used by inline assembly are indicated by Directives Support.

Crates

Filesystem

  • tempfile: Temporary files and directories
  • temp-dir: Simple temporary directory with cleanup
  • walkdir: recursively scan directories
  • jwalk: Filesystem walk performed in parallel with streamed and sorted results
  • glob: Support for matching file paths against Unix shell style patterns
  • notify: filesystem watcher
  • camino: UTF-8 paths
  • sugar_path: Sugar functions for manipulating paths
  • path-absolutize: A library for extending Path and PathBuf in order to get an absolute path and remove the containing dots
  • fs_extra: Expanding std::fs and std::io. Recursively copy folders with information about process and much more.
  • vfs: A virtual filesystem for Rust
  • fuser: Filesystem in Userspace (FUSE) for Rust
  • directories: A tiny mid-level library that provides platform-specific standard locations of directories for config, cache and other data on Linux, Windows and macOS
  • xattr: unix extended filesystem attributes
  • open: Open a path or URL using the program configured on the system
  • infer: Small crate to infer file type based on magic number signatures

Error Handling

  • anyhow: Flexible concrete Error type built on std::error::Error
  • thiserror: macros for creating error types
  • user-error: Pretty printed errors for your CLI application.
  • eyre: Flexible concrete Error Reporting type built on std::error::Error with customizable Reports
  • color-eyre: An error report handler for panics and eyre::Reports for colorful, consistent, and well formatted error reports for all kinds of errors

Data Structures

  • hashbrown: A Rust port of Google's SwissTable hash map
  • bitvec: Addresses memory by bits, for packed collections and bitfields
  • bitflags: A macro to generate structures which behave like bitflags
  • smallvec: 'Small vector' optimization: store up to a small number of items on the stack
  • ndarray: An n-dimensional array for general elements and for numerics. Lightweight array views and slicing; views support chunking and splitting.
  • zerovec: Zero-copy vector backed by a byte array
  • priority-queue: A Priority Queue implemented as a heap with a function to efficiently change the priority of an item
  • histogram: A collection of histogram data structures
  • fraction: Lossless fractions and decimals; drop-in float replacement
  • ringbuffer: A fixed-size circular buffer
  • grid: Dynamic generic 2D data structure
  • datas: A library for data structures and algorithms and data analisys
  • trees: General purpose tree data structures
  • either: The enum Either with variants Left and Right is a general purpose sum type with two cases
  • either_of: Utilities for working with enumerated types that contain one of 2..n other types
  • petgraph: Graph data structure library. Provides graph types and graph algorithms.
  • hypergraph: Hypergraph is data structure library to create a directed hypergraph in which an hyperedge can join any number of vertices
  • gix: Interact with git repositories just like git would
  • git2: Bindings to libgit2 for interoperating with git repositories.

Parser

  • nom: A byte-oriented, zero-copy, parser combinators library
  • pest: pest is a general purpose parser written in Rust
  • keepass: KeePass .kdbx database file parser
  • html5ever: High-performance browser-grade HTML5 parser
  • comrak: A 100% CommonMark-compatible GitHub Flavored Markdown parser and formatter
  • uriparse: A URI parser including relative references
  • markdown: CommonMark compliant markdown parser in Rust with ASTs and extensions
  • evalexpr: A powerful arithmetic and boolean expression evaluator
  • uuid: A library to generate and parse UUIDs
  • semver: Parser and evaluator for Cargo's flavor of Semantic Versioning
  • url: URL library for Rust, based on the WHATWG URL Standard
  • httparse: A tiny, safe, speedy, zero-copy HTTP/1.x parser
  • syntect: library for high quality syntax highlighting and code intelligence using Sublime Text's grammars

Serialization

  • serde: A generic serialization/deserialization framework
  • serde_with: Custom de/serialization functions for Rust's serde
  • bincode: A binary serialization / deserialization strategy for transforming structs into bytes and vice versa!
  • serde_json: A JSON serialization file format
  • serde_jsonc: A JSON serialization file format
  • serde_yaml: YAML data format for Serde
  • bson: Encoding and decoding support for BSON in Rust
  • toml: A native Rust encoder and decoder of TOML-formatted files and streams.
  • gray_matter: Smart front matter parser. An implementation of gray-matter in rust. Parses YAML, JSON, TOML and support for custom parsers.
  • schemars: Generate JSON Schemas from Rust code
  • jsonschema: JSON schema validaton library
  • json-patch: RFC 6902, JavaScript Object Notation (JSON) Patch
  • rss: Library for serializing the RSS web content syndication format
  • postcard: A no_std + serde compatible message library for Rust

Encoding

  • hex: Encoding and decoding data into/from hexadecimal representation
  • base62: A Base62 encoding/decoding library
  • base64: encodes and decodes base64 as bytes or utf8
  • base64-url: Base64 encode, decode, escape and unescape for URL applications
  • encoding_rs: A Gecko-oriented implementation of the Encoding Standard
  • data-encoding: Efficient and customizable data-encoding functions like base64, base32, and hex
  • shell-quote: A Rust library for shell-quoting strings, e.g. for interpolating into a Bash script.
  • urlencoding: A Rust library for doing URL percentage encoding
  • bytesize: Semantic wrapper for byte count representations
  • hex-literal: Macro for converting hexadecimal string to a byte array at compile time
  • byte-unit: A library for interacting with units of bytes
  • bytes: Types and traits for working with bytes

Algorithms

  • rand: Random number generators and other randomness functionality
  • bonsai-bt: Behaviour trees
  • pathfinding: Pathfinding, flow, and graph algorithms
  • treediff: Find the difference between arbitrary data structures
  • raft: The rust language implementation of Raft algorithm

Crypto

  • rustls: Rustls is a modern TLS library written in Rust
  • rustls-pemfile: Basic .pem file parser for keys and certificates
  • pem: Parse and encode PEM-encoded data
  • x509-parser: Parser for the X.509 v3 format (RFC 5280 certificates)
  • openssl: OpenSSL bindings
  • hkdf: HMAC-based Extract-and-Expand Key Derivation Function (HKDF)
  • ed25519-compact: A small, self-contained, wasm-friendly Ed25519 implementation
  • snow: A pure-rust implementation of the Noise Protocol Framework
  • keyring: Cross-platform library for managing passwords/credentials
  • scrypt: Scrypt password-based key derivation function
  • totp-rs: RFC-compliant TOTP implementation with ease of use as a goal and additionnal QoL features
  • mnemonic: Encode any data into a sequence of English words
  • jwt: JSON Web Token library
  • secrets: Protected-access memory for cryptographic secrets
  • redact: A simple library for keeping secrets out of logs
  • noise: Procedural noise generation library
  • ulid: a Universally Unique Lexicographically Sortable Identifier implementation

Hashes

  • digest: Traits for cryptographic hash functions and message authentication codes
  • seahash: A blazingly fast, portable hash function with proven statistical guarantees
  • highway: Native Rust port of Google's HighwayHash, which makes use of SIMD instructions for a fast and strong hash function
  • md5: The package provides the MD5 hash function
  • crc32c: Safe implementation for hardware accelerated CRC32C instructions with software fallback
  • blake3: the BLAKE3 hash function
  • siphasher: SipHash-2-4, SipHash-1-3 and 128-bit variants in pure Rust
  • bcrypt: Easily hash and verify passwords using bcrypt
  • sha1: SHA-1 hash function
  • sha2: Pure Rust implementation of the SHA-2 hash function family including SHA-224, SHA-256, SHA-384, and SHA-512
  • sha3: Pure Rust implementation of SHA-3, a family of Keccak-based hash functions including the SHAKE family of eXtendable-Output Functions (XOFs), as well as the accelerated variant TurboSHAKE

Logging

  • log: A lightweight logging facade for Rust
  • env_logger: A logging implementation for log which is configured via an environment variable
  • prometheus: Prometheus instrumentation library for Rust applications
  • opentelemetry: OpenTelemetry API for Rust
  • sentry-core: Core sentry library used for instrumentation and integration development
  • logging_timer: Simple timers that log the elapsed time when dropped
  • dioxus-logger: A logging utility to provide a standard interface whether you're targeting web desktop, fullstack, and more in Dioxus
  • tracing: advanced logger
  • tracing-appender: Provides utilities for file appenders and making non-blocking writers
  • tracing-loki: A tracing layer for shipping logs to Grafana Loki

Mail

Visualization

  • plotters: A Rust drawing library focus on data plotting for both WASM and native applications
  • plotly: A plotting library powered by Plotly.js
  • textplot: Terminal plotting library

Templates

  • maud: Compile-time HTML templates
  • tera: Template engine based on Jinja templates
  • subst: shell-like variable substitution
  • minijinja: a powerful template engine for Rust with minimal dependencies
  • handlebars: Handlebars templating implemented in Rust

Media

Images

  • image: Imaging library. Provides basic image processing and encoders/decoders for common image formats.
  • rgb: Pixel types for Rust
  • qrcode: QR code encoder in Rust
  • gif: GIF de- and encoder
  • opencv: Rust bindings for OpenCV
  • imgref: A basic 2-dimensional slice for safe and convenient handling of pixel buffers with width, height & stride
  • palette: Convert and manage colors with a focus on correctness, flexibility and ease of use
  • imageproc: Image processing operations
  • resvg: An SVG rendering library
  • png: PNG decoding and encoding library in pure Rust
  • webp: WebP conversion library
  • image_hasher: A simple library that provides perceptual hashing and difference calculation for images
  • dify: A fast pixel-by-pixel image comparison tool in Rust
  • qoi: VERY fast encoder/decoder for QOI (Quite Okay Image) format
  • auto-palette: 🎨 A Rust library that extracts prominent color palettes from images automatically
  • blockhash: A perceptual hashing algorithm for detecting similar images

Video

Audio

  • symphonia: Pure Rust media container and audio decoding library
  • hound: A wav encoding and decoding library
  • id3: A library for reading and writing ID3 metadata
  • metaflac: A library for reading and writing FLAC metadata
  • bliss-audio: A song analysis library for making playlists

3D

  • glam: A simple and fast 3D math library for games and graphics
  • tobj: A lightweight OBJ loader in the spirit of tinyobjloader
  • obj-rs: Wavefront obj parser for Rust. It handles both 'obj' and 'mtl' formats.

CLI

  • argh: Derive-based argument parser optimized for code size
  • clap: A simple to use, efficient, and full-featured Command Line Argument Parser
  • yansi: A dead simple ANSI terminal color painting library
  • owo-colors: Zero-allocation terminal colors that'll make people go owo
  • named-colour: named-colour provides Hex Codes for popular colour names
  • colored: The most simple way to add colors in your terminal
  • crossterm: A crossplatform terminal library for manipulating terminals
  • trauma: Simplify and prettify HTTP downloads
  • comfy-table: An easy to use library for building beautiful tables with automatic content wrapping
  • tabled: An easy to use library for pretty print tables of Rust structs and enums
  • tabular: Plain text tables, aligned automatically
  • rustyline: Rustyline, a readline implementation based on Antirez's Linenoise
  • rpassword: Read passwords in console applications
  • inquire: inquire is a library for building interactive prompts on terminals
  • indicatif: A progress bar and cli reporting library for Rust
  • spinners: Elegant terminal spinners for Rust
  • is-terminal: Test whether a given stream is a terminal
  • bishop: Library for visualizing keys and hashes using OpenSSH's Drunken Bishop algorithm
  • termimad: Markdown Renderer for the Terminal
  • rust-script: Command-line tool to run Rust "scripts" which can make use of crates
  • sysinfo: Library to get system information such as processes, CPUs, disks, components and networks
  • which: A Rust equivalent of Unix command "which". Locate installed executable in cross platforms.
  • ctrlc: Easy Ctrl-C handler for Rust projects
  • subprocess: Execution of child processes and pipelines, inspired by Python's subprocess module, with Rust-specific extensions
  • cmd_lib: Common rust commandline macros and utils, to write shell script like tasks easily

Compression

  • flate2: DEFLATE compression and decompression exposed as Read/BufRead/Write streams. Supports miniz_oxide and multiple zlib implementations. Supports zlib, gzip, and raw deflate streams.
  • tar: A Rust implementation of a TAR file reader and writer.
  • zstd: Binding for the zstd compression library
  • unrar: list and extract RAR archives
  • zip: Library to support the reading and writing of zip files
  • brotli: A brotli compressor and decompressor
  • huffman-compress2: Huffman compression given a probability distribution over arbitrary symbols
  • arithmetic-coding: fast and flexible arithmetic coding library

Cache

  • lru: A LRU cache implementation
  • moka: A fast and concurrent cache library inspired by Java Caffeine
  • ustr: Fast, FFI-friendly string interning
  • cacache: Content-addressable, key-value, high-performance, on-disk cache
  • cached: Caching Crate
  • memoize: Attribute macro for auto-memoizing functions with somewhat-simple signatures
  • internment: Easy interning of data
  • http-cache-semantics: RFC 7234. Parses HTTP headers to correctly compute cacheability of responses, even in complex cases
  • assets_manager: Conveniently load, cache, and reload external resources

Databases

  • rusqlite: Ergonomic wrapper for SQLite
  • sqlx: The Rust SQL Toolkit. An async, pure Rust SQL crate featuring compile-time checked queries without a DSL. Supports PostgreSQL, MySQL, and SQLite.
  • mongodb: The official MongoDB driver for Rust
  • rocksdb: embedded database
  • uuid: UUID Generation
  • polars: Dataframes computation
  • surrealdb: A scalable, distributed, collaborative, document-graph database, for the realtime web
  • sql-builder: Simple SQL code generator
  • pgvector: pgvector support for Rust
  • sea-orm: 🐚 An async & dynamic ORM for Rust
  • sled: Lightweight high-performance pure-rust transactional embedded database

Date and Time

  • chrono: Date and time library for Rust
  • chrono-tz: TimeZone implementations for chrono from the IANA database
  • humantime: A parser and formatter for std::time::{Duration, SystemTime}
  • duration-str: duration string parser
  • cron: A cron expression parser and schedule explorer
  • dateparser: Parse dates in string formats that are commonly used
  • icalendar: Strongly typed iCalendar builder and parser

Network

  • tower: Tower is a library of modular and reusable components for building robust clients and servers
  • tungstenite: Lightweight stream-based WebSocket implementation
  • tokio-websockets: High performance, strict, tokio-util based WebSockets implementation
  • message-io: Fast and easy-to-use event-driven network library
  • ipnet: Provides types and useful methods for working with IPv4 and IPv6 network addresses
  • object_store: A generic object store interface for uniformly interacting with AWS S3, Google Cloud Storage, Azure Blob Storage and local files
  • matchit: A high performance, zero-copy URL router
  • tun: TUN device creation and handling
  • quiche: 🥧 Savoury implementation of the QUIC transport protocol and HTTP/3
  • arti-client: Library for connecting to the Tor network as an anonymous client
  • etherparse: A library for parsing & writing a bunch of packet based protocols (EthernetII, IPv4, IPv6, UDP, TCP ...)
  • ldap3: Pure-Rust LDAP Client
  • hyperlocal: Hyper bindings for Unix domain sockets
  • openssh-sftp-client: Highlevel API used to communicate with openssh sftp server
  • swarm-discovery: Discovery service for IP-based swarms
  • libmdns: mDNS Responder library for building discoverable LAN services in Rust
  • networkmanager: Bindings for the Linux NetworkManager
  • renet: Server/Client network library for multiplayer games with authentication and connection management
  • dhcproto: A DHCP parser and encoder for DHCPv4/DHCPv6. dhcproto aims to be a functionally complete DHCP implementation.
  • irc: the irc crate usable, async IRC for Rust
  • ssh2: Bindings to libssh2 for interacting with SSH servers and executing remote commands, forwarding local ports, etc
  • openssh: SSH through OpenSSH
  • amqprs: AMQP 0-9-1 client implementation for RabbitMQ
  • wyoming: Abstractions over the Wyoming protocol

HTTP

  • hyper: A fast and correct HTTP library
  • reqwest: higher level HTTP client library
  • ureq: Simple, safe HTTP client
  • curl: Rust bindings to libcurl for making HTTP requests
  • actix-web: Actix Web is a powerful, pragmatic, and extremely fast web framework for Rust
  • rocket: web server framework for Rust
  • thirtyfour: Thirtyfour is a Selenium / WebDriver library for Rust, for automated website UI testing
  • http-types: Common types for HTTP operations
  • headers: typed HTTP headers
  • cookie: HTTP cookie parsing and cookie jar management. Supports signed and private (encrypted, authenticated) jars.
  • http: A set of types for representing HTTP requests and responses
  • h2: An HTTP/2 client and server
  • h3: An async HTTP/3 implementation
  • mime: Strongly Typed Mimes
  • scraper: HTML parsing and querying with CSS selectors
  • selectors: CSS Selectors matching for Rust
  • spider: A web crawler and scraper, building blocks for data curation workloads
  • htmlize: Encode and decode HTML entities in UTF-8 according to the standard
  • ammonia: HTML Sanitization
  • rookie: Load cookie from your web browsers
  • tonic: A gRPC over HTTP/2 implementation focused on high performance, interoperability, and flexibility
  • web-sys: Bindings for all Web APIs, a procedurally generated crate from WebIDL
  • jsonwebtoken: Create and decode JWTs in a strongly typed way
  • http-range-header: No-dep range header parser

Axum

  • axum: Web framework that focuses on ergonomics and modularity
  • axum-valid: Provides validation extractors for your Axum application, allowing you to validate data using validator, garde, validify or all of them.
  • axum-prometheus: A tower middleware to collect and export HTTP metrics for Axum
  • axum-htmx: A set of htmx extractors, responders, and request guards for axum.
  • axum_session: 📝 Session management layer for axum that supports HTTP and Rest.
  • axum_csrf: Library to Provide a CSRF (Cross-Site Request Forgery) protection layer.

Text

  • regex: An implementation of regular expressions for Rust. This implementation uses finite automata and guarantees linear time matching on all inputs.
  • fancy-regex: An implementation of regexes, supporting a relatively rich set of features, including backreferences and look-around
  • pretty_regex: 🧶 Elegant and readable way of writing regular expressions
  • similar: A diff library for Rust
  • dissimilar: Diff library with semantic cleanup, based on Google's diff-match-patch
  • strsim: Implementations of string similarity metrics. Includes Hamming, Levenshtein, OSA, Damerau-Levenshtein, Jaro, Jaro-Winkler, and Sørensen-Dice.
  • enquote: Quotes and unquotes strings
  • emojis: Lookup emoji in O(1) time, access metadata and GitHub shortcodes, iterate over all emoji, and more!
  • text-splitter: Split text into semantic chunks, up to a desired chunk size. Supports calculating length by characters and tokens, and is callable from Rust and Python.
  • wildcard: Wildcard matching
  • wildmatch: Simple string matching with single- and multi-character wildcard operator
  • textwrap: Library for word wrapping, indenting, and dedenting strings. Has optional support for Unicode and emojis as well as machine hyphenation.
  • pad: Library for padding strings at runtime
  • const-str: compile-time string operations
  • const_format: Compile-time string formatting
  • convert_case: Convert strings into any case
  • heck: heck is a case conversion library
  • html2md: Library to convert simple html documents into markdown

AI

  • safetensors: Provides functions to read and write safetensors which aim to be safer than their PyTorch counterpart.
  • burn: Flexible and Comprehensive Deep Learning Framework in Rust
  • ollama-rs: A Rust library for interacting with the Ollama API
  • linfa: A Machine Learning framework for Rust
  • neurons: Neural networks from scratch, in Rust

Concurrency

  • parking_lot: More compact and efficient implementations of the standard synchronization primitives
  • crossbeam: Tools for concurrent programming
  • rayon: Simple work-stealing parallelism for Rust
  • dashmap: fast hashmap
  • spin: Spin-based synchronization primitives
  • flume: A blazingly fast multi-producer channel
  • state: A library for safe and effortless global and thread-local state management
  • atomic: Generic Atomic<T> wrapper type
  • yaque: Yaque is yet another disk-backed persistent queue for Rust
  • kanal: The fast sync and async channel that Rust deserves

Memory Management

  • jemallocator: jemalloc allocator
  • memmap2: Map something to memory
  • sharded-slab: lock free concurrent slab allocation
  • heapless: static friendly data structures without heap allocation
  • bumpalo: bump allocation arena
  • singlyton: Singleton for Rust
  • pipe: Synchronous Read/Write memory pipe
  • memory_storage: Vec like data structure with constant index
  • effective-limits: Estimate effective resource limits for a process
  • iter-chunks: Extend Iterator with chunks
  • shared_vector: Reference counted vector data structure
  • census: Keeps an inventory of living objects
  • static_cell: Statically allocated, initialized at runtime cell
  • arcstr: A better reference-counted string type, with zero-cost (allocation-free) support for string literals, and reference counted substrings
  • bytebuffer: A bytebuffer for networking and binary protocols

Science

  • syunit: SI Units
  • uom: Units of measurement
  • measurements: Handle metric, imperial, and other measurements with ease! Types: Length, Temperature, Weight, Volume, Pressure
  • t4t: game theory toolbox

Hardware / Embedded

  • virt: Rust bindings to the libvirt C library
  • qapi: QEMU QMP and Guest Agent API
  • bootloader: An experimental x86_64 bootloader that works on both BIOS and UEFI systems
  • embedded-graphics: Embedded graphics library for small hardware displays
  • riscv: Low level access to RISC-V processors
  • aarch64-cpu: Low level access to processors using the AArch64 execution state
  • uefi: safe UEFI wrapper
  • elf: A pure-rust library for parsing ELF files
  • smoltcp: A TCP/IP stack designed for bare-metal, real-time systems without a heap
  • fatfs: FAT filesystem library

Metrics

  • criterion2: Statistics-driven micro-benchmarking library
  • inferno: Rust port of the FlameGraph performance profiling tool suite
  • divan: Statistically-comfy benchmarking library

Testing

  • test-log: A replacement of the #[test] attribute that initializes logging and/or tracing infrastructure before running tests
  • googletest: A rich assertion and matcher library inspired by GoogleTest for C++
  • predicates: An implementation of boolean-valued predicate functions
  • validator: Common validation functions (email, url, length, …) and trait - to be used with validator_derive
  • garde: Validation library
  • fake: An easy to use library and command line for generating fake data like name, number, address, lorem, dates, etc
  • static_assertions: Compile-time assertions to ensure that invariants are met

i18n

Async

  • tokio: An event-driven, non-blocking I/O platform for writing asynchronous I/O backed applications
  • futures: An implementation of futures and streams featuring zero allocations, composability, and iterator-like interfaces
  • mio: Lightweight non-blocking I/O
  • deadpool: Dead simple async pool
  • blocking: A thread pool for isolating blocking I/O in async programs
  • pollster: Synchronously block the thread until a future completes
  • smol: A small and fast async runtime
  • async-stream: Asynchronous streams using async & await notation
  • async-trait: Type erasure for async trait methods

Macros

  • proc-macro2: A substitute implementation of the compilers proc_macro API to decouple token-based libraries from the procedural macro use case
  • syn: Parse Rust syntax into AST
  • quote: Turn Rust syntax into TokenStream
  • paste: Concat Rust idents

Build Tools

  • flamegraph: A simple cargo subcommand for generating flamegraphs, using inferno under the hood
  • cargo-hack: Cargo subcommand to provide various options useful for testing and continuous integration
  • cargo-outdated: Cargo subcommand for displaying when dependencies are out of date
  • cargo-binstall: Binary installation for rust projects
  • cargo-cache: Manage cargo cache, show sizes and remove directories selectively
  • cargo-watch: Watches over your Cargo projects source
  • cargo-expand: Wrapper around rustc -Zunpretty=expanded. Shows the result of macro expansion and #[derive] expansion.
  • cargo-audit: Audit Cargo.lock for crates with security vulnerabilities
  • cargo-aur: Prepare Rust projects to be released on the Arch Linux User Repository
  • cargo-bom: Bill of Materials for Rust Crates
  • cc: A build-time dependency for Cargo build scripts to assist in invoking the native C compiler to compile native C code into a static archive to be linked into Rust code
  • cmake: A build dependency for running cmake to build a native library
  • cross: Zero setup cross compilation and cross testing
  • wasm-bindgen: Easy support for interacting between JS and Rust

Math

  • num: A collection of numeric types and traits for Rust, including bigint, complex, rational, range iterators, generic integers, and more!
  • num-format: A Rust crate for producing string-representations of numbers, formatted according to international standards
  • num-rational: Rational numbers implementation for Rust
  • num-complex: Complex numbers implementation for Rust
  • statrs: Statistical computing library for Rust
  • bigdecimal: Arbitrary precision decimal numbers
  • nalgebra: General-purpose linear algebra library with transformations and statically-sized or dynamically-sized matrices
  • euclid: Geometry primitives
  • ultraviolet: A crate to do linear algebra, fast
  • peroxide: Rust comprehensive scientific computation library contains linear algebra, numerical analysis, statistics and machine learning tools with farmiliar syntax

Desktop

  • notify-rust: Show desktop notifications (linux, bsd, mac). Pure Rust dbus client and server.
  • arboard: Image and text handling for the OS clipboard

Configuration

  • config: Layered configuration system for Rust applications
  • envy: deserialize env vars into typesafe structs

Language Extensions

Enums

  • strum: Helpful macros for working with enums and strings
  • enum_dispatch: Near drop-in replacement for dynamic-dispatched method calls with up to 10x the speed
  • num_enum: Procedural macros to make inter-operation between primitives and enums easier
  • enum-display: A macro to derive Display for enums

Memory

  • smol_str: small-string optimized string type with O(1) clone
  • beef: More compact Cow
  • dyn-clone: Clone trait that is dyn-compatible
  • memoffset: offset_of functionality for Rust structs
  • az: Casts and checked casts
  • zerocopy: Zerocopy makes zero-cost memory manipulation effortless. We write "unsafe" so you don't have to.
  • once_cell: Single assignment cells and lazy values
  • lazy_static: A macro for declaring lazily evaluated statics in Rust
  • globals: Painless global variables in Rust
  • lazy_format: A utility crate for lazily formatting values for later
  • fragile: Provides wrapper types for sending non-send values to other threads

Syntax

  • tap: Generic extensions for tapping values in Rust
  • option_trait: Helper traits for more generalized options
  • cascade: Dart-like cascade macro for Rust
  • enclose: A convenient macro, for cloning values into a closure
  • extend: Create extensions for types you don't own with extension traits but without the boilerplate
  • hex_lit: Hex macro literals without use of hex macros
  • replace_with: Temporarily take ownership of a value at a mutable location, and replace it with a new value based on the old one
  • scopeguard: A RAII scope guard that will run a given closure when it goes out of scope, even if the code between panics (assuming unwinding panic).
  • backon: Make retry like a built-in feature provided by Rust
  • tryhard: Easily retry futures
  • retry: Utilities for retrying operations that can fail
  • statum: Compile-time state machine magic for Rust: Zero-boilerplate typestate patterns with automatic transition validation
  • formatx: A macro for formatting non literal strings at runtime
  • erased: Erase the type of a reference or box, retaining the lifetime
  • include_dir: Embed the contents of a directory in your binary
  • stacker: A stack growth library useful when implementing deeply recursive algorithms that may accidentally blow the stack
  • recursive: Easy recursion without stack overflows

Type Extensions

  • itertools: Extra iterator adaptors, iterator methods, free functions, and macros
  • itermore: 🤸‍♀️ More iterator adaptors
  • derive_more: Adds #[derive(x)] macros for more traits
  • derive_builder: Rust macro to automatically implement the builder pattern for arbitrary structs
  • ordered-float: Wrappers for total ordering on floats
  • stdext: Extensions for the Rust standard library structures
  • bounded-integer: Bounded integers
  • tuples: Provides many useful tools related to tuples
  • fallible-iterator: Fallible iterator traits
  • sequential: A configurable sequential number generator

Compilation

  • cfg-if: A macro to ergonomically define an item depending on a large number of #[cfg] parameters. Structured like an if-else chain, the first matching branch is the item that gets emitted.
  • cfg_aliases: A tiny utility to help save you a lot of effort with long winded #[cfg()] checks
  • nameof: Provides a Rust macro to determine the string name of a binding, type, const, or function
  • tynm: Returns type names in shorter form

Const

  • constcat: concat! with support for const variables and expressions
  • konst: Const equivalents of std functions, compile-time comparison, and parsing

Geo

  • geo: Geospatial primitives and algorithms
  • geojson: Read and write GeoJSON vector geographic data
  • geozero: Zero-Copy reading and writing of geospatial data in WKT/WKB, GeoJSON, MVT, GDAL, and other formats
  • versatiles: A toolbox for converting, checking and serving map tiles in various formats
  • ipcap: 🌍 A CLI & library for decoding IP addresses into state, postal code, country, coordinates, etc without internet access