From a38c1201b50b8d911ba701ef0313a399a29090ab Mon Sep 17 00:00:00 2001 From: tidely <43219534+tidely@users.noreply.github.com> Date: Fri, 7 Aug 2026 00:28:59 +0300 Subject: [PATCH 1/3] add serde feature --- Cargo.toml | 5 +++ RELEASES.md | 4 ++ src/lib.rs | 122 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 131 insertions(+) diff --git a/Cargo.toml b/Cargo.toml index 8af6bb5..f0efee5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,10 +8,15 @@ repository = "https://github.com/bevyengine/atomicow" license = "MIT OR Apache-2.0" [dependencies] +serde = { version = "1", default-features = false, features = ["alloc"], optional = true } [features] default = ["std"] std = [] +serde = ["dep:serde"] + +[dev-dependencies] +serde_json = "1" [target.'cfg(not(target_has_atomic = "ptr"))'.dependencies] portable-atomic = { version = "1", default-features = false } diff --git a/RELEASES.md b/RELEASES.md index c6fd8db..c628606 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -1,5 +1,9 @@ # `atomicow` Release Notes +## Unreleased + +Added the `serde` feature + ## Version 1.2 The `T` in `Arc` can now be `!Sized` when converting into an `CowArc<'static, T>` diff --git a/src/lib.rs b/src/lib.rs index 60fb1fd..32bea74 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -182,6 +182,128 @@ impl Display for CowArc<'_, T> { } } +#[cfg(feature = "serde")] +impl serde::Serialize for CowArc<'_, T> { + #[inline] + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serde::Serialize::serialize(self.deref(), serializer) + } +} + +#[cfg(feature = "serde")] +impl<'de, T> serde::Deserialize<'de> for CowArc<'static, T> +where + T: serde::Deserialize<'de>, +{ + #[inline] + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + ::deserialize(deserializer).map(CowArc::new_owned) + } +} + +#[cfg(feature = "serde")] +impl<'de, T> serde::Deserialize<'de> for CowArc<'static, [T]> +where + T: serde::Deserialize<'de> + 'static, +{ + #[inline] + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + struct SliceVisitor(core::marker::PhantomData); + + impl<'de, T> serde::de::Visitor<'de> for SliceVisitor + where + T: serde::Deserialize<'de> + 'static, + { + type Value = CowArc<'static, [T]>; + + fn expecting(&self, formatter: &mut core::fmt::Formatter) -> core::fmt::Result { + formatter.write_str("a sequence") + } + + fn visit_seq(self, mut sequence: A) -> Result + where + A: serde::de::SeqAccess<'de>, + { + let mut values = alloc::vec::Vec::new(); + + while let Some(value) = sequence.next_element()? { + values.push(value); + } + + Ok(CowArc::Owned(Arc::from(values))) + } + } + + deserializer.deserialize_seq(SliceVisitor(core::marker::PhantomData)) + } +} + +#[cfg(feature = "serde")] +impl<'de> serde::Deserialize<'de> for CowArc<'static, str> { + #[inline] + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + struct StrVisitor; + + impl<'de> serde::de::Visitor<'de> for StrVisitor { + type Value = CowArc<'static, str>; + + fn expecting(&self, formatter: &mut core::fmt::Formatter) -> core::fmt::Result { + formatter.write_str("a string") + } + + fn visit_borrowed_str(self, value: &'de str) -> Result + where + E: serde::de::Error, + { + Ok(CowArc::Owned(Arc::from(value))) + } + + fn visit_str(self, value: &str) -> Result + where + E: serde::de::Error, + { + Ok(CowArc::Owned(Arc::from(value))) + } + + fn visit_bytes(self, value: &[u8]) -> Result + where + E: serde::de::Error, + { + let value = core::str::from_utf8(value).map_err(E::custom)?; + self.visit_str(value) + } + + fn visit_borrowed_bytes(self, value: &'de [u8]) -> Result + where + E: serde::de::Error, + { + self.visit_bytes(value) + } + + fn visit_string(self, value: String) -> Result + where + E: serde::de::Error, + { + Ok(CowArc::Owned(Arc::from(value))) + } + } + + deserializer.deserialize_str(StrVisitor) + } +} + impl PartialOrd for CowArc<'_, T> { #[inline] fn partial_cmp(&self, other: &Self) -> Option { From 631a711d319f599bc2bdd68d6ecf164ba348e582 Mon Sep 17 00:00:00 2001 From: tidely <43219534+tidely@users.noreply.github.com> Date: Fri, 7 Aug 2026 00:41:20 +0300 Subject: [PATCH 2/3] remove stray dev dependency --- Cargo.toml | 3 --- 1 file changed, 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index f0efee5..fc5c53b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,9 +15,6 @@ default = ["std"] std = [] serde = ["dep:serde"] -[dev-dependencies] -serde_json = "1" - [target.'cfg(not(target_has_atomic = "ptr"))'.dependencies] portable-atomic = { version = "1", default-features = false } portable-atomic-util = { version = "0.2.4", features = ["alloc"] } From 28f4dc95eed7f84a15a199b347a8302b98905818 Mon Sep 17 00:00:00 2001 From: Alice Cecile Date: Fri, 7 Aug 2026 17:35:22 -0700 Subject: [PATCH 3/3] Improve release note. --- RELEASES.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RELEASES.md b/RELEASES.md index c628606..73b47b8 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -2,7 +2,7 @@ ## Unreleased -Added the `serde` feature +Added the `serde` feature, allowing the serialization and deserialization of `CowArc` types when the contained type implements the appropriate trait. ## Version 1.2