rkyv/impls/core/
mod.rs

1use core::{
2    alloc::{Layout, LayoutError},
3    marker::{PhantomData, PhantomPinned},
4    mem::{ManuallyDrop, MaybeUninit},
5    ptr::{self, addr_of_mut},
6    str,
7};
8
9use ptr_meta::Pointee;
10use rancor::Fallible;
11
12use crate::{
13    primitive::ArchivedUsize,
14    ser::{Allocator, Writer, WriterExt as _},
15    traits::{ArchivePointee, CopyOptimization, LayoutRaw, NoUndef},
16    tuple::*,
17    Archive, ArchiveUnsized, ArchivedMetadata, Deserialize, DeserializeUnsized,
18    Place, Portable, Serialize, SerializeUnsized,
19};
20
21mod ffi;
22mod net;
23mod ops;
24mod option;
25mod primitive;
26mod result;
27mod time;
28pub(crate) mod with;
29
30impl<T> LayoutRaw for T {
31    fn layout_raw(
32        _: <Self as Pointee>::Metadata,
33    ) -> Result<Layout, LayoutError> {
34        Ok(Layout::new::<T>())
35    }
36}
37
38impl<T> LayoutRaw for [T] {
39    fn layout_raw(
40        metadata: <Self as Pointee>::Metadata,
41    ) -> Result<Layout, LayoutError> {
42        Layout::array::<T>(metadata)
43    }
44}
45
46impl LayoutRaw for str {
47    #[inline]
48    fn layout_raw(
49        metadata: <Self as Pointee>::Metadata,
50    ) -> Result<Layout, LayoutError> {
51        Layout::array::<u8>(metadata)
52    }
53}
54
55impl<T> ArchivePointee for T {
56    type ArchivedMetadata = ();
57
58    fn pointer_metadata(
59        _: &Self::ArchivedMetadata,
60    ) -> <Self as Pointee>::Metadata {
61    }
62}
63
64impl<T: Archive> ArchiveUnsized for T {
65    type Archived = T::Archived;
66
67    fn archived_metadata(&self) -> ArchivedMetadata<Self> {}
68}
69
70impl<T, S> SerializeUnsized<S> for T
71where
72    T: Serialize<S>,
73    S: Fallible + Writer + ?Sized,
74{
75    fn serialize_unsized(&self, serializer: &mut S) -> Result<usize, S::Error> {
76        let resolver = self.serialize(serializer)?;
77        serializer.align_for::<T::Archived>()?;
78        unsafe { serializer.resolve_aligned(self, resolver) }
79    }
80}
81
82impl<T, D> DeserializeUnsized<T, D> for T::Archived
83where
84    T: Archive,
85    D: Fallible + ?Sized,
86    T::Archived: Deserialize<T, D>,
87{
88    unsafe fn deserialize_unsized(
89        &self,
90        deserializer: &mut D,
91        out: *mut T,
92    ) -> Result<(), D::Error> {
93        // SAFETY: The caller has guaranteed that `out` is non-null, properly
94        // aligned, valid for writes, and allocated according to the layout of
95        // the deserialized metadata (the unit type for sized types).
96        unsafe {
97            out.write(self.deserialize(deserializer)?);
98        }
99        Ok(())
100    }
101
102    fn deserialize_metadata(&self) -> <T as Pointee>::Metadata {}
103}
104
105macro_rules! impl_tuple {
106    ($name:ident, $($type:ident $index:tt),*) => {
107        impl<$($type),*> Archive for ($($type,)*)
108        where
109            $($type: Archive,)*
110        {
111            type Archived = $name<$($type::Archived,)*>;
112            type Resolver = ($($type::Resolver,)*);
113
114            fn resolve(
115                &self,
116                resolver: Self::Resolver,
117                out: Place<Self::Archived>,
118            ) {
119                // SAFETY: This pointer will only be used to manually project
120                // to each of the fields to wrap them in a `Place` again.
121                let out_ptr = unsafe { out.ptr() };
122                $(
123                    // SAFETY: `out_ptr` is guaranteed to be properly aligned
124                    // and dereferenceable.
125                    let ptr = unsafe { addr_of_mut!((*out_ptr).$index) };
126                    // SAFETY:
127                    // - `ptr` points to the `$index` field of `out`
128                    // - `ptr` is properly aligned, dereferenceable, and all of
129                    //   its bytes are initialized
130                    let out_field = unsafe {
131                        Place::from_field_unchecked(out, ptr)
132                    };
133                    self.$index.resolve(resolver.$index, out_field);
134                )*
135            }
136        }
137
138        impl<$($type,)* S> Serialize<S> for ($($type,)*)
139        where
140            $($type: Serialize<S>,)*
141            S: Fallible + ?Sized,
142        {
143            fn serialize(
144                &self,
145                serializer: &mut S,
146            ) -> Result<Self::Resolver, S::Error> {
147                Ok((
148                    $(self.$index.serialize(serializer)?,)*
149                ))
150            }
151        }
152
153        impl<$($type,)* D> Deserialize<($($type,)*), D>
154            for $name<$($type::Archived,)*>
155        where
156            D: Fallible + ?Sized,
157            $($type: Archive,)*
158            $($type::Archived: Deserialize<$type, D>,)*
159        {
160            fn deserialize(
161                &self,
162                deserializer: &mut D,
163            ) -> Result<($($type,)*), D::Error> {
164                Ok((
165                    $(self.$index.deserialize(deserializer)?,)*
166                ))
167            }
168        }
169    };
170}
171
172impl_tuple!(ArchivedTuple1, T0 0);
173impl_tuple!(ArchivedTuple2, T0 0, T1 1);
174impl_tuple!(ArchivedTuple3, T0 0, T1 1, T2 2);
175impl_tuple!(ArchivedTuple4, T0 0, T1 1, T2 2, T3 3);
176impl_tuple!(ArchivedTuple5, T0 0, T1 1, T2 2, T3 3, T4 4);
177impl_tuple!(ArchivedTuple6, T0 0, T1 1, T2 2, T3 3, T4 4, T5 5);
178impl_tuple!(ArchivedTuple7, T0 0, T1 1, T2 2, T3 3, T4 4, T5 5, T6 6);
179impl_tuple!(ArchivedTuple8, T0 0, T1 1, T2 2, T3 3, T4 4, T5 5, T6 6, T7 7);
180impl_tuple!(
181    ArchivedTuple9, T0 0, T1 1, T2 2, T3 3, T4 4, T5 5, T6 6, T7 7, T8 8
182);
183impl_tuple!(
184    ArchivedTuple10, T0 0, T1 1, T2 2, T3 3, T4 4, T5 5, T6 6, T7 7, T8 8, T9 9
185);
186impl_tuple!(
187    ArchivedTuple11, T0 0, T1 1, T2 2, T3 3, T4 4, T5 5, T6 6, T7 7, T8 8, T9 9,
188    T10 10
189);
190impl_tuple!(
191    ArchivedTuple12, T0 0, T1 1, T2 2, T3 3, T4 4, T5 5, T6 6, T7 7, T8 8, T9 9,
192    T10 10, T11 11
193);
194impl_tuple!(
195    ArchivedTuple13, T0 0, T1 1, T2 2, T3 3, T4 4, T5 5, T6 6, T7 7, T8 8, T9 9,
196    T10 10, T11 11, T12 12
197);
198
199// Arrays
200
201// SAFETY: `[T; N]` is a `T` array and so is portable as long as `T` is also
202// `Portable`.
203unsafe impl<T: Portable, const N: usize> Portable for [T; N] {}
204
205impl<T: Archive, const N: usize> Archive for [T; N] {
206    const COPY_OPTIMIZATION: CopyOptimization<Self> = unsafe {
207        CopyOptimization::enable_if(T::COPY_OPTIMIZATION.is_enabled())
208    };
209
210    type Archived = [T::Archived; N];
211    type Resolver = [T::Resolver; N];
212
213    fn resolve(&self, resolver: Self::Resolver, out: Place<Self::Archived>) {
214        for (i, (value, resolver)) in self.iter().zip(resolver).enumerate() {
215            let out_i = unsafe { out.index(i) };
216            value.resolve(resolver, out_i);
217        }
218    }
219}
220
221impl<T, S, const N: usize> Serialize<S> for [T; N]
222where
223    T: Serialize<S>,
224    S: Fallible + ?Sized,
225{
226    fn serialize(
227        &self,
228        serializer: &mut S,
229    ) -> Result<Self::Resolver, S::Error> {
230        let mut result = core::mem::MaybeUninit::<Self::Resolver>::uninit();
231        let result_ptr = result.as_mut_ptr().cast::<T::Resolver>();
232        for (i, value) in self.iter().enumerate() {
233            unsafe {
234                result_ptr.add(i).write(value.serialize(serializer)?);
235            }
236        }
237        unsafe { Ok(result.assume_init()) }
238    }
239}
240
241impl<T, D, const N: usize> Deserialize<[T; N], D> for [T::Archived; N]
242where
243    T: Archive,
244    T::Archived: Deserialize<T, D>,
245    D: Fallible + ?Sized,
246{
247    fn deserialize(&self, deserializer: &mut D) -> Result<[T; N], D::Error> {
248        let mut result = core::mem::MaybeUninit::<[T; N]>::uninit();
249        let result_ptr = result.as_mut_ptr().cast::<T>();
250        for (i, value) in self.iter().enumerate() {
251            unsafe {
252                result_ptr.add(i).write(value.deserialize(deserializer)?);
253            }
254        }
255        unsafe { Ok(result.assume_init()) }
256    }
257}
258
259// Slices
260
261// SAFETY: `[T]` is a `T` slice and so is portable as long as `T` is also
262// `Portable`.
263unsafe impl<T: Portable> Portable for [T] {}
264
265impl<T: Archive> ArchiveUnsized for [T] {
266    type Archived = [T::Archived];
267
268    fn archived_metadata(&self) -> ArchivedMetadata<Self> {
269        ArchivedUsize::from_native(ptr_meta::metadata(self) as _)
270    }
271}
272
273impl<T> ArchivePointee for [T] {
274    type ArchivedMetadata = ArchivedUsize;
275
276    fn pointer_metadata(
277        archived: &Self::ArchivedMetadata,
278    ) -> <Self as Pointee>::Metadata {
279        archived.to_native() as usize
280    }
281}
282
283impl<T, S> SerializeUnsized<S> for [T]
284where
285    T: Serialize<S>,
286    S: Fallible + Allocator + Writer + ?Sized,
287{
288    fn serialize_unsized(&self, serializer: &mut S) -> Result<usize, S::Error> {
289        if T::COPY_OPTIMIZATION.is_enabled() {
290            let result = serializer.align_for::<T::Archived>()?;
291            let as_bytes = unsafe {
292                core::slice::from_raw_parts(
293                    self.as_ptr().cast::<u8>(),
294                    core::mem::size_of_val(self),
295                )
296            };
297            serializer.write(as_bytes)?;
298
299            Ok(result)
300        } else {
301            use crate::util::SerVec;
302
303            SerVec::with_capacity(
304                serializer,
305                self.len(),
306                |resolvers, serializer| {
307                    for value in self.iter() {
308                        unsafe {
309                            resolvers
310                                .push_unchecked(value.serialize(serializer)?);
311                        }
312                    }
313
314                    let result = serializer.align_for::<T::Archived>()?;
315
316                    for (value, resolver) in self.iter().zip(resolvers.drain())
317                    {
318                        unsafe {
319                            serializer.resolve_aligned(value, resolver)?;
320                        }
321                    }
322
323                    Ok(result)
324                },
325            )?
326        }
327    }
328}
329
330impl<T, U, D> DeserializeUnsized<[U], D> for [T]
331where
332    T: Deserialize<U, D>,
333    D: Fallible + ?Sized,
334{
335    unsafe fn deserialize_unsized(
336        &self,
337        deserializer: &mut D,
338        out: *mut [U],
339    ) -> Result<(), D::Error> {
340        for (i, item) in self.iter().enumerate() {
341            // SAFETY: The caller has guaranteed that `out` points to a slice
342            // with a length guaranteed to match the length of `self`. Since `i`
343            // is less than the length of the slice, the result of the pointer
344            // add is always in-bounds.
345            let out_ptr = unsafe { out.cast::<U>().add(i) };
346            // SAFETY: `out_ptr` points to an element of `out` and so is
347            // guaranteed to be non-null, properly aligned, and valid for
348            // writes.
349            unsafe {
350                out_ptr.write(item.deserialize(deserializer)?);
351            }
352        }
353        Ok(())
354    }
355
356    fn deserialize_metadata(&self) -> <[U] as Pointee>::Metadata {
357        ptr_meta::metadata(self)
358    }
359}
360
361// `str`
362
363// SAFETY: `str` is a byte slice and so has a stable, well-defined layout that
364// is the same on all targets. It doesn't have any interior mutability.
365unsafe impl Portable for str {}
366
367// SAFETY: `str` is a byte slice and so does not contain any uninit bytes.
368unsafe impl NoUndef for str {}
369
370impl ArchiveUnsized for str {
371    type Archived = str;
372
373    #[inline]
374    fn archived_metadata(&self) -> ArchivedMetadata<Self> {
375        ArchivedUsize::from_native(ptr_meta::metadata(self) as _)
376    }
377}
378
379impl ArchivePointee for str {
380    type ArchivedMetadata = ArchivedUsize;
381
382    #[inline]
383    fn pointer_metadata(
384        archived: &Self::ArchivedMetadata,
385    ) -> <Self as Pointee>::Metadata {
386        <[u8]>::pointer_metadata(archived)
387    }
388}
389
390impl<S: Fallible + Writer + ?Sized> SerializeUnsized<S> for str {
391    fn serialize_unsized(&self, serializer: &mut S) -> Result<usize, S::Error> {
392        let result = serializer.pos();
393        serializer.write(self.as_bytes())?;
394        Ok(result)
395    }
396}
397
398impl<D: Fallible + ?Sized> DeserializeUnsized<str, D> for str {
399    unsafe fn deserialize_unsized(
400        &self,
401        _: &mut D,
402        out: *mut str,
403    ) -> Result<(), D::Error> {
404        // SAFETY: The caller has guaranteed that `out` is non-null, properly
405        // aligned, valid for writes, and points to memory allocated according
406        // to the layout for the metadata returned from `deserialize_metadata`.
407        // Therefore, `out` points to at least `self.len()` bytes.
408        // `self.as_ptr()` is valid for reads and points to the bytes of `self`
409        // which are also at least `self.len()` bytes.
410        unsafe {
411            ptr::copy_nonoverlapping(
412                self.as_ptr(),
413                out.cast::<u8>(),
414                self.len(),
415            );
416        }
417        Ok(())
418    }
419
420    fn deserialize_metadata(&self) -> <str as Pointee>::Metadata {
421        ptr_meta::metadata(self)
422    }
423}
424
425// PhantomData
426
427// SAFETY: `PhantomData` always a size of 0 and align of 1, and so has a stable,
428// well-defined layout that is the same on all targets.
429unsafe impl<T: ?Sized> Portable for PhantomData<T> {}
430
431impl<T: ?Sized> Archive for PhantomData<T> {
432    const COPY_OPTIMIZATION: CopyOptimization<Self> =
433        unsafe { CopyOptimization::enable() };
434
435    type Archived = PhantomData<T>;
436    type Resolver = ();
437
438    fn resolve(&self, _: Self::Resolver, _: Place<Self::Archived>) {}
439}
440
441impl<T: ?Sized, S: Fallible + ?Sized> Serialize<S> for PhantomData<T> {
442    fn serialize(&self, _: &mut S) -> Result<Self::Resolver, S::Error> {
443        Ok(())
444    }
445}
446
447impl<T: ?Sized, D: Fallible + ?Sized> Deserialize<PhantomData<T>, D>
448    for PhantomData<T>
449{
450    fn deserialize(&self, _: &mut D) -> Result<PhantomData<T>, D::Error> {
451        Ok(PhantomData)
452    }
453}
454
455// PhantomPinned
456
457// SAFETY: `PhantomPinned` always a size of 0 and align of 1, and so has a
458// stable, well-defined layout that is the same on all targets.
459unsafe impl Portable for PhantomPinned {}
460
461impl Archive for PhantomPinned {
462    const COPY_OPTIMIZATION: CopyOptimization<Self> =
463        unsafe { CopyOptimization::enable() };
464
465    type Archived = PhantomPinned;
466    type Resolver = ();
467
468    #[inline]
469    fn resolve(&self, _: Self::Resolver, _: Place<Self::Archived>) {}
470}
471
472impl<S: Fallible + ?Sized> Serialize<S> for PhantomPinned {
473    fn serialize(&self, _: &mut S) -> Result<Self::Resolver, S::Error> {
474        Ok(())
475    }
476}
477
478impl<D: Fallible + ?Sized> Deserialize<PhantomPinned, D> for PhantomPinned {
479    fn deserialize(&self, _: &mut D) -> Result<PhantomPinned, D::Error> {
480        Ok(PhantomPinned)
481    }
482}
483
484// `ManuallyDrop`
485
486// SAFETY: `ManuallyDrop<T>` is guaranteed to have the same layout and bit
487// validity as `T`, so it is `Portable` when `T` is `Portable`.
488unsafe impl<T: Portable> Portable for ManuallyDrop<T> {}
489
490impl<T: Archive> Archive for ManuallyDrop<T> {
491    const COPY_OPTIMIZATION: CopyOptimization<Self> = unsafe {
492        CopyOptimization::enable_if(T::COPY_OPTIMIZATION.is_enabled())
493    };
494
495    type Archived = ManuallyDrop<T::Archived>;
496    type Resolver = T::Resolver;
497
498    fn resolve(&self, resolver: Self::Resolver, out: Place<Self::Archived>) {
499        let out_inner = unsafe { out.cast_unchecked::<T::Archived>() };
500        T::resolve(self, resolver, out_inner)
501    }
502}
503
504impl<T: Serialize<S>, S: Fallible + ?Sized> Serialize<S> for ManuallyDrop<T> {
505    fn serialize(
506        &self,
507        serializer: &mut S,
508    ) -> Result<Self::Resolver, S::Error> {
509        T::serialize(self, serializer)
510    }
511}
512
513impl<T, D> Deserialize<ManuallyDrop<T>, D> for ManuallyDrop<T::Archived>
514where
515    T: Archive,
516    T::Archived: Deserialize<T, D>,
517    D: Fallible + ?Sized,
518{
519    fn deserialize(
520        &self,
521        deserializer: &mut D,
522    ) -> Result<ManuallyDrop<T>, D::Error> {
523        T::Archived::deserialize(self, deserializer).map(ManuallyDrop::new)
524    }
525}
526
527// `MaybeUninit`
528
529// SAFETY: `MaybeUninit` is guaranteed to have the same layout as `T`, and `T`
530// is portable. `MaybeUninit` does not have interior mutability.
531unsafe impl<T: Portable> Portable for MaybeUninit<T> {}
532
533#[cfg(test)]
534mod tests {
535    use core::{
536        marker::{PhantomData, PhantomPinned},
537        mem::ManuallyDrop,
538    };
539
540    use crate::{
541        api::test::{roundtrip, roundtrip_with},
542        tuple::ArchivedTuple3,
543    };
544
545    #[test]
546    fn roundtrip_tuple() {
547        roundtrip_with(
548            &(24, true, 16f32),
549            |(a, b, c), ArchivedTuple3(d, e, f)| {
550                assert_eq!(a, d);
551                assert_eq!(b, e);
552                assert_eq!(c, f);
553            },
554        );
555    }
556
557    #[test]
558    fn roundtrip_array() {
559        roundtrip(&[1, 2, 3, 4, 5, 6]);
560        roundtrip(&[(); 0]);
561        roundtrip(&[(), (), (), ()]);
562    }
563
564    #[test]
565    fn roundtrip_phantoms() {
566        roundtrip(&PhantomData::<&'static u8>);
567        roundtrip(&PhantomPinned);
568    }
569
570    #[test]
571    fn roundtrip_manually_drop() {
572        roundtrip(&ManuallyDrop::new(123i8));
573    }
574}