notes.org
1 #+title: The Rust Programming Language 2 3 /by Steve labnik, carol Nichols, and Chris Krycho, with contributions from the Rust Community/ 4 5 This version of the text assumes you’re using Rust 1.90.0 (released 2025-09-18) or later with =edition = "2024"= in the /Cargo.toml/ file of all projects to configure them to use Rust 2024 Edition idioms. See the [[*Installation][“Installation” section of Chapter 1]] for instructions on installing or updating Rust, and see [[*E - Editions][Appendix E]] for information on editions. 6 7 The HTML format is available online at https://doc.rust-lang.org/stable/book/ and offline with installations of Rust made with =rustup=; run =rustup doc --book= to open. 8 9 Several community [[*F - Translations of the Book][translations]] are also available. 10 11 This text is available in [[https://nostarch.com/rust-programming-language-3e][paperback and ebook format from No Starch Press]]. 12 13 #+begin_quote 14 🚨 Want a more interactive learning experience? 15 16 Try the Rust Book with quizzes, highlighting, and more: 17 https://rust-book.cs.brown.edu 18 #+end_quote 19 20 - *Foreward* 21 22 The Rust programming language has come a long way in a few short years, from its creation and incubation by a small and nascent community of enthusiasts, to becoming one of the most loved and in-demand programming languages in the world. Looking back, it was inevitable that the power and promise of Rust would turn heads and gain a foothold in systems programming. What was not inevitable was the global growth in interest and innovation that permeated through open source communities and catalyzed wide-scale adoption across industries. 23 24 At this point in time, it is easy to point to the wonderful features that Rust has to offer to explain this explosion in interest and adoption. Who doesn’t want memory safety, and fast performance, and a friendly compiler, and great tooling, among a host of other wonderful features? The Rust language you see today combines years of research in systems programming with the practical wisdom of a vibrant and passionate community. This language was designed with purpose and crafted with care, offering developers a tool that makes it easier to write safe, fast, and reliable code. 25 26 But what makes Rust truly special is its roots in empowering you, the user, to achieve your goals. This is a language that wants you to succeed, and the principle of empowerment runs through the core of the community that builds, maintains, and advocates for this language. Since the previous edition of this definitive text, Rust has further developed into a truly global and trusted language. The Rust Project is now robustly supported by the Rust Foundation, which also invests in key initiatives to ensure that Rust is secure, stable, and sustainable. 27 28 This edition of The Rust Programming Language is a comprehensive update, reflecting the language’s evolution over the years and providing valuable new information. But it is not just a guide to syntax and libraries—it’s an invitation to join a community that values quality, performance, and thoughtful design. Whether you’re a seasoned developer looking to explore Rust for the first time or an experienced Rustacean looking to refine your skills, this edition offers something for everyone. 29 30 The Rust journey has been one of collaboration, learning, and iteration. The growth of the language and its ecosystem is a direct reflection of the vibrant, diverse community behind it. The contributions of thousands of developers, from core language designers to casual contributors, are what make Rust such a unique and powerful tool. By picking up this book, you’re not just learning a new programming language—you’re joining a movement to make software better, safer, and more enjoyable to work with. 31 32 Welcome to the Rust community! 33 34 * Bec Rumbul, Executive Director of the Rust Foundation 35 36 - *Introduction* 37 38 #+begin_quote 39 Note: This edition of the book is the same as [[https://nostarch.com/rust-programming-language-3e][The Rust Programming Language]] available in print and ebook format from [[https://nostarch.com][No Starch Press]]. 40 #+end_quote 41 42 Welcome to /The Rust Programming Language/, an introductory book about Rust. The Rust programming language helps you write faster, more reliable software. High-level ergonomics and low-level control are often at odds in programming language design; Rust challenges that conflict. Through balancing powerful technical capacity and a great developer experience, Rust gives you the option to control low-level details (such as memory usage) without all the hassle traditionally associated with such control. 43 44 *Who Rust Is For* 45 46 Rust is ideal for many people for a variety of reasons. Let’s look at a few of the most important groups. 47 48 *Teams of Developers* 49 50 Rust is proving to be a productive tool for collaborating among large teams of developers with varying levels of systems programming knowledge. Low-level code is prone to various subtle bugs, which in most other languages can only be caught through extensive testing and careful code review by experienced developers. In Rust, the compiler plays a gatekeeper role by refusing to compile code with these elusive bugs, including concurrency bugs. By working alongside the compiler, the team can spend its time focusing on the program’s logic rather than chasing down bugs. 51 52 Rust also brings contemporary developer tools to the systems programming world: 53 54 * Cargo, the included dependency manager and build tool, makes adding, compiling, and managing dependencies painless and consistent across the Rust ecosystem. 55 * The =rustfmt= formatting tool ensures a consistent coding style across developers. 56 * The Rust Language Server powers integrated development environment (IDE) integration for code completion and inline error messages. 57 58 By using these and other tools in the Rust ecosystem, developers can be productive while writing systems-level code. 59 60 *Students* 61 62 Rust is for students and those who are interested in learning about systems concepts. Using Rust, many people have learned about topics like operating systems development. The community is very welcoming and happy to answer students’ questions. Through efforts such as this book, the Rust teams want to make systems concepts more accessible to more people, especially those new to programming. 63 64 *Companies* 65 66 Hundreds of companies, large and small, use Rust in production for a variety of tasks, including command line tools, web services, DevOps tooling, embedded devices, audio and video analysis and transcoding, cryptocurrencies, bioinformatics, search engines, Internet of Things applications, machine learning, and even major parts of the Firefox web browser. 67 68 *Open Source Developers* 69 70 Rust is for people who want to build the Rust programming language, community, developer tools, and libraries. We’d love to have you contribute to the Rust language. 71 72 *People Who Value Speed and Stability* 73 74 Rust is for people who crave speed and stability in a language. By speed, we mean both how quickly Rust code can run and the speed at which Rust lets you write programs. The Rust compiler’s checks ensure stability through feature additions and refactoring. This is in contrast to the brittle legacy code in languages without these checks, which developers are often afraid to modify. By striving for zero-cost abstractions—higher-level features that compile to lower-level code as fast as code written manually—Rust endeavors to make safe code be fast code as well. 75 76 The Rust language hopes to support many other users as well; those mentioned here are merely some of the biggest stakeholders. Overall, Rust’s greatest ambition is to eliminate the trade-offs that programmers have accepted for decades by providing safety and productivity, speed and ergonomics. Give Rust a try, and see if its choices work for you. 77 78 *Who This Book Is For* 79 80 This book assumes that you’ve written code in another programming language, but it doesn’t make any assumptions about which one. We’ve tried to make the material broadly accessible to those from a wide variety of programming backgrounds. We don’t spend a lot of time talking about what programming is or how to think about it. If you’re entirely new to programming, you would be better served by reading a book that specifically provides an introduction to programming. 81 82 *How to Use This Book* 83 84 In general, this book assumes that you’re reading it in sequence from front to back. Later chapters build on concepts in earlier chapters, and earlier chapters might not delve into details on a particular topic but will revisit the topic in a later chapter. 85 86 You’ll find two kinds of chapters in this book: concept chapters and project chapters. In concept chapters, you’ll learn about an aspect of Rust. In project chapters, we’ll build small programs together, applying what you’ve learned so far. Chapter 2, Chapter 12, and Chapter 21 are project chapters; the rest are concept chapters. 87 88 [[*Getting Started][Chapter 1]] explains how to install Rust, how to write a “Hello, world!” program, and how to use Cargo, Rust’s package manager and build tool. [[*Programming a Guessing Game][Chapter 2]] is a hands-on introduction to writing a program in Rust, having you build up a number-guessing game. Here, we cover concepts at a high level, and later chapters will provide additional detail. If you want to get your hands dirty right away, Chapter 2 is the place for that. If you’re a particularly meticulous learner who prefers to learn every detail before moving on to the next, you might want to skip Chapter 2 and go straight to [[* Common Programming Concepts][Chapter 3]], which covers Rust features that are similar to those of other programming languages; then, you can return to Chapter 2 when you’d like to work on a project applying the details you’ve learned. 89 90 In [[* Understanding Ownership][Chapter 4]], you’ll learn about Rust’s ownership system. [[*Using Structs to Structure Related Data][Chapter 5]] discusses structs and methods. [[*Enums and Pattern Matching][Chapter 6]] covers enums, =match= expressions, and the =if let= and =let...else= control flow constructs. You’ll use structs and enums to make custom types. 91 92 In [[Packages, Crates, and Modules][Chapter 7]], you’ll learn about Rust’s module system and about privacy rules for organizing your code and its public application programming interface (API). [[*Common Collections][Chapter 8]] discusses some common collection data structures that the standard library provides: vectors, strings, and hash maps. [[*Error Handling][Chapter 9]] explores Rust’s error-handling philosophy and techniques. 93 94 [[Generic Types, Traits, and Lifetimes][Chapter 10]] digs into generics, traits, and lifetimes, which give you the power to define code that applies to multiple types. [[*Writing Automated Tests][Chapter 11]] is all about testing, which even with Rust’s safety guarantees is necessary to ensure that your program’s logic is correct. In [[*An I/O Project: Building a Command Line Program][Chapter 12]], we’ll build our own implementation of a subset of functionality from the grep command line tool that searches for text within files. For this, we’ll use many of the concepts we discussed in the previous chapters. 95 96 [[*Functional Language Features: Iterators and Closures][Chapter 13]] explores closures and iterators: features of Rust that come from functional programming languages. In [[*More about Cargo and Crates.io][Chapter 14]], we’ll examine Cargo in more depth and talk about best practices for sharing your libraries with others. [[*Smart Pointers][Chapter 15]] discusses smart pointers that the standard library provides and the traits that enable their functionality. 97 98 In [[*Fearless Concurrency][Chapter 16]], we’ll walk through different models of concurrent programming and talk about how Rust helps you program in multiple threads fearlessly. In [[*Fundamentals of Asynchronous Programming: Async, Await, Futures, and Streams][Chapter 17]], we build on that by exploring Rust’s async and await syntax, along with tasks, futures, and streams, and the lightweight concurrency model they enable. 99 100 [[*Object Oriented Programming Features][Chapter 18]] looks at how Rust idioms compare to object-oriented programming principles you might be familiar with. [[*Patterns and Matching][Chapter 19]] is a reference on patterns and pattern matching, which are powerful ways of expressing ideas throughout Rust programs. [[*Advanced Features][Chapter 20]] contains a smorgasbord of advanced topics of interest, including unsafe Rust, macros, and more about lifetimes, traits, types, functions, and closures. 101 102 In [[Final Project: Building a Multithreaded Web Server][Chapter 21]], we’ll complete a project in which we’ll implement a low-level multithreaded web server! 103 104 Finally, some appendixes contain useful information about the language in a more reference-like format. [[*A - Keywords][Appendix A]] covers Rust’s keywords, [[*B - Operators and Symbols][Appendix B]] covers Rust’s operators and symbols, [[*C - Derivable Traits][Appendix C]] covers derivable traits provided by the standard library, [[*Useful Development Tools][Appendix D]] covers some useful development tools, and [[*E - Editions][Appendix E]] explains Rust editions. In [[*F - Translations of the Book][Appendix F]], you can find translations of the book, and in [[*G - How Rust is Made and "Nightly Rust"][Appendix G]] we’ll cover how Rust is made and what nightly Rust is. 105 106 There is no wrong way to read this book: If you want to skip ahead, go for it! You might have to jump back to earlier chapters if you experience any confusion. But do whatever works for you. 107 108 109 An important part of the process of learning Rust is learning how to read the error messages the compiler displays: These will guide you toward working code. As such, we’ll provide many examples that don’t compile along with the error message the compiler will show you in each situation. Know that if you enter and run a random example, it may not compile! Make sure you read the surrounding text to see whether the example you’re trying to run is meant to error. In most situations, we’ll lead you to the correct version of any code that doesn’t compile. Ferris will also help you distinguish code that isn’t meant to work: 110 111 | *Ferris* | *Meaning* | 112 |--------+--------------------------------------------------| 113 | | This code does not compile! | 114 | | This code panics! | 115 | | This code does not produce the desired behavior. | 116 117 *Source Code* 118 119 The source files from which this book is generated can be found on [[https://github.com/rust-lang/book/tree/main/src][GitHub]]. 120 121 * Getting Started 122 123 Let’s start your Rust journey! There’s a lot to learn, but every journey starts somewhere. In this chapter, we’ll discuss: 124 125 * Installing Rust on Linux, macOS, and Windows 126 * Writing a program that prints =Hello, world!= 127 * Using =cargo=, Rust’s package manager and build system 128 129 ** Installation 130 ** Hello, World! 131 ** Hello, Cargo! 132 133 * Programming a Guessing Game 134 135 #+BEGIN_SRC toml 136 [package] 137 name = "guessing_game" 138 version = "0.1.0" 139 edition = "2024" 140 # edition.workspace = true 141 142 [dependencies] 143 rand = "0.9.0" 144 145 [workspace] 146 #+END_SRC 147 148 #+BEGIN_SRC rust 149 use std::cmp::Ordering; 150 use std::io; 151 use rand::Rng; 152 153 fn main() { 154 println!("Guess the number!"); 155 156 let secret_number = 157 rand::thread_rng().gen_range(1..=100); 158 159 // println!("The secret number is: {secret_number}"); 160 161 loop { 162 println!("Please input your guess."); 163 164 let mut guess = String::new(); 165 166 io::stdin() 167 .read_line(&mut guess) 168 .expect("Failed to read line"); 169 170 let guess: u32 = match guess 171 .trim() 172 .parse(){ 173 Ok(num) => num, 174 Err(_) => continue 175 }; 176 177 println!("You guessed: {guess}"); 178 179 match guess.cmp(&secret_number){ 180 Ordering::Less => println!("Too small!"), 181 Ordering::Greater => println!("Too big!"), 182 Ordering::Equal => { 183 println!("You win!"); 184 break; 185 } 186 } 187 } 188 } 189 #+END_SRC 190 * Common Programming Concepts 191 ** Variables and Mutability 192 193 #+BEGIN_SRC rust 194 use std::io; 195 196 #[allow(unused)] 197 fn main() { 198 let x = 5; 199 200 let x = x + 1; 201 202 { 203 let x = x * 2; 204 println!("The value of x in the inner scope is: {x}"); 205 } 206 207 println!("The value of x is: {x}"); 208 209 let spaces = " "; 210 let spaces = spaces.len(); 211 println!("Length of spaces is: {spaces}"); 212 213 let guess: u32 = "42".parse().expect("Not a number!"); 214 215 let x = 2.0; // f64 216 let y: f32 = 3.0; // f32 217 218 // addition 219 let sum = 5 + 10; 220 221 // subtraction 222 let difference = 95.5 - 4.3; 223 224 // multiplication 225 let product = 4 * 30; 226 227 // division 228 let quotient = 56.7 / 32.2; 229 let truncated = -5 / 3; // Results in -1 230 231 // remainder 232 let remainder = 43 % 5; 233 234 let t = true; 235 let f: bool = false; // with explicit type annotation 236 237 let c = 'z'; 238 let z: char = 'Z'; // with explicit type annotation 239 let heart_eyed_cat = '😻'; 240 241 let tup: (i32, f64, u8) = (500, 6.4, 1); 242 println!("{:?}", tup); 243 244 let tup = (500, 6.4, 1); 245 246 let (x, y, z) = tup; 247 248 println!("The value of y is: {y}"); 249 250 let x: (i32, f64, u8) = (500, 6.4, 1); 251 252 let five_hundred = x.0; 253 254 let six_point_four = x.1; 255 256 let one = x.2; 257 258 let a = [1, 2, 3, 4, 5]; 259 260 let months = [ 261 "January", 262 "February", 263 "March", 264 "April", 265 "May", 266 "June", 267 "July", 268 "August", 269 "September", 270 "October", 271 "November", 272 "December", 273 ]; 274 275 let a: [i32; 5] = [1, 2, 3, 4, 5]; 276 277 let a = [3; 5]; // 3, 3, 3, 3, 3 278 279 let first = a[0]; 280 let second = a[1]; 281 282 // invalid array element access 283 let a = [1, 2, 3, 4, 5]; 284 285 println!("Please enter an array index."); 286 287 let mut index = String::new(); 288 289 io::stdin() 290 .read_line(&mut index) 291 .expect("Failed to read line"); 292 293 let index: usize = index 294 .trim() 295 .parse() 296 .expect("Index entered was not a number"); 297 298 let element = a[index]; 299 300 println!("The value of the element at index {index} is: {element}"); 301 #+END_SRC 302 303 ** Functions 304 305 #+BEGIN_SRC rust 306 fn main() { 307 println!("Hello, world!"); 308 309 another_function(); 310 print_labeled_measurement(5, 'h'); 311 an_expression(); 312 // statement_to_another_variable_wont_compile(); 313 statement_to_expression(); 314 315 let x = five(); 316 317 println!("The value of x is: {x}"); 318 319 let x = plus_one(5); 320 321 println!("The value of x is: {x}"); 322 } 323 324 fn another_function() { 325 println!("Another function."); 326 } 327 328 fn print_labeled_measurement(value: i32, unit_label: char) { 329 println!("The measurement is: {value}{unit_label}") 330 } 331 332 fn an_expression() { 333 let y = 6; 334 } 335 336 // fn statement_to_another_variable_wont_compile(){ 337 // let x = (let y =6); 338 // } 339 340 fn statement_to_expression() { 341 let y = { 342 let x = 3; 343 x + 1 344 // expressions don't include ending semicolons 345 // adding a semicolor to the end of an expression turns it into a statement, which will not return a value 346 }; 347 348 println!("The value of y is: {y}") 349 } 350 351 fn five() -> i32 { 352 5 353 } 354 355 fn plus_one(x: i32) -> i32 { 356 x + 1 357 } 358 #+END_SRC 359 360 ** Comments 361 362 #+BEGIN_SRC rust 363 #![allow(unused)] 364 fn main() { 365 // hello, world 366 367 // So we're doing something complicated here, long enough that we need 368 // multiple lines of comments to do it! Whew! Hopefully, this comment will 369 // explain what's going on. 370 371 let lucky_number = 7; // I'm feeling lucky today 372 373 // I'm feeling lucky today 374 let another_lucky_number = 7; 375 } 376 #+END_SRC 377 378 ** Control Flow 379 380 #+BEGIN_SRC rust 381 fn if_expressions() { 382 let number = 3; 383 384 if number < 5 { 385 println!("condition was true"); 386 } else { 387 println!("condition was false"); 388 } 389 390 let number = 7; 391 392 if number < 5 { 393 println!("condition was true"); 394 } else { 395 println!("condition was false"); 396 } 397 398 let number = 3; 399 if number != 0 { 400 println!("number was something other than zero"); 401 } 402 } 403 404 fn handling_multiple_conditions_with_else_if() { 405 let number = 6; 406 407 if number % 4 == 0 { 408 println!("number is divisible by 4"); 409 } else if number % 3 == 0 { 410 println!("number is divisible by 3"); 411 } else if number % 2 == 0 { 412 println!("number is divisible by 2"); 413 } else { 414 println!("number is not divisible by 4, 3, or 2"); 415 } 416 } 417 418 fn using_if_in_a_let_statement() { 419 let condition = true; 420 let number = if condition { 5 } else { 6 }; 421 422 println!("The value of number is: {number}"); 423 } 424 425 fn repetition_with_loops() { 426 loop { 427 println!("again!"); 428 } 429 } 430 431 fn returning_values_from_loops() { 432 let mut counter = 0; 433 434 let result = loop { 435 counter += 1; 436 437 if counter == 10 { 438 break counter * 2; 439 } 440 }; 441 442 println!("The result is {result}") 443 } 444 445 fn loop_labels_to_disambiguate_between_multiple_loops() { 446 let mut count = 0; 447 448 'counting_up: loop { 449 println!("count = {count}"); 450 let mut remaining = 10; 451 452 loop { 453 println!("remaining = {remaining}"); 454 if remaining == 9 { 455 break; 456 } 457 if count == 2 { 458 break 'counting_up; 459 } 460 remaining -= 1; 461 } 462 count += 1; 463 } 464 println!("End count = {count}"); 465 } 466 467 fn conditional_loops_with_while() { 468 let mut number = 3; 469 470 while number != 0 { 471 println!("{number}!"); 472 number -= 1; 473 } 474 475 println!("LIFTOFF!!!"); 476 } 477 478 fn looping_through_a_collection_with_for() { 479 let a = [10, 20, 30, 40, 50]; 480 let mut index = 0; 481 482 while index < 5 { 483 println!("the value is: {}", a[index]); 484 485 index += 1; 486 } 487 488 // more concise with for loop 489 for element in a { 490 println!("the value is: {element}"); 491 } 492 } 493 494 fn convert_temperature_between_fahrenheit_and_celcius() { 495 loop { 496 println!("Enter any number."); 497 let mut number = String::new(); 498 499 std::io::stdin() 500 .read_line(&mut number) 501 .expect("Failed to read line"); 502 503 let number: u32 = match number.trim().parse() { 504 Ok(num) => num, 505 Err(_) => continue, 506 }; 507 508 let celcius = (number - 32) / (9 / 5); 509 let fahrenheit = (celcius * (9 / 5)) + 32; 510 511 println!("{number}°F -> {celcius}°C"); 512 println!("{number}°C -> {fahrenheit}°F"); 513 break; 514 } 515 } 516 517 fn generate_nth_fibonacci_number() { 518 loop { 519 println!("Enter any number for n."); 520 let mut number = String::new(); 521 522 std::io::stdin() 523 .read_line(&mut number) 524 .expect("Failed to read line"); 525 526 let number: u32 = match number.trim().parse() { 527 Ok(num) => num, 528 Err(_) => continue, 529 }; 530 531 match number.cmp(&1) { 532 std::cmp::Ordering::Less => println!("0"), 533 std::cmp::Ordering::Equal => println!("1"), 534 std::cmp::Ordering::Greater => { 535 println!("Fn = Fn-1 + Fn+2 for n>1"); 536 println!("Example: 0,1,1,2,3,5,8,13,21"); 537 } 538 } 539 break; 540 } 541 } 542 543 fn main() { 544 // if_expressions(); 545 // handling_multiple_conditions_with_else_if(); 546 // using_if_in_a_let_statement(); 547 // repetition_with_loops(); 548 // returning_values_from_loops(); 549 // loop_labels_to_disambiguate_between_multiple_loops(); 550 // conditional_loops_with_while(); 551 // looping_through_a_collection_with_for(); 552 convert_temperature_between_fahrenheit_and_celcius(); 553 generate_nth_fibonacci_number(); 554 } 555 #+END_SRC 556 557 * Understanding Ownership 558 ** What is Ownership? 559 560 #+BEGIN_SRC rust 561 fn variables_and_data_interacting_with_move() { 562 // let x = 5; 563 // let y = x; 564 565 let s1 = String::from("hello"); 566 let s2 = s1.clone(); 567 568 println!("s1 = {s1}, s2 = {s2}"); 569 println!("{s1}, world!"); 570 } 571 572 fn stack_only_data_copy() { 573 let x = 5; 574 let y = x; 575 576 println!("x = {x}, y = {y}"); 577 } 578 579 fn ownership_and_functions() { 580 let s = String::from("hello"); // s comes into scope 581 takes_ownership(s); // s's value moves into the function... 582 // ... and so is no longer valid here 583 let x = 5; // x comes into scope 584 makes_copy(x); // Because i32 implements the Copy trait, 585 // x does NOT move into the function, 586 // so it's okay to use x afterward. 587 } // Here, x goes out of scope, then s. However, because s's value was moved, 588 // nothing special happens. 589 590 fn takes_ownership(some_string: String) { 591 // some_string comes into scope 592 println!("{some_string}"); 593 } // Here, some_string goes out of scope and `drop` is called. The backing 594 // memory is freed. 595 596 fn makes_copy(some_integer: i32) { 597 // some_integer comes into scope 598 println!("{some_integer}") 599 } // Here, some_integer goes out of scope. Nothing special happens. 600 601 fn return_values_and_scope() { 602 let s1 = gives_ownership(); // gives_ownership moves its return value into s1 603 let s2 = String::from("hello"); // s2 comes into scope 604 let s3 = takes_and_gives_back(s2); // s2 is moved into takes_and_gives_back, which also moves its return value into s3 605 } // Here, s3 goes out of scope and is dropped. s2 ws moved, so nothing happens. s1 goes out of scope and is dropped. 606 607 fn gives_ownership() -> String { 608 // gives_ownership will move its return value into the function that calls it 609 let some_string = String::from("yours"); //some_string comes into scope 610 some_string // some_string is returned and moves out to the calling function 611 } 612 613 // This function takes a String and returns a String. 614 fn takes_and_gives_back(a_string: String) -> String { 615 // a_string comes into scope 616 a_string // a_string is returned and moves out to the calling function 617 } 618 619 fn return_multiple_values_using_a_tuple() { 620 let s1 = String::from("hello"); 621 let (s2, len) = calculate_length(s1); 622 println!("The length of '{s2}' is {len}.") 623 } 624 625 fn calculate_length(s: String) -> (String, usize) { 626 let length = s.len(); // len() returns the length of a String 627 (s, length) 628 } 629 630 fn main() { 631 // let s = "hello"; 632 // let mut s = String::from("hello"); 633 // s.push_str(", world!"); 634 // println!("{s}"); 635 // variables_and_data_interacting_with_move(); 636 return_values_and_scope(); 637 return_multiple_values_using_a_tuple(); 638 } 639 #+END_SRC 640 641 ** References and Borrowing 642 643 BEGIN_SRC rust 644 calculate_length(s: &String) -> usize { 645 // s is a reference to a String 646 s.len() 647 // Here, s goes out of scope. But because s does not have ownership of what it refers to, the String is not dropped. 648 649 fn borrowing_without_returning(){ 650 let s = String::from("hello"); 651 change(&s); 652 } 653 654 fn change(some_string: &String){ 655 some_string.push_str(", world"); 656 } 657 658 mutable_references() { 659 let mut s = String::from("hello"); 660 { 661 let r1 = &mut s; 662 } // r1 goes out of scope here, so we can make a new reference with no problems. 663 let r2 = &mut s; 664 665 let r1 = &s; // no problem 666 let r2 = &s; // no problem 667 // let r3 = &mut s; // BIG PROBLEM 668 669 // println!("{r1}, {r2}, and {r3}"); 670 671 672 reference_scope() { 673 let mut s = String::from("hello"); 674 let r1 = &s; // no problem 675 let r2 = &s; // no problem 676 println!("{r1} and {r2}"); 677 // Variables r1 and r2 will not be used after this point. 678 679 let r3 = &mut s; // no problem 680 println!("{r3}"); 681 682 683 dangling_references() { 684 // let reference_to_string = dangle(); 685 let reference_to_string = no_dangle(); 686 687 688 fn dangle() -> &String { // dangle returns a reference to a String 689 let s = String::from("hello"); // s is a new String 690 &s // we return a reference to the String, s 691 } // Here, s goes out of scope and is dropped, so its memory goes away. 692 // Danger! 693 694 no_dangle() -> String { 695 let s = String::from("hello"); 696 s 697 698 699 main() { 700 let s1 = String::from("hello"); 701 let len = calculate_length(&s1); 702 println!("The length of '{s1}' is {len}."); 703 704 // borrowing_without_returning(); 705 mutable_references(); 706 reference_scope(); 707 708 END_SRC 709 710 ** The Slice Type 711 712 #+BEGIN_SRC rust 713 fn main() { 714 let mut s = String::from("hello world"); 715 let word = first_word(&s); 716 // s.clear(); // error 717 println!("the first word is: {word}"); 718 719 let my_string = String::from("hello world"); 720 721 // `first_word` works on slices of `String`s, whether partial or whole. 722 let word = first_word(&my_string[0..6]); 723 let word = first_word(&my_string[..]); 724 // `first_word` also works on references to `String`s, which are equivalent 725 // to whole slices of `String`s 726 let word = first_word(&my_string); 727 728 let my_string_literal = "hello world"; 729 730 // `first_word` works on slices of string literals, whether partial or whole. 731 let word = first_word(&my_string_literal[0..6]); 732 let word = first_word(&my_string_literal[..]); 733 734 // Because string literals *are* string slices already, 735 // this works too, without the slice syntax! 736 let word = first_word(my_string_literal); 737 738 let a = [1, 2, 3, 4, 5]; 739 740 let slice = &a[1..3]; 741 assert_eq!(slice, &[2, 3]); 742 } 743 744 fn first_word(s: &str) -> &str { 745 let bytes = s.as_bytes(); 746 747 for (i, &item) in bytes.iter().enumerate() { 748 if item == b' ' { 749 return &s[0..i]; 750 } 751 } 752 753 &s[..] 754 } 755 #+END_SRC 756 757 * Using Structs to Structure Related Data 758 ** Defining and Instantiating Structs 759 760 #+BEGIN_SRC rust 761 struct User { 762 active: bool, 763 username: String, 764 email: String, 765 sign_in_count: u64, 766 } 767 768 fn build_user(email: String, username: String) -> User { 769 User { 770 active: true, 771 username, 772 email, 773 sign_in_count: 1, 774 } 775 } 776 777 fn creating_different_types_with_tuple_structs() { 778 struct Color(i32, i32, i32); 779 struct Point(i32, i32, i32); 780 781 let black = Color(0, 0, 0); 782 let origin = Point(0, 0, 0); 783 } 784 785 fn defining_unit_like_structs() { 786 struct AlwaysEqual; 787 788 let subject = AlwaysEqual; 789 } 790 791 fn main() { 792 let mut user1 = User { 793 active: true, 794 username: String::from("someusername123"), 795 email: String::from("someone@example.com"), 796 sign_in_count: 1, 797 }; 798 799 user1.email = String::from("anotheremail@example.com"); 800 801 // let user2 = User { 802 // active: user1.active, 803 // username: user1.username, 804 // email: String::from("another@example.com"), 805 // sign_in_count: user1.sign_in_count, 806 // }; 807 808 let user2 = User { 809 email: String::from("another@example.com"), 810 ..user1 811 }; 812 813 creating_different_types_with_tuple_structs(); 814 defining_unit_like_structs(); 815 } 816 #+END_SRC 817 818 ** An Example Program Using Structs 819 820 #+BEGIN_SRC rust 821 fn area(width: u32, height: u32) -> u32 { 822 width * height 823 } 824 825 fn refactoring_with_tuples() { 826 fn area(dimensions: (u32, u32)) -> u32 { 827 dimensions.0 * dimensions.1 828 } 829 830 let rect1 = (30, 50); 831 832 println!( 833 "The area of the rectangle is {} square pixels.", 834 area(rect1) 835 ) 836 } 837 838 fn refactoring_with_structs() { 839 struct Rectangle { 840 width: u32, 841 height: u32, 842 } 843 844 fn area(rectangle: &Rectangle) -> u32 { 845 rectangle.width * rectangle.height 846 } 847 848 let rect1 = Rectangle { 849 width: 30, 850 height: 50, 851 }; 852 853 println!( 854 "The area of the rectangle is {} square pixels.", 855 area(&rect1) 856 ) 857 } 858 859 fn adding_functionality_with_derived_traits() { 860 #[derive(Debug)] 861 struct Rectangle { 862 width: u32, 863 height: u32, 864 } 865 866 let rect1 = Rectangle { 867 width: 30, 868 height: 50, 869 }; 870 871 println!("rect1 is {rect1:?}"); 872 println!("rect1 is {rect1:#?}"); 873 874 let scale = 2; 875 let rect1 = Rectangle { 876 width: dbg!(30 * scale), 877 height: 50, 878 }; 879 880 dbg!(&rect1); 881 } 882 883 fn main() { 884 let width1 = 30; 885 let height1 = 50; 886 887 println!( 888 "The area of the rectangle is {} square pixels.", 889 area(width1, height1) 890 ); 891 892 refactoring_with_tuples(); 893 refactoring_with_structs(); 894 adding_functionality_with_derived_traits(); 895 } 896 #+END_SRC 897 898 ** Methods 899 900 Methods are similar to functions: We declare them with the =fn= keyword and a name, they can have parameters and a return value, and they contain some code that's run whe the method is called from somewhere else. Unlike functions, methods are defined within the context of a struct (or an enum or a trait object, which we cover in Chapter 6 and Chapter 18, respectively), and their first parameter is always =self=, which represents the instance of the struct the method is being called on. 901 902 *** Method Syntax 903 904 Let's change the =area= function that has a =Rectangle= instance as a parameter and instead make an =area= method defined on the =Rectangle= struct, as shown in Listing 5-13. 905 906 #+BEGIN_SRC rust 907 #[derive(Debug)] 908 struct Rectangle { 909 width: u32, 910 height: u32 911 } 912 913 impl Rectangle { 914 fn area(&self) -> u32 { 915 self.width * self.height 916 } 917 } 918 919 fn main() { 920 let rect1 = Rectangle { 921 width: 30, 922 height: 50 923 }; 924 925 println!( 926 "The area of the rectangle is {} square pixels.", 927 rect1.area() 928 ); 929 } 930 #+END_SRC 931 Listing 5-13: Defining an =area= method on the =Rectangle= struct 932 933 To define the function within the context of =Rectangle=, we start an =impl= (implementation) block for =Rectangle=. Everything within this =impl= block will be associated with the =Rectangle= type. kthen, we move the =area= function within the =impl= curly brackets and change the first (and in this case, only) parameter to be =self= in the signature and everywhere within the body. In =main=, where we called the =area= function and passed =rect1= as an argument, we can instead use /method syntax/ to call the =area= method on our =Rectangle= instance. The method syntax goes after an instance: We add a dot followed by the method name, parentheses, and any arguments. 934 935 In the signature for =area=, we use =&self= instead of =rectangle: &Rectangle=. the =&self= is actually showrt for =self: &Self=. Within an =impl= block, the type =Self= is an alias for the type that the =impl= block is for. Methods must have a parameter named =self= of type =Self= for their first parameter, so Rust lets you abbreviate this with only the name =self= in the first parameter spot. Note that we still need to use the =&= in front of the =self= shorthand to indicate that this method borrows the =Self= instance, just as we did in =rectangle: &Rectangle=. Methods can take ownership of =self=, borrow =self= immutably, as we've done here, or borrow =self= mutably, just as they can any other parameter. 936 937 #+BEGIN_SRC rust 938 #[derive(Debug)] 939 struct Rectangle { 940 width: u32, 941 height: u32 942 } 943 944 impl Rectangle { 945 fn width(&self) -> bool{ 946 self.width > 0 947 } 948 } 949 950 fn main() { 951 let rect1 = Rectangle { 952 width: 30, 953 height: 50 954 }; 955 956 if rect1.width() { 957 println!("The rectangle has a nonzero width; it is {}", rect1.width); 958 } 959 } 960 #+END_SRC 961 962 *** Methods with More Parameters 963 964 Let's practice using methods by implementing a second method on the =Rectangle= struct. This time we want an instance of =Rectangle= to take another instance of =Rectangle= and return =true= if the second =Rectangle= can fit completely within =self= (the first =Rectangle=); otherwise, it should return =false=. That is, once we've defined the =can_hold= method, we want to be able to write the program shown in Listing 5-14. 965 966 #+BEGIN_SRC rust 967 #[derive(Debug)] 968 struct Rectangle { 969 width: u32, 970 height: u32 971 } 972 973 impl Rectangle { 974 fn area(&self) -> u32{ 975 self.width * self.height 976 } 977 978 fn can_hold(&self, other: &Rectangle) -> bool { 979 self.width > other.width && self.height > other.height 980 } 981 } 982 983 fn main(){ 984 let rect1 = Rectangle { 985 width: 30, 986 height: 50 987 }; 988 989 let rect2 = Rectangle { 990 width: 10, 991 height: 40 992 }; 993 994 let rect3 = Rectangle { 995 width: 60, 996 height: 45 997 }; 998 999 println!("Can rect1 hold rect2? {}", rect1.can_hold(&rect2)); 1000 println!("Can rect1 hold rect3? {}", rect1.can_hold(&rect3)); 1001 } 1002 #+END_SRC 1003 1004 *** Associated Functions 1005 1006 All functions defined within an =impl= block are called /associated functions/ because they're associated with the type named after the =impl=. We can define associated functions that don't have =self= as their first parameter (and thus are not methods) because they don't need an instance of the type to work with. We've already used one function like this: the =String::from= function that's defined on the =String= type. 1007 1008 Associated functions that aren't methods are often used for constructors that will return a new instance of the struct. These are often called =new=, but =new= isn't a special name and isn't built into the language. For example, we could choose to provide an associated function named =square= that would have one dimension parameter and use that as both width and height, thus making it easier to create a square =Rectangle= rather than having to specify the same value twice: 1009 1010 #+BEGIN_SRC rust 1011 impl Rectangle { 1012 fn square(size: u32) -> Self { 1013 Self { 1014 width: size, 1015 height: size 1016 } 1017 } 1018 } 1019 #+END_SRC 1020 1021 The =Self= keywords in the return type and in the body of the function are aliases for the type that appears after the =impl= keyword, which in this case is =Rectangle=. 1022 1023 To call this associated function, we use the =::= syntax with the struct name; =let sq = Rectangle::square(3);= is an example. This function is namespaced by the struct: The =::= syntax is used for both associated functions and namespaces created by modules. We'll discuss modules in Chapter 7. 1024 1025 *** Multiple impl Blocks 1026 1027 Each struct is allowed to have multiple =impl= blocks. For example, Listing 5-15 is equivalent to the code shown in Listing 5-16, which has each method in its own =impl= block. 1028 1029 #+BEGIN_SRC rust 1030 impl Rectangle { 1031 fn area(&self) -> u32 { 1032 self.width * self.height 1033 } 1034 } 1035 1036 impl Rectangle { 1037 fn can_hold(&self, other: &Rectangle) -> bool { 1038 self.width > other.width && self.height > other.height 1039 } 1040 } 1041 #+END_SRC 1042 Listing 5-16: Rewriting Listing 5-15 using multiple =impl= blocks 1043 1044 There's no reason to separate these methods into multiple =impl= blocks here, but this is valid syntax. We'll see a case in which multiple =impl= blocks are useful in Chapter 10, where we discuss generic types and traits. 1045 1046 *** Summary 1047 1048 Structs let you create custom types that are meaningful for your domain. By using structs, you can keep associated pieces of data connected to each other and nae each piece to make your code clear. In =impl= blocks, you can define functions that are associated with your type, and methods are a kind of associated function that let you specify the behavior that instances of your structs have. 1049 1050 But structs aren't the only way you can create custom types: Let's turn to Rust's enum feature to add another tool to your toolbox. 1051 1052 1053 * Enums and Pattern Matching 1054 In this chapter, we'll look at enumerations, also referred to as /enums/. Enums allow you to define a type by enumerating its possible variants. First we'll define and use an enum to show how an enum can encode meaning along with data. Next, we'll explore a particularly useful enum, called =Option=, which expresses that a value can be either something or nothing. Then, we'll look at how pattern matching in the =match= expression makes it easy to run different code for different values of an enum. Finally, we'll cover how the =if let= construct is another convenient and concise idiom available to handle enums in your code. 1055 1056 ** Defining an Enum 1057 1058 Where structs give you a way of grouping together related fields and data, like a =Rectangle= with its =width= and =height=, enums give you a way of saying a value is one of a possible set of values. For example, we may want to say that =Rectangle= is one of a set of possible shapes that also includes =Circle= and =Triangle=. To do this, Rust allows us to encode these possibilities as an enum. 1059 1060 Let’s look at a situation we might want to express in code and see why enums are useful and more appropriate than structs in this case. Say we need to work with IP addresses. Currently, two major standards are used for IP addresses: version four and version six. Because these are the only possibilities for an IP address that our program will come across, we can enumerate all possible variants, which is where enumeration gets its name. 1061 1062 Any IP address can be either a version four or a version six address, but not both at the same time. That property of IP addresses makes the enum data structure appropriate because an enum value can only be one of its variants. Both version four and version six addresses are still fundamentally IP addresses, so they should be treated as the same type when the code is handling situations that apply to any kind of IP address. 1063 1064 We can express this concept in code by defining an =IpAddrKind= enumeration and listing the possible kinds an IP address can be, =V4= and =V6=. These are the variants of the enum: 1065 1066 #+BEGIN_SRC rust 1067 enum IpAddrKind { 1068 V4, 1069 V6 1070 } 1071 #+END_SRC 1072 1073 =IpAddrKind= is now a custom data type that we can use elsewhere in our code. 1074 1075 *** Enum Values 1076 1077 We can create instances of each of the two variants of =IpAddrKind= like this: 1078 1079 #+BEGIN_SRC rust 1080 let four = IpAddrKind::V4; 1081 let six = IpAddrKind::V6; 1082 #+END_SRC 1083 1084 *** The /Option/ Enum 1085 1086 This section explores a case study of =Option=, which is another enum defined by the standard library. The =Option= type encodes the very common scenario in which a value could be something, or it could be nothing. 1087 1088 For example, if you request the first item in a non-empty list, you would get a value. If you request the first item in an empty list, you would get nothing. Expressing this concept in terms of the type system means the compiler can check whether you’ve handled all the cases you should be handling; this functionality can prevent bugs that are extremely common in other programming languages. 1089 1090 Programming language design is often thought of in terms of which features you include, but the features you exclude are important too. Rust doesn’t have the null feature that many other languages have. Null is a value that means there is no value there. In languages with null, variables can always be in one of two states: null or not-null. 1091 1092 In his 2009 presentation “Null References: The Billion Dollar Mistake,” Tony Hoare, the inventor of null, had this to say: 1093 1094 #+begin_quote 1095 I call it my billion-dollar mistake. At that time, I was designing the first comprehensive type system for references in an object-oriented language. My goal was to ensure that all use of references should be absolutely safe, with checking performed automatically by the compiler. But I couldn’t resist the temptation to put in a null reference, simply because it was so easy to implement. This has led to innumerable errors, vulnerabilities, and system crashes, which have probably caused a billion dollars of pain and damage in the last forty years. 1096 #+end_quote 1097 1098 The problem with null values is that if you try to use a null value as a not-null value, you’ll get an error of some kind. Because this null or not-null property is pervasive, it’s extremely easy to make this kind of error. 1099 1100 However, the concept that null is trying to express is still a useful one: A null is a value that is currently invalid or absent for some reason. 1101 1102 The problem isn’t really with the concept but with the particular implementation. As such, Rust does not have nulls, but it does have an enum that can encode the concept of a value being present or absent. This enum is =Option<T>=, and it is defined by the standard library as follows: 1103 1104 #+BEGIN_SRC rust 1105 enum Option<T> { 1106 None, 1107 Some(T) 1108 } 1109 #+END_SRC 1110 1111 ** The match Control Flow Construct 1112 Rust has an extremely powerful control flow construct called =match= that allows you to compare a value against a series of patterns and then execute code based on which pattern matches. Patterns can be made up of literal values, variable names, wildcards, and many other things; Chapter 19 covers all the different kinds of patterns and what they do. The power of =match= comes from the expressiveness of the patterns and the fact that the compiler confirms that all possible cases are handled. 1113 1114 Think of a =match= expression as being like a coin-sorting machine: Coins slide down a track with variously sized holes along it, and each coin falls through the first hole it encounters that it fits into. In the same way, values go through each pattern in a =match=, and at the first pattern the value “fits,” the value falls into the associated code block to be used during execution. 1115 1116 Speaking of coins, let’s use them as an example using =match=! We can write a function that takes an unknown US coin and, in a similar way as the counting machine, determines which coin it is and returns its value in cents, as shown in Listing 6-3. 1117 1118 #+BEGIN_SRC rust 1119 enum Coin { 1120 Penny, 1121 Nickel, 1122 Dime, 1123 Quarter 1124 } 1125 1126 fn value_in_cents(coin: Coin) -> u8{ 1127 match coin { 1128 Coin::Penny => 1, 1129 Coin::Nickel => 5, 1130 Coin::Dime => 10, 1131 Coin::Quarter => 25, 1132 } 1133 } 1134 #+END_SRC 1135 Listing 6-3: An enum and a =match= expression that has the variants of the enum as its patterns 1136 1137 Let’s break down the =match= in the =value_in_cents= function. First, we list the =match= keyword followed by an expression, which in this case is the value =coin=. This seems very similar to a conditional expression used with =if=, but there’s a big difference: With =if=, the condition needs to evaluate to a Boolean value, but here it can be any type. The type of =coin= in this example is the =Coin= enum that we defined on the first line. 1138 1139 Next are the =match= arms. An arm has two parts: a pattern and some code. The first arm here has a pattern that is the value =Coin::Penny= and then the ==>= operator that separates the pattern and the code to run. The code in this case is just the value =1=. Each arm is separated from the next with a comma. 1140 1141 When the =match= expression executes, it compares the resultant value against the pattern of each arm, in order. If a pattern matches the value, the code associated with that pattern is executed. If that pattern doesn’t match the value, execution continues to the next arm, much as in a coin-sorting machine. We can have as many arms as we need: In Listing 6-3, our match has four arms. 1142 1143 The code associated with each arm is an expression, and the resultant value of the expression in the matching arm is the value that gets returned for the entire =match= expression. 1144 1145 We don’t typically use curly brackets if the match arm code is short, as it is in Listing 6-3 where each arm just returns a value. If you want to run multiple lines of code in a match arm, you must use curly brackets, and the comma following the arm is then optional. For example, the following code prints “Lucky penny!” every time the method is called with a =Coin::Penny=, but it still returns the last value of the block, =1=: 1146 1147 #+BEGIN_SRC rust 1148 fn value_in_cents(coin: Coin) -> u8 { 1149 match coin { 1150 Coin::Penny => { 1151 println!("Lucky penny!"); 1152 1 1153 } 1154 Coin::Nickel => 5, 1155 Coin::Dime => 10, 1156 Coin::Quarter => 25 1157 } 1158 } 1159 #+END_SRC 1160 1161 *** Patterns That Bind to Values 1162 1163 Another useful feature of match arms is that they can bind to the parts of the values that match the pattern. This is how we can extract values out of enum variants. 1164 1165 As an example, let’s change one of our enum variants to hold data inside it. From 1999 through 2008, the United States minted quarters with different designs for each of the 50 states on one side. No other coins got state designs, so only quarters have this extra value. We can add this information to our =enum= by changing the =Quarter= variant to include a =UsState= value stored inside it, which we’ve done in Listing 6-4. 1166 1167 #+BEGIN_SRC rust 1168 #[derive(Debug)] 1169 enum UsState { 1170 Alabama, 1171 Alaska 1172 } 1173 1174 enum Coin { 1175 Penny, 1176 Nickel, 1177 Dime, 1178 Quarter(UsState) 1179 } 1180 #+END_SRC 1181 Listing 6-4: A =Coin= enum in which the =Quarter= variant also holds a =UsState= value 1182 1183 Let's imagine that a friend is trying to collect all 50 state quarters. While we sort our loose change by coin type, we'll also call out the name of the state associated with each quarter so that if it's one our friend doesn't have, they can add it to their collection. 1184 1185 In the match expression for this code, we add a variable called =state= to the pattern that matches values of the variant =Coin::Quarter=. When a =Coin::Quarter= matches, the =state= variable will bind to the value of that quarter's state. Then we can use =state= in the code for that arm, like so: 1186 1187 #+BEGIN_SRC rust 1188 fn value_in_cents(coin: Coin)-> u8 { 1189 match coin { 1190 Coin::Penny => 1, 1191 Coin::Nickel => 5, 1192 Coin::Dime => 10, 1193 Coin::Quarter(state) => { 1194 println!("State quarter from {state:?}!"); 1195 25 1196 } 1197 } 1198 } 1199 #+END_SRC 1200 1201 If we were to call =value_in_cents(Coin::Quarter(UsState::Alaska))=, =coin= would be =Coin::Quarter(UsState::Alaska)=. When we compare that value with each of the match arms, none of them match until we reach =Coin::Quarter(state)=. At that point, the binding for =state= will be the value =UsState::Alaska=. We can then use that binding in the =println!= expression, thus getting the inner state value out of the =Coin= enum variant for =Quarter=. 1202 1203 The Option<T> match Pattern 1204 1205 #+BEGIN_SRC rust 1206 fn plus_one(x: Option<i32>) -> Option<i32> { 1207 match x { 1208 None => None, 1209 Some(i) => Some(i + 1), 1210 } 1211 } 1212 1213 let five = Some(5); 1214 let six = plus_one(five); 1215 let none = plus_one(None); 1216 #+END_SRC 1217 Listing 6-5: A function that uses a =match= expression on an =Option<i32>= 1218 1219 Matches are Exhaustive 1220 1221 ** Concise Control Flow with if let and let...else 1222 * Packages, Crates, and Modules 1223 ** Packages and Crates 1224 The first parts of the module system we'll cover are packages and crates. 1225 1226 A /crate/ is the smallest amount of code that the Rust compiler considers at a time. Even if you run =rustc= rather than =cargo= and pass a single source code file (as we did all the way back in "Rust Program Basics" in Chapter 1), the compiler considers that file to be a crate. Crates can contain modules, and the modules may be defined in other files that get compiled with the crate, as we'll see in the coming sections. 1227 1228 A crate can come in one of two forms: a binary crate or a library crate. /Binary/ crates are programs you can compile to an executable that you can run, such as a command line program or a server. Each must have a function called =main= that defines what happens when the executable runs. All the crates we’ve created so far have been binary crates. 1229 1230 /Library/ crates don’t have a =main= function, and they don’t compile to an executable. Instead, they define functionality intended to be shared with multiple projects. For example, the =rand= crate we used in Chapter 2 provides functionality that generates random numbers. Most of the time when Rustaceans say “crate,” they mean library crate, and they use “crate” interchangeably with the general programming concept of a “library.” 1231 1232 The /crate/ root is a source file that the Rust compiler starts from and makes up the root module of your crate (we’ll explain modules in depth in “Control Scope and Privacy with Modules”). 1233 1234 A /package/ is a bundle of one or more crates that provides a set of functionality. A package contains a /Cargo.toml/ file that describes how to build those crates. Cargo is actually a package that contains the binary crate for the command line tool you’ve been using to build your code. The Cargo package also contains a library crate that the binary crate depends on. Other projects can depend on the Cargo library crate to use the same logic the Cargo command line tool uses. 1235 1236 A package can contain as many binary crates as you like, but at most only one library crate. A package must contain at least one crate, whether that’s a library or binary crate. 1237 1238 Let’s walk through what happens when we create a package. First, we enter the command =cargo new my-project=: 1239 1240 #+BEGIN_SRC sh 1241 cargo new my-project 1242 ls my-project 1243 ls my-project/src 1244 #+END_SRC 1245 1246 After we run =cargo new my-project=, we use =ls= to see what Cargo creates. In the /my-project/ directory, there’s a /Cargo.toml/ file, giving us a package. There’s also a /src/ directory that contains /main.rs/. Open /Cargo.toml/ in your text editor and note that there’s no mention of /src/main.rs/. Cargo follows a convention that src/main.rs is the crate root of a binary crate with the same name as the package. Likewise, Cargo knows that if the package directory contains src/lib.rs, the package contains a library crate with the same name as the package, and src/lib.rs is its crate root. Cargo passes the crate root files to rustc to build the library or binary. 1247 1248 Here, we have a package that only contains src/main.rs, meaning it only contains a binary crate named my-project. If a package contains src/main.rs and src/lib.rs, it has two crates: a binary and a library, both with the same name as the package. A package can have multiple binary crates by placing files in the src/bin directory: Each file will be a separate binary crate. 1249 1250 ** Control Scope and Privacy with Modules 1251 In this section, we'll talk about modules and other parts of the module system, namely /paths/, which allow you to name items; the =use= keyword that brings a path into scope; and the =pub= keyword to make items public. We'll also discuss the =as= keyword, external packages, and the glob operator. 1252 1253 *Modules Cheat Sheet* 1254 1255 Before we get to the details of modules and paths, here we provide a quick reference on how modules, paths, the =use= keyword, and the =pub= keyword work in the compiler, and how most developers organize their code. 1256 1257 ** Paths for Referring to an Item in the Module Tree 1258 ** Bringing Paths Into Scope with the use Keyword 1259 ** Separating Modules into Different Files 1260 * Common Collections 1261 ** Storing Lists of Values with Vectors 1262 ** Storing UTF-8 Encoded Text with Strings 1263 ** Storing Keys with Associated Values in Hash Maps 1264 * Error Handling 1265 ** Unrecoverable Errors with panic! 1266 ** Recoverable Errors with Result 1267 ** To panic! or Not to panic! 1268 * Generic Types, Traits, and Lifetimes 1269 ** Generic Data Types 1270 ** Defining Shared Behavior with Traits 1271 ** Validating References with Lifetimes 1272 * Writing Automated Tests 1273 ** How to Write Tests 1274 ** Controlling How Tests Are Run 1275 ** Test Organization 1276 * An I/O Project: Building a Command Line Program 1277 ** Accepting Command Line Arguments 1278 ** Reading a File 1279 ** Refactoring to Improve Modularity and Error Handling 1280 ** Adding Functionality with Test Driven Development 1281 ** Working with Environment Variables 1282 ** Redirecting Errors to Standard Error 1283 * Functional Language Features: Iterators and Closures 1284 ** Closures 1285 ** Processing a Series of Items with Iterators 1286 ** Improving Our I/O Project 1287 ** Performance in Loops vs. Iterators 1288 * More about Cargo and Crates.io 1289 ** Customizing Builds with Release Profiles 1290 ** Publishing a Crate to Crates.io 1291 ** Cargo Workspaces 1292 ** Installing Binaries with cargo install 1293 ** Extending Cargo with Custom Commands 1294 * Smart Pointers 1295 ** Using Box<T> to Point to Data on the Heap 1296 ** Treating Smart Pointers Like Regular References 1297 ** Running Code on Cleanup with the Drop Trait 1298 ** Rc<T>, the Reference Counted Smart Pointer 1299 ** RefCell<T> and the Interior Mutability Pattern 1300 ** Reference Cycles Can Leak Memory 1301 * Fearless Concurrency 1302 ** Using Threads to Run Code Simultaneously 1303 ** Transfer Data Between Threads with Message Passing 1304 ** Shared-State Concurrency 1305 ** Extensible Concurrency with Send and Sync 1306 * Fundamentals of Asynchronous Programming: Async, Await, Futures, and Streams 1307 ** Futures and the Async Syntax 1308 ** Applying Concurrency with Async 1309 ** Working With Any Number of Futures 1310 ** Streams: Futures in Sequence 1311 ** A Closer Look at the Traits for Async 1312 ** Futures, Tasks, and Threads 1313 * Object Oriented Programming Features 1314 ** Characteristics of Object-Oriented Languages 1315 ** Using Trait Objects to Abstract over Shared Behavior 1316 ** Implementing an Object-Oriented Design Pattern 1317 * Patterns and Matching 1318 ** All the Places Patterns Can Be Used 1319 ** Refutability: Whether a Pattern Might Fail to Match 1320 ** Pattern Syntax 1321 * Advanced Features 1322 ** Unsafe Rust 1323 ** Advanced Traits 1324 ** Advanced Types 1325 ** Advanced Functions and Closures 1326 ** Macros 1327 * Final Project: Building a Multithreaded Web Server 1328 ** Building a Single-Threaded Web Server 1329 ** From Single-Threaded to Multithreaded Server 1330 ** Graceful Shutdown and Cleanup 1331 * Appendix 1332 ** A - Keywords 1333 ** B - Operators and Symbols 1334 ** C - Derivable Traits 1335 ** D - Useful Development Tools 1336 ** E - Editions 1337 ** F - Translations of the Book 1338 ** G - How Rust is Made and “Nightly Rust”