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()
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 unsafe {
262 let (init, uninit) = self.split_at_mut(len);
263
264 let init = slice::from_raw_parts_mut(init.as_mut_ptr().cast::<T>(), init.len());
266
267 (init, uninit)
268 }
269 }
270}
271
272impl<'a, T, const N: usize> Buffer<T> for &'a mut [MaybeUninit<T>; N] {
273 type Output = (&'a mut [T], &'a mut [MaybeUninit<T>]);
274
275 #[inline]
276 fn buffer_ptr(&mut self) -> *mut T {
277 self.as_mut_ptr().cast()
278 }
279
280 #[inline]
281 fn buffer_len(&self) -> usize {
282 N
283 }
284
285 #[inline]
286 unsafe fn assume_init(self, len: usize) -> Self::Output {
287 unsafe {
290 let (init, uninit) = self.split_at_mut(len);
291
292 let init = slice::from_raw_parts_mut(init.as_mut_ptr().cast::<T>(), init.len());
294
295 (init, uninit)
296 }
297 }
298}
299
300#[cfg(feature = "alloc")]
301impl<'a, T> Buffer<T> for &'a mut Vec<MaybeUninit<T>> {
302 type Output = (&'a mut [T], &'a mut [MaybeUninit<T>]);
303
304 #[inline]
305 fn buffer_ptr(&mut self) -> *mut T {
306 self.as_mut_ptr().cast()
307 }
308
309 #[inline]
310 fn buffer_len(&self) -> usize {
311 self.len()
312 }
313
314 #[inline]
315 unsafe fn assume_init(self, len: usize) -> Self::Output {
316 unsafe {
319 let (init, uninit) = self.split_at_mut(len);
320
321 let init = slice::from_raw_parts_mut(init.as_mut_ptr().cast::<T>(), init.len());
323
324 (init, uninit)
325 }
326 }
327}
328
329#[cfg(feature = "alloc")]
330impl<'a, T> Buffer<T> for &'a mut Box<[MaybeUninit<T>]> {
331 type Output = (&'a mut [T], &'a mut [MaybeUninit<T>]);
332
333 #[inline]
334 fn buffer_ptr(&mut self) -> *mut T {
335 self.as_mut_ptr().cast()
336 }
337
338 #[inline]
339 fn buffer_len(&self) -> usize {
340 self.len()
341 }
342
343 #[inline]
344 unsafe fn assume_init(self, len: usize) -> Self::Output {
345 unsafe {
348 let (init, uninit) = self.split_at_mut(len);
349
350 let init = slice::from_raw_parts_mut(init.as_mut_ptr().cast::<T>(), init.len());
352
353 (init, uninit)
354 }
355 }
356}
357
358#[cfg(feature = "std")]
362impl<'a> Buffer<u8> for &mut std::io::IoSliceMut<'a> {
363 type Output = usize;
364
365 #[inline]
366 fn buffer_ptr(&mut self) -> *mut u8 {
367 self.as_mut_ptr()
368 }
369
370 #[inline]
371 fn buffer_len(&self) -> usize {
372 self.len()
373 }
374
375 #[inline]
376 unsafe fn assume_init(self, len: usize) -> Self::Output {
377 len
378 }
379}
380
381#[cfg(feature = "alloc")]
389#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
390pub struct SpareCapacity<'a, T>(&'a mut Vec<T>);
391
392#[cfg(feature = "alloc")]
422#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
423pub fn spare_capacity<'a, T>(v: &'a mut Vec<T>) -> SpareCapacity<'a, T> {
424 debug_assert_ne!(
425 v.capacity(),
426 0,
427 "`extend` uses spare capacity, and never allocates new memory, so the `Vec` passed to it \
428 should have some spare capacity."
429 );
430
431 SpareCapacity(v)
432}
433
434#[cfg(feature = "alloc")]
435impl<'a, T> Buffer<T> for SpareCapacity<'a, T> {
436 type Output = usize;
442
443 #[inline]
444 fn buffer_ptr(&mut self) -> *mut T {
445 self.0.spare_capacity_mut().as_mut_ptr().cast()
446 }
447
448 #[inline]
449 fn buffer_len(&self) -> usize {
450 self.0.capacity() - self.0.len()
451 }
452
453 #[inline]
454 unsafe fn assume_init(self, len: usize) -> Self::Output {
455 unsafe {
458 self.0.set_len(self.0.len() + len);
459 }
460 len
461 }
462}
463
464pub struct Cursor<T, B: Buffer<T>> {
481 pos: usize,
482 b: B,
483 phantom: PhantomData<T>,
484}
485
486impl<T, B: Buffer<T>> Cursor<T, B> {
487 pub const fn new(b: B) -> Self {
489 Self {
490 pos: 0,
491 b,
492 phantom: PhantomData,
493 }
494 }
495
496 pub fn remaining(&self) -> usize {
498 self.b.buffer_len() - self.pos
499 }
500
501 pub fn write(&mut self, t: T) {
507 let ptr = self.b.buffer_ptr();
508 let len = self.b.buffer_len();
509
510 assert!(
511 self.pos < len,
512 "element would extend beyond the end of the buffer"
513 );
514
515 unsafe {
518 ptr.add(self.pos).write(t);
519 }
520
521 self.pos += 1;
523 }
524
525 pub fn write_slice(&mut self, t: &[T])
532 where
533 T: Copy,
534 {
535 let ptr = self.b.buffer_ptr();
536 let len = self.b.buffer_len();
537
538 assert!(
539 len - self.pos >= t.len(),
540 "elements would extend beyond the end of the buffer"
541 );
542
543 unsafe {
547 core::ptr::copy_nonoverlapping(t.as_ptr(), ptr, t.len());
548 }
549
550 self.pos += t.len();
552 }
553
554 pub fn finish(self) -> B::Output {
556 unsafe { self.b.assume_init(self.pos) }
559 }
560}
561
562impl<T, B: Buffer<T>> Buffer<T> for &mut Cursor<T, B> {
563 type Output = usize;
564
565 #[inline]
566 fn buffer_ptr(&mut self) -> *mut T {
567 unsafe { self.b.buffer_ptr().add(self.pos) }
570 }
571
572 #[inline]
573 fn buffer_len(&self) -> usize {
574 self.remaining()
575 }
576
577 #[inline]
578 unsafe fn assume_init(self, len: usize) -> Self::Output {
579 self.pos += len;
581 len
582 }
583}
584
585#[cfg(test)]
586mod tests {
587 #[allow(unused_imports)]
588 use super::*;
589
590 #[cfg(not(windows))]
592 #[test]
593 fn test_compilation() {
594 use core::mem::MaybeUninit;
595
596 fn read<B: Buffer<u8>>(b: B) -> Result<B::Output, ()> {
597 Ok(b.cursor().finish())
598 }
599
600 let mut buf = vec![0_u8; 3];
601 buf.reserve(32);
602 let _x: usize = read(spare_capacity(&mut buf)).unwrap();
603 let _x: (&mut [u8], &mut [MaybeUninit<u8>]) = read(buf.spare_capacity_mut()).unwrap();
604 let _x: usize = read(&mut buf).unwrap();
605 let _x: usize = read(&mut *buf).unwrap();
606 let _x: usize = read(&mut buf[..]).unwrap();
607 let _x: usize = read(&mut (*buf)[..]).unwrap();
608
609 let mut buf = [0, 0, 0];
610 let _x: usize = read(&mut buf).unwrap();
611 let _x: usize = read(&mut buf[..]).unwrap();
612
613 let mut buf = vec![0, 0, 0];
614 let _x: usize = read(&mut buf).unwrap();
615 let _x: usize = read(&mut buf[..]).unwrap();
616
617 let mut buf = vec![0, 0, 0].into_boxed_slice();
618 let _x: usize = read(&mut buf).unwrap();
619 let _x: usize = read(&mut buf[..]).unwrap();
620
621 let mut buf = [
622 MaybeUninit::uninit(),
623 MaybeUninit::uninit(),
624 MaybeUninit::uninit(),
625 ];
626 let _x: (&mut [u8], &mut [MaybeUninit<u8>]) = read(&mut buf).unwrap();
627 let _x: (&mut [u8], &mut [MaybeUninit<u8>]) = read(&mut buf[..]).unwrap();
628
629 let mut buf = vec![
630 MaybeUninit::uninit(),
631 MaybeUninit::uninit(),
632 MaybeUninit::uninit(),
633 ];
634 let _x: (&mut [u8], &mut [MaybeUninit<u8>]) = read(&mut buf).unwrap();
635 let _x: (&mut [u8], &mut [MaybeUninit<u8>]) = read(&mut buf[..]).unwrap();
636
637 let mut buf = vec![
638 MaybeUninit::uninit(),
639 MaybeUninit::uninit(),
640 MaybeUninit::uninit(),
641 ]
642 .into_boxed_slice();
643 let _x: (&mut [u8], &mut [MaybeUninit<u8>]) = read(&mut buf).unwrap();
644 let _x: (&mut [u8], &mut [MaybeUninit<u8>]) = read(&mut buf[..]).unwrap();
645
646 let mut buf = Cursor::new(&mut buf);
647 let _x: usize = read(&mut buf).unwrap();
648 let _x: (&mut [u8], &mut [MaybeUninit<u8>]) = buf.finish();
649
650 let mut buf = [0, 0, 0];
651 let mut io_slice = std::io::IoSliceMut::new(&mut buf);
652 let _x: usize = read(&mut io_slice).unwrap();
653 let _x: usize = read(&mut io_slice[..]).unwrap();
654 }
655
656 #[cfg(not(windows))]
658 #[test]
659 fn test_slice() {
660 use std::io::{Seek, SeekFrom};
661
662 let mut input = std::fs::File::open("src/lib.rs").unwrap();
665
666 let mut buf = [0_u8; 64];
667 let nread = read(&input, &mut buf).unwrap();
668 assert_eq!(nread, buf.len());
669 assert_eq!(
670 &buf[..54],
671 b"#![cfg_attr(doc, doc = include_str!(\"../README.md\"))]\n"
672 );
673 input.seek(SeekFrom::End(-1)).unwrap();
674 let nread = read(&input, &mut buf).unwrap();
675 assert_eq!(nread, 1);
676 assert_eq!(buf[0], b'\n');
677 input.seek(SeekFrom::End(0)).unwrap();
678 let nread = read(&input, &mut buf).unwrap();
679 assert_eq!(nread, 0);
680 }
681
682 #[cfg(not(windows))]
684 #[test]
685 fn test_slice_uninit() {
686 use core::mem::MaybeUninit;
687 use std::io::{Seek, SeekFrom};
688
689 let mut input = std::fs::File::open("src/lib.rs").unwrap();
692
693 let mut buf = [MaybeUninit::<u8>::uninit(); 64];
694 let (init, uninit) = read(&input, &mut buf).unwrap();
695 assert_eq!(uninit.len(), 0);
696 assert_eq!(
697 &init[..54],
698 b"#![cfg_attr(doc, doc = include_str!(\"../README.md\"))]\n"
699 );
700 assert_eq!(init.len(), buf.len());
701 assert_eq!(
702 unsafe { core::mem::transmute::<&mut [MaybeUninit<u8>], &mut [u8]>(&mut buf[..54]) },
703 b"#![cfg_attr(doc, doc = include_str!(\"../README.md\"))]\n"
704 );
705 input.seek(SeekFrom::End(-1)).unwrap();
706 let (init, uninit) = read(&input, &mut buf).unwrap();
707 assert_eq!(init.len(), 1);
708 assert_eq!(init[0], b'\n');
709 assert_eq!(uninit.len(), buf.len() - 1);
710 input.seek(SeekFrom::End(0)).unwrap();
711 let (init, uninit) = read(&input, &mut buf).unwrap();
712 assert_eq!(init.len(), 0);
713 assert_eq!(uninit.len(), buf.len());
714 }
715
716 #[cfg(not(windows))]
718 #[test]
719 fn test_spare_capacity() {
720 use std::io::{Seek, SeekFrom};
721
722 let mut input = std::fs::File::open("src/lib.rs").unwrap();
725
726 let mut buf = Vec::with_capacity(64);
727 let nread = read(&input, spare_capacity(&mut buf)).unwrap();
728 assert_eq!(nread, buf.capacity());
729 assert_eq!(nread, buf.len());
730 assert_eq!(
731 &buf[..54],
732 b"#![cfg_attr(doc, doc = include_str!(\"../README.md\"))]\n"
733 );
734 buf.clear();
735 input.seek(SeekFrom::End(-1)).unwrap();
736 let nread = read(&input, spare_capacity(&mut buf)).unwrap();
737 assert_eq!(nread, 1);
738 assert_eq!(buf.len(), 1);
739 assert_eq!(buf[0], b'\n');
740 buf.clear();
741 input.seek(SeekFrom::End(0)).unwrap();
742 let nread = read(&input, spare_capacity(&mut buf)).unwrap();
743 assert_eq!(nread, 0);
744 assert!(buf.is_empty());
745 }
746
747 #[test]
749 fn test_cursor_as_buffer() {
750 use std::io::{Seek, SeekFrom};
751
752 let mut input = std::fs::File::open("src/lib.rs").unwrap();
755
756 let mut total_read = 0;
757
758 let mut buf = Vec::with_capacity(256);
759 let mut cursor = Cursor::new(spare_capacity(&mut buf));
760 input.seek(SeekFrom::End(-39)).unwrap();
761 let nread = read(&input, &mut cursor).unwrap();
762 total_read += nread;
763 assert_eq!(cursor.remaining(), 256 - 39);
764 input.seek(SeekFrom::End(-39)).unwrap();
765 let nread = read(&input, &mut cursor).unwrap();
766 total_read += nread;
767 assert_eq!(cursor.remaining(), 256 - 39 * 2);
768 input.seek(SeekFrom::End(-39)).unwrap();
769 let nread = read(&input, &mut cursor).unwrap();
770 total_read += nread;
771 assert_eq!(cursor.remaining(), 256 - 39 * 3);
772
773 assert_eq!(total_read, 39 * 3);
774
775 let cursor_read = cursor.finish();
776 assert_eq!(cursor_read, total_read);
777
778 assert_eq!(buf.len(), 39 * 3);
779 assert_eq!(buf.capacity(), 256);
780 assert_eq!(
781 buf,
782 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"
783 );
784 }
785
786 #[test]
788 fn test_nesting() {
789 use std::io::{Seek, SeekFrom};
790
791 let mut input = std::fs::File::open("src/lib.rs").unwrap();
794
795 let mut total_read = 0;
796
797 let mut buf = Vec::with_capacity(256);
798 let mut cursor = Cursor::new(spare_capacity(&mut buf));
799 input.seek(SeekFrom::End(-39)).unwrap();
800 let nread = read(&input, &mut cursor).unwrap();
801 total_read += nread;
802 assert_eq!(cursor.remaining(), 256 - 39);
803 input.seek(SeekFrom::End(-39)).unwrap();
804 let mut nested_cursor = Cursor::new(&mut cursor);
805 let nested_nread = read(&input, &mut nested_cursor).unwrap();
806 assert_eq!(nested_nread, 39);
807 assert_eq!(nested_cursor.remaining(), 256 - 39 * 2);
808 input.seek(SeekFrom::End(-39)).unwrap();
809 let mut nested_nested_cursor = Cursor::new(&mut nested_cursor);
810 let nested_nested_nread = read(&input, &mut nested_nested_cursor).unwrap();
811 assert_eq!(nested_nested_nread, 39);
812 assert_eq!(nested_nested_cursor.remaining(), 256 - 39 * 3);
813 let inner_nread = nested_nested_cursor.finish();
814 assert_eq!(inner_nread, 39);
815 assert_eq!(nested_cursor.remaining(), 256 - 39 * 3);
816 let nread = nested_cursor.finish();
817 total_read += nread;
818
819 assert_eq!(total_read, 39 * 3);
820 assert_eq!(cursor.remaining(), 256 - 39 * 3);
821
822 let cursor_read = cursor.finish();
823 assert_eq!(cursor_read, total_read);
824
825 assert_eq!(buf.len(), 39 * 3);
826 assert_eq!(buf.capacity(), 256);
827 assert_eq!(
828 &buf[..39*3],
829 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"
830 );
831 }
832
833 #[test]
836 fn test_incremental() {
837 use std::io::{Seek, SeekFrom};
838
839 let mut input = std::fs::File::open("src/lib.rs").unwrap();
842
843 let mut total_read = 0;
844
845 let mut buf = [MaybeUninit::<u8>::zeroed(); 256];
846 let mut cursor = Cursor::new(&mut buf);
847 input.seek(SeekFrom::End(-39)).unwrap();
848 let nread = read(&input, &mut cursor).unwrap();
849 total_read += nread;
850 assert_eq!(cursor.remaining(), 256 - 39);
851 input.seek(SeekFrom::End(-39)).unwrap();
852 let nread = read(&input, &mut cursor).unwrap();
853 total_read += nread;
854 assert_eq!(cursor.remaining(), 256 - 39 * 2);
855 input.seek(SeekFrom::End(-39)).unwrap();
856 let nread = read(&input, &mut cursor).unwrap();
857 total_read += nread;
858 assert_eq!(cursor.remaining(), 256 - 39 * 3);
859
860 assert_eq!(total_read, 39 * 3);
861
862 let (init, uninit) = cursor.finish();
863 assert_eq!(init.len(), total_read);
864 assert_eq!(uninit.len(), 256 - total_read);
865
866 assert_eq!(
867 init,
868 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"
869 );
870 }
871
872 fn read<B: Buffer<u8>>(input: &std::fs::File, mut b: B) -> std::io::Result<B::Output> {
873 use std::os::fd::AsRawFd;
874 let ptr = b.buffer_ptr();
875 let len = b.buffer_len();
876 let n = unsafe { libc::read(input.as_raw_fd(), ptr.cast(), len) };
877 if let Ok(n) = usize::try_from(n) {
878 unsafe { Ok(b.assume_init(n)) }
879 } else {
880 Err(std::io::Error::last_os_error())
881 }
882 }
883}
884
885