Skip to content

Commit 8a505b4

Browse files
author
Rebekah Kim
committed
Add support for std::sync::atomic
1 parent 5b850c3 commit 8a505b4

3 files changed

Lines changed: 175 additions & 0 deletions

File tree

src/derive/atomic.rs

Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
use super::convert::ConvertFrom;
2+
use std::sync::atomic;
3+
4+
macro_rules! atomic_impl {
5+
($atomic: path, $repr: ident) => {
6+
impl ConvertFrom<&$atomic> for $repr {
7+
fn convert_from(atomic: &$atomic) -> Self {
8+
atomic.load(std::sync::atomic::Ordering::Relaxed)
9+
}
10+
}
11+
12+
impl ConvertFrom<$repr> for $atomic {
13+
fn convert_from(bits: $repr) -> Self {
14+
Self::from(bits)
15+
}
16+
}
17+
};
18+
}
19+
20+
atomic_impl!(atomic::AtomicBool, bool);
21+
atomic_impl!(atomic::AtomicI8, i8);
22+
atomic_impl!(atomic::AtomicI16, i16);
23+
atomic_impl!(atomic::AtomicI32, i32);
24+
atomic_impl!(atomic::AtomicI64, i64);
25+
atomic_impl!(atomic::AtomicIsize, isize);
26+
atomic_impl!(atomic::AtomicU8, u8);
27+
atomic_impl!(atomic::AtomicU16, u16);
28+
atomic_impl!(atomic::AtomicU32, u32);
29+
atomic_impl!(atomic::AtomicU64, u64);
30+
atomic_impl!(atomic::AtomicUsize, usize);
31+
32+
#[cfg(test)]
33+
mod tests {
34+
use crate::{decode, encode, Decode, Encode};
35+
use std::sync::atomic::*;
36+
37+
#[allow(unused)]
38+
#[test]
39+
fn test_atomic() {
40+
macro_rules! atomic_test {
41+
($atomic: ident, $inner: expr) => {
42+
assert!(decode::<$atomic>(&encode(&$atomic::new($inner)))
43+
.is_ok_and(|x| x.load(Ordering::Relaxed) == $inner));
44+
};
45+
}
46+
atomic_test!(AtomicBool, true);
47+
atomic_test!(AtomicI8, -128i8);
48+
atomic_test!(AtomicI16, -5897i16);
49+
atomic_test!(AtomicI32, -487952i32);
50+
atomic_test!(AtomicI64, -783414i64);
51+
atomic_test!(AtomicIsize, isize::MIN);
52+
atomic_test!(AtomicU8, 255u8);
53+
atomic_test!(AtomicU16, 8932u16);
54+
atomic_test!(AtomicU32, 58902u32);
55+
atomic_test!(AtomicU64, 90887783u64);
56+
atomic_test!(AtomicUsize, usize::MAX);
57+
}
58+
59+
#[derive(Default, Encode, Decode)]
60+
struct AtomicStruct {
61+
a: AtomicBool,
62+
b: AtomicI8,
63+
c: AtomicI16,
64+
d: AtomicI32,
65+
e: AtomicI64,
66+
f: AtomicIsize,
67+
g: AtomicU8,
68+
h: AtomicU16,
69+
i: AtomicU32,
70+
j: AtomicU64,
71+
k: AtomicUsize,
72+
}
73+
impl AtomicStruct {
74+
fn new(value: i32) -> Self {
75+
Self {
76+
d: AtomicI32::new(value),
77+
..Default::default()
78+
}
79+
}
80+
fn load(&self, ordering: Ordering) -> i32 {
81+
self.d.load(ordering)
82+
}
83+
}
84+
85+
#[allow(unused)]
86+
#[test]
87+
fn test_struct_atomic() {
88+
macro_rules! atomic_struct_test {
89+
($field: ident, $atomic: ident, $inner: expr) => {
90+
let original = AtomicStruct::default();
91+
let encoded = encode(&original);
92+
let decoded = decode::<AtomicStruct>(&encoded).unwrap();
93+
assert_eq!(
94+
original.$field.load(Ordering::Relaxed),
95+
decoded.$field.load(Ordering::Relaxed)
96+
);
97+
};
98+
}
99+
100+
atomic_struct_test!(a, AtomicBool, true);
101+
atomic_struct_test!(b, AtomicI8, -128i8);
102+
atomic_struct_test!(c, AtomicI16, -5897i16);
103+
atomic_struct_test!(d, AtomicI32, -487952i32);
104+
atomic_struct_test!(e, AtomicI64, -783414i64);
105+
atomic_struct_test!(f, AtomicIsize, isize::MIN);
106+
atomic_struct_test!(g, AtomicU8, 255u8);
107+
atomic_struct_test!(h, AtomicU16, 8932u16);
108+
atomic_struct_test!(i, AtomicU32, 58902u32);
109+
atomic_struct_test!(j, AtomicU64, 90887783u64);
110+
atomic_struct_test!(k, AtomicUsize, usize::MAX);
111+
}
112+
113+
#[allow(unused)]
114+
#[test]
115+
fn test_enum_atomic() {
116+
macro_rules! atomic_enum_test {
117+
($variant: ident, $atomic: ident, $inner: expr) => {
118+
let original = AtomicEnum::$variant($atomic::new($inner));
119+
let encoded = encode(&original);
120+
let decoded = decode::<AtomicEnum>(&encoded).unwrap();
121+
match (original, decoded) {
122+
(AtomicEnum::$variant(a), AtomicEnum::$variant(b)) => {
123+
assert_eq!(a.load(Ordering::Relaxed), b.load(Ordering::Relaxed))
124+
}
125+
_ => panic!("Enum variant mismatch"),
126+
}
127+
};
128+
}
129+
130+
#[derive(Encode, Decode)]
131+
enum AtomicEnum {
132+
A(AtomicBool),
133+
B(AtomicI8),
134+
C(AtomicI16),
135+
D(AtomicI32),
136+
E(AtomicI64),
137+
F(AtomicIsize),
138+
G(AtomicU8),
139+
H(AtomicU16),
140+
I(AtomicU32),
141+
J(AtomicU64),
142+
K(AtomicUsize),
143+
L(NestedAtomic),
144+
}
145+
type NestedAtomic = AtomicStruct;
146+
147+
atomic_enum_test!(A, AtomicBool, true);
148+
atomic_enum_test!(B, AtomicI8, -128i8);
149+
atomic_enum_test!(C, AtomicI16, -5897i16);
150+
atomic_enum_test!(D, AtomicI32, -487952i32);
151+
atomic_enum_test!(E, AtomicI64, -783414i64);
152+
atomic_enum_test!(F, AtomicIsize, isize::MIN);
153+
atomic_enum_test!(G, AtomicU8, 255u8);
154+
atomic_enum_test!(H, AtomicU16, 8932u16);
155+
atomic_enum_test!(I, AtomicU32, 58902u32);
156+
atomic_enum_test!(J, AtomicU64, 90887783u64);
157+
atomic_enum_test!(K, AtomicUsize, usize::MAX);
158+
atomic_enum_test!(L, NestedAtomic, 37982i32);
159+
}
160+
}

src/derive/impls.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,7 @@ mod with_std {
167167
use crate::derive::convert::impl_convert;
168168
use core::hash::{BuildHasher, Hash};
169169
use std::collections::{HashMap, HashSet};
170+
use std::sync::atomic;
170171

171172
impl<T: Encode, S> Encode for HashSet<T, S> {
172173
type Encoder = VecEncoder<T>;
@@ -183,6 +184,18 @@ mod with_std {
183184
type Decoder = MapDecoder<'a, K, V>;
184185
}
185186

187+
impl_convert!(atomic::AtomicBool, bool);
188+
impl_convert!(atomic::AtomicI8, i8);
189+
impl_convert!(atomic::AtomicI16, i16);
190+
impl_convert!(atomic::AtomicI32, i32);
191+
impl_convert!(atomic::AtomicI64, i64);
192+
impl_convert!(atomic::AtomicIsize, isize);
193+
impl_convert!(atomic::AtomicU8, u8);
194+
impl_convert!(atomic::AtomicU16, u16);
195+
impl_convert!(atomic::AtomicU32, u32);
196+
impl_convert!(atomic::AtomicU64, u64);
197+
impl_convert!(atomic::AtomicUsize, usize);
198+
186199
macro_rules! impl_ipvx_addr {
187200
($addr: ident, $repr: ident) => {
188201
impl_convert!(std::net::$addr, $repr);

src/derive/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ use alloc::vec::Vec;
55
use core::num::NonZeroUsize;
66

77
mod array;
8+
#[cfg(feature = "std")]
9+
mod atomic;
810
pub(crate) mod convert;
911
mod duration;
1012
mod empty;

0 commit comments

Comments
 (0)