Book Image

Rust Standard Library Cookbook

By : Jan Hohenheim, Daniel Durante
Book Image

Rust Standard Library Cookbook

By: Jan Hohenheim, Daniel Durante

Overview of this book

Mozilla’s Rust is gaining much attention with amazing features and a powerful library. This book will take you through varied recipes to teach you how to leverage the Standard library to implement efficient solutions. The book begins with a brief look at the basic modules of the Standard library and collections. From here, the recipes will cover packages that support file/directory handling and interaction through parsing. You will learn about packages related to advanced data structures, error handling, and networking. You will also learn to work with futures and experimental nightly features. The book also covers the most relevant external crates in Rust. By the end of the book, you will be proficient at using the Rust Standard library.
Table of Contents (12 chapters)

How to do it...

  1. In the src/bin folder, create a file called builder.rs

  2. Add all of the following code and run it with cargo run --bin builder:

1  fn main() {
2 // We can easily create different configurations
3 let normal_burger = BurgerBuilder::new().build();
4 let cheese_burger = BurgerBuilder::new()
.cheese(true)
.salad(false)
.build();
5 let veggie_bigmac = BurgerBuilder::new()
.vegetarian(true)
.patty_count(2)
.build();
6
7 if let Ok(normal_burger) = normal_burger {
8 normal_burger.print();
9 }
10 if let Ok(cheese_burger) = cheese_burger {
11 cheese_burger.print();
12 }
13 if let Ok(veggie_bigmac) = veggie_bigmac {
14 veggie_bigmac.print();
15 }
16
17 // Our builder can perform a check for
18 // invalid configurations
19 let invalid_burger = BurgerBuilder::new()
.vegetarian(true)
.bacon(true)
.build();
20 if let Err(error) = invalid_burger {
21 println!("Failed to print burger: {}", error);
22 }
23
24 // If we omit the last step, we can reuse our builder
25 let cheese_burger_builder = BurgerBuilder::new().cheese(true);
26 for i in 1..10 {
27 let cheese_burger = cheese_burger_builder.build();
28 if let Ok(cheese_burger) = cheese_burger {
29 println!("cheese burger number {} is ready!", i);
30 cheese_burger.print();
31 }
32 }
33 }

This is the configurable object:

35 struct Burger {
36 patty_count: i32,
37 vegetarian: bool,
38 cheese: bool,
39 bacon: bool,
40 salad: bool,
41 }
42 impl Burger {
43 // This method is just here for illustrative purposes
44 fn print(&self) {
45 let pretty_patties = if self.patty_count == 1 {
46 "patty"
47 } else {
48 "patties"
49 };
50 let pretty_bool = |val| if val { "" } else { "no " };
51 let pretty_vegetarian = if self.vegetarian { "vegetarian "
}
else { "" };
52 println!(
53 "This is a {}burger with {} {}, {}cheese, {}bacon and
{}salad",
54 pretty_vegetarian,
55 self.patty_count,
56 pretty_patties,
57 pretty_bool(self.cheese),
58 pretty_bool(self.bacon),
59 pretty_bool(self.salad)
60 )
61 }
62 }

And this is the builder itself. It is used to configure and create a Burger:

64  struct BurgerBuilder {
65 patty_count: i32,
66 vegetarian: bool,
67 cheese: bool,
68 bacon: bool,
69 salad: bool,
70 }
71 impl BurgerBuilder {
72 // in the constructor, we can specify
73 // the standard values
74 fn new() -> Self {
75 BurgerBuilder {
76 patty_count: 1,
77 vegetarian: false,
78 cheese: false,
79 bacon: false,
80 salad: true,
81 }
82 }
83
84 // Now we have to define a method for every
85 // configurable value
86 fn patty_count(mut self, val: i32) -> Self {
87 self.patty_count = val;
88 self
89 }
90
91 fn vegetarian(mut self, val: bool) -> Self {
92 self.vegetarian = val;
93 self
94 }
95 fn cheese(mut self, val: bool) -> Self {
96 self.cheese = val;
97 self
98 }
99 fn bacon(mut self, val: bool) -> Self {
100 self.bacon = val;
101 self
102 }
103 fn salad(mut self, val: bool) -> Self {
104 self.salad = val;
105 self
106 }
107
108 // The final method actually constructs our object
109 fn build(&self) -> Result<Burger, String> {
110 let burger = Burger {
111 patty_count: self.patty_count,
112 vegetarian: self.vegetarian,
113 cheese: self.cheese,
114 bacon: self.bacon,
115 salad: self.salad,
116 };
117 // Check for invalid configuration
118 if burger.vegetarian && burger.bacon {
119 Err("Sorry, but we don't server vegetarian bacon
yet".to_string())
120 } else {
121 Ok(burger)
122 }
123 }
124 }