#struct-fields #field-access #proc-macro

name-index

Library for accessing struct fields by name at runtime

3 unstable releases

0.2.1 Sep 12, 2025
0.2.0 Sep 2, 2025
0.1.0 Aug 27, 2025

#669 in Procedural macros

Download history

126 downloads per month

MIT license

13KB

name-index

Library for accessing struct fields by name at runtime

Example:

use name_index::NameIndex;

#[derive(Default, NameIndex)]
struct MyStruct {
    // The #[index] attributes tells the derive macro to
    // start indexing all u32 fields from here on
    #[index]
    first: u32,
    second: u32,
    third: u32,
}

fn main() {
    let mut my_struct = MyStruct::default();

    // The name of the field we want to index
    // Might come from user input for example
    let name = "second";

    // Use NameIndex::get_ref_mut to get a mutable
    // reference to our field
    let field_ref: &mut u32 =
        NameIndex::get_ref_mut(&mut my_struct, name)
        .expect("second is a field of MyStruct");

    *field_ref = 5;

    assert_eq!(my_struct.second, 5);
}

lib.rs:

Dynamic struct field indexing library

name-index implements functionality to allow users to dynamically access the fields of realitively-homogenous structs by name at runtime.

This functionality may prove useful for problems where fixed key-value pairs are mapped as fields of a struct (for example to aid performance and allow compile-time type checking) but which need to be accessed sparingly at runtime by their respective name.

The lookup functionality is not optimized for performance. In cases where this lookup is frequently used, it is likely better to use alternatives like std::collections::HashMap.

Example

use name_index::NameIndex;

#[derive(Default, NameIndex)]
struct MyStruct {
    // The #[index] attributes tells the derive macro to
    // start indexing all u32 fields from here on
    #[index]
    first: u32,
    second: u32,
    third: u32,
}

fn main() {
    let mut my_struct = MyStruct::default();

    // The name of the field we want to index
    // Might come from user input for example
    let name = "second";

    // Use NameIndex::get_ref_mut to get a mutable
    // reference to our field
    let field_ref: &mut u32 =
        NameIndex::get_ref_mut(&mut my_struct, name)
        .expect("second is a field of MyStruct");

    *field_ref = 5;

    assert_eq!(my_struct.second, 5);
}

For the previous example the [NameIndex] derive creates the following (simplified[^simpl]) code:

impl NameIndex<u32> for MyStruct {
    fn get_ref_mut(&mut self, name: &str) -> Option<&mut u32> {
        match name {
            "first" => Some(&mut self.first),
            "second" => Some(&mut self.second),
            "third" => Some(&mut self.third),
            _ => None,
        }
    }
    // -- snip --
    # fn get_ref(&self, name: &str) -> Option<&u32> {unimplemented!()}
    # fn fields(&self) -> Vec<Field<u32>> {unimplemented!()}
    # fn fields_mut(&mut self) -> Vec<FieldMut<u32>> {unimplemented!()}
    # fn field_aliases(&self, name: &str) -> Vec<&'static str>
    #     {unimplemented!()}
    # fn resolve_alias(&self, name: &str) -> Option<&'static str>
    #     {unimplemented!()}
}

Second Example

This example is supposed to illustrate how [NameIndexCopy] can be used to save some redundant typing when the generic type of [NameIndex] implements std::marker::Copy.

use name_index::{NameIndex, NameIndexCopy};

#[derive(NameIndex)]
struct MyStruct {
    // When no `#[index]` attribute is given, the first field is
    // automatically chosen as the reference.
    first: u32,
    second: u32,
    third: u32,
}

fn main() {
    let mut my_struct = MyStruct {
        first: 1,
        second: 2,
        third: 3,
    };

    // We can use NameIndexCopy<u32> here because NameIndexCopy<T>
    // is automatically implemented for NameIndex<T> when T: Copy

    // Get the value of my_struct.third
    let val: u32 = NameIndexCopy::get(&my_struct, "third")
        .expect("'third' is a field of MyStruct");

    assert_eq!(val, my_struct.third);

    // Set the value of my_struct.first to 7
    NameIndexCopy::set(&mut my_struct, "first", 7)
        .expect("'first' is a field of MyStruct");

    assert_eq!(my_struct.first, 7);
}

[^simpl]: Only the NameIndex::get_ref_mut function is implemented here for clarity.

Dependencies

~110–475KB
~11K SLoC