1use core::num::{
2 NonZeroI128, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI8, NonZeroIsize,
3 NonZeroU128, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8, NonZeroUsize,
4};
5
6use rancor::Fallible;
7
8use crate::{
9 primitive::{
10 ArchivedChar, ArchivedF32, ArchivedF64, ArchivedI128, ArchivedI16,
11 ArchivedI32, ArchivedI64, ArchivedIsize, ArchivedNonZeroI128,
12 ArchivedNonZeroI16, ArchivedNonZeroI32, ArchivedNonZeroI64,
13 ArchivedNonZeroIsize, ArchivedNonZeroU128, ArchivedNonZeroU16,
14 ArchivedNonZeroU32, ArchivedNonZeroU64, ArchivedNonZeroUsize,
15 ArchivedU128, ArchivedU16, ArchivedU32, ArchivedU64, ArchivedUsize,
16 },
17 traits::{CopyOptimization, NoUndef},
18 Archive, Deserialize, Place, Portable, Serialize,
19};
20
21macro_rules! unsafe_impl_primitive {
22 ($($ty:ty),* $(,)?) => {
23 $(
24 unsafe impl NoUndef for $ty {}
25 unsafe impl Portable for $ty {}
26 )*
27 };
28}
29
30unsafe_impl_primitive! {
31 (),
32 bool,
33 i8,
34 u8,
35 NonZeroI8,
36 NonZeroU8,
37 rend::NonZeroI16_be,
38 rend::NonZeroI16_le,
39 rend::NonZeroI32_be,
40 rend::NonZeroI32_le,
41 rend::NonZeroI64_be,
42 rend::NonZeroI64_le,
43 rend::NonZeroI128_be,
44 rend::NonZeroI128_le,
45 rend::NonZeroU16_be,
46 rend::NonZeroU16_le,
47 rend::NonZeroU32_be,
48 rend::NonZeroU32_le,
49 rend::NonZeroU64_be,
50 rend::NonZeroU64_le,
51 rend::NonZeroU128_be,
52 rend::NonZeroU128_le,
53 rend::char_be,
54 rend::char_le,
55 rend::f32_be,
56 rend::f32_le,
57 rend::f64_be,
58 rend::f64_le,
59 rend::i16_be,
60 rend::i16_le,
61 rend::i32_be,
62 rend::i32_le,
63 rend::i64_be,
64 rend::i64_le,
65 rend::i128_be,
66 rend::i128_le,
67 rend::u16_be,
68 rend::u16_le,
69 rend::u32_be,
70 rend::u32_le,
71 rend::u64_be,
72 rend::u64_le,
73 rend::u128_be,
74 rend::u128_le,
75 rend::unaligned::NonZeroI16_ube,
76 rend::unaligned::NonZeroI16_ule,
77 rend::unaligned::NonZeroI32_ube,
78 rend::unaligned::NonZeroI32_ule,
79 rend::unaligned::NonZeroI64_ube,
80 rend::unaligned::NonZeroI64_ule,
81 rend::unaligned::NonZeroI128_ube,
82 rend::unaligned::NonZeroI128_ule,
83 rend::unaligned::NonZeroU16_ube,
84 rend::unaligned::NonZeroU16_ule,
85 rend::unaligned::NonZeroU32_ube,
86 rend::unaligned::NonZeroU32_ule,
87 rend::unaligned::NonZeroU64_ube,
88 rend::unaligned::NonZeroU64_ule,
89 rend::unaligned::NonZeroU128_ube,
90 rend::unaligned::NonZeroU128_ule,
91 rend::unaligned::char_ube,
92 rend::unaligned::char_ule,
93 rend::unaligned::f32_ube,
94 rend::unaligned::f32_ule,
95 rend::unaligned::f64_ube,
96 rend::unaligned::f64_ule,
97 rend::unaligned::i16_ube,
98 rend::unaligned::i16_ule,
99 rend::unaligned::i32_ube,
100 rend::unaligned::i32_ule,
101 rend::unaligned::i64_ube,
102 rend::unaligned::i64_ule,
103 rend::unaligned::i128_ube,
104 rend::unaligned::i128_ule,
105 rend::unaligned::u16_ube,
106 rend::unaligned::u16_ule,
107 rend::unaligned::u32_ube,
108 rend::unaligned::u32_ule,
109 rend::unaligned::u64_ube,
110 rend::unaligned::u64_ule,
111 rend::unaligned::u128_ube,
112 rend::unaligned::u128_ule,
113}
114
115macro_rules! impl_serialize_noop {
116 ($type:ty) => {
117 impl<S: Fallible + ?Sized> Serialize<S> for $type {
118 fn serialize(&self, _: &mut S) -> Result<Self::Resolver, S::Error> {
119 Ok(())
120 }
121 }
122 };
123}
124
125macro_rules! impl_archive_self_primitive {
126 ($type:ty) => {
127 impl Archive for $type {
128 const COPY_OPTIMIZATION: CopyOptimization<Self> =
129 unsafe { CopyOptimization::enable() };
130
131 type Archived = Self;
132 type Resolver = ();
133
134 #[inline]
135 fn resolve(&self, _: Self::Resolver, out: Place<Self::Archived>) {
136 out.write(*self);
137 }
138 }
139
140 impl_serialize_noop!($type);
141
142 impl<D: Fallible + ?Sized> Deserialize<$type, D> for $type {
143 fn deserialize(&self, _: &mut D) -> Result<$type, D::Error> {
144 Ok(*self)
145 }
146 }
147 };
148}
149
150macro_rules! impl_archive_self_primitives {
151 ($($type:ty;)*) => {
152 $(
153 impl_archive_self_primitive!($type);
154 )*
155 }
156}
157
158impl_archive_self_primitives! {
159 ();
160 bool;
161 i8;
162 u8;
163 NonZeroI8;
164 NonZeroU8;
165}
166
167#[cfg(any(
168 all(not(feature = "big_endian"), target_endian = "little"),
169 all(feature = "big_endian", target_endian = "big"),
170))]
171const MULTIBYTE_PRIMITIVES_ARE_TRIVIALLY_COPYABLE: bool = true;
172#[cfg(any(
173 all(feature = "big_endian", target_endian = "little"),
174 all(not(feature = "big_endian"), target_endian = "big"),
175))]
176const MULTIBYTE_PRIMITIVES_ARE_TRIVIALLY_COPYABLE: bool = false;
177
178macro_rules! impl_multibyte_primitive {
179 ($archived:ident : $type:ty) => {
180 impl Archive for $type {
181 const COPY_OPTIMIZATION: CopyOptimization<Self> = unsafe {
182 CopyOptimization::enable_if(
183 MULTIBYTE_PRIMITIVES_ARE_TRIVIALLY_COPYABLE,
184 )
185 };
186
187 type Archived = $archived;
188 type Resolver = ();
189
190 #[inline]
191 fn resolve(&self, _: Self::Resolver, out: Place<Self::Archived>) {
192 out.write(<$archived>::from_native(*self));
193 }
194 }
195
196 impl_serialize_noop!($type);
197
198 impl<D: Fallible + ?Sized> Deserialize<$type, D> for $archived {
199 fn deserialize(&self, _: &mut D) -> Result<$type, D::Error> {
200 Ok(self.to_native())
201 }
202 }
203 };
204}
205
206macro_rules! impl_multibyte_primitives {
207 ($($archived:ident: $type:ty),* $(,)?) => {
208 $(
209 impl_multibyte_primitive!($archived: $type);
210 )*
211 };
212}
213
214impl_multibyte_primitives! {
215 ArchivedI16: i16,
216 ArchivedI32: i32,
217 ArchivedI64: i64,
218 ArchivedI128: i128,
219 ArchivedU16: u16,
220 ArchivedU32: u32,
221 ArchivedU64: u64,
222 ArchivedU128: u128,
223 ArchivedF32: f32,
224 ArchivedF64: f64,
225 ArchivedChar: char,
226 ArchivedNonZeroI16: NonZeroI16,
227 ArchivedNonZeroI32: NonZeroI32,
228 ArchivedNonZeroI64: NonZeroI64,
229 ArchivedNonZeroI128: NonZeroI128,
230 ArchivedNonZeroU16: NonZeroU16,
231 ArchivedNonZeroU32: NonZeroU32,
232 ArchivedNonZeroU64: NonZeroU64,
233 ArchivedNonZeroU128: NonZeroU128,
234}
235
236#[cfg(any(
239 all(target_pointer_width = "16", feature = "pointer_width_16"),
240 all(
241 target_pointer_width = "32",
242 not(any(feature = "pointer_width_16", feature = "pointer_width_64")),
243 ),
244 all(target_pointer_width = "64", feature = "pointer_width_64"),
245))]
246const POINTER_WIDTH_EQUALS_ARCHIVED_POINTER_WIDTH: bool = true;
247#[cfg(not(any(
248 all(target_pointer_width = "16", feature = "pointer_width_16"),
249 all(
250 target_pointer_width = "32",
251 not(any(feature = "pointer_width_16", feature = "pointer_width_64")),
252 ),
253 all(target_pointer_width = "64", feature = "pointer_width_64"),
254)))]
255const POINTER_WIDTH_EQUALS_ARCHIVED_POINTER_WIDTH: bool = false;
256
257impl Archive for usize {
258 const COPY_OPTIMIZATION: CopyOptimization<Self> = unsafe {
259 CopyOptimization::enable_if(
260 MULTIBYTE_PRIMITIVES_ARE_TRIVIALLY_COPYABLE
261 && POINTER_WIDTH_EQUALS_ARCHIVED_POINTER_WIDTH,
262 )
263 };
264
265 type Archived = ArchivedUsize;
266 type Resolver = ();
267
268 #[inline]
269 fn resolve(&self, _: Self::Resolver, out: Place<Self::Archived>) {
270 out.write(ArchivedUsize::from_native(*self as _));
271 }
272}
273
274impl<S: Fallible + ?Sized> Serialize<S> for usize {
275 fn serialize(&self, _: &mut S) -> Result<Self::Resolver, S::Error> {
276 Ok(())
277 }
278}
279
280impl<D: Fallible + ?Sized> Deserialize<usize, D> for ArchivedUsize {
281 fn deserialize(&self, _: &mut D) -> Result<usize, D::Error> {
282 Ok(self.to_native() as usize)
283 }
284}
285
286impl Archive for isize {
289 const COPY_OPTIMIZATION: CopyOptimization<Self> = unsafe {
290 CopyOptimization::enable_if(
291 MULTIBYTE_PRIMITIVES_ARE_TRIVIALLY_COPYABLE
292 && POINTER_WIDTH_EQUALS_ARCHIVED_POINTER_WIDTH,
293 )
294 };
295
296 type Archived = ArchivedIsize;
297 type Resolver = ();
298
299 #[inline]
300 fn resolve(&self, _: Self::Resolver, out: Place<Self::Archived>) {
301 out.write(ArchivedIsize::from_native(*self as _));
302 }
303}
304
305impl<S: Fallible + ?Sized> Serialize<S> for isize {
306 fn serialize(&self, _: &mut S) -> Result<Self::Resolver, S::Error> {
307 Ok(())
308 }
309}
310
311impl<D: Fallible + ?Sized> Deserialize<isize, D> for ArchivedIsize {
312 fn deserialize(&self, _: &mut D) -> Result<isize, D::Error> {
313 Ok(self.to_native() as isize)
314 }
315}
316
317impl Archive for NonZeroUsize {
320 const COPY_OPTIMIZATION: CopyOptimization<Self> = unsafe {
321 CopyOptimization::enable_if(
322 MULTIBYTE_PRIMITIVES_ARE_TRIVIALLY_COPYABLE
323 && POINTER_WIDTH_EQUALS_ARCHIVED_POINTER_WIDTH,
324 )
325 };
326
327 type Archived = ArchivedNonZeroUsize;
328 type Resolver = ();
329
330 #[inline]
331 fn resolve(&self, _: Self::Resolver, out: Place<Self::Archived>) {
332 let value =
333 unsafe { ArchivedNonZeroUsize::new_unchecked(self.get() as _) };
334 out.write(value);
335 }
336}
337
338impl<S: Fallible + ?Sized> Serialize<S> for NonZeroUsize {
339 fn serialize(&self, _: &mut S) -> Result<Self::Resolver, S::Error> {
340 Ok(())
341 }
342}
343
344impl<D> Deserialize<NonZeroUsize, D> for ArchivedNonZeroUsize
345where
346 D: Fallible + ?Sized,
347{
348 fn deserialize(&self, _: &mut D) -> Result<NonZeroUsize, D::Error> {
349 Ok(unsafe { NonZeroUsize::new_unchecked(self.get() as usize) })
350 }
351}
352
353impl Archive for NonZeroIsize {
356 const COPY_OPTIMIZATION: CopyOptimization<Self> = unsafe {
357 CopyOptimization::enable_if(
358 MULTIBYTE_PRIMITIVES_ARE_TRIVIALLY_COPYABLE
359 && POINTER_WIDTH_EQUALS_ARCHIVED_POINTER_WIDTH,
360 )
361 };
362
363 type Archived = ArchivedNonZeroIsize;
364 type Resolver = ();
365
366 #[inline]
367 fn resolve(&self, _: Self::Resolver, out: Place<Self::Archived>) {
368 let value =
369 unsafe { ArchivedNonZeroIsize::new_unchecked(self.get() as _) };
370 out.write(value);
371 }
372}
373
374impl<S: Fallible + ?Sized> Serialize<S> for NonZeroIsize {
375 fn serialize(&self, _: &mut S) -> Result<Self::Resolver, S::Error> {
376 Ok(())
377 }
378}
379
380impl<D> Deserialize<NonZeroIsize, D> for ArchivedNonZeroIsize
381where
382 D: Fallible + ?Sized,
383{
384 fn deserialize(&self, _: &mut D) -> Result<NonZeroIsize, D::Error> {
385 Ok(unsafe { NonZeroIsize::new_unchecked(self.get() as isize) })
386 }
387}
388
389#[cfg(test)]
390mod tests {
391 use core::num::{
392 NonZeroI128, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI8,
393 NonZeroIsize, NonZeroU128, NonZeroU16, NonZeroU32, NonZeroU64,
394 NonZeroU8, NonZeroUsize,
395 };
396
397 use crate::api::test::{roundtrip, roundtrip_with};
398
399 #[test]
400 fn roundtrip_portable_primitives() {
401 roundtrip(&());
402 roundtrip(&true);
403 roundtrip(&false);
404 roundtrip(&123i8);
405 roundtrip(&123u8);
406 roundtrip(&NonZeroI8::new(123i8).unwrap());
407 roundtrip(&NonZeroU8::new(123u8).unwrap());
408 }
409
410 #[test]
411 fn roundtrip_multibyte_primitives() {
412 roundtrip(&12345i16);
413 roundtrip(&1234567890i32);
414 roundtrip(&1234567890123456789i64);
415 roundtrip(&123456789012345678901234567890123456789i128);
416 roundtrip(&12345u16);
417 roundtrip(&1234567890u32);
418 roundtrip(&12345678901234567890u64);
419 roundtrip(&123456789012345678901234567890123456789u128);
420
421 roundtrip(&1234567f32);
422 roundtrip(&12345678901234f64);
423
424 roundtrip(&'x');
425 roundtrip(&'🥺');
426
427 roundtrip(&NonZeroI16::new(12345i16).unwrap());
428 roundtrip(&NonZeroI32::new(1234567890i32).unwrap());
429 roundtrip(&NonZeroI64::new(1234567890123456789i64).unwrap());
430 roundtrip(
431 &NonZeroI128::new(123456789012345678901234567890123456789i128)
432 .unwrap(),
433 );
434 roundtrip(&NonZeroU16::new(12345u16).unwrap());
435 roundtrip(&NonZeroU32::new(1234567890u32).unwrap());
436 roundtrip(&NonZeroU64::new(12345678901234567890u64).unwrap());
437 roundtrip(
438 &NonZeroU128::new(123456789012345678901234567890123456789u128)
439 .unwrap(),
440 );
441 }
442
443 #[test]
444 fn roundtrip_sizes() {
445 roundtrip_with(&12345isize, |a, b| {
446 assert_eq!(*a, isize::try_from(b.to_native()).unwrap())
447 });
448 roundtrip_with(&12345usize, |a, b| {
449 assert_eq!(*a, usize::try_from(b.to_native()).unwrap())
450 });
451 roundtrip_with(&NonZeroIsize::new(12345isize).unwrap(), |a, b| {
452 assert_eq!(*a, NonZeroIsize::try_from(b.to_native()).unwrap())
453 });
454 roundtrip_with(&NonZeroUsize::new(12345usize).unwrap(), |a, b| {
455 assert_eq!(*a, NonZeroUsize::try_from(b.to_native()).unwrap())
456 });
457 }
458}