Skip to main content

rkyv/impls/core/
result.rs

1use core::hint::unreachable_unchecked;
2
3use munge::munge;
4use rancor::Fallible;
5
6use crate::{
7    result::ArchivedResult, traits::NoUndef, Archive, Deserialize, Place,
8    Serialize,
9};
10
11#[allow(dead_code)]
12#[repr(u8)]
13enum ArchivedResultTag {
14    Ok,
15    Err,
16}
17
18// SAFETY: `ArchivedResultTag` is `repr(u8)` and so always consists of a single
19// well-defined byte.
20unsafe impl NoUndef for ArchivedResultTag {}
21
22#[repr(C)]
23struct ArchivedResultVariantOk<T>(ArchivedResultTag, T);
24
25#[repr(C)]
26struct ArchivedResultVariantErr<U>(ArchivedResultTag, U);
27
28impl<T: Archive, U: Archive> Archive for Result<T, U> {
29    type Archived = ArchivedResult<T::Archived, U::Archived>;
30    type Resolver = Result<T::Resolver, U::Resolver>;
31
32    fn resolve(&self, resolver: Self::Resolver, out: Place<Self::Archived>) {
33        match resolver {
34            Ok(resolver) => {
35                let out = unsafe {
36                    out.cast_unchecked::<ArchivedResultVariantOk<T::Archived>>()
37                };
38                munge!(let ArchivedResultVariantOk(tag, out_value) = out);
39                tag.write(ArchivedResultTag::Ok);
40
41                match self.as_ref() {
42                    Ok(value) => value.resolve(resolver, out_value),
43                    Err(_) => unsafe { unreachable_unchecked() },
44                }
45            }
46            Err(resolver) => {
47                let out = unsafe {
48                    out.cast_unchecked::<ArchivedResultVariantErr<U::Archived>>(
49                    )
50                };
51                munge!(let ArchivedResultVariantErr(tag, out_err) = out);
52                tag.write(ArchivedResultTag::Err);
53
54                match self.as_ref() {
55                    Ok(_) => unsafe { unreachable_unchecked() },
56                    Err(err) => err.resolve(resolver, out_err),
57                }
58            }
59        }
60    }
61}
62
63impl<T, U, S> Serialize<S> for Result<T, U>
64where
65    T: Serialize<S>,
66    U: Serialize<S>,
67    S: Fallible + ?Sized,
68{
69    fn serialize(
70        &self,
71        serializer: &mut S,
72    ) -> Result<Self::Resolver, S::Error> {
73        Ok(match self.as_ref() {
74            Ok(value) => Ok(value.serialize(serializer)?),
75            Err(value) => Err(value.serialize(serializer)?),
76        })
77    }
78}
79
80impl<T, U, D> Deserialize<Result<T, U>, D>
81    for ArchivedResult<T::Archived, U::Archived>
82where
83    T: Archive,
84    U: Archive,
85    D: Fallible + ?Sized,
86    T::Archived: Deserialize<T, D>,
87    U::Archived: Deserialize<U, D>,
88{
89    fn deserialize(
90        &self,
91        deserializer: &mut D,
92    ) -> Result<Result<T, U>, D::Error> {
93        match self {
94            ArchivedResult::Ok(value) => {
95                Ok(Ok(value.deserialize(deserializer)?))
96            }
97            ArchivedResult::Err(err) => Ok(Err(err.deserialize(deserializer)?)),
98        }
99    }
100}
101
102#[cfg(test)]
103mod tests {
104    use crate::api::test::roundtrip;
105
106    #[test]
107    fn roundtrip_result() {
108        roundtrip(&Result::<i32, u32>::Ok(12345i32));
109        roundtrip(&Result::<i32, u32>::Err(12345u32));
110    }
111}