Scripting languages will provide safety, but not concurrency and speed, while traditional systems programming languages such as C and C++ will definitely give you speed and some concurrency, but forget about safety. If you need safety, concurrency, and speed, then Rust is the only viable option.
Scripting languages will provide safety, but not concurrency and speed, while traditional systems programming languages such as C and C++ will definitely give you speed and some concurrency, but forget about safety. If you need safety, concurrency, and speed, then Rust is the only viable option.
In this course, you will learn how Rust guarantees memory and thread safety at compile-time, yet uses zero-cost abstractions without the runtime overhead of a garbage collector. You'll learn how to monitor the flow of data through a pipeline by building your own middleware utility. You'll learn how to utilize I/O to interact with the command line, work with standard library mpsc channels to perform data flows, and create an ergonomic timer for your project. You'll apply key concepts in every section while creating your own middleware tool in Rust along the way.
By the end of this practical course, you will feel comfortable designing safe, consistent, parallel, and high-performance applications in Rust using systems programming.
This course should appeal to intermediate Linux and general Unix programmers, network programmers, and C/C++ programmers interested in learning different approaches to concurrency. Prior knowledge of basic programming concepts is required, and a working knowledge of Rust is assumed.
About the Author
Nathan Stocks has spent the last 20 years working in software development, mostly in the field of backend infrastructure. He fell in love with Rust in 2016 and began teaching it in 2017. For the past several years, he has focused on systems-level programming. He maintained the AVbin audio library (written in C) from 2011-2013. He has had tons of fun learning, using, and teaching Rust at conferences and online. He also loves Python and PostgreSQL, and still occasionally suffers from nightmares about C and C++.
He currently works at GitHub, managing the Git Storage team, and spends his nights in pursuit of someday creating a successful indie game in Rust.
This video provides an overview of the entire course.
Here, see the overview of what Rust is, where it came from, and why we might want to use it.
• Describe what Rust is
• Explain how Rust came to be
• Explain the benefits of Rust
Rust is a difficult language to learn and use. Rust support in your IDE/Editor helps a lot.
• Show the website that lists major IDEs/Editors and how to configure them
• Show how to find Rust support for IDEs/Editors not on the list
• Demonstrate the benefits of Rust IDE support in IntelliJ
We need a tool to create, manage, build, run, document, and test our code.
• Overview cargo’s capabilities
• Demonstrate creating a binary application
• Demonstrate creating a library
The student does not know what we are going to build for this course, so let’s show them.
• Describe the problem of processing data without progress indicators
• Show processing data with and without our project
• Describe the capabilities of our project
We have no project to work in, yet.
• Select a name and location for the project
• Create the project with cargo and configure it
• Select a version control system and configure it
We need to read data from somewhere, process it, and write it back out somewhere else.
• Read data from stdin
• Process the data
• Write data to stdout
We need an ergonomic way to print extra debugging information during development.
• Identify a candidate debugging expression
• Wrap the expression in dbg!()
• Analyze the debugging output
Code is harder to read and distracting conflicts often occur when code is not styled consistently and using the same idioms.
• Call out problems of not adhering to standards and idioms
• Demonstrate cargo fmt and cargo clippy
• Demonstrate automating the tools
Ignoring and not handling errors leads to unsafe and buggy code.
• Describe situations which occur when errors are not handled properly
• Demonstrate handling errors by choosing to crash
• Demonstrate handling errors more gracefully
We need a way to parse command-line arguments to affect the behavior of our program.
• Describe the need to handle command-line arguments
• Demonstrate how to use the clap library in code
• Demonstrate the command-line handling in the compiled project
We need to be able to read and write files, it needs to be fast, and we would like it to be convenient.
• Demonstrate reading and writing files
• Demonstrate buffered reading and writing files for better performance
• Demonstrate using Read/Write traits to make code convenient
As projects grow larger keeping all the code in one file causes it to be hard to understand, use, and re-use. Organizing code into libraries is the answer.
• Describe the problem of having all code in one file
• Explain how libraries work in Rust
• Organize code into a library and use it from our binary
Our main thread can only do one thing at a time: it can read, it can process, or it can output. We would like to be able to do all three simultaneously.
• Describe the limitation of one thread
• Explain how to create child threads
• Execute our read, processing, and write code in separate threads
We need to communicate between our threads, preferably in a way that avoids locking. MPSC channels are a good tool for that.
• Describe our need to communicate between threads
• Explain how MPSC channels work
• Use MPSC channels to communicate between our threads
Using MPSC channels has it’s pros and cons. Use crossbeam channels to take advantage of different tradeoffs.
• Describe the drawbacks of using MPSC channels
• Explain how crossbeam channels overcome those drawbacks
• Refactor our project to use crossbeam channels
Working with time requires understanding the primitive Instant time type.
• Explain how to measure time, as we need points in time
• Explain how Instant works
• Use Instant in our program
Once we have Instants, we can calculate durations between Instants for use in calculations.
• Explain how to use Instants to get durations
• Calculate durations in our project
• Use the durations for progress output
Mixing time-keeping code with other logic can get confusing. Encapsulating all the time-keeping into a struct helps keep code understandable.
• Explain how mixing time-keeping code with logic gets messy
• Describe a strategy to encapsulate the code in a struct
• Refactor the time-keeping code into a struct
We are printing progress at a rate far higher than a human can perceive, which wastes resources unnecessarily. We can use our timer struct to only output progress periodically.
• Describe how updating progress after every read is wasteful
• Refactor our code to output progress only periodically
• Demonstrate the change in the working project
Colored output is often more engaging and more readable. We can use a library to easily colorize our output.
• Describe the benefits of colorizing our output
• Explain how to use the crossterm library
• Refactor our code to colorize output with crossterm
Well-organized libraries are crucial for being able to build larger projects. To make a well-organized library, one must understand how to build libraries.
• Explain the importance of maintaining well-organized libraries
• Explain library organization in much more detail than earlier
• Show an example of using more advanced techniques
Automated tests are vital to both, helping ensure your code runs correctly in the first place, and ensuring that future changes do not break the expected behavior.
• Explain why testing is important
• Show how to write tests
• Demonstrate running tests and interpreting the output
Undocumented code is difficult to figure out, even for the person who originally wrote it. Documenting the design, intentions, and behavior of your code will enable better use of it.
• Explain the problem of undocumented code
• Demonstrate different techniques for documenting code
• Demonstrate generation of the documentation web pages
Version numbers are an important way to communicate how your project changes over time. Semantic versioning is the scheme that Rust uses.
• Explain the importance of adhering to a versioning scheme
• Explain how semantic versioning works and what it means
• Demonstrate changing version numbers on a project
In order to participate in the larger Rust ecosystem, you must be able to publish your code in a way that others can consume it. Cargo facilitates publishing your project to crates.io.
• Describe how your project can be published for others to use
• Explain publishing settings that need to be set
• Demonstrate publishing the project for this course to crates.io
OpenCourser helps millions of learners each year. People visit us to learn workspace skills, ace their exams, and nurture their curiosity.
Our extensive catalog contains over 50,000 courses and twice as many books. Browse by search, by topic, or even by career interests. We'll match you to the right resources quickly.
Find this site helpful? Tell a friend about us.
We're supported by our community of learners. When you purchase or subscribe to courses and programs or purchase books, we may earn a commission from our partners.
Your purchases help us maintain our catalog and keep our servers humming without ads.
Thank you for supporting OpenCourser.