Guided route
Follow the selected readings and build the final output.
This introductory route covers selected foundations, not the entire field.
Finding the next step…
Learn ownership, borrowing and explicit errors through a small Rust file tool.
Basic variables, functions and conditionals, as in Python foundations; no Rust knowledge required. Use a terminal and follow the current Rust book’s toolchain setup. This is an introduction to resource-aware programming, not a complete systems course.
A tested UTF-8 line counter with clear ownership, input and failure contracts.
Start here if the background is new. Equivalent experience is enough.
Practise variables, functions and conditionals before tracing ownership in Rust.
Steve Klabnik · Carol Nichols · Chris Krycho · reference
Installation
Check reading access
Open the readingSteve Klabnik · Carol Nichols · Chris Krycho · reference
Hello, Cargo!
Check reading access
Open the readingSteve Klabnik · Carol Nichols · Chris Krycho · reference
Functions
Check reading access
Open the readingSteve Klabnik · Carol Nichols · Chris Krycho · reference
Control Flow
Check reading access
Open the readingThe Rust Programming Language: Installation. Follow the installation instructions for your operating system; confirm rustc and cargo versions.
The Rust Programming Language: Hello, Cargo!. Create a project and compare cargo check, build and run.
The Rust Programming Language: Functions. Write a function that returns a value; distinguish a statement from an expression.
The Rust Programming Language: Control Flow. Use a conditional and loop in a small input-processing task.
Steve Klabnik · Carol Nichols · Chris Krycho · reference
What Is Ownership?
Check reading access
Open the readingSteve Klabnik · Carol Nichols · Chris Krycho · reference
References and Borrowing
Check reading access
Open the readingSteve Klabnik · Carol Nichols · Chris Krycho · reference
The Slice Type
Check reading access
Open the readingRust contributors · reference
lines(), len() and chars()
Check reading access
Open the readingThe Rust Programming Language: What Is Ownership?. Trace which binding owns a String before and after a move.
The Rust Programming Language: References and Borrowing. Pass a borrowed string to a function and reuse the owner afterward.
The Rust Programming Language: The Slice Type. Borrow a string slice without assuming a byte offset is a character boundary.
Rust standard library: str. Check the lines() contract on empty input and a trailing newline; distinguish bytes from characters.
Why does this invented Rust snippet fail to compile? let label = String::from("route"); let other = label; println!("{label}"); Change it so other only borrows the string and both names can be printed.
String is moved by this assignment; a reference does not take ownership.
The assignment moves the String from label into other, so label cannot be used afterward. If other only needs read access, write let other = &label; and then println!("{label} {other}");. label remains the owner and other is an immutable reference. A clone would create separate owned data, but borrowing expresses the read-only need without that copy.
What to look for
Common mistake: Assuming assigning a String always copies its data like assigning a small integer.
Start this pathway to keep your answers in My learning.
Steve Klabnik · Carol Nichols · Chris Krycho · reference
Recoverable Errors with Result
Check reading access
Open the readingSteve Klabnik · Carol Nichols · Chris Krycho · reference
The match Control Flow Construct
Check reading access
Open the readingSteve Klabnik · Carol Nichols · Chris Krycho · reference
Accepting Command Line Arguments
Check reading access
Open the readingSteve Klabnik · Carol Nichols · Chris Krycho · reference
Reading a File
Check reading access
Open the readingRust contributors · reference
lines(), len() and chars()
Check reading access
Open the readingThe Rust Programming Language: Recoverable Errors with Result. Return a Result for file input and preserve useful error information.
The Rust Programming Language: The match Control Flow Construct. Handle every variant and explain what happens in the error case.
The Rust Programming Language: Accepting Command Line Arguments. Parse a file path and report a missing argument clearly.
The Rust Programming Language: Reading a File. Read a small UTF-8 file and handle a missing path.
Rust standard library: str. Check the lines() contract on empty input and a trailing newline; distinguish bytes from characters.
Why does this invented snippet fail? let mut text = String::from("route"); let first = &mut text; let second = &mut text; first.push_str("!"); second.push_str("?"); Repair it by finishing the first use before creating the second reference.
Both references need mutable access to the same value while their uses overlap.
The second mutable borrow overlaps the first, which is still used afterward. Reorder the uses: let mut text = String::from("route"); let first = &mut text; first.push_str("!"); let second = &mut text; second.push_str("?"); The first reference is no longer used when the second is created, so these borrows do not overlap. The final String is "route!?". Separate blocks are another way to make the sequence clear.
What to look for
Common mistake: Adding mut to more bindings without changing the overlapping uses.
Start this pathway to keep your answers in My learning.
Steve Klabnik · Carol Nichols · Chris Krycho · reference
How to Write Tests
Check reading access
Open the readingSteve Klabnik · Carol Nichols · Chris Krycho · reference
Storing UTF-8 Encoded Text with Strings
Check reading access
Open the readingRust contributors · reference
lines(), len() and chars()
Check reading access
Open the readingThe Rust Programming Language: How to Write Tests. Add cases for empty input, one line and a trailing newline.
The Rust Programming Language: Storing UTF-8 Encoded Text with Strings. Compare byte length and character count; avoid arbitrary string indexing.
Rust standard library: str. Check the lines() contract on empty input and a trailing newline; distinguish bytes from characters.
Steve Klabnik · Carol Nichols · Chris Krycho · reference
How to Write Tests
Check reading access
Open the readingSteve Klabnik · Carol Nichols · Chris Krycho · reference
Recoverable Errors with Result
Check reading access
Open the readingRust contributors · reference
lines(), len() and chars()
Check reading access
Open the readingThe Rust Programming Language: How to Write Tests. Add cases for empty input, one line and a trailing newline.
The Rust Programming Language: Recoverable Errors with Result. Return a Result for file input and preserve useful error information.
Rust standard library: str. Check the lines() contract on empty input and a trailing newline; distinguish bytes from characters.
For a counter that uses text.lines().count(), what should the results be for "", "a", "a\n" and "a\n\n"? Here \n means a newline. Why should the README name the counting rule?
Check the str::lines contract rather than counting newline characters alone.
The counts are 0, 1, 1 and 2. Empty text has no lines; a single trailing newline does not add another empty line, but the extra newline in "a\n\n" represents a blank second line. The README should state that the tool uses Rust’s lines() behaviour on UTF-8 text, because newline counts and other definitions may differ. Tests should preserve this contract.
What to look for
Common mistake: Counting newline characters and treating that as the same contract for every input.
Start this pathway to keep your answers in My learning.
Editorial perspectives based on selected works, rather than author-endorsed reading lists.
Follow the selected readings and build the final output.
This introductory route covers selected foundations, not the entire field.
Focus on how values move and how functions borrow them.
Safe ownership rules do not automatically prove the program’s logic correct.
Focus on recoverable failures and a small testable boundary.
A clean interface does not remove file-system or encoding failures.
Background, different viewpoints, and further reading.
Follow the installation instructions for your operating system; confirm rustc and cargo versions.
Installation
Compile and run one small program; distinguish source code from the executable.
Hello, World!
Create a project and compare cargo check, build and run.
Hello, Cargo!
Change one binding deliberately and read the compiler message.
Variables and Mutability
Choose explicit types for a small calculation and inspect a type mismatch.
Data Types
Write a function that returns a value; distinguish a statement from an expression.
Functions
Use a conditional and loop in a small input-processing task.
Control Flow
Trace which binding owns a String before and after a move.
What Is Ownership?
Pass a borrowed string to a function and reuse the owner afterward.
References and Borrowing
Borrow a string slice without assuming a byte offset is a character boundary.
The Slice Type
Group related values in a struct when separate parameters become unclear.
Defining and Instantiating Structs
Represent alternatives explicitly instead of using an unexplained flag.
Defining an Enum
Handle every variant and explain what happens in the error case.
The match Control Flow Construct
Compare byte length and character count; avoid arbitrary string indexing.
Storing UTF-8 Encoded Text with Strings
Return a Result for file input and preserve useful error information.
Recoverable Errors with Result
Add cases for empty input, one line and a trailing newline.
How to Write Tests
Parse a file path and report a missing argument clearly.
Accepting Command Line Arguments
Read a small UTF-8 file and handle a missing path.
Reading a File
Separate argument handling, file input and the function you can test.
Refactoring to Improve Modularity and Error Handling
Check the lines() contract on empty input and a trailing newline; distinguish bytes from characters.
lines(), len() and chars()