Rust Standard Library Cookbook
Jan Hohenheim, Daniel Durante
- 360 pages
- English
- ePUB (mobile friendly)
- Available on iOS & Android
Rust Standard Library Cookbook
Jan Hohenheim, Daniel Durante
About This Book
Explore the Rust Standard library and compose algorithms with minimal dependency on external libraries
Key Features
- Develop high-quality, fast, and portable applications by leveraging the power of Rust's Standard library.
- Practical recipes that will help you work with the Standard library to boost your productivity as a Rust developer.
- Learn about most relevant external crates to be used along with the Standard library.
Book Description
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.
What you will learn
- How to use the basic modules of the library: strings, command line access, and more.
- Implement collections and folding of collections using vectors, Deque, linked lists, and more.
- Handle various file types, compressing, and decompressing data.
- Search for files with glob patterns.
- Implement parsing through various formats such as CSV, TOML, and JSON.
- Utilize drop trait, the Rust version of destructor.
- Resource locking with Bilocks.
Who this book is for
This book is for developers who would like to explore the power of Rust and learn to use the STL for various functionalities. A basic Rust programming knowledge is assumed.
Frequently asked questions
Information
- Using a vector
- Using a string
- Accessing collections as iterators
- Using a VecDeque
- Using a HashMap
- Using a HashSet
- Creating an own iterator
- Using a slab
Introduction
Using a vector
How to do it...
- In the command line, jump one folder up with cd .. so you're not in chapter-one anymore. In the next chapters, we are going to assume that you always started with this step.
- Create a Rust project to work on during this chapter with cargo new chapter-two.
- Navigate into the newly-created chapter-two folder. For the rest of this chapter, we will assume that your command line is currently in this directory.
- Inside the folder src, create a new folder called bin.
- Delete the generated lib.rs file, as we are not creating a library.
- In the folder src/bin, create a file called vector.rs.
- Add the following code blocks to the file and run them with cargo run --bin vector:
1 fn main() {
2 // Create a vector with some elements
3 let fruits = vec!["apple", "tomato", "pear"];
4 // A vector cannot be directly printed
5 // But we can debug-print it
6 println!("fruits: {:?}", fruits);
7
8 // Create an empty vector and fill it
9 let mut fruits = Vec::new();
10 fruits.push("apple");
11 fruits.push("tomato");
12 fruits.push("pear");
13 println!("fruits: {:?}", fruits);
14
15 // Remove the last element
16 let last = fruits.pop();
17 if let Some(last) = last {
18 println!("Removed {} from {:?}", last, fruits);
19 }
20
21 // Insert an element into the middle of the vector
22 fruits.insert(1, "grape");
23 println!("fruits after insertion: {:?}", fruits);
24
25 // Swap two elements
26 fruits.swap(0, 1);
27 println!("fruits after swap: {:?}", fruits);
- This is how you can access single elements in a vector:
29 // Access the first and last elements
30 let first = fruits.first();
31 if let Some(first) = first {
32 println!("First fruit: {}", first);
33 }
34 let last = fruits.last();
35 if let Some(last) = last {
36 println!("Last fruit: {}", last);
37 }
38
39 // Access arbitrary elements
40 let second = fruits.get(1);
41 if let Some(second) = second {
42 println!("Second fruit: {}", second);
43 }
44 // Access arbitrary elements without bonds checking
45 let second = fruits[1];
46 println!("Second fruit: {}", second);
- The next few methods apply to the whole vector:
50 // Initialize the vector with a value
51 // Here, we fill our vector with five zeroes
52 let bunch_of_zeroes = vec![0; 5];
53 println!("bunch_of_zeroes: {:?}", bunch_of_zeroes);
54
55 // Remove some item and shift all that come after
56 // into place
57 let mut nums = vec![1, 2, 3, 4];
58 let second_num = nums.remove(1);
59 println!("Removed {} from {:?}", second_num, nums);
60
61 // Filter the vector in place
62 let mut names = vec!["Aaron", "Felicia", "Alex", "Daniel"];
63 // Only keep names starting with 'A'
64 names.retain(|name| name.starts_with('A'));
65 println!("Names starting with A: {:?}", names);
66
67 // Check if the vector contains an element
68 println!("Does 'names' contain \"Alex\"? {}",
names.contains(&"Alex"));
69
70
71
72 // Remove consecutive(!) duplicates
73 let mut nums = vec![1, 2, 2, 3, 4, 4, 4, 5];
74 nums.dedup();
75 println!("Deduped, pre-sorted nums: {:?}", nums);
76
77 // Be careful if your data is not sorted!
78 let mut nums = vec![2, 1, 4, 2, 3, 5, 1, 2];
79 nums.dedup();
80 // Doens't print what you might expect
81 println!("Deduped, unsorted nums: {:?}", nums);
82
83 // Sort a vector
84 nums.sort();
85 println!("Manually sorted nums: {:?}", nums);
86 nums.dedup();
87 println!("Deduped, sorted nums: {:?}", nums);
88
89 // Reverse a vector
90 nums.reverse();
91 println!("nums after being reversed: {:?}", nums);
92
93 // Create a consuming iterator over a range
94 let mut alphabet = vec!['a', 'b', 'c'];
95 print!("The first two letters of the alphabet are: ");
96 for letter in alphabet.drain(..2) {
97 print!("{} ", letter);
98 }
99 println!();
100 // The drained elements are no longer in the vector
101 println!("alphabet after being drained: {:?}", alphabet);
102
103
104 // Check if a vector is empty
105 let mut fridge = vec!["Beer", "Leftovers", "Mayonaise"];
106 println!("Is the fridge empty {}", fridge.is_empty());
107 // Remove all elements
108 fridge.clear();
109 println!("Is the fridge now empty? {}", fridge.is_empty());
- We can split a vector into two and combine them again:
111 // Split a vector into two pieces
112 let mut colors = vec!["red", "green", "blue", "yellow"];
113 println!("colors before splitting: {:?}", colors);
114 let half = colors.len() / 2;
115 let mut second_half = colors.split_off(half);
116 println!("colors after splitting: {:?}", colors);
117 println!("second_half: {:?}", second_half);
118
119 // Put two vectors together
120 colors.append(&mut second_half);
121 println!("colors after appending: {:?}", colors);
122 // This empties the second vector
123 println!("second_half after appending: {:?}", second_half);
- You might remember the splice method from JavaScript:
127 let mut stuff = vec!["1", "2", "3", "4", "5", "6"];
128 println!("Original stuff: {:?}", stuff);
129 let stuff_to_insert = vec!["a", "b", "c"];
130 let removed_stuff: Vec<_> = stuff.splice(1..4,
stuff_to_insert).collect();
131 println!("Spliced stuff: {:?}", stuff);
132 println!("Removed stuff: {:?}", removed_stuff);
- If you are working with very big datasets, you can optimize the performance of your vector:
136 // Initialize the vector with a certain capacity
137 let mut large_vec: Vec<i32> = Vec::with_capacity(1_000_000);
138 println!("large_vec after creation:");
139 println!("len:\t\t{}", large_vec.len());
140 println!("capacity:\t{}", large_vec.capacity());
141
142 // Shrink the vector as close as possible to its length
143 large_vec.shrink_to_fit();
144 println!("large_vec after shrinking:");
145 println!(...