Get fields of type struct in a macro

I was wondering if there is a way to get the structure field names in the macro. Consider the following example:

struct S { a: String, b: String } 

and the macro my_macro , which is called as follows:

 my_macro!(S); 

Now I want to access the structure field names, something like this:

 macro_rules! my_macro { ($t:ty) => { { let field_names = get_field_names($t); // do something with field_names } } } 

I'm new to Rust and macros, so maybe I'm missing something obvious.

+7
rust
source share
2 answers

A macro expands during parsing, more or less; he doesnโ€™t have access to AST or anything like that - all he has access to is the stuff that you tell him that for my_macro!(S) pure that there must be a type named S

If you define a structure as part of a macro, you can find out about the fields:

 macro_rules! my_macro { (struct $name:ident { $($field_name:ident: $field_type:ty,)* }) => { struct $name { $($field_name: $field_type,)* } impl $name { // This is purely an exampleโ€”not a good one. fn get_field_names() -> Vec<&'static str> { vec![$(stringify!($field_name)),*] } } } } my_macro! { struct S { a: String, b: String, } } // S::get_field_names() == vec!["a", "b"] 

... but this, although potentially useful, will often be a dubious affair.

+11
source share

Here is another feature that does not require a macro record (however field names will be resolved at runtime):

 extern crate rustc_serialize; use rustc_serialize::json::{Encoder, Json}; use rustc_serialize::json::Json::Object; use rustc_serialize::Encodable; #[derive(Default, RustcEncodable)] struct S { a: String, b: String, } fn main() { let mut json = "".to_owned(); { let mut encoder = Encoder::new(&mut json); S::default().encode(&mut encoder).unwrap(); } let json = Json::from_str(&json).unwrap(); if let Object(object) = json { let field_names: Vec<_> = object.keys().collect(); println!("{:?}", field_names); } } 

(for this solution you need a rustc-serialize box)

derive(Default) added to avoid the need to manually create the structure as you wish (but the structure will still be created).

This solution works by encoding a structure in String format in JSON format and decoding it to Json . From the Json object Json we can extract the field names (if it is a variant of Object ).

Perhaps a more efficient way is to create your own encoder:

 struct FieldNames { names: Vec<String>, } impl FieldNames { fn new() -> FieldNames { FieldNames { names: vec![], } } } struct FieldsEncoder<'a> { fields: &'a mut FieldNames, } impl<'a> FieldsEncoder<'a> { fn new(fields: &mut FieldNames) -> FieldsEncoder { FieldsEncoder { fields: fields, } } } type EncoderError = (); impl<'a> Encoder for FieldsEncoder<'a> { fn emit_struct<F>(&mut self, _name: &str, _len: usize, f: F) -> Result<(), Self::Error> where F: FnOnce(&mut Self) -> Result<(), Self::Error> { f(self) } fn emit_struct_field<F>(&mut self, f_name: &str, _f_idx: usize, _f: F) -> Result<(), Self::Error> where F: FnOnce(&mut Self) -> Result<(), Self::Error> { self.fields.names.push(f_name.to_owned()); Ok(()) } type Error = EncoderError; fn emit_nil(&mut self) -> Result<(), Self::Error> { Err(()) } fn emit_usize(&mut self, _v: usize) -> Result<(), Self::Error> { Err(()) } fn emit_u64(&mut self, _v: u64) -> Result<(), Self::Error> { Err(()) } fn emit_u32(&mut self, _v: u32) -> Result<(), Self::Error> { Err(()) } fn emit_u16(&mut self, _v: u16) -> Result<(), Self::Error> { Err(()) } fn emit_u8(&mut self, _v: u8) -> Result<(), Self::Error> { Err(()) } fn emit_isize(&mut self, _v: isize) -> Result<(), Self::Error> { Err(()) } fn emit_i64(&mut self, _v: i64) -> Result<(), Self::Error> { Err(()) } fn emit_i32(&mut self, _v: i32) -> Result<(), Self::Error> { Err(()) } fn emit_i16(&mut self, _v: i16) -> Result<(), Self::Error> { Err(()) } fn emit_i8(&mut self, _v: i8) -> Result<(), Self::Error> { Err(()) } fn emit_bool(&mut self, _v: bool) -> Result<(), Self::Error> { Err(()) } fn emit_f64(&mut self, _v: f64) -> Result<(), Self::Error> { Err(()) } fn emit_f32(&mut self, _v: f32) -> Result<(), Self::Error> { Err(()) } fn emit_char(&mut self, _v: char) -> Result<(), Self::Error> { Err(()) } fn emit_str(&mut self, _v: &str) -> Result<(), Self::Error> { Err(()) } fn emit_enum<F>(&mut self, _name: &str, _f: F) -> Result<(), Self::Error> where F: FnOnce(&mut Self) -> Result<(), Self::Error> { Err(()) } fn emit_enum_variant<F>(&mut self, _v_name: &str, _v_id: usize, _len: usize, _f: F) -> Result<(), Self::Error> where F: FnOnce(&mut Self) -> Result<(), Self::Error> { Err(()) } fn emit_enum_variant_arg<F>(&mut self, _a_idx: usize, _f: F) -> Result<(), Self::Error> where F: FnOnce(&mut Self) -> Result<(), Self::Error> { Err(()) } fn emit_enum_struct_variant<F>(&mut self, _v_name: &str, _v_id: usize, _len: usize, _f: F) -> Result<(), Self::Error> where F: FnOnce(&mut Self) -> Result<(), Self::Error> { Err(()) } fn emit_enum_struct_variant_field<F>(&mut self, _f_name: &str, _f_idx: usize, _f: F) -> Result<(), Self::Error> where F: FnOnce(&mut Self) -> Result<(), Self::Error> { Err(()) } fn emit_tuple<F>(&mut self, _len: usize, _f: F) -> Result<(), Self::Error> where F: FnOnce(&mut Self) -> Result<(), Self::Error> { Err(()) } fn emit_tuple_arg<F>(&mut self, _idx: usize, _f: F) -> Result<(), Self::Error> where F: FnOnce(&mut Self) -> Result<(), Self::Error> { Err(()) } fn emit_tuple_struct<F>(&mut self, _name: &str, _len: usize, _f: F) -> Result<(), Self::Error> where F: FnOnce(&mut Self) -> Result<(), Self::Error> { Err(()) } fn emit_tuple_struct_arg<F>(&mut self, _f_idx: usize, _f: F) -> Result<(), Self::Error> where F: FnOnce(&mut Self) -> Result<(), Self::Error> { Err(()) } fn emit_option<F>(&mut self, _f: F) -> Result<(), Self::Error> where F: FnOnce(&mut Self) -> Result<(), Self::Error> { Err(()) } fn emit_option_none(&mut self) -> Result<(), Self::Error> { Err(()) } fn emit_option_some<F>(&mut self, _f: F) -> Result<(), Self::Error> where F: FnOnce(&mut Self) -> Result<(), Self::Error> { Err(()) } fn emit_seq<F>(&mut self, _len: usize, _f: F) -> Result<(), Self::Error> where F: FnOnce(&mut Self) -> Result<(), Self::Error> { Err(()) } fn emit_seq_elt<F>(&mut self, _idx: usize, _f: F) -> Result<(), Self::Error> where F: FnOnce(&mut Self) -> Result<(), Self::Error> { Err(()) } fn emit_map<F>(&mut self, _len: usize, _f: F) -> Result<(), Self::Error> where F: FnOnce(&mut Self) -> Result<(), Self::Error> { Err(()) } fn emit_map_elt_key<F>(&mut self, _idx: usize, _f: F) -> Result<(), Self::Error> where F: FnOnce(&mut Self) -> Result<(), Self::Error> { Err(()) } fn emit_map_elt_val<F>(&mut self, _idx: usize, _f: F) -> Result<(), Self::Error> where F: FnOnce(&mut Self) -> Result<(), Self::Error> { Err(()) } } 

which can be used as such:

 fn main() { let mut fields = FieldNames::new(); { let mut encoder = FieldsEncoder::new(&mut fields); S::default().encode(&mut encoder).unwrap(); } println!("{:?}", fields.names); } 
+2
source share

All Articles