1#![cfg_attr(doc, doc = include_str!("../README.md"))]
2#![cfg_attr(not(feature = "std"), no_std)]
3#![cfg_attr(docsrs, feature(doc_cfg))]
4
5#[cfg(feature = "alloc")]
6extern crate alloc;
7
8#[cfg(feature = "alloc")]
9use alloc::boxed::Box;
10#[cfg(feature = "alloc")]
11use alloc::vec::Vec;
12use core::marker::PhantomData;
13use core::mem::MaybeUninit;
14use core::slice;
15
16pub trait Buffer<T>
123where
124 Self: Sized,
125{
126 type Output;
128
129 fn buffer_ptr(&mut self) -> *mut T;
136
137 fn buffer_len(&self) -> usize;
139
140 unsafe fn assume_init(self, len: usize) -> Self::Output;
146
147 fn cursor(self) -> Cursor<T, Self> {
156 Cursor::new(self)
157 }
158}
159
160impl<T> Buffer<T> for &mut [T] {
161 type Output = usize;
162
163 #[inline]
164 fn buffer_ptr(&mut self) -> *mut T {
165 self.as_mut_ptr()
166 }
167
168 #[inline]
169 fn buffer_len(&self) -> usize {
170 self.len()
171 }
172
173 #[inline]
174 unsafe fn assume_init(self, len: usize) -> Self::Output {
175 len
176 }
177}
178
179impl<T, const N: usize> Buffer<T> for &mut [T; N] {
180 type Output = usize;
181
182 #[inline]
183 fn buffer_ptr(&mut self) -> *mut T {
184 self.as_mut_ptr()
185 }
186
187 #[inline]
188 fn buffer_len(&self) -> usize {
189 N
190 }
191
192 #[inline]
193 unsafe fn assume_init(self, len: usize) -> Self::Output {
194 len
195 }
196}
197
198#[cfg(feature = "alloc")]
202impl<T> Buffer<T> for &mut Vec<T> {
203 type Output = usize;
204
205 #[inline]
206 fn buffer_ptr(&mut self) -> *mut T {
207 self.as_mut_ptr()
208 }
209
210 #[inline]
211 fn buffer_len(&self) -> usize {
212 self.len()
213 }
214
215 #[inline]
216 unsafe fn assume_init(self, len: usize) -> Self::Output {
217 len
218 }
219}
220
221#[cfg(feature = "alloc")]
225impl<T> Buffer<T> for &mut Box<[T]> {
226 type Output = usize;
227
228 #[inline]
229 fn buffer_ptr(&mut self) -> *mut T {
230 self.as_mut_ptr()
231 }
232
233 #[inline]
234 fn buffer_len(&self) -> usize {
235 self.len()
236 }
237
238 #[inline]
239 unsafe fn assume_init(self, len: usize) -> Self::Output {
240 len
241 }
242}
243
244impl<'a, T> Buffer<T> for &'a mut [MaybeUninit<T>] {
245 type Output = (&'a mut [T], &'a mut [MaybeUninit<T>]);
246
247 #[inline]
248 fn buffer_ptr(&mut self) -> *mut T {
249 self.as_mut_ptr().cast::<T>()
250 }
251
252 #[inline]
253 fn buffer_len(&self) -> usize {
254 self.len()
255 }
256
257 #[inline]
258 unsafe fn assume_init(self, len: usize) -> Self::Output {
259 let (init, uninit) = self.split_at_mut(len);
260
261 let init = unsafe { slice::from_raw_parts_mut(init.as_mut_ptr().cast::<T>(), init.len()) };
266
267 (init, uninit)
268 }
269}
270
271impl<'a, T, const N: usize> Buffer<T> for &'a mut [MaybeUninit<T>; N] {
272 type Output = (&'a mut [T], &'a mut [MaybeUninit<T>]);
273
274 #[inline]
275 fn buffer_ptr(&mut self) -> *mut T {
276 self.as_mut_ptr().cast::<T>()
277 }
278
279 #[inline]
280 fn buffer_len(&self) -> usize {
281 N
282 }
283
284 #[inline]
285 unsafe fn assume_init(self, len: usize) -> Self::Output {
286 let (init, uninit) = self.split_at_mut(len);
287
288 let init = unsafe { slice::from_raw_parts_mut(init.as_mut_ptr().cast::<T>(), init.len()) };
293
294 (init, uninit)
295 }
296}
297
298#[cfg(feature = "alloc")]
299impl<'a, T> Buffer<T> for &'a mut Vec<MaybeUninit<T>> {
300 type Output = (&'a mut [T], &'a mut [MaybeUninit<T>]);
301
302 #[inline]
303 fn buffer_ptr(&mut self) -> *mut T {
304 self.as_mut_ptr().cast::<T>()
305 }
306
307 #[inline]
308 fn buffer_len(&self) -> usize {
309 self.len()
310 }
311
312 #[inline]
313 unsafe fn assume_init(self, len: usize) -> Self::Output {
314 let (init, uninit) = self.split_at_mut(len);
315
316 let init = unsafe { slice::from_raw_parts_mut(init.as_mut_ptr().cast::<T>(), init.len()) };
321
322 (init, uninit)
323 }
324}
325
326#[cfg(feature = "alloc")]
327impl<'a, T> Buffer<T> for &'a mut Box<[MaybeUninit<T>]> {
328 type Output = (&'a mut [T], &'a mut [MaybeUninit<T>]);
329
330 #[inline]
331 fn buffer_ptr(&mut self) -> *mut T {
332 self.as_mut_ptr().cast::<T>()
333 }
334
335 #[inline]
336 fn buffer_len(&self) -> usize {
337 self.len()
338 }
339
340 #[inline]
341 unsafe fn assume_init(self, len: usize) -> Self::Output {
342 let (init, uninit) = self.split_at_mut(len);
343
344 let init = unsafe { slice::from_raw_parts_mut(init.as_mut_ptr().cast::<T>(), init.len()) };
349
350 (init, uninit)
351 }
352}
353
354#[cfg(feature = "std")]
358impl<'a> Buffer<u8> for &mut std::io::IoSliceMut<'a> {
359 type Output = usize;
360
361 #[inline]
362 fn buffer_ptr(&mut self) -> *mut u8 {
363 self.as_mut_ptr()
364 }
365
366 #[inline]
367 fn buffer_len(&self) -> usize {
368 self.len()
369 }
370
371 #[inline]
372 unsafe fn assume_init(self, len: usize) -> Self::Output {
373 len
374 }
375}
376
377#[cfg(feature = "alloc")]
385#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
386pub struct SpareCapacity<'a, T>(&'a mut Vec<T>);
387
388#[cfg(feature = "alloc")]
418#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
419pub fn spare_capacity<'a, T>(v: &'a mut Vec<T>) -> SpareCapacity<'a, T> {
420 debug_assert_ne!(
421 v.capacity(),
422 0,
423 "`extend` uses spare capacity, and never allocates new memory, so the `Vec` passed to it \
424 should have some spare capacity."
425 );
426
427 SpareCapacity(v)
428}
429
430#[cfg(feature = "alloc")]
431impl<'a, T> Buffer<T> for SpareCapacity<'a, T> {
432 type Output = usize;
438
439 #[inline]
440 fn buffer_ptr(&mut self) -> *mut T {
441 self.0.spare_capacity_mut().as_mut_ptr().cast::<T>()
442 }
443
444 #[inline]
445 fn buffer_len(&self) -> usize {
446 self.0.capacity() - self.0.len()
447 }
448
449 #[inline]
450 unsafe fn assume_init(self, len: usize) -> Self::Output {
451 unsafe {
454 self.0.set_len(self.0.len() + len);
455 }
456 len
457 }
458}
459
460pub struct Cursor<T, B: Buffer<T>> {
477 pos: usize,
478 b: B,
479 phantom: PhantomData<T>,
480}
481
482impl<T, B: Buffer<T>> Cursor<T, B> {
483 pub const fn new(b: B) -> Self {
485 Self {
486 pos: 0,
487 b,
488 phantom: PhantomData,
489 }
490 }
491
492 pub fn remaining(&self) -> usize {
494 self.b.buffer_len() - self.pos
495 }
496
497 pub fn write(&mut self, t: T) {
503 let ptr = self.b.buffer_ptr();
504 let len = self.b.buffer_len();
505
506 assert!(
507 self.pos < len,
508 "element would extend beyond the end of the buffer"
509 );
510
511 unsafe {
514 ptr.add(self.pos).write(t);
515 }
516
517 self.pos += 1;
519 }
520
521 pub fn write_slice(&mut self, t: &[T])
528 where
529 T: Copy,
530 {
531 let ptr = self.b.buffer_ptr();
532 let len = self.b.buffer_len();
533
534 assert!(
535 len - self.pos >= t.len(),
536 "elements would extend beyond the end of the buffer"
537 );
538
539 unsafe {
543 core::ptr::copy_nonoverlapping(t.as_ptr(), ptr, t.len());
544 }
545
546 self.pos += t.len();
548 }
549
550 pub fn finish(self) -> B::Output {
552 unsafe { self.b.assume_init(self.pos) }
555 }
556}
557
558impl<T, B: Buffer<T>> Buffer<T> for Cursor<T, B> {
559 type Output = B::Output;
560
561 #[inline]
562 fn buffer_ptr(&mut self) -> *mut T {
563 unsafe { self.b.buffer_ptr().add(self.pos) }
566 }
567
568 #[inline]
569 fn buffer_len(&self) -> usize {
570 self.remaining()
571 }
572
573 #[inline]
574 unsafe fn assume_init(mut self, len: usize) -> Self::Output {
575 self.pos += len;
577 self.finish()
578 }
579}
580
581impl<T, B: Buffer<T>> Buffer<T> for &mut Cursor<T, B> {
584 type Output = usize;
585
586 #[inline]
587 fn buffer_ptr(&mut self) -> *mut T {
588 unsafe { self.b.buffer_ptr().add(self.pos) }
591 }
592
593 #[inline]
594 fn buffer_len(&self) -> usize {
595 self.remaining()
596 }
597
598 #[inline]
599 unsafe fn assume_init(self, len: usize) -> Self::Output {
600 self.pos += len;
602 len
603 }
604}
605
606#[cfg(test)]
607mod tests {
608 #[allow(unused_imports)]
609 use super::*;
610
611 #[cfg(not(windows))]
613 #[test]
614 fn test_compilation() {
615 use core::mem::MaybeUninit;
616
617 fn read<B: Buffer<u8>>(b: B) -> Result<B::Output, ()> {
618 Ok(b.cursor().finish())
619 }
620
621 let mut buf = vec![0_u8; 3];
622 buf.reserve(32);
623 let _x: usize = read(spare_capacity(&mut buf)).unwrap();
624 let _x: (&mut [u8], &mut [MaybeUninit<u8>]) = read(buf.spare_capacity_mut()).unwrap();
625 let _x: usize = read(&mut buf).unwrap();
626 let _x: usize = read(&mut *buf).unwrap();
627 let _x: usize = read(&mut buf[..]).unwrap();
628 let _x: usize = read(&mut (*buf)[..]).unwrap();
629
630 let mut buf = [0, 0, 0];
631 let _x: usize = read(&mut buf).unwrap();
632 let _x: usize = read(&mut buf[..]).unwrap();
633
634 let mut buf = vec![0, 0, 0];
635 let _x: usize = read(&mut buf).unwrap();
636 let _x: usize = read(&mut buf[..]).unwrap();
637
638 let mut buf = vec![0, 0, 0].into_boxed_slice();
639 let _x: usize = read(&mut buf).unwrap();
640 let _x: usize = read(&mut buf[..]).unwrap();
641
642 let mut buf = [
643 MaybeUninit::uninit(),
644 MaybeUninit::uninit(),
645 MaybeUninit::uninit(),
646 ];
647 let _x: (&mut [u8], &mut [MaybeUninit<u8>]) = read(&mut buf).unwrap();
648 let _x: (&mut [u8], &mut [MaybeUninit<u8>]) = read(&mut buf[..]).unwrap();
649
650 let mut buf = vec![
651 MaybeUninit::uninit(),
652 MaybeUninit::uninit(),
653 MaybeUninit::uninit(),
654 ];
655 let _x: (&mut [u8], &mut [MaybeUninit<u8>]) = read(&mut buf).unwrap();
656 let _x: (&mut [u8], &mut [MaybeUninit<u8>]) = read(&mut buf[..]).unwrap();
657
658 let mut buf = vec![
659 MaybeUninit::uninit(),
660 MaybeUninit::uninit(),
661 MaybeUninit::uninit(),
662 ]
663 .into_boxed_slice();
664 let _x: (&mut [u8], &mut [MaybeUninit<u8>]) = read(&mut buf).unwrap();
665 let _x: (&mut [u8], &mut [MaybeUninit<u8>]) = read(&mut buf[..]).unwrap();
666
667 let mut buf = Cursor::new(&mut buf);
668 let _x: usize = read(&mut buf).unwrap();
669 let _x: (&mut [u8], &mut [MaybeUninit<u8>]) = buf.finish();
670
671 let mut buf = [0, 0, 0];
672 let mut io_slice = std::io::IoSliceMut::new(&mut buf);
673 let _x: usize = read(&mut io_slice).unwrap();
674 let _x: usize = read(&mut io_slice[..]).unwrap();
675 }
676
677 #[cfg(not(windows))]
679 #[test]
680 fn test_slice() {
681 use std::io::{Seek, SeekFrom};
682
683 let mut input = std::fs::File::open("src/lib.rs").unwrap();
686
687 let mut buf = [0_u8; 64];
688 let nread = read(&input, &mut buf).unwrap();
689 assert_eq!(nread, buf.len());
690 assert_eq!(
691 &buf[..54],
692 b"#![cfg_attr(doc, doc = include_str!(\"../README.md\"))]\n"
693 );
694 input.seek(SeekFrom::End(-1)).unwrap();
695 let nread = read(&input, &mut buf).unwrap();
696 assert_eq!(nread, 1);
697 assert_eq!(buf[0], b'\n');
698 input.seek(SeekFrom::End(0)).unwrap();
699 let nread = read(&input, &mut buf).unwrap();
700 assert_eq!(nread, 0);
701 }
702
703 #[cfg(not(windows))]
705 #[test]
706 fn test_slice_uninit() {
707 use core::mem::MaybeUninit;
708 use std::io::{Seek, SeekFrom};
709
710 let mut input = std::fs::File::open("src/lib.rs").unwrap();
713
714 let mut buf = [MaybeUninit::<u8>::uninit(); 64];
715 let (init, uninit) = read(&input, &mut buf).unwrap();
716 assert_eq!(uninit.len(), 0);
717 assert_eq!(
718 &init[..54],
719 b"#![cfg_attr(doc, doc = include_str!(\"../README.md\"))]\n"
720 );
721 assert_eq!(init.len(), buf.len());
722 assert_eq!(
723 unsafe { core::mem::transmute::<&mut [MaybeUninit<u8>], &mut [u8]>(&mut buf[..54]) },
724 b"#![cfg_attr(doc, doc = include_str!(\"../README.md\"))]\n"
725 );
726 input.seek(SeekFrom::End(-1)).unwrap();
727 let (init, uninit) = read(&input, &mut buf).unwrap();
728 assert_eq!(init.len(), 1);
729 assert_eq!(init[0], b'\n');
730 assert_eq!(uninit.len(), buf.len() - 1);
731 input.seek(SeekFrom::End(0)).unwrap();
732 let (init, uninit) = read(&input, &mut buf).unwrap();
733 assert_eq!(init.len(), 0);
734 assert_eq!(uninit.len(), buf.len());
735 }
736
737 #[cfg(not(windows))]
739 #[test]
740 fn test_spare_capacity() {
741 use std::io::{Seek, SeekFrom};
742
743 let mut input = std::fs::File::open("src/lib.rs").unwrap();
746
747 let mut buf = Vec::with_capacity(64);
748 let nread = read(&input, spare_capacity(&mut buf)).unwrap();
749 assert_eq!(nread, buf.capacity());
750 assert_eq!(nread, buf.len());
751 assert_eq!(
752 &buf[..54],
753 b"#![cfg_attr(doc, doc = include_str!(\"../README.md\"))]\n"
754 );
755 buf.clear();
756 input.seek(SeekFrom::End(-1)).unwrap();
757 let nread = read(&input, spare_capacity(&mut buf)).unwrap();
758 assert_eq!(nread, 1);
759 assert_eq!(buf.len(), 1);
760 assert_eq!(buf[0], b'\n');
761 buf.clear();
762 input.seek(SeekFrom::End(0)).unwrap();
763 let nread = read(&input, spare_capacity(&mut buf)).unwrap();
764 assert_eq!(nread, 0);
765 assert!(buf.is_empty());
766 }
767
768 #[test]
770 fn test_cursor_as_buffer() {
771 use std::io::{Seek, SeekFrom};
772
773 let mut input = std::fs::File::open("src/lib.rs").unwrap();
776
777 let mut total_read = 0;
778
779 let mut buf = Vec::with_capacity(256);
780 let mut cursor = Cursor::new(spare_capacity(&mut buf));
781 input.seek(SeekFrom::End(-39)).unwrap();
782 let nread = read(&input, &mut cursor).unwrap();
783 total_read += nread;
784 assert_eq!(cursor.remaining(), 256 - 39);
785 input.seek(SeekFrom::End(-39)).unwrap();
786 let nread = read(&input, &mut cursor).unwrap();
787 total_read += nread;
788 assert_eq!(cursor.remaining(), 256 - 39 * 2);
789 input.seek(SeekFrom::End(-39)).unwrap();
790 let nread = read(&input, &mut cursor).unwrap();
791 total_read += nread;
792 assert_eq!(cursor.remaining(), 256 - 39 * 3);
793
794 assert_eq!(total_read, 39 * 3);
795
796 let cursor_read = cursor.finish();
797 assert_eq!(cursor_read, total_read);
798
799 assert_eq!(buf.len(), 39 * 3);
800 assert_eq!(buf.capacity(), 256);
801 assert_eq!(
802 buf,
803 b"// The comment at the end of the file!\n// The comment at the end of the file!\n// The comment at the end of the file!\n"
804 );
805 }
806
807 #[test]
809 fn test_nesting() {
810 use std::io::{Seek, SeekFrom};
811
812 let mut input = std::fs::File::open("src/lib.rs").unwrap();
815
816 let mut total_read = 0;
817
818 let mut buf = Vec::with_capacity(256);
819 let mut cursor = Cursor::new(spare_capacity(&mut buf));
820 input.seek(SeekFrom::End(-39)).unwrap();
821 let nread = read(&input, &mut cursor).unwrap();
822 total_read += nread;
823 assert_eq!(cursor.remaining(), 256 - 39);
824 input.seek(SeekFrom::End(-39)).unwrap();
825 let mut nested_cursor = Cursor::new(&mut cursor);
826 let nested_nread = read(&input, &mut nested_cursor).unwrap();
827 assert_eq!(nested_nread, 39);
828 assert_eq!(nested_cursor.remaining(), 256 - 39 * 2);
829 input.seek(SeekFrom::End(-39)).unwrap();
830 let mut nested_nested_cursor = Cursor::new(&mut nested_cursor);
831 let nested_nested_nread = read(&input, &mut nested_nested_cursor).unwrap();
832 assert_eq!(nested_nested_nread, 39);
833 assert_eq!(nested_nested_cursor.remaining(), 256 - 39 * 3);
834 let inner_nread = nested_nested_cursor.finish();
835 assert_eq!(inner_nread, 39);
836 assert_eq!(nested_cursor.remaining(), 256 - 39 * 3);
837 let nread = nested_cursor.finish();
838 total_read += nread;
839
840 assert_eq!(total_read, 39 * 3);
841 assert_eq!(cursor.remaining(), 256 - 39 * 3);
842
843 let cursor_read = cursor.finish();
844 assert_eq!(cursor_read, total_read);
845
846 assert_eq!(buf.len(), 39 * 3);
847 assert_eq!(buf.capacity(), 256);
848 assert_eq!(
849 &buf[..39*3],
850 b"// The comment at the end of the file!\n// The comment at the end of the file!\n// The comment at the end of the file!\n"
851 );
852 }
853
854 #[test]
857 fn test_incremental() {
858 use std::io::{Seek, SeekFrom};
859
860 let mut input = std::fs::File::open("src/lib.rs").unwrap();
863
864 let mut total_read = 0;
865
866 let mut buf = [MaybeUninit::<u8>::zeroed(); 256];
867 let mut cursor = Cursor::new(&mut buf);
868 input.seek(SeekFrom::End(-39)).unwrap();
869 let nread = read(&input, &mut cursor).unwrap();
870 total_read += nread;
871 assert_eq!(cursor.remaining(), 256 - 39);
872 input.seek(SeekFrom::End(-39)).unwrap();
873 let nread = read(&input, &mut cursor).unwrap();
874 total_read += nread;
875 assert_eq!(cursor.remaining(), 256 - 39 * 2);
876 input.seek(SeekFrom::End(-39)).unwrap();
877 let nread = read(&input, &mut cursor).unwrap();
878 total_read += nread;
879 assert_eq!(cursor.remaining(), 256 - 39 * 3);
880
881 assert_eq!(total_read, 39 * 3);
882
883 let (init, uninit) = cursor.finish();
884 assert_eq!(init.len(), total_read);
885 assert_eq!(uninit.len(), 256 - total_read);
886
887 assert_eq!(
888 init,
889 b"// The comment at the end of the file!\n// The comment at the end of the file!\n// The comment at the end of the file!\n"
890 );
891 }
892
893 fn read<B: Buffer<u8>>(input: &std::fs::File, mut b: B) -> std::io::Result<B::Output> {
894 use std::os::fd::AsRawFd;
895 let ptr = b.buffer_ptr();
896 let len = b.buffer_len();
897 let n = unsafe { libc::read(input.as_raw_fd(), ptr.cast(), len) };
898 if let Ok(n) = usize::try_from(n) {
899 unsafe { Ok(b.assume_init(n)) }
900 } else {
901 Err(std::io::Error::last_os_error())
902 }
903 }
904}
905
906