Index | About | Me | Jump to Menu Section

Notes on Rust For Rustaceans

Last modified: Wed May 11 2022 11:00:32 GMT+0000 (Coordinated Universal Time)

Foundations

Types

Alignment

Wide Pointers

The orphan rule

Designing Interfaces

Traits

Auto-traits

Object-safe (&dyn Trait)

Common traits for types

Wrapper types

Borrowed vs Owned

Fallible and Blocking Desctructors

Type system


struct Grounded;
struct Launched;

struct Rocket<Stage = Grounded> {
sage: std::marker::PhantomData<Stage>
// using phantomdata to guarantee that it is elimitend at compile time
}

impl Default for Rocket<Grounded> {}
impl Rocket<Grounded> {
pub fn launch(self)-> Rocket<Launched> {}
}

impl Rocket<Launched> {
pub fn accelerate(&mut self) { }
}

// everything that is generic and should be always available
// goes here
impl<Stage> for Rocket<Stage> {
pub fn color(&self) -> Color {}
}
// and so on...

Tests

Fuzzers

libfuzzer_sys::fuz_target!(|data: &[u8]| {
if let Ok(s) = std::str::from_utf8(data) {
let _ = url::Url::parse(s);
}
})

Property-based testing

Macros

Declarative Macros

Procedural Macros

Asynchronous Programming

enum Poll<T> {
Ready(T),
Pending,
}

Pin

Wakers

Blocking in async code

Unsafe Rust

Terms

Interfaces

Concurrency (And Parallelism)

Tips / Terms

Ordering

The CPU and compiler can reorder some instructions in order to optimize the result. Unless two instructions depend on each other (e.g. the output of one is used as input of the other), this generates analogous programs. The issue is: when we have multi-thread we may reason about the result believing that the order of instructions will be followed which may not be true. In Rust we can configure the reodering of instructions using atomics with the Ordering enum.

Methods

Tests

FFI

Compiler crash course

Compilers are split into different components and have three high level phases: compilation, code generation and linking.

The first phase deails with type checking, borrow checking, monorphization and other features we asssociate with a given programming language. It generates a low-level representation of the code. THe code generation takes that representation and generates machine code that actually can run in a CPU.

On the third phase the linker using the symbols, link together different binaries compiled by the previous step. It normally uses static linking for Rust genareted code and dynamic linking for FFI.

Code

#[no_mangle]
pub static RS_DEBUG: bool = true;

The no_mangle attribute ensures that RS_DEBUG retains that name during compilation rather than having the compiler assign it another symbol name to.

This can be accessed from other languages that ar linked against the binary.