rkyv/impls/core/with/atomic/
multibyte.rs1use 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
75macro_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}