buffer_trait/
lib.rs

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
16/// A memory buffer that may be uninitialized.
17///
18/// When a function has a `Buffer` argument, the type of the argument
19/// determines the return type of the function:
20///
21/// | If you pass a…          | You get back a… |
22/// | ----------------------- | --------------- |
23/// | `&mut [T]`              | `usize`, indicating the number of elements initialized. |
24/// | `&mut [MaybeUninit<T>]` | `(&mut [T], &mut [MaybeUninit<T>])`, holding the initialized and uninitialized subslices. |
25/// | [`SpareCapacity`]       | `usize`, indicating the number of elements initialized. And the `Vec` is extended. |
26/// | `&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. |
27///
28/// # Examples
29///
30/// Passing a `&mut [T]`:
31///
32/// ```
33/// # use rustix::io::read;
34/// # fn example(fd: rustix::fd::BorrowedFd) -> rustix::io::Result<()> {
35/// let mut buf = [0_u8; 64];
36/// let nread = read(fd, &mut buf)?;
37/// // `nread` is the number of bytes read.
38/// # Ok(())
39/// # }
40/// ```
41///
42/// Passing a `&mut [MaybeUninit<T>]`:
43///
44/// ```
45/// # use rustix::io::read;
46/// # use std::mem::MaybeUninit;
47/// # fn example(fd: rustix::fd::BorrowedFd) -> rustix::io::Result<()> {
48/// let mut buf = [MaybeUninit::<u8>::uninit(); 64];
49/// let (init, uninit) = read(fd, &mut buf)?;
50/// // `init` is a `&mut [u8]` with the initialized bytes.
51/// // `uninit` is a `&mut [MaybeUninit<u8>]` with the remaining bytes.
52/// # Ok(())
53/// # }
54/// ```
55///
56/// Passing a [`SpareCapacity`], via the [`spare_capacity`] helper function:
57///
58/// ```
59/// # use rustix::io::read;
60/// # use rustix::buffer::spare_capacity;
61/// # fn example(fd: rustix::fd::BorrowedFd) -> rustix::io::Result<()> {
62/// let mut buf = Vec::with_capacity(64);
63/// let nread = read(fd, spare_capacity(&mut buf))?;
64/// // `nread` is the number of bytes read.
65/// // Also, `buf.len()` is now `nread` elements longer than it was before.
66/// # Ok(())
67/// # }
68/// ```
69///
70/// Passing a `&mut`[`Cursor<T, B>`]:
71///
72/// ```no_run,ignore
73/// # use rustix::io::read;
74/// # fn example(fd: rustix::fd::BorrowedFd) -> rustix::io::Result<()> {
75/// let mut buf = [0_u8; 64];
76/// let mut cursor = Cursor::new(&mut buf);
77/// let _nread = read(fd, &mut cursor)?;
78/// let _nread = read(fd, &mut cursor)?;
79/// let _nread = read(fd, &mut cursor)?;
80/// let total_nread = cursor.finish();
81/// // `total_nread` is the total number of bytes read.
82/// # Ok(())
83/// # }
84/// ```
85///
86/// # Guide to error messages
87///
88/// Sometimes code using `Buffer` can encounter non-obvious error messages.
89/// Here are some we've encountered, along with ways to fix them.
90///
91/// If you see errors like
92/// "cannot move out of `self` which is behind a mutable reference"
93/// and
94/// "move occurs because `x` has type `&mut [u8]`, which does not implement the `Copy` trait",
95/// replace `x` with `&mut *x`. See `error_buffer_wrapper` in
96/// examples/buffer_errors.rs.
97///
98/// If you see errors like
99/// "type annotations needed"
100/// and
101/// "cannot infer type of the type parameter `Buf` declared on the function `read`",
102/// you may need to change a `&mut []` to `&mut [0_u8; 0]`. See
103/// `error_empty_slice` in examples/buffer_errors.rs.
104///
105/// If you see errors like
106/// "the trait bound `[MaybeUninit<u8>; 1]: Buffer<u8>` is not satisfied",
107/// add a `&mut` to pass the array by reference instead of by value. See
108/// `error_array_by_value` in examples/buffer_errors.rs.
109///
110/// If you see errors like
111/// "cannot move out of `x`, a captured variable in an `FnMut` closure",
112/// try replacing `x` with `&mut *x`, or, if that doesn't work, try moving a
113/// `let` into the closure body. See `error_retry_closure` and
114/// `error_retry_indirect_closure` in examples/buffer_errors.rs.
115///
116/// If you see errors like
117/// "captured variable cannot escape `FnMut` closure body",
118/// use an explicit loop instead of `retry_on_intr`, assuming you're using
119/// that. See `error_retry_closure_uninit` in examples/buffer_errors.rs.
120///
121/// [`&mut Cursor<T, B>`]: crate::Cursor
122pub trait Buffer<T>
123where
124    Self: Sized,
125{
126    /// The type of the value returned by functions with `Buffer` arguments.
127    type Output;
128
129    /// Return a raw mutable pointer to the underlying buffer.
130    ///
131    /// After using this pointer to initialize some elements, call
132    /// [`assume_init`] to declare how many were initialized.
133    ///
134    /// [`assume_init`]: Self::assume_init
135    fn buffer_ptr(&mut self) -> *mut T;
136
137    /// Return the length in elements of the underlying buffer.
138    fn buffer_len(&self) -> usize;
139
140    /// Assert that `len` elements were written to, and provide a return value.
141    ///
142    /// # Safety
143    ///
144    /// At least the first `len` elements of the buffer must be initialized.
145    unsafe fn assume_init(self, len: usize) -> Self::Output;
146
147    /// Return a [`Cursor`] for safely writing to the buffer.
148    ///
149    /// Calling [`finish`] on the cursor returns the `Self::Output`.
150    ///
151    /// This is an alternative to `buffer_ptr`/`assume_init` which allows
152    /// callers to avoid using `unsafe`.
153    ///
154    /// [`finish`]: Cursor::finish
155    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// `Vec` implements `DerefMut` to `&mut [T]`, however it doesn't get
199// auto-derefed in a `impl Buffer<T>`, so we add this `impl` so that our users
200// don't have to add an extra `*` in these situations.
201#[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// Similarly, `Box<[T]>` implements `DerefMut` to `&mut [T]`, however it
222// doesn't get auto-derefed in a `impl Buffer<u8>`, so we add this `impl` so
223// that our users don't have to add an extra `*` in these situations.
224#[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        // SAFETY: The caller asserts that at least `len` elements of the
260        // buffer have been initialized.
261        unsafe {
262            let (init, uninit) = self.split_at_mut(len);
263
264            // Convert `init` from `&mut [MaybeUninit<T>]` to `&mut [T]`.
265            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        // SAFETY: The caller asserts that at least `len` elements of the
288        // buffer have been initialized.
289        unsafe {
290            let (init, uninit) = self.split_at_mut(len);
291
292            // Convert `init` from `&mut [MaybeUninit<T>]` to `&mut [T]`.
293            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        // SAFETY: The caller asserts that at least `len` elements of the
317        // buffer have been initialized.
318        unsafe {
319            let (init, uninit) = self.split_at_mut(len);
320
321            // Convert `init` from `&mut [MaybeUninit<T>]` to `&mut [T]`.
322            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        // SAFETY: The caller asserts that at least `len` elements of the
346        // buffer have been initialized.
347        unsafe {
348            let (init, uninit) = self.split_at_mut(len);
349
350            // Convert `init` from `&mut [MaybeUninit<T>]` to `&mut [T]`.
351            let init = slice::from_raw_parts_mut(init.as_mut_ptr().cast::<T>(), init.len());
352
353            (init, uninit)
354        }
355    }
356}
357
358// Similarly, `IoSliceMut` implements `DerefMut` to `&mut [u8]`, however it
359// doesn't get auto-derefed in a `impl Buffer<u8>`, so we add this `impl` so
360// that our users don't have to add an extra `*` in these situations.
361#[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/// A type that implements [`Buffer`] by appending to a `Vec`, up to its
382/// capacity.
383///
384/// To use this, use the [`spare_capacity`] function.
385///
386/// Because this uses the capacity, and never reallocates, the `Vec` should
387/// have some non-empty spare capacity.
388#[cfg(feature = "alloc")]
389#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
390pub struct SpareCapacity<'a, T>(&'a mut Vec<T>);
391
392/// Construct a [`SpareCapacity`], which implements [`Buffer`].
393///
394/// This wraps a `&mut Vec` and uses the spare capacity of the `Vec` as the
395/// buffer to receive data in, automatically calling `set_len` on the `Vec` to
396/// set the length to include the received elements.
397///
398/// This uses the existing capacity, and never allocates, so the `Vec` should
399/// have some non-empty spare capacity!
400///
401/// # Examples
402///
403/// ```
404/// # fn test(input: rustix::fd::BorrowedFd) -> rustix::io::Result<()> {
405/// use rustix::buffer::spare_capacity;
406/// use rustix::io::{Errno, read};
407///
408/// let mut buf = Vec::with_capacity(1024);
409/// match read(input, spare_capacity(&mut buf)) {
410///     Ok(0) => { /* end of stream */ }
411///     Ok(n) => { /* `buf` is now `n` bytes longer */ }
412///     Err(Errno::INTR) => { /* `buf` is unmodified */ }
413///     Err(e) => {
414///         return Err(e);
415///     }
416/// }
417///
418/// # Ok(())
419/// # }
420/// ```
421#[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    /// The number of elements written into the buffer.
437    ///
438    /// This is somewhat redundant, as `set_len` is also called on the
439    /// referenced `Vec`, however it can be convenient in some cases, such as
440    /// for testing for end-of-stream.
441    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        // SAFETY: The caller asserts that at least `len` elements of the spare
456        // capacity region have been initialized.
457        unsafe {
458            self.0.set_len(self.0.len() + len);
459        }
460        len
461    }
462}
463
464/// A cursor for safely writing into an uninitialized buffer.
465///
466/// A `Cursor` is returned from [`Buffer::cursor`], which provides way to
467/// write to a [`Buffer`] without needing to use `unsafe`.
468///
469/// # Examples
470///
471/// ```ignore
472/// # use buffer_trait::{Cursor, spare_capacity};
473/// let mut buf = Vec::with_capacity(256);
474/// let mut cursor = Cursor::new(spare_capacity(&mut buf));
475/// let _nread = read(&input, &mut cursor).unwrap();
476/// let _nread = read(&input, &mut cursor).unwrap();
477/// let _nread = read(&input, &mut cursor).unwrap();
478/// let total_read = cursor.finish();
479/// ```
480pub 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    /// Construct a new `Cursor`.
488    pub const fn new(b: B) -> Self {
489        Self {
490            pos: 0,
491            b,
492            phantom: PhantomData,
493        }
494    }
495
496    /// Return the remaining amount of space in the buffer.
497    pub fn remaining(&self) -> usize {
498        self.b.buffer_len() - self.pos
499    }
500
501    /// Write an element to the buffer.
502    ///
503    /// # Panics
504    ///
505    /// Panics if this cursor has already reached the end of the buffer.
506    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        // SAFETY: `Cursor::new` requires that `ptr` and `len` are valid, and we
516        // just bounds-checked `pos`.
517        unsafe {
518            ptr.add(self.pos).write(t);
519        }
520
521        // Count how many elements we've initialized.
522        self.pos += 1;
523    }
524
525    /// Write multiple elements to the buffer.
526    ///
527    /// # Panics
528    ///
529    /// Panics if this cursor is already within `t.len()` elements of the end
530    /// of the buffer.
531    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        // SAFETY: We've required that `T` implements `Copy`, bounds-checked
544        // the length, `buffer_ptr` should have given us a correct pointer, and
545        // `buffer_len` should have given us a correct length.
546        unsafe {
547            core::ptr::copy_nonoverlapping(t.as_ptr(), ptr, t.len());
548        }
549
550        // Count how many elements we've initialized.
551        self.pos += t.len();
552    }
553
554    /// Finish writing to the buffer and return the output value.
555    pub fn finish(self) -> B::Output {
556        // SAFETY: `Cursor` ensures that exactly `pos` elements have been
557        // written.
558        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        // SAFETY: We ensure that `self.pos` is always within the bounds
568        // of the buffer.
569        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        // Count how many elements we've initialized.
580        self.pos += len;
581        len
582    }
583}
584
585#[cfg(test)]
586mod tests {
587    #[allow(unused_imports)]
588    use super::*;
589
590    /// Test type signatures.
591    #[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    /// Test passing a `&mut [u8]` to `read`.
657    #[cfg(not(windows))]
658    #[test]
659    fn test_slice() {
660        use std::io::{Seek, SeekFrom};
661
662        // We need to obtain input stream with contents that we can compare
663        // against, so open our own source file.
664        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    /// Test passing a `&mut [MaybeUninit<u8>]` to `read`.
683    #[cfg(not(windows))]
684    #[test]
685    fn test_slice_uninit() {
686        use core::mem::MaybeUninit;
687        use std::io::{Seek, SeekFrom};
688
689        // We need to obtain input stream with contents that we can compare
690        // against, so open our own source file.
691        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    /// Test passing a `SpareCapacity` to `read`.
717    #[cfg(not(windows))]
718    #[test]
719    fn test_spare_capacity() {
720        use std::io::{Seek, SeekFrom};
721
722        // We need to obtain input stream with contents that we can compare
723        // against, so open our own source file.
724        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 passing a `Cursor` to `read`.
748    #[test]
749    fn test_cursor_as_buffer() {
750        use std::io::{Seek, SeekFrom};
751
752        // We need to obtain input stream with contents that we can compare
753        // against, so open our own source file.
754        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 nesting `Cursor`s inside of `Cursor`s.
787    #[test]
788    fn test_nesting() {
789        use std::io::{Seek, SeekFrom};
790
791        // We need to obtain input stream with contents that we can compare
792        // against, so open our own source file.
793        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 using a `Cursor` to read into a `MaybeUninit` buffer in multiple
834    /// reads, ultimately producing a single initialized slice.
835    #[test]
836    fn test_incremental() {
837        use std::io::{Seek, SeekFrom};
838
839        // We need to obtain input stream with contents that we can compare
840        // against, so open our own source file.
841        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// The comment at the end of the file!