struct_reflection/
lib.rs

1use std::marker::PhantomData;
2
3pub use struct_reflection_derive::StructReflection;
4
5pub trait StructReflection {
6    fn struct_reflection() -> Option<Vec<String>>;
7}
8
9pub trait StructReflectionHelper {
10    fn struct_reflection() -> Option<Vec<String>>;
11}
12
13/// Implementation of StructReflectionHelper for any type that implements StructReflection.
14/// This bridges the two traits, allowing types with #[derive(StructReflection)] to work
15/// in contexts that require StructReflectionHelper.
16impl<T: StructReflection> StructReflectionHelper for T {
17    fn struct_reflection() -> Option<Vec<String>> {
18        T::struct_reflection()
19    }
20}
21
22impl<T: StructReflectionHelper, const N: usize> StructReflectionHelper for [T; N] {
23    fn struct_reflection() -> Option<Vec<String>> {
24        match T::struct_reflection() {
25            Some(inner_fields) => {
26                let mut fields = Vec::new();
27
28                for i in 0..N {
29                    for field in &inner_fields {
30                        fields.push(format!("{i}__{field}"));
31                    }
32                }
33
34                Some(fields)
35            }
36            None => Some((0..N).map(|i| i.to_string()).collect()),
37        }
38    }
39}
40
41// Note on Option<T> implementation:
42//
43// Ideally, we would handle Option<T> differently based on T:
44// - For primitives: return a single "optional" field
45// - For structs: return internal fields with "__optional" suffix
46//
47// This isn't currently possible in stable Rust due to trait coherence rules
48// and lack of specialization. As a compromise, we use a simplified implementation
49// that treats all Option<T> the same way, regardless of what T is.
50//
51// This might be improved in future versions when Rust's type system evolves.
52impl<T> StructReflectionHelper for Option<T> {
53    fn struct_reflection() -> Option<Vec<String>> {
54        // Simple implementation that always returns "optional"
55        Some(vec!["optional".to_string()])
56    }
57}
58
59impl<T> StructReflectionHelper for PhantomData<T> {
60    fn struct_reflection() -> Option<Vec<String>> {
61        None
62    }
63}