RSS

Posts Tagged ‘Rust’

Getting Started with Rust – Variables, Functions and Loops

Wednesday, October 15th, 2025

Getting Started with Rust (Week One) Banner

With the tools installed it is time to start learning some language basics:

  • Variables
  • Functions
  • Control structures (if and loops)

The above are covered in the first three chapters of The Rust Programming Language.

Installing the Tools (Update)

Installation of the tools went pretty smoothly and took only a few hours. The Rust in Visual Studio Code page proved to be a nice addition to the links in the blog post.

The page provides information on:

  • Intellisense
  • Linting
  • Refactoring
  • Debugging

plus more.

The Rust Programming Language (Chapters 1 through 3)

The initial chapters of the The Rust Programming Language covers the basics of Rust:

  • Variables
  • Immutability and mutability
  • Functions
  • Control flow

It was interesting to discover that Rust has a greater degree of distinction between expressions and statements:

Function bodies are made up of a series of statements optionally ending in an expression. So far, the functions we’ve covered haven’t included an ending expression, but you have seen an expression as part of a statement. Because Rust is an expression-based language, this is an important distinction to understand. Other languages don’t have the same distinctions, so let’s look at what statements and expressions are and how their differences affect the bodies of functions.

This difference means that there is no analogy to the following C code:

int x, y;
x = y = 1024;

The basic rule is statements perform actions and expressions return a result. So functions that return a result must return an expression. The general rule being that a statement also ends with a semicolon and an expression does not need one.

Now consider this simple (and admittedly contrived example):

fn add_or_multiply(value : i32) -> i32 {
    if value > 5 {
        return value * 2;
    }
    //  Maybe do some other stuff...
    value + 1
}

fn main() {
    for number in 0..10 {
        let result = add_or_multiply(number);
        println!("Number: {number}, Result: {result}");
    }
}

Running the above generates the following output:

     Running `target/debug/hello_world`
Number: 0, Result: 1
Number: 1, Result: 2
Number: 2, Result: 3
Number: 3, Result: 4
Number: 4, Result: 5
Number: 5, Result: 6
Number: 6, Result: 12
Number: 7, Result: 14
Number: 8, Result: 16
Number: 9, Result: 18

The line return value * 2; can be changed to:

return value * 2

Note the semicolon has been removed. Running the resultant application also generates the same output. Further investigation is required to determine why this works and also what is considered best practice amongst the Rust community.

Language Highlights

From a C/C++ programmers perspective, two Rust constructs are appealing due to their convenience and ability to make code tidier:

  • Using if statements in assignments
  • Labelled loops

The first construct is alien to the C/C++ developer but should be familiar to Python developers. This is the ability to use an if statement in an assignment operation:

let x = if y <= MAXIMUM { MAXIMUM } else { y };

This means the trivial function add_or_multiply in the above application could have been written as:

const MAXIMUM: i32  = 5;

fn add_or_multiply(value : i32) -> i32 {
    let result = if value > MAXIMUM { value * 2 } else { value + 1 };
    result
}

Nice little feature that can make code more compact and readable.

The second nice feature is the ability to label loops. This allows the application to break in an inner loop to also break an outer loop.

'outer_loop: loop {
    //  Setup for the inner loop...
    loop {
        if remaining == MAXIMUM {
            break;
        }
        if (count % 2) == 0 {
            break 'outer_loop;  // Ignore even numbers.
        }
        // More inner loop processing...
    }
    // More outer loop processing...
}

The inner loop may be a contrived version of a while loop but it serves to illustrate the language feature. The break ‘outer_loop allows the inner loop to skip even numbers without the need run unnecessary nested if statements.

Conclusion

A slow start but some interesting language features:

  • Immutability by default
  • Using if statements in assignments
  • Labelled loops

Next up is ownership.

Rust – Installing the Tools

Sunday, October 5th, 2025

Bacon running in a terminal

This week was a gentle start with Rust just installing the toolchain and some browsing for possibly useful tools.

Installing Rust

First step, install the compiler so lets head over to the Getting Started page. According to the page we just need to execute the command:

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

Which generates the following output:

info: downloading installer

Welcome to Rust!

This will download and install the official compiler for the Rust
programming language, and its package manager, Cargo.

Rustup metadata and toolchains will be installed into the Rustup
home directory, located at:

  /home/tester/.rustup

This can be modified with the RUSTUP_HOME environment variable.

The Cargo home directory is located at:

  /home/tester/.cargo

This can be modified with the CARGO_HOME environment variable.

The cargo, rustc, rustup and other commands will be added to
Cargo's bin directory, located at:

  /home/tester/.cargo/bin

This path will then be added to your PATH environment variable by
modifying the profile files located at:

  /home/tester/.profile
  /home/tester/.bashrc
  /home/tester/.zshenv

You can uninstall at any time with rustup self uninstall and
these changes will be reverted.

Current installation options:


   default host triple: aarch64-unknown-linux-gnu
     default toolchain: stable (default)
               profile: default
  modify PATH variable: yes

1) Proceed with standard installation (default - just press enter)
2) Customize installation
3) Cancel installation
>

Lets go with option 1, the default install:

info: profile set to 'default'
info: default host triple is aarch64-unknown-linux-gnu
info: syncing channel updates for 'stable-aarch64-unknown-linux-gnu'
info: latest update on 2025-09-18, rust version 1.90.0 (1159e78c4 2025-09-14)
info: downloading component 'cargo'
info: downloading component 'clippy'
info: downloading component 'rust-docs'
info: downloading component 'rust-std'
info: downloading component 'rustc'
info: downloading component 'rustfmt'
info: installing component 'cargo'
info: installing component 'clippy'
info: installing component 'rust-docs'
 20.5 MiB /  20.5 MiB (100 %)   8.3 MiB/s in  2s         
info: installing component 'rust-std'
 29.1 MiB /  29.1 MiB (100 %)  14.0 MiB/s in  2s         
info: installing component 'rustc'
 58.5 MiB /  58.5 MiB (100 %)  14.1 MiB/s in  4s         
info: installing component 'rustfmt'
info: default toolchain set to 'stable-aarch64-unknown-linux-gnu'

  stable-aarch64-unknown-linux-gnu installed - rustc 1.90.0 (1159e78c4 2025-09-14)


Rust is installed now. Great!

To get started you may need to restart your current shell.
This would reload your PATH environment variable to include
Cargo's bin directory ($HOME/.cargo/bin).

To configure your current shell, you need to source
the corresponding env file under $HOME/.cargo.

This is usually done by running one of the following (note the leading DOT):
. "$HOME/.cargo/env"            # For sh/bash/zsh/ash/dash/pdksh
source "$HOME/.cargo/env.fish"  # For fish
source $"($nu.home-path)/.cargo/env.nu"  # For nushell

Following the instructions to add rust to the PATH:

. "$HOME/.cargo/env"

Checking that the compiler has been installed:

$ rustup
rustup 1.28.2 (e4f3ad6f8 2025-04-28)

First Application – Hello, World

The classic way to test a new toolchain is to write Hello, world. The cargo build system has a simple way to do this:

cargo new hello_world

    Creating binary (application) `hello_world` package
note: see more `Cargo.toml` keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

cargo should have created a new directory with the name hello_world along with any necessary support files for a Rust project, including default git files.

cd hello_world
total 16
drwxr-xr-x 5 tester tester 4.0K Oct  1 10:11 .
drwxr-xr-x 3 tester tester 4.0K Oct  1 10:10 ..
-rw-r--r-- 1 tester tester   82 Oct  1 10:10 Cargo.toml
drwxr-xr-x 6 tester tester 4.0K Oct  1 10:11 .git
-rw-r--r-- 1 tester tester    8 Oct  1 10:10 .gitignore
drwxr-xr-x 2 tester tester 4.0K Oct  1 10:10 src

The source file for the project is in the src directory with the entry point to the application in the src/main.rs file:

cat < src/main.rs

fn main() {
    println!("Hello, world!");
}

The application can be run with the cargo run command:

cargo run

   Compiling hello_world v0.1.0 (/home/tester/Rust101/hello_world)
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.24s
     Running `target/debug/hello_world`
Hello, world!

Supplementary Tools

A little web browsing highlighted a couple of tools that might prove useful:

  • Bacon – Background Analyser
  • Visual Studio Code Extension – rust-analyzer

Let’s install these tools.

Bacon – Background Analyser

Bacon runs in a terminal and it scans the file system for any changes. It then runs cargo and checks the project source code for any errors. These are then displayed in the terminal. This means that the developer gets fast feedback of any issues throughout the development cycle.

Installation is simple:

cargo install --locked bacon

To run the application simply open a new terminal and run the command:

bacon --all-features

Visual Studio Code: rust-analyzer

Rust-analyzer is a popular extension for Visual Studio Code providing features such as:

  • Syntax highlighting
  • Code completion
  • Hints when hovering over variables, types etc.
  • Goto definition

The extension can be installed from the Visual Studio Marketplace or through Visual Studio Code itself.

Project

The best way to learn a new language is to reproduce an application / project that you have developed. This makes writing the application a little simpler as the problem is already understood, the only new element to the project is the new language.

  • Command line application
  • Process the command line
  • Using a directory passed through the command line, generate a list of all files in the directory
  • If a directory is found add to a list and recurse through the directory structure list all the files found

Short, simple problem maybe but it should be enough to get started.

Getting Started with Rust

Wednesday, October 1st, 2025

Rusty Bolts

Last year saw the push towards using safer programming languages. Languages such as C# and Rust, languages that help the developer avoid mistakes common to C and C++ (although there is a movement to make C++ safer to use).

It is time to take a look at Rust as a language and more specifically how easy it is to develop code that will run on a micrcontroller.

General Rust

The usual place to start is the The Rust Programming Language (Rust 2021) book.

There are also a number of online resources:

Only time will tell how good these resources are.

Microcontroller Specific

Initial learning will be laptop based as it will be easier to gain familiarity with the language. It will certainly be quicker than the usual develop, deploy and debug cycle that slows down firmware development.

The eventual aim is to move over to development for microcontrollers, likely the ESP32 variants or Raspberry Pi Pico boards. With this in mind the following Rust and micrcontroller resources are looking like they will be useful:

The microcontroller part of the journey will look at using the ESP32C6 microcontroller as this is on the supported list for both the bare metal and IDF versions of the HALL (see below).

ESP Hardware Abstraction Layer (HAL)

Espressif have released two versions of the HAL one supporting the IDF framework and one for bare metal applications:

Installation and use is covered in the Rust on the ESP Book.

Let’s get started and see where this takes us.