From 5baeca2a05e0ec16a87780e5c0074ba4a18a7d82 Mon Sep 17 00:00:00 2001 From: JieningYu Date: Tue, 23 Jan 2024 19:15:58 +0800 Subject: [PATCH] make serde update as a standalone crate --- Cargo.toml | 15 +-- primitives/Cargo.toml | 6 +- primitives/src/lib.rs | 4 +- util/serde-update/Cargo.toml | 20 +++ .../serde-update/src/erased.rs | 114 +++++++----------- util/serde-update/src/lib.rs | 31 +++++ 6 files changed, 102 insertions(+), 88 deletions(-) create mode 100644 util/serde-update/Cargo.toml rename primitives/src/serde_update.rs => util/serde-update/src/erased.rs (57%) create mode 100644 util/serde-update/src/lib.rs diff --git a/Cargo.toml b/Cargo.toml index 81b2b79..4c53048 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -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"] diff --git a/primitives/Cargo.toml b/primitives/Cargo.toml index 15aaacb..3af69fa 100644 --- a/primitives/Cargo.toml +++ b/primitives/Cargo.toml @@ -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"] diff --git a/primitives/src/lib.rs b/primitives/src/lib.rs index 1f8af68..4b7bda1 100644 --- a/primitives/src/lib.rs +++ b/primitives/src/lib.rs @@ -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; @@ -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] diff --git a/util/serde-update/Cargo.toml b/util/serde-update/Cargo.toml new file mode 100644 index 0000000..9eb40b0 --- /dev/null +++ b/util/serde-update/Cargo.toml @@ -0,0 +1,20 @@ +[package] +name = "rimecraft-serde-update" +version = "0.1.0" +edition = "2021" +authors = ["JieningYu "] +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"] diff --git a/primitives/src/serde_update.rs b/util/serde-update/src/erased.rs similarity index 57% rename from primitives/src/serde_update.rs rename to util/serde-update/src/erased.rs index 9e272f6..d77a4f9 100644 --- a/primitives/src/serde_update.rs +++ b/util/serde-update/src/erased.rs @@ -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<(), >::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<(), >::Error> + where + D: serde::Deserializer<'de>, + { + use serde::de::Error; + self.erased_update(&mut ::erase(deserializer)) + .map_err(D::Error::custom) + } + }; } -impl Update for T -where - T: serde::Serialize + for<'de> serde::Deserialize<'de>, -{ - #[inline] - fn update<'de, D>( - &'de mut self, - deserializer: D, - ) -> Result<(), >::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. @@ -43,6 +58,7 @@ impl ErasedUpdate for T where T: ?Sized + Update, { + #[inline] fn erased_update<'de>( &'de mut self, deserializer: &mut dyn erased_serde::Deserializer<'de>, @@ -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<(), >::Error> - where - D: serde::Deserializer<'de>, - { - use serde::de::Error; - self.erased_update(&mut ::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, @@ -106,7 +80,7 @@ impl Update for ErasedWrapper<'_> { D: serde::Deserializer<'de>, { use serde::de::Error; - self.value + self.0 .erased_update(&mut ::erase(deserializer)) .map_err(D::Error::custom) } diff --git a/util/serde-update/src/lib.rs b/util/serde-update/src/lib.rs new file mode 100644 index 0000000..5303119 --- /dev/null +++ b/util/serde-update/src/lib.rs @@ -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<(), >::Error> + where + D: serde::Deserializer<'de>; +} + +impl Update for T +where + T: serde::Serialize + for<'de> serde::Deserialize<'de>, +{ + #[inline] + fn update<'de, D>( + &'de mut self, + deserializer: D, + ) -> Result<(), >::Error> + where + D: serde::Deserializer<'de>, + { + *self = Self::deserialize(deserializer)?; + Ok(()) + } +}