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::vec::Vec;
10use core::marker::PhantomData;
11use core::mem::MaybeUninit;
12use core::slice;
13
14pub trait Buffer<T> where Self: Sized {
122 type Output;
124
125 fn buffer_len(&self) -> usize;
127
128 fn parts_mut(&mut self) -> (*mut T, usize);
133
134 unsafe fn assume_init(self, len: usize) -> Self::Output;
140
141 fn cursor(self) -> Cursor<T, Self> {
149 Cursor::new(self)
150 }
151}
152
153impl<T> Buffer<T> for &mut [T] {
154 type Output = usize;
155
156 #[inline]
157 fn buffer_len(&self) -> usize {
158 self.len()
159 }
160
161 #[inline]
162 fn parts_mut(&mut self) -> (*mut T, usize) {
163 (self.as_mut_ptr(), self.len())
164 }
165
166 #[inline]
167 unsafe fn assume_init(self, len: usize) -> Self::Output {
168 len
169 }
170}
171
172impl<T, const N: usize> Buffer<T> for &mut [T; N] {
173 type Output = usize;
174
175 #[inline]
176 fn buffer_len(&self) -> usize {
177 N
178 }
179
180 #[inline]
181 fn parts_mut(&mut self) -> (*mut T, usize) {
182 (self.as_mut_ptr(), N)
183 }
184
185 #[inline]
186 unsafe fn assume_init(self, len: usize) -> Self::Output {
187 len
188 }
189}
190
191#[cfg(feature = "alloc")]
195impl<T> Buffer<T> for &mut Vec<T> {
196 type Output = usize;
197
198 #[inline]
199 fn buffer_len(&self) -> usize {
200 self.len()
201 }
202
203 #[inline]
204 fn parts_mut(&mut self) -> (*mut T, usize) {
205 (self.as_mut_ptr(), self.len())
206 }
207
208 #[inline]
209 unsafe fn assume_init(self, len: usize) -> Self::Output {
210 len
211 }
212}
213
214impl<'a, T> Buffer<T> for &'a mut [MaybeUninit<T>] {
215 type Output = (&'a mut [T], &'a mut [MaybeUninit<T>]);
216
217 #[inline]
218 fn buffer_len(&self) -> usize {
219 self.len()
220 }
221
222 #[inline]
223 fn parts_mut(&mut self) -> (*mut T, usize) {
224 (self.as_mut_ptr().cast(), self.len())
225 }
226
227 #[inline]
228 unsafe fn assume_init(self, len: usize) -> Self::Output {
229 unsafe {
230 let (init, uninit) = self.split_at_mut(len);
231
232 let init = slice::from_raw_parts_mut(init.as_mut_ptr().cast::<T>(), init.len());
236
237 (init, uninit)
238 }
239 }
240}
241
242impl<'a, T, const N: usize> Buffer<T> for &'a mut [MaybeUninit<T>; N] {
243 type Output = (&'a mut [T], &'a mut [MaybeUninit<T>]);
244
245 #[inline]
246 fn buffer_len(&self) -> usize {
247 self.len()
248 }
249
250 #[inline]
251 fn parts_mut(&mut self) -> (*mut T, usize) {
252 (self.as_mut_ptr().cast(), self.len())
253 }
254
255 #[inline]
256 unsafe fn assume_init(self, len: usize) -> Self::Output {
257 unsafe {
258 let (init, uninit) = self.split_at_mut(len);
259
260 let init = slice::from_raw_parts_mut(init.as_mut_ptr().cast::<T>(), init.len());
262
263 (init, uninit)
264 }
265 }
266}
267
268#[cfg(feature = "alloc")]
269impl<'a, T> Buffer<T> for &'a mut Vec<MaybeUninit<T>> {
270 type Output = (&'a mut [T], &'a mut [MaybeUninit<T>]);
271
272 #[inline]
273 fn buffer_len(&self) -> usize {
274 self.len()
275 }
276
277 #[inline]
278 fn parts_mut(&mut self) -> (*mut T, usize) {
279 (self.as_mut_ptr().cast(), self.len())
280 }
281
282 #[inline]
283 unsafe fn assume_init(self, len: usize) -> Self::Output {
284 unsafe {
285 let (init, uninit) = self.split_at_mut(len);
286
287 let init = slice::from_raw_parts_mut(init.as_mut_ptr().cast::<T>(), init.len());
289
290 (init, uninit)
291 }
292 }
293}
294
295#[cfg(feature = "alloc")]
303#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
304pub struct SpareCapacity<'a, T>(&'a mut Vec<T>);
305
306#[cfg(feature = "alloc")]
336#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
337pub fn spare_capacity<'a, T>(v: &'a mut Vec<T>) -> SpareCapacity<'a, T> {
338 debug_assert_ne!(
339 v.capacity(),
340 0,
341 "`extend` uses spare capacity, and never allocates new memory, so the `Vec` passed to it \
342 should have some spare capacity."
343 );
344
345 SpareCapacity(v)
346}
347
348#[cfg(feature = "alloc")]
349impl<'a, T> Buffer<T> for SpareCapacity<'a, T> {
350 type Output = usize;
354
355 #[inline]
356 fn buffer_len(&self) -> usize {
357 self.0.capacity() - self.0.len()
358 }
359
360 #[inline]
361 fn parts_mut(&mut self) -> (*mut T, usize) {
362 let spare = self.0.spare_capacity_mut();
363 (spare.as_mut_ptr().cast(), spare.len())
364 }
365
366 #[inline]
367 unsafe fn assume_init(self, len: usize) -> Self::Output {
368 unsafe {
369 self.0.set_len(self.0.len() + len);
371 len
372 }
373 }
374}
375
376pub struct Cursor<T, B: Buffer<T>> {
390 pos: usize,
391 b: B,
392 phantom: PhantomData<T>,
393}
394
395impl<T, B: Buffer<T>> Cursor<T, B> {
396 pub fn new(b: B) -> Self {
398 Self {
399 pos: 0,
400 b,
401 phantom: PhantomData,
402 }
403 }
404
405 pub fn remaining(&self) -> usize {
407 self.b.buffer_len() - self.pos
408 }
409
410 pub fn write(&mut self, t: T) {
416 let (ptr, len) = self.b.parts_mut();
417
418 assert!(self.pos < len);
419
420 unsafe {
423 ptr.add(self.pos).write(t);
424 }
425
426 self.pos += 1;
428 }
429
430 pub fn write_slice(&mut self, t: &[T])
437 where
438 T: Copy,
439 {
440 let (ptr, len) = self.b.parts_mut();
441
442 assert!(len - self.pos >= t.len());
443
444 unsafe {
448 core::ptr::copy_nonoverlapping(t.as_ptr(), ptr, t.len());
449 }
450
451 self.pos += t.len();
453 }
454
455 pub fn finish(self) -> B::Output {
457 unsafe { self.b.assume_init(self.pos) }
459 }
460}
461
462impl<T, B: Buffer<T>> Buffer<T> for &mut Cursor<T, B> {
463 type Output = usize;
467
468 #[inline]
469 fn buffer_len(&self) -> usize {
470 self.remaining()
471 }
472
473 #[inline]
474 fn parts_mut(&mut self) -> (*mut T, usize) {
475 let parts = self.b.parts_mut();
476 unsafe { (parts.0.add(self.pos), parts.1 - self.pos) }
479 }
480
481 #[inline]
482 unsafe fn assume_init(self, len: usize) -> Self::Output {
483 self.pos += len;
485 len
486 }
487}
488
489#[cfg(test)]
490mod tests {
491 #[allow(unused_imports)]
492 use super::*;
493
494 #[cfg(not(windows))]
496 #[test]
497 fn test_compilation() {
498 use core::mem::MaybeUninit;
499
500 fn read<B: Buffer<u8>>(b: B) -> Result<B::Output, ()> {
501 Ok(b.cursor().finish())
502 }
503
504 let mut buf = vec![0_u8; 3];
505 buf.reserve(32);
506 let _x: usize = read(spare_capacity(&mut buf)).unwrap();
507 let _x: (&mut [u8], &mut [MaybeUninit<u8>]) = read(buf.spare_capacity_mut()).unwrap();
508 let _x: usize = read(&mut buf).unwrap();
509 let _x: usize = read(&mut *buf).unwrap();
510 let _x: usize = read(&mut buf[..]).unwrap();
511 let _x: usize = read(&mut (*buf)[..]).unwrap();
512
513 let mut buf = [0, 0, 0];
514 let _x: usize = read(&mut buf).unwrap();
515 let _x: usize = read(&mut buf[..]).unwrap();
516
517 let mut buf = [
518 MaybeUninit::uninit(),
519 MaybeUninit::uninit(),
520 MaybeUninit::uninit(),
521 ];
522 let _x: (&mut [u8], &mut [MaybeUninit<u8>]) = read(&mut buf).unwrap();
523 let _x: (&mut [u8], &mut [MaybeUninit<u8>]) = read(&mut buf[..]).unwrap();
524
525 let mut buf = vec![
526 MaybeUninit::uninit(),
527 MaybeUninit::uninit(),
528 MaybeUninit::uninit(),
529 ];
530 let _x: (&mut [u8], &mut [MaybeUninit<u8>]) = read(&mut buf).unwrap();
531 let _x: (&mut [u8], &mut [MaybeUninit<u8>]) = read(&mut buf[..]).unwrap();
532
533 let mut buf = Cursor::new(&mut buf);
534 let _x: usize = read(&mut buf).unwrap();
535 let _x: (&mut [u8], &mut [MaybeUninit<u8>]) = buf.finish();
536 }
537
538 #[cfg(not(windows))]
540 #[test]
541 fn test_slice() {
542 use std::io::{Seek, SeekFrom};
543
544 let mut input = std::fs::File::open("src/lib.rs").unwrap();
547
548 let mut buf = [0_u8; 64];
549 let nread = read(&input, &mut buf).unwrap();
550 assert_eq!(nread, buf.len());
551 assert_eq!(&buf[..39], b"#![doc = include_str!(\"../README.md\")]\n");
552 input.seek(SeekFrom::End(-1)).unwrap();
553 let nread = read(&input, &mut buf).unwrap();
554 assert_eq!(nread, 1);
555 assert_eq!(buf[0], b'\n');
556 input.seek(SeekFrom::End(0)).unwrap();
557 let nread = read(&input, &mut buf).unwrap();
558 assert_eq!(nread, 0);
559 }
560
561 #[cfg(not(windows))]
563 #[test]
564 fn test_slice_uninit() {
565 use core::mem::MaybeUninit;
566 use std::io::{Seek, SeekFrom};
567
568 let mut input = std::fs::File::open("src/lib.rs").unwrap();
571
572 let mut buf = [MaybeUninit::<u8>::uninit(); 64];
573 let (init, uninit) = read(&input, &mut buf).unwrap();
574 assert_eq!(uninit.len(), 0);
575 assert_eq!(&init[..39], b"#![doc = include_str!(\"../README.md\")]\n");
576 assert_eq!(init.len(), buf.len());
577 assert_eq!(
578 unsafe { core::mem::transmute::<&mut [MaybeUninit<u8>], &mut [u8]>(&mut buf[..39]) },
579 b"#![doc = include_str!(\"../README.md\")]\n"
580 );
581 input.seek(SeekFrom::End(-1)).unwrap();
582 let (init, uninit) = read(&input, &mut buf).unwrap();
583 assert_eq!(init.len(), 1);
584 assert_eq!(init[0], b'\n');
585 assert_eq!(uninit.len(), buf.len() - 1);
586 input.seek(SeekFrom::End(0)).unwrap();
587 let (init, uninit) = read(&input, &mut buf).unwrap();
588 assert_eq!(init.len(), 0);
589 assert_eq!(uninit.len(), buf.len());
590 }
591
592 #[cfg(not(windows))]
594 #[test]
595 fn test_spare_capacity() {
596 use std::io::{Seek, SeekFrom};
597
598 let mut input = std::fs::File::open("src/lib.rs").unwrap();
601
602 let mut buf = Vec::with_capacity(64);
603 let nread = read(&input, spare_capacity(&mut buf)).unwrap();
604 assert_eq!(nread, buf.capacity());
605 assert_eq!(nread, buf.len());
606 assert_eq!(&buf[..39], b"#![doc = include_str!(\"../README.md\")]\n");
607 buf.clear();
608 input.seek(SeekFrom::End(-1)).unwrap();
609 let nread = read(&input, spare_capacity(&mut buf)).unwrap();
610 assert_eq!(nread, 1);
611 assert_eq!(buf.len(), 1);
612 assert_eq!(buf[0], b'\n');
613 buf.clear();
614 input.seek(SeekFrom::End(0)).unwrap();
615 let nread = read(&input, spare_capacity(&mut buf)).unwrap();
616 assert_eq!(nread, 0);
617 assert!(buf.is_empty());
618 }
619
620 #[test]
622 fn test_cursor_as_buffer() {
623 use std::io::{Seek, SeekFrom};
624
625 let mut input = std::fs::File::open("src/lib.rs").unwrap();
628
629 let mut total_read = 0;
630
631 let mut buf = Vec::with_capacity(256);
632 let mut cursor = Cursor::new(spare_capacity(&mut buf));
633 input.seek(SeekFrom::End(-39)).unwrap();
634 let nread = read(&input, &mut cursor).unwrap();
635 total_read += nread;
636 assert_eq!(cursor.remaining(), 256 - 39);
637 input.seek(SeekFrom::End(-39)).unwrap();
638 let nread = read(&input, &mut cursor).unwrap();
639 total_read += nread;
640 assert_eq!(cursor.remaining(), 256 - 39 * 2);
641 input.seek(SeekFrom::End(-39)).unwrap();
642 let nread = read(&input, &mut cursor).unwrap();
643 total_read += nread;
644 assert_eq!(cursor.remaining(), 256 - 39 * 3);
645
646 assert_eq!(total_read, 39 * 3);
647
648 let cursor_read = cursor.finish();
649 assert_eq!(cursor_read, total_read);
650
651 assert_eq!(buf.len(), 39 * 3);
652 assert_eq!(buf.capacity(), 256);
653 assert_eq!(
654 buf,
655 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"
656 );
657 }
658
659 #[test]
661 fn test_nesting() {
662 use std::io::{Seek, SeekFrom};
663
664 let mut input = std::fs::File::open("src/lib.rs").unwrap();
667
668 let mut total_read = 0;
669
670 let mut buf = Vec::with_capacity(256);
671 let mut cursor = Cursor::new(spare_capacity(&mut buf));
672 input.seek(SeekFrom::End(-39)).unwrap();
673 let nread = read(&input, &mut cursor).unwrap();
674 total_read += nread;
675 assert_eq!(cursor.remaining(), 256 - 39);
676 input.seek(SeekFrom::End(-39)).unwrap();
677 let mut nested_cursor = Cursor::new(&mut cursor);
678 let nested_nread = read(&input, &mut nested_cursor).unwrap();
679 assert_eq!(nested_nread, 39);
680 assert_eq!(nested_cursor.remaining(), 256 - 39 * 2);
681 input.seek(SeekFrom::End(-39)).unwrap();
682 let mut nested_nested_cursor = Cursor::new(&mut nested_cursor);
683 let nested_nested_nread = read(&input, &mut nested_nested_cursor).unwrap();
684 assert_eq!(nested_nested_nread, 39);
685 assert_eq!(nested_nested_cursor.remaining(), 256 - 39 * 3);
686 let inner_nread = nested_nested_cursor.finish();
687 assert_eq!(inner_nread, 39);
688 assert_eq!(nested_cursor.remaining(), 256 - 39 * 3);
689 let nread = nested_cursor.finish();
690 total_read += nread;
691
692 assert_eq!(total_read, 39 * 3);
693 assert_eq!(cursor.remaining(), 256 - 39 * 3);
694
695 let cursor_read = cursor.finish();
696 assert_eq!(cursor_read, total_read);
697
698 assert_eq!(buf.len(), 39 * 3);
699 assert_eq!(buf.capacity(), 256);
700 assert_eq!(
701 &buf[..39*3],
702 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"
703 );
704 }
705
706 #[test]
709 fn test_incremental() {
710 use std::io::{Seek, SeekFrom};
711
712 let mut input = std::fs::File::open("src/lib.rs").unwrap();
715
716 let mut total_read = 0;
717
718 let mut buf = [MaybeUninit::<u8>::zeroed(); 256];
719 let mut cursor = Cursor::new(&mut buf);
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);
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 * 2);
728 input.seek(SeekFrom::End(-39)).unwrap();
729 let nread = read(&input, &mut cursor).unwrap();
730 total_read += nread;
731 assert_eq!(cursor.remaining(), 256 - 39 * 3);
732
733 assert_eq!(total_read, 39 * 3);
734
735 let (init, uninit) = cursor.finish();
736 assert_eq!(init.len(), total_read);
737 assert_eq!(uninit.len(), 256 - total_read);
738
739 assert_eq!(
740 init,
741 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"
742 );
743 }
744
745 fn read<B: Buffer<u8>>(input: &std::fs::File, mut b: B) -> std::io::Result<B::Output> {
746 use std::os::fd::AsRawFd;
747 let parts = b.parts_mut();
748 let n = unsafe { libc::read(input.as_raw_fd(), parts.0.cast(), parts.1) };
749 if n < 0 {
750 Err(std::io::Error::last_os_error())
751 } else {
752 unsafe { Ok(b.assume_init(n as usize)) }
753 }
754 }
755}
756
757