Skip to content

Journey: Rust basics

After this journey you can: write, compile, and run Rust programs. You'll understand ownership, structs, enums, error handling, and how to use Cargo. You'll be ready to read and contribute to Stratorys codebases.

This journey does not cover: async/await, lifetimes in depth, macros, unsafe code, or advanced trait patterns.

How to use this page: Each task gives you a goal and links to relevant documentation. Read the docs, write your solution in src/main.rs, and compare your output with the expected result. Complete the tasks in order - all tasks use the same rust-practice project.

Setup

If Rust is not installed:

bash
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

Verify:

bash
rustc --version
bash
cargo --version

Task 1: Create a project

Goal: Create a new Cargo project called rust-practice and run it.

Docs:

Expected output:

> cargo run
Hello, world!

Task 2: Temperature converter

Goal: Write a program that converts these Fahrenheit temperatures to Celsius: 32.0, 72.0, 98.6, 212.0. Print each conversion on its own line, formatted to one decimal place.

The formula is: C = (F - 32) × 5 / 9

INFO

Rust infers types from values. 3.14 is f64 by default, 42 is i32. You can be explicit with let x: f64 = 3.14;.

Docs:

Expected output:

> cargo run
32.0°F = 0.0°C
72.0°F = 22.2°C
98.6°F = 37.0°C
212.0°F = 100.0°C

Task 3: Number classifier

Goal: Write a function classify that takes a number and returns whether it is "positive", "negative", or "zero". Call it for each integer from -2 to 2 and print the result.

Docs:

Expected output:

> cargo run
-2 is negative
-1 is negative
0 is zero
1 is positive
2 is positive

Task 4: First word

Goal: Write a function first_word that takes a string and returns everything before the first space, or the whole string if there is no space. Call it with "hello world", "rust", and "one two three".

INFO

Every value in Rust has exactly one owner. When you pass a String to a function, it moves - the caller can no longer use it. Use & to borrow a reference instead of transferring ownership.

Docs:

Expected output:

> cargo run
"hello world" -> "hello"
"rust" -> "rust"
"one two three" -> "one"

Task 5: Task tracker

Goal: Define a struct for a task with a title, completion status, and priority level. Implement three methods:

  • One to create a new task (starts as not done)
  • One to mark it as done
  • One to return a summary in the format [P{priority}] {title} - pending or [P{priority}] {title} - done

Create a task titled "Learn Rust ownership" with priority 1. Print its summary, complete it, and print again.

INFO

&self borrows the struct for reading. &mut self borrows it for writing. Methods that modify the struct need &mut self.

Docs:

Expected output:

> cargo run
[P1] Learn Rust ownership - pending
[P1] Learn Rust ownership - done

Task 6: Shape calculator

Goal: Define an enum Shape with three variants:

  • Circle - holds a radius
  • Rectangle - holds width and height
  • Triangle - holds base and height

Implement an area method using match. Create a circle with radius 3.0, a rectangle 4.0 × 5.0, and a triangle with base 6.0 and height 2.0. Print each area formatted to two decimal places.

Docs:

Expected output:

> cargo run
Circle: 28.27
Rectangle: 20.00
Triangle: 6.00

Task 7: Safe number parsing

Goal: Write a function that parses a string into a port number (u16). Return an error instead of crashing if the input is not a valid number. In main, call it with "8080" and "abc". Handle both results - print the value on success, the error on failure.

Also write a function that reads a file and returns its content, using the ? operator to propagate errors. Call it with "config.toml" (which does not exist) and handle the error.

WARNING

Never use unwrap() or expect() in production code at Stratorys. They crash the program on error. Always handle errors with match or ?.

Docs:

Expected output:

> cargo run
Port: 8080
Parse error: invalid digit found in string
Config error: No such file or directory (os error 2)

Task 8: Word counter

Goal: Write a program that counts how many times each word appears in the string "the cat sat on the mat the cat". Print each word and its count, sorted alphabetically by word.

INFO

HashMap does not guarantee iteration order. To print sorted output, collect entries into a Vec and sort it.

Docs:

Expected output:

> cargo run
cat: 2
mat: 1
on: 1
sat: 1
the: 3

Task 9: Describable resources

Goal: Define a trait with a method that returns a description as a String. Create two structs - one for a server (with a name and CPU core count) and one for a database (with a name and engine). Implement the trait for both.

Write a function that accepts any type implementing the trait and prints its description. Call it with a server named "prod-1" with 8 cores and a database named "analytics" running PostgreSQL.

Docs:

Expected output:

> cargo run
Server 'prod-1' with 8 cores
Database 'analytics' (PostgreSQL)

Task 10: JSON config

Material:

Add the required dependencies:

bash
cargo add serde --features derive
bash
cargo add serde_json

Goal: Define a struct for a service configuration with a name (String), port (u16), and debug flag (bool). Use derive macros to make it serializable, deserializable, and printable with Debug.

Create an instance with name "my-service", port 8080, debug true. Serialize it to pretty JSON and print it.

Then deserialize this JSON string and print it with Debug formatting: {"name": "other-service", "port": 3000, "debug": false}

INFO

#[derive(...)] automatically generates trait implementations. Common derives include Debug, Clone, Serialize, and Deserialize.

Docs:

Expected output:

> cargo run
{
  "name": "my-service",
  "port": 8080,
  "debug": true
}
Config { name: "other-service", port: 3000, debug: false }

Task 11: Write tests

Goal: Write two functions: one that adds two integers, and one that checks if an integer is even. Then write a test module with two test functions, each containing at least 3 assertions.

Docs:

Expected output:

> cargo test
...
test tests::test_add ... ok
test tests::test_is_even ... ok

test result: ok. 2 passed; 0 failed

Cleanup

bash
cd ..
bash
rm -rf rust-practice

You now have the fundamentals. To go deeper, work through the official Rust Book or practice with Rustlings. The real learning happens on Stratorys projects - read existing code, ask questions, and submit PRs.