diff --git a/util/registry/src/entry.rs b/util/registry/src/entry.rs index 26b97f2b..89379e64 100644 --- a/util/registry/src/entry.rs +++ b/util/registry/src/entry.rs @@ -1,3 +1,5 @@ +//! Registry entry types. + use std::{collections::HashSet, hash::Hash, ops::Deref}; use parking_lot::RwLock; @@ -93,6 +95,7 @@ impl RefEntry { } } +/// Guard of tags. pub struct TagsGuard<'a, K, T> { inner: parking_lot::RwLockReadGuard<'a, HashSet>>, } diff --git a/util/registry/src/key.rs b/util/registry/src/key.rs index ff682ddd..a22ede3c 100644 --- a/util/registry/src/key.rs +++ b/util/registry/src/key.rs @@ -1,5 +1,9 @@ +//! Registry key related types. + use std::{hash::Hash, marker::PhantomData}; +use crate::ProvideRegistry; + /// A key for a value in a registry in a context /// where a root registry is available. pub struct Key { @@ -81,3 +85,33 @@ impl AsRef for Key { &self.value } } + +#[cfg(feature = "serde")] +impl serde::Serialize for Key +where + K: serde::Serialize, +{ + #[inline] + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + self.value.serialize(serializer) + } +} + +#[cfg(feature = "serde")] +impl<'r, 'de, K, T> serde::Deserialize<'de> for Key +where + K: serde::Deserialize<'de> + Clone + 'r, + T: ProvideRegistry<'r, K, T> + 'r, +{ + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let registry = T::registry(); + let value = K::deserialize(deserializer)?; + Ok(Self::new(registry.key.value.clone(), value)) + } +} diff --git a/util/registry/src/lib.rs b/util/registry/src/lib.rs index 33756c6e..43c85b9f 100644 --- a/util/registry/src/lib.rs +++ b/util/registry/src/lib.rs @@ -316,6 +316,7 @@ impl<'a, K, T> IntoIterator for &'a Registry { } } +/// Mutable registry of various in-game components. pub struct RegistryMut { key: Key>, entries: Vec<(T, RefEntry)>, @@ -323,6 +324,7 @@ pub struct RegistryMut { } impl RegistryMut { + /// Creates a new mutable registry. #[inline] pub fn new(key: Key>) -> Self { Self { diff --git a/util/registry/src/tag.rs b/util/registry/src/tag.rs index 4ca14fad..3740fd4b 100644 --- a/util/registry/src/tag.rs +++ b/util/registry/src/tag.rs @@ -1,3 +1,5 @@ +//! Tag related types. + use std::{collections::HashMap, hash::Hash}; use crate::{key::Key, Registry}; @@ -99,3 +101,97 @@ impl<'a, K, T> Iterator for Iter<'a, K, T> { }) } } + +#[cfg(feature = "serde")] +pub mod serde { + //! Helper module for serde support. + + use std::str::FromStr; + + use crate::ProvideRegistry; + + use super::TagKey; + + /// `TagKey` serialize and deserailize wrapper + /// without `#` prefix. + #[derive(Debug, Clone, Copy)] + pub struct Unprefixed(pub T); + + impl<'a, K, T> serde::Serialize for Unprefixed<&'a TagKey> + where + K: serde::Serialize, + { + #[inline] + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + self.0.id.serialize(serializer) + } + } + + impl serde::Serialize for Unprefixed> + where + K: serde::Serialize, + { + #[inline] + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + Unprefixed(&self.0).serialize(serializer) + } + } + + impl<'de, 'r, K, T> serde::Deserialize<'de> for Unprefixed> + where + K: serde::Deserialize<'de> + Clone + 'r, + T: ProvideRegistry<'r, K, T> + 'r, + { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + Ok(Unprefixed(TagKey { + registry: T::registry().key.clone(), + id: K::deserialize(deserializer)?, + })) + } + } + + impl serde::Serialize for TagKey + where + K: ToString, + { + #[inline] + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + format!("#{}", self.id.to_string()).serialize(serializer) + } + } + + impl<'de, 'r, K, T> serde::Deserialize<'de> for TagKey + where + K: FromStr + Clone + 'r, + T: ProvideRegistry<'r, K, T> + 'r, + ::Err: std::fmt::Display, + { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let value = String::deserialize(deserializer)?; + let id = value + .strip_prefix('#') + .ok_or_else(|| serde::de::Error::custom("not a tag key"))? + .parse::() + .map_err(serde::de::Error::custom)?; + Ok(Self { + registry: T::registry().key.clone(), + id, + }) + } + } +}