Skip to main content

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/// # Safety
29///
30/// This trait is unsafe to implement because safe code, such as
31/// [`Cursor::write`], trusts the values it returns and performs raw pointer
32/// writes into the buffer without further checks. Implementations must
33/// ensure all the following:
34///
35///  - [`buffer_ptr`] returns a pointer that is non-null, properly aligned,
36///    and valid for writes of [`buffer_len`] consecutive elements of `T`.
37///
38///  - [`buffer_len`] returns the length in elements of the region that
39///    [`buffer_ptr`] points to.
40///
41///  - Unless the buffer is mutated through means outside of this trait,
42///    successive calls to [`buffer_ptr`] and [`buffer_len`] describe the
43///    same region, as callers such as [`Cursor`] call them repeatedly while
44///    tracking how many elements they have initialized.
45///
46///  - Implementations do not read the contents of the buffer, which may be
47///    uninitialized. In particular, [`assume_init`] may assume only that the
48///    first `len` elements are initialized.
49///
50/// [`buffer_ptr`]: Self::buffer_ptr
51/// [`buffer_len`]: Self::buffer_len
52/// [`assume_init`]: Self::assume_init
53///
54/// # Examples
55///
56/// Passing a `&mut [T]`:
57///
58/// ```
59/// # use rustix::io::read;
60/// # fn example(fd: rustix::fd::BorrowedFd) -> rustix::io::Result<()> {
61/// let mut buf = [0_u8; 64];
62/// let nread = read(fd, &mut buf)?;
63/// // `nread` is the number of bytes read.
64/// # Ok(())
65/// # }
66/// ```
67///
68/// Passing a `&mut [MaybeUninit<T>]`:
69///
70/// ```
71/// # use rustix::io::read;
72/// # use std::mem::MaybeUninit;
73/// # fn example(fd: rustix::fd::BorrowedFd) -> rustix::io::Result<()> {
74/// let mut buf = [MaybeUninit::<u8>::uninit(); 64];
75/// let (init, uninit) = read(fd, &mut buf)?;
76/// // `init` is a `&mut [u8]` with the initialized bytes.
77/// // `uninit` is a `&mut [MaybeUninit<u8>]` with the remaining bytes.
78/// # Ok(())
79/// # }
80/// ```
81///
82/// Passing a [`SpareCapacity`], via the [`spare_capacity`] helper function:
83///
84/// ```
85/// # use rustix::io::read;
86/// # use rustix::buffer::spare_capacity;
87/// # fn example(fd: rustix::fd::BorrowedFd) -> rustix::io::Result<()> {
88/// let mut buf = Vec::with_capacity(64);
89/// let nread = read(fd, spare_capacity(&mut buf))?;
90/// // `nread` is the number of bytes read.
91/// // Also, `buf.len()` is now `nread` elements longer than it was before.
92/// # Ok(())
93/// # }
94/// ```
95///
96/// Passing a `&mut` [`Cursor<T, B>`]:
97///
98/// ```no_run,ignore
99/// # use rustix::io::read;
100/// # fn example(fd: rustix::fd::BorrowedFd) -> rustix::io::Result<()> {
101/// let mut buf = [0_u8; 64];
102/// let mut cursor = Cursor::new(&mut buf);
103/// let _nread = read(fd, &mut cursor)?;
104/// let _nread = read(fd, &mut cursor)?;
105/// let _nread = read(fd, &mut cursor)?;
106/// let total_nread = cursor.finish();
107/// // `total_nread` is the total number of bytes read.
108/// # Ok(())
109/// # }
110/// ```
111///
112/// Accepting a `Buffer` argument, using `unsafe`:
113///
114/// ```
115/// # use buffer_trait::Buffer;
116/// # unsafe extern "C" { fn read_bytes(ptr: *mut u8, len: usize); }
117/// pub fn read_into_buffer<B: Buffer<u8>>(mut b: B) -> B::Output {
118///     let ptr = b.buffer_ptr();
119///     let len = b.buffer_len();
120///
121///     unsafe {
122///         // Some FFI call to do I/O.
123///         read_bytes(ptr, len);
124///
125///         // Assume we just wrote `len` elements.
126///         b.assume_init(len)
127///     }
128/// }
129/// ```
130///
131/// Accepting a `Buffer` argument, without using `unsafe`:
132///
133/// ```
134/// # use buffer_trait::Buffer;
135/// # use std::cmp::min;
136/// # fn read_one_byte() -> u8 { unimplemented!() }
137/// # fn read_some_more_bytes(num: usize) -> Vec<u8> { unimplemented!() }
138/// pub fn read_into_buffer<B: Buffer<u8>>(b: B) -> B::Output {
139///     let mut cursor = b.cursor();
140///
141///     // Without `unsafe`, we can't do FFI I/O directly into the buffer, so
142///     // we use the `Cursor` type's API to write some data in. The advantage
143///     // of this approach is that we don't need an `unsafe` block in the
144///     // code here.
145///     let num = min(cursor.remaining(), 3);
146///     for i in 0..num {
147///         cursor.write(read_one_byte());
148///     }
149///     let more: Vec<u8> = read_some_more_bytes(cursor.remaining());
150///     cursor.write_slice(&more);
151///
152///     cursor.finish()
153/// }
154/// ```
155///
156/// # Guide to error messages
157///
158/// Sometimes code using `Buffer` can encounter non-obvious error messages.
159/// Here are some we've encountered, along with ways to fix them.
160///
161/// If you see errors like
162/// "cannot move out of `self` which is behind a mutable reference"
163/// and
164/// "move occurs because `x` has type `&mut [u8]`, which does not implement the `Copy` trait",
165/// replace `x` with `&mut *x`. See `error_buffer_wrapper` in
166/// examples/buffer_errors.rs.
167///
168/// If you see errors like
169/// "type annotations needed"
170/// and
171/// "cannot infer type of the type parameter `Buf` declared on the function `read`",
172/// you may need to change a `&mut []` to `&mut [0_u8; 0]`. See
173/// `error_empty_slice` in examples/buffer_errors.rs.
174///
175/// If you see errors like
176/// "the trait bound `[MaybeUninit<u8>; 1]: Buffer<u8>` is not satisfied",
177/// add a `&mut` to pass the array by reference instead of by value. See
178/// `error_array_by_value` in examples/buffer_errors.rs.
179///
180/// If you see errors like
181/// "cannot move out of `x`, a captured variable in an `FnMut` closure",
182/// try replacing `x` with `&mut *x`, or, if that doesn't work, try moving a
183/// `let` into the closure body. See `error_retry_closure` and
184/// `error_retry_indirect_closure` in examples/buffer_errors.rs.
185///
186/// If you see errors like
187/// "captured variable cannot escape `FnMut` closure body",
188/// use an explicit loop instead of `retry_on_intr`, assuming you're using
189/// that. See `error_retry_closure_uninit` in examples/buffer_errors.rs.
190///
191/// [`&mut Cursor<T, B>`]: crate::Cursor
192pub unsafe trait Buffer<T>
193where
194    Self: Sized,
195{
196    /// The type of the value returned by functions with `Buffer` arguments.
197    type Output;
198
199    /// Return a raw mutable pointer to the underlying buffer.
200    ///
201    /// The returned pointer may be used to write data into the buffer, which
202    /// requires use of `unsafe`. For an alternative safe API, see [`cursor`].
203    ///
204    /// After using this pointer to initialize some elements, call
205    /// [`assume_init`] to declare how many were initialized.
206    ///
207    /// [`cursor`]: Self::cursor
208    /// [`assume_init`]: Self::assume_init
209    fn buffer_ptr(&mut self) -> *mut T;
210
211    /// Return the length in elements of the underlying buffer.
212    fn buffer_len(&self) -> usize;
213
214    /// Assert that `len` elements were written to, and provide a return value.
215    ///
216    /// # Safety
217    ///
218    /// At least the first `len` elements of the buffer must be initialized.
219    unsafe fn assume_init(self, len: usize) -> Self::Output;
220
221    /// Return a [`Cursor`] for safely writing to the buffer.
222    ///
223    /// Calling [`finish`] on the cursor returns the `Self::Output`.
224    ///
225    /// This is an alternative to `buffer_ptr`/`assume_init` which allows
226    /// callers to avoid using `unsafe`.
227    ///
228    /// [`finish`]: Cursor::finish
229    fn cursor(self) -> Cursor<T, Self> {
230        Cursor::new(self)
231    }
232}
233
234unsafe impl<T> Buffer<T> for &mut [T] {
235    type Output = usize;
236
237    #[inline]
238    fn buffer_ptr(&mut self) -> *mut T {
239        self.as_mut_ptr()
240    }
241
242    #[inline]
243    fn buffer_len(&self) -> usize {
244        self.len()
245    }
246
247    #[inline]
248    unsafe fn assume_init(self, len: usize) -> Self::Output {
249        len
250    }
251}
252
253unsafe impl<T, const N: usize> Buffer<T> for &mut [T; N] {
254    type Output = usize;
255
256    #[inline]
257    fn buffer_ptr(&mut self) -> *mut T {
258        self.as_mut_ptr()
259    }
260
261    #[inline]
262    fn buffer_len(&self) -> usize {
263        N
264    }
265
266    #[inline]
267    unsafe fn assume_init(self, len: usize) -> Self::Output {
268        len
269    }
270}
271
272// `Vec` implements `DerefMut` to `&mut [T]`, however it doesn't get
273// auto-derefed in a `impl Buffer<T>`, so we add this `impl` so that our users
274// don't have to add an extra `*` in these situations.
275#[cfg(feature = "alloc")]
276unsafe impl<T> Buffer<T> for &mut Vec<T> {
277    type Output = usize;
278
279    #[inline]
280    fn buffer_ptr(&mut self) -> *mut T {
281        self.as_mut_ptr()
282    }
283
284    #[inline]
285    fn buffer_len(&self) -> usize {
286        self.len()
287    }
288
289    #[inline]
290    unsafe fn assume_init(self, len: usize) -> Self::Output {
291        len
292    }
293}
294
295// Similarly, `Box<[T]>` implements `DerefMut` to `&mut [T]`, however it
296// doesn't get auto-derefed in a `impl Buffer<u8>`, so we add this `impl` so
297// that our users don't have to add an extra `*` in these situations.
298#[cfg(feature = "alloc")]
299unsafe impl<T> Buffer<T> for &mut Box<[T]> {
300    type Output = usize;
301
302    #[inline]
303    fn buffer_ptr(&mut self) -> *mut T {
304        self.as_mut_ptr()
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        len
315    }
316}
317
318unsafe impl<'a, T> Buffer<T> for &'a mut [MaybeUninit<T>] {
319    type Output = (&'a mut [T], &'a mut [MaybeUninit<T>]);
320
321    #[inline]
322    fn buffer_ptr(&mut self) -> *mut T {
323        self.as_mut_ptr().cast::<T>()
324    }
325
326    #[inline]
327    fn buffer_len(&self) -> usize {
328        self.len()
329    }
330
331    #[inline]
332    unsafe fn assume_init(self, len: usize) -> Self::Output {
333        let (init, uninit) = self.split_at_mut(len);
334
335        // Convert `init` from `&mut [MaybeUninit<T>]` to `&mut [T]`.
336        //
337        // SAFETY: The caller asserts that at least `len` elements of the
338        // buffer have been initialized.
339        let init = unsafe { slice::from_raw_parts_mut(init.as_mut_ptr().cast::<T>(), init.len()) };
340
341        (init, uninit)
342    }
343}
344
345unsafe impl<'a, T, const N: usize> Buffer<T> for &'a mut [MaybeUninit<T>; N] {
346    type Output = (&'a mut [T], &'a mut [MaybeUninit<T>]);
347
348    #[inline]
349    fn buffer_ptr(&mut self) -> *mut T {
350        self.as_mut_ptr().cast::<T>()
351    }
352
353    #[inline]
354    fn buffer_len(&self) -> usize {
355        N
356    }
357
358    #[inline]
359    unsafe fn assume_init(self, len: usize) -> Self::Output {
360        let (init, uninit) = self.split_at_mut(len);
361
362        // Convert `init` from `&mut [MaybeUninit<T>]` to `&mut [T]`.
363        //
364        // SAFETY: The caller asserts that at least `len` elements of the
365        // buffer have been initialized.
366        let init = unsafe { slice::from_raw_parts_mut(init.as_mut_ptr().cast::<T>(), init.len()) };
367
368        (init, uninit)
369    }
370}
371
372#[cfg(feature = "alloc")]
373unsafe impl<'a, T> Buffer<T> for &'a mut Vec<MaybeUninit<T>> {
374    type Output = (&'a mut [T], &'a mut [MaybeUninit<T>]);
375
376    #[inline]
377    fn buffer_ptr(&mut self) -> *mut T {
378        self.as_mut_ptr().cast::<T>()
379    }
380
381    #[inline]
382    fn buffer_len(&self) -> usize {
383        self.len()
384    }
385
386    #[inline]
387    unsafe fn assume_init(self, len: usize) -> Self::Output {
388        let (init, uninit) = self.split_at_mut(len);
389
390        // Convert `init` from `&mut [MaybeUninit<T>]` to `&mut [T]`.
391        //
392        // SAFETY: The caller asserts that at least `len` elements of the
393        // buffer have been initialized.
394        let init = unsafe { slice::from_raw_parts_mut(init.as_mut_ptr().cast::<T>(), init.len()) };
395
396        (init, uninit)
397    }
398}
399
400#[cfg(feature = "alloc")]
401unsafe impl<'a, T> Buffer<T> for &'a mut Box<[MaybeUninit<T>]> {
402    type Output = (&'a mut [T], &'a mut [MaybeUninit<T>]);
403
404    #[inline]
405    fn buffer_ptr(&mut self) -> *mut T {
406        self.as_mut_ptr().cast::<T>()
407    }
408
409    #[inline]
410    fn buffer_len(&self) -> usize {
411        self.len()
412    }
413
414    #[inline]
415    unsafe fn assume_init(self, len: usize) -> Self::Output {
416        let (init, uninit) = self.split_at_mut(len);
417
418        // Convert `init` from `&mut [MaybeUninit<T>]` to `&mut [T]`.
419        //
420        // SAFETY: The caller asserts that at least `len` elements of the
421        // buffer have been initialized.
422        let init = unsafe { slice::from_raw_parts_mut(init.as_mut_ptr().cast::<T>(), init.len()) };
423
424        (init, uninit)
425    }
426}
427
428// Similarly, `IoSliceMut` implements `DerefMut` to `&mut [u8]`, however it
429// doesn't get auto-derefed in a `impl Buffer<u8>`, so we add this `impl` so
430// that our users don't have to add an extra `*` in these situations.
431#[cfg(feature = "std")]
432unsafe impl<'a> Buffer<u8> for &mut std::io::IoSliceMut<'a> {
433    type Output = usize;
434
435    #[inline]
436    fn buffer_ptr(&mut self) -> *mut u8 {
437        self.as_mut_ptr()
438    }
439
440    #[inline]
441    fn buffer_len(&self) -> usize {
442        self.len()
443    }
444
445    #[inline]
446    unsafe fn assume_init(self, len: usize) -> Self::Output {
447        len
448    }
449}
450
451/// A type that implements [`Buffer`] by appending to a `Vec`, up to its
452/// capacity.
453///
454/// To use this, use the [`spare_capacity`] function.
455///
456/// Because this uses the capacity, and never reallocates, the `Vec` should
457/// have some non-empty spare capacity.
458#[cfg(feature = "alloc")]
459#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
460pub struct SpareCapacity<'a, T>(&'a mut Vec<T>);
461
462/// Construct a [`SpareCapacity`], which implements [`Buffer`].
463///
464/// This wraps a `&mut Vec` and uses the spare capacity of the `Vec` as the
465/// buffer to receive data in, automatically calling `set_len` on the `Vec` to
466/// set the length to include the received elements.
467///
468/// This uses the existing capacity, and never allocates, so the `Vec` should
469/// have some non-empty spare capacity!
470///
471/// # Examples
472///
473/// ```
474/// # fn test(input: rustix::fd::BorrowedFd) -> rustix::io::Result<()> {
475/// use rustix::buffer::spare_capacity;
476/// use rustix::io::{Errno, read};
477///
478/// let mut buf = Vec::with_capacity(1024);
479/// match read(input, spare_capacity(&mut buf)) {
480///     Ok(0) => { /* end of stream */ }
481///     Ok(n) => { /* `buf` is now `n` bytes longer */ }
482///     Err(Errno::INTR) => { /* `buf` is unmodified */ }
483///     Err(e) => {
484///         return Err(e);
485///     }
486/// }
487///
488/// # Ok(())
489/// # }
490/// ```
491#[cfg(feature = "alloc")]
492#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
493pub fn spare_capacity<'a, T>(v: &'a mut Vec<T>) -> SpareCapacity<'a, T> {
494    debug_assert_ne!(
495        v.capacity(),
496        0,
497        "`extend` uses spare capacity, and never allocates new memory, so the `Vec` passed to it \
498         should have some spare capacity."
499    );
500
501    SpareCapacity(v)
502}
503
504#[cfg(feature = "alloc")]
505unsafe impl<'a, T> Buffer<T> for SpareCapacity<'a, T> {
506    /// The number of elements written into the buffer.
507    ///
508    /// This is somewhat redundant, as `set_len` is also called on the
509    /// referenced `Vec`, however it can be convenient in some cases, such as
510    /// for testing for end-of-stream.
511    type Output = usize;
512
513    #[inline]
514    fn buffer_ptr(&mut self) -> *mut T {
515        self.0.spare_capacity_mut().as_mut_ptr().cast::<T>()
516    }
517
518    #[inline]
519    fn buffer_len(&self) -> usize {
520        self.0.capacity() - self.0.len()
521    }
522
523    #[inline]
524    unsafe fn assume_init(self, len: usize) -> Self::Output {
525        // SAFETY: The caller asserts that at least `len` elements of the spare
526        // capacity region have been initialized.
527        unsafe {
528            self.0.set_len(self.0.len() + len);
529        }
530        len
531    }
532}
533
534/// A cursor for safely writing into an uninitialized buffer.
535///
536/// A `Cursor` is returned from [`Buffer::cursor`], which provides users a way
537/// to write to a [`Buffer`] without needing to use `unsafe` in their own code.
538///
539/// # Examples
540///
541/// ```ignore
542/// # use buffer_trait::{Cursor, spare_capacity};
543/// let mut buf = Vec::with_capacity(256);
544/// let mut cursor = Cursor::new(spare_capacity(&mut buf));
545/// let _nread = read(&input, &mut cursor).unwrap();
546/// let _nread = read(&input, &mut cursor).unwrap();
547/// let _nread = read(&input, &mut cursor).unwrap();
548/// let total_read = cursor.finish();
549/// ```
550pub struct Cursor<T, B: Buffer<T>> {
551    pos: usize,
552    b: B,
553    phantom: PhantomData<T>,
554}
555
556impl<T, B: Buffer<T>> Cursor<T, B> {
557    /// Construct a new `Cursor`.
558    pub const fn new(b: B) -> Self {
559        Self {
560            pos: 0,
561            b,
562            phantom: PhantomData,
563        }
564    }
565
566    /// Return the remaining amount of space in the buffer.
567    pub fn remaining(&self) -> usize {
568        self.b.buffer_len() - self.pos
569    }
570
571    /// Write an element to the buffer.
572    ///
573    /// # Panics
574    ///
575    /// Panics if this cursor has already reached the end of the buffer.
576    pub fn write(&mut self, t: T) {
577        let ptr = self.b.buffer_ptr();
578        let len = self.b.buffer_len();
579
580        assert!(
581            self.pos < len,
582            "element would extend beyond the end of the buffer"
583        );
584
585        // SAFETY: `Cursor::new` requires that `ptr` and `len` are valid, and we
586        // just bounds-checked `pos`.
587        unsafe {
588            ptr.add(self.pos).write(t);
589        }
590
591        // Count how many elements we've initialized.
592        self.pos += 1;
593    }
594
595    /// Write multiple elements to the buffer.
596    ///
597    /// # Panics
598    ///
599    /// Panics if this cursor is already within `t.len()` elements of the end
600    /// of the buffer.
601    pub fn write_slice(&mut self, t: &[T])
602    where
603        T: Copy,
604    {
605        let ptr = self.b.buffer_ptr();
606        let len = self.b.buffer_len();
607
608        assert!(
609            len - self.pos >= t.len(),
610            "elements would extend beyond the end of the buffer"
611        );
612
613        // SAFETY: We've required that `T` implements `Copy`, bounds-checked
614        // the length, `buffer_ptr` should have given us a correct pointer, and
615        // `buffer_len` should have given us a correct length.
616        unsafe {
617            core::ptr::copy_nonoverlapping(t.as_ptr(), ptr.add(self.pos), t.len());
618        }
619
620        // Count how many elements we've initialized.
621        self.pos += t.len();
622    }
623
624    /// Finish writing to the buffer and return the output value.
625    pub fn finish(self) -> B::Output {
626        // SAFETY: `Cursor` ensures that exactly `pos` elements have been
627        // written.
628        unsafe { self.b.assume_init(self.pos) }
629    }
630}
631
632unsafe impl<T, B: Buffer<T>> Buffer<T> for Cursor<T, B> {
633    type Output = B::Output;
634
635    #[inline]
636    fn buffer_ptr(&mut self) -> *mut T {
637        // SAFETY: We ensure that `self.pos` is always within the bounds
638        // of the buffer.
639        unsafe { self.b.buffer_ptr().add(self.pos) }
640    }
641
642    #[inline]
643    fn buffer_len(&self) -> usize {
644        self.remaining()
645    }
646
647    #[inline]
648    unsafe fn assume_init(mut self, len: usize) -> Self::Output {
649        // Count how many elements we've initialized.
650        self.pos += len;
651        self.finish()
652    }
653}
654
655// TODO: Is is too surprising to have `&mut Cursor<T, B>` use a different
656// `Output` type than `Cursor<T, B>`?
657unsafe impl<T, B: Buffer<T>> Buffer<T> for &mut Cursor<T, B> {
658    type Output = usize;
659
660    #[inline]
661    fn buffer_ptr(&mut self) -> *mut T {
662        // SAFETY: We ensure that `self.pos` is always within the bounds
663        // of the buffer.
664        unsafe { self.b.buffer_ptr().add(self.pos) }
665    }
666
667    #[inline]
668    fn buffer_len(&self) -> usize {
669        self.remaining()
670    }
671
672    #[inline]
673    unsafe fn assume_init(self, len: usize) -> Self::Output {
674        // Count how many elements we've initialized.
675        self.pos += len;
676        len
677    }
678}
679
680#[cfg(test)]
681mod tests {
682    #[allow(unused_imports)]
683    use super::*;
684
685    /// Test type signatures.
686    #[cfg(not(windows))]
687    #[test]
688    fn test_compilation() {
689        use core::mem::MaybeUninit;
690
691        fn read<B: Buffer<u8>>(b: B) -> Result<B::Output, ()> {
692            Ok(b.cursor().finish())
693        }
694
695        let mut buf = vec![0_u8; 3];
696        buf.reserve(32);
697        let _x: usize = read(spare_capacity(&mut buf)).unwrap();
698        let _x: (&mut [u8], &mut [MaybeUninit<u8>]) = read(buf.spare_capacity_mut()).unwrap();
699        let _x: usize = read(&mut buf).unwrap();
700        let _x: usize = read(&mut *buf).unwrap();
701        let _x: usize = read(&mut buf[..]).unwrap();
702        let _x: usize = read(&mut (*buf)[..]).unwrap();
703
704        let mut buf = [0, 0, 0];
705        let _x: usize = read(&mut buf).unwrap();
706        let _x: usize = read(&mut buf[..]).unwrap();
707
708        let mut buf = vec![0, 0, 0];
709        let _x: usize = read(&mut buf).unwrap();
710        let _x: usize = read(&mut buf[..]).unwrap();
711
712        let mut buf = vec![0, 0, 0].into_boxed_slice();
713        let _x: usize = read(&mut buf).unwrap();
714        let _x: usize = read(&mut buf[..]).unwrap();
715
716        let mut buf = [
717            MaybeUninit::uninit(),
718            MaybeUninit::uninit(),
719            MaybeUninit::uninit(),
720        ];
721        let _x: (&mut [u8], &mut [MaybeUninit<u8>]) = read(&mut buf).unwrap();
722        let _x: (&mut [u8], &mut [MaybeUninit<u8>]) = read(&mut buf[..]).unwrap();
723
724        let mut buf = vec![
725            MaybeUninit::uninit(),
726            MaybeUninit::uninit(),
727            MaybeUninit::uninit(),
728        ];
729        let _x: (&mut [u8], &mut [MaybeUninit<u8>]) = read(&mut buf).unwrap();
730        let _x: (&mut [u8], &mut [MaybeUninit<u8>]) = read(&mut buf[..]).unwrap();
731
732        let mut buf = vec![
733            MaybeUninit::uninit(),
734            MaybeUninit::uninit(),
735            MaybeUninit::uninit(),
736        ]
737        .into_boxed_slice();
738        let _x: (&mut [u8], &mut [MaybeUninit<u8>]) = read(&mut buf).unwrap();
739        let _x: (&mut [u8], &mut [MaybeUninit<u8>]) = read(&mut buf[..]).unwrap();
740
741        let mut buf = Cursor::new(&mut buf);
742        let _x: usize = read(&mut buf).unwrap();
743        let _x: (&mut [u8], &mut [MaybeUninit<u8>]) = buf.finish();
744
745        let mut buf = [0, 0, 0];
746        let mut io_slice = std::io::IoSliceMut::new(&mut buf);
747        let _x: usize = read(&mut io_slice).unwrap();
748        let _x: usize = read(&mut io_slice[..]).unwrap();
749    }
750
751    /// Test passing a `&mut [u8]` to `read`.
752    #[cfg(not(windows))]
753    #[test]
754    fn test_slice() {
755        use std::io::{Seek, SeekFrom};
756
757        // We need to obtain input stream with contents that we can compare
758        // against, so open our own source file.
759        let mut input = std::fs::File::open("src/lib.rs").unwrap();
760
761        let mut buf = [0_u8; 64];
762        let nread = read_all(&input, &mut buf).unwrap();
763        assert_eq!(nread, buf.len());
764        assert_eq!(
765            &buf[..54],
766            b"#![cfg_attr(doc, doc = include_str!(\"../README.md\"))]\n"
767        );
768        input.seek(SeekFrom::End(-1)).unwrap();
769        let nread = read_all(&input, &mut buf).unwrap();
770        assert_eq!(nread, 1);
771        assert_eq!(buf[0], b'\n');
772        input.seek(SeekFrom::End(0)).unwrap();
773        let nread = read_all(&input, &mut buf).unwrap();
774        assert_eq!(nread, 0);
775    }
776
777    /// Test passing a `&mut [MaybeUninit<u8>]` to `read`.
778    #[cfg(not(windows))]
779    #[test]
780    fn test_slice_uninit() {
781        use core::mem::MaybeUninit;
782        use std::io::{Seek, SeekFrom};
783
784        // We need to obtain input stream with contents that we can compare
785        // against, so open our own source file.
786        let mut input = std::fs::File::open("src/lib.rs").unwrap();
787
788        let mut buf = [MaybeUninit::<u8>::uninit(); 64];
789        let (init, uninit) = read_all(&input, &mut buf).unwrap();
790        assert_eq!(uninit.len(), 0);
791        assert_eq!(
792            &init[..54],
793            b"#![cfg_attr(doc, doc = include_str!(\"../README.md\"))]\n"
794        );
795        assert_eq!(init.len(), buf.len());
796        assert_eq!(
797            unsafe { core::mem::transmute::<&mut [MaybeUninit<u8>], &mut [u8]>(&mut buf[..54]) },
798            b"#![cfg_attr(doc, doc = include_str!(\"../README.md\"))]\n"
799        );
800        input.seek(SeekFrom::End(-1)).unwrap();
801        let (init, uninit) = read_all(&input, &mut buf).unwrap();
802        assert_eq!(init.len(), 1);
803        assert_eq!(init[0], b'\n');
804        assert_eq!(uninit.len(), buf.len() - 1);
805        input.seek(SeekFrom::End(0)).unwrap();
806        let (init, uninit) = read_all(&input, &mut buf).unwrap();
807        assert_eq!(init.len(), 0);
808        assert_eq!(uninit.len(), buf.len());
809    }
810
811    /// Test passing a `SpareCapacity` to `read`.
812    #[cfg(not(windows))]
813    #[test]
814    fn test_spare_capacity() {
815        use std::io::{Seek, SeekFrom};
816
817        // We need to obtain input stream with contents that we can compare
818        // against, so open our own source file.
819        let mut input = std::fs::File::open("src/lib.rs").unwrap();
820
821        let mut buf = Vec::with_capacity(64);
822        let nread = read_all(&input, spare_capacity(&mut buf)).unwrap();
823        assert_eq!(nread, buf.capacity());
824        assert_eq!(nread, buf.len());
825        assert_eq!(
826            &buf[..54],
827            b"#![cfg_attr(doc, doc = include_str!(\"../README.md\"))]\n"
828        );
829        buf.clear();
830        input.seek(SeekFrom::End(-1)).unwrap();
831        let nread = read_all(&input, spare_capacity(&mut buf)).unwrap();
832        assert_eq!(nread, 1);
833        assert_eq!(buf.len(), 1);
834        assert_eq!(buf[0], b'\n');
835        buf.clear();
836        input.seek(SeekFrom::End(0)).unwrap();
837        let nread = read_all(&input, spare_capacity(&mut buf)).unwrap();
838        assert_eq!(nread, 0);
839        assert!(buf.is_empty());
840    }
841
842    /// Test passing a `Cursor` to `read`.
843    #[test]
844    fn test_cursor_as_buffer() {
845        use std::io::{Seek, SeekFrom};
846
847        // We need to obtain input stream with contents that we can compare
848        // against, so open our own source file.
849        let mut input = std::fs::File::open("src/lib.rs").unwrap();
850
851        let mut total_read = 0;
852
853        let mut buf = Vec::with_capacity(256);
854        let mut cursor = Cursor::new(spare_capacity(&mut buf));
855        input.seek(SeekFrom::End(-39)).unwrap();
856        let nread = read_all(&input, &mut cursor).unwrap();
857        total_read += nread;
858        assert_eq!(cursor.remaining(), 256 - 39);
859        input.seek(SeekFrom::End(-39)).unwrap();
860        let nread = read_all(&input, &mut cursor).unwrap();
861        total_read += nread;
862        assert_eq!(cursor.remaining(), 256 - 39 * 2);
863        input.seek(SeekFrom::End(-39)).unwrap();
864        let nread = read_all(&input, &mut cursor).unwrap();
865        total_read += nread;
866        assert_eq!(cursor.remaining(), 256 - 39 * 3);
867
868        assert_eq!(total_read, 39 * 3);
869
870        let cursor_read = cursor.finish();
871        assert_eq!(cursor_read, total_read);
872
873        assert_eq!(buf.len(), 39 * 3);
874        assert_eq!(buf.capacity(), 256);
875        assert_eq!(
876            buf,
877            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"
878        );
879    }
880
881    /// Test nesting `Cursor`s inside of `Cursor`s.
882    #[test]
883    fn test_nesting() {
884        use std::io::{Seek, SeekFrom};
885
886        // We need to obtain input stream with contents that we can compare
887        // against, so open our own source file.
888        let mut input = std::fs::File::open("src/lib.rs").unwrap();
889
890        let mut total_read = 0;
891
892        let mut buf = Vec::with_capacity(256);
893        let mut cursor = Cursor::new(spare_capacity(&mut buf));
894        input.seek(SeekFrom::End(-39)).unwrap();
895        let nread = read_all(&input, &mut cursor).unwrap();
896        total_read += nread;
897        assert_eq!(cursor.remaining(), 256 - 39);
898        input.seek(SeekFrom::End(-39)).unwrap();
899        let mut nested_cursor = Cursor::new(&mut cursor);
900        let nested_nread = read_all(&input, &mut nested_cursor).unwrap();
901        assert_eq!(nested_nread, 39);
902        assert_eq!(nested_cursor.remaining(), 256 - 39 * 2);
903        input.seek(SeekFrom::End(-39)).unwrap();
904        let mut nested_nested_cursor = Cursor::new(&mut nested_cursor);
905        let nested_nested_nread = read_all(&input, &mut nested_nested_cursor).unwrap();
906        assert_eq!(nested_nested_nread, 39);
907        assert_eq!(nested_nested_cursor.remaining(), 256 - 39 * 3);
908        let inner_nread = nested_nested_cursor.finish();
909        assert_eq!(inner_nread, 39);
910        assert_eq!(nested_cursor.remaining(), 256 - 39 * 3);
911        let nread = nested_cursor.finish();
912        total_read += nread;
913
914        assert_eq!(total_read, 39 * 3);
915        assert_eq!(cursor.remaining(), 256 - 39 * 3);
916
917        let cursor_read = cursor.finish();
918        assert_eq!(cursor_read, total_read);
919
920        assert_eq!(buf.len(), 39 * 3);
921        assert_eq!(buf.capacity(), 256);
922        assert_eq!(
923            &buf[..39*3],
924            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"
925        );
926    }
927
928    /// Test using a `Cursor` to read into a `MaybeUninit` buffer in multiple
929    /// reads, ultimately producing a single initialized slice.
930    #[test]
931    fn test_incremental() {
932        use std::io::{Seek, SeekFrom};
933
934        // We need to obtain input stream with contents that we can compare
935        // against, so open our own source file.
936        let mut input = std::fs::File::open("src/lib.rs").unwrap();
937
938        let mut total_read = 0;
939
940        let mut buf = [MaybeUninit::<u8>::zeroed(); 256];
941        let mut cursor = Cursor::new(&mut buf);
942        input.seek(SeekFrom::End(-39)).unwrap();
943        let nread = read_all(&input, &mut cursor).unwrap();
944        total_read += nread;
945        assert_eq!(cursor.remaining(), 256 - 39);
946        input.seek(SeekFrom::End(-39)).unwrap();
947        let nread = read_all(&input, &mut cursor).unwrap();
948        total_read += nread;
949        assert_eq!(cursor.remaining(), 256 - 39 * 2);
950        input.seek(SeekFrom::End(-39)).unwrap();
951        let nread = read_all(&input, &mut cursor).unwrap();
952        total_read += nread;
953        assert_eq!(cursor.remaining(), 256 - 39 * 3);
954
955        assert_eq!(total_read, 39 * 3);
956
957        let (init, uninit) = cursor.finish();
958        assert_eq!(init.len(), total_read);
959        assert_eq!(uninit.len(), 256 - total_read);
960
961        assert_eq!(
962            init,
963            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"
964        );
965    }
966
967    /// Test that consecutive `write_slice` calls write at the cursor position.
968    #[test]
969    fn test_write_slice_advances_cursor() {
970        let mut storage = Vec::<u8>::with_capacity(4);
971        let mut cursor = spare_capacity(&mut storage).cursor();
972
973        cursor.write_slice(b"ab");
974        cursor.write_slice(b"cd");
975        assert_eq!(cursor.finish(), 4);
976        assert_eq!(storage, b"abcd");
977    }
978
979    fn read_all<B: Buffer<u8>>(input: &std::fs::File, mut b: B) -> std::io::Result<B::Output> {
980        use std::os::fd::AsRawFd;
981        let mut ptr = b.buffer_ptr();
982        let len = b.buffer_len();
983        let mut filled_len = 0;
984
985        while filled_len < len {
986            let n = unsafe { libc::read(input.as_raw_fd(), ptr.cast(), len - filled_len) };
987            match usize::try_from(n) {
988                Ok(0) => break,
989                Ok(n) => {
990                    filled_len += n;
991                    assert!(filled_len <= len);
992                    ptr = unsafe { ptr.add(n) };
993                }
994                Err(_) => return Err(std::io::Error::last_os_error()),
995            }
996        }
997
998        Ok(unsafe { b.assume_init(filled_len) })
999    }
1000}
1001
1002// The comment at the end of the file!