bevy_ecs/system/
system_name.rs

1use crate::{
2    component::Tick,
3    prelude::World,
4    query::FilteredAccessSet,
5    system::{ExclusiveSystemParam, ReadOnlySystemParam, SystemMeta, SystemParam},
6    world::unsafe_world_cell::UnsafeWorldCell,
7};
8use bevy_utils::prelude::DebugName;
9use derive_more::derive::{Display, Into};
10
11/// [`SystemParam`] that returns the name of the system which it is used in.
12///
13/// This is not a reliable identifier, it is more so useful for debugging or logging.
14///
15/// # Examples
16///
17/// ```
18/// # use bevy_ecs::system::SystemName;
19/// # use bevy_ecs::system::SystemParam;
20///
21/// #[derive(SystemParam)]
22/// struct Logger {
23///     system_name: SystemName,
24/// }
25///
26/// impl Logger {
27///     fn log(&mut self, message: &str) {
28///         eprintln!("{}: {}", self.system_name, message);
29///     }
30/// }
31///
32/// fn system1(mut logger: Logger) {
33///     // Prints: "crate_name::mod_name::system1: Hello".
34///     logger.log("Hello");
35/// }
36/// ```
37#[derive(Debug, Into, Display)]
38pub struct SystemName(DebugName);
39
40impl SystemName {
41    /// Gets the name of the system.
42    pub fn name(&self) -> DebugName {
43        self.0.clone()
44    }
45}
46
47// SAFETY: no component value access
48unsafe impl SystemParam for SystemName {
49    type State = ();
50    type Item<'w, 's> = SystemName;
51
52    fn init_state(_world: &mut World) -> Self::State {}
53
54    fn init_access(
55        _state: &Self::State,
56        _system_meta: &mut SystemMeta,
57        _component_access_set: &mut FilteredAccessSet,
58        _world: &mut World,
59    ) {
60    }
61
62    #[inline]
63    unsafe fn get_param<'w, 's>(
64        _state: &'s mut Self::State,
65        system_meta: &SystemMeta,
66        _world: UnsafeWorldCell<'w>,
67        _change_tick: Tick,
68    ) -> Self::Item<'w, 's> {
69        SystemName(system_meta.name.clone())
70    }
71}
72
73// SAFETY: Only reads internal system state
74unsafe impl ReadOnlySystemParam for SystemName {}
75
76impl ExclusiveSystemParam for SystemName {
77    type State = ();
78    type Item<'s> = SystemName;
79
80    fn init(_world: &mut World, _system_meta: &mut SystemMeta) -> Self::State {}
81
82    fn get_param<'s>(_state: &'s mut Self::State, system_meta: &SystemMeta) -> Self::Item<'s> {
83        SystemName(system_meta.name.clone())
84    }
85}
86
87#[cfg(test)]
88#[cfg(feature = "trace")]
89mod tests {
90    use crate::{
91        system::{IntoSystem, RunSystemOnce, SystemName},
92        world::World,
93    };
94    use alloc::{borrow::ToOwned, string::String};
95
96    #[test]
97    fn test_system_name_regular_param() {
98        fn testing(name: SystemName) -> String {
99            name.name().as_string()
100        }
101
102        let mut world = World::default();
103        let id = world.register_system(testing);
104        let name = world.run_system(id).unwrap();
105        assert!(name.ends_with("testing"));
106    }
107
108    #[test]
109    fn test_system_name_exclusive_param() {
110        fn testing(_world: &mut World, name: SystemName) -> String {
111            name.name().as_string()
112        }
113
114        let mut world = World::default();
115        let id = world.register_system(testing);
116        let name = world.run_system(id).unwrap();
117        assert!(name.ends_with("testing"));
118    }
119
120    #[test]
121    fn test_closure_system_name_regular_param() {
122        let mut world = World::default();
123        let system =
124            IntoSystem::into_system(|name: SystemName| name.name().to_owned()).with_name("testing");
125        let name = world.run_system_once(system).unwrap().as_string();
126        assert_eq!(name, "testing");
127    }
128
129    #[test]
130    fn test_exclusive_closure_system_name_regular_param() {
131        let mut world = World::default();
132        let system =
133            IntoSystem::into_system(|_world: &mut World, name: SystemName| name.name().to_owned())
134                .with_name("testing");
135        let name = world.run_system_once(system).unwrap().as_string();
136        assert_eq!(name, "testing");
137    }
138}