buffer_trait/
lib.rs

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
14/// A memory buffer that may be uninitialized.
15///
16/// There are three types that implement the `Buffer` trait, and the type you
17/// use determines the return type of the functions that use it:
18///
19/// | If you pass a…           | You get back a… |
20/// | ------------------------ | --------------- |
21/// | `&mut [u8]`              | `usize`, indicating the number of elements initialized. |
22/// | `&mut [MaybeUninit<u8>]` | `(&mut [u8], &mut [MaybeUninit<u8>])`, holding the initialized and uninitialized subslices. |
23/// | [`SpareCapacity`]        | `usize`, indicating the number of elements initialized. And the `Vec` is extended. |
24/// | `&mut`[`Cursor<T, B>`]   | `usize`, indicating the number of elements initialized. And the `Cursor` is advanced. Be sure to call `Cursor::finish` when you're done writing to it. |
25///
26/// # Examples
27///
28/// Passing a `&mut [u8]`:
29///
30/// ```
31/// # use rustix::io::read;
32/// # fn example(fd: rustix::fd::BorrowedFd) -> rustix::io::Result<()> {
33/// let mut buf = [0_u8; 64];
34/// let nread = read(fd, &mut buf)?;
35/// // `nread` is the number of bytes read.
36/// # Ok(())
37/// # }
38/// ```
39///
40/// Passing a `&mut [MaybeUninit<u8>]`:
41///
42/// ```
43/// # use rustix::io::read;
44/// # use std::mem::MaybeUninit;
45/// # fn example(fd: rustix::fd::BorrowedFd) -> rustix::io::Result<()> {
46/// let mut buf = [MaybeUninit::<u8>::uninit(); 64];
47/// let (init, uninit) = read(fd, &mut buf)?;
48/// // `init` is a `&mut [u8]` with the initialized bytes.
49/// // `uninit` is a `&mut [MaybeUninit<u8>]` with the remaining bytes.
50/// # Ok(())
51/// # }
52/// ```
53///
54/// Passing a [`SpareCapacity`], via the [`spare_capacity`] helper function:
55///
56/// ```
57/// # use rustix::io::read;
58/// # use rustix::buffer::spare_capacity;
59/// # fn example(fd: rustix::fd::BorrowedFd) -> rustix::io::Result<()> {
60/// let mut buf = Vec::with_capacity(64);
61/// let nread = read(fd, spare_capacity(&mut buf))?;
62/// // `nread` is the number of bytes read.
63/// // Also, `buf.len()` is now `nread` elements longer than it was before.
64/// # Ok(())
65/// # }
66/// ```
67///
68/// Passing a `&mut`[`Cursor<T, B>`]:
69///
70/// ```no_run,ignore
71/// # use rustix::io::read;
72/// # fn example(fd: rustix::fd::BorrowedFd) -> rustix::io::Result<()> {
73/// let mut buf = [0_u8; 64];
74/// let mut cursor = Cursor::new(spare_capacity(&mut buf));
75/// let _nread = read(fd, &mut cursor)?;
76/// let _nread = read(fd, &mut cursor)?;
77/// let _nread = read(fd, &mut cursor)?;
78/// let total_nread = cursor.finish();
79/// // `total_nread` is the total number of bytes read.
80/// // Also, `buf.len()` is now `total_nread` elements longer than it was before.
81/// # Ok(())
82/// # }
83/// ```
84///
85/// # Guide to error messages
86///
87/// Sometimes code using `Buffer` can encounter non-obvious error messages.
88/// Here are some we've encountered, along with ways to fix them.
89///
90/// If you see errors like
91/// "cannot move out of `self` which is behind a mutable reference"
92/// and
93/// "move occurs because `x` has type `&mut [u8]`, which does not implement the `Copy` trait",
94/// replace `x` with `&mut *x`. See `error_buffer_wrapper` in
95/// examples/buffer_errors.rs.
96///
97/// If you see errors like
98/// "type annotations needed"
99/// and
100/// "cannot infer type of the type parameter `Buf` declared on the function `read`",
101/// you may need to change a `&mut []` to `&mut [0_u8; 0]`. See
102/// `error_empty_slice` in examples/buffer_errors.rs.
103///
104/// If you see errors like
105/// "the trait bound `[MaybeUninit<u8>; 1]: Buffer<u8>` is not satisfied",
106/// add a `&mut` to pass the array by reference instead of by value. See
107/// `error_array_by_value` in examples/buffer_errors.rs.
108///
109/// If you see errors like
110/// "cannot move out of `x`, a captured variable in an `FnMut` closure",
111/// try replacing `x` with `&mut *x`, or, if that doesn't work, try moving a
112/// `let` into the closure body. See `error_retry_closure` and
113/// `error_retry_indirect_closure` in examples/buffer_errors.rs.
114///
115/// If you see errors like
116/// "captured variable cannot escape `FnMut` closure body",
117/// use an explicit loop instead of `retry_on_intr`, assuming you're using
118/// that. See `error_retry_closure_uninit` in examples/buffer_errors.rs.
119///
120/// [`&mut Cursor<T, B>`]: crate::Cursor
121pub trait Buffer<T> where Self: Sized {
122    /// The type of the value returned by functions with `Buffer` arguments.
123    type Output;
124
125    /// Return the length of the underlying buffer.
126    fn buffer_len(&self) -> usize;
127
128    /// Return a raw mutable pointer to and length of the underlying buffer.
129    ///
130    /// After using this pointer and length to initialize some elements, call
131    /// `assume_init` to declare how many were initialized.
132    fn parts_mut(&mut self) -> (*mut T, usize);
133
134    /// Assert that `len` elements were written to, and provide a return value.
135    ///
136    /// # Safety
137    ///
138    /// At least the first `len` elements of the buffer must be initialized.
139    unsafe fn assume_init(self, len: usize) -> Self::Output;
140
141    /// Return a `Cursor` for safely writing to the buffer.
142    ///
143    /// Return a `Cursor`. Calling `.finish()` on the cursor returns the
144    /// `Self::Output`.
145    ///
146    /// This is an alternative to `parts_mut`/`assume_init` which allows
147    /// callers to avoid using `unsafe`.
148    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// `Vec` implements `DerefMut` to `&mut [T]`, however it doesn't get
192// auto-derefed in a `impl Buffer<u8>`, so we add this `impl` so that our users
193// don't have to add an extra `*` in these situations.
194#[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            // Convert `init` from `&mut [MaybeUninit<T>]` to `&mut [T]`.
233            //
234            // SAFETY: The user asserts that the slice is now initialized.
235            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            // SAFETY: The user asserts that the slice is now initialized.
261            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            // SAFETY: The user asserts that the slice is now initialized.
288            let init = slice::from_raw_parts_mut(init.as_mut_ptr().cast::<T>(), init.len());
289
290            (init, uninit)
291        }
292    }
293}
294
295/// A type that implements [`Buffer`] by appending to a `Vec`, up to its
296/// capacity.
297///
298/// To use this, use the [`spare_capacity`] function.
299///
300/// Because this uses the capacity, and never reallocates, the `Vec` should
301/// have some non-empty spare capacity.
302#[cfg(feature = "alloc")]
303#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
304pub struct SpareCapacity<'a, T>(&'a mut Vec<T>);
305
306/// Construct a [`SpareCapacity`], which implements [`Buffer`].
307///
308/// This wraps a `&mut Vec` and uses the spare capacity of the `Vec` as the
309/// buffer to receive data in, automatically calling `set_len` on the `Vec` to
310/// set the length to include the received elements.
311///
312/// This uses the existing capacity, and never allocates, so the `Vec` should
313/// have some non-empty spare capacity!
314///
315/// # Examples
316///
317/// ```
318/// # fn test(input: rustix::fd::BorrowedFd) -> rustix::io::Result<()> {
319/// use rustix::buffer::spare_capacity;
320/// use rustix::io::{Errno, read};
321///
322/// let mut buf = Vec::with_capacity(1024);
323/// match read(input, spare_capacity(&mut buf)) {
324///     Ok(0) => { /* end of stream */ }
325///     Ok(n) => { /* `buf` is now `n` bytes longer */ }
326///     Err(Errno::INTR) => { /* `buf` is unmodified */ }
327///     Err(e) => {
328///         return Err(e);
329///     }
330/// }
331///
332/// # Ok(())
333/// # }
334/// ```
335#[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    /// The mutated `Vec` reflects the number of bytes read. We also return
351    /// this number, and a value of 0 indicates the end of the stream has
352    /// been reached.
353    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            // We initialized `len` elements; extend the `Vec` to include them.
370            self.0.set_len(self.0.len() + len);
371            len
372        }
373    }
374}
375
376/// A cursor for safely writing into an uninitialized buffer.
377///
378/// # Examples
379///
380/// ```ignore
381/// # use buffer_trait::{Cursor, spare_capacity};
382/// let mut buf = Vec::with_capacity(256);
383/// let mut cursor = Cursor::new(spare_capacity(&mut buf));
384/// let _nread = read(&input, &mut cursor).unwrap();
385/// let _nread = read(&input, &mut cursor).unwrap();
386/// let _nread = read(&input, &mut cursor).unwrap();
387/// let total_read = cursor.finish();
388/// ```
389pub 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    /// Construct a new `Cursor`.
397    pub fn new(b: B) -> Self {
398        Self {
399            pos: 0,
400            b,
401            phantom: PhantomData,
402        }
403    }
404
405    /// Return the remaining amount of space in the buffer.
406    pub fn remaining(&self) -> usize {
407        self.b.buffer_len() - self.pos
408    }
409
410    /// Write an element to the buffer.
411    ///
412    /// # Panics
413    ///
414    /// Panics if this cursor has already reached the end of the buffer.
415    pub fn write(&mut self, t: T) {
416        let (ptr, len) = self.b.parts_mut();
417
418        assert!(self.pos < len);
419
420        // SAFETY: `Cursor::new` requires that `ptr` and `len` are valid, and we
421        // just bounds-checked `pos`.
422        unsafe {
423            ptr.add(self.pos).write(t);
424        }
425
426        // Count how many elements we've initialized.
427        self.pos += 1;
428    }
429
430    /// Write multiple elements to the buffer.
431    ///
432    /// # Panics
433    ///
434    /// Panics if this cursor is already within `t.len()` elements of the
435    /// end of the buffer.
436    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        // SAFETY: We've required that `T` implements `Copy`, bounds-checked
445        // the length, and `parts_mut()` should have given us a correct pointer
446        // and length.
447        unsafe {
448            core::ptr::copy_nonoverlapping(t.as_ptr(), ptr, t.len());
449        }
450
451        // Count how many elements we've initialized.
452        self.pos += t.len();
453    }
454
455    /// Finish writing to the buffer and return the output value.
456    pub fn finish(self) -> B::Output {
457        // SAFETY: `Cursor` ensures that exactly `pos` bytes have been written.
458        unsafe { self.b.assume_init(self.pos) }
459    }
460}
461
462impl<T, B: Buffer<T>> Buffer<T> for &mut Cursor<T, B> {
463    /// The mutated `Cursor` reflects the number of bytes read. We also return
464    /// this number, and a value of 0 indicates the end of the stream has
465    /// been reached.
466    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        // SAFETY: We ensure that `self.pos` is always within the bounds
477        // of the buffer.
478        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        // Count how many elements we've initialized.
484        self.pos += len;
485        len
486    }
487}
488
489#[cfg(test)]
490mod tests {
491    #[allow(unused_imports)]
492    use super::*;
493
494    /// Test type signatures.
495    #[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    /// Test passing a `&mut [u8]` to `read`.
539    #[cfg(not(windows))]
540    #[test]
541    fn test_slice() {
542        use std::io::{Seek, SeekFrom};
543
544        // We need to obtain input stream with contents that we can compare
545        // against, so open our own source file.
546        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    /// Test passing a `&mut [MaybeUninit<u8>]` to `read`.
562    #[cfg(not(windows))]
563    #[test]
564    fn test_slice_uninit() {
565        use core::mem::MaybeUninit;
566        use std::io::{Seek, SeekFrom};
567
568        // We need to obtain input stream with contents that we can compare
569        // against, so open our own source file.
570        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    /// Test passing a `SpareCapacity` to `read`.
593    #[cfg(not(windows))]
594    #[test]
595    fn test_spare_capacity() {
596        use std::io::{Seek, SeekFrom};
597
598        // We need to obtain input stream with contents that we can compare
599        // against, so open our own source file.
600        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 passing a `Cursor` to `read`.
621    #[test]
622    fn test_cursor_as_buffer() {
623        use std::io::{Seek, SeekFrom};
624
625        // We need to obtain input stream with contents that we can compare
626        // against, so open our own source file.
627        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 nesting `Cursor`s inside of `Cursor`s.
660    #[test]
661    fn test_nesting() {
662        use std::io::{Seek, SeekFrom};
663
664        // We need to obtain input stream with contents that we can compare
665        // against, so open our own source file.
666        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 using a `Cursor` to read into a `MaybeUninit` buffer in multiple
707    /// reads, ultimately producing a single initialized slice.
708    #[test]
709    fn test_incremental() {
710        use std::io::{Seek, SeekFrom};
711
712        // We need to obtain input stream with contents that we can compare
713        // against, so open our own source file.
714        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// The comment at the end of the file!