rkyv_test/impls/core/
option.rs

1use crate::{option::ArchivedOption, Archive, Deserialize, Fallible, Serialize};
2use core::{hint::unreachable_unchecked, ptr};
3
4#[allow(dead_code)]
5#[repr(u8)]
6enum ArchivedOptionTag {
7    None,
8    Some,
9}
10
11#[repr(C)]
12struct ArchivedOptionVariantNone(ArchivedOptionTag);
13
14#[repr(C)]
15struct ArchivedOptionVariantSome<T>(ArchivedOptionTag, T);
16
17impl<T: Archive> Archive for Option<T> {
18    type Archived = ArchivedOption<T::Archived>;
19    type Resolver = Option<T::Resolver>;
20
21    #[inline]
22    unsafe fn resolve(&self, pos: usize, resolver: Self::Resolver, out: *mut Self::Archived) {
23        match resolver {
24            None => {
25                let out = out.cast::<ArchivedOptionVariantNone>();
26                ptr::addr_of_mut!((*out).0).write(ArchivedOptionTag::None);
27            }
28            Some(resolver) => {
29                let out = out.cast::<ArchivedOptionVariantSome<T::Archived>>();
30                ptr::addr_of_mut!((*out).0).write(ArchivedOptionTag::Some);
31
32                let value = if let Some(value) = self.as_ref() {
33                    value
34                } else {
35                    unreachable_unchecked();
36                };
37
38                let (fp, fo) = out_field!(out.1);
39                value.resolve(pos + fp, resolver, fo);
40            }
41        }
42    }
43}
44
45impl<T: Serialize<S>, S: Fallible + ?Sized> Serialize<S> for Option<T> {
46    #[inline]
47    fn serialize(&self, serializer: &mut S) -> Result<Self::Resolver, S::Error> {
48        self.as_ref()
49            .map(|value| value.serialize(serializer))
50            .transpose()
51    }
52}
53
54impl<T: Archive, D: Fallible + ?Sized> Deserialize<Option<T>, D> for ArchivedOption<T::Archived>
55where
56    T::Archived: Deserialize<T, D>,
57{
58    #[inline]
59    fn deserialize(&self, deserializer: &mut D) -> Result<Option<T>, D::Error> {
60        match self {
61            ArchivedOption::Some(value) => Ok(Some(value.deserialize(deserializer)?)),
62            ArchivedOption::None => Ok(None),
63        }
64    }
65}