Skip to content

Commit

Permalink
more serde support
Browse files Browse the repository at this point in the history
  • Loading branch information
JieningYu committed Jan 29, 2024
1 parent 81293d0 commit dcbe8ec
Show file tree
Hide file tree
Showing 4 changed files with 135 additions and 0 deletions.
3 changes: 3 additions & 0 deletions util/registry/src/entry.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
//! Registry entry types.
use std::{collections::HashSet, hash::Hash, ops::Deref};

use parking_lot::RwLock;
Expand Down Expand Up @@ -93,6 +95,7 @@ impl<K, T> RefEntry<K, T> {
}
}

/// Guard of tags.
pub struct TagsGuard<'a, K, T> {
inner: parking_lot::RwLockReadGuard<'a, HashSet<TagKey<K, T>>>,
}
Expand Down
34 changes: 34 additions & 0 deletions util/registry/src/key.rs
Original file line number Diff line number Diff line change
@@ -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<K, T> {
Expand Down Expand Up @@ -81,3 +85,33 @@ impl<K, T> AsRef<K> for Key<K, T> {
&self.value
}
}

#[cfg(feature = "serde")]
impl<K, T> serde::Serialize for Key<K, T>
where
K: serde::Serialize,
{
#[inline]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
self.value.serialize(serializer)
}
}

#[cfg(feature = "serde")]
impl<'r, 'de, K, T> serde::Deserialize<'de> for Key<K, T>
where
K: serde::Deserialize<'de> + Clone + 'r,
T: ProvideRegistry<'r, K, T> + 'r,
{
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
let registry = T::registry();
let value = K::deserialize(deserializer)?;
Ok(Self::new(registry.key.value.clone(), value))
}
}
2 changes: 2 additions & 0 deletions util/registry/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -316,13 +316,15 @@ impl<'a, K, T> IntoIterator for &'a Registry<K, T> {
}
}

/// Mutable registry of various in-game components.
pub struct RegistryMut<K, T> {
key: Key<K, Registry<K, T>>,
entries: Vec<(T, RefEntry<K, T>)>,
keys: HashSet<Key<K, T>>,
}

impl<K, T> RegistryMut<K, T> {
/// Creates a new mutable registry.
#[inline]
pub fn new(key: Key<K, Registry<K, T>>) -> Self {
Self {
Expand Down
96 changes: 96 additions & 0 deletions util/registry/src/tag.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
//! Tag related types.
use std::{collections::HashMap, hash::Hash};

use crate::{key::Key, Registry};
Expand Down Expand Up @@ -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<T>(pub T);

impl<'a, K, T> serde::Serialize for Unprefixed<&'a TagKey<K, T>>
where
K: serde::Serialize,
{
#[inline]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
self.0.id.serialize(serializer)
}
}

impl<K, T> serde::Serialize for Unprefixed<TagKey<K, T>>
where
K: serde::Serialize,
{
#[inline]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
Unprefixed(&self.0).serialize(serializer)
}
}

impl<'de, 'r, K, T> serde::Deserialize<'de> for Unprefixed<TagKey<K, T>>
where
K: serde::Deserialize<'de> + Clone + 'r,
T: ProvideRegistry<'r, K, T> + 'r,
{
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
Ok(Unprefixed(TagKey {
registry: T::registry().key.clone(),
id: K::deserialize(deserializer)?,
}))
}
}

impl<K, T> serde::Serialize for TagKey<K, T>
where
K: ToString,
{
#[inline]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
format!("#{}", self.id.to_string()).serialize(serializer)
}
}

impl<'de, 'r, K, T> serde::Deserialize<'de> for TagKey<K, T>
where
K: FromStr + Clone + 'r,
T: ProvideRegistry<'r, K, T> + 'r,
<K as FromStr>::Err: std::fmt::Display,
{
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
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::<K>()
.map_err(serde::de::Error::custom)?;
Ok(Self {
registry: T::registry().key.clone(),
id,
})
}
}
}

0 comments on commit dcbe8ec

Please sign in to comment.