1#[cfg(feature = "derive")]
20pub use peek_poke_derive::*;
21
22use core::{marker::PhantomData, mem::size_of, slice};
23use crate::{slice_ext::*, vec_ext::*};
24
25mod slice_ext;
26mod vec_ext;
27
28union MaybeUninitShim<T: Copy> {
29 uninit: (),
30 init: T,
31}
32
33pub unsafe fn peek_from_uninit<T: Copy + Peek>(bytes: *const u8) -> (T, *const u8) {
36 let mut val = MaybeUninitShim { uninit: () };
37 let bytes = <T>::peek_from(bytes, &mut val.init);
38 (val.init, bytes)
39}
40
41pub unsafe fn peek_from_default<T: Default + Peek>(bytes: *const u8) -> (T, *const u8) {
44 let mut val = T::default();
45 let bytes = <T>::peek_from(bytes, &mut val);
46 (val, bytes)
47}
48
49pub fn peek_from_slice<'a, T: Peek>(src: &'a [u8], dst: &mut T) -> &'a [u8] {
54 unsafe {
55 assert!(T::max_size() < src.len(), "WRDL: unexpected end of display list");
57 let end_ptr = T::peek_from(src.as_ptr(), dst);
58 let len = end_ptr as usize - src.as_ptr() as usize;
59 assert!(len <= src.len(), "WRDL: Peek::max_size was wrong");
62 slice::from_raw_parts(end_ptr, src.len() - len)
63 }
64}
65
66pub fn poke_inplace_slice<T: Poke>(src: &T, dst: &mut [u8]) {
68 assert!(T::max_size() <= dst.len(), "WRDL: buffer too small to write into");
69 unsafe {
70 src.poke_into(dst.as_mut_ptr());
71 }
72}
73
74pub fn poke_into_vec<T: Poke>(src: &T, dst: &mut Vec<u8>) {
76 dst.reserve(T::max_size());
77 unsafe {
78 let ptr = dst.as_end_mut_ptr();
79 let end_ptr = src.poke_into(ptr);
80 dst.set_end_ptr(end_ptr);
81 }
82}
83
84pub fn poke_extend_vec<I>(src: I, dst: &mut Vec<u8>) -> usize
86where
87 I: ExactSizeIterator,
88 I::Item: Poke,
89{
90 let len = src.len();
91 let max_size = len * I::Item::max_size();
92 dst.reserve(max_size);
93 unsafe {
94 let ptr = dst.as_end_mut_ptr();
95 let end_ptr = src.take(len).fold(ptr, |ptr, item| item.poke_into(ptr));
98 dst.set_end_ptr(end_ptr);
99 }
100
101 len
102}
103
104pub fn ensure_red_zone<T: Poke>(bytes: &mut Vec<u8>) {
108 bytes.reserve(T::max_size());
109 unsafe {
110 let end_ptr = bytes.as_end_mut_ptr();
111 end_ptr.write_bytes(0, T::max_size());
112 bytes.set_end_ptr(end_ptr.add(T::max_size()));
113 }
114}
115
116pub fn strip_red_zone<T: Poke>(bytes: &mut Vec<u8>) {
122 assert!(bytes.len() >= T::max_size());
123 unsafe {
124 let end_ptr = bytes.as_end_mut_ptr();
125 end_ptr.write_bytes(0, T::max_size());
126 bytes.set_end_ptr(end_ptr.sub(T::max_size()));
127 }
128}
129
130#[inline]
131unsafe fn read_verbatim<T>(src: *const u8, dst: *mut T) -> *const u8 {
132 *dst = (src as *const T).read_unaligned();
133 src.add(size_of::<T>())
134}
135
136#[inline]
137unsafe fn write_verbatim<T>(src: T, dst: *mut u8) -> *mut u8 {
138 (dst as *mut T).write_unaligned(src);
139 dst.add(size_of::<T>())
140}
141
142#[cfg(feature = "extras")]
143mod euclid;
144
145pub unsafe trait Poke {
179 fn max_size() -> usize;
188 unsafe fn poke_into(&self, bytes: *mut u8) -> *mut u8;
202}
203
204pub trait Peek: Poke {
237 unsafe fn peek_from(bytes: *const u8, output: *mut Self) -> *const u8;
252}
253
254macro_rules! impl_poke_for_deref {
255 (<$($desc:tt)+) => {
256 unsafe impl <$($desc)+ {
257 #[inline(always)]
258 fn max_size() -> usize {
259 <T>::max_size()
260 }
261 unsafe fn poke_into(&self, bytes: *mut u8) -> *mut u8 {
262 (**self).poke_into(bytes)
263 }
264 }
265 }
266}
267
268impl_poke_for_deref!(<'a, T: Poke> Poke for &'a T);
269impl_poke_for_deref!(<'a, T: Poke> Poke for &'a mut T);
270
271macro_rules! impl_for_primitive {
272 ($($ty:ty)+) => {
273 $(unsafe impl Poke for $ty {
274 #[inline(always)]
275 fn max_size() -> usize {
276 size_of::<Self>()
277 }
278 #[inline(always)]
279 unsafe fn poke_into(&self, bytes: *mut u8) -> *mut u8 {
280 write_verbatim(*self, bytes)
281 }
282 }
283 impl Peek for $ty {
284 #[inline(always)]
285 unsafe fn peek_from(bytes: *const u8, output: *mut Self) -> *const u8 {
286 read_verbatim(bytes, output)
287 }
288 })+
289 };
290}
291
292impl_for_primitive! {
293 i8 i16 i32 i64 isize
294 u8 u16 u32 u64 usize
295 f32 f64
296}
297
298unsafe impl Poke for bool {
299 #[inline(always)]
300 fn max_size() -> usize {
301 u8::max_size()
302 }
303 #[inline]
304 unsafe fn poke_into(&self, bytes: *mut u8) -> *mut u8 {
305 (*self as u8).poke_into(bytes)
306 }
307}
308
309impl Peek for bool {
310 #[inline]
311 unsafe fn peek_from(bytes: *const u8, output: *mut Self) -> *const u8 {
312 let mut int_bool = 0u8;
313 let ptr = <u8>::peek_from(bytes, &mut int_bool);
314 *output = int_bool != 0;
315 ptr
316 }
317}
318
319unsafe impl<T> Poke for PhantomData<T> {
320 #[inline(always)]
321 fn max_size() -> usize {
322 0
323 }
324 #[inline(always)]
325 unsafe fn poke_into(&self, bytes: *mut u8) -> *mut u8 {
326 bytes
327 }
328}
329
330impl<T> Peek for PhantomData<T> {
331 #[inline(always)]
332 unsafe fn peek_from(bytes: *const u8, output: *mut Self) -> *const u8 {
333 *output = PhantomData;
334 bytes
335 }
336}
337
338unsafe impl<T: Poke> Poke for Option<T> {
339 #[inline(always)]
340 fn max_size() -> usize {
341 u8::max_size() + T::max_size()
342 }
343
344 #[inline]
345 unsafe fn poke_into(&self, bytes: *mut u8) -> *mut u8 {
346 match self {
347 None => 0u8.poke_into(bytes),
348 Some(ref v) => {
349 let bytes = 1u8.poke_into(bytes);
350 let bytes = v.poke_into(bytes);
351 bytes
352 }
353 }
354 }
355}
356
357impl<T: Default + Peek> Peek for Option<T> {
358 #[inline]
359 unsafe fn peek_from(bytes: *const u8, output: *mut Self) -> *const u8 {
360 let (variant, bytes) = peek_from_default::<u8>(bytes);
361 match variant {
362 0 => {
363 *output = None;
364 bytes
365 }
366 1 => {
367 let (val, bytes) = peek_from_default(bytes);
368 *output = Some(val);
369 bytes
370 }
371 _ => unreachable!(),
372 }
373 }
374}
375
376macro_rules! impl_for_arrays {
377 ($($len:tt)+) => {
378 $(unsafe impl<T: Poke> Poke for [T; $len] {
379 fn max_size() -> usize {
380 $len * T::max_size()
381 }
382 unsafe fn poke_into(&self, bytes: *mut u8) -> *mut u8 {
383 self.iter().fold(bytes, |bytes, e| e.poke_into(bytes))
384 }
385 }
386 impl<T: Peek> Peek for [T; $len] {
387 unsafe fn peek_from(bytes: *const u8, output: *mut Self) -> *const u8 {
388 (&mut *output).iter_mut().fold(bytes, |bytes, e| <T>::peek_from(bytes, e))
389 }
390 })+
391 }
392}
393
394impl_for_arrays! {
395 01 02 03 04 05 06 07 08 09 10
396 11 12 13 14 15 16 17 18 19 20
397 21 22 23 24 25 26 27 28 29 30
398 31 32
399}
400
401unsafe impl Poke for () {
402 fn max_size() -> usize {
403 0
404 }
405 unsafe fn poke_into(&self, bytes: *mut u8) -> *mut u8 {
406 bytes
407 }
408}
409impl Peek for () {
410 unsafe fn peek_from(bytes: *const u8, output: *mut Self) -> *const u8 {
411 *output = ();
412 bytes
413 }
414}
415
416macro_rules! impl_for_tuple {
417 ($($n:tt: $ty:ident),+) => {
418 unsafe impl<$($ty: Poke),+> Poke for ($($ty,)+) {
419 #[inline(always)]
420 fn max_size() -> usize {
421 0 $(+ <$ty>::max_size())+
422 }
423 unsafe fn poke_into(&self, bytes: *mut u8) -> *mut u8 {
424 $(let bytes = self.$n.poke_into(bytes);)+
425 bytes
426 }
427 }
428 impl<$($ty: Peek),+> Peek for ($($ty,)+) {
429 unsafe fn peek_from(bytes: *const u8, output: *mut Self) -> *const u8 {
430 $(let bytes = $ty::peek_from(bytes, &mut (*output).$n);)+
431 bytes
432 }
433 }
434 }
435}
436
437impl_for_tuple!(0: A);
438impl_for_tuple!(0: A, 1: B);
439impl_for_tuple!(0: A, 1: B, 2: C);
440impl_for_tuple!(0: A, 1: B, 2: C, 3: D);
441impl_for_tuple!(0: A, 1: B, 2: C, 3: D, 4: E);