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::<T>()
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        let (init, uninit) = self.split_at_mut(len);
260
261        // Convert `init` from `&mut [MaybeUninit<T>]` to `&mut [T]`.
262        //
263        // SAFETY: The caller asserts that at least `len` elements of the
264        // buffer have been initialized.
265        let init = unsafe { slice::from_raw_parts_mut(init.as_mut_ptr().cast::<T>(), init.len()) };
266
267        (init, uninit)
268    }
269}
270
271impl<'a, T, const N: usize> Buffer<T> for &'a mut [MaybeUninit<T>; N] {
272    type Output = (&'a mut [T], &'a mut [MaybeUninit<T>]);
273
274    #[inline]
275    fn buffer_ptr(&mut self) -> *mut T {
276        self.as_mut_ptr().cast::<T>()
277    }
278
279    #[inline]
280    fn buffer_len(&self) -> usize {
281        N
282    }
283
284    #[inline]
285    unsafe fn assume_init(self, len: usize) -> Self::Output {
286        let (init, uninit) = self.split_at_mut(len);
287
288        // Convert `init` from `&mut [MaybeUninit<T>]` to `&mut [T]`.
289        //
290        // SAFETY: The caller asserts that at least `len` elements of the
291        // buffer have been initialized.
292        let init = unsafe { slice::from_raw_parts_mut(init.as_mut_ptr().cast::<T>(), init.len()) };
293
294        (init, uninit)
295    }
296}
297
298#[cfg(feature = "alloc")]
299impl<'a, T> Buffer<T> for &'a mut Vec<MaybeUninit<T>> {
300    type Output = (&'a mut [T], &'a mut [MaybeUninit<T>]);
301
302    #[inline]
303    fn buffer_ptr(&mut self) -> *mut T {
304        self.as_mut_ptr().cast::<T>()
305    }
306
307    #[inline]
308    fn buffer_len(&self) -> usize {
309        self.len()
310    }
311
312    #[inline]
313    unsafe fn assume_init(self, len: usize) -> Self::Output {
314        let (init, uninit) = self.split_at_mut(len);
315
316        // Convert `init` from `&mut [MaybeUninit<T>]` to `&mut [T]`.
317        //
318        // SAFETY: The caller asserts that at least `len` elements of the
319        // buffer have been initialized.
320        let init = unsafe { slice::from_raw_parts_mut(init.as_mut_ptr().cast::<T>(), init.len()) };
321
322        (init, uninit)
323    }
324}
325
326#[cfg(feature = "alloc")]
327impl<'a, T> Buffer<T> for &'a mut Box<[MaybeUninit<T>]> {
328    type Output = (&'a mut [T], &'a mut [MaybeUninit<T>]);
329
330    #[inline]
331    fn buffer_ptr(&mut self) -> *mut T {
332        self.as_mut_ptr().cast::<T>()
333    }
334
335    #[inline]
336    fn buffer_len(&self) -> usize {
337        self.len()
338    }
339
340    #[inline]
341    unsafe fn assume_init(self, len: usize) -> Self::Output {
342        let (init, uninit) = self.split_at_mut(len);
343
344        // Convert `init` from `&mut [MaybeUninit<T>]` to `&mut [T]`.
345        //
346        // SAFETY: The caller asserts that at least `len` elements of the
347        // buffer have been initialized.
348        let init = unsafe { slice::from_raw_parts_mut(init.as_mut_ptr().cast::<T>(), init.len()) };
349
350        (init, uninit)
351    }
352}
353
354// Similarly, `IoSliceMut` implements `DerefMut` to `&mut [u8]`, however it
355// doesn't get auto-derefed in a `impl Buffer<u8>`, so we add this `impl` so
356// that our users don't have to add an extra `*` in these situations.
357#[cfg(feature = "std")]
358impl<'a> Buffer<u8> for &mut std::io::IoSliceMut<'a> {
359    type Output = usize;
360
361    #[inline]
362    fn buffer_ptr(&mut self) -> *mut u8 {
363        self.as_mut_ptr()
364    }
365
366    #[inline]
367    fn buffer_len(&self) -> usize {
368        self.len()
369    }
370
371    #[inline]
372    unsafe fn assume_init(self, len: usize) -> Self::Output {
373        len
374    }
375}
376
377/// A type that implements [`Buffer`] by appending to a `Vec`, up to its
378/// capacity.
379///
380/// To use this, use the [`spare_capacity`] function.
381///
382/// Because this uses the capacity, and never reallocates, the `Vec` should
383/// have some non-empty spare capacity.
384#[cfg(feature = "alloc")]
385#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
386pub struct SpareCapacity<'a, T>(&'a mut Vec<T>);
387
388/// Construct a [`SpareCapacity`], which implements [`Buffer`].
389///
390/// This wraps a `&mut Vec` and uses the spare capacity of the `Vec` as the
391/// buffer to receive data in, automatically calling `set_len` on the `Vec` to
392/// set the length to include the received elements.
393///
394/// This uses the existing capacity, and never allocates, so the `Vec` should
395/// have some non-empty spare capacity!
396///
397/// # Examples
398///
399/// ```
400/// # fn test(input: rustix::fd::BorrowedFd) -> rustix::io::Result<()> {
401/// use rustix::buffer::spare_capacity;
402/// use rustix::io::{Errno, read};
403///
404/// let mut buf = Vec::with_capacity(1024);
405/// match read(input, spare_capacity(&mut buf)) {
406///     Ok(0) => { /* end of stream */ }
407///     Ok(n) => { /* `buf` is now `n` bytes longer */ }
408///     Err(Errno::INTR) => { /* `buf` is unmodified */ }
409///     Err(e) => {
410///         return Err(e);
411///     }
412/// }
413///
414/// # Ok(())
415/// # }
416/// ```
417#[cfg(feature = "alloc")]
418#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
419pub fn spare_capacity<'a, T>(v: &'a mut Vec<T>) -> SpareCapacity<'a, T> {
420    debug_assert_ne!(
421        v.capacity(),
422        0,
423        "`extend` uses spare capacity, and never allocates new memory, so the `Vec` passed to it \
424         should have some spare capacity."
425    );
426
427    SpareCapacity(v)
428}
429
430#[cfg(feature = "alloc")]
431impl<'a, T> Buffer<T> for SpareCapacity<'a, T> {
432    /// The number of elements written into the buffer.
433    ///
434    /// This is somewhat redundant, as `set_len` is also called on the
435    /// referenced `Vec`, however it can be convenient in some cases, such as
436    /// for testing for end-of-stream.
437    type Output = usize;
438
439    #[inline]
440    fn buffer_ptr(&mut self) -> *mut T {
441        self.0.spare_capacity_mut().as_mut_ptr().cast::<T>()
442    }
443
444    #[inline]
445    fn buffer_len(&self) -> usize {
446        self.0.capacity() - self.0.len()
447    }
448
449    #[inline]
450    unsafe fn assume_init(self, len: usize) -> Self::Output {
451        // SAFETY: The caller asserts that at least `len` elements of the spare
452        // capacity region have been initialized.
453        unsafe {
454            self.0.set_len(self.0.len() + len);
455        }
456        len
457    }
458}
459
460/// A cursor for safely writing into an uninitialized buffer.
461///
462/// A `Cursor` is returned from [`Buffer::cursor`], which provides way to
463/// write to a [`Buffer`] without needing to use `unsafe`.
464///
465/// # Examples
466///
467/// ```ignore
468/// # use buffer_trait::{Cursor, spare_capacity};
469/// let mut buf = Vec::with_capacity(256);
470/// let mut cursor = Cursor::new(spare_capacity(&mut buf));
471/// let _nread = read(&input, &mut cursor).unwrap();
472/// let _nread = read(&input, &mut cursor).unwrap();
473/// let _nread = read(&input, &mut cursor).unwrap();
474/// let total_read = cursor.finish();
475/// ```
476pub struct Cursor<T, B: Buffer<T>> {
477    pos: usize,
478    b: B,
479    phantom: PhantomData<T>,
480}
481
482impl<T, B: Buffer<T>> Cursor<T, B> {
483    /// Construct a new `Cursor`.
484    pub const fn new(b: B) -> Self {
485        Self {
486            pos: 0,
487            b,
488            phantom: PhantomData,
489        }
490    }
491
492    /// Return the remaining amount of space in the buffer.
493    pub fn remaining(&self) -> usize {
494        self.b.buffer_len() - self.pos
495    }
496
497    /// Write an element to the buffer.
498    ///
499    /// # Panics
500    ///
501    /// Panics if this cursor has already reached the end of the buffer.
502    pub fn write(&mut self, t: T) {
503        let ptr = self.b.buffer_ptr();
504        let len = self.b.buffer_len();
505
506        assert!(
507            self.pos < len,
508            "element would extend beyond the end of the buffer"
509        );
510
511        // SAFETY: `Cursor::new` requires that `ptr` and `len` are valid, and we
512        // just bounds-checked `pos`.
513        unsafe {
514            ptr.add(self.pos).write(t);
515        }
516
517        // Count how many elements we've initialized.
518        self.pos += 1;
519    }
520
521    /// Write multiple elements to the buffer.
522    ///
523    /// # Panics
524    ///
525    /// Panics if this cursor is already within `t.len()` elements of the end
526    /// of the buffer.
527    pub fn write_slice(&mut self, t: &[T])
528    where
529        T: Copy,
530    {
531        let ptr = self.b.buffer_ptr();
532        let len = self.b.buffer_len();
533
534        assert!(
535            len - self.pos >= t.len(),
536            "elements would extend beyond the end of the buffer"
537        );
538
539        // SAFETY: We've required that `T` implements `Copy`, bounds-checked
540        // the length, `buffer_ptr` should have given us a correct pointer, and
541        // `buffer_len` should have given us a correct length.
542        unsafe {
543            core::ptr::copy_nonoverlapping(t.as_ptr(), ptr, t.len());
544        }
545
546        // Count how many elements we've initialized.
547        self.pos += t.len();
548    }
549
550    /// Finish writing to the buffer and return the output value.
551    pub fn finish(self) -> B::Output {
552        // SAFETY: `Cursor` ensures that exactly `pos` elements have been
553        // written.
554        unsafe { self.b.assume_init(self.pos) }
555    }
556}
557
558impl<T, B: Buffer<T>> Buffer<T> for Cursor<T, B> {
559    type Output = B::Output;
560
561    #[inline]
562    fn buffer_ptr(&mut self) -> *mut T {
563        // SAFETY: We ensure that `self.pos` is always within the bounds
564        // of the buffer.
565        unsafe { self.b.buffer_ptr().add(self.pos) }
566    }
567
568    #[inline]
569    fn buffer_len(&self) -> usize {
570        self.remaining()
571    }
572
573    #[inline]
574    unsafe fn assume_init(mut self, len: usize) -> Self::Output {
575        // Count how many elements we've initialized.
576        self.pos += len;
577        self.finish()
578    }
579}
580
581// TODO: Is is too surprising to have `&mut Cursor<T, B>` use a different
582// `Output` type than `Cursor<T, B>`?
583impl<T, B: Buffer<T>> Buffer<T> for &mut Cursor<T, B> {
584    type Output = usize;
585
586    #[inline]
587    fn buffer_ptr(&mut self) -> *mut T {
588        // SAFETY: We ensure that `self.pos` is always within the bounds
589        // of the buffer.
590        unsafe { self.b.buffer_ptr().add(self.pos) }
591    }
592
593    #[inline]
594    fn buffer_len(&self) -> usize {
595        self.remaining()
596    }
597
598    #[inline]
599    unsafe fn assume_init(self, len: usize) -> Self::Output {
600        // Count how many elements we've initialized.
601        self.pos += len;
602        len
603    }
604}
605
606#[cfg(test)]
607mod tests {
608    #[allow(unused_imports)]
609    use super::*;
610
611    /// Test type signatures.
612    #[cfg(not(windows))]
613    #[test]
614    fn test_compilation() {
615        use core::mem::MaybeUninit;
616
617        fn read<B: Buffer<u8>>(b: B) -> Result<B::Output, ()> {
618            Ok(b.cursor().finish())
619        }
620
621        let mut buf = vec![0_u8; 3];
622        buf.reserve(32);
623        let _x: usize = read(spare_capacity(&mut buf)).unwrap();
624        let _x: (&mut [u8], &mut [MaybeUninit<u8>]) = read(buf.spare_capacity_mut()).unwrap();
625        let _x: usize = read(&mut buf).unwrap();
626        let _x: usize = read(&mut *buf).unwrap();
627        let _x: usize = read(&mut buf[..]).unwrap();
628        let _x: usize = read(&mut (*buf)[..]).unwrap();
629
630        let mut buf = [0, 0, 0];
631        let _x: usize = read(&mut buf).unwrap();
632        let _x: usize = read(&mut buf[..]).unwrap();
633
634        let mut buf = vec![0, 0, 0];
635        let _x: usize = read(&mut buf).unwrap();
636        let _x: usize = read(&mut buf[..]).unwrap();
637
638        let mut buf = vec![0, 0, 0].into_boxed_slice();
639        let _x: usize = read(&mut buf).unwrap();
640        let _x: usize = read(&mut buf[..]).unwrap();
641
642        let mut buf = [
643            MaybeUninit::uninit(),
644            MaybeUninit::uninit(),
645            MaybeUninit::uninit(),
646        ];
647        let _x: (&mut [u8], &mut [MaybeUninit<u8>]) = read(&mut buf).unwrap();
648        let _x: (&mut [u8], &mut [MaybeUninit<u8>]) = read(&mut buf[..]).unwrap();
649
650        let mut buf = vec![
651            MaybeUninit::uninit(),
652            MaybeUninit::uninit(),
653            MaybeUninit::uninit(),
654        ];
655        let _x: (&mut [u8], &mut [MaybeUninit<u8>]) = read(&mut buf).unwrap();
656        let _x: (&mut [u8], &mut [MaybeUninit<u8>]) = read(&mut buf[..]).unwrap();
657
658        let mut buf = vec![
659            MaybeUninit::uninit(),
660            MaybeUninit::uninit(),
661            MaybeUninit::uninit(),
662        ]
663        .into_boxed_slice();
664        let _x: (&mut [u8], &mut [MaybeUninit<u8>]) = read(&mut buf).unwrap();
665        let _x: (&mut [u8], &mut [MaybeUninit<u8>]) = read(&mut buf[..]).unwrap();
666
667        let mut buf = Cursor::new(&mut buf);
668        let _x: usize = read(&mut buf).unwrap();
669        let _x: (&mut [u8], &mut [MaybeUninit<u8>]) = buf.finish();
670
671        let mut buf = [0, 0, 0];
672        let mut io_slice = std::io::IoSliceMut::new(&mut buf);
673        let _x: usize = read(&mut io_slice).unwrap();
674        let _x: usize = read(&mut io_slice[..]).unwrap();
675    }
676
677    /// Test passing a `&mut [u8]` to `read`.
678    #[cfg(not(windows))]
679    #[test]
680    fn test_slice() {
681        use std::io::{Seek, SeekFrom};
682
683        // We need to obtain input stream with contents that we can compare
684        // against, so open our own source file.
685        let mut input = std::fs::File::open("src/lib.rs").unwrap();
686
687        let mut buf = [0_u8; 64];
688        let nread = read(&input, &mut buf).unwrap();
689        assert_eq!(nread, buf.len());
690        assert_eq!(
691            &buf[..54],
692            b"#![cfg_attr(doc, doc = include_str!(\"../README.md\"))]\n"
693        );
694        input.seek(SeekFrom::End(-1)).unwrap();
695        let nread = read(&input, &mut buf).unwrap();
696        assert_eq!(nread, 1);
697        assert_eq!(buf[0], b'\n');
698        input.seek(SeekFrom::End(0)).unwrap();
699        let nread = read(&input, &mut buf).unwrap();
700        assert_eq!(nread, 0);
701    }
702
703    /// Test passing a `&mut [MaybeUninit<u8>]` to `read`.
704    #[cfg(not(windows))]
705    #[test]
706    fn test_slice_uninit() {
707        use core::mem::MaybeUninit;
708        use std::io::{Seek, SeekFrom};
709
710        // We need to obtain input stream with contents that we can compare
711        // against, so open our own source file.
712        let mut input = std::fs::File::open("src/lib.rs").unwrap();
713
714        let mut buf = [MaybeUninit::<u8>::uninit(); 64];
715        let (init, uninit) = read(&input, &mut buf).unwrap();
716        assert_eq!(uninit.len(), 0);
717        assert_eq!(
718            &init[..54],
719            b"#![cfg_attr(doc, doc = include_str!(\"../README.md\"))]\n"
720        );
721        assert_eq!(init.len(), buf.len());
722        assert_eq!(
723            unsafe { core::mem::transmute::<&mut [MaybeUninit<u8>], &mut [u8]>(&mut buf[..54]) },
724            b"#![cfg_attr(doc, doc = include_str!(\"../README.md\"))]\n"
725        );
726        input.seek(SeekFrom::End(-1)).unwrap();
727        let (init, uninit) = read(&input, &mut buf).unwrap();
728        assert_eq!(init.len(), 1);
729        assert_eq!(init[0], b'\n');
730        assert_eq!(uninit.len(), buf.len() - 1);
731        input.seek(SeekFrom::End(0)).unwrap();
732        let (init, uninit) = read(&input, &mut buf).unwrap();
733        assert_eq!(init.len(), 0);
734        assert_eq!(uninit.len(), buf.len());
735    }
736
737    /// Test passing a `SpareCapacity` to `read`.
738    #[cfg(not(windows))]
739    #[test]
740    fn test_spare_capacity() {
741        use std::io::{Seek, SeekFrom};
742
743        // We need to obtain input stream with contents that we can compare
744        // against, so open our own source file.
745        let mut input = std::fs::File::open("src/lib.rs").unwrap();
746
747        let mut buf = Vec::with_capacity(64);
748        let nread = read(&input, spare_capacity(&mut buf)).unwrap();
749        assert_eq!(nread, buf.capacity());
750        assert_eq!(nread, buf.len());
751        assert_eq!(
752            &buf[..54],
753            b"#![cfg_attr(doc, doc = include_str!(\"../README.md\"))]\n"
754        );
755        buf.clear();
756        input.seek(SeekFrom::End(-1)).unwrap();
757        let nread = read(&input, spare_capacity(&mut buf)).unwrap();
758        assert_eq!(nread, 1);
759        assert_eq!(buf.len(), 1);
760        assert_eq!(buf[0], b'\n');
761        buf.clear();
762        input.seek(SeekFrom::End(0)).unwrap();
763        let nread = read(&input, spare_capacity(&mut buf)).unwrap();
764        assert_eq!(nread, 0);
765        assert!(buf.is_empty());
766    }
767
768    /// Test passing a `Cursor` to `read`.
769    #[test]
770    fn test_cursor_as_buffer() {
771        use std::io::{Seek, SeekFrom};
772
773        // We need to obtain input stream with contents that we can compare
774        // against, so open our own source file.
775        let mut input = std::fs::File::open("src/lib.rs").unwrap();
776
777        let mut total_read = 0;
778
779        let mut buf = Vec::with_capacity(256);
780        let mut cursor = Cursor::new(spare_capacity(&mut buf));
781        input.seek(SeekFrom::End(-39)).unwrap();
782        let nread = read(&input, &mut cursor).unwrap();
783        total_read += nread;
784        assert_eq!(cursor.remaining(), 256 - 39);
785        input.seek(SeekFrom::End(-39)).unwrap();
786        let nread = read(&input, &mut cursor).unwrap();
787        total_read += nread;
788        assert_eq!(cursor.remaining(), 256 - 39 * 2);
789        input.seek(SeekFrom::End(-39)).unwrap();
790        let nread = read(&input, &mut cursor).unwrap();
791        total_read += nread;
792        assert_eq!(cursor.remaining(), 256 - 39 * 3);
793
794        assert_eq!(total_read, 39 * 3);
795
796        let cursor_read = cursor.finish();
797        assert_eq!(cursor_read, total_read);
798
799        assert_eq!(buf.len(), 39 * 3);
800        assert_eq!(buf.capacity(), 256);
801        assert_eq!(
802            buf,
803            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"
804        );
805    }
806
807    /// Test nesting `Cursor`s inside of `Cursor`s.
808    #[test]
809    fn test_nesting() {
810        use std::io::{Seek, SeekFrom};
811
812        // We need to obtain input stream with contents that we can compare
813        // against, so open our own source file.
814        let mut input = std::fs::File::open("src/lib.rs").unwrap();
815
816        let mut total_read = 0;
817
818        let mut buf = Vec::with_capacity(256);
819        let mut cursor = Cursor::new(spare_capacity(&mut buf));
820        input.seek(SeekFrom::End(-39)).unwrap();
821        let nread = read(&input, &mut cursor).unwrap();
822        total_read += nread;
823        assert_eq!(cursor.remaining(), 256 - 39);
824        input.seek(SeekFrom::End(-39)).unwrap();
825        let mut nested_cursor = Cursor::new(&mut cursor);
826        let nested_nread = read(&input, &mut nested_cursor).unwrap();
827        assert_eq!(nested_nread, 39);
828        assert_eq!(nested_cursor.remaining(), 256 - 39 * 2);
829        input.seek(SeekFrom::End(-39)).unwrap();
830        let mut nested_nested_cursor = Cursor::new(&mut nested_cursor);
831        let nested_nested_nread = read(&input, &mut nested_nested_cursor).unwrap();
832        assert_eq!(nested_nested_nread, 39);
833        assert_eq!(nested_nested_cursor.remaining(), 256 - 39 * 3);
834        let inner_nread = nested_nested_cursor.finish();
835        assert_eq!(inner_nread, 39);
836        assert_eq!(nested_cursor.remaining(), 256 - 39 * 3);
837        let nread = nested_cursor.finish();
838        total_read += nread;
839
840        assert_eq!(total_read, 39 * 3);
841        assert_eq!(cursor.remaining(), 256 - 39 * 3);
842
843        let cursor_read = cursor.finish();
844        assert_eq!(cursor_read, total_read);
845
846        assert_eq!(buf.len(), 39 * 3);
847        assert_eq!(buf.capacity(), 256);
848        assert_eq!(
849            &buf[..39*3],
850            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"
851        );
852    }
853
854    /// Test using a `Cursor` to read into a `MaybeUninit` buffer in multiple
855    /// reads, ultimately producing a single initialized slice.
856    #[test]
857    fn test_incremental() {
858        use std::io::{Seek, SeekFrom};
859
860        // We need to obtain input stream with contents that we can compare
861        // against, so open our own source file.
862        let mut input = std::fs::File::open("src/lib.rs").unwrap();
863
864        let mut total_read = 0;
865
866        let mut buf = [MaybeUninit::<u8>::zeroed(); 256];
867        let mut cursor = Cursor::new(&mut buf);
868        input.seek(SeekFrom::End(-39)).unwrap();
869        let nread = read(&input, &mut cursor).unwrap();
870        total_read += nread;
871        assert_eq!(cursor.remaining(), 256 - 39);
872        input.seek(SeekFrom::End(-39)).unwrap();
873        let nread = read(&input, &mut cursor).unwrap();
874        total_read += nread;
875        assert_eq!(cursor.remaining(), 256 - 39 * 2);
876        input.seek(SeekFrom::End(-39)).unwrap();
877        let nread = read(&input, &mut cursor).unwrap();
878        total_read += nread;
879        assert_eq!(cursor.remaining(), 256 - 39 * 3);
880
881        assert_eq!(total_read, 39 * 3);
882
883        let (init, uninit) = cursor.finish();
884        assert_eq!(init.len(), total_read);
885        assert_eq!(uninit.len(), 256 - total_read);
886
887        assert_eq!(
888            init,
889            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"
890        );
891    }
892
893    fn read<B: Buffer<u8>>(input: &std::fs::File, mut b: B) -> std::io::Result<B::Output> {
894        use std::os::fd::AsRawFd;
895        let ptr = b.buffer_ptr();
896        let len = b.buffer_len();
897        let n = unsafe { libc::read(input.as_raw_fd(), ptr.cast(), len) };
898        if let Ok(n) = usize::try_from(n) {
899            unsafe { Ok(b.assume_init(n)) }
900        } else {
901            Err(std::io::Error::last_os_error())
902        }
903    }
904}
905
906// The comment at the end of the file!