I have a structure of heterogenous data:
struct Data {
a: i16, // index "0"
b: i32, // index "1"
c: u8, // index "2"
}
Is there a good way to create an "access table" (can be done at compile time with a build tool) which allows me to access references to the underlying data by index rather than field name? The data will be a nested struct of non-homogenous data (u8, i8, u16, i16, etc). The "indexs" are basically the number corresponding to each item of the nested struct were flattened.
The application is for schema-based communication. We have a run-time database consisting of a static hierarchical struct and a lightweight communication protocol for reading and writing to the run-time database using power-line communication. Due to bandwidth limitations, we use a schema system where we access the structure by index rather than name.
#################### UPDATE (My Solution) ########################
Thanks to those who provided the links below. They helped give me ideas but were not perfect fits to my problem. A little bit more background first, this is a rather large hierarchical struct with around 1000 "items". Each "item" is going to be primitive type of u8, i8, u16, i16, u32, i32, u64, i64, or char. We treat this struct as like a run-time database for shared resources between embedded applications running on an ARM M4.
We have a protocol specification for reading/writing 1 or several values of this runtime database over UART and over our own Powerline Communication modem. For bandwidth reasons, we create a schema system similar to protobuf for accessing individual items by index rather than name. In our C implementation, we have a Python library that generates an "Access Table" at compile time. This "Access Table" contains fixed size array of structs, where each struct contains access info including pointer address and number the size of the item. We then have an access function that is able to fill a buffer with the raw contents of the data using a memcopy. It is important that the access table use pointers, as the application has access to this runtime database and is making changes to the values as the application runs.
Since we only have 9 different variants for the "items" the solution I came up with was to simply encapsulate each item in an Enum. Here is a syntactically correct (tested) implementation. I can then use pattern matching to fill my buffer in the protocol code. I am curious what more experienced Rustaceans think of this solution.
// This is the runtime database struct
#[derive(Debug)]
struct Data {
a: i32,
b: u8
}
#[derive(Debug)]
enum Item<'a> {
U8(&'a u8),
I8(&'a i8),
U16(&'a u16),
I16(&'a i16),
U32(&'a u32),
I32(&'a i32),
U64(&'a u64),
I64(&'a i64)
}
fn main() {
// initialize the data in the runtime database
let data = Data{a:2001, b:42};
// this "access table" generated by Python script at compile time
// allows indexed access to the data by reference
let table: [Item; 2] = [Item::I32(&data.a),
Item::U8(&data.b)];
let item:&Item = &table[1];
println!("Struct data => {:?}", data);
println!("The second value of the struct is {:?}", item);
}