1use std::marker::PhantomData;
44use zerocopy::FromBytes;
45
46#[derive(Debug, Copy, Clone)]
48pub struct PtrByteSlice<'a> {
49 slice: *const [u8],
50 _marker: PhantomData<&'a [u8]>,
51}
52
53impl<'a> PtrByteSlice<'a> {
54 pub unsafe fn new(slice: *const [u8]) -> Self {
60 Self { slice, _marker: PhantomData }
61 }
62
63 pub fn len(&self) -> usize {
65 self.slice.len()
66 }
67
68 pub fn is_empty(&self) -> bool {
70 self.len() == 0
71 }
72
73 pub fn read<T: Copy + FromBytes>(&self) -> Option<T> {
77 let size = std::mem::size_of::<T>();
78 if size > self.len() {
79 return None;
80 }
81 let ptr = self.slice as *const T;
82 unsafe { Some(std::ptr::read_unaligned(ptr)) }
86 }
87
88 pub fn copy_to_slice(&self, dest: &mut [u8]) {
94 assert!(dest.len() >= self.len());
95 unsafe {
101 std::ptr::copy_nonoverlapping(self.slice as *const u8, dest.as_mut_ptr(), self.len());
102 }
103 }
104
105 pub fn subslice(&self, range: std::ops::Range<usize>) -> Self {
111 assert!(range.start <= range.end);
112 assert!(range.end <= self.len());
113 unsafe {
118 let new_ptr = (self.slice as *const u8).add(range.start);
119 let new_slice = std::ptr::slice_from_raw_parts(new_ptr, range.end - range.start);
120 Self::new(new_slice)
121 }
122 }
123
124 pub fn split_at(self, mid: usize) -> (Self, Self) {
130 assert!(mid <= self.len());
131 unsafe {
136 let ptr = self.slice as *const u8;
137 (
138 Self::new(std::ptr::slice_from_raw_parts(ptr, mid)),
139 Self::new(std::ptr::slice_from_raw_parts(ptr.add(mid), self.len() - mid)),
140 )
141 }
142 }
143
144 pub fn as_raw_slice_ptr(&self) -> *const [u8] {
146 self.slice
147 }
148
149 pub fn as_ptr(&self) -> *const u8 {
151 self.slice as *const u8
152 }
153
154 pub fn to_vec(&self) -> Vec<u8> {
157 let mut vec = Vec::with_capacity(self.len());
158 unsafe {
161 std::ptr::copy_nonoverlapping(self.slice as *const u8, vec.as_mut_ptr(), self.len());
162 vec.set_len(self.len());
163 }
164 vec
165 }
166
167 pub fn append_to(&self, vec: &mut Vec<u8>) {
170 let old_len = vec.len();
171 let new_len = old_len + self.len();
172 vec.reserve(self.len());
173 unsafe {
180 let dest_ptr = vec.as_mut_ptr().add(old_len);
181 std::ptr::copy_nonoverlapping(self.slice as *const u8, dest_ptr, self.len());
182 vec.set_len(new_len);
183 }
184 }
185
186 pub fn iter_as<T: Copy + FromBytes>(&self) -> IterAs<'_, T> {
193 let size = std::mem::size_of::<T>();
194 let align = std::mem::align_of::<T>();
195 assert!(size > 0, "Chunk size must be greater than 0");
196 assert_eq!(self.slice as *const u8 as usize % align, 0, "Slice is not aligned to T");
197 assert_eq!(self.len() % size, 0, "Slice length is not a multiple of T size");
198
199 let end = unsafe { (self.slice as *const T).add(self.len() / size) };
204 IterAs { ptr: self.slice as *const T, end, _marker: PhantomData }
205 }
206
207 pub fn chunks(&self, chunk_size: usize) -> Chunks<'a> {
213 assert!(chunk_size > 0, "chunk_size must be > 0");
214 Chunks { slice: *self, chunk_size, offset: 0 }
215 }
216}
217
218#[derive(Debug)]
220pub struct MutPtrByteSlice<'a> {
221 slice: *mut [u8],
222 _marker: PhantomData<&'a mut [u8]>,
223}
224
225impl<'a> MutPtrByteSlice<'a> {
226 pub unsafe fn new(slice: *mut [u8]) -> Self {
232 Self { slice, _marker: PhantomData }
233 }
234
235 pub fn len(&self) -> usize {
237 self.slice.len()
238 }
239
240 pub fn is_empty(&self) -> bool {
242 self.len() == 0
243 }
244
245 pub fn read<T: Copy + FromBytes>(&self) -> Option<T> {
249 let size = std::mem::size_of::<T>();
250 if size > self.len() {
251 return None;
252 }
253 let ptr = self.slice as *const T;
254 unsafe { Some(std::ptr::read_unaligned(ptr)) }
258 }
259
260 pub fn write<T: Copy + FromBytes>(&mut self, val: T) -> Option<()> {
264 let size = std::mem::size_of::<T>();
265 if size > self.len() {
266 return None;
267 }
268 let ptr = self.slice as *mut T;
269 unsafe {
273 std::ptr::write_unaligned(ptr, val);
274 }
275 Some(())
276 }
277
278 pub fn copy_to_slice(&self, dest: &mut [u8]) {
284 assert!(dest.len() >= self.len());
285 unsafe {
291 std::ptr::copy_nonoverlapping(self.slice as *mut u8, dest.as_mut_ptr(), self.len());
292 }
293 }
294
295 pub fn copy_from_ptr_slice(&mut self, src: PtrByteSlice<'_>) {
301 assert_eq!(self.len(), src.len());
302 unsafe {
308 std::ptr::copy_nonoverlapping(src.as_ptr(), self.slice as *mut u8, self.len());
309 }
310 }
311
312 pub fn copy_from_slice(&mut self, src: &[u8]) {
318 assert_eq!(self.len(), src.len());
319 unsafe {
324 std::ptr::copy_nonoverlapping(src.as_ptr(), self.slice as *mut u8, self.len());
325 }
326 }
327
328 pub fn fill(&mut self, val: u8) {
330 unsafe {
332 std::ptr::write_bytes(self.slice as *mut u8, val, self.len());
333 }
334 }
335
336 pub fn as_ptr_slice(&self) -> PtrByteSlice<'_> {
338 unsafe { PtrByteSlice::new(self.slice as *const [u8]) }
340 }
341
342 pub fn subslice_mut(&mut self, range: std::ops::Range<usize>) -> Self {
348 assert!(range.start <= range.end);
349 assert!(range.end <= self.len());
350 unsafe {
355 let new_ptr = (self.slice as *mut u8).add(range.start);
356 let new_slice = std::ptr::slice_from_raw_parts_mut(new_ptr, range.end - range.start);
357 Self::new(new_slice)
358 }
359 }
360
361 pub fn split_at_mut(self, mid: usize) -> (Self, Self) {
367 assert!(mid <= self.len());
368 unsafe {
374 let ptr = self.slice as *mut u8;
375 (
376 Self::new(std::ptr::slice_from_raw_parts_mut(ptr, mid)),
377 Self::new(std::ptr::slice_from_raw_parts_mut(ptr.add(mid), self.len() - mid)),
378 )
379 }
380 }
381
382 pub fn as_raw_mut_slice_ptr(&self) -> *mut [u8] {
384 self.slice
385 }
386
387 pub fn as_ptr(&self) -> *const u8 {
389 self.slice as *const u8
390 }
391
392 pub fn as_mut_ptr(&self) -> *mut u8 {
394 self.slice as *mut u8
395 }
396
397 pub fn reborrow(&mut self) -> MutPtrByteSlice<'_> {
399 MutPtrByteSlice { slice: self.slice, _marker: std::marker::PhantomData }
400 }
401
402 pub fn to_vec(&self) -> Vec<u8> {
405 let mut vec = Vec::with_capacity(self.len());
406 unsafe {
409 std::ptr::copy_nonoverlapping(self.slice as *mut u8, vec.as_mut_ptr(), self.len());
410 vec.set_len(self.len());
411 }
412 vec
413 }
414
415 pub fn append_to(&self, vec: &mut Vec<u8>) {
418 let old_len = vec.len();
419 let new_len = old_len + self.len();
420 vec.reserve(self.len());
421 unsafe {
428 let dest_ptr = vec.as_mut_ptr().add(old_len);
429 std::ptr::copy_nonoverlapping(self.slice as *mut u8, dest_ptr, self.len());
430 vec.set_len(new_len);
431 }
432 }
433
434 pub fn iter_as_mut<T: Copy + FromBytes>(&mut self) -> IterAsMut<'_, T> {
441 let size = std::mem::size_of::<T>();
442 let align = std::mem::align_of::<T>();
443 assert!(size > 0, "Chunk size must be greater than 0");
444 assert_eq!(self.slice as *mut u8 as usize % align, 0, "Slice is not aligned to T");
445 assert_eq!(self.len() % size, 0, "Slice length is not a multiple of T size");
446
447 let end = unsafe { (self.slice as *mut T).add(self.len() / size) };
452 IterAsMut { ptr: self.slice as *mut T, end, _marker: PhantomData }
453 }
454
455 pub fn chunks_mut(&mut self, chunk_size: usize) -> ChunksMut<'_> {
461 assert!(chunk_size > 0, "chunk_size must be > 0");
462 ChunksMut { slice: self.reborrow(), chunk_size, offset: 0 }
463 }
464
465 pub fn into_chunks_mut(self, chunk_size: usize) -> ChunksMut<'a> {
472 assert!(chunk_size > 0, "chunk_size must be > 0");
473 ChunksMut { slice: self, chunk_size, offset: 0 }
474 }
475
476 pub fn writer(self) -> Writer<'a> {
478 Writer::new(self)
479 }
480}
481
482#[derive(Debug)]
484pub struct Writer<'a> {
485 slice: MutPtrByteSlice<'a>,
486 pos: usize,
487}
488
489impl<'a> Writer<'a> {
490 pub fn new(slice: MutPtrByteSlice<'a>) -> Self {
492 Self { slice, pos: 0 }
493 }
494
495 pub fn position(&self) -> usize {
497 self.pos
498 }
499
500 pub fn remaining(&mut self) -> MutPtrByteSlice<'_> {
502 let len = self.slice.len();
503 self.slice.reborrow().subslice_mut(self.pos..len)
504 }
505
506 pub fn into_written(mut self) -> MutPtrByteSlice<'a> {
508 let pos = self.pos;
509 self.slice.subslice_mut(0..pos)
510 }
511}
512
513impl std::io::Write for Writer<'_> {
514 fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
515 let remaining = self.slice.len() - self.pos;
516 if remaining == 0 {
517 return Ok(0);
518 }
519 let to_write = std::cmp::min(remaining, buf.len());
520 self.slice
521 .reborrow()
522 .subslice_mut(self.pos..self.pos + to_write)
523 .copy_from_slice(&buf[..to_write]);
524 self.pos += to_write;
525 Ok(to_write)
526 }
527
528 fn write_all(&mut self, buf: &[u8]) -> std::io::Result<()> {
529 if buf.len() > self.slice.len() - self.pos {
530 return Err(std::io::Error::new(
531 std::io::ErrorKind::WriteZero,
532 "failed to write whole buffer",
533 ));
534 }
535 self.slice.reborrow().subslice_mut(self.pos..self.pos + buf.len()).copy_from_slice(buf);
536 self.pos += buf.len();
537 Ok(())
538 }
539
540 fn flush(&mut self) -> std::io::Result<()> {
541 Ok(())
542 }
543}
544
545unsafe impl Send for PtrByteSlice<'_> {}
550unsafe impl Sync for PtrByteSlice<'_> {}
552unsafe impl Send for MutPtrByteSlice<'_> {}
558unsafe impl Sync for MutPtrByteSlice<'_> {}
561
562impl<'a> From<&'a [u8]> for PtrByteSlice<'a> {
563 fn from(slice: &'a [u8]) -> Self {
564 unsafe { Self::new(slice as *const [u8]) }
566 }
567}
568
569impl<'a> From<&'a Vec<u8>> for PtrByteSlice<'a> {
570 fn from(vec: &'a Vec<u8>) -> Self {
571 Self::from(vec.as_slice())
572 }
573}
574
575impl<'a> From<MutPtrByteSlice<'a>> for PtrByteSlice<'a> {
576 fn from(slice: MutPtrByteSlice<'a>) -> Self {
577 unsafe { Self::new(slice.slice as *const [u8]) }
581 }
582}
583
584impl<'a> From<&'a mut [u8]> for MutPtrByteSlice<'a> {
585 fn from(slice: &'a mut [u8]) -> Self {
586 unsafe { Self::new(slice as *mut [u8]) }
588 }
589}
590
591impl<'a> From<&'a mut Vec<u8>> for MutPtrByteSlice<'a> {
592 fn from(vec: &'a mut Vec<u8>) -> Self {
593 Self::from(vec.as_mut_slice())
594 }
595}
596
597pub struct IterAs<'a, T> {
599 ptr: *const T,
600 end: *const T,
601 _marker: PhantomData<&'a T>,
602}
603
604impl<'a, T: Copy + FromBytes> Iterator for IterAs<'a, T> {
605 type Item = T;
606
607 fn next(&mut self) -> Option<Self::Item> {
608 if self.ptr == self.end {
609 None
610 } else {
611 let current = self.ptr;
612 self.ptr = unsafe { self.ptr.add(1) };
615 Some(unsafe { std::ptr::read(current) })
618 }
619 }
620
621 fn size_hint(&self) -> (usize, Option<usize>) {
622 let len = unsafe { self.end.offset_from(self.ptr) as usize };
623 (len, Some(len))
624 }
625}
626
627impl<T: Copy + FromBytes> ExactSizeIterator for IterAs<'_, T> {}
628
629pub struct IterAsMut<'a, T> {
631 ptr: *mut T,
632 end: *mut T,
633 _marker: PhantomData<&'a mut T>,
634}
635
636impl<'a, T: Copy + FromBytes> Iterator for IterAsMut<'a, T> {
637 type Item = ElemMut<'a, T>;
638
639 fn next(&mut self) -> Option<Self::Item> {
640 if self.ptr == self.end {
641 None
642 } else {
643 let current = self.ptr;
644 self.ptr = unsafe { self.ptr.add(1) };
647 Some(ElemMut { ptr: current, _marker: PhantomData })
648 }
649 }
650
651 fn size_hint(&self) -> (usize, Option<usize>) {
652 let len = unsafe { self.end.offset_from(self.ptr) as usize };
653 (len, Some(len))
654 }
655}
656
657impl<T: Copy + FromBytes> ExactSizeIterator for IterAsMut<'_, T> {}
658
659pub struct ElemMut<'a, T> {
661 ptr: *mut T,
662 _marker: PhantomData<&'a mut T>,
663}
664
665impl<T> ElemMut<'_, T> {
666 pub fn as_ptr(&self) -> *mut T {
668 self.ptr
669 }
670}
671
672impl<T: Copy + FromBytes> ElemMut<'_, T> {
673 pub fn read(&self) -> T {
678 unsafe { std::ptr::read(self.ptr) }
680 }
681
682 pub fn write(&self, val: T) {
687 unsafe { std::ptr::write(self.ptr, val) }
689 }
690}
691
692#[derive(Debug)]
694pub struct Chunks<'a> {
695 slice: PtrByteSlice<'a>,
696 chunk_size: usize,
697 offset: usize,
698}
699
700impl<'a> Iterator for Chunks<'a> {
701 type Item = PtrByteSlice<'a>;
702
703 fn next(&mut self) -> Option<Self::Item> {
704 if self.offset >= self.slice.len() {
705 None
706 } else {
707 let len = std::cmp::min(self.chunk_size, self.slice.len() - self.offset);
708 let chunk = self.slice.subslice(self.offset..self.offset + len);
709 self.offset += len;
710 Some(chunk)
711 }
712 }
713
714 fn size_hint(&self) -> (usize, Option<usize>) {
715 let len = self.len();
716 (len, Some(len))
717 }
718}
719
720impl ExactSizeIterator for Chunks<'_> {
721 fn len(&self) -> usize {
722 let remaining = self.slice.len().saturating_sub(self.offset);
723 remaining.div_ceil(self.chunk_size)
724 }
725}
726
727impl std::iter::FusedIterator for Chunks<'_> {}
728
729#[derive(Debug)]
731pub struct ChunksMut<'a> {
732 slice: MutPtrByteSlice<'a>,
733 chunk_size: usize,
734 offset: usize,
735}
736
737impl<'a> Iterator for ChunksMut<'a> {
738 type Item = MutPtrByteSlice<'a>;
739
740 fn next(&mut self) -> Option<Self::Item> {
741 if self.offset >= self.slice.len() {
742 None
743 } else {
744 let len = std::cmp::min(self.chunk_size, self.slice.len() - self.offset);
745 let chunk = self.slice.subslice_mut(self.offset..self.offset + len);
746 self.offset += len;
747 Some(chunk)
748 }
749 }
750
751 fn size_hint(&self) -> (usize, Option<usize>) {
752 let len = self.len();
753 (len, Some(len))
754 }
755}
756
757impl ExactSizeIterator for ChunksMut<'_> {
758 fn len(&self) -> usize {
759 let remaining = self.slice.len().saturating_sub(self.offset);
760 if remaining == 0 { 0 } else { remaining.div_ceil(self.chunk_size) }
761 }
762}
763
764impl std::iter::FusedIterator for ChunksMut<'_> {}
765
766impl std::io::Read for PtrByteSlice<'_> {
767 fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
768 let remaining = self.len();
769 if remaining == 0 {
770 return Ok(0);
771 }
772 let to_read = std::cmp::min(remaining, buf.len());
773 let (a, b) = self.split_at(to_read);
774 a.copy_to_slice(&mut buf[..to_read]);
775 *self = b;
776 Ok(to_read)
777 }
778
779 fn read_exact(&mut self, buf: &mut [u8]) -> std::io::Result<()> {
780 if buf.len() > self.len() {
781 return Err(std::io::Error::new(
782 std::io::ErrorKind::UnexpectedEof,
783 "failed to fill whole buffer",
784 ));
785 }
786 let (a, b) = self.split_at(buf.len());
787 a.copy_to_slice(buf);
788 *self = b;
789 Ok(())
790 }
791
792 fn read_to_end(&mut self, buf: &mut Vec<u8>) -> std::io::Result<usize> {
793 let len = self.len();
794 self.append_to(buf);
795 *self = self.subslice(len..len);
796 Ok(len)
797 }
798}
799
800#[cfg(test)]
801mod tests {
802 use super::*;
803 use std::io::{Read, Write};
804 use zerocopy::IntoBytes;
805
806 #[derive(Copy, Clone, Debug, FromBytes, IntoBytes)]
807 #[repr(C, align(4))]
808 struct Aligned4(u32);
809
810 #[test]
811 fn test_iter_as_success() {
812 let bytes = [0u8; 16];
813 let slice = PtrByteSlice::from(&bytes[..]);
814 let elems = slice.iter_as::<Aligned4>();
815 assert_eq!(elems.count(), 4);
816 }
817
818 #[test]
819 #[should_panic(expected = "Slice is not aligned to T")]
820 fn test_iter_as_unaligned_panic() {
821 #[repr(C, align(4))]
822 struct AligningBuffer {
823 buffer: [u8; 17],
824 }
825 let aligned = AligningBuffer { buffer: [0u8; 17] };
826 let slice = PtrByteSlice::from(&aligned.buffer[1..17]);
827 let _ = slice.iter_as::<Aligned4>();
828 }
829
830 #[test]
831 #[should_panic]
832 fn test_iter_as_missized_panic() {
833 let bytes = [0u8; 15];
834 let slice = PtrByteSlice::from(&bytes[..]);
835 let _ = slice.iter_as::<Aligned4>();
836 }
837
838 #[test]
839 fn test_iter_as_mut_success() {
840 let mut bytes = [0u8; 16];
841 let mut slice = MutPtrByteSlice::from(&mut bytes[..]);
842 let elems = slice.iter_as_mut::<Aligned4>();
843 assert_eq!(elems.count(), 4);
844 }
845
846 #[test]
847 #[should_panic(expected = "Slice is not aligned to T")]
848 fn test_iter_as_mut_unaligned_panic() {
849 #[repr(C, align(4))]
850 struct AligningBuffer {
851 buffer: [u8; 17],
852 }
853 let mut aligned = AligningBuffer { buffer: [0u8; 17] };
854 let mut slice = MutPtrByteSlice::from(&mut aligned.buffer[1..17]);
855 let _ = slice.iter_as_mut::<Aligned4>();
856 }
857
858 #[test]
859 #[should_panic]
860 fn test_iter_as_mut_missized_panic() {
861 let mut bytes = [0u8; 15];
862 let mut slice = MutPtrByteSlice::from(&mut bytes[..]);
863 let _ = slice.iter_as_mut::<Aligned4>();
864 }
865
866 #[test]
867 fn test_byte_chunks() {
868 let bytes = [1u8, 2, 3, 4, 5, 6, 7, 8, 9, 10];
869 let slice = PtrByteSlice::from(&bytes[..]);
870 let chunks: Vec<_> = slice.chunks(4).map(|c| c.to_vec()).collect();
871 assert_eq!(chunks, vec![vec![1, 2, 3, 4], vec![5, 6, 7, 8], vec![9, 10]]);
872 }
873
874 #[test]
875 fn test_byte_chunks_mut() {
876 let mut bytes = [1u8, 2, 3, 4, 5, 6, 7, 8, 9, 10];
877 let mut slice = MutPtrByteSlice::from(&mut bytes[..]);
878 for mut chunk in slice.chunks_mut(4) {
879 chunk.fill(0);
880 }
881 assert_eq!(bytes, [0u8; 10]);
882 }
883
884 #[test]
885 fn test_reader() {
886 let bytes = [1u8, 2, 3, 4, 5, 6, 7, 8, 9, 10];
887 let mut slice = PtrByteSlice::from(&bytes[..]);
888 let mut buf = [0u8; 4];
889 assert_eq!(Read::read(&mut slice, &mut buf).unwrap(), 4);
890 assert_eq!(buf, [1, 2, 3, 4]);
891 assert_eq!(slice.len(), 6);
892 let mut rest = Vec::new();
893 assert_eq!(slice.read_to_end(&mut rest).unwrap(), 6);
894 assert_eq!(rest, [5, 6, 7, 8, 9, 10]);
895 assert_eq!(slice.len(), 0);
896 }
897
898 #[test]
899 fn test_read_success() {
900 let bytes = [1u8, 2u8, 3u8, 4u8, 5u8, 6u8, 7u8, 8u8];
901 let slice = PtrByteSlice::from(&bytes[..]);
902
903 let val = slice.read::<Aligned4>().unwrap();
904 assert_eq!(val.0, u32::from_ne_bytes([1, 2, 3, 4]));
907
908 let sub = slice.subslice(1..8);
910 let val_unaligned = sub.read::<Aligned4>().unwrap();
911 assert_eq!(val_unaligned.0, u32::from_ne_bytes([2, 3, 4, 5]));
912 }
913
914 #[test]
915 fn test_read_bounds_failure() {
916 let bytes = [1u8, 2u8, 3u8];
917 let slice = PtrByteSlice::from(&bytes[..]);
918 assert!(slice.read::<Aligned4>().is_none());
919 }
920
921 #[test]
922 fn test_mut_read_write_success() {
923 let mut bytes = [0u8; 8];
924 let mut slice = MutPtrByteSlice::from(&mut bytes[..]);
925
926 slice.write(Aligned4(0x12345678)).unwrap();
928 assert_eq!(slice.read::<Aligned4>().unwrap().0, 0x12345678);
929
930 let mut sub = slice.subslice_mut(1..8);
932 sub.write(Aligned4(0xabcdef01)).unwrap();
933 assert_eq!(sub.read::<Aligned4>().unwrap().0, 0xabcdef01);
934 }
935
936 #[test]
937 fn test_mut_write_bounds_failure() {
938 let mut bytes = [0u8; 3];
939 let mut slice = MutPtrByteSlice::from(&mut bytes[..]);
940 assert!(slice.write(Aligned4(0)).is_none());
941 }
942
943 #[test]
944 fn test_writer() {
945 let mut bytes = [0u8; 16];
946 let slice = MutPtrByteSlice::from(&mut bytes[..]);
947 let mut writer = slice.writer();
948 assert_eq!(writer.write(&[1, 2, 3]).unwrap(), 3);
949 assert_eq!(writer.position(), 3);
950 writer.write_all(&[4, 5, 6, 7]).unwrap();
951 assert_eq!(writer.position(), 7);
952 assert_eq!(&bytes[..7], &[1, 2, 3, 4, 5, 6, 7]);
953 }
954
955 #[test]
956 fn test_writer_write_all_error() {
957 let mut bytes = [0u8; 4];
958 let slice = MutPtrByteSlice::from(&mut bytes[..]);
959 let mut writer = slice.writer();
960 let err = writer.write_all(&[1, 2, 3, 4, 5]).unwrap_err();
961 assert_eq!(err.kind(), std::io::ErrorKind::WriteZero);
962 assert_eq!(writer.position(), 0);
963 }
964
965 #[test]
966 fn test_writer_write_full_and_remaining() {
967 let mut bytes = [0u8; 4];
968 let slice = MutPtrByteSlice::from(&mut bytes[..]);
969 let mut writer = slice.writer();
970 assert_eq!(writer.write(&[1, 2, 3, 4, 5]).unwrap(), 4);
971 assert_eq!(writer.position(), 4);
972 assert_eq!(writer.write(&[6]).unwrap(), 0);
973 assert_eq!(writer.remaining().len(), 0);
974 writer.flush().unwrap();
975 let written = writer.into_written();
976 assert_eq!(written.len(), 4);
977 assert_eq!(&bytes[..], &[1, 2, 3, 4]);
978 }
979}