I’ve been wondering how to implement a clean XDR codec in Rust. The thing that’s been vexing me is how to map from a Rust enum into an XDR switch - specifically, how to represent the mapping to an XDR enum (which is simply a symbolic name for an int, like in C).
Go has the concept of “tags” for structure fields, which is useful for adding metadata. Rust’s attribute mechanism seems to be a way of achieving something similar.
For example:
enum Thing {
// associate a static str with an enum field
#[tag("xdr: enum=44")]
Foo(u32),
#[tag("xdr: enum=33")]
Bar(String),
}
Go makes the tags visible at runtime via its reflection interface, but as Rust doesn’t have reflection it would need some other mechanism. I don’t see any precedents for something analogous, but I guess its a little like sizeof (ie, querying a compile-time attribute of a type), so it would be exposed as a compiler intrinsic function with a signature something like: … well, I don’t know what it would look like. I can’t think of a way of referring to a field except by name. This, maybe?
// Get a tag for a field of type T
fn get_tag<T>(field: &str) -> Option<&'static str>
Even assuming this is a reasonable way to solve the problem, I’m not sure what its full semantics are. Should it be defined for all types T, or just struct/enum? What if the field doesn’t exist - it would be annoying to have a runtime error, or a silent failure because the field no longer exists, was typoed, or renamed.
Maybe I’m barking up the wrong tree with this. Perhaps it would be better to define an auxillary trait for Encodable/Decodable that can return extra metadata, and then have a specific Encoder/Decoder call that trait to get info. (Or just add it to Encodable/Decodable.)
Thoughts?