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!