1use {
2 super::*,
3 core::{marker::PhantomData, ptr::copy_nonoverlapping},
4};
5
6#[inline(always)]
9fn advance_slice_mut_checked<'a, T>(input: &mut &'a mut [T], len: usize) -> Option<&'a mut [T]> {
10 let (dst, rest) = mem::take(input).split_at_mut_checked(len)?;
11 *input = rest;
12 Some(dst)
13}
14
15#[inline(always)]
23unsafe fn advance_slice_mut_unchecked<'a, T>(input: &mut &'a mut [T], len: usize) -> &'a mut [T] {
24 let (dst, rest) = unsafe { mem::take(input).split_at_mut_unchecked(len) };
25 *input = rest;
26 dst
27}
28
29#[inline(always)]
32fn advance_slice_checked<'a, T>(input: &mut &'a [T], len: usize) -> Option<&'a [T]> {
33 let (dst, rest) = input.split_at_checked(len)?;
34 *input = rest;
35 Some(dst)
36}
37
38#[inline(always)]
46unsafe fn advance_slice_unchecked<'a, T>(input: &mut &'a [T], len: usize) -> &'a [T] {
47 let (dst, rest) = unsafe { input.split_at_unchecked(len) };
48 *input = rest;
49 dst
50}
51
52pub struct SliceUnchecked<'a, T> {
57 buf: &'a [T],
58}
59
60impl<'a, T> SliceUnchecked<'a, T> {
61 pub const unsafe fn new(buf: &'a [T]) -> Self {
69 Self { buf }
70 }
71}
72
73unsafe impl<'a> Reader<'a> for SliceUnchecked<'a, u8> {
74 const BORROW_KINDS: u8 = BorrowKind::Backing.mask() | BorrowKind::CallSite.mask();
75
76 #[inline]
77 fn copy_into_slice(&mut self, dst: &mut [u8]) -> ReadResult<()> {
78 let chunk = unsafe { advance_slice_unchecked(&mut self.buf, dst.len()) };
81 unsafe { copy_nonoverlapping(chunk.as_ptr(), dst.as_mut_ptr(), dst.len()) };
87 Ok(())
88 }
89
90 #[inline]
91 fn copy_into_uninit_slice(&mut self, dst: &mut [MaybeUninit<u8>]) -> ReadResult<()> {
92 let chunk = unsafe { advance_slice_unchecked(&mut self.buf, dst.len()) };
95 unsafe { copy_nonoverlapping(chunk.as_ptr(), dst.as_mut_ptr().cast::<u8>(), dst.len()) };
101 Ok(())
102 }
103
104 #[inline(always)]
105 fn take_array<const N: usize>(&mut self) -> ReadResult<[u8; N]> {
106 let chunk = unsafe { advance_slice_unchecked(&mut self.buf, N) };
109 Ok(unsafe { *(chunk.as_ptr().cast::<[u8; N]>()) })
113 }
114
115 #[inline]
116 fn take_borrowed(&mut self, len: usize) -> ReadResult<&'a [u8]> {
117 let chunk = unsafe { advance_slice_unchecked(&mut self.buf, len) };
120 Ok(chunk)
121 }
122
123 #[inline]
124 fn take_scoped(&mut self, len: usize) -> ReadResult<&[u8]> {
125 self.take_borrowed(len)
126 }
127}
128
129pub struct SliceMutUnchecked<'a, T> {
134 buf: &'a mut [T],
135}
136
137#[cfg(test)]
138impl<T> core::ops::Deref for SliceMutUnchecked<'_, T> {
139 type Target = [T];
140
141 fn deref(&self) -> &Self::Target {
142 self.buf
143 }
144}
145
146impl<'a, T> SliceMutUnchecked<'a, T> {
147 pub const unsafe fn new(buf: &'a mut [T]) -> Self {
166 Self { buf }
167 }
168}
169
170unsafe impl<'a> Reader<'a> for SliceMutUnchecked<'a, u8> {
171 const BORROW_KINDS: u8 =
172 BorrowKind::Backing.mask() | BorrowKind::BackingMut.mask() | BorrowKind::CallSite.mask();
173
174 #[inline]
175 fn copy_into_slice(&mut self, dst: &mut [u8]) -> ReadResult<()> {
176 let chunk = unsafe { advance_slice_mut_unchecked(&mut self.buf, dst.len()) };
179 unsafe { copy_nonoverlapping(chunk.as_ptr(), dst.as_mut_ptr(), dst.len()) };
185 Ok(())
186 }
187
188 #[inline]
189 fn copy_into_uninit_slice(&mut self, dst: &mut [MaybeUninit<u8>]) -> ReadResult<()> {
190 let chunk = unsafe { advance_slice_mut_unchecked(&mut self.buf, dst.len()) };
193 unsafe { copy_nonoverlapping(chunk.as_ptr(), dst.as_mut_ptr().cast::<u8>(), dst.len()) };
199 Ok(())
200 }
201
202 #[inline(always)]
203 fn take_array<const N: usize>(&mut self) -> ReadResult<[u8; N]> {
204 let chunk = unsafe { advance_slice_mut_unchecked(&mut self.buf, N) };
207 Ok(unsafe { *(chunk.as_ptr().cast::<[u8; N]>()) })
211 }
212
213 #[inline]
214 fn take_borrowed_mut(&mut self, len: usize) -> ReadResult<&'a mut [u8]> {
215 Ok(unsafe { advance_slice_mut_unchecked(&mut self.buf, len) })
218 }
219
220 #[inline]
221 fn take_borrowed(&mut self, len: usize) -> ReadResult<&'a [u8]> {
222 self.take_borrowed_mut(len).map(|s| &*s)
223 }
224
225 #[inline]
226 fn take_scoped(&mut self, len: usize) -> ReadResult<&[u8]> {
227 self.take_borrowed(len)
228 }
229}
230
231pub struct SliceScopedUnchecked<'a, 'b, T> {
236 inner: SliceUnchecked<'b, T>,
237 _marker: PhantomData<&'a [T]>,
238}
239
240impl<'b, T> SliceScopedUnchecked<'_, 'b, T> {
241 #[inline(always)]
249 pub const unsafe fn new(buf: &'b [T]) -> Self {
250 Self {
251 inner: unsafe { SliceUnchecked::new(buf) },
252 _marker: PhantomData,
253 }
254 }
255}
256
257unsafe impl<'a> Reader<'a> for SliceScopedUnchecked<'a, '_, u8> {
258 const BORROW_KINDS: u8 = BorrowKind::CallSite.mask();
259
260 #[inline(always)]
261 fn copy_into_slice(&mut self, dst: &mut [u8]) -> ReadResult<()> {
262 self.inner.copy_into_slice(dst)
263 }
264
265 #[inline(always)]
266 fn copy_into_uninit_slice(&mut self, dst: &mut [MaybeUninit<u8>]) -> ReadResult<()> {
267 self.inner.copy_into_uninit_slice(dst)
268 }
269
270 #[inline(always)]
271 fn take_array<const N: usize>(&mut self) -> ReadResult<[u8; N]> {
272 self.inner.take_array()
273 }
274
275 #[inline(always)]
276 fn take_scoped(&mut self, len: usize) -> ReadResult<&[u8]> {
277 self.inner.take_scoped(len)
278 }
279}
280
281unsafe impl<'a> Reader<'a> for &'a [u8] {
282 const BORROW_KINDS: u8 = BorrowKind::Backing.mask() | BorrowKind::CallSite.mask();
283
284 #[inline]
285 fn take_borrowed(&mut self, len: usize) -> ReadResult<&'a [u8]> {
286 let Some(src) = advance_slice_checked(self, len) else {
287 return Err(read_size_limit(len));
288 };
289 Ok(src)
290 }
291
292 #[inline(always)]
293 fn take_scoped(&mut self, len: usize) -> ReadResult<&[u8]> {
294 self.take_borrowed(len)
295 }
296
297 #[inline]
298 fn copy_into_slice(&mut self, dst: &mut [u8]) -> ReadResult<()> {
299 let Some(src) = advance_slice_checked(self, dst.len()) else {
300 return Err(read_size_limit(dst.len()));
301 };
302 unsafe { copy_nonoverlapping(src.as_ptr(), dst.as_mut_ptr(), dst.len()) };
307 Ok(())
308 }
309
310 #[inline]
311 fn copy_into_uninit_slice(&mut self, dst: &mut [MaybeUninit<u8>]) -> ReadResult<()> {
312 let Some(src) = advance_slice_checked(self, dst.len()) else {
313 return Err(read_size_limit(dst.len()));
314 };
315 unsafe { copy_nonoverlapping(src.as_ptr(), dst.as_mut_ptr().cast::<u8>(), dst.len()) };
320 Ok(())
321 }
322
323 #[inline(always)]
324 fn take_array<const N: usize>(&mut self) -> ReadResult<[u8; N]> {
325 let Some((src, rest)) = self.split_first_chunk() else {
326 return Err(read_size_limit(N));
327 };
328 *self = rest;
329 Ok(*src)
330 }
331
332 #[inline(always)]
333 unsafe fn as_trusted_for(&mut self, n_bytes: usize) -> ReadResult<impl Reader<'a>> {
334 let Some(window) = advance_slice_checked(self, n_bytes) else {
335 return Err(read_size_limit(n_bytes));
336 };
337 Ok(unsafe { SliceUnchecked::new(window) })
340 }
341}
342
343unsafe impl<'a> Reader<'a> for &'a mut [u8] {
344 const BORROW_KINDS: u8 =
345 BorrowKind::Backing.mask() | BorrowKind::BackingMut.mask() | BorrowKind::CallSite.mask();
346
347 #[inline(always)]
348 unsafe fn as_trusted_for(&mut self, n_bytes: usize) -> ReadResult<impl Reader<'a>> {
349 let Some(window) = advance_slice_mut_checked(self, n_bytes) else {
350 return Err(read_size_limit(n_bytes));
351 };
352 Ok(unsafe { SliceMutUnchecked::new(window) })
355 }
356
357 #[inline]
358 fn take_borrowed_mut(&mut self, len: usize) -> ReadResult<&'a mut [u8]> {
359 let Some(src) = advance_slice_mut_checked(self, len) else {
360 return Err(read_size_limit(len));
361 };
362 Ok(src)
363 }
364
365 #[inline]
366 fn take_borrowed(&mut self, len: usize) -> ReadResult<&'a [u8]> {
367 self.take_borrowed_mut(len).map(|s| &*s)
368 }
369
370 #[inline]
371 fn take_scoped(&mut self, len: usize) -> ReadResult<&[u8]> {
372 self.take_borrowed(len)
373 }
374
375 #[inline]
376 fn copy_into_slice(&mut self, dst: &mut [u8]) -> ReadResult<()> {
377 let src = self.take_borrowed(dst.len())?;
378 unsafe { copy_nonoverlapping(src.as_ptr(), dst.as_mut_ptr(), dst.len()) }
382 Ok(())
383 }
384
385 #[inline]
386 fn copy_into_uninit_slice(&mut self, dst: &mut [MaybeUninit<u8>]) -> ReadResult<()> {
387 let src = self.take_borrowed(dst.len())?;
388 unsafe { copy_nonoverlapping(src.as_ptr(), dst.as_mut_ptr().cast::<u8>(), dst.len()) }
392 Ok(())
393 }
394
395 #[inline(always)]
396 fn take_array<const N: usize>(&mut self) -> ReadResult<[u8; N]> {
397 let Some((src, rest)) = mem::take(self).split_first_chunk_mut() else {
398 return Err(read_size_limit(N));
399 };
400 *self = rest;
401 Ok(*src)
402 }
403}
404
405impl Writer for SliceMutUnchecked<'_, u8> {
406 #[inline(always)]
407 fn write(&mut self, src: &[u8]) -> WriteResult<()> {
408 let dst = unsafe { advance_slice_mut_unchecked(&mut self.buf, src.len()) };
411 unsafe { copy_nonoverlapping(src.as_ptr(), dst.as_mut_ptr().cast(), src.len()) }
417 Ok(())
418 }
419}
420
421impl Writer for SliceMutUnchecked<'_, MaybeUninit<u8>> {
422 #[inline(always)]
423 fn write(&mut self, src: &[u8]) -> WriteResult<()> {
424 let dst = unsafe { advance_slice_mut_unchecked(&mut self.buf, src.len()) };
427 unsafe { copy_nonoverlapping(src.as_ptr(), dst.as_mut_ptr().cast(), src.len()) }
433 Ok(())
434 }
435}
436
437impl Writer for &mut [MaybeUninit<u8>] {
438 #[inline(always)]
439 unsafe fn as_trusted_for(&mut self, n_bytes: usize) -> WriteResult<impl Writer> {
440 let Some(window) = advance_slice_mut_checked(self, n_bytes) else {
441 return Err(write_size_limit(n_bytes));
442 };
443 Ok(unsafe { SliceMutUnchecked::new(window) })
447 }
448
449 #[inline(always)]
450 fn write(&mut self, src: &[u8]) -> WriteResult<()> {
451 let Some(dst) = advance_slice_mut_checked(self, src.len()) else {
452 return Err(write_size_limit(src.len()));
453 };
454
455 unsafe { copy_nonoverlapping(src.as_ptr(), dst.as_mut_ptr().cast(), src.len()) }
457 Ok(())
458 }
459}
460
461impl Writer for &mut [u8] {
462 #[inline(always)]
463 unsafe fn as_trusted_for(&mut self, n_bytes: usize) -> WriteResult<impl Writer> {
464 let Some(window) = advance_slice_mut_checked(self, n_bytes) else {
465 return Err(write_size_limit(n_bytes));
466 };
467 Ok(unsafe { SliceMutUnchecked::new(window) })
471 }
472
473 #[inline]
474 fn write(&mut self, src: &[u8]) -> WriteResult<()> {
475 let Some(dst) = advance_slice_mut_checked(self, src.len()) else {
476 return Err(write_size_limit(src.len()));
477 };
478
479 unsafe { copy_nonoverlapping(src.as_ptr(), dst.as_mut_ptr().cast(), src.len()) }
484 Ok(())
485 }
486}
487
488#[cfg(all(test, feature = "alloc"))]
489mod tests {
490 #![allow(clippy::arithmetic_side_effects)]
491 use {super::*, crate::proptest_config::proptest_cfg, alloc::vec::Vec, proptest::prelude::*};
492
493 macro_rules! with_readers {
495 ($bytes:expr, |$reader:ident| $body:block) => {{
496 {
497 let mut $reader = $bytes.as_slice();
498 $body
499 }
500 {
501 let mut $reader = unsafe { SliceUnchecked::new($bytes) };
502 $body
503 }
504 {
505 let mut $reader = Cursor::new($bytes);
506 $body
507 }
508 #[cfg(feature = "std")]
509 {
510 let mut $reader = std::io::Cursor::new($bytes);
511 $body
512 }
513 }};
514 }
515
516 macro_rules! with_untrusted_readers {
518 ($bytes:expr, |$reader:ident| $body:block) => {{
519 {
520 let mut $reader = $bytes.as_slice();
521 $body
522 }
523 {
524 let mut $reader = Cursor::new($bytes);
525 $body
526 }
527 #[cfg(feature = "std")]
528 {
529 let mut $reader = std::io::Cursor::new($bytes);
530 $body
531 }
532 }};
533 }
534
535 macro_rules! with_writers {
537 ($buffer:expr, |$writer:ident| $body:block) => {{
538 {
539 let mut $writer = $buffer.spare_capacity_mut();
540 $body
541 $buffer.clear();
542 }
543 {
544 let mut $writer = unsafe { SliceMutUnchecked::new($buffer.spare_capacity_mut()) };
545 $body
546 $buffer.clear();
547 }
548 {
549 let _capacity = $buffer.capacity();
550 $buffer.resize(_capacity, 0);
551 let mut $writer = $buffer.as_mut_slice();
552 $body
553 $buffer.clear();
554 }
555 }};
556 }
557
558 macro_rules! with_known_len_writers {
560 ($buffer:expr, |$writer:ident| $body_write:block, $body_check:expr) => {{
561 let capacity = $buffer.capacity();
562 {
563 $buffer.resize(capacity, 0);
564 $buffer.fill(0);
565 let mut $writer = $buffer.as_mut_slice();
566 $body_write
567 $body_check;
568 $buffer.clear();
569 }
570 {
571 $buffer.fill(0);
572 $buffer.clear();
573 let mut $writer = $buffer.spare_capacity_mut();
574 $body_write
575 unsafe { $buffer.set_len(capacity) }
576 $body_check;
577 }
578 }};
579 }
580
581 proptest! {
582 #![proptest_config(proptest_cfg())]
583
584 #[test]
585 fn test_reader_copy_into_slice(bytes in any::<Vec<u8>>()) {
586 let len = bytes.len();
587 with_readers!(&bytes, |reader| {
588 let mut dst = alloc::vec![0; len];
589 let half = len / 2;
590 reader.copy_into_slice(&mut dst[..half]).unwrap();
591 unsafe { Reader::as_trusted_for(&mut reader, len - half) }
593 .unwrap()
594 .copy_into_slice(&mut dst[half..])
595 .unwrap();
596 prop_assert_eq!(&dst, &bytes);
597 });
598 }
599
600 #[test]
601 fn test_reader_copy_into_uninit_slice(bytes in any::<Vec<u8>>()) {
602 let len = bytes.len();
603 with_readers!(&bytes, |reader| {
604 let mut dst = Vec::with_capacity(len);
605 let half = len / 2;
606 let spare = dst.spare_capacity_mut();
607 reader.copy_into_uninit_slice(&mut spare[..half]).unwrap();
608 unsafe { Reader::as_trusted_for(&mut reader, len - half) }
610 .unwrap()
611 .copy_into_uninit_slice(&mut spare[half..])
612 .unwrap();
613 unsafe { dst.set_len(len) };
615 prop_assert_eq!(&dst, &bytes);
616 });
617 }
618
619 #[test]
620 fn test_reader_take_scoped(bytes in any::<Vec<u8>>()) {
621 with_readers!(&bytes, |reader| {
622 let read = reader.take_scoped(bytes.len()).unwrap();
623 prop_assert_eq!(&read, &bytes);
624 });
625 }
626
627 #[test]
628 fn reader_take_scoped_input_too_large(bytes in any::<Vec<u8>>()) {
629 with_untrusted_readers!(&bytes, |reader| {
630 prop_assert!(matches!(reader.take_scoped(bytes.len() + 1), Err(ReadError::ReadSizeLimit(x)) if x == bytes.len() + 1));
631 });
632 }
633
634 #[test]
635 fn test_reader_copy_into_slice_input_too_large(bytes in any::<Vec<u8>>()) {
636 let requested = bytes.len() + 1;
637 with_untrusted_readers!(&bytes, |reader| {
638 let mut dst = alloc::vec![0; requested];
639 prop_assert!(matches!(reader.copy_into_slice(&mut dst), Err(ReadError::ReadSizeLimit(x)) if x == requested));
640 });
641 }
642
643 #[test]
644 fn test_reader_copy_into_uninit_slice_input_too_large(bytes in any::<Vec<u8>>()) {
645 let requested = bytes.len() + 1;
646 with_untrusted_readers!(&bytes, |reader| {
647 let mut dst = Vec::with_capacity(requested);
648 prop_assert!(matches!(reader.copy_into_uninit_slice(dst.spare_capacity_mut()), Err(ReadError::ReadSizeLimit(x)) if x == requested));
649 });
650 }
651
652 #[test]
653 fn test_reader_copy_into_t(ints in proptest::collection::vec(any::<u64>(), 0..=100)) {
654 let bytes = ints.iter().flat_map(|int| int.to_le_bytes()).collect::<Vec<u8>>();
655 with_readers!(&bytes, |reader| {
656 for int in &ints {
657 let mut val = MaybeUninit::<u64>::uninit();
658 unsafe { reader.copy_into_t(&mut val).unwrap() };
659 unsafe { prop_assert_eq!(val.assume_init(), *int) };
660 }
661 });
662 }
663
664 #[test]
665 fn test_reader_copy_into_slice_t(ints in proptest::collection::vec(any::<u64>(), 0..=100)) {
666 let bytes = ints.iter().flat_map(|int| int.to_le_bytes()).collect::<Vec<u8>>();
667 with_readers!(&bytes, |reader| {
668 let mut vals: Vec<u64> = Vec::with_capacity(ints.len());
669 let dst = vals.spare_capacity_mut();
670 unsafe { reader.copy_into_slice_t(dst).unwrap() };
671 unsafe { vals.set_len(ints.len()) };
672 prop_assert_eq!(&vals, &ints);
673 });
674 }
675
676 #[test]
677 fn test_writer_write(bytes in any::<Vec<u8>>()) {
678 let capacity = bytes.len();
679 let mut buffer = Vec::with_capacity(capacity);
680 with_writers!(&mut buffer, |writer| {
681 writer.write(&bytes).unwrap();
682 let written = capacity - writer.len();
683 unsafe { buffer.set_len(written) };
684 prop_assert_eq!(&buffer, &bytes);
685 });
686
687 with_known_len_writers!(&mut buffer, |writer| {
688 writer.write(&bytes).unwrap();
689 }, prop_assert_eq!(&buffer, &bytes));
690 }
691
692 #[test]
693 fn test_writer_write_input_too_large(bytes in proptest::collection::vec(any::<u8>(), 1..=100)) {
694 let mut buffer = Vec::with_capacity(bytes.len() - 1);
695 let mut writer = buffer.spare_capacity_mut();
696 prop_assert!(matches!(writer.write(&bytes), Err(WriteError::WriteSizeLimit(x)) if x == bytes.len()));
697 }
698
699 #[test]
700 fn test_writer_write_t(int in any::<u64>()) {
701 let capacity = 8;
702 let mut buffer = Vec::with_capacity(capacity);
703 with_writers!(&mut buffer, |writer| {
704 unsafe { writer.write_t(&int).unwrap() };
705 let written = capacity - writer.len();
706 unsafe { buffer.set_len(written) };
707 prop_assert_eq!(&buffer, &int.to_le_bytes());
708 });
709
710 with_known_len_writers!(&mut buffer, |writer| {
711 unsafe { writer.write_t(&int).unwrap() };
712 }, prop_assert_eq!(&buffer, &int.to_le_bytes()));
713 }
714
715 #[test]
716 fn test_writer_write_slice_t(ints in proptest::collection::vec(any::<u64>(), 0..=100)) {
717 let bytes = ints.iter().flat_map(|int| int.to_le_bytes()).collect::<Vec<u8>>();
718 let capacity = bytes.len();
719 let mut buffer = Vec::with_capacity(capacity);
720 with_writers!(&mut buffer, |writer| {
721 unsafe { writer.write_slice_t(&ints).unwrap() };
722 let written = capacity - writer.len();
723 unsafe { buffer.set_len(written) };
724 prop_assert_eq!(&buffer, &bytes);
725 });
726
727 with_known_len_writers!(&mut buffer, |writer| {
728 unsafe { writer.write_slice_t(&ints).unwrap() };
729 }, prop_assert_eq!(&buffer, &bytes));
730 }
731 }
732}