diff --git a/serde/build.rs b/serde/build.rs index e27e2f34..ae0f9869 100644 --- a/serde/build.rs +++ b/serde/build.rs @@ -68,6 +68,10 @@ fn main() { if minor >= 28 { println!("cargo:rustc-cfg=num_nonzero"); } + + if minor >= 34 { + println!("cargo:rustc-cfg=std_integer_atomics"); + } } fn rustc_minor_version() -> Option { diff --git a/serde/src/de/impls.rs b/serde/src/de/impls.rs index 1d4c3187..0a28c43e 100644 --- a/serde/src/de/impls.rs +++ b/serde/src/de/impls.rs @@ -2543,3 +2543,56 @@ where Deserialize::deserialize(deserializer).map(Wrapping) } } + +#[cfg(all(feature="std", std_integer_atomics))] +use std::sync::atomic; + + +#[cfg(all(feature="std", std_integer_atomics))] +macro_rules! atomic_impl { + ($ty:path, $primitive:ident) => { + impl<'de> Deserialize<'de> for $ty + { + #[inline] + fn deserialize(deserializer: D) -> Result + where D: Deserializer<'de> + { + let val = $primitive::deserialize(deserializer)?; + Ok(Self::new(val)) + } + } + } +} + +#[cfg(all(feature="std", std_integer_atomics))] +atomic_impl!(atomic::AtomicBool, bool); + +#[cfg(all(feature="std", std_integer_atomics))] +atomic_impl!(atomic::AtomicI8, i8); + +#[cfg(all(feature="std", std_integer_atomics))] +atomic_impl!(atomic::AtomicI16, i16); + +#[cfg(all(feature="std", std_integer_atomics))] +atomic_impl!(atomic::AtomicI32, i32); + +#[cfg(all(feature="std", std_integer_atomics))] +atomic_impl!(atomic::AtomicI64, i64); + +#[cfg(all(feature="std", std_integer_atomics))] +atomic_impl!(atomic::AtomicIsize, isize); + +#[cfg(all(feature="std", std_integer_atomics))] +atomic_impl!(atomic::AtomicU8, u8); + +#[cfg(all(feature="std", std_integer_atomics))] +atomic_impl!(atomic::AtomicU16, u16); + +#[cfg(all(feature="std", std_integer_atomics))] +atomic_impl!(atomic::AtomicU32, u32); + +#[cfg(all(feature="std", std_integer_atomics))] +atomic_impl!(atomic::AtomicU64, u64); + +#[cfg(all(feature="std", std_integer_atomics))] +atomic_impl!(atomic::AtomicUsize, usize); diff --git a/serde/src/ser/impls.rs b/serde/src/ser/impls.rs index fb0449a7..59b54117 100644 --- a/serde/src/ser/impls.rs +++ b/serde/src/ser/impls.rs @@ -839,3 +839,55 @@ where self.0.serialize(serializer) } } + +//////////////////////////////////////////////////////////////////////////////// +#[cfg(all(feature="std", std_integer_atomics))] +use std::sync::atomic; + +#[cfg(all(feature="std", std_integer_atomics))] +macro_rules! atomic_impl { + ($ty:path, $method:ident $($cast:tt)*) => { + impl Serialize for $ty { + #[inline] + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + serializer.$method(self.load(atomic::Ordering::SeqCst) $($cast)*) + } + } + } +} + +#[cfg(all(feature="std", std_integer_atomics))] +atomic_impl!(atomic::AtomicBool, serialize_bool); + +#[cfg(all(feature="std", std_integer_atomics))] +atomic_impl!(atomic::AtomicI8, serialize_i8); + +#[cfg(all(feature="std", std_integer_atomics))] +atomic_impl!(atomic::AtomicI16, serialize_i16); + +#[cfg(all(feature="std", std_integer_atomics))] +atomic_impl!(atomic::AtomicI32, serialize_i32); + +#[cfg(all(feature="std", std_integer_atomics))] +atomic_impl!(atomic::AtomicI64, serialize_i64); + +#[cfg(all(feature="std", std_integer_atomics))] +atomic_impl!(atomic::AtomicIsize, serialize_i64 as i64); + +#[cfg(all(feature="std", std_integer_atomics))] +atomic_impl!(atomic::AtomicU8, serialize_u8); + +#[cfg(all(feature="std", std_integer_atomics))] +atomic_impl!(atomic::AtomicU16, serialize_u16); + +#[cfg(all(feature="std", std_integer_atomics))] +atomic_impl!(atomic::AtomicU32, serialize_u32); + +#[cfg(all(feature="std", std_integer_atomics))] +atomic_impl!(atomic::AtomicU64, serialize_u64); + +#[cfg(all(feature="std", std_integer_atomics))] +atomic_impl!(atomic::AtomicUsize, serialize_u64 as u64); diff --git a/test_suite/tests/test_de.rs b/test_suite/tests/test_de.rs index 90e0f395..c970b8de 100644 --- a/test_suite/tests/test_de.rs +++ b/test_suite/tests/test_de.rs @@ -9,6 +9,7 @@ use std::num::Wrapping; use std::ops::Bound; use std::path::{Path, PathBuf}; use std::rc::{Rc, Weak as RcWeak}; +use std::sync::atomic; use std::sync::{Arc, Weak as ArcWeak}; use std::time::{Duration, UNIX_EPOCH}; @@ -1140,6 +1141,81 @@ fn test_never_type() { ); } +macro_rules! assert_de_tokens_atomic { + ($ty:ty, $val:expr, $tokens:expr) => { + let mut de = serde_test::Deserializer::new($tokens); + match <$ty>::deserialize(&mut de) { + Ok(v) => { + let loaded = v.load(atomic::Ordering::SeqCst); + assert_eq!($val, loaded); + }, + Err(e) => panic!("tokens failed to deserialize: {}", e) + }; + if de.remaining() > 0 { + panic!("{} remaining tokens", de.remaining()); + } + } +} + +#[test] +fn test_atomics() { + assert_de_tokens_atomic!( + atomic::AtomicBool, + true, + &[Token::Bool(true)] + ); + assert_de_tokens_atomic!( + atomic::AtomicI8, + -127, + &[Token::I8(-127i8)] + ); + assert_de_tokens_atomic!( + atomic::AtomicI16, + -510, + &[Token::I16(-510i16)] + ); + assert_de_tokens_atomic!( + atomic::AtomicI32, + -131072, + &[Token::I32(-131072i32)] + ); + assert_de_tokens_atomic!( + atomic::AtomicI64, + -8589934592, + &[Token::I64(-8589934592)] + ); + assert_de_tokens_atomic!( + atomic::AtomicIsize, + -131072isize, + &[Token::I32(-131072)] + ); + assert_de_tokens_atomic!( + atomic::AtomicU8, + 127, + &[Token::U8(127u8)] + ); + assert_de_tokens_atomic!( + atomic::AtomicU16, + 510u16, + &[Token::U16(510u16)] + ); + assert_de_tokens_atomic!( + atomic::AtomicU32, + 131072u32, + &[Token::U32(131072u32)] + ); + assert_de_tokens_atomic!( + atomic::AtomicU64, + 8589934592u64, + &[Token::U64(8589934592)] + ); + assert_de_tokens_atomic!( + atomic::AtomicUsize, + 131072usize, + &[Token::U32(131072)] + ); +} + declare_error_tests! { test_unknown_field { &[ diff --git a/test_suite/tests/test_ser.rs b/test_suite/tests/test_ser.rs index 55be9800..88e349ae 100644 --- a/test_suite/tests/test_ser.rs +++ b/test_suite/tests/test_ser.rs @@ -10,6 +10,7 @@ use std::ops::Bound; use std::path::{Path, PathBuf}; use std::rc::{Rc, Weak as RcWeak}; use std::sync::{Arc, Weak as ArcWeak}; +use std::sync::atomic; use std::time::{Duration, UNIX_EPOCH}; #[cfg(unix)] @@ -483,6 +484,20 @@ declare_tests! { Token::Str("1a"), ], } + test_atomic { + atomic::AtomicBool::new(false) => &[Token::Bool(false)], + atomic::AtomicBool::new(true) => &[Token::Bool(true)], + atomic::AtomicI8::new(63i8) => &[Token::I8(63i8)], + atomic::AtomicI16::new(-318i16) => &[Token::I16(-318i16)], + atomic::AtomicI32::new(65792i32) => &[Token::I32(65792i32)], + atomic::AtomicI64::new(-4295032832i64) => &[Token::I64(-4295032832i64)], + atomic::AtomicIsize::new(-65792isize) => &[Token::I64(-65792i64)], + atomic::AtomicU8::new(192u8) => &[Token::U8(192u8)], + atomic::AtomicU16::new(510u16) => &[Token::U16(510u16)], + atomic::AtomicU32::new(131072u32) => &[Token::U32(131072u32)], + atomic::AtomicU64::new(12884901888u64) => &[Token::U64(12884901888u64)], + atomic::AtomicUsize::new(655360usize) => &[Token::U64(655360u64)], + } } declare_tests! {