- Preface
- Who Should Read This Book
- Why We Wrote This Book
- Navigating This Book
- Conventions Used in This Book
- Using Code Examples
- O’Reilly Online Learning
- How to Contact Us
- Acknowledgments
- 1. Systems Programmers Can Have Nice Things
- Rust Shoulders the Load for You
- Parallel Programming Is Tamed
- And Yet Rust Is Still Fast
- Rust Makes Collaboration Easier
- 2. A Tour of Rust
- rustup and Cargo
- Rust Functions
- Writing and Running Unit Tests
- Handling Command-Line Arguments
- Serving Pages to the Web
- Concurrency
- What the Mandelbrot Set Actually Is
- Parsing Pair Command-Line Arguments
- Mapping from Pixels to Complex Numbers
- Plotting the Set
- Writing Image Files
- A Concurrent Mandelbrot Program
- Running the Mandelbrot Plotter
- Safety Is Invisible
- Filesystems and Command-Line Tools
- The Command-Line Interface
- Reading and Writing Files
- Find and Replace
- 3. Fundamental Types
- Fixed-Width Numeric Types
- Integer Types
- Checked, Wrapping, Saturating, and Overflowing Arithmetic
- Floating-Point Types
- The bool Type
- Characters
- Tuples
- Pointer Types
- References
- Boxes
- Raw Pointers
- Arrays, Vectors, and Slices
- Arrays
- Vectors
- Slices
- String Types
- String Literals
- Byte Strings
- Strings in Memory
- String
- Using Strings
- Other String-Like Types
- Type Aliases
- Beyond the Basics
- 4. Ownership and Moves
- Ownership
- Moves
- More Operations That Move
- Moves and Control Flow
- Moves and Indexed Content
- Copy Types: The Exception to Moves
- Rc and Arc: Shared Ownership
- 5. References
- References to Values
- Working with References
- Rust References Versus C++ References
- Assigning References
- References to References
- Comparing References
- References Are Never Null
- Borrowing References to Arbitrary Expressions
- References to Slices and Trait Objects
- Reference Safety
- Borrowing a Local Variable
- Receiving References as Function Arguments
- Passing References to Functions
- Returning References
- Structs Containing References
- Distinct Lifetime Parameters
- Omitting Lifetime Parameters
- Sharing Versus Mutation
- Taking Arms Against a Sea of Objects
- 6. Expressions
- An Expression Language
- Precedence and Associativity
- Blocks and Semicolons
- Declarations
- if and match
- if let
- Loops
- Control Flow in Loops
- return Expressions
- Why Rust Has loop
- Function and Method Calls
- Fields and Elements
- Reference Operators
- Arithmetic, Bitwise, Comparison, and Logical Operators
- Assignment
- Type Casts
- Closures
- Onward
- 7. Error Handling
- Panic
- Unwinding
- Aborting
- Result
- Catching Errors
- Result Type Aliases
- Printing Errors
- Propagating Errors
- Working with Multiple Error Types
- Dealing with Errors That “Can’t Happen”
- Ignoring Errors
- Handling Errors in main()
- Declaring a Custom Error Type
- Why Results?
- 8. Crates and Modules
- Crates
- Editions
- Build Profiles
- Modules
- Nested Modules
- Modules in Separate Files
- Paths and Imports
- The Standard Prelude
- Making use Declarations pub
- Making Struct Fields pub
- Statics and Constants
- Turning a Program into a Library
- The src/bin Directory
- Attributes
- Tests and Documentation
- Integration Tests
- Documentation
- Doc-Tests
- Specifying Dependencies
- Versions
- Cargo.lock
- Publishing Crates to crates.io
- Workspaces
- More Nice Things
- 9. Structs
- Named-Field Structs
- Tuple-Like Structs
- Unit-Like Structs
- Struct Layout
- Defining Methods with impl
- Passing Self as a Box, Rc, or Arc
- Type-Associated Functions
- Associated Consts
- Generic Structs
- Structs with Lifetime Parameters
- Deriving Common Traits for Struct Types
- Interior Mutability
- 10. Enums and Patterns
- Enums
- Enums with Data
- Enums in Memory
- Rich Data Structures Using Enums
- Generic Enums
- Patterns
- Literals, Variables, and Wildcards in Patterns
- Tuple and Struct Patterns
- Array and Slice Patterns
- Reference Patterns
- Match Guards
- Matching Multiple Possibilities
- Binding with @ Patterns
- Where Patterns Are Allowed
- Populating a Binary Tree
- The Big Picture
- 11. Traits and Generics
- Using Traits
- Trait Objects
- Generic Functions and Type Parameters
- Which to Use
- Defining and Implementing Traits
- Default Methods
- Traits and Other People’s Types
- Self in Traits
- Subtraits
- Type-Associated Functions
- Fully Qualified Method Calls
- Traits That Define Relationships Between Types
- Associated Types (or How Iterators Work)
- Generic Traits (or How Operator Overloading Works)
- impl Trait
- Associated Consts
- Reverse-Engineering Bounds
- Traits as a Foundation
- 12. Operator Overloading
- Arithmetic and Bitwise Operators
- Unary Operators
- Binary Operators
- Compound Assignment Operators
- Equivalence Comparisons
- Ordered Comparisons
- Index and IndexMut
- Other Operators
- 13. Utility Traits
- Drop
- Sized
- Clone
- Copy
- Deref and DerefMut
- Default
- AsRef and AsMut
- Borrow and BorrowMut
- From and Into
- TryFrom and TryInto
- ToOwned
- Borrow and ToOwned at Work: The Humble Cow
- 14. Closures
- Capturing Variables
- Closures That Borrow
- Closures That Steal
- Function and Closure Types
- Closure Performance
- Closures and Safety
- Closures That Kill
- FnOnce
- FnMut
- Copy and Clone for Closures
- Callbacks
- Using Closures Effectively
- 15. Iterators
- The Iterator and IntoIterator Traits
- Creating Iterators
- iter and iter_mut Methods
- IntoIterator Implementations
- from_fn and successors
- drain Methods
- Other Iterator Sources
- Iterator Adapters
- map and filter
- filter_map and flat_map
- flatten
- take and take_while
- skip and skip_while
- peekable
- fuse
- Reversible Iterators and rev
- inspect
- chain
- enumerate
- zip
- by_ref
- cloned, copied
- cycle
- Consuming Iterators
- Simple Accumulation: count, sum, product
- max, min
- max_by, min_by
- max_by_key, min_by_key
- Comparing Item Sequences
- any and all
- position, rposition, and ExactSizeIterator
- fold and rfold
- try_fold and try_rfold
- nth, nth_back
- last
- find, rfind, and find_map
- Building Collections: collect and FromIterator
- The Extend Trait
- partition
- for_each and try_for_each
- Implementing Your Own Iterators
- 16. Collections
- Overview
- Vec<T>
- Accessing Elements
- Iteration
- Growing and Shrinking Vectors
- Joining
- Splitting
- Swapping
- Sorting and Searching
- Comparing Slices
- Random Elements
- Rust Rules Out Invalidation Errors
- VecDeque<T>
- BinaryHeap<T>
- HashMap<K, V> and BTreeMap<K, V>
- Entries
- Map Iteration
- HashSet<T> and BTreeSet<T>
- Set Iteration
- When Equal Values Are Different
- Whole-Set Operations
- Hashing
- Using a Custom Hashing Algorithm
- Beyond the Standard Collections
- 17. Strings and Text
- Some Unicode Background
- ASCII, Latin-1, and Unicode
- UTF-8
- Text Directionality
- Characters (char)
- Classifying Characters
- Handling Digits
- Case Conversion for Characters
- Conversions to and from Integers
- String and str
- Creating String Values
- Simple Inspection
- Appending and Inserting Text
- Removing and Replacing Text
- Conventions for Searching and Iterating
- Patterns for Searching Text
- Searching and Replacing
- Iterating over Text
- Trimming
- Case Conversion for Strings
- Parsing Other Types from Strings
- Converting Other Types to Strings
- Borrowing as Other Text-Like Types
- Accessing Text as UTF-8
- Producing Text from UTF-8 Data
- Putting Off Allocation
- Strings as Generic Collections
- Formatting Values
- Formatting Text Values
- Formatting Numbers
- Formatting Other Types
- Formatting Values for Debugging
- Formatting Pointers for Debugging
- Referring to Arguments by Index or Name
- Dynamic Widths and Precisions
- Formatting Your Own Types
- Using the Formatting Language in Your Own Code
- Regular Expressions
- Basic Regex Use
- Building Regex Values Lazily
- Normalization
- Normalization Forms
- The unicode-normalization Crate
- 18. Input and Output
- Readers and Writers
- Readers
- Buffered Readers
- Reading Lines
- Collecting Lines
- Writers
- Files
- Seeking
- Other Reader and Writer Types
- Binary Data, Compression, and Serialization
- Files and Directories
- OsStr and Path
- Path and PathBuf Methods
- Filesystem Access Functions
- Reading Directories
- Platform-Specific Features
- Networking
- 19. Concurrency
- Fork-Join Parallelism
- spawn and join
- Error Handling Across Threads
- Sharing Immutable Data Across Threads
- Rayon
- Revisiting the Mandelbrot Set
- Channels
- Sending Values
- Receiving Values
- Running the Pipeline
- Channel Features and Performance
- Thread Safety: Send and Sync
- Piping Almost Any Iterator to a Channel
- Beyond Pipelines
- Shared Mutable State
- What Is a Mutex?
- Mutex<T>
- mut and Mutex
- Why Mutexes Are Not Always a Good Idea
- Deadlock
- Poisoned Mutexes
- Multiconsumer Channels Using Mutexes
- Read/Write Locks (RwLock<T>)
- Condition Variables (Condvar)
- Atomics
- Global Variables
- What Hacking Concurrent Code in Rust Is Like
- 20. Asynchronous Programming
- From Synchronous to Asynchronous
- Futures
- Async Functions and Await Expressions
- Calling Async Functions from Synchronous Code: block_on
- Spawning Async Tasks
- Async Blocks
- Building Async Functions from Async Blocks
- Spawning Async Tasks on a Thread Pool
- But Does Your Future Implement Send?
- Long Running Computations: yield_now and spawn_blocking
- Comparing Asynchronous Designs
- A Real Asynchronous HTTP Client
- An Asynchronous Client and Server
- Error and Result Types
- The Protocol
- Taking User Input: Asynchronous Streams
- Sending Packets
- Receiving Packets: More Asynchronous Streams
- The Client’s Main Function
- The Server’s Main Function
- Handling Chat Connections: Async Mutexes
- The Group Table: Synchronous Mutexes
- Chat Groups: tokio’s Broadcast Channels
- Primitive Futures and Executors: When Is a Future Worth Polling Again?
- Invoking Wakers: spawn_blocking
- Implementing block_on
- Pinning
- The Two Life Stages of a Future
- Pinned Pointers
- The Unpin Trait
- When Is Asynchronous Code Helpful?
- 21. Macros
- Macro Basics
- Basics of Macro Expansion
- Unintended Consequences
- Repetition
- Built-In Macros
- Debugging Macros
- Building the json! Macro
- Fragment Types
- Recursion in Macros
- Using Traits with Macros
- Scoping and Hygiene
- Importing and Exporting Macros
- Avoiding Syntax Errors During Matching
- Beyond macro_rules!
- 22. Unsafe Code
- Unsafe from What?
- Unsafe Blocks
- Example: An Efficient ASCII String Type
- Unsafe Functions
- Unsafe Block or Unsafe Function?
- Undefined Behavior
- Unsafe Traits
- Raw Pointers
- Dereferencing Raw Pointers Safely
- Example: RefWithFlag
- Nullable Pointers
- Type Sizes and Alignments
- Pointer Arithmetic
- Moving into and out of Memory
- Example: GapBuffer
- Panic Safety in Unsafe Code
- Reinterpreting Memory with Unions
- Matching Unions
- Borrowing Unions
- 23. Foreign Functions
- Finding Common Data Representations
- Declaring Foreign Functions and Variables
- Using Functions from Libraries
- A Raw Interface to libgit2
- A Safe Interface to libgit2
- Conclusion
- Index