# Programming Rust ![rw-book-cover](https://m.media-amazon.com/images/I/91syf9W6vpS._SY160.jpg) ## Metadata - Author: Jim Blandy, Jason Orendorff, and Leonora F. S. Tindall - Full Title: Programming Rust - Category: #books ## Highlights - systems programming is resource-constrained programming. ([Location 42](https://readwise.io/to_kindle?action=open&asin=B0979PWD4Z&location=42)) - fn gcd(mut n: u64, mut m: u64) -> u64 {     assert!(n != 0 && m != 0);     while m != 0 {         if m < n {             let t = m;             m = n;             n = t;         }         m = m % n;     }     n } ([Location 367](https://readwise.io/to_kindle?action=open&asin=B0979PWD4Z&location=367)) - Rust always checks assertions regardless of how the program was compiled. There is also a debug_assert! macro, whose assertions are skipped when the program is compiled for speed. ([Location 412](https://readwise.io/to_kindle?action=open&asin=B0979PWD4Z&location=412)) - If a function body ends with an expression that is not followed by a semicolon, that’s the function’s return value. ([Location 428](https://readwise.io/to_kindle?action=open&asin=B0979PWD4Z&location=428)) - The #[test] marker is an example of an attribute. Attributes are an open-ended system for marking functions and other declarations with extra information, like attributes in C++ and C#, or annotations in Java. ([Location 466](https://readwise.io/to_kindle?action=open&asin=B0979PWD4Z&location=466)) - A trait is a collection of methods that types can implement. ([Location 527](https://readwise.io/to_kindle?action=open&asin=B0979PWD4Z&location=527)) - Although we never use the name FromStr elsewhere in the program, a trait must be in scope in order to use its methods. ([Location 530](https://readwise.io/to_kindle?action=open&asin=B0979PWD4Z&location=530)) - Vec is Rust’s growable vector type, analogous to C++’s std::vector, a Python list, or a JavaScript array. ([Location 545](https://readwise.io/to_kindle?action=open&asin=B0979PWD4Z&location=545)) - The std::env module’s args function returns an iterator, a value that produces each argument on demand, and indicates when we’re done. Iterators are ubiquitous in Rust; the standard library includes other iterators that produce the elements of a vector, the lines of a file, messages received on a communications channel, and almost anything else that makes sense to loop over. ([Location 558](https://readwise.io/to_kindle?action=open&asin=B0979PWD4Z&location=558)) - Rust’s iterators are very efficient: the compiler is usually able to translate them into the same code as a handwritten loop. ([Location 562](https://readwise.io/to_kindle?action=open&asin=B0979PWD4Z&location=562)) - So when we iterate, we want to tell Rust that ownership of the vector should remain with numbers; we are merely borrowing its elements for the loop. The & operator in &numbers[1..] borrows a reference to the vector’s elements from the second onward. The for loop iterates over the referenced elements, letting m borrow each element in succession. The * operator in *m dereferences m, yielding the value it refers to; this is the next u64 we want to pass to gcd. ([Location 618](https://readwise.io/to_kindle?action=open&asin=B0979PWD4Z&location=618)) - A closure is a value that can be called as if it were a function. This closure takes no arguments, but if it did, their names would appear between the || vertical bars. ([Location 763](https://readwise.io/to_kindle?action=open&asin=B0979PWD4Z&location=763)) - Rust “raw string” syntax: the letter r, zero or more hash marks (that is, the # character), a double quote, and then the contents of the string, terminated by another double quote followed by the same number of hash marks. ([Location 780](https://readwise.io/to_kindle?action=open&asin=B0979PWD4Z&location=780)) - The annotation above the struct definition is an attribute, like the #[test] attribute we used earlier to mark test functions. Placing a #[derive(Deserialize)] attribute above a type definition tells the serde crate to examine the type when the program is compiled and automatically generate code to parse a value of this type from data in the format that HTML forms use for POST requests. ([Location 813](https://readwise.io/to_kindle?action=open&asin=B0979PWD4Z&location=813)) - If you use a mutex to coordinate threads making changes to a shared data structure, Rust ensures that you can’t access the data except when you’re holding the lock, and releases the lock automatically when you’re done. ([Location 910](https://readwise.io/to_kindle?action=open&asin=B0979PWD4Z&location=910)) - If you want to share read-only data among several threads, Rust ensures that you cannot modify the data accidentally. ([Location 913](https://readwise.io/to_kindle?action=open&asin=B0979PWD4Z&location=913)) - If you transfer ownership of a data structure from one thread to another, Rust makes sure you have indeed relinquished all access to it. ([Location 914](https://readwise.io/to_kindle?action=open&asin=B0979PWD4Z&location=914)) - if your program compiles, it is free of data races. All Rust functions are thread-safe. ([Location 924](https://readwise.io/to_kindle?action=open&asin=B0979PWD4Z&location=924)) - Option is an enumerated type, often called an enum, because its definition enumerates several variants that a value of this type could be: for any type T, a value of type Option<T> is either Some(v), where v is a value of type T, or None, indicating no T value is available. Like the Complex type we discussed earlier, Option is a generic type: you can use Option<T> to represent an optional value of any type T you like. ([Location 1076](https://readwise.io/to_kindle?action=open&asin=B0979PWD4Z&location=1076)) - You can read the clause <T: FromStr> aloud as, “For any type T that implements the FromStr trait...” This effectively lets us define an entire family of functions at once: parse_pair::<i32> is a function that parses pairs of i32 values, parse_pair::<f64> parses pairs of floating-point values, and so on. ([Location 1186](https://readwise.io/to_kindle?action=open&asin=B0979PWD4Z&location=1186)) - It’s a common beginner’s mistake to attempt to use ? in the main function. However, since main itself doesn’t return a value, this won’t work; instead, you need to use a match statement, or one of the shorthand methods like unwrap and expect. ([Location 1515](https://readwise.io/to_kindle?action=open&asin=B0979PWD4Z&location=1515)) - Note that, unlike functions declared with fn, we don’t need to declare the types of a closure’s arguments; Rust will infer them, along with its return type. ([Location 1721](https://readwise.io/to_kindle?action=open&asin=B0979PWD4Z&location=1721)) - The move keyword at the front indicates that this closure takes ownership of the variables it uses; in particular, only the closure may use the mutable slice band. The argument list |_| means that the closure takes one argument, which it doesn’t use (another spawner for making nested threads). ([Location 1775](https://readwise.io/to_kindle?action=open&asin=B0979PWD4Z&location=1775)) - The #[derive(Debug)] attribute tells the compiler to generate some extra code that allows us to format the Arguments struct with {:?} in println!. ([Location 1872](https://readwise.io/to_kindle?action=open&asin=B0979PWD4Z&location=1872)) - The collect() method produces a Vec of arguments. ([Location 1922](https://readwise.io/to_kindle?action=open&asin=B0979PWD4Z&location=1922)) - To a great extent, the Rust language is designed around its types. ([Location 2144](https://readwise.io/to_kindle?action=open&asin=B0979PWD4Z&location=2144)) - Rust’s memory and thread safety guarantees also rest on the soundness of its type system, and Rust’s flexibility stems from its generic types and traits. ([Location 2148](https://readwise.io/to_kindle?action=open&asin=B0979PWD4Z&location=2148)) - These source-level types have concrete machine-level counterparts with predictable costs and performance. ([Location 2150](https://readwise.io/to_kindle?action=open&asin=B0979PWD4Z&location=2150)) - Given the types that you do spell out, Rust’s type inference will figure out most of the rest for you. ([Location 2154](https://readwise.io/to_kindle?action=open&asin=B0979PWD4Z&location=2154)) - Rust lets you leave out, or elide, the type. ([Location 2156](https://readwise.io/to_kindle?action=open&asin=B0979PWD4Z&location=2156)) - These two definitions are exactly equivalent, and Rust will generate the same machine code either way. ([Location 2184](https://readwise.io/to_kindle?action=open&asin=B0979PWD4Z&location=2184)) - Functions can be generic: a single function can work on values of many different types. ([Location 2186](https://readwise.io/to_kindle?action=open&asin=B0979PWD4Z&location=2186)) - duck typing: if it quacks like a duck, it’s a duck.) ([Location 2190](https://readwise.io/to_kindle?action=open&asin=B0979PWD4Z&location=2190)) - The footing of Rust’s type system is a collection of fixed-width numeric types, chosen to match the types that almost all modern processors implement directly in hardware. ([Location 2269](https://readwise.io/to_kindle?action=open&asin=B0979PWD4Z&location=2269)) - Fixed-width numeric types can overflow or lose precision, but they are adequate for most applications and can be thousands of times faster than representations like arbitrary-precision integers and exact rationals. ([Location 2273](https://readwise.io/to_kindle?action=open&asin=B0979PWD4Z&location=2273)) - machine word is a value the size of an address on the machine the code runs on, 32 or 64 bits. ([Location 2293](https://readwise.io/to_kindle?action=open&asin=B0979PWD4Z&location=2293)) - Integer literals in Rust can take a suffix indicating their type: 42u8 is a u8 value, and 1729isize is an isize. ([Location 2338](https://readwise.io/to_kindle?action=open&asin=B0979PWD4Z&location=2338)) - In the end, if multiple types could work, Rust defaults to i32 if that is among the possibilities. ([Location 2342](https://readwise.io/to_kindle?action=open&asin=B0979PWD4Z&location=2342)) - Although numeric types and the char type are distinct, Rust does provide byte literals, character-like literals for u8 values: b'X' represents the ASCII code for the character X, as a u8 value. ([Location 2361](https://readwise.io/to_kindle?action=open&asin=B0979PWD4Z&location=2361)) - You can convert from one integer type to another using the as operator. We explain how conversions work in “Type Casts”, ([Location 2385](https://readwise.io/to_kindle?action=open&asin=B0979PWD4Z&location=2385)) - Rust wants to know exactly which integer type a value has before it will call the type’s own methods. The default of i32 applies only if the type is still ambiguous after all method calls have been resolved, so that’s too late to help here. ([Location 2442](https://readwise.io/to_kindle?action=open&asin=B0979PWD4Z&location=2442)) - When an integer arithmetic operation overflows, Rust panics, in a debug build. In a release build, the operation wraps around: it produces the value equivalent to the mathematically correct result modulo the range of the value. ([Location 2458](https://readwise.io/to_kindle?action=open&asin=B0979PWD4Z&location=2458)) - Checked operations return an Option of the result: Some(v) if the mathematically correct result can be represented as a value of that type, or None if it cannot. ([Location 2482](https://readwise.io/to_kindle?action=open&asin=B0979PWD4Z&location=2482)) - Wrapping operations return the value equivalent to the mathematically correct result modulo the range of the value: ([Location 2501](https://readwise.io/to_kindle?action=open&asin=B0979PWD4Z&location=2501)) - Saturating operations return the representable value that is closest to the mathematically correct result. ([Location 2521](https://readwise.io/to_kindle?action=open&asin=B0979PWD4Z&location=2521)) - Overflowing operations return a tuple (result, overflowed), where result is what the wrapping version of the function would return, and overflowed is a bool indicating whether an overflow occurred: ([Location 2532](https://readwise.io/to_kindle?action=open&asin=B0979PWD4Z&location=2532)) - Rust provides IEEE single- and double-precision floating-point types. These types include positive and negative infinities, distinct positive and negative zero values, and a not-a-number value ([Location 2576](https://readwise.io/to_kindle?action=open&asin=B0979PWD4Z&location=2576)) - For the purposes of type inference, Rust treats integer literals and floating-point literals as distinct classes: it will never infer a floating-point type for an integer literal, or vice versa. ([Location 2599](https://readwise.io/to_kindle?action=open&asin=B0979PWD4Z&location=2599)) - But you can always write out explicit conversions using the as operator: i as f64, or x as i32. ([Location 2651](https://readwise.io/to_kindle?action=open&asin=B0979PWD4Z&location=2651)) - Rust’s Boolean type, bool, has the usual two values for such types, true and false. ([Location 2663](https://readwise.io/to_kindle?action=open&asin=B0979PWD4Z&location=2663)) - Rust, however, is very strict: control structures like if and while require their conditions to be bool expressions, as do the short-circuiting logical operators && and ||. You must write if x != 0 { ... }, not simply if x { ... }. ([Location 2672](https://readwise.io/to_kindle?action=open&asin=B0979PWD4Z&location=2672)) - Rust’s character type char represents a single Unicode character, as a 32-bit value. ([Location 2686](https://readwise.io/to_kindle?action=open&asin=B0979PWD4Z&location=2686)) - u8 is the only type the as operator will convert to char: ([Location 2731](https://readwise.io/to_kindle?action=open&asin=B0979PWD4Z&location=2731)) - A tuple is a pair, or triple, quadruple, quintuple, etc. (hence, n-tuple, or tuple), of values of assorted types. ([Location 2757](https://readwise.io/to_kindle?action=open&asin=B0979PWD4Z&location=2757)) - To a certain extent, tuples resemble arrays: both types represent an ordered sequence of values. ([Location 2764](https://readwise.io/to_kindle?action=open&asin=B0979PWD4Z&location=2764)) - For one thing, each element of a tuple can have a different type, whereas an array’s elements must be all the same type. ([Location 2766](https://readwise.io/to_kindle?action=open&asin=B0979PWD4Z&location=2766)) - The other commonly used tuple type is the zero-tuple (). This is traditionally called the unit type because it has only one value, also written (). Rust uses the unit type where there’s no meaningful value to carry, but context requires some sort of type nonetheless. ([Location 2819](https://readwise.io/to_kindle?action=open&asin=B0979PWD4Z&location=2819)) - Rust has several types that represent memory addresses. ([Location 2852](https://readwise.io/to_kindle?action=open&asin=B0979PWD4Z&location=2852)) - This is great for memory efficiency, but as a consequence, when a Rust program needs values to point to other values, it must use pointer types explicitly. ([Location 2859](https://readwise.io/to_kindle?action=open&asin=B0979PWD4Z&location=2859)) - It’s easiest to get started by thinking of references as Rust’s basic pointer type. ([Location 2866](https://readwise.io/to_kindle?action=open&asin=B0979PWD4Z&location=2866)) - The expression &x produces a reference to x; in Rust terminology, we say that it borrows a reference to x. ([Location 2868](https://readwise.io/to_kindle?action=open&asin=B0979PWD4Z&location=2868)) - Given a reference r, the expression *r refers to the value r points to. ([Location 2869](https://readwise.io/to_kindle?action=open&asin=B0979PWD4Z&location=2869)) - a reference does not automatically free any resources when it goes out of scope. ([Location 2871](https://readwise.io/to_kindle?action=open&asin=B0979PWD4Z&location=2871)) - Rust references are never null: there is simply no way to produce a null reference in safe Rust. ([Location 2872](https://readwise.io/to_kindle?action=open&asin=B0979PWD4Z&location=2872)) - An immutable, shared reference. ([Location 2877](https://readwise.io/to_kindle?action=open&asin=B0979PWD4Z&location=2877)) - A mutable, exclusive reference. ([Location 2881](https://readwise.io/to_kindle?action=open&asin=B0979PWD4Z&location=2881)) - Rust uses this dichotomy between shared and mutable references to enforce a “single writer or multiple readers” rule: either you can read and write the value, or it can be shared by any number of readers, but never both at the same time. This separation, enforced by compile-time checks, is central to Rust’s safety guarantees. ([Location 2886](https://readwise.io/to_kindle?action=open&asin=B0979PWD4Z&location=2886)) - The simplest way to allocate a value in the heap is to use Box::new: ([Location 2890](https://readwise.io/to_kindle?action=open&asin=B0979PWD4Z&location=2890)) - When b goes out of scope, the memory is freed immediately, unless b has been moved—by returning it, for example. Moves are essential to the way Rust handles heap-allocated values; ([Location 2901](https://readwise.io/to_kindle?action=open&asin=B0979PWD4Z&location=2901)) - Rust also has the raw pointer types *mut T and *const ([Location 2905](https://readwise.io/to_kindle?action=open&asin=B0979PWD4Z&location=2905)) - Using a raw pointer is unsafe, because Rust makes no effort to track what it points to. ([Location 2907](https://readwise.io/to_kindle?action=open&asin=B0979PWD4Z&location=2907)) - An unsafe block is Rust’s opt-in mechanism for advanced language features whose safety is up to you. ([Location 2915](https://readwise.io/to_kindle?action=open&asin=B0979PWD4Z&location=2915)) - The type [T; N] represents an array of N values, each of type T. ([Location 2923](https://readwise.io/to_kindle?action=open&asin=B0979PWD4Z&location=2923)) - The type Vec<T>, called a vector of Ts, is a dynamically allocated, growable sequence of values of type T. ([Location 2926](https://readwise.io/to_kindle?action=open&asin=B0979PWD4Z&location=2926)) - The types &[T] and &mut [T], called a shared slice of Ts and mutable slice of Ts, are references to a series of elements that are a part of some other value, like an array or vector. ([Location 2930](https://readwise.io/to_kindle?action=open&asin=B0979PWD4Z&location=2930)) - When you need an array whose length varies at run time (and you usually do), use a vector instead. ([Location 2992](https://readwise.io/to_kindle?action=open&asin=B0979PWD4Z&location=2992)) - A vector Vec<T> is a resizable array of elements of type T, allocated on the heap. ([Location 3011](https://readwise.io/to_kindle?action=open&asin=B0979PWD4Z&location=3011)) - Another possibility is to build a vector from the values produced by an iterator: ([Location 3057](https://readwise.io/to_kindle?action=open&asin=B0979PWD4Z&location=3057)) - You’ll often need to supply the type when using collect (as we’ve done here), because it can build many different sorts of collections, not just vectors. ([Location 3067](https://readwise.io/to_kindle?action=open&asin=B0979PWD4Z&location=3067)) - A Vec<T> consists of three values: a pointer to the heap-allocated buffer for the elements, which is created and owned by the Vec<T>; the number of elements that buffer has the capacity to store; and the number it actually contains now (in other words, its length). ([Location 3087](https://readwise.io/to_kindle?action=open&asin=B0979PWD4Z&location=3087)) - If you know the number of elements a vector will need in advance, instead of Vec::new you can call Vec::with_capacity to create a vector with a buffer large enough to hold them all, right from the start; then, you can add the elements to the vector one at a time without causing any reallocation. ([Location 3092](https://readwise.io/to_kindle?action=open&asin=B0979PWD4Z&location=3092)) - A slice, written [T] without specifying the length, is a region of an array or vector. ([Location 3196](https://readwise.io/to_kindle?action=open&asin=B0979PWD4Z&location=3196)) - Since a slice can be any length, slices can’t be stored directly in variables or passed as function arguments. Slices are always passed by reference. ([Location 3200](https://readwise.io/to_kindle?action=open&asin=B0979PWD4Z&location=3200)) - A reference to a slice is a fat pointer: a two-word value comprising a pointer to the slice’s first element, and the number of elements in the slice. ([Location 3201](https://readwise.io/to_kindle?action=open&asin=B0979PWD4Z&location=3201)) - This makes slice references a good choice when you want to write a function that operates on either an array or a vector. ([Location 3228](https://readwise.io/to_kindle?action=open&asin=B0979PWD4Z&location=3228)) - String literals are enclosed in double quotes. ([Location 3266](https://readwise.io/to_kindle?action=open&asin=B0979PWD4Z&location=3266)) - Rust offers raw strings. A raw string is tagged with the lowercase letter r. ([Location 3285](https://readwise.io/to_kindle?action=open&asin=B0979PWD4Z&location=3285)) - You can’t include a double-quote character in a raw string simply by putting a backslash in front of it—remember, we said no escape sequences are recognized. However, there is a cure for that too. The start and end of a raw string can be marked with pound signs: ([Location 3294](https://readwise.io/to_kindle?action=open&asin=B0979PWD4Z&location=3294)) - A string literal with the b prefix is a byte string. Such a string is a slice of u8 values—that is, bytes—rather than Unicode text: ([Location 3310](https://readwise.io/to_kindle?action=open&asin=B0979PWD4Z&location=3310)) - Rust strings are sequences of Unicode characters, but they are not stored in memory as arrays of chars. Instead, they are stored using UTF-8, a variable-width encoding. ([Location 3327](https://readwise.io/to_kindle?action=open&asin=B0979PWD4Z&location=3327)) - A String has a resizable buffer holding UTF-8 text. The buffer is allocated on the heap, so it can resize its buffer as needed or requested. ([Location 3340](https://readwise.io/to_kindle?action=open&asin=B0979PWD4Z&location=3340)) - &str is very much like &[T]: a fat pointer to some data. String is analogous to Vec<T>, ([Location 3380](https://readwise.io/to_kindle?action=open&asin=B0979PWD4Z&location=3380)) - The .to_string() method converts a &str to a String. ([Location 3403](https://readwise.io/to_kindle?action=open&asin=B0979PWD4Z&location=3403)) - This means that &str is more appropriate for function arguments when the caller should be allowed to pass either kind of string. ([Location 3440](https://readwise.io/to_kindle?action=open&asin=B0979PWD4Z&location=3440)) - Rust guarantees that strings are valid UTF-8. ([Location 3476](https://readwise.io/to_kindle?action=open&asin=B0979PWD4Z&location=3476)) - Stick to String and &str for Unicode text. When working with filenames, use std::path::PathBuf and &Path instead. When working with binary data that isn’t UTF-8 encoded at all, use Vec<u8> and &[u8]. When working with environment variable names and command-line arguments in the native form presented by the operating system, use OsString and &OsStr. When interoperating with C libraries that use null-terminated strings, use std::ffi::CString and &CStr. ([Location 3482](https://readwise.io/to_kindle?action=open&asin=B0979PWD4Z&location=3482)) - When it comes to managing memory, there are two characteristics we’d like from our programing languages: We ʼ d like memory to be freed promptly, at a time of our choosing. This gives us control over the program’s memory consumption. We never want to use a pointer to an object after it’s been freed. This would be undefined behavior, leading to crashes and security holes. ([Location 3513](https://readwise.io/to_kindle?action=open&asin=B0979PWD4Z&location=3513)) - At run time, your pointers are simple addresses in memory, just as they would be in C and C++. The difference is that your code has been proven to use them safely. ([Location 3538](https://readwise.io/to_kindle?action=open&asin=B0979PWD4Z&location=3538)) - These same rules also form the basis of Rust’s support for safe concurrent programming. Using Rust’s carefully designed threading primitives, the rules that ensure your code uses memory correctly also serve to prove that it is free of data races. ([Location 3540](https://readwise.io/to_kindle?action=open&asin=B0979PWD4Z&location=3540)) - In Rust, however, the concept of ownership is built into the language itself and enforced by compile-time checks. Every value has a single owner that determines its lifetime. When the owner is freed—dropped, in Rust terminology—the owned value is dropped too. ([Location 3579](https://readwise.io/to_kindle?action=open&asin=B0979PWD4Z&location=3579)) - Rust’s Box type serves as another example of ownership. A Box<T> is a pointer to a value of type T stored on the heap. Calling Box::new(v) allocates some heap space, moves the value v into it, and returns a Box pointing to the heap space. ([Location 3617](https://readwise.io/to_kindle?action=open&asin=B0979PWD4Z&location=3617)) - Just as variables own their values, structs own their fields, and tuples, arrays, and vectors own their elements: ([Location 3642](https://readwise.io/to_kindle?action=open&asin=B0979PWD4Z&location=3642)) - It follows that the owners and their owned values form trees: your owner is your parent, and the values you own are your children. And at the ultimate root of each tree is a variable; when that variable goes out of scope, the entire tree goes with it. ([Location 3683](https://readwise.io/to_kindle?action=open&asin=B0979PWD4Z&location=3683)) - Rust extends this simple idea in several ways: You  can  move  values  from  one  owner  to  another. This allows you to  build,  rearrange, and tear down the tree. Very simple types like integers, floating-point numbers, and characters are excused from the ownership rules. These are called Copy types. The standard library provides the reference-counted pointer types Rc and Arc, which allow values to have multiple owners, under some restrictions. You can “borrow a reference” to a value; references are non-owning pointers, with limited lifetimes. ([Location 3700](https://readwise.io/to_kindle?action=open&asin=B0979PWD4Z&location=3700)) - A tokio broadcast channel is a queue of values (in our case, chat messages) that allows any number of different threads or tasks to send and receive values. It’s called a “broadcast” channel because every consumer gets its own copy of each value sent. (The value type must implement Clone.) ([Location 26392](https://readwise.io/to_kindle?action=open&asin=B0979PWD4Z&location=26392))