Skip to content

Commit

Permalink
make serde update as a standalone crate
Browse files Browse the repository at this point in the history
  • Loading branch information
JieningYu committed Jan 23, 2024
1 parent 5af3755 commit 5baeca2
Show file tree
Hide file tree
Showing 6 changed files with 102 additions and 88 deletions.
15 changes: 1 addition & 14 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,16 +1,3 @@
[workspace]
resolver = "2"
members = [
"core",
"primitives",
"flare3d",
# Utils
"util/caches",
"util/nbt_ext",
"util/event",
"util/edcode",
"util/collections",
"util/freezer",
# Examples
"flare3d/examples",
]
members = ["core", "primitives", "flare3d", "util/*", "flare3d/examples"]
6 changes: 4 additions & 2 deletions primitives/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,12 @@ once_cell = { version = "1.18", optional = true }
rimecraft-edcode = { path = "../util/edcode", optional = true }
bytes = { version = "*", optional = true }
anyhow = { version = "*", optional = true }
erased-serde = { version = "0.4", optional = true }
rimecraft-serde-update = { path = "../util/serde-update", optional = true, features = [
"erased",
] }

[features]
default = ["caches"]
serde = ["dep:serde", "dep:erased-serde"]
serde = ["dep:serde", "dep:rimecraft-serde-update"]
caches = ["dep:rimecraft-caches", "dep:once_cell"]
edcode = ["dep:rimecraft-edcode", "dep:bytes", "dep:anyhow"]
4 changes: 2 additions & 2 deletions primitives/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ pub mod identifier;
pub mod reference;

#[cfg(feature = "serde")]
pub mod serde_update;
pub use rimecraft_serde_update as serde_update;

#[cfg(test)]
mod tests;
Expand All @@ -11,7 +11,7 @@ pub use identifier::Identifier as Id;
pub use reference::Reference as Ref;

#[cfg(feature = "serde")]
pub use serde_update::{ErasedUpdate as ErasedSerDeUpdate, Update as SerDeUpdate};
pub use serde_update::{erased::ErasedUpdate as ErasedSerDeUpdate, Update as SerDeUpdate};

/// Combine multiple traits into one.
#[macro_export]
Expand Down
20 changes: 20 additions & 0 deletions util/serde-update/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
[package]
name = "rimecraft-serde-update"
version = "0.1.0"
edition = "2021"
authors = ["JieningYu <[email protected]>"]
description = "Traits describing types that can be updated from a serialized representation"
repository = "https://github.com/rimecraft-rs/rimecraft/"
license = "AGPL-3.0-or-later"
categories = ["data-structures"]

[badges]
maintenance = { status = "passively-maintained" }

[dependencies]
serde = { version = "1.0", features = ["derive"] }
erased-serde = { version = "0.4", optional = true }


[features]
erased = ["dep:erased-serde"]
114 changes: 44 additions & 70 deletions primitives/src/serde_update.rs → util/serde-update/src/erased.rs
Original file line number Diff line number Diff line change
@@ -1,30 +1,45 @@
/// Represent types that are able to be updated
/// through serializing and deserializing.
pub trait Update: serde::Serialize {
/// Update this type from a deserializer.
fn update<'de, D>(
&'de mut self,
deserializer: D,
) -> Result<(), <D as serde::Deserializer<'_>>::Error>
where
D: serde::Deserializer<'de>;
use crate::*;

#[doc(hidden)]
#[macro_export]
macro_rules! __internal_update_from_erased {
() => {
#[inline]
fn update<'de, D>(
&'de mut self,
deserializer: D,
) -> Result<(), <D as serde::Deserializer<'_>>::Error>
where
D: serde::Deserializer<'de>,
{
use serde::de::Error;
self.erased_update(&mut <dyn erased_serde::Deserializer>::erase(deserializer))
.map_err(D::Error::custom)
}
};
}

impl<T> Update for T
where
T: serde::Serialize + for<'de> serde::Deserialize<'de>,
{
#[inline]
fn update<'de, D>(
&'de mut self,
deserializer: D,
) -> Result<(), <D as serde::Deserializer<'_>>::Error>
where
D: serde::Deserializer<'de>,
{
*self = Self::deserialize(deserializer)?;
Ok(())
}
/// Implement [`Update`] for the target trait object types
/// that implements [`ErasedUpdate`].
#[macro_export]
macro_rules! update_trait_object {
($t:path) => {
impl $crate::Update for dyn $t {
$crate::__internal_update_from_erased!();
}

impl $crate::Update for dyn $t + Send {
$crate::__internal_update_from_erased!();
}

impl $crate::Update for dyn $t + Sync {
$crate::__internal_update_from_erased!();
}

impl $crate::Update for dyn $t + Send + Sync {
$crate::__internal_update_from_erased!();
}
};
}

/// [`Update`] but type erased.
Expand All @@ -43,6 +58,7 @@ impl<T> ErasedUpdate for T
where
T: ?Sized + Update,
{
#[inline]
fn erased_update<'de>(
&'de mut self,
deserializer: &mut dyn erased_serde::Deserializer<'de>,
Expand All @@ -51,53 +67,11 @@ where
}
}

/// Implement [`Update`] for the target trait object types
/// that implements [`ErasedUpdate`].
#[macro_export]
macro_rules! update_trait_object {
($t:path) => {
impl $crate::serde_update::Update for dyn $t {
$crate::__impl_update_from_erased!();
}

impl $crate::serde_update::Update for dyn $t + Send {
$crate::__impl_update_from_erased!();
}

impl $crate::serde_update::Update for dyn $t + Sync {
$crate::__impl_update_from_erased!();
}

impl $crate::serde_update::Update for dyn $t + Send + Sync {
$crate::__impl_update_from_erased!();
}
};
}

#[doc(hidden)]
#[macro_export]
macro_rules! __impl_update_from_erased {
() => {
fn update<'de, D>(
&'de mut self,
deserializer: D,
) -> Result<(), <D as serde::Deserializer<'_>>::Error>
where
D: serde::Deserializer<'de>,
{
use serde::de::Error;
self.erased_update(&mut <dyn erased_serde::Deserializer>::erase(deserializer))
.map_err(D::Error::custom)
}
};
}

#[derive(serde::Serialize)]
struct ErasedWrapper<'a> {
value: &'a mut dyn ErasedUpdate,
}
pub struct ErasedWrapper<'a>(pub &'a mut dyn ErasedUpdate);

impl Update for ErasedWrapper<'_> {
#[inline]
fn update<'de, D>(
&'de mut self,
deserializer: D,
Expand All @@ -106,7 +80,7 @@ impl Update for ErasedWrapper<'_> {
D: serde::Deserializer<'de>,
{
use serde::de::Error;
self.value
self.0
.erased_update(&mut <dyn erased_serde::Deserializer>::erase(deserializer))
.map_err(D::Error::custom)
}
Expand Down
31 changes: 31 additions & 0 deletions util/serde-update/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#[cfg(feature = "erased")]
pub mod erased;

/// Represent types that are able to be updated
/// through serializing and deserializing.
pub trait Update: serde::Serialize {
/// Update this type from a deserializer.
fn update<'de, D>(
&'de mut self,
deserializer: D,
) -> Result<(), <D as serde::Deserializer<'_>>::Error>
where
D: serde::Deserializer<'de>;
}

impl<T> Update for T
where
T: serde::Serialize + for<'de> serde::Deserialize<'de>,
{
#[inline]
fn update<'de, D>(
&'de mut self,
deserializer: D,
) -> Result<(), <D as serde::Deserializer<'_>>::Error>
where
D: serde::Deserializer<'de>,
{
*self = Self::deserialize(deserializer)?;
Ok(())
}
}

0 comments on commit 5baeca2

Please sign in to comment.