rkyv/impls/alloc/
boxed.rs

1use core::cmp;
2
3use rancor::{Fallible, ResultExt as _, Source};
4
5use crate::{
6    alloc::{
7        alloc::{alloc, handle_alloc_error},
8        boxed::Box,
9    },
10    boxed::{ArchivedBox, BoxResolver},
11    niche::option_box::ArchivedOptionBox,
12    traits::{ArchivePointee, LayoutRaw},
13    Archive, ArchiveUnsized, Deserialize, DeserializeUnsized, Place, Serialize,
14    SerializeUnsized,
15};
16
17impl<T: ArchiveUnsized + ?Sized> Archive for Box<T> {
18    type Archived = ArchivedBox<T::Archived>;
19    type Resolver = BoxResolver;
20
21    fn resolve(&self, resolver: Self::Resolver, out: Place<Self::Archived>) {
22        ArchivedBox::resolve_from_ref(self.as_ref(), resolver, out);
23    }
24}
25
26impl<T, S> Serialize<S> for Box<T>
27where
28    T: SerializeUnsized<S> + ?Sized,
29    S: Fallible + ?Sized,
30{
31    fn serialize(
32        &self,
33        serializer: &mut S,
34    ) -> Result<Self::Resolver, S::Error> {
35        ArchivedBox::serialize_from_ref(self.as_ref(), serializer)
36    }
37}
38
39impl<T, D> Deserialize<Box<T>, D> for ArchivedBox<T::Archived>
40where
41    T: ArchiveUnsized + LayoutRaw + ?Sized,
42    T::Archived: DeserializeUnsized<T, D>,
43    D: Fallible + ?Sized,
44    D::Error: Source,
45{
46    fn deserialize(&self, deserializer: &mut D) -> Result<Box<T>, D::Error> {
47        let metadata = self.get().deserialize_metadata();
48        let layout = T::layout_raw(metadata).into_error()?;
49        let data_address = if layout.size() > 0 {
50            let ptr = unsafe { alloc(layout) };
51            if ptr.is_null() {
52                handle_alloc_error(layout);
53            }
54            ptr
55        } else {
56            crate::polyfill::dangling(&layout).as_ptr()
57        };
58
59        let out = ptr_meta::from_raw_parts_mut(data_address.cast(), metadata);
60
61        unsafe {
62            self.get().deserialize_unsized(deserializer, out)?;
63        }
64        unsafe { Ok(Box::from_raw(out)) }
65    }
66}
67
68impl<T, U> PartialEq<Box<U>> for ArchivedBox<T>
69where
70    T: ArchivePointee + PartialEq<U> + ?Sized,
71    U: ?Sized,
72{
73    fn eq(&self, other: &Box<U>) -> bool {
74        self.get().eq(other.as_ref())
75    }
76}
77
78impl<T, U> PartialOrd<Box<U>> for ArchivedBox<T>
79where
80    T: ArchivePointee + PartialOrd<U> + ?Sized,
81    U: ?Sized,
82{
83    fn partial_cmp(&self, other: &Box<U>) -> Option<cmp::Ordering> {
84        self.get().partial_cmp(other.as_ref())
85    }
86}
87
88impl<T, U> PartialEq<Option<Box<T>>> for ArchivedOptionBox<U>
89where
90    T: ?Sized,
91    U: ArchivePointee + PartialEq<T> + ?Sized,
92{
93    fn eq(&self, other: &Option<Box<T>>) -> bool {
94        match (self.as_deref(), other.as_deref()) {
95            (Some(self_value), Some(other_value)) => self_value.eq(other_value),
96            (None, None) => true,
97            _ => false,
98        }
99    }
100}
101
102#[cfg(test)]
103mod tests {
104    use crate::{
105        alloc::{boxed::Box, string::ToString, vec, vec::Vec},
106        api::test::roundtrip,
107    };
108
109    #[test]
110    fn roundtrip_box() {
111        roundtrip(&Box::new(42));
112        roundtrip(&Box::new([1, 2, 3, 4, 5, 6]));
113    }
114
115    #[test]
116    fn roundtrip_boxed_str() {
117        roundtrip(&"".to_string().into_boxed_str());
118        roundtrip(&"hello world".to_string().into_boxed_str());
119    }
120
121    #[test]
122    fn roundtrip_boxed_slice() {
123        roundtrip(&Vec::<i32>::new().into_boxed_slice());
124        roundtrip(&vec![1, 2, 3, 4].into_boxed_slice());
125    }
126
127    #[test]
128    fn roundtrip_box_zsts() {
129        roundtrip(&Box::new(()));
130        roundtrip(&Vec::<()>::new().into_boxed_slice());
131        roundtrip(&vec![(), (), (), ()].into_boxed_slice());
132    }
133
134    #[test]
135    fn roundtrip_option_box() {
136        roundtrip(&Some(Box::new(42)));
137        roundtrip(&Some(Box::new([1, 2, 3, 4, 5, 6])));
138    }
139
140    #[test]
141    fn roundtrip_option_box_str() {
142        roundtrip(&Some("".to_string().into_boxed_str()));
143        roundtrip(&Some("hello world".to_string().into_boxed_str()));
144    }
145
146    #[test]
147    fn roundtrip_option_box_slice() {
148        roundtrip(&Some(Vec::<i32>::new().into_boxed_slice()));
149        roundtrip(&Some(vec![1, 2, 3, 4].into_boxed_slice()));
150    }
151
152    #[test]
153    fn roundtrip_result_box() {
154        roundtrip(&Ok::<_, ()>(Box::new(42)));
155        roundtrip(&Ok::<_, ()>(Box::new([1, 2, 3, 4, 5, 6])));
156
157        roundtrip(&Err::<(), _>(Box::new(42)));
158        roundtrip(&Err::<(), _>(Box::new([1, 2, 3, 4, 5, 6])));
159    }
160
161    #[test]
162    fn roundtrip_result_box_str() {
163        roundtrip(&Ok::<_, ()>("".to_string().into_boxed_str()));
164        roundtrip(&Ok::<_, ()>("hello world".to_string().into_boxed_str()));
165
166        roundtrip(&Err::<(), _>("".to_string().into_boxed_str()));
167        roundtrip(&Err::<(), _>("hello world".to_string().into_boxed_str()));
168    }
169
170    #[test]
171    fn roundtrip_result_box_slice() {
172        roundtrip(&Ok::<_, ()>(Vec::<i32>::new().into_boxed_slice()));
173        roundtrip(&Ok::<_, ()>(vec![1, 2, 3, 4].into_boxed_slice()));
174
175        roundtrip(&Err::<(), _>(Vec::<i32>::new().into_boxed_slice()));
176        roundtrip(&Err::<(), _>(vec![1, 2, 3, 4].into_boxed_slice()));
177    }
178}