1use crate::{can_cast_u32, const_can_cast_u32, to_u32};
2use crate::sealed::AadSealed as Sealed;
3use core::fmt;
4
5
6#[allow(clippy::missing_safety_doc)]
8pub unsafe trait Aad: Sealed {
9 #[doc(hidden)]
19 #[must_use]
20 fn try_size(&self) -> Option<u32>;
21
22 #[doc(hidden)]
34 #[must_use]
35 fn ptr(&self) -> *const u8;
36
37 #[doc(hidden)]
49 #[must_use]
50 unsafe fn size(&self) -> u32;
51
52 #[doc(hidden)]
56 #[must_use]
57 fn is_valid_size(&self) -> bool;
58}
59
60#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
62#[repr(transparent)]
63pub struct AadSlice<'s> {
64 inner: Option<&'s [u8]>
65}
66
67impl<'s> fmt::Debug for AadSlice<'s> {
68 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
69 f.write_str("AadSlice(")
70 .and_then(|()| match self.inner {
71 None => f.write_str("EMPTY"),
72 Some(inner) => <[u8] as fmt::Debug>::fmt(inner, f)
73 })
74 .and_then(|()| f.write_str(")"))
75 }
76}
77
78impl<'a> PartialEq<[u8]> for AadSlice<'a> {
79 #[inline]
80 fn eq(&self, other: &[u8]) -> bool {
81 self.inner.is_some_and(|inner| inner == other)
82 }
83}
84
85impl<'s> AadSlice<'s> {
86 pub const EMPTY: Self = Self { inner: None };
88
89 pub const fn new(aad: &'s [u8]) -> Self {
91 Self { inner: Some(aad) }
92 }
93
94 #[inline]
96 pub(crate) const fn as_ptr(&self) -> *const u8 {
97 match self.inner {
98 Some(inner) => inner.as_ptr(),
99 None => core::ptr::null()
100 }
101 }
102
103 #[inline(always)]
109 #[must_use]
110 pub const fn size(&self) -> Option<u32> {
111 match self.inner {
112 None => Some(0),
113 Some(val) => to_u32(val.len())
114 }
115 }
116
117 #[inline]
119 #[must_use]
120 pub const fn valid_size(&self) -> bool {
121 match self.inner {
122 Some(inner) => can_cast_u32(inner.len()),
123 None => true
124 }
125 }
126}
127
128impl<'a> From<&'a [u8]> for AadSlice<'a> {
129 #[inline]
130 fn from(value: &'a [u8]) -> Self {
131 Self::new(value)
132 }
133}
134
135impl<'a> Sealed for AadSlice<'a> {}
136
137unsafe impl<'a> Aad for AadSlice<'a> {
138 #[inline]
139 fn try_size(&self) -> Option<u32> { self.size() }
140 #[inline]
141 fn ptr(&self) -> *const u8 { self.as_ptr() }
142
143 #[inline]
144 unsafe fn size(&self) -> u32 {
145 debug_assert!(self.is_valid_size());
146 self.inner.map_or(0, |inner| inner.len() as u32)
147 }
148
149 #[inline]
150 fn is_valid_size(&self) -> bool { self.valid_size() }
151}
152
153impl<T: ?Sized + Sealed> Sealed for &T {}
154unsafe impl<T: ?Sized + Aad> Aad for &T {
155 #[inline]
156 fn try_size(&self) -> Option<u32> {
157 T::try_size(self)
158 }
159 #[inline]
160 fn ptr(&self) -> *const u8 {
161 T::ptr(self)
162 }
163 #[inline]
164 #[cfg_attr(debug_assertions, track_caller)]
165 unsafe fn size(&self) -> u32 {
166 T::size(self)
167 }
168 #[inline]
169 fn is_valid_size(&self) -> bool {
170 T::is_valid_size(self)
171 }
172}
173impl<T: ?Sized + Sealed> Sealed for &mut T {}
174unsafe impl<T: ?Sized + Aad> Aad for &mut T {
175 #[inline]
176 fn try_size(&self) -> Option<u32> {
177 T::try_size(self)
178 }
179 #[inline]
180 fn ptr(&self) -> *const u8 {
181 T::ptr(self)
182 }
183 #[inline]
184 #[cfg_attr(debug_assertions, track_caller)]
185 unsafe fn size(&self) -> u32 {
186 T::size(self)
187 }
188 #[inline]
189 fn is_valid_size(&self) -> bool {
190 T::is_valid_size(self)
191 }
192}
193
194impl Sealed for [u8] {}
195
196unsafe impl Aad for [u8] {
197 #[inline]
198 fn try_size(&self) -> Option<u32> {
199 to_u32(self.len())
200 }
201 #[inline]
202 fn ptr(&self) -> *const u8 {
203 self.as_ptr()
204 }
205 #[inline]
206 #[cfg_attr(debug_assertions, track_caller)]
207 unsafe fn size(&self) -> u32 {
208 debug_assert!(self.is_valid_size());
209 self.len() as u32
210 }
211 #[inline]
212 fn is_valid_size(&self) -> bool {
213 can_cast_u32(self.len())
214 }
215}
216
217impl<const C: usize> Sealed for [u8; C] {}
218
219unsafe impl<const C: usize> Aad for [u8; C] {
220 #[inline]
221 fn try_size(&self) -> Option<u32> {
222 if const_can_cast_u32::<C>() {
223 Some(C as u32)
224 } else {
225 None
226 }
227 }
228 #[inline]
229 fn ptr(&self) -> *const u8 {
230 self.as_ptr()
231 }
232 #[inline]
233 #[cfg_attr(debug_assertions, track_caller)]
234 unsafe fn size(&self) -> u32 {
235 debug_assert!(const_can_cast_u32::<C>());
236 C as u32
237 }
238 #[inline]
239 fn is_valid_size(&self) -> bool {
240 const_can_cast_u32::<C>()
241 }
242}
243
244impl Sealed for str {}
245
246unsafe impl Aad for str {
247 #[inline]
248 fn try_size(&self) -> Option<u32> {
249 to_u32(self.len())
250 }
251 #[inline]
252 fn ptr(&self) -> *const u8 {
253 self.as_ptr()
254 }
255 #[inline]
256 #[cfg_attr(debug_assertions, track_caller)]
257 unsafe fn size(&self) -> u32 {
258 debug_assert!(self.is_valid_size());
259 self.len() as u32
260 }
261 #[inline]
262 fn is_valid_size(&self) -> bool {
263 can_cast_u32(self.len())
264 }
265}
266
267impl Sealed for () {}
268
269unsafe impl Aad for () {
270 #[inline]
271 fn try_size(&self) -> Option<u32> {
272 Some(0)
273 }
274 #[inline]
275 fn ptr(&self) -> *const u8 {
276 core::ptr::null()
277 }
278 #[inline]
279 unsafe fn size(&self) -> u32 {
280 0
281 }
282 #[inline]
283 fn is_valid_size(&self) -> bool {
284 true
285 }
286}
287
288impl<T: Sealed> Sealed for Option<T> {}
289
290unsafe impl<T: Aad> Aad for Option<T> {
291 #[inline]
292 fn try_size(&self) -> Option<u32> {
293 self.as_ref().map_or(Some(0), Aad::try_size)
294 }
295 #[inline]
296 fn ptr(&self) -> *const u8 {
297 self.as_ref().map_or(core::ptr::null(), Aad::ptr)
298 }
299 #[inline]
300 unsafe fn size(&self) -> u32 {
301 #[allow(clippy::option_if_let_else)]
302 match self {
303 None => 0,
304 Some(inner) => inner.size()
305 }
306 }
307 #[inline]
308 fn is_valid_size(&self) -> bool {
309 self.as_ref().map_or(true, Aad::is_valid_size)
310 }
311}
312
313alloc! {
314 impl Sealed for Vec<u8> {}
315
316 unsafe impl Aad for Vec<u8> {
317 #[inline]
318 fn try_size(&self) -> Option<u32> {
319 to_u32(self.len())
320 }
321 #[inline]
322 fn ptr(&self) -> *const u8 {
323 self.as_ptr()
324 }
325 #[inline]
326 #[cfg_attr(debug_assertions, track_caller)]
327 unsafe fn size(&self) -> u32 {
328 debug_assert!(self.is_valid_size());
329 self.len() as u32
330 }
331 #[inline]
332 fn is_valid_size(&self) -> bool {
333 can_cast_u32(self.len())
334 }
335 }
336
337 impl Sealed for String {}
338
339 unsafe impl Aad for String {
340 #[inline]
341 fn try_size(&self) -> Option<u32> {
342 to_u32(self.len())
343 }
344 #[inline]
345 fn ptr(&self) -> *const u8 {
346 self.as_ptr()
347 }
348 #[inline]
349 #[cfg_attr(debug_assertions, track_caller)]
350 unsafe fn size(&self) -> u32 {
351 debug_assert!(self.is_valid_size());
352 self.len() as u32
353 }
354 #[inline]
355 fn is_valid_size(&self) -> bool {
356 can_cast_u32(self.len())
357 }
358 }
359}