rkyv/impls/alloc/
boxed.rs

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