Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.syntblaze.com/llms.txt

Use this file to discover all available pages before exploring further.

A struct (structure) is a user-defined compound data type that aggregates multiple values of potentially different types into a single, cohesive unit. It establishes a custom type signature and memory layout that can be utilized throughout a Rust program.

Struct Variants

Rust provides three distinct structural forms, each with specific syntactic rules and memory characteristics.

1. Named-Field Structs

The standard struct defines explicit identifiers and types for each field.
struct ProcessState {
    pid: u32,
    is_active: bool,
    memory_allocated: u64,
}

2. Tuple Structs

Tuple structs rely on positional indexing rather than named fields. They are defined with a type identifier followed by a parenthesized list of component types. To instantiate a tuple struct, you call it like a function. Its fields are accessed using dot notation with zero-based indices.
struct Checksum(u32, u32, String);

// Instantiation
let c = Checksum(1, 2, String::new());

// Accessing fields via zero-based indices
let primary_hash = c.0;
let secondary_hash = c.1;

3. Unit-Like Structs

Unit-like structs contain no fields and consume zero bytes of memory at runtime. They are typically utilized as marker types or to implement traits on a stateless type.
struct StatelessMarker;

Generics and Lifetimes

Structs can be parameterized with generic types and lifetimes to operate on diverse data types and borrowed data. Generics: Type parameters are declared in angle brackets <T> immediately following the struct identifier.
struct Point<T> {
    x: T,
    y: T,
}
Lifetimes: If a struct holds a reference, Rust’s borrow checker requires explicit lifetime annotations. This is a fundamental rule guaranteeing that the struct instance cannot outlive the data it references. The lifetime parameter (e.g., 'a) is declared in angle brackets and applied to the reference type.
struct BorrowedText<'a> {
    text: &'a str,
}
Multiple generic types and lifetimes can be combined within the same struct definition.
struct ParsedData<'a, T, U> {
    raw_input: &'a str,
    primary_value: T,
    metadata: U,
}

Visibility

By default, structs and their fields are private to the module in which they are defined. To expose a struct or its fields to external modules, the pub visibility modifier must be explicitly applied. A public struct can still encapsulate private fields.
pub struct NetworkConfig {
    pub port: u16,    // Publicly accessible field
    host: String,     // Private to the defining module
}

Instantiation and Mutability

Struct instances are created by specifying the struct identifier and providing values for all defined fields. Standard mutability in Rust is inherited from the variable binding. Individual fields cannot be marked as mutable; the entire instance must be declared with mut to allow field modification.
let mut state = ProcessState {
    pid: 1024,
    is_active: true,
    memory_allocated: 4096,
};

// Modifying a field requires the instance binding to be mutable
state.memory_allocated = 8192;
Interior Mutability: Rust provides an exception to inherited mutability through the concept of interior mutability. By wrapping field types in wrapper types or synchronization primitives like Cell, RefCell, or Mutex, you can mutate specific fields even if the struct instance itself is bound immutably.
use std::cell::Cell;

struct ProcessMonitor {
    pid: u32,
    restart_count: Cell<u32>,
}

let monitor = ProcessMonitor {
    pid: 1024,
    restart_count: Cell::new(0),
};

// Valid modification despite `monitor` being immutable
monitor.restart_count.set(1); 

Initialization Shorthands

Rust provides syntactic sugar to streamline struct initialization. Field Init Shorthand: If a local variable shares the exact identifier as a struct field, the explicit assignment can be omitted.
let pid = 2048;
let is_active = false;

let state = ProcessState {
    pid,       // Equivalent to pid: pid
    is_active, // Equivalent to is_active: is_active
    memory_allocated: 0,
};
Struct Update Syntax: The .. operator allows a new struct instance to inherit the values of remaining fields from an existing instance of the exact same type.
let state_two = ProcessState {
    pid: 4096,
    ..state // Copies `is_active` and `memory_allocated` from `state`
};
Note: Struct update syntax moves data. If the copied fields contain types that do not implement the Copy trait, the original instance will be partially moved and invalidated for those specific fields.

Destructuring and Pattern Matching

Destructuring is the idiomatic method for extracting and binding struct fields to local variables. This is achieved using pattern matching. The .. syntax can be used to ignore remaining fields.
let state = ProcessState {
    pid: 1024,
    is_active: true,
    memory_allocated: 4096,
};

// Destructuring fields into local variables
let ProcessState { pid, is_active, .. } = state;

// `pid` and `is_active` are now bound to 1024 and true, respectively

Implementation Blocks (impl)

Behavior is attached to structs using impl blocks. These blocks encapsulate functions associated with the struct’s type.
impl ProcessState {
    // Associated Function (does not take `self`).
    // Invoked via the path separator: ProcessState::new(1024)
    fn new(pid: u32) -> Self {
        Self {
            pid,
            is_active: true,
            memory_allocated: 0,
        }
    }

    // Method (takes an immutable reference to `self`).
    // Invoked via dot notation: state.allocation_size()
    fn allocation_size(&self) -> u64 {
        self.memory_allocated
    }

    // Mutable Method (takes a mutable reference to `self`).
    fn allocate(&mut self, bytes: u64) {
        self.memory_allocated += bytes;
    }
}

Memory Layout

By default, Rust does not guarantee the memory layout or field ordering of a struct. The compiler (rustc) is permitted to reorder fields to minimize padding and optimize memory alignment. To enforce a deterministic memory layout, such as strict C-compatibility for FFI (Foreign Function Interface), the #[repr(C)] attribute must be applied to the struct definition.
#[repr(C)]
struct FfiCompatibleStruct {
    flag: u8,
    address: u64,
}
Master Rust with Deep Grasping Methodology!Learn More