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