1#![doc = include_str!("../README.md")]
2#![cfg_attr(not(test), 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>
124where
125 Self: Sized,
126{
127 type Output;
129
130 fn buffer_len(&self) -> usize;
132
133 fn parts_mut(&mut self) -> (*mut T, usize);
140
141 unsafe fn assume_init(self, len: usize) -> Self::Output;
147
148 fn cursor(self) -> Cursor<T, Self> {
158 Cursor::new(self)
159 }
160}
161
162impl<T> Buffer<T> for &mut [T] {
163 type Output = usize;
164
165 #[inline]
166 fn buffer_len(&self) -> usize {
167 self.len()
168 }
169
170 #[inline]
171 fn parts_mut(&mut self) -> (*mut T, usize) {
172 (self.as_mut_ptr(), self.len())
173 }
174
175 #[inline]
176 unsafe fn assume_init(self, len: usize) -> Self::Output {
177 len
178 }
179}
180
181impl<T, const N: usize> Buffer<T> for &mut [T; N] {
182 type Output = usize;
183
184 #[inline]
185 fn buffer_len(&self) -> usize {
186 N
187 }
188
189 #[inline]
190 fn parts_mut(&mut self) -> (*mut T, usize) {
191 (self.as_mut_ptr(), N)
192 }
193
194 #[inline]
195 unsafe fn assume_init(self, len: usize) -> Self::Output {
196 len
197 }
198}
199
200#[cfg(feature = "alloc")]
204impl<T> Buffer<T> for &mut Vec<T> {
205 type Output = usize;
206
207 #[inline]
208 fn buffer_len(&self) -> usize {
209 self.len()
210 }
211
212 #[inline]
213 fn parts_mut(&mut self) -> (*mut T, usize) {
214 (self.as_mut_ptr(), self.len())
215 }
216
217 #[inline]
218 unsafe fn assume_init(self, len: usize) -> Self::Output {
219 len
220 }
221}
222
223#[cfg(feature = "alloc")]
227impl<T> Buffer<T> for &mut Box<[T]> {
228 type Output = usize;
229
230 #[inline]
231 fn buffer_len(&self) -> usize {
232 self.len()
233 }
234
235 #[inline]
236 fn parts_mut(&mut self) -> (*mut T, usize) {
237 (self.as_mut_ptr(), self.len())
238 }
239
240 #[inline]
241 unsafe fn assume_init(self, len: usize) -> Self::Output {
242 len
243 }
244}
245
246impl<'a, T> Buffer<T> for &'a mut [MaybeUninit<T>] {
247 type Output = (&'a mut [T], &'a mut [MaybeUninit<T>]);
248
249 #[inline]
250 fn buffer_len(&self) -> usize {
251 self.len()
252 }
253
254 #[inline]
255 fn parts_mut(&mut self) -> (*mut T, usize) {
256 (self.as_mut_ptr().cast(), self.len())
257 }
258
259 #[inline]
260 unsafe fn assume_init(self, len: usize) -> Self::Output {
261 unsafe {
264 let (init, uninit) = self.split_at_mut(len);
265
266 let init = slice::from_raw_parts_mut(init.as_mut_ptr().cast::<T>(), init.len());
268
269 (init, uninit)
270 }
271 }
272}
273
274impl<'a, T, const N: usize> Buffer<T> for &'a mut [MaybeUninit<T>; N] {
275 type Output = (&'a mut [T], &'a mut [MaybeUninit<T>]);
276
277 #[inline]
278 fn buffer_len(&self) -> usize {
279 N
280 }
281
282 #[inline]
283 fn parts_mut(&mut self) -> (*mut T, usize) {
284 (self.as_mut_ptr().cast(), N)
285 }
286
287 #[inline]
288 unsafe fn assume_init(self, len: usize) -> Self::Output {
289 unsafe {
292 let (init, uninit) = self.split_at_mut(len);
293
294 let init = slice::from_raw_parts_mut(init.as_mut_ptr().cast::<T>(), init.len());
296
297 (init, uninit)
298 }
299 }
300}
301
302#[cfg(feature = "alloc")]
303impl<'a, T> Buffer<T> for &'a mut Vec<MaybeUninit<T>> {
304 type Output = (&'a mut [T], &'a mut [MaybeUninit<T>]);
305
306 #[inline]
307 fn buffer_len(&self) -> usize {
308 self.len()
309 }
310
311 #[inline]
312 fn parts_mut(&mut self) -> (*mut T, usize) {
313 (self.as_mut_ptr().cast(), self.len())
314 }
315
316 #[inline]
317 unsafe fn assume_init(self, len: usize) -> Self::Output {
318 unsafe {
321 let (init, uninit) = self.split_at_mut(len);
322
323 let init = slice::from_raw_parts_mut(init.as_mut_ptr().cast::<T>(), init.len());
325
326 (init, uninit)
327 }
328 }
329}
330
331#[cfg(feature = "alloc")]
332impl<'a, T> Buffer<T> for &'a mut Box<[MaybeUninit<T>]> {
333 type Output = (&'a mut [T], &'a mut [MaybeUninit<T>]);
334
335 #[inline]
336 fn buffer_len(&self) -> usize {
337 self.len()
338 }
339
340 #[inline]
341 fn parts_mut(&mut self) -> (*mut T, usize) {
342 (self.as_mut_ptr().cast(), self.len())
343 }
344
345 #[inline]
346 unsafe fn assume_init(self, len: usize) -> Self::Output {
347 unsafe {
350 let (init, uninit) = self.split_at_mut(len);
351
352 let init = slice::from_raw_parts_mut(init.as_mut_ptr().cast::<T>(), init.len());
354
355 (init, uninit)
356 }
357 }
358}
359
360#[cfg(feature = "alloc")]
368#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
369pub struct SpareCapacity<'a, T>(&'a mut Vec<T>);
370
371#[cfg(feature = "alloc")]
401#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
402pub fn spare_capacity<'a, T>(v: &'a mut Vec<T>) -> SpareCapacity<'a, T> {
403 debug_assert_ne!(
404 v.capacity(),
405 0,
406 "`extend` uses spare capacity, and never allocates new memory, so the `Vec` passed to it \
407 should have some spare capacity."
408 );
409
410 SpareCapacity(v)
411}
412
413#[cfg(feature = "alloc")]
414impl<'a, T> Buffer<T> for SpareCapacity<'a, T> {
415 type Output = usize;
421
422 #[inline]
423 fn buffer_len(&self) -> usize {
424 self.0.capacity() - self.0.len()
425 }
426
427 #[inline]
428 fn parts_mut(&mut self) -> (*mut T, usize) {
429 let spare = self.0.spare_capacity_mut();
430 (spare.as_mut_ptr().cast(), spare.len())
431 }
432
433 #[inline]
434 unsafe fn assume_init(self, len: usize) -> Self::Output {
435 unsafe {
438 self.0.set_len(self.0.len() + len);
439 }
440 len
441 }
442}
443
444pub struct Cursor<T, B: Buffer<T>> {
458 pos: usize,
459 b: B,
460 phantom: PhantomData<T>,
461}
462
463impl<T, B: Buffer<T>> Cursor<T, B> {
464 pub fn new(b: B) -> Self {
466 Self {
467 pos: 0,
468 b,
469 phantom: PhantomData,
470 }
471 }
472
473 pub fn remaining(&self) -> usize {
475 self.b.buffer_len() - self.pos
476 }
477
478 pub fn write(&mut self, t: T) {
484 let (ptr, len) = self.b.parts_mut();
485
486 assert!(self.pos < len);
487
488 unsafe {
491 ptr.add(self.pos).write(t);
492 }
493
494 self.pos += 1;
496 }
497
498 pub fn write_slice(&mut self, t: &[T])
505 where
506 T: Copy,
507 {
508 let (ptr, len) = self.b.parts_mut();
509
510 assert!(len - self.pos >= t.len());
511
512 unsafe {
516 core::ptr::copy_nonoverlapping(t.as_ptr(), ptr, t.len());
517 }
518
519 self.pos += t.len();
521 }
522
523 pub fn finish(self) -> B::Output {
525 unsafe { self.b.assume_init(self.pos) }
528 }
529}
530
531impl<T, B: Buffer<T>> Buffer<T> for &mut Cursor<T, B> {
532 type Output = usize;
533
534 #[inline]
535 fn buffer_len(&self) -> usize {
536 self.remaining()
537 }
538
539 #[inline]
540 fn parts_mut(&mut self) -> (*mut T, usize) {
541 let parts = self.b.parts_mut();
542 unsafe { (parts.0.add(self.pos), parts.1 - self.pos) }
545 }
546
547 #[inline]
548 unsafe fn assume_init(self, len: usize) -> Self::Output {
549 self.pos += len;
551 len
552 }
553}
554
555#[cfg(test)]
556mod tests {
557 #[allow(unused_imports)]
558 use super::*;
559
560 #[cfg(not(windows))]
562 #[test]
563 fn test_compilation() {
564 use core::mem::MaybeUninit;
565
566 fn read<B: Buffer<u8>>(b: B) -> Result<B::Output, ()> {
567 Ok(b.cursor().finish())
568 }
569
570 let mut buf = vec![0_u8; 3];
571 buf.reserve(32);
572 let _x: usize = read(spare_capacity(&mut buf)).unwrap();
573 let _x: (&mut [u8], &mut [MaybeUninit<u8>]) = read(buf.spare_capacity_mut()).unwrap();
574 let _x: usize = read(&mut buf).unwrap();
575 let _x: usize = read(&mut *buf).unwrap();
576 let _x: usize = read(&mut buf[..]).unwrap();
577 let _x: usize = read(&mut (*buf)[..]).unwrap();
578
579 let mut buf = [0, 0, 0];
580 let _x: usize = read(&mut buf).unwrap();
581 let _x: usize = read(&mut buf[..]).unwrap();
582
583 let mut buf = vec![0, 0, 0];
584 let _x: usize = read(&mut buf).unwrap();
585 let _x: usize = read(&mut buf[..]).unwrap();
586
587 let mut buf = vec![0, 0, 0].into_boxed_slice();
588 let _x: usize = read(&mut buf).unwrap();
589 let _x: usize = read(&mut buf[..]).unwrap();
590
591 let mut buf = [
592 MaybeUninit::uninit(),
593 MaybeUninit::uninit(),
594 MaybeUninit::uninit(),
595 ];
596 let _x: (&mut [u8], &mut [MaybeUninit<u8>]) = read(&mut buf).unwrap();
597 let _x: (&mut [u8], &mut [MaybeUninit<u8>]) = read(&mut buf[..]).unwrap();
598
599 let mut buf = vec![
600 MaybeUninit::uninit(),
601 MaybeUninit::uninit(),
602 MaybeUninit::uninit(),
603 ];
604 let _x: (&mut [u8], &mut [MaybeUninit<u8>]) = read(&mut buf).unwrap();
605 let _x: (&mut [u8], &mut [MaybeUninit<u8>]) = read(&mut buf[..]).unwrap();
606
607 let mut buf = vec![
608 MaybeUninit::uninit(),
609 MaybeUninit::uninit(),
610 MaybeUninit::uninit(),
611 ]
612 .into_boxed_slice();
613 let _x: (&mut [u8], &mut [MaybeUninit<u8>]) = read(&mut buf).unwrap();
614 let _x: (&mut [u8], &mut [MaybeUninit<u8>]) = read(&mut buf[..]).unwrap();
615
616 let mut buf = Cursor::new(&mut buf);
617 let _x: usize = read(&mut buf).unwrap();
618 let _x: (&mut [u8], &mut [MaybeUninit<u8>]) = buf.finish();
619 }
620
621 #[cfg(not(windows))]
623 #[test]
624 fn test_slice() {
625 use std::io::{Seek, SeekFrom};
626
627 let mut input = std::fs::File::open("src/lib.rs").unwrap();
630
631 let mut buf = [0_u8; 64];
632 let nread = read(&input, &mut buf).unwrap();
633 assert_eq!(nread, buf.len());
634 assert_eq!(&buf[..39], b"#![doc = include_str!(\"../README.md\")]\n");
635 input.seek(SeekFrom::End(-1)).unwrap();
636 let nread = read(&input, &mut buf).unwrap();
637 assert_eq!(nread, 1);
638 assert_eq!(buf[0], b'\n');
639 input.seek(SeekFrom::End(0)).unwrap();
640 let nread = read(&input, &mut buf).unwrap();
641 assert_eq!(nread, 0);
642 }
643
644 #[cfg(not(windows))]
646 #[test]
647 fn test_slice_uninit() {
648 use core::mem::MaybeUninit;
649 use std::io::{Seek, SeekFrom};
650
651 let mut input = std::fs::File::open("src/lib.rs").unwrap();
654
655 let mut buf = [MaybeUninit::<u8>::uninit(); 64];
656 let (init, uninit) = read(&input, &mut buf).unwrap();
657 assert_eq!(uninit.len(), 0);
658 assert_eq!(&init[..39], b"#![doc = include_str!(\"../README.md\")]\n");
659 assert_eq!(init.len(), buf.len());
660 assert_eq!(
661 unsafe { core::mem::transmute::<&mut [MaybeUninit<u8>], &mut [u8]>(&mut buf[..39]) },
662 b"#![doc = include_str!(\"../README.md\")]\n"
663 );
664 input.seek(SeekFrom::End(-1)).unwrap();
665 let (init, uninit) = read(&input, &mut buf).unwrap();
666 assert_eq!(init.len(), 1);
667 assert_eq!(init[0], b'\n');
668 assert_eq!(uninit.len(), buf.len() - 1);
669 input.seek(SeekFrom::End(0)).unwrap();
670 let (init, uninit) = read(&input, &mut buf).unwrap();
671 assert_eq!(init.len(), 0);
672 assert_eq!(uninit.len(), buf.len());
673 }
674
675 #[cfg(not(windows))]
677 #[test]
678 fn test_spare_capacity() {
679 use std::io::{Seek, SeekFrom};
680
681 let mut input = std::fs::File::open("src/lib.rs").unwrap();
684
685 let mut buf = Vec::with_capacity(64);
686 let nread = read(&input, spare_capacity(&mut buf)).unwrap();
687 assert_eq!(nread, buf.capacity());
688 assert_eq!(nread, buf.len());
689 assert_eq!(&buf[..39], b"#![doc = include_str!(\"../README.md\")]\n");
690 buf.clear();
691 input.seek(SeekFrom::End(-1)).unwrap();
692 let nread = read(&input, spare_capacity(&mut buf)).unwrap();
693 assert_eq!(nread, 1);
694 assert_eq!(buf.len(), 1);
695 assert_eq!(buf[0], b'\n');
696 buf.clear();
697 input.seek(SeekFrom::End(0)).unwrap();
698 let nread = read(&input, spare_capacity(&mut buf)).unwrap();
699 assert_eq!(nread, 0);
700 assert!(buf.is_empty());
701 }
702
703 #[test]
705 fn test_cursor_as_buffer() {
706 use std::io::{Seek, SeekFrom};
707
708 let mut input = std::fs::File::open("src/lib.rs").unwrap();
711
712 let mut total_read = 0;
713
714 let mut buf = Vec::with_capacity(256);
715 let mut cursor = Cursor::new(spare_capacity(&mut buf));
716 input.seek(SeekFrom::End(-39)).unwrap();
717 let nread = read(&input, &mut cursor).unwrap();
718 total_read += nread;
719 assert_eq!(cursor.remaining(), 256 - 39);
720 input.seek(SeekFrom::End(-39)).unwrap();
721 let nread = read(&input, &mut cursor).unwrap();
722 total_read += nread;
723 assert_eq!(cursor.remaining(), 256 - 39 * 2);
724 input.seek(SeekFrom::End(-39)).unwrap();
725 let nread = read(&input, &mut cursor).unwrap();
726 total_read += nread;
727 assert_eq!(cursor.remaining(), 256 - 39 * 3);
728
729 assert_eq!(total_read, 39 * 3);
730
731 let cursor_read = cursor.finish();
732 assert_eq!(cursor_read, total_read);
733
734 assert_eq!(buf.len(), 39 * 3);
735 assert_eq!(buf.capacity(), 256);
736 assert_eq!(
737 buf,
738 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"
739 );
740 }
741
742 #[test]
744 fn test_nesting() {
745 use std::io::{Seek, SeekFrom};
746
747 let mut input = std::fs::File::open("src/lib.rs").unwrap();
750
751 let mut total_read = 0;
752
753 let mut buf = Vec::with_capacity(256);
754 let mut cursor = Cursor::new(spare_capacity(&mut buf));
755 input.seek(SeekFrom::End(-39)).unwrap();
756 let nread = read(&input, &mut cursor).unwrap();
757 total_read += nread;
758 assert_eq!(cursor.remaining(), 256 - 39);
759 input.seek(SeekFrom::End(-39)).unwrap();
760 let mut nested_cursor = Cursor::new(&mut cursor);
761 let nested_nread = read(&input, &mut nested_cursor).unwrap();
762 assert_eq!(nested_nread, 39);
763 assert_eq!(nested_cursor.remaining(), 256 - 39 * 2);
764 input.seek(SeekFrom::End(-39)).unwrap();
765 let mut nested_nested_cursor = Cursor::new(&mut nested_cursor);
766 let nested_nested_nread = read(&input, &mut nested_nested_cursor).unwrap();
767 assert_eq!(nested_nested_nread, 39);
768 assert_eq!(nested_nested_cursor.remaining(), 256 - 39 * 3);
769 let inner_nread = nested_nested_cursor.finish();
770 assert_eq!(inner_nread, 39);
771 assert_eq!(nested_cursor.remaining(), 256 - 39 * 3);
772 let nread = nested_cursor.finish();
773 total_read += nread;
774
775 assert_eq!(total_read, 39 * 3);
776 assert_eq!(cursor.remaining(), 256 - 39 * 3);
777
778 let cursor_read = cursor.finish();
779 assert_eq!(cursor_read, total_read);
780
781 assert_eq!(buf.len(), 39 * 3);
782 assert_eq!(buf.capacity(), 256);
783 assert_eq!(
784 &buf[..39*3],
785 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"
786 );
787 }
788
789 #[test]
792 fn test_incremental() {
793 use std::io::{Seek, SeekFrom};
794
795 let mut input = std::fs::File::open("src/lib.rs").unwrap();
798
799 let mut total_read = 0;
800
801 let mut buf = [MaybeUninit::<u8>::zeroed(); 256];
802 let mut cursor = Cursor::new(&mut buf);
803 input.seek(SeekFrom::End(-39)).unwrap();
804 let nread = read(&input, &mut cursor).unwrap();
805 total_read += nread;
806 assert_eq!(cursor.remaining(), 256 - 39);
807 input.seek(SeekFrom::End(-39)).unwrap();
808 let nread = read(&input, &mut cursor).unwrap();
809 total_read += nread;
810 assert_eq!(cursor.remaining(), 256 - 39 * 2);
811 input.seek(SeekFrom::End(-39)).unwrap();
812 let nread = read(&input, &mut cursor).unwrap();
813 total_read += nread;
814 assert_eq!(cursor.remaining(), 256 - 39 * 3);
815
816 assert_eq!(total_read, 39 * 3);
817
818 let (init, uninit) = cursor.finish();
819 assert_eq!(init.len(), total_read);
820 assert_eq!(uninit.len(), 256 - total_read);
821
822 assert_eq!(
823 init,
824 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"
825 );
826 }
827
828 fn read<B: Buffer<u8>>(input: &std::fs::File, mut b: B) -> std::io::Result<B::Output> {
829 use std::os::fd::AsRawFd;
830 let parts = b.parts_mut();
831 let n = unsafe { libc::read(input.as_raw_fd(), parts.0.cast(), parts.1) };
832 if n < 0 {
833 Err(std::io::Error::last_os_error())
834 } else {
835 unsafe { Ok(b.assume_init(n as usize)) }
836 }
837 }
838}
839
840