From 2e75c172f7fdbf654575d105b8ee72d91f527796 Mon Sep 17 00:00:00 2001 From: Stepan Koltsov Date: Sun, 31 Dec 2023 17:37:28 +0000 Subject: [PATCH] impl ExclusiveSystemParam for SystemName --- crates/bevy_ecs/src/system/mod.rs | 2 + crates/bevy_ecs/src/system/system_name.rs | 134 +++++++++++++++++++++ crates/bevy_ecs/src/system/system_param.rs | 86 ------------- 3 files changed, 136 insertions(+), 86 deletions(-) create mode 100644 crates/bevy_ecs/src/system/system_name.rs diff --git a/crates/bevy_ecs/src/system/mod.rs b/crates/bevy_ecs/src/system/mod.rs index 5cd9f0c233468..ee06535ebf108 100644 --- a/crates/bevy_ecs/src/system/mod.rs +++ b/crates/bevy_ecs/src/system/mod.rs @@ -110,6 +110,7 @@ mod function_system; mod query; #[allow(clippy::module_inception)] mod system; +mod system_name; mod system_param; mod system_registry; @@ -123,6 +124,7 @@ pub use exclusive_system_param::*; pub use function_system::*; pub use query::*; pub use system::*; +pub use system_name::*; pub use system_param::*; pub use system_registry::*; diff --git a/crates/bevy_ecs/src/system/system_name.rs b/crates/bevy_ecs/src/system/system_name.rs new file mode 100644 index 0000000000000..cc61542f795a0 --- /dev/null +++ b/crates/bevy_ecs/src/system/system_name.rs @@ -0,0 +1,134 @@ +use crate::component::Tick; +use crate::prelude::World; +use crate::system::{ExclusiveSystemParam, ReadOnlySystemParam, SystemMeta, SystemParam}; +use crate::world::unsafe_world_cell::UnsafeWorldCell; +use std::borrow::Cow; +use std::ops::Deref; + +/// [`SystemParam`] that returns the name of the system which it is used in. +/// +/// This is not a reliable identifier, it is more so useful for debugging or logging. +/// +/// # Examples +/// +/// ``` +/// # use bevy_ecs::system::SystemName; +/// # use bevy_ecs::system::SystemParam; +/// +/// #[derive(SystemParam)] +/// struct Logger<'s> { +/// system_name: SystemName<'s>, +/// } +/// +/// impl<'s> Logger<'s> { +/// fn log(&mut self, message: &str) { +/// eprintln!("{}: {}", self.system_name, message); +/// } +/// } +/// +/// fn system1(mut logger: Logger) { +/// // Prints: "crate_name::mod_name::system1: Hello". +/// logger.log("Hello"); +/// } +/// ``` +#[derive(Debug)] +pub struct SystemName<'s>(&'s str); + +impl<'s> SystemName<'s> { + /// Gets the name of the system. + pub fn name(&self) -> &str { + self.0 + } +} + +impl<'s> Deref for SystemName<'s> { + type Target = str; + fn deref(&self) -> &Self::Target { + self.name() + } +} + +impl<'s> AsRef for SystemName<'s> { + fn as_ref(&self) -> &str { + self.name() + } +} + +impl<'s> From> for &'s str { + fn from(name: SystemName<'s>) -> &'s str { + name.0 + } +} + +impl<'s> std::fmt::Display for SystemName<'s> { + #[inline(always)] + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + std::fmt::Display::fmt(&self.name(), f) + } +} + +// SAFETY: no component value access +unsafe impl SystemParam for SystemName<'_> { + type State = Cow<'static, str>; + type Item<'w, 's> = SystemName<'s>; + + fn init_state(_world: &mut World, system_meta: &mut SystemMeta) -> Self::State { + system_meta.name.clone() + } + + #[inline] + unsafe fn get_param<'w, 's>( + name: &'s mut Self::State, + _system_meta: &SystemMeta, + _world: UnsafeWorldCell<'w>, + _change_tick: Tick, + ) -> Self::Item<'w, 's> { + SystemName(name) + } +} + +// SAFETY: Only reads internal system state +unsafe impl<'s> ReadOnlySystemParam for SystemName<'s> {} + +impl ExclusiveSystemParam for SystemName<'_> { + type State = Cow<'static, str>; + type Item<'s> = SystemName<'s>; + + fn init(_world: &mut World, system_meta: &mut SystemMeta) -> Self::State { + system_meta.name.clone() + } + + fn get_param<'s>(state: &'s mut Self::State, _system_meta: &SystemMeta) -> Self::Item<'s> { + SystemName(state) + } +} + +#[cfg(test)] +mod tests { + use crate::system::SystemName; + use crate::world::World; + + #[test] + fn test_system_name_regular_param() { + fn testing(name: SystemName) -> String { + name.name().to_owned() + } + + let mut world = World::default(); + let id = world.register_system(testing); + let name = world.run_system(id).unwrap(); + assert!(name.ends_with("testing")); + } + + #[test] + fn test_system_name_exclusive_param() { + fn testing(_world: &mut World, name: SystemName) -> String { + name.name().to_owned() + } + + let mut world = World::default(); + let id = world.register_system(testing); + let name = world.run_system(id).unwrap(); + assert!(name.ends_with("testing")); + } +} diff --git a/crates/bevy_ecs/src/system/system_param.rs b/crates/bevy_ecs/src/system/system_param.rs index d5a7f4c74f817..a3d5872c8a123 100644 --- a/crates/bevy_ecs/src/system/system_param.rs +++ b/crates/bevy_ecs/src/system/system_param.rs @@ -18,7 +18,6 @@ pub use bevy_ecs_macros::SystemParam; use bevy_ptr::UnsafeCellDeref; use bevy_utils::{all_tuples, synccell::SyncCell}; use std::{ - borrow::Cow, fmt::Debug, marker::PhantomData, ops::{Deref, DerefMut}, @@ -1287,91 +1286,6 @@ unsafe impl SystemParam for SystemChangeTick { } } -/// [`SystemParam`] that returns the name of the system which it is used in. -/// -/// This is not a reliable identifier, it is more so useful for debugging or logging. -/// -/// # Examples -/// -/// ``` -/// # use bevy_ecs::system::SystemName; -/// # use bevy_ecs::system::SystemParam; -/// -/// #[derive(SystemParam)] -/// struct Logger<'s> { -/// system_name: SystemName<'s>, -/// } -/// -/// impl<'s> Logger<'s> { -/// fn log(&mut self, message: &str) { -/// eprintln!("{}: {}", self.system_name, message); -/// } -/// } -/// -/// fn system1(mut logger: Logger) { -/// // Prints: "crate_name::mod_name::system1: Hello". -/// logger.log("Hello"); -/// } -/// ``` -#[derive(Debug)] -pub struct SystemName<'s>(&'s str); - -impl<'s> SystemName<'s> { - /// Gets the name of the system. - pub fn name(&self) -> &str { - self.0 - } -} - -impl<'s> Deref for SystemName<'s> { - type Target = str; - fn deref(&self) -> &Self::Target { - self.name() - } -} - -impl<'s> AsRef for SystemName<'s> { - fn as_ref(&self) -> &str { - self.name() - } -} - -impl<'s> From> for &'s str { - fn from(name: SystemName<'s>) -> &'s str { - name.0 - } -} - -impl<'s> std::fmt::Display for SystemName<'s> { - #[inline(always)] - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - std::fmt::Display::fmt(&self.name(), f) - } -} - -// SAFETY: no component value access -unsafe impl SystemParam for SystemName<'_> { - type State = Cow<'static, str>; - type Item<'w, 's> = SystemName<'s>; - - fn init_state(_world: &mut World, system_meta: &mut SystemMeta) -> Self::State { - system_meta.name.clone() - } - - #[inline] - unsafe fn get_param<'w, 's>( - name: &'s mut Self::State, - _system_meta: &SystemMeta, - _world: UnsafeWorldCell<'w>, - _change_tick: Tick, - ) -> Self::Item<'w, 's> { - SystemName(name) - } -} - -// SAFETY: Only reads internal system state -unsafe impl<'s> ReadOnlySystemParam for SystemName<'s> {} - macro_rules! impl_system_param_tuple { ($($param: ident),*) => { // SAFETY: tuple consists only of ReadOnlySystemParams