Using reflection to enumerate through the fields of a struct at runtime
Asked Answered
L

3

1

If I have a data structure like this:

struct Point {
    x: i32,
    y: i32,
}

impl Point {
    fn setX(&mut self, x: i32) -> &mut Point {
        self.x = x;
        self
    }
}

Is it possible to iterate through Point and see both each member and the name of each member?

Is it also possible to go through the implementation and see what each function's name is?

Is it possible to do the above two tasks at runtime, without special implementations?

Lignocellulose answered 22/5, 2015 at 22:56 Comment(3)
FYI what you're trying to do usually goes under the term "reflection".Phobia
@delnan Is there a better I could phrase my title / post?Lignocellulose
I would just use pub struct fields. And perhaps a tuple struct.Mildamilde
S
3

In fact, there is a way to (ab)use Encodable or Serialize traits to obtain reflection-like information about structure contents (not methods, though).

Encodable/Serialize are used primarily for writing a structure to some serialized representation, e.g. a JSON object. Their implementations can be automatically generated (e.g. with #[derive(RustcEncodable)] for Encodable) for any structure whose contents also implement corresponding trait.

Implementations of these traits capture information about the structure and they pass it to an implementation of Encoder or Serializer. Implementors of the latter traits usually use this information (field names, types and values) to serialize objects but of course you can write your own implementation of Encoder/Serializer which will do with this information whatever you want. I'm not providing an example of such implementation here because they tend to be boilerplate-y, but you can find some through the links above.

The limitation is that you always need a value of a structure in order to get information about fields. You can't just get a list of fields of an arbitrary type, like e.g. Java reflection allows. I think it is possible to write an internally unsafe implementation of Encoder/Serializer and a function like fn type_info<T: Encodable>() -> TypeInfo which collects information about a type by creating an uninitialized piece of memory of the corresponding type and running its Encodable methods, but I'm not 100% sure about this.

Savoirfaire answered 23/5, 2015 at 7:49 Comment(1)
To clarify why Rust can't accomplish the same thing for methods: Rust does not have a virtual machine counter-part like Java or C#. It is only compiled to assembly, and doesn't have type information stored with objects when they're created.Davin
T
3

You can accomplish the first thing (iterating over the fields) with my crate fields-iter:

#[derive(fields_iter::FieldsInspect)]
struct Point {
    x: i32,
    y: i32,
}

for (name, value) in fields_iter::FieldsIter::new(&point) {
    // Do something with it.
}
Turban answered 24/11, 2022 at 11:25 Comment(0)
E
2

Rust does not really support this kind of reflection at runtime, no.

In theory, you might be able to write a syntax extension that would let you generate some code that would do something like this, maybe...

Elianaelianora answered 22/5, 2015 at 23:4 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.