From 56d3c8f07196fd40d77609486f89d32045063aea Mon Sep 17 00:00:00 2001 From: James Brown Date: Thu, 11 Jul 2019 17:34:53 -0700 Subject: [PATCH 1/3] implement serialization for atomic integer types --- serde/src/ser/impls.rs | 52 ++++++++++++++++++++++++++++++++++++ test_suite/tests/test_ser.rs | 15 +++++++++++ 2 files changed, 67 insertions(+) diff --git a/serde/src/ser/impls.rs b/serde/src/ser/impls.rs index fb0449a7..745f69d5 100644 --- a/serde/src/ser/impls.rs +++ b/serde/src/ser/impls.rs @@ -839,3 +839,55 @@ where self.0.serialize(serializer) } } + +//////////////////////////////////////////////////////////////////////////////// +#[cfg(feature = "std")] +use std::sync::atomic; + +#[cfg(feature = "std")] +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(feature = "std")] +atomic_impl!(atomic::AtomicBool, serialize_bool); + +#[cfg(feature = "std")] +atomic_impl!(atomic::AtomicI8, serialize_i8); + +#[cfg(feature = "std")] +atomic_impl!(atomic::AtomicI16, serialize_i16); + +#[cfg(feature = "std")] +atomic_impl!(atomic::AtomicI32, serialize_i32); + +#[cfg(feature = "std")] +atomic_impl!(atomic::AtomicI64, serialize_i64); + +#[cfg(feature = "std")] +atomic_impl!(atomic::AtomicIsize, serialize_i64 as i64); + +#[cfg(feature = "std")] +atomic_impl!(atomic::AtomicU8, serialize_u8); + +#[cfg(feature = "std")] +atomic_impl!(atomic::AtomicU16, serialize_u16); + +#[cfg(feature = "std")] +atomic_impl!(atomic::AtomicU32, serialize_u32); + +#[cfg(feature = "std")] +atomic_impl!(atomic::AtomicU64, serialize_u64); + +#[cfg(feature = "std")] +atomic_impl!(atomic::AtomicUsize, serialize_u64 as u64); 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! { From de709e72a8e708a12eac5dbd2a92619d4fcef4a8 Mon Sep 17 00:00:00 2001 From: James Brown Date: Thu, 11 Jul 2019 17:51:19 -0700 Subject: [PATCH 2/3] implement deserialization for atomic integer types --- serde/src/de/impls.rs | 53 +++++++++++++++++++++++++ test_suite/tests/test_de.rs | 77 +++++++++++++++++++++++++++++++++++++ 2 files changed, 130 insertions(+) diff --git a/serde/src/de/impls.rs b/serde/src/de/impls.rs index 1d4c3187..300abe34 100644 --- a/serde/src/de/impls.rs +++ b/serde/src/de/impls.rs @@ -2543,3 +2543,56 @@ where Deserialize::deserialize(deserializer).map(Wrapping) } } + +#[cfg(feature = "std")] +use std::sync::atomic; + + +#[cfg(feature = "std")] +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(feature = "std")] +atomic_impl!(atomic::AtomicBool, bool); + +#[cfg(feature = "std")] +atomic_impl!(atomic::AtomicI8, i8); + +#[cfg(feature = "std")] +atomic_impl!(atomic::AtomicI16, i16); + +#[cfg(feature = "std")] +atomic_impl!(atomic::AtomicI32, i32); + +#[cfg(feature = "std")] +atomic_impl!(atomic::AtomicI64, i64); + +#[cfg(feature = "std")] +atomic_impl!(atomic::AtomicIsize, isize); + +#[cfg(feature = "std")] +atomic_impl!(atomic::AtomicU8, u8); + +#[cfg(feature = "std")] +atomic_impl!(atomic::AtomicU16, u16); + +#[cfg(feature = "std")] +atomic_impl!(atomic::AtomicU32, u32); + +#[cfg(feature = "std")] +atomic_impl!(atomic::AtomicU64, u64); + +#[cfg(feature = "std")] +atomic_impl!(atomic::AtomicUsize, usize); diff --git a/test_suite/tests/test_de.rs b/test_suite/tests/test_de.rs index 90e0f395..b96f1739 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,82 @@ 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 { &[ From 4e5f63ff451bb3d9b1ea45fb5c4e31cd8657d97f Mon Sep 17 00:00:00 2001 From: James Brown Date: Fri, 12 Jul 2019 13:44:42 -0700 Subject: [PATCH 3/3] gate atomic serde on rust 1.34 or higher --- serde/build.rs | 4 ++++ serde/src/de/impls.rs | 26 +++++++++++++------------- serde/src/ser/impls.rs | 26 +++++++++++++------------- test_suite/tests/test_de.rs | 1 - 4 files changed, 30 insertions(+), 27 deletions(-) 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 300abe34..0a28c43e 100644 --- a/serde/src/de/impls.rs +++ b/serde/src/de/impls.rs @@ -2544,11 +2544,11 @@ where } } -#[cfg(feature = "std")] +#[cfg(all(feature="std", std_integer_atomics))] use std::sync::atomic; -#[cfg(feature = "std")] +#[cfg(all(feature="std", std_integer_atomics))] macro_rules! atomic_impl { ($ty:path, $primitive:ident) => { impl<'de> Deserialize<'de> for $ty @@ -2564,35 +2564,35 @@ macro_rules! atomic_impl { } } -#[cfg(feature = "std")] +#[cfg(all(feature="std", std_integer_atomics))] atomic_impl!(atomic::AtomicBool, bool); -#[cfg(feature = "std")] +#[cfg(all(feature="std", std_integer_atomics))] atomic_impl!(atomic::AtomicI8, i8); -#[cfg(feature = "std")] +#[cfg(all(feature="std", std_integer_atomics))] atomic_impl!(atomic::AtomicI16, i16); -#[cfg(feature = "std")] +#[cfg(all(feature="std", std_integer_atomics))] atomic_impl!(atomic::AtomicI32, i32); -#[cfg(feature = "std")] +#[cfg(all(feature="std", std_integer_atomics))] atomic_impl!(atomic::AtomicI64, i64); -#[cfg(feature = "std")] +#[cfg(all(feature="std", std_integer_atomics))] atomic_impl!(atomic::AtomicIsize, isize); -#[cfg(feature = "std")] +#[cfg(all(feature="std", std_integer_atomics))] atomic_impl!(atomic::AtomicU8, u8); -#[cfg(feature = "std")] +#[cfg(all(feature="std", std_integer_atomics))] atomic_impl!(atomic::AtomicU16, u16); -#[cfg(feature = "std")] +#[cfg(all(feature="std", std_integer_atomics))] atomic_impl!(atomic::AtomicU32, u32); -#[cfg(feature = "std")] +#[cfg(all(feature="std", std_integer_atomics))] atomic_impl!(atomic::AtomicU64, u64); -#[cfg(feature = "std")] +#[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 745f69d5..59b54117 100644 --- a/serde/src/ser/impls.rs +++ b/serde/src/ser/impls.rs @@ -841,10 +841,10 @@ where } //////////////////////////////////////////////////////////////////////////////// -#[cfg(feature = "std")] +#[cfg(all(feature="std", std_integer_atomics))] use std::sync::atomic; -#[cfg(feature = "std")] +#[cfg(all(feature="std", std_integer_atomics))] macro_rules! atomic_impl { ($ty:path, $method:ident $($cast:tt)*) => { impl Serialize for $ty { @@ -859,35 +859,35 @@ macro_rules! atomic_impl { } } -#[cfg(feature = "std")] +#[cfg(all(feature="std", std_integer_atomics))] atomic_impl!(atomic::AtomicBool, serialize_bool); -#[cfg(feature = "std")] +#[cfg(all(feature="std", std_integer_atomics))] atomic_impl!(atomic::AtomicI8, serialize_i8); -#[cfg(feature = "std")] +#[cfg(all(feature="std", std_integer_atomics))] atomic_impl!(atomic::AtomicI16, serialize_i16); -#[cfg(feature = "std")] +#[cfg(all(feature="std", std_integer_atomics))] atomic_impl!(atomic::AtomicI32, serialize_i32); -#[cfg(feature = "std")] +#[cfg(all(feature="std", std_integer_atomics))] atomic_impl!(atomic::AtomicI64, serialize_i64); -#[cfg(feature = "std")] +#[cfg(all(feature="std", std_integer_atomics))] atomic_impl!(atomic::AtomicIsize, serialize_i64 as i64); -#[cfg(feature = "std")] +#[cfg(all(feature="std", std_integer_atomics))] atomic_impl!(atomic::AtomicU8, serialize_u8); -#[cfg(feature = "std")] +#[cfg(all(feature="std", std_integer_atomics))] atomic_impl!(atomic::AtomicU16, serialize_u16); -#[cfg(feature = "std")] +#[cfg(all(feature="std", std_integer_atomics))] atomic_impl!(atomic::AtomicU32, serialize_u32); -#[cfg(feature = "std")] +#[cfg(all(feature="std", std_integer_atomics))] atomic_impl!(atomic::AtomicU64, serialize_u64); -#[cfg(feature = "std")] +#[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 b96f1739..c970b8de 100644 --- a/test_suite/tests/test_de.rs +++ b/test_suite/tests/test_de.rs @@ -1141,7 +1141,6 @@ fn test_never_type() { ); } - macro_rules! assert_de_tokens_atomic { ($ty:ty, $val:expr, $tokens:expr) => { let mut de = serde_test::Deserializer::new($tokens);