1use core::{borrow::Borrow, cmp, fmt, hash, ops::Deref};
4
5use munge::munge;
6use rancor::Fallible;
7
8use crate::{
9 primitive::FixedUsize, seal::Seal, traits::ArchivePointee, ArchiveUnsized,
10 Place, Portable, RelPtr, SerializeUnsized,
11};
12
13#[derive(Portable)]
18#[rkyv(crate)]
19#[cfg_attr(
20 feature = "bytecheck",
21 derive(bytecheck::CheckBytes),
22 bytecheck(verify)
23)]
24#[repr(transparent)]
25pub struct ArchivedBox<T: ArchivePointee + ?Sized> {
26 ptr: RelPtr<T>,
27}
28
29impl<T: ArchivePointee + ?Sized> ArchivedBox<T> {
30 pub fn get(&self) -> &T {
32 unsafe { &*self.ptr.as_ptr() }
33 }
34
35 pub fn get_seal(this: Seal<'_, Self>) -> Seal<'_, T> {
37 munge!(let Self { ptr } = this);
38 Seal::new(unsafe { &mut *RelPtr::as_mut_ptr(ptr) })
39 }
40
41 pub fn resolve_from_ref<U: ArchiveUnsized<Archived = T> + ?Sized>(
43 value: &U,
44 resolver: BoxResolver,
45 out: Place<Self>,
46 ) {
47 Self::resolve_from_raw_parts(resolver, value.archived_metadata(), out)
48 }
49
50 pub fn serialize_from_ref<U, S>(
52 value: &U,
53 serializer: &mut S,
54 ) -> Result<BoxResolver, S::Error>
55 where
56 U: SerializeUnsized<S, Archived = T> + ?Sized,
57 S: Fallible + ?Sized,
58 {
59 Ok(BoxResolver {
60 pos: value.serialize_unsized(serializer)? as FixedUsize,
61 })
62 }
63
64 pub fn resolve_from_raw_parts(
67 resolver: BoxResolver,
68 metadata: T::ArchivedMetadata,
69 out: Place<Self>,
70 ) {
71 munge!(let ArchivedBox { ptr } = out);
72 RelPtr::emplace_unsized(resolver.pos as usize, metadata, ptr);
73 }
74}
75
76impl<T: ArchivePointee + ?Sized> AsRef<T> for ArchivedBox<T> {
77 fn as_ref(&self) -> &T {
78 self.get()
79 }
80}
81
82impl<T: ArchivePointee + ?Sized> Borrow<T> for ArchivedBox<T> {
83 fn borrow(&self) -> &T {
84 self.get()
85 }
86}
87
88impl<T: ArchivePointee + ?Sized> fmt::Debug for ArchivedBox<T>
89where
90 T::ArchivedMetadata: fmt::Debug,
91{
92 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
93 f.debug_tuple("ArchivedBox").field(&self.ptr).finish()
94 }
95}
96
97impl<T: ArchivePointee + ?Sized> Deref for ArchivedBox<T> {
98 type Target = T;
99
100 fn deref(&self) -> &Self::Target {
101 self.get()
102 }
103}
104
105impl<T: ArchivePointee + fmt::Display + ?Sized> fmt::Display
106 for ArchivedBox<T>
107{
108 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
109 self.get().fmt(f)
110 }
111}
112
113impl<T: ArchivePointee + Eq + ?Sized> Eq for ArchivedBox<T> {}
114
115impl<T: ArchivePointee + hash::Hash + ?Sized> hash::Hash for ArchivedBox<T> {
116 fn hash<H: hash::Hasher>(&self, state: &mut H) {
117 self.get().hash(state);
118 }
119}
120
121impl<T: ArchivePointee + Ord + ?Sized> Ord for ArchivedBox<T> {
122 fn cmp(&self, other: &Self) -> cmp::Ordering {
123 self.as_ref().cmp(other.as_ref())
124 }
125}
126
127impl<T: ArchivePointee + PartialEq<U> + ?Sized, U: ArchivePointee + ?Sized>
128 PartialEq<ArchivedBox<U>> for ArchivedBox<T>
129{
130 fn eq(&self, other: &ArchivedBox<U>) -> bool {
131 self.get().eq(other.get())
132 }
133}
134
135impl<T: ArchivePointee + PartialOrd + ?Sized> PartialOrd for ArchivedBox<T> {
136 fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
137 self.get().partial_cmp(other.get())
138 }
139}
140
141impl<T: ArchivePointee + ?Sized> fmt::Pointer for ArchivedBox<T> {
142 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
143 let ptr = self.get() as *const T;
144 fmt::Pointer::fmt(&ptr, f)
145 }
146}
147
148pub struct BoxResolver {
150 pos: FixedUsize,
151}
152
153impl BoxResolver {
154 pub fn from_pos(pos: usize) -> Self {
159 Self {
160 pos: pos as FixedUsize,
161 }
162 }
163}
164
165#[cfg(feature = "bytecheck")]
166mod verify {
167 use bytecheck::{
168 rancor::{Fallible, Source},
169 CheckBytes, Verify,
170 };
171
172 use crate::{
173 boxed::ArchivedBox,
174 traits::{ArchivePointee, LayoutRaw},
175 validation::{ArchiveContext, ArchiveContextExt},
176 };
177
178 unsafe impl<T, C> Verify<C> for ArchivedBox<T>
179 where
180 T: ArchivePointee + CheckBytes<C> + LayoutRaw + ?Sized,
181 T::ArchivedMetadata: CheckBytes<C>,
182 C: Fallible + ArchiveContext + ?Sized,
183 C::Error: Source,
184 {
185 fn verify(&self, context: &mut C) -> Result<(), C::Error> {
186 let ptr = self.ptr.as_ptr_wrapping();
187 context.in_subtree(ptr, |context| unsafe {
188 T::check_bytes(ptr, context)
189 })
190 }
191 }
192}