#How to improve the following code (lifetime wise)

2 messages · Page 1 of 1 (latest)

rain harness
#

Besides lifetimes where I feel like I overcomplicated it, I was wondering if it's possible for Field and FieldMut to be only taken as &Field and &FieldMut, so no need for &mut FieldMut since the internal field is already a mutable reference, but I couldn't immediately figure out the lifetimes and signatures to make it compile

#[test]
fn test_something() {
    pub trait FieldsTuple<'a>: Sized {
        type TupleType<'w>
        where
            Self: 'w;

        fn get_tuple(self) -> Self::TupleType<'a>;
    }

    pub struct Fields<T> {
        pub(crate) _phantom: PhantomData<T>,
    }

    pub struct Field<'a, T> {
        array: &'a [T],
        pub(crate) _phantom: PhantomData<T>,
    }

    pub struct FieldMut<'a, T> {
        pub array: &'a mut [T],
        pub(crate) _phantom: PhantomData<T>,
    }

    pub trait IterableTypeFieldOperation<'a> {
        type ActualType<'w>;

        fn get_data(self) -> Self::ActualType<'a>;
    }

    impl<'a, T: 'static> IterableTypeFieldOperation<'a> for (&'a Field<'a, T>, usize) {
        type ActualType<'w> = &'w T;

        fn get_data(self) -> Self::ActualType<'a> {
            &self.0.array[self.1]
        }
    }
    impl<'a, T: 'static> IterableTypeFieldOperation<'a> for (&'a mut FieldMut<'a, T>, usize) {
        type ActualType<'w> = &'w mut T;

        fn get_data(self) -> Self::ActualType<'a> {
            &mut self.0.array[self.1]
        }
    }

    impl<'a, A, B> FieldsTuple<'a> for (A, B)
    where
        A: IterableTypeFieldOperation<'a> + 'a,
        B: IterableTypeFieldOperation<'a> + 'a,
    {
        type TupleType<'w>
            = (
            <A as IterableTypeFieldOperation<'a>>::ActualType<'a>,
            <B as IterableTypeFieldOperation<'a>>::ActualType<'a>,
        )
        where
            A: 'w,
            B: 'w;

        fn get_tuple(self) -> Self::TupleType<'a> {
            (self.0.get_data(), self.1.get_data())
        }
    }
}
#
    impl<T> Fields<T> {
        pub fn new() -> Self {
            Fields {
                _phantom: PhantomData,
            }
        }

        pub fn get<'a, F: FieldsTuple<'a> + 'a, Func: FnMut(F::TupleType<'a>) + 'a>(
            &self,
            fields: F,
            mut func: Func,
        ) {
            let tuple = fields.get_tuple();
            func(tuple);
        }
    }

    #[derive(Debug, Clone, Copy)]
    struct Transsform {
        x: f32,
        y: f32,
    }

    let transform_array = [Transsform { x: 1.0, y: 1.0 }; 10];
    let mut transform_array2 = [Transsform { x: 3.0, y: 4.0 }; 10];
    let fields = Fields::<Transsform>::new();
    let field = Field {
        array: &transform_array,
        _phantom: PhantomData,
    };
    let mut field2 = FieldMut {
        array: &mut transform_array2,
        _phantom: PhantomData,
    };

    // Test with 2-tuple
    fields.get(((&field, 0), (&mut field2, 1)), |(f1, f2)| {
        println!("f1: {:?}", f1);
        println!("f2: {:?}", f2);
    });