32,99 €
Quickly learn the ropes with the Rust programming language using this practical, step-by-step guide In Beginning Rust Programming, accomplished programmer and author Ric Messier delivers a highly practical, real-world guide to coding with Rust. Avoiding dry, theoretical content and "Hello, world"-type tutorials of questionable utility, the book dives immediately into functional Rust programming that takes advantage of the language's blazing speed and memory efficiency. Designed from the ground up to give you a running start to using the multiparadigm system programming language, this book will teach you to: * Solve real-world computer science problems of practical importance * Use Rust's rich type system and ownership model to guarantee memory-safety and thread-safety * Integrate Rust with other programming languages and use it for embedded devices Perfect for programmers with some experience in other languages, like C or C++, Beginning Rust Programming is also a great pick for students new to programming and seeking a user-friendly and robust language with which to start their coding career.
Sie lesen das E-Book in den Legimi-Apps auf:
Seitenzahl: 929
Veröffentlichungsjahr: 2021
COVER
TITLE PAGE
INTRODUCTION
OBTAINING RUST
GETTING THE SOURCE CODE
WHAT YOU WILL LEARN
PROVIDING FEEDBACK
1 Game of Life: The Basics
GAME OF LIFE: THE PROGRAM
STARTING WITH CARGO
PUTTING THE PIECES TOGETHER
GENERATING THE GAME GRID
DISSECTING MAIN
LOOKING AT MORE FUNCTION FUNCTIONS
COMPILING PROGRAMS
SUMMARY
ADDITIONAL RESOURCES
2 Extended Life
UNDERSTANDING OWNERSHIP
EXTENDING LIFE
READING FROM FILES
OUTPUTTING TO THE TERMINAL
SUMMARY
ADDITIONAL RESOURCES
3 Building a Library
REFERENCES
FIRST PASS
SECOND PASS
SUMMARY
ADDITIONAL RESOURCES
4 Hangman
OUR DATA
READING FILES AND SELECTING WORDS
THE REST OF THE STORY
SUMMARY
ADDITIONAL RESOURCES
5 In Concurrence
THE DINING PHILOSOPHERS
THE MAIN EVENT
THREADING IN THE MAIN
SUMMARY
ADDITIONAL RESOURCES
6 Clients and Servers
PLANNING
NETWORK PROGRAMMING
RUST TCP SERVER
SUMMARY
ADDITIONAL RESOURCES
7 Client-Side Applications
ENCRYPTION
REMOTE ACCESS CLIENT
SUMMARY
ADDITIONAL RESOURCES
8 Going Relational
APPLICATION ARCHITECTURES
DATABASES
WRITING A DATABASE PROGRAM
SUMMARY
ADDITIONAL RESOURCES
9 No(SQL) Going
ASSERTIONS
NOSQL
WORKING WITH MONGODB
SUMMARY
ADDITIONAL RESOURCES
10 Web Communications
STYLE GUIDES
HYPERTEXT TRANSFER PROTOCOL
CLIENT COMMUNICATION
SUMMARY
ADDITIONAL RESOURCES
11 Web Server
OFFENSIVE VS. DEFENSIVE PROGRAMMING
WEB APPLICATION COMMUNICATIONS
RUST ROCKET
SUMMARY
ADDITIONAL RESOURCES
12 Getting to the System
EXTENDING FUNCTIONALITY
WINDOWS REGISTRY
SYSTEM INFORMATION WITH RUST
PERSISTENCE (FOR FUN)
SUMMARY
ADDITIONAL RESOURCES
13 Device Programming
LOGGING
WORKING WITH RASPBERRY PI
SUMMARY
ADDITIONAL RESOURCES
14 Collecting Stuff
ARRAYS AND VECTORS
LINKED LISTS
SEARCH TREES
SUMMARY
ADDITIONAL RESOURCES
15 Odds and Sods
UNIT TESTING
RECURSION
MACHINE LEARNING
SUMMARY
ADDITIONAL RESOURCES
INDEX
COPYRIGHT
ABOUT THE AUTHOR
ABOUT THE TECHNICAL EDITOR
ACKNOWLEDGMENTS
END USER LICENSE AGREEMENT
Chapter 13
TABLE 13.1: Syslog facilities
TABLE 13.2: Severity table
Chapter 15
TABLE 15.1: Rust test plan
Chapter 1
FIGURE 1.1: Single-dimension array
FIGURE 1.2: Multidimensional array
FIGURE 1.3: Passing by reference in C
Chapter 2
FIGURE 2.1: Visual representation of variables
FIGURE 2.2: Assigning variables
FIGURE 2.3: Reference counting
FIGURE 2.4: Demonstration of an iterator
FIGURE 2.5: Life generation output
Chapter 3
FIGURE 3.1: Representation of a
Dvd
structure
FIGURE 3.2: Instance of a
Dvd
Chapter 4
FIGURE 4.1: Notes on program design
FIGURE 4.2:
Option enum
FIGURE 4.3: Embedded values
Chapter 5
FIGURE 5.1: Dining philosophers
FIGURE 5.2: Visual representation of a mutex
FIGURE 5.3: Multithreaded program
FIGURE 5.4: Process memory sharing
Chapter 6
FIGURE 6.1: UML diagram of the client program
FIGURE 6.2: TCP/IP layers
FIGURE 6.3: Network transmission
FIGURE 6.4: Network envelope
Chapter 7
FIGURE 7.1: Creating ciphertext with a key
FIGURE 7.2: Diffie-Hellman key derivation
Chapter 8
FIGURE 8.1: Traditional web application design
FIGURE 8.2: Microservices design
FIGURE 8.3: Model-View-Controller
FIGURE 8.4: Model-View-Controller
FIGURE 8.5: MySQL Workbench with the query
FIGURE 8.6: Error hierarchy
Chapter 9
FIGURE 9.1: Design by contract diagram
FIGURE 9.2: Graph database
FIGURE 9.3: MongoDB database creation
FIGURE 9.4: Records in MongoDB
Chapter 10
FIGURE 10.1: C++ exception style rule
FIGURE 10.2: Rust style guide
FIGURE 10.3: Web server directory tree
Chapter 11
FIGURE 11.1: Simple web form
FIGURE 11.2: Web application architecture
FIGURE 11.3: API architecture
Chapter 12
FIGURE 12.1: Encapsulated data
FIGURE 12.2: Magic card box
FIGURE 12.3: Registry editor
FIGURE 12.4: Registry hive files
FIGURE 12.5: Value added to the Registry
Chapter 13
FIGURE 13.1: Windows Event Viewer
FIGURE 13.2: Windows Event Log entry
FIGURE 13.3: Reordered log entries
FIGURE 13.4: Windows Event Log entry
FIGURE 13.5: Error message in Windows Event Log
FIGURE 13.6: Raspberry Pi
FIGURE 13.7: AMD processor with a fan
FIGURE 13.8: Raspberry Pi compared with a traditional processor
FIGURE 13.9: Breadboard for a Raspberry Pi
FIGURE 13.10: Wiring an LED light
FIGURE 13.11: Push-button wiring
Chapter 14
FIGURE 14.1: Daily temperature including tenths.
FIGURE 14.2: Linked list.
FIGURE 14.3: Reordered linked list.
FIGURE 14.4: Stack diagram
FIGURE 14.5: Real-life stack
FIGURE 14.6: Binary tree before placement
FIGURE 14.7: Binary tree after placement
Chapter 15
FIGURE 15.1: Software development lifecycle
FIGURE 15.2: Relative cost of software defects
FIGURE 15.3: Boxes needing sorting
FIGURE 15.4: Factorial call stack
FIGURE 15.5: Towers of Hanoi
FIGURE 15.6: Find the plant
Cover Page
Table of Contents
Begin Reading
v
xix
xx
xxi
xxii
xxiii
xxiv
xxv
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
375
376
377
378
379
380
381
382
383
384
385
386
387
388
vi
vii
ix
xi
389
Ric Messier
Save me from another “hello, world” book. Don't make me have to skim or skip through a half dozen chapters before I can get to something that's going to be useful to me. Or you, in this case. I can't tell you the number of programming books I've purchased over the decades, hoping to actually learn the language, only to end up just not using the book because it wasn't presented in a way that made a lot of sense to me. Instead of a dry explanation of how the language is constructed so you can try to put it all together in meaningful ways yourself, the purpose of this book is to jump straight into writing hopefully interesting or useful programs. Once we have the program, we can take a look at how it's constructed. You'll be learning by doing—or learning by example, if you prefer. I hope you'll find this a more useful and practical way of learning Rust.
Rust is an interesting language, as it turns out. Like so many other languages, it claims a C-like syntax, which is roughly correct but misses out on many important elements. Where Rust really shines is where C has introduced bad behavior in programming practices. This is more apparent as more have been using C as a language. Where C provides you with the gun and the bullets to shoot yourself in the foot, Rust provides you with necessary protections to keep you from injuring yourself or, from the perspective of the application, keeps the application from crashing. Rust is focused on protecting the memory space of the program, in part to provide a better ability for concurrent programming. After all, Rust is considered to be a systems programming language, meaning it is intended for applications that are lower level than those that a user directly interacts with.
In addition to protections provided to the programmer, Rust has a reasonably active community that can be used not only for support but also to get additional functionality for your programs. There are a lot of third-party libraries. These libraries can make your life easier by introducing you to functionality without you needing to write it yourself.
The idea behind this book is to introduce you to Rust in context, rather than via snippets that, by themselves, don't work. You need all the surround to fully understand what is happening in the program. You'll find this out when you are looking at example code sometimes. This is true with the Rust documentation: it's like you need to fully understand the language to understand the examples you are looking at. This book doesn't take that approach. It assumes that you don't know the language, so every line in every program is explained in as much detail as is necessary to pull it all apart, since Rust can be a dense language in some ways. This means single lines can pack a lot of meaning and functionality.
The one thing this book does not assume, though, is that you are coming to programming completely fresh. You will see examples for the programs written in Rust also presented in other programming languages. This may be helpful if you come from another language like C or Python, for instance, but want to learn Rust. Seeing the approach in a language you know before translating it into Rust may be beneficial. If you don't know those other languages, you can skip through those examples and jump to the explanation of how to write a program for the problem under discussion in Rust. You can still compare the other languages to Rust as you are going through so you can better understand Rust and how it is different from other languages.
Rust is a collection of programs that you will use. While a big part of it is the compiler, that's not the only program that will get installed. First, of course, is the compiler, rustc. This program will compile any Rust source code file, but more than that, it will compile complete executables. With some compiler programs, you have to compile source code files individually and then perform a step called linking, where you link all the source code files together along with any needed libraries to create the executable. If there is a reference to another source code file you have written as a module, the Rust compiler will compile all the modules and generate an executable without any additional intervention.
In practice, though, you probably won't use the Rust compiler directly. Instead, you'll use the cargo program. You'll want to get used to using cargo because it not only compiles your source code but also will manage any external dependencies. You will probably have libraries that are not part of the standard library. With languages like C and Python, you'd typically need to go get the library yourself and get it installed. You'd need to make sure it was installed in the right place, and then, in the case of C, you'd probably need to call the compiler in a way that made it clear you wanted to link in the external library so all the external references could get resolved and put into the resulting executable.
Rust is also a newer program, which means there are changes being made to it. You'll generally want to keep up-to-date on the newest Rust compiler. Your third-party libraries may be keeping up with the latest Rust changes, and if you aren't up-to-date, your program won't compile. You'll want the rustup utility to help manage your Rust installation.
If you are working on a Linux distribution, you may be inclined to use whatever package manager you have to install Rust. There's a better-than-good chance that your distribution has the Rust language in it. The problem is, once you install using the package manager, you may be held back by the package manager. The latest Rust software may not be available to you. It's easier to just install Rust without the Linux package manager. With operating systems like macOS and Windows, you don't even have a built-in package manager, so installing that way wouldn't be an option anyway.
The best approach is to go to the Rust website (www.rust-lang.org). For Unix-like operating systems, including Linux and macOS, there is a command-line string you will probably use to install. Because there is a chance this approach may change, it's best to just go to the website to get the right way. As of the writing of this book, the command used to install Rust on those operating systems follows. If you are on Windows, you can download an installer from the Rust website:
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
Once you have the Rust toolchain installed, you can keep it updated by using the command rustup update. This will always get the latest version of the Rust toolchain and make sure it is installed. You will also need to use a good source code editor. There are several available that will support Rust extensions, including Visual Studio Code, Atom, and Sublime. You should make sure you have installed the Rust extensions, which will help you with syntax highlighting and other features.
As you work your way through this book, you will see primarily complete programs that are explained in context. You can certainly retype the programs from the book, and most are not that long. There is some value in retyping because it helps to ingrain the code and approach to programming used by Rust. However, it can be tedious to stare at a program and try to retype it. You may want to just start with the source code. It's all available on GitHub. GitHub is a source code repository site using the git source code management software. It was originally written to be used with the Linux kernel, as previous source code management software was not considered to be feature-rich enough. While there is other software available, git is most widely used today because public repositories like GitHub use git. To get the source code for this book, you can use the following command:
git clone https://github.com/securitykilroy/rust.git
If you have a git client that you prefer to the command line, you can certainly use it. The command line is going to be the most common approach to grabbing source code from a git server.
NOTE The files are also available at www.wiley.com/go/beginningrust.
The approach in this book is to write complete programs that are useful in some way, even if they are very simple starting points to more interesting programs. The idea is not to try to deconstruct enormous programs, so each chapter will tackle important ideas, but the programs presented may be limited. You will get important building blocks but maybe not large, complex programs. Each chapter will present some essential ideas in Rust and, sometimes, programming in general. Many chapters build on ideas from previous chapters. You can certainly read individual chapters since, in most cases, the program is still explained in detail, not always assuming you have read previous chapters.
The book doesn't exclusively cover the Rust programming language. Programming is about far more than language syntax. There is much more to programming than just how a language is constructed. This is especially true if you ever want to write software on a team—working with an open source project or being employed as a programmer. You need to be aware of how larger programs are constructed and ways to write software in a way that is readable and maintainable, as well as ways to write tests of your software. You can see the topics covered in each chapter here.
We get started with a partially functional implementation of Conway's Game of Life, a classic computer science program. Along the way, you will learn how to use cargo to create a new program with all the files and directories needed for cargo to build the program for you. You'll also learn about data types and some initial control structures, as well as creating functions in Rust.
The reason for making the program in Chapter 1, “Game of Life: The Basics,” only partly functional is that the complete program is larger, and there are a lot of concepts to introduce to implement everything. By the end of this chapter, you will have a fully functional program that will implement Conway's Game of Life. You will also learn about the use of a collection data type that is good for dynamically sized collections. You will also learn about performing input/output to interact with the user. One of the most important concepts in Rust is introduced in this chapter, and it will keep recurring in several subsequent chapters. Ownership is foundational to Rust and is part of what makes it a good language for systems programming. Rust is designed to be a safe language, unlike a language like C.
This chapter works with another essential concept in Rust—the struct. This is a complex data structure, defined entirely by the programmer. It underpins data abstraction in Rust, so it will be covered across multiple chapters in different ways. You'll also be working with writing to files as well as working with JavaScript Object Notation (JSON), a common approach to store and transmit complex data structures in a way that is self-describing. We'll also extend the idea of ownership by talking about lifetimes.
The struct is an important concept in Rust because it provides a way to abstract data. Data abstraction is hiding the data behind a data structure and a set of functionality that acts on the data. This is done using traits in Rust, and this chapter introduces those traits. We'll spend a lot of time in subsequent chapters looking at traits in more detail. We'll also talk about error handling, which is another dense and important topic that will be covered in unfolding detail across several chapters. Additionally, we’ll cover another control structure that allows you to make different decisions based on the contents of an identifier. Identifiers in Rust are similar to variables in other languages, although there are some subtle nuances, which is why it's easier to refer to them as identifiers. We'll also look at how to take input from a user.
This chapter covers concurrent programming, sometimes called parallel programming. This is where a program ends up breaking into multiple, simultaneous execution paths. There are a lot of challenges with concurrent programming, not least of which is the way the different execution paths communicate with one another to keep data and timing synchronized. We'll also look at how to interact with the operating system to get information from the filesystem. And we'll take an initial pass at encryption, although this is not the last time encryption will be covered.
We'll start on network programming, although this will also be spread across additional chapters. There are a lot of different ways to write programs for network communication because there are so many protocols that are used over networks. We'll look at some additional interactions with the operating system in this chapter as well. This is the first of a pair of chapters that are linked. In this chapter, we implement a network server that requires a client to talk to it. This chapter also talks about different ways to design your program so you’ll have thought about all the elements and features the program needs before you start writing it.
This is the chapter that covers the client that communicates with the server from the previous chapter. We will also cover using encryption to communicate over the network. Additionally, we'll use regular expressions, which can be a powerful pattern-matching system. While they have a lot of other uses, we're going to use regular expressions in this chapter to help us make sure we have the right input from the user.
This is the first chapter that talks about database communications. This chapter covers the use of relational databases, which are traditional ways to store structured information. If you've seen the use of MySQL, PostgreSQL, Microsoft SQL Server, Oracle, SQLite, or other databases, you've seen relational databases in action. You may be working with a database server or an embedded database. This chapter will cover those two techniques so you will be able to talk to a server or store data in a searchable way in a local file.
Relational databases have been around for decades; but the way forward is using other database types, since data isn't always so well structured that you know exactly what properties will be associated with it. Additionally, there may be documents involved that need to be dealt with. This chapter covers the use of NoSQL databases, which are databases that use something other than traditional relational techniques to store and retrieve data. This chapter also covers assertions, which are ways to ensure that data is in the state it is expected to be in before being handled by a function. This is a way of protecting the program, allowing it to fail gracefully.
Many applications are moving to the web. This means you need to be able to write programs that can communicate over web-based technologies, including the HTTP protocol. This chapter will cover not only how to write web client programs but also extracting data from web pages and asynchronous communication, where you may send a request and not wait for the response but still be able to handle the response when it comes back. This chapter also covers how to use style guides to make your programs more consistent and readable.
Where the last chapter talked about writing web-based clients, this program presents a couple of different ways to write a web server. This is useful if you want to write an application programming interface (API) that can be consumed by clients remotely. This gives Rust the ability to be on the server end of a multitier web application as well as on the client side. Additionally, this chapter will talk about considering offensive and defensive programming practices to make your programs more resilient and more resistant to attack. This includes the idea of design by contract, guaranteeing that a program acts exactly the way it is expected to.
Rust is considered a systems programming language, so we will investigate how to interact with the system. We'll start by writing programs to extend data structures, including some built-in data structures. We'll also take a look at how to interact with the Windows Registry to store and retrieve information. Finally, we'll introduce functionality to get information about the system, including process listings.
We're going to take the systems programming idea and talk about an essential aspect of programming that is often overlooked; whether you are writing a system service or something that is user-focused, you should always be generating logs. We'll take a look at how to write to both syslog as well as the Windows Event Log. On top of that, we'll take a look at how to write directly to hardware on a Raspberry Pi using the General Purpose Input Output (GPIO) header on the single-board computer.
Early in the book, we covered data collections in the form of arrays and vectors. Data collections are such a useful feature, though, that we spend this chapter on different types of data collections, including linked lists, queues, stacks, and binary search trees.
There are some fun and useful ideas that are left over and covered in this chapter. First, recursion is a common way to tackle programming problems, so we take a look at how to address some problems using recursion. We'll also look at how to use Rust to write machine learning programs using third-party libraries. Finally, we will be writing unit tests in Rust, which are ways to ensure that a function does what it is meant to do. This can also be a way to try to break a function. A library included in Rust makes it easy to write tests, which should be a practice always used when writing programs.
We hope that Beginning Rust Programming will be of benefit to you and that you create some amazing programs with Rust. We've done our best to eliminate errors, but sometimes they do slip through. If you find an error, please let our publisher know. Visit the book's web page, www.wiley.com/go/beginningrust, and click the Errata link to find a form to use to identify the problem.
Thanks for choosing Beginning Rust Programming.