diff --git a/serde/src/de/impls.rs b/serde/src/de/impls.rs index f79b9550..b13800dc 100644 --- a/serde/src/de/impls.rs +++ b/serde/src/de/impls.rs @@ -1474,6 +1474,44 @@ where //////////////////////////////////////////////////////////////////////////////// +/// This impl requires the [`"rc"`] Cargo feature of Serde. The resulting +/// `Weak` has a reference count of 0 and cannot be upgraded. +/// +/// [`"rc"`]: https://serde.rs/feature-flags.html#-features-rc +#[cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))] +impl<'de, T: ?Sized> Deserialize<'de> for RcWeak +where + T: Deserialize<'de>, +{ + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + try!(Option::::deserialize(deserializer)); + Ok(RcWeak::new()) + } +} + +/// This impl requires the [`"rc"`] Cargo feature of Serde. The resulting +/// `Weak` has a reference count of 0 and cannot be upgraded. +/// +/// [`"rc"`]: https://serde.rs/feature-flags.html#-features-rc +#[cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))] +impl<'de, T: ?Sized> Deserialize<'de> for ArcWeak +where + T: Deserialize<'de>, +{ + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + try!(Option::::deserialize(deserializer)); + Ok(ArcWeak::new()) + } +} + +//////////////////////////////////////////////////////////////////////////////// + #[cfg(all(feature = "unstable", feature = "rc", any(feature = "std", feature = "alloc")))] macro_rules! box_forwarded_impl { ( diff --git a/serde/src/lib.rs b/serde/src/lib.rs index 923b7596..ce0c3326 100644 --- a/serde/src/lib.rs +++ b/serde/src/lib.rs @@ -179,14 +179,14 @@ mod lib { pub use std::boxed::Box; #[cfg(all(feature = "rc", feature = "alloc", not(feature = "std")))] - pub use alloc::rc::Rc; + pub use alloc::rc::{Rc, Weak as RcWeak}; #[cfg(all(feature = "rc", feature = "std"))] - pub use std::rc::Rc; + pub use std::rc::{Rc, Weak as RcWeak}; #[cfg(all(feature = "rc", feature = "alloc", not(feature = "std")))] - pub use alloc::arc::Arc; + pub use alloc::arc::{Arc, Weak as ArcWeak}; #[cfg(all(feature = "rc", feature = "std"))] - pub use std::sync::Arc; + pub use std::sync::{Arc, Weak as ArcWeak}; #[cfg(all(feature = "alloc", not(feature = "std")))] pub use alloc::{BTreeMap, BTreeSet, BinaryHeap, LinkedList, VecDeque}; diff --git a/serde/src/ser/impls.rs b/serde/src/ser/impls.rs index f2de2822..fbe057cd 100644 --- a/serde/src/ser/impls.rs +++ b/serde/src/ser/impls.rs @@ -374,6 +374,40 @@ deref_impl!(<'a, T: ?Sized> Serialize for Cow<'a, T> where T: Serialize + ToOwne //////////////////////////////////////////////////////////////////////////////// +/// This impl requires the [`"rc"`] Cargo feature of Serde. +/// +/// [`"rc"`]: https://serde.rs/feature-flags.html#-features-rc +#[cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))] +impl Serialize for RcWeak +where + T: Serialize, +{ + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + self.upgrade().serialize(serializer) + } +} + +/// This impl requires the [`"rc"`] Cargo feature of Serde. +/// +/// [`"rc"`]: https://serde.rs/feature-flags.html#-features-rc +#[cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))] +impl Serialize for ArcWeak +where + T: Serialize, +{ + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + self.upgrade().serialize(serializer) + } +} + +//////////////////////////////////////////////////////////////////////////////// + #[cfg(feature = "unstable")] #[allow(deprecated)] impl Serialize for NonZero diff --git a/test_suite/tests/test_de.rs b/test_suite/tests/test_de.rs index 3a8fcc44..a7eedba3 100644 --- a/test_suite/tests/test_de.rs +++ b/test_suite/tests/test_de.rs @@ -17,15 +17,15 @@ use std::ffi::{CString, OsString}; use std::net; use std::num::Wrapping; use std::path::{Path, PathBuf}; -use std::rc::Rc; -use std::sync::Arc; +use std::rc::{Rc, Weak as RcWeak}; +use std::sync::{Arc, Weak as ArcWeak}; use std::time::{Duration, UNIX_EPOCH}; #[cfg(feature = "unstable")] use std::ffi::CStr; extern crate serde; -use serde::Deserialize; +use serde::{Deserialize, Deserializer}; extern crate fnv; use self::fnv::FnvHasher; @@ -182,6 +182,27 @@ macro_rules! declare_error_tests { } } +#[derive(Debug)] +struct SkipPartialEq(T); + +impl<'de, T> Deserialize<'de> for SkipPartialEq +where + T: Deserialize<'de>, +{ + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + T::deserialize(deserializer).map(SkipPartialEq) + } +} + +impl PartialEq for SkipPartialEq { + fn eq(&self, _other: &Self) -> bool { + true + } +} + fn assert_de_tokens_ignore(ignorable_tokens: &[Token]) { #[derive(PartialEq, Debug, Deserialize)] struct IgnoreBase { @@ -788,11 +809,33 @@ declare_tests! { Token::Bool(true), ], } + test_rc_weak_some { + SkipPartialEq(RcWeak::::new()) => &[ + Token::Some, + Token::Bool(true), + ], + } + test_rc_weak_none { + SkipPartialEq(RcWeak::::new()) => &[ + Token::None, + ], + } test_arc { Arc::new(true) => &[ Token::Bool(true), ], } + test_arc_weak_some { + SkipPartialEq(ArcWeak::::new()) => &[ + Token::Some, + Token::Bool(true), + ], + } + test_arc_weak_none { + SkipPartialEq(ArcWeak::::new()) => &[ + Token::None, + ], + } test_wrapping { Wrapping(1usize) => &[ Token::U32(1), diff --git a/test_suite/tests/test_ser.rs b/test_suite/tests/test_ser.rs index dbc42da6..d677fe35 100644 --- a/test_suite/tests/test_ser.rs +++ b/test_suite/tests/test_ser.rs @@ -11,11 +11,12 @@ extern crate serde_derive; use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet}; use std::ffi::CString; +use std::mem; use std::net; use std::num::Wrapping; use std::path::{Path, PathBuf}; -use std::rc::Rc; -use std::sync::Arc; +use std::rc::{Rc, Weak as RcWeak}; +use std::sync::{Arc, Weak as ArcWeak}; use std::time::{Duration, UNIX_EPOCH}; #[cfg(unix)] @@ -398,11 +399,41 @@ declare_tests! { Token::Bool(true), ], } + test_rc_weak_some { + { + let rc = Rc::new(true); + mem::forget(rc.clone()); + Rc::downgrade(&rc) + } => &[ + Token::Some, + Token::Bool(true), + ], + } + test_rc_weak_none { + RcWeak::::new() => &[ + Token::None, + ], + } test_arc { Arc::new(true) => &[ Token::Bool(true), ], } + test_arc_weak_some { + { + let arc = Arc::new(true); + mem::forget(arc.clone()); + Arc::downgrade(&arc) + } => &[ + Token::Some, + Token::Bool(true), + ], + } + test_arc_weak_none { + ArcWeak::::new() => &[ + Token::None, + ], + } test_wrapping { Wrapping(1usize) => &[ Token::U64(1),