diff --git a/crates/bevy_core/Cargo.toml b/crates/bevy_core/Cargo.toml index d149581ebb..bbf51137c7 100644 --- a/crates/bevy_core/Cargo.toml +++ b/crates/bevy_core/Cargo.toml @@ -32,6 +32,7 @@ serialize = ["dep:serde"] [dev-dependencies] crossbeam-channel = "0.5.0" +serde_test = "1.0" [lints] workspace = true diff --git a/crates/bevy_core/src/lib.rs b/crates/bevy_core/src/lib.rs index 073460b3b3..dc93ddf2c0 100644 --- a/crates/bevy_core/src/lib.rs +++ b/crates/bevy_core/src/lib.rs @@ -80,7 +80,7 @@ fn tick_global_task_pools(_main_thread_marker: Option>) { /// [`FrameCount`] will wrap to 0 after exceeding [`u32::MAX`]. Within reasonable /// assumptions, one may exploit wrapping arithmetic to determine the number of frames /// that have elapsed between two observations – see [`u32::wrapping_sub()`]. -#[derive(Debug, Default, Resource, Clone, Copy)] +#[derive(Debug, Default, Resource, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] pub struct FrameCount(pub u32); /// Adds frame counting functionality to Apps. diff --git a/crates/bevy_core/src/serde.rs b/crates/bevy_core/src/serde.rs index f8835e9a5f..fc4d81b4bd 100644 --- a/crates/bevy_core/src/serde.rs +++ b/crates/bevy_core/src/serde.rs @@ -9,6 +9,7 @@ use serde::{ }; use super::name::Name; +use super::FrameCount; impl Serialize for Name { fn serialize(&self, serializer: S) -> Result { @@ -39,3 +40,52 @@ impl<'de> Visitor<'de> for EntityVisitor { Ok(Name::new(v)) } } + +// Manually implementing serialize/deserialize allows us to use a more compact representation as simple integers +impl Serialize for FrameCount { + fn serialize(&self, serializer: S) -> Result { + serializer.serialize_u32(self.0) + } +} + +impl<'de> Deserialize<'de> for FrameCount { + fn deserialize>(deserializer: D) -> Result { + deserializer.deserialize_u32(FrameVisitor) + } +} + +struct FrameVisitor; + +impl<'de> Visitor<'de> for FrameVisitor { + type Value = FrameCount; + + fn expecting(&self, formatter: &mut Formatter) -> fmt::Result { + formatter.write_str(any::type_name::()) + } + + fn visit_u32(self, v: u32) -> Result + where + E: Error, + { + Ok(FrameCount(v)) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + use serde_test::{assert_tokens, Token}; + + #[test] + fn test_serde_name() { + let name = Name::new("MyComponent"); + assert_tokens(&name, &[Token::String("MyComponent")]); + } + + #[test] + fn test_serde_frame_count() { + let frame_count = FrameCount(100); + assert_tokens(&frame_count, &[Token::U32(100)]); + } +}