More About Cargo and Crates.io So far, we’ve used only the most basic features of Cargo to build, run, and test our code, but it can do a lot more. In this chapter, we’ll discuss some of its other, more advanced features to show you how to...
Customizing Builds with Release Profiles In Rust, release profiles are predefined, customizable profiles with different configurations that allow a programmer to have more control over various options for compiling code. Each profile is con...
Publishing a Crate to Crates.io We’ve used packages from crates.io as dependencies of our project, but you can also share your code with other people by publishing your own packages. The crate registry at crates.io distributes the source co...
Cargo Workspaces In Chapter 12, we built a package that included a binary crate and a library crate. As your project develops, you might find that the library crate continues to get bigger and you want to split your package further into mul...
Installing Binaries with cargo install The cargo install command allows you to install and use binary crates locally. This isn’t intended to replace system packages; it’s meant to be a convenient way for Rust developers to install tools tha...
Extending Cargo with Custom Commands Cargo is designed so that you can extend it with new subcommands without having to modify it. If a binary in your $PATH is named cargo-something, you can run it as if it were a Cargo subcommand by runnin...
Smart Pointers A pointer is a general concept for a variable that contains an address in memory. This address refers to, or “points at,” some other data. The most common kind of pointer in Rust is a reference, which you learned about in Cha...
Using Box<T> to Point to Data on the Heap The most straightforward smart pointer is a box, whose type is written Box<T>. Boxes allow you to store data on the heap rather than the stack. What remains on the stack is the pointer to the heap d...
Treating Smart Pointers Like Regular References Implementing the Deref trait allows you to customize the behavior of the dereference operator * (not to be confused with the multiplication or glob operator). By implementing Deref in such a w...
Running Code on Cleanup with the Drop Trait The second trait important to the smart pointer pattern is Drop, which lets you customize what happens when a value is about to go out of scope. You can provide an implementation for the Drop trai...
Rc<T>, the Reference-Counted Smart Pointer In the majority of cases, ownership is clear: You know exactly which variable owns a given value. However, there are cases when a single value might have multiple owners. For example, in graph data...
RefCell<T> and the Interior Mutability Pattern Interior mutability is a design pattern in Rust that allows you to mutate data even when there are immutable references to that data; normally, this action is disallowed by the borrowing rules....
Reference Cycles Can Leak Memory Rust’s memory safety guarantees make it difficult, but not impossible, to accidentally create memory that is never cleaned up (known as a memory leak). Preventing memory leaks entirely is not one of Rust’s g...
Fearless Concurrency Handling concurrent programming safely and efficiently is another of Rust’s major goals. Concurrent programming, in which different parts of a program execute independently, and parallel programming, in which different...
Using Threads to Run Code Simultaneously In most current operating systems, an executed program’s code is run in a process, and the operating system will manage multiple processes at once. Within a program, you can also have independent par...
Transfer Data Between Threads with Message Passing One increasingly popular approach to ensuring safe concurrency is message passing, where threads or actors communicate by sending each other messages containing data. Here’s the idea in a s...
Shared-State Concurrency Message passing is a fine way to handle concurrency, but it’s not the only way. Another method would be for multiple threads to access the same shared data. Consider this part of the slogan from the Go language docu...
Extensible Concurrency with Send and Sync Interestingly, almost every concurrency feature we’ve talked about so far in this chapter has been part of the standard library, not the language. Your options for handling concurrency are not limit...
Fundamentals of Asynchronous Programming: Async, Await, Futures, and Streams Many operations we ask the computer to do can take a while to finish. It would be nice if we could do something else while we’re waiting for those long-running pro...
Futures and the Async Syntax The key elements of asynchronous programming in Rust are futures and Rust’s async and await keywords. A future is a value that may not be ready now but will become ready at some point in the future. (This same c...