Home Wiki Programming & Logic Structs and Enums in Rust: Modeling Factory Data
Programming & Logic

Structs and Enums in Rust: Modeling Factory Data

Structs: Custom Data Types

In industrial software, we constantly model real-world objects: sensors, machines, alarms. Rust structs let us group related data into a single, meaningful type.

// A temperature sensor on a production line
struct TemperatureSensor {
    id: u32,
    location: String,
    current_reading: f64, // in Celsius
    is_active: bool,
}

fn main() {
    let sensor = TemperatureSensor {
        id: 101,
        location: String::from("Furnace Zone A"),
        current_reading: 482.5,
        is_active: true,
    };

    println!("Sensor {} at {}: {}°C", sensor.id, sensor.location, sensor.current_reading);
}

Each field has a name and a type. You access fields with dot notation like sensor.id.

impl Blocks: Adding Behavior

Structs hold data, but impl blocks attach functions (methods) to them.

struct PressureGauge {
    max_pressure: f64, // bar
    current_pressure: f64,
}

impl PressureGauge {
    // Associated function (constructor) - no &self
    fn new(max_pressure: f64) -> Self {
        PressureGauge {
            max_pressure,
            current_pressure: 0.0,
        }
    }

    // Method - takes &self to read data
    fn is_over_limit(&self) -> bool {
        self.current_pressure > self.max_pressure
    }

    // Method - takes &mut self to modify data
    fn update_reading(&mut self, value: f64) {
        self.current_pressure = value;
    }
}

fn main() {
    let mut gauge = PressureGauge::new(10.0);
    gauge.update_reading(12.3);

    if gauge.is_over_limit() {
        println!("WARNING: Pressure exceeds maximum!");
    }
}

Tuple Structs and Unit Structs

Tuple structs have fields without names. They are useful for creating distinct types from simple values. Unit structs have no fields at all.

// Tuple structs - distinct types wrapping values
struct Millimeters(f64);
struct Celsius(f64);

// Unit struct - used as a marker or signal
struct EmergencyStop;

fn calibrate_thickness(reading: Millimeters) {
    println!("Thickness: {} mm", reading.0); // access by index
}

fn main() {
    let thickness = Millimeters(2.45);
    let temp = Celsius(95.0);
    calibrate_thickness(thickness);
    // calibrate_thickness(temp); // Compile error! Different type.
}

Enums: Types with Variants

An enum defines a type that can be one of several variants. This is perfect for states, modes, or categories in industrial systems.

enum MachineState {
    Idle,
    Running,
    Maintenance,
    Faulted,
}

fn describe_state(state: &MachineState) {
    match state {
        MachineState::Idle => println!("Machine is idle"),
        MachineState::Running => println!("Machine is running"),
        MachineState::Maintenance => println!("Under maintenance"),
        MachineState::Faulted => println!("FAULT detected"),
    }
}

Enums with Data: Rust's Power Feature

Unlike many languages, Rust enum variants can carry data. Each variant can hold different types and amounts of data.

enum SensorReading {
    Temperature(f64),              // single value
    Vibration { x: f64, y: f64 },  // named fields
    Offline,                       // no data
    Error(u32, String),            // multiple values
}

fn log_reading(reading: &SensorReading) {
    match reading {
        SensorReading::Temperature(t) => println!("Temp: {t}°C"),
        SensorReading::Vibration { x, y } => println!("Vibration: x={x}, y={y}"),
        SensorReading::Offline => println!("Sensor offline"),
        SensorReading::Error(code, msg) => println!("Error {code}: {msg}"),
    }
}

match with Enums: Exhaustive Handling

Rust's match forces you to handle every variant. The compiler will reject code that misses a case, preventing bugs before they reach production.

enum ConveyorSpeed {
    Stop,
    Slow,
    Normal,
    Fast,
}

fn get_rpm(speed: &ConveyorSpeed) -> u32 {
    match speed {
        ConveyorSpeed::Stop => 0,
        ConveyorSpeed::Slow => 200,
        ConveyorSpeed::Normal => 600,
        ConveyorSpeed::Fast => 1200,
    }
    // Removing any arm causes a compile error!
}

You can also use _ as a wildcard to catch all remaining variants.

Practical Example: Factory Alarm System

Combining structs and enums to build a factory alarm model:

enum AlarmSeverity {
    Info,
    Warning,
    Critical,
}

enum AlarmSource {
    Sensor(u32),
    Machine(String),
    ProductionLine(u8),
}

struct Alarm {
    severity: AlarmSeverity,
    source: AlarmSource,
    message: String,
}

impl Alarm {
    fn should_stop_line(&self) -> bool {
        matches!(self.severity, AlarmSeverity::Critical)
    }

    fn display(&self) {
        let level = match &self.severity {
            AlarmSeverity::Info => "INFO",
            AlarmSeverity::Warning => "WARN",
            AlarmSeverity::Critical => "CRIT",
        };
        let origin = match &self.source {
            AlarmSource::Sensor(id) => format!("Sensor #{id}"),
            AlarmSource::Machine(name) => format!("Machine: {name}"),
            AlarmSource::ProductionLine(n) => format!("Line {n}"),
        };
        println!("[{level}] {origin} - {}", self.message);
    }
}

fn main() {
    let alarm = Alarm {
        severity: AlarmSeverity::Critical,
        source: AlarmSource::Machine(String::from("CNC-07")),
        message: String::from("Spindle overheated"),
    };

    alarm.display();
    if alarm.should_stop_line() {
        println!(">>> STOPPING PRODUCTION LINE <<<");
    }
}

Summary

  • Structs group related fields into custom types that model real-world objects.
  • impl blocks attach methods and constructors to structs.
  • Tuple structs create distinct types from simple values; unit structs carry no data.
  • Enums define types with multiple variants, each optionally carrying data.
  • match ensures every variant is handled, eliminating forgotten cases at compile time.
  • Combining structs and enums is the foundation for modeling industrial systems in Rust.
struct enum impl methods tuple-struct associated-functions الهياكل التعدادات الأساليب نمذجة البيانات أنواع مخصصة بنية البيانات