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}