musli_zerocopy/pointer/
pointee.rs1use core::alloc::{Layout, LayoutError};
2use core::mem::size_of;
3
4use crate::error::CoerceError;
5use crate::pointer::Size;
6use crate::traits::ZeroCopy;
7
8mod sealed {
9 use crate::mem::MaybeUninit;
10 use crate::pointer::Pointee;
11 use crate::traits::ZeroCopy;
12
13 pub trait Sealed {}
14
15 impl<T> Sealed for MaybeUninit<T> where T: Pointee {}
16 impl<T> Sealed for T where T: ZeroCopy {}
17 impl<T> Sealed for [T] where T: ZeroCopy {}
18 impl Sealed for str {}
19}
20
21pub trait Pointee: self::sealed::Sealed {
37 type Metadata: Copy;
39
40 #[doc(hidden)]
42 type Stored<O>: Copy + ZeroCopy
43 where
44 O: Size;
45
46 #[doc(hidden)]
48 fn try_from_metadata<O>(metadata: Self::Metadata) -> Result<Self::Stored<O>, CoerceError>
49 where
50 O: Size;
51
52 #[doc(hidden)]
54 fn size<O>(metadata: Self::Stored<O>) -> Option<usize>
55 where
56 O: Size;
57
58 #[doc(hidden)]
60 fn align<O>(metadata: Self::Stored<O>) -> usize
61 where
62 O: Size;
63
64 #[doc(hidden)]
66 fn pointee_layout<O>(metadata: Self::Stored<O>) -> Result<Layout, LayoutError>
67 where
68 O: Size;
69}
70
71impl<T> Pointee for T
72where
73 T: ZeroCopy,
74{
75 type Metadata = ();
76 type Stored<O>
77 = ()
78 where
79 O: Size;
80
81 #[inline(always)]
82 fn try_from_metadata<O>((): ()) -> Result<Self::Stored<O>, CoerceError>
83 where
84 O: Size,
85 {
86 Ok(())
87 }
88
89 #[inline(always)]
90 fn size<O>((): Self::Stored<O>) -> Option<usize>
91 where
92 O: Size,
93 {
94 Some(size_of::<T>())
95 }
96
97 #[inline(always)]
98 fn align<O>((): Self::Stored<O>) -> usize
99 where
100 O: Size,
101 {
102 align_of::<T>()
103 }
104
105 #[inline(always)]
106 fn pointee_layout<O>((): Self::Stored<O>) -> Result<Layout, LayoutError>
107 where
108 O: Size,
109 {
110 Ok(Layout::new::<T>())
111 }
112}
113
114impl<T> Pointee for [T]
115where
116 T: ZeroCopy,
117{
118 type Metadata = usize;
119 type Stored<O>
120 = O
121 where
122 O: Size;
123
124 #[inline(always)]
125 fn try_from_metadata<O>(metadata: usize) -> Result<O, CoerceError>
126 where
127 O: Size,
128 {
129 O::try_from_usize(metadata)
130 }
131
132 #[inline(always)]
133 fn size<O>(metadata: Self::Stored<O>) -> Option<usize>
134 where
135 O: Size,
136 {
137 let len = metadata.as_usize();
138 size_of::<T>().checked_mul(len)
139 }
140
141 #[inline(always)]
142 fn align<O>(_: Self::Stored<O>) -> usize
143 where
144 O: Size,
145 {
146 align_of::<T>()
147 }
148
149 #[inline(always)]
150 fn pointee_layout<O>(metadata: Self::Stored<O>) -> Result<Layout, LayoutError>
151 where
152 O: Size,
153 {
154 let len = metadata.as_usize();
155 Layout::array::<T>(len)
156 }
157}
158
159impl Pointee for str {
160 type Metadata = usize;
161 type Stored<O>
162 = O
163 where
164 O: Size;
165
166 #[inline(always)]
167 fn try_from_metadata<O>(metadata: usize) -> Result<O, CoerceError>
168 where
169 O: Size,
170 {
171 O::try_from_usize(metadata)
172 }
173
174 #[inline(always)]
175 fn size<O>(metadata: Self::Stored<O>) -> Option<usize>
176 where
177 O: Size,
178 {
179 Some(metadata.as_usize())
180 }
181
182 #[inline(always)]
183 fn align<O>(_: Self::Stored<O>) -> usize
184 where
185 O: Size,
186 {
187 align_of::<u8>()
188 }
189
190 #[inline(always)]
191 fn pointee_layout<O>(metadata: Self::Stored<O>) -> Result<Layout, LayoutError>
192 where
193 O: Size,
194 {
195 Layout::array::<u8>(metadata.as_usize())
196 }
197}