Rust Standard Library Cookbook
eBook - ePub

Rust Standard Library Cookbook

Jan Hohenheim, Daniel Durante

Share book
  1. 360 pages
  2. English
  3. ePUB (mobile friendly)
  4. Available on iOS & Android
eBook - ePub

Rust Standard Library Cookbook

Jan Hohenheim, Daniel Durante

Book details
Book preview
Table of contents
Citations

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

How do I cancel my subscription?
Simply head over to the account section in settings and click on “Cancel Subscription” - it’s as simple as that. After you cancel, your membership will stay active for the remainder of the time you’ve paid for. Learn more here.
Can/how do I download books?
At the moment all of our mobile-responsive ePub books are available to download via the app. Most of our PDFs are also available to download and we're working on making the final remaining ones downloadable now. Learn more here.
What is the difference between the pricing plans?
Both plans give you full access to the library and all of Perlego’s features. The only differences are the price and subscription period: With the annual plan you’ll save around 30% compared to 12 months on the monthly plan.
What is Perlego?
We are an online textbook subscription service, where you can get access to an entire online library for less than the price of a single book per month. With over 1 million books across 1000+ topics, we’ve got you covered! Learn more here.
Do you support text-to-speech?
Look out for the read-aloud symbol on your next book to see if you can listen to it. The read-aloud tool reads text aloud for you, highlighting the text as it is being read. You can pause it, speed it up and slow it down. Learn more here.
Is Rust Standard Library Cookbook an online PDF/ePUB?
Yes, you can access Rust Standard Library Cookbook by Jan Hohenheim, Daniel Durante in PDF and/or ePUB format, as well as other popular books in Computer Science & Programming Languages. We have over one million books available in our catalogue for you to explore.

Information

Year
2018
ISBN
9781788629652
Edition
1
Working with Collections
In this chapter, we will cover the following recipes:
  • 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

Rust provides a very broad set of collections to use. We will look at most of them, see how they're used, discuss how they're implemented, and when to use and choose them. A big part of this chapter focuses on iterators. Much of Rust's flexibility comes from them, as all collections (and more!) can be used as iterators. Learning how to use them is crucial.
Throughout this chapter, we are going to use the big O notation to show how effective certain algorithms are. In case you don't know it yet, it is a way of telling how much longer an algorithm takes when working with more elements. Let's look at it briefly.
means that an algorithm is going to take the same time, no matter how much data is stored in a collection. It doesn't tell us how fast exactly it is, just that it's not going to slow down with size. This is the realistic ideal for a function. A practical example for this is accessing the first number in an infinite list of numbers: no matter how many numbers there are, you're always going to be able to instantly pick out the first one.
means that an algorithm is going to slow down by the same degree for every element. This is not good, but still okay. An example for this is printing all data in a for loop.
is really bad. It tells us that an algorithm is going to be slower and slower with every element. An example of it would be accessing data in a for loop nested in another for loop over the same data.

Using a vector

The most basic collection is the vector, or Vec for short. It is essentially a variable-length array with a very low overhead. As such, it is the collection that you will use most of the time.

How to do it...

  1. 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.
  2. Create a Rust project to work on during this chapter with cargo new chapter-two.
  3. 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.
  4. Inside the folder src, create a new folder called bin.
  5. Delete the generated lib.rs file, as we are not creating a library.
  6. In the folder src/bin, create a file called vector.rs.
  7. 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);
  1. 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);
  1. 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());
  1. 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);
  1. 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);
  1. 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!(...

Table of contents