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
126 downloads per month
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