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}