musli_zerocopy/pointer/pointee.rs
1use core::fmt;
2
3use crate::error::IntoRepr;
4use crate::pointer::Size;
5use crate::traits::ZeroCopy;
6
7mod sealed {
8 use crate::mem::MaybeUninit;
9 use crate::pointer::Pointee;
10 use crate::traits::ZeroCopy;
11
12 pub trait Sealed {}
13
14 impl<T> Sealed for MaybeUninit<T> where T: Pointee {}
15 impl<T> Sealed for T where T: ZeroCopy {}
16 impl<T> Sealed for [T] where T: ZeroCopy {}
17 impl Sealed for str {}
18}
19
20/// The trait for a value that can be pointed to by a [`Ref<T>`].
21///
22/// This ultimately determines the layout of [`Ref<T>`] as for unsized types it
23/// needs to accommodate the size of the pointed-to type as well.
24///
25/// ```
26/// use std::mem::size_of;
27///
28/// use musli_zerocopy::Ref;
29///
30/// assert_eq!(size_of::<Ref::<u32>>(), 4);
31/// assert_eq!(size_of::<Ref::<[u32]>>(), 8);
32/// ```
33///
34/// [`Ref<T>`]: crate::Ref
35pub trait Pointee: self::sealed::Sealed {
36 /// Metadata associated with a pointee.
37 type Metadata: Copy + fmt::Debug + IntoRepr;
38
39 /// The stored representation of the pointee metadata.
40 #[doc(hidden)]
41 type Stored<O>: Copy + ZeroCopy
42 where
43 O: Size;
44
45 /// Try to construct packed value from its metadata.
46 #[doc(hidden)]
47 fn try_from_metadata<O>(metadata: Self::Metadata) -> Option<Self::Stored<O>>
48 where
49 O: Size;
50}
51
52impl<T> Pointee for T
53where
54 T: ZeroCopy,
55{
56 type Metadata = ();
57 type Stored<O>
58 = ()
59 where
60 O: Size;
61
62 #[inline(always)]
63 fn try_from_metadata<O>((): ()) -> Option<Self::Stored<O>>
64 where
65 O: Size,
66 {
67 Some(())
68 }
69}
70
71impl<T> Pointee for [T]
72where
73 T: ZeroCopy,
74{
75 type Metadata = usize;
76 type Stored<O>
77 = O
78 where
79 O: Size;
80
81 #[inline(always)]
82 fn try_from_metadata<O>(metadata: usize) -> Option<O>
83 where
84 O: Size,
85 {
86 O::try_from_usize(metadata)
87 }
88}
89
90impl Pointee for str {
91 type Metadata = usize;
92 type Stored<O>
93 = O
94 where
95 O: Size;
96
97 #[inline(always)]
98 fn try_from_metadata<O>(metadata: usize) -> Option<O>
99 where
100 O: Size,
101 {
102 O::try_from_usize(metadata)
103 }
104}