Repository: bevyengine/bevy
File: crates/bevy_reflect/src/structs.rs (Rust)

Code before:
///
/// [struct-like]: https://doc.rust-lang.org/book/ch05-01-defining-structs.html
/// [reflection]: crate
/// [unit structs]: https://doc.rust-lang.org/book/ch05-01-defining-structs.html#unit-like-structs-without-any-fields
pub trait Struct: PartialReflect {
    /// Gets a reference to the value of the field named `name` as a `&dyn
    /// PartialReflect`.
    fn field(&self, name: &str) -> Option<&dyn PartialReflect>;

    /// Gets a mutable reference to the value of the field named `name` as a
    /// `&mut dyn PartialReflect`.
    fn field_mut(&mut self, name: &str) -> Option<&mut dyn PartialReflect>;

    /// Gets a reference to the value of the field with index `index` as a
    /// `&dyn PartialReflect`.
    fn field_at(&self, index: usize) -> Option<&dyn PartialReflect>;

    /// Gets a mutable reference to the value of the field with index `index`
    /// as a `&mut dyn PartialReflect`.
    fn field_at_mut(&mut self, index: usize) -> Option<&mut dyn PartialReflect>;

    /// Gets the name of the field with index `index`.
    fn name_at(&self, index: usize) -> Option<&str>;

    /// Gets the name of the field, if it exists.
    fn name_of(&self, field: &dyn PartialReflect) -> Option<&str>;

    /// Gets the index of the field
    fn index_of(&self, value: &dyn PartialReflect) -> Option<usize>;

    /// Gets the index of the field with the given name.
    fn index_of_name(&self, name: &str) -> Option<usize>;

    /// Returns the number of fields in the struct.
    fn field_len(&self) -> usize;

    /// Returns an iterator over the values of the reflectable fields for this struct.
    fn iter_fields(&self) -> FieldIter<'_>;

    /// Creates a new [`DynamicStruct`] from this struct.
    fn to_dynamic_struct(&self) -> DynamicStruct {
        let mut dynamic_struct = DynamicStruct::default();
        dynamic_struct.set_represented_type(self.get_represented_type_info());
        for (name, value) in self.iter_fields() {
            dynamic_struct.insert_boxed(name, value.to_dynamic());
        }
        dynamic_struct
    }

    /// Will return `None` if [`TypeInfo`] is not available.
    fn get_represented_struct_info(&self) -> Option<&'static StructInfo> {

Review comment (suggestion):
We should probably document that this only checks the address of the pointer. And because of this, the method will return `None` if it's given a reference to the same field from a different struct of the same type or if the field is not the original (i.e. it's a clone of the original).

As mentioned in my comment [here](https://github.com/bevyengine/bevy/pull/22702#discussion_r2725961917), I do think that the address equality is a limitation of the current implementation. Therefore, it may not really belong in the documentation (in case users choose to manually implement it another way that can guarantee it works across struct instances and clones). However, the default implementation from the derive macro is going to be the most common, so I think it's definitely worth noting.

Code after:
///
/// [struct-like]: https://doc.rust-lang.org/book/ch05-01-defining-structs.html
/// [reflection]: crate
/// [unit structs]: https://doc.rust-lang.org/book/ch05-01-defining-structs.html#unit-like-structs-without-any-fields
pub trait Struct: PartialReflect {
    /// Gets a reference to the value of the field named `name` as a `&dyn
    /// PartialReflect`.
    fn field(&self, name: &str) -> Option<&dyn PartialReflect>;

    /// Gets a mutable reference to the value of the field named `name` as a
    /// `&mut dyn PartialReflect`.
    fn field_mut(&mut self, name: &str) -> Option<&mut dyn PartialReflect>;

    /// Gets a reference to the value of the field with index `index` as a
    /// `&dyn PartialReflect`.
    fn field_at(&self, index: usize) -> Option<&dyn PartialReflect>;

    /// Gets a mutable reference to the value of the field with index `index`
    /// as a `&mut dyn PartialReflect`.
    fn field_at_mut(&mut self, index: usize) -> Option<&mut dyn PartialReflect>;

    /// Gets the name of the field with index `index`.
    fn name_at(&self, index: usize) -> Option<&str>;

    /// Gets the index of the field with the given name.
    fn index_of_name(&self, name: &str) -> Option<usize>;

    /// Returns the number of fields in the struct.
    fn field_len(&self) -> usize;

    /// Returns an iterator over the values of the reflectable fields for this struct.
    fn iter_fields(&self) -> FieldIter<'_>;

    /// Creates a new [`DynamicStruct`] from this struct.
    fn to_dynamic_struct(&self) -> DynamicStruct {
        let mut dynamic_struct = DynamicStruct::default();
        dynamic_struct.set_represented_type(self.get_represented_type_info());
        for (name, value) in self.iter_fields() {
            dynamic_struct.insert_boxed(name, value.to_dynamic());
        }
        dynamic_struct
    }

    /// Will return `None` if [`TypeInfo`] is not available.
    fn get_represented_struct_info(&self) -> Option<&'static StructInfo> {
        self.get_represented_type_info()?.as_struct().ok()
    }
}

impl<'a> IntoIterator for &'a dyn Struct {
    type Item = (&'a str, &'a dyn PartialReflect);