Skip to content

Commit

Permalink
Merge pull request #1572 from Roguelazer/issue-1496
Browse files Browse the repository at this point in the history
Implement serialization and deserialization for std::sync::atomic types
  • Loading branch information
dtolnay committed Jul 16, 2019
2 parents 24f292d + 4e5f63f commit 637dba5
Show file tree
Hide file tree
Showing 5 changed files with 200 additions and 0 deletions.
4 changes: 4 additions & 0 deletions serde/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<u32> {
Expand Down
53 changes: 53 additions & 0 deletions serde/src/de/impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<D>(deserializer: D) -> Result<Self, D::Error>
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);
52 changes: 52 additions & 0 deletions serde/src/ser/impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
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);
76 changes: 76 additions & 0 deletions test_suite/tests/test_de.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};

Expand Down Expand Up @@ -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<StructDenyUnknown> {
&[
Expand Down
15 changes: 15 additions & 0 deletions test_suite/tests/test_ser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand Down Expand Up @@ -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! {
Expand Down

0 comments on commit 637dba5

Please sign in to comment.