rkyv/impls/core/with/atomic/
multibyte.rs

1use crate::{
2    impls::core::with::atomic::LoadOrdering,
3    rancor::Fallible,
4    with::{ArchiveWith, AtomicLoad, DeserializeWith},
5    Place,
6};
7
8macro_rules! impl_multi_byte_atomic {
9    ($atomic:ty, $archived:ty) => {
10        impl<SO: LoadOrdering> ArchiveWith<$atomic> for AtomicLoad<SO> {
11            type Archived = $archived;
12            type Resolver = ();
13
14            fn resolve_with(
15                field: &$atomic,
16                _: Self::Resolver,
17                out: Place<Self::Archived>,
18            ) {
19                out.write(<$archived>::from_native(field.load(SO::ORDERING)));
20            }
21        }
22
23        impl_serialize_with_atomic_load!($atomic);
24
25        impl<D, SO> DeserializeWith<$archived, $atomic, D> for AtomicLoad<SO>
26        where
27            D: Fallible + ?Sized,
28        {
29            fn deserialize_with(
30                field: &$archived,
31                _: &mut D,
32            ) -> Result<$atomic, D::Error> {
33                Ok(<$atomic>::new(field.to_native()))
34            }
35        }
36    };
37}
38
39macro_rules! impl_multi_byte_atomics {
40    ($($atomic:ty, $archived: ty);* $(;)?) => {
41        $(
42            impl_multi_byte_atomic!($atomic, $archived);
43        )*
44    }
45}
46
47#[cfg(target_has_atomic = "16")]
48impl_multi_byte_atomics! {
49    core::sync::atomic::AtomicI16, crate::primitive::ArchivedI16;
50    core::sync::atomic::AtomicU16, crate::primitive::ArchivedU16;
51    rend::AtomicI16_le, rend::i16_le;
52    rend::AtomicI16_be, rend::i16_be;
53    rend::AtomicU16_le, rend::u16_le;
54    rend::AtomicU16_be, rend::u16_be;
55}
56#[cfg(target_has_atomic = "32")]
57impl_multi_byte_atomics! {
58    core::sync::atomic::AtomicI32, crate::primitive::ArchivedI32;
59    core::sync::atomic::AtomicU32, crate::primitive::ArchivedU32;
60    rend::AtomicI32_le, crate::primitive::ArchivedI32;
61    rend::AtomicI32_be, crate::primitive::ArchivedI32;
62    rend::AtomicU32_le, crate::primitive::ArchivedU32;
63    rend::AtomicU32_be, crate::primitive::ArchivedU32;
64}
65#[cfg(target_has_atomic = "64")]
66impl_multi_byte_atomics! {
67    core::sync::atomic::AtomicI64, crate::primitive::ArchivedI64;
68    core::sync::atomic::AtomicU64, crate::primitive::ArchivedU64;
69    rend::AtomicI64_le, crate::primitive::ArchivedI64;
70    rend::AtomicI64_be, crate::primitive::ArchivedI64;
71    rend::AtomicU64_le, crate::primitive::ArchivedU64;
72    rend::AtomicU64_be, crate::primitive::ArchivedU64;
73}
74
75// AtomicUsize
76
77macro_rules! impl_atomic_size_type {
78    ($atomic:ty, $archived:ty) => {
79        impl<SO: LoadOrdering> ArchiveWith<$atomic> for AtomicLoad<SO> {
80            type Archived = $archived;
81            type Resolver = ();
82
83            fn resolve_with(
84                field: &$atomic,
85                _: Self::Resolver,
86                out: Place<Self::Archived>,
87            ) {
88                out.write(<$archived>::from_native(
89                    field.load(SO::ORDERING) as _
90                ));
91            }
92        }
93
94        impl_serialize_with_atomic_load!($atomic);
95
96        impl<D, SO> DeserializeWith<$archived, $atomic, D> for AtomicLoad<SO>
97        where
98            D: Fallible + ?Sized,
99        {
100            fn deserialize_with(
101                field: &$archived,
102                _: &mut D,
103            ) -> Result<$atomic, D::Error> {
104                Ok(<$atomic>::new(field.to_native() as _))
105            }
106        }
107    };
108}
109
110macro_rules! impl_atomic_size_types {
111    ($($atomic:ty, $archived:ty);* $(;)?) => {
112        $(
113            impl_atomic_size_type!($atomic, $archived);
114        )*
115    }
116}
117
118#[cfg(any(
119    all(target_has_atomic = "16", feature = "pointer_width_16"),
120    all(
121        target_has_atomic = "32",
122        not(any(feature = "pointer_width_16", feature = "pointer_width_64")),
123    ),
124    all(target_has_atomic = "64", feature = "pointer_width_64"),
125))]
126impl_atomic_size_types! {
127    core::sync::atomic::AtomicIsize, crate::primitive::ArchivedIsize;
128    core::sync::atomic::AtomicUsize, crate::primitive::ArchivedUsize;
129}
130
131#[cfg(test)]
132mod tests {
133    #[cfg(target_has_atomic = "32")]
134    #[test]
135    fn with_atomic_load() {
136        use core::sync::atomic::{AtomicU32, Ordering};
137
138        use crate::{
139            api::test::roundtrip,
140            with::{AtomicLoad, Relaxed},
141            Archive, Deserialize, Serialize,
142        };
143
144        #[derive(Archive, Debug, Deserialize, Serialize)]
145        #[rkyv(crate, derive(Debug))]
146        struct Test {
147            #[rkyv(with = AtomicLoad<Relaxed>)]
148            a: AtomicU32,
149        }
150
151        impl PartialEq for Test {
152            fn eq(&self, other: &Self) -> bool {
153                self.a.load(Ordering::Relaxed)
154                    == other.a.load(Ordering::Relaxed)
155            }
156        }
157
158        impl PartialEq<Test> for ArchivedTest {
159            fn eq(&self, other: &Test) -> bool {
160                self.a == other.a.load(Ordering::Relaxed)
161            }
162        }
163
164        let value = Test {
165            a: AtomicU32::new(42),
166        };
167        roundtrip(&value);
168    }
169}