Rust in Action

Book description

Rust in Action introduces the Rust programming language by exploring numerous systems programming concepts and techniques. You'll be learning Rust by delving into how computers work under the hood. You'll find yourself playing with persistent storage, memory, networking and even tinkering with CPU instructions. The book takes you through using Rust to extend other applications and teaches you tricks to write blindingly fast code. You'll also discover parallel and concurrent programming. Filled to the brim with real-life use cases and scenarios, you'll go beyond the Rust syntax and see what Rust has to offer in real-world use cases.

About the Technology
Rust is the perfect language for systems programming. It delivers the low-level power of C along with rock-solid safety features that let you code fearlessly. Ideal for applications requiring concurrency, Rust programs are compact, readable, and blazingly fast. Best of all, Rust’s famously smart compiler helps you avoid even subtle coding errors.

About the Book
Rust in Action is a hands-on guide to systems programming with Rust. Written for inquisitive programmers, it presents real-world use cases that go far beyond syntax and structure. You’ll explore Rust implementations for file manipulation, networking, and kernel-level programming and discover awesome techniques for parallelism and concurrency. Along the way, you’ll master Rust’s unique borrow checker model for memory management without a garbage collector.

What's Inside
  • Elementary to advanced Rust programming
  • Practical examples from systems programming
  • Command-line, graphical and networked applications


About the Reader
For intermediate programmers. No previous experience with Rust required.

About the Author
Tim McNamara uses Rust to build data processing pipelines and generative art. He is an expert in natural language processing and data engineering.

Quotes
This well-written book will help you make the most of what Rust has to offer.
- Ramnivas Laddad, author of AspectJ in Action

Engaging writing style and crisp, easy-to-grasp examples help the reader get off the ground in no time.
- Sumant Tambe, Linkedin

Rust in Action is remarkably polished!
- Christopher Haupt, Swoogo

Makes it easy to explore the language and get going with it.
- Federico Hernandez, Meltwater

I highly recommend this book to those who want to learn Rust.
- Afshin Mehrabani, Etsy

Publisher resources

View/Submit Errata

Table of contents

  1. inside front cover
  2. Rust in Action
  3. Copyright
  4. dedication
  5. contents
  6. front matter
    1. preface
    2. acknowledgments
    3. about this book
      1. Who should read this book
      2. How this book is organized: A roadmap
      3. About the code
      4. liveBook discussion forum
      5. Other online resources
    4. about the author
    5. about the cover illustration
  7. 1 Introducing Rust
    1. 1.1 Where is Rust used?
    2. 1.2 Advocating for Rust at work
    3. 1.3 A taste of the language
      1. 1.3.1 Cheating your way to “Hello, world!”
      2. 1.3.2 Your first Rust program
    4. 1.4 Downloading the book’s source code
    5. 1.5 What does Rust look and feel like?
    6. 1.6 What is Rust?
      1. 1.6.1 Goal of Rust: Safety
      2. 1.6.2 Goal of Rust: Productivity
      3. 1.6.3 Goal of Rust: Control
    7. 1.7 Rust’s big features
      1. 1.7.1 Performance
      2. 1.7.2 Concurrency
      3. 1.7.3 Memory efficiency
    8. 1.8 Downsides of Rust
      1. 1.8.1 Cyclic data structures
      2. 1.8.2 Compile times
      3. 1.8.3 Strictness
      4. 1.8.4 Size of the language
      5. 1.8.5 Hype
    9. 1.9 TLS security case studies
      1. 1.9.1 Heartbleed
      2. 1.9.2 Goto fail;
    10. 1.10 Where does Rust fit best?
      1. 1.10.1 Command-line utilities
      2. 1.10.2 Data processing
      3. 1.10.3 Extending applications
      4. 1.10.4 Resource-constrained environments
      5. 1.10.5 Server-side applications
      6. 1.10.6 Desktop applications
      7. 1.10.7 Desktop
      8. 1.10.8 Mobile
      9. 1.10.9 Web
      10. 1.10.10 Systems programming
    11. 1.11 Rust’s hidden feature: Its community
    12. 1.12 Rust phrase book
    13. Summary
  8. Part 1 Rust language distinctives
  9. 2 Language foundations
    1. 2.1 Creating a running program
      1. 2.1.1 Compiling single files with rustc
      2. 2.1.2 Compiling Rust projects with cargo
    2. 2.2 A glance at Rust’s syntax
      1. 2.2.1 Defining variables and calling functions
    3. 2.3 Numbers
      1. 2.3.1 Integers and decimal (floating-point) numbers
      2. 2.3.2 Integers with base 2, base 8, and base 16 notation
      3. 2.3.3 Comparing numbers
      4. 2.3.4 Rational, complex numbers, and other numeric types
    4. 2.4 Flow control
      1. 2.4.1 For: The central pillar of iteration
      2. 2.4.2 Continue: Skipping the rest of the current iteration
      3. 2.4.3 While: Looping until a condition changes its state
      4. 2.4.4 Loop: The basis for Rust’s looping constructs
      5. 2.4.5 Break: Aborting a loop
      6. 2.4.6 If, if else, and else: Conditional branching
      7. 2.4.7 Match: Type-aware pattern matching
    5. 2.5 Defining functions
    6. 2.6 Using references
    7. 2.7 Project: Rendering the Mandelbrot set
    8. 2.8 Advanced function definitions
      1. 2.8.1 Explicit lifetime annotations
      2. 2.8.2 Generic functions
    9. 2.9 Creating grep-lite
    10. 2.10 Making lists of things with arrays, slices, and vectors
      1. 2.10.1 Arrays
      2. 2.10.2 Slices
      3. 2.10.3 Vectors
    11. 2.11 Including third-party code
      1. 2.11.1 Adding support for regular expressions
      2. 2.11.2 Generating the third-party crate documentation locally
      3. 2.11.3 Managing Rust toolchains with rustup
    12. 2.12 Supporting command-line arguments
    13. 2.13 Reading from files
    14. 2.14 Reading from stdin
    15. Summary
  10. 3 Compound data types
    1. 3.1 Using plain functions to experiment with an API
    2. 3.2 Modeling files with struct
    3. 3.3 Adding methods to a struct with impl
      1. 3.3.1 Simplifying object creation by implementing new()
    4. 3.4 Returning errors
      1. 3.4.1 Modifying a known global variable
      2. 3.4.2 Making use of the Result return type
    5. 3.5 Defining and making use of an enum
      1. 3.5.1 Using an enum to manage internal state
    6. 3.6 Defining common behavior with traits
      1. 3.6.1 Creating a Read trait
      2. 3.6.2 Implementing std::fmt::Display for your own types
    7. 3.7 Exposing your types to the world
      1. 3.7.1 Protecting private data
    8. 3.8 Creating inline documentation for your projects
      1. 3.8.1 Using rustdoc to render docs for a single source file
      2. 3.8.2 Using cargo to render docs for a crate and its dependencies
    9. Summary
  11. 4 Lifetimes, ownership, and borrowing
    1. 4.1 Implementing a mock CubeSat ground station
      1. 4.1.1 Encountering our first lifetime issue
      2. 4.1.2 Special behavior of primitive types
    2. 4.2 Guide to the figures in this chapter
    3. 4.3 What is an owner? Does it have any responsibilities?
    4. 4.4 How ownership moves
    5. 4.5 Resolving ownership issues
      1. 4.5.1 Use references where full ownership is not required
      2. 4.5.2 Use fewer long-lived values
      3. 4.5.3 Duplicate the value
      4. 4.5.4 Wrap data within specialty types
    6. Summary
  12. Part 2 Demystifying systems programming
  13. 5 Data in depth
    1. 5.1 Bit patterns and types
    2. 5.2 Life of an integer
      1. 5.2.1 Understanding endianness
    3. 5.3 Representing decimal numbers
    4. 5.4 Floating-point numbers
      1. 5.4.1 Looking inside an f32
      2. 5.4.2 Isolating the sign bit
      3. 5.4.3 Isolating the exponent
      4. 5.4.4 Isolate the mantissa
      5. 5.4.5 Dissecting a floating-point number
    5. 5.5 Fixed-point number formats
    6. 5.6 Generating random probabilities from random bytes
    7. 5.7 Implementing a CPU to establish that functions are also data
      1. 5.7.1 CPU RIA/1: The Adder
      2. 5.7.2 Full code listing for CPU RIA/1: The Adder
      3. 5.7.3 CPU RIA/2: The Multiplier
      4. 5.7.4 CPU RIA/3: The Caller
      5. 5.7.5 CPU 4: Adding the rest
    8. Summary
  14. 6 Memory
    1. 6.1 Pointers
    2. 6.2 Exploring Rust’s reference and pointer types
      1. 6.2.1 Raw pointers in Rust
      2. 6.2.2 Rust’s pointer ecosystem
      3. 6.2.3 Smart pointer building blocks
    3. 6.3 Providing programs with memory for their data
      1. 6.3.1 The stack
      2. 6.3.2 The heap
      3. 6.3.3 What is dynamic memory allocation?
      4. 6.3.4 Analyzing the impact of dynamic memory allocation
    4. 6.4 Virtual memory
      1. 6.4.1 Background
      2. 6.4.2 Step 1: Having a process scan its own memory
      3. 6.4.3 Translating virtual addresses to physical addresses
      4. 6.4.4 Step 2: Working with the OS to scan an address space
      5. 6.4.5 Step 3: Reading from and writing to process memory
    5. Summary
  15. 7 Files and storage
    1. 7.1 What is a file format?
    2. 7.2 Creating your own file formats for data storage
      1. 7.2.1 Writing data to disk with serde and the bincode format
    3. 7.3 Implementing a hexdump clone
    4. 7.4 File operations in Rust
      1. 7.4.1 Opening a file in Rust and controlling its file mode
      2. 7.4.2 Interacting with the filesystem in a type-safe manner with std::fs::Path
    5. 7.5 Implementing a key-value store with a log-structured, append-only storage architecture
      1. 7.5.1 The key-value model
      2. 7.5.2 Introducing actionkv v1: An in-memory key-value store with a command-line interface
    6. 7.6 Actionkv v1: The front-end code
      1. 7.6.1 Tailoring what is compiled with conditional compilation
    7. 7.7 Understanding the core of actionkv: The libactionkv crate
      1. 7.7.1 Initializing the ActionKV struct
      2. 7.7.2 Processing an individual record
      3. 7.7.3 Writing multi-byte binary data to disk in a guaranteed byte order
      4. 7.7.4 Validating I/O errors with checksums
      5. 7.7.5 Inserting a new key-value pair into an existing database
      6. 7.7.6 The full code listing for actionkv
      7. 7.7.7 Working with keys and values with HashMap and BTreeMap
      8. 7.7.8 Creating a HashMap and populating it with values
      9. 7.7.9 Retrieving values from HashMap and BTreeMap
      10. 7.7.10 How to decide between HashMap and BTreeMap
      11. 7.7.11 Adding a database index to actionkv v2.0
    8. Summary
  16. 8 Networking
    1. 8.1 All of networking in seven paragraphs
    2. 8.2 Generating an HTTP GET request with reqwest
    3. 8.3 Trait objects
      1. 8.3.1 What do trait objects enable?
      2. 8.3.2 What is a trait object?
      3. 8.3.3 Creating a tiny role-playing game: The rpg project
    4. 8.4 TCP
      1. 8.4.1 What is a port number?
      2. 8.4.2 Converting a hostname to an IP address
    5. 8.5 Ergonomic error handling for libraries
      1. 8.5.1 Issue: Unable to return multiple error types
      2. 8.5.2 Wrapping downstream errors by defining our own error type
      3. 8.5.3 Cheating with unwrap() and expect()
    6. 8.6 MAC addresses
      1. 8.6.1 Generating MAC addresses
    7. 8.7 Implementing state machines with Rust’s enums
    8. 8.8 Raw TCP
    9. 8.9 Creating a virtual networking device
    10. 8.10 “Raw” HTTP
    11. Summary
  17. 9 Time and timekeeping
    1. 9.1 Background
    2. 9.2 Sources of time
    3. 9.3 Definitions
    4. 9.4 Encoding time
      1. 9.4.1 Representing time zones
    5. 9.5 clock v0.1.0: Teaching an application how to tell the time
    6. 9.6 clock v0.1.1: Formatting timestamps to comply with ISO 8601 and email standards
      1. 9.6.1 Refactoring the clock v0.1.0 code to support a wider architecture
      2. 9.6.2 Formatting the time
      3. 9.6.3 Providing a full command-line interface
      4. 9.6.4 clock v0.1.1: Full project
    7. 9.7 clock v0.1.2: Setting the time
      1. 9.7.1 Common behavior
      2. 9.7.2 Setting the time for operating systems that use libc
      3. 9.7.3 Setting the time on MS Windows
      4. 9.7.4 clock v0.1.2: The full code listing
    8. 9.8 Improving error handling
    9. 9.9 clock v0.1.3: Resolving differences between clocks with the Network Time Protocol (NTP)
      1. 9.9.1 Sending NTP requests and interpreting responses
      2. 9.9.2 Adjusting the local time as a result of the server’s response
      3. 9.9.3 Converting between time representations that use different precisions and epochs
      4. 9.9.4 clock v0.1.3: The full code listing
    10. Summary
  18. 10 Processes, threads, and containers
    1. 10.1 Anonymous functions
    2. 10.2 Spawning threads
      1. 10.2.1 Introduction to closures
      2. 10.2.2 Spawning a thread
      3. 10.2.3 Effect of spawning a few threads
      4. 10.2.4 Effect of spawning many threads
      5. 10.2.5 Reproducing the results
      6. 10.2.6 Shared variables
    3. 10.3 Differences between closures and functions
    4. 10.4 Procedurally generated avatars from a multithreaded parser and code generator
      1. 10.4.1 How to run render-hex and its intended output
      2. 10.4.2 Single-threaded render-hex overview
      3. 10.4.3 Spawning a thread per logical task
      4. 10.4.4 Using a thread pool and task queue
    5. 10.5 Concurrency and task virtualization
      1. 10.5.1 Threads
      2. 10.5.2 What is a context switch?
      3. 10.5.3 Processes
      4. 10.5.4 WebAssembly
      5. 10.5.5 Containers
      6. 10.5.6 Why use an operating system (OS) at all?
    6. Summary
  19. 11 Kernel
    1. 11.1 A fledgling operating system (FledgeOS)
      1. 11.1.1 Setting up a development environment for developing an OS kernel
      2. 11.1.2 Verifying the development environment
    2. 11.2 Fledgeos-0: Getting something working
      1. 11.2.1 First boot
      2. 11.2.2 Compilation instructions
      3. 11.2.3 Source code listings
      4. 11.2.4 Panic handling
      5. 11.2.5 Writing to the screen with VGA-compatible text mode
      6. 11.2.6 _start(): The main() function for FledgeOS
    3. 11.3 fledgeos-1: Avoiding a busy loop
      1. 11.3.1 Being power conscious by interacting with the CPU directly
      2. 11.3.2 fledgeos-1 source code
    4. 11.4 fledgeos-2: Custom exception handling
      1. 11.4.1 Handling exceptions properly, almost
      2. 11.4.2 fledgeos-2 source code
    5. 11.5 fledgeos-3: Text output
      1. 11.5.1 Writing colored text to the screen
      2. 11.5.2 Controlling the in-memory representation of enums
      3. 11.5.3 Why use enums?
      4. 11.5.4 Creating a type that can print to the VGA frame buffer
      5. 11.5.5 Printing to the screen
      6. 11.5.6 fledgeos-3 source code
    6. 11.6 fledgeos-4: Custom panic handling
      1. 11.6.1 Implementing a panic handler that reports the error to the user
      2. 11.6.2 Reimplementing panic() by making use of core::fmt::Write
      3. 11.6.3 Implementing core::fmt::Write
      4. 11.6.4 fledge-4 source code
    7. Summary
  20. 12 Signals, interrupts, and exceptions
    1. 12.1 Glossary
      1. 12.1.1 Signals vs. interrupts
    2. 12.2 How interrupts affect applications
    3. 12.3 Software interrupts
    4. 12.4 Hardware interrupts
    5. 12.5 Signal handling
      1. 12.5.1 Default behavior
      2. 12.5.2 Suspend and resume a program’s operation
      3. 12.5.3 Listing all signals supported by the OS
    6. 12.6 Handling signals with custom actions
      1. 12.6.1 Global variables in Rust
      2. 12.6.2 Using a global variable to indicate that shutdown has been initiated
    7. 12.7 Sending application-defined signals
      1. 12.7.1 Understanding function pointers and their syntax
    8. 12.8 Ignoring signals
    9. 12.9 Shutting down from deeply nested call stacks
      1. 12.9.1 Introducing the sjlj project
      2. 12.9.2 Setting up intrinsics in a program
      3. 12.9.3 Casting a pointer to another type
      4. 12.9.4 Compiling the sjlj project
      5. 12.9.5 sjlj project source code
    10. 12.10 A note on applying these techniques to platforms without signals
    11. 12.11 Revising exceptions
    12. Summary
  21. index

Product information

  • Title: Rust in Action
  • Author(s): Tim McNamara
  • Release date: August 2021
  • Publisher(s): Manning Publications
  • ISBN: 9781617294556