Skip to main content

cu29_runtime/
reflect.rs

1//! Runtime reflection helpers built on top of `bevy_reflect`.
2
3#[cfg(feature = "reflect")]
4use alloc::format;
5use alloc::string::String;
6#[cfg(feature = "reflect")]
7use alloc::vec::Vec;
8
9#[cfg(feature = "reflect")]
10pub use bevy_reflect::*;
11
12#[cfg(feature = "reflect")]
13pub trait ReflectTypePath: TypePath {}
14
15#[cfg(feature = "reflect")]
16impl<T: TypePath> ReflectTypePath for T {}
17
18#[cfg(not(feature = "reflect"))]
19pub use cu29_reflect_derive::Reflect;
20
21#[cfg(not(feature = "reflect"))]
22pub trait Reflect: 'static {}
23
24#[cfg(not(feature = "reflect"))]
25impl<T: 'static> Reflect for T {}
26
27#[cfg(not(feature = "reflect"))]
28pub trait TypePath {
29    fn type_path() -> &'static str {
30        core::any::type_name::<Self>()
31    }
32
33    fn short_type_path() -> &'static str {
34        core::any::type_name::<Self>()
35    }
36
37    fn type_ident() -> Option<&'static str> {
38        None
39    }
40
41    fn crate_name() -> Option<&'static str> {
42        None
43    }
44
45    fn module_path() -> Option<&'static str> {
46        None
47    }
48}
49
50#[cfg(not(feature = "reflect"))]
51macro_rules! impl_type_path_for_primitives {
52    ($($ty:ty),* $(,)?) => {
53        $(impl TypePath for $ty {})*
54    };
55}
56
57#[cfg(not(feature = "reflect"))]
58impl_type_path_for_primitives!(
59    (),
60    bool,
61    char,
62    str,
63    u8,
64    u16,
65    u32,
66    u64,
67    u128,
68    usize,
69    i8,
70    i16,
71    i32,
72    i64,
73    i128,
74    isize,
75    f32,
76    f64,
77);
78
79#[cfg(not(feature = "reflect"))]
80pub trait ReflectTypePath {}
81
82#[cfg(not(feature = "reflect"))]
83impl<T> ReflectTypePath for T {}
84
85#[cfg(not(feature = "reflect"))]
86pub trait GetTypeRegistration {}
87
88#[cfg(not(feature = "reflect"))]
89impl<T> GetTypeRegistration for T {}
90
91#[cfg(not(feature = "reflect"))]
92#[derive(Debug, Default, Clone, Copy)]
93pub struct TypeInfo;
94
95#[cfg(not(feature = "reflect"))]
96#[derive(Debug, Default)]
97pub struct TypeRegistry;
98
99#[cfg(not(feature = "reflect"))]
100impl TypeRegistry {
101    pub fn register<T>(&mut self) {
102        let _ = core::any::type_name::<T>();
103    }
104}
105
106/// Runtime task-reflect contract exposed by generated Copper applications.
107pub trait ReflectTaskIntrospection {
108    /// Returns a reflected immutable task instance for the given task id.
109    fn reflect_task(&self, task_id: &str) -> Option<&dyn Reflect>;
110
111    /// Returns a reflected mutable task instance for the given task id.
112    fn reflect_task_mut(&mut self, task_id: &str) -> Option<&mut dyn Reflect>;
113
114    /// Registers reflected schema types for this mission's app (tasks, messages, bridges).
115    fn register_reflect_types(_registry: &mut TypeRegistry) {}
116}
117
118/// Dumps a stable, human-readable schema snapshot for the registered reflected types.
119///
120/// This is intended for diagnostics, examples, and contract validation.
121#[cfg(feature = "reflect")]
122pub fn dump_type_registry_schema(registry: &TypeRegistry) -> String {
123    let mut entries: Vec<(&'static str, String)> = registry
124        .iter()
125        .map(|registration| {
126            let info = registration.type_info();
127            (info.type_path(), format!("{info:#?}"))
128        })
129        .collect();
130
131    entries.sort_by_key(|(left, _)| *left);
132
133    let mut dump = String::new();
134    for (type_path, info_dump) in entries {
135        dump.push_str("=== ");
136        dump.push_str(type_path);
137        dump.push_str(" ===\n");
138        dump.push_str(&info_dump);
139        dump.push('\n');
140    }
141    dump
142}
143
144#[cfg(not(feature = "reflect"))]
145pub fn dump_type_registry_schema(_registry: &TypeRegistry) -> String {
146    String::new()
147}
148
149#[cfg(all(test, not(feature = "reflect")))]
150mod tests {
151    use super::TypePath;
152
153    fn assert_type_path<T: TypePath + ?Sized>() {}
154
155    #[test]
156    fn unit_and_primitive_type_paths_exist_without_reflect() {
157        assert_type_path::<()>();
158        assert_type_path::<i8>();
159    }
160}