#![allow(unsafe_code)]
#[cfg(feature = "alloc")]
use alloc::vec::Vec;
use core::mem::MaybeUninit;
use core::slice;
pub trait Buffer<T>: private::Sealed<T> {}
impl<T> Buffer<T> for &mut [T] {}
impl<T, const N: usize> Buffer<T> for &mut [T; N] {}
#[cfg(feature = "alloc")]
impl<T> Buffer<T> for &mut Vec<T> {}
impl<T> Buffer<T> for &mut [MaybeUninit<T>] {}
impl<T, const N: usize> Buffer<T> for &mut [MaybeUninit<T>; N] {}
#[cfg(feature = "alloc")]
impl<T> Buffer<T> for &mut Vec<MaybeUninit<T>> {}
#[cfg(feature = "alloc")]
impl<'a, T> Buffer<T> for SpareCapacity<'a, T> {}
impl<T> private::Sealed<T> for &mut [T] {
type Output = usize;
#[inline]
fn parts_mut(&mut self) -> (*mut T, usize) {
(self.as_mut_ptr(), self.len())
}
#[inline]
unsafe fn assume_init(self, len: usize) -> Self::Output {
len
}
}
impl<T, const N: usize> private::Sealed<T> for &mut [T; N] {
type Output = usize;
#[inline]
fn parts_mut(&mut self) -> (*mut T, usize) {
(self.as_mut_ptr(), N)
}
#[inline]
unsafe fn assume_init(self, len: usize) -> Self::Output {
len
}
}
#[cfg(feature = "alloc")]
impl<T> private::Sealed<T> for &mut Vec<T> {
type Output = usize;
#[inline]
fn parts_mut(&mut self) -> (*mut T, usize) {
(self.as_mut_ptr(), self.len())
}
#[inline]
unsafe fn assume_init(self, len: usize) -> Self::Output {
len
}
}
impl<'a, T> private::Sealed<T> for &'a mut [MaybeUninit<T>] {
type Output = (&'a mut [T], &'a mut [MaybeUninit<T>]);
#[inline]
fn parts_mut(&mut self) -> (*mut T, usize) {
(self.as_mut_ptr().cast(), self.len())
}
#[inline]
unsafe fn assume_init(self, len: usize) -> Self::Output {
let (init, uninit) = self.split_at_mut(len);
let init = slice::from_raw_parts_mut(init.as_mut_ptr().cast::<T>(), init.len());
(init, uninit)
}
}
impl<'a, T, const N: usize> private::Sealed<T> for &'a mut [MaybeUninit<T>; N] {
type Output = (&'a mut [T], &'a mut [MaybeUninit<T>]);
#[inline]
fn parts_mut(&mut self) -> (*mut T, usize) {
(self.as_mut_ptr().cast(), self.len())
}
#[inline]
unsafe fn assume_init(self, len: usize) -> Self::Output {
let (init, uninit) = self.split_at_mut(len);
let init = slice::from_raw_parts_mut(init.as_mut_ptr().cast::<T>(), init.len());
(init, uninit)
}
}
#[cfg(feature = "alloc")]
impl<'a, T> private::Sealed<T> for &'a mut Vec<MaybeUninit<T>> {
type Output = (&'a mut [T], &'a mut [MaybeUninit<T>]);
#[inline]
fn parts_mut(&mut self) -> (*mut T, usize) {
(self.as_mut_ptr().cast(), self.len())
}
#[inline]
unsafe fn assume_init(self, len: usize) -> Self::Output {
let (init, uninit) = self.split_at_mut(len);
let init = slice::from_raw_parts_mut(init.as_mut_ptr().cast::<T>(), init.len());
(init, uninit)
}
}
#[cfg(feature = "alloc")]
#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
pub struct SpareCapacity<'a, T>(&'a mut Vec<T>);
#[cfg(feature = "alloc")]
#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
pub fn spare_capacity<'a, T>(v: &'a mut Vec<T>) -> SpareCapacity<'a, T> {
debug_assert_ne!(
v.capacity(),
0,
"`extend` uses spare capacity, and never allocates new memory, so the `Vec` passed to it \
should have some spare capacity."
);
SpareCapacity(v)
}
#[cfg(feature = "alloc")]
impl<'a, T> private::Sealed<T> for SpareCapacity<'a, T> {
type Output = usize;
#[inline]
fn parts_mut(&mut self) -> (*mut T, usize) {
let spare = self.0.spare_capacity_mut();
(spare.as_mut_ptr().cast(), spare.len())
}
#[inline]
unsafe fn assume_init(self, len: usize) -> Self::Output {
self.0.set_len(self.0.len() + len);
len
}
}
mod private {
pub trait Sealed<T> {
type Output;
fn parts_mut(&mut self) -> (*mut T, usize);
#[must_use]
unsafe fn assume_init(self, len: usize) -> Self::Output;
}
}
#[cfg(test)]
mod tests {
#[allow(unused_imports)]
use super::*;
#[cfg(not(windows))]
#[test]
fn test_compilation() {
use crate::io::read;
use core::mem::MaybeUninit;
let input = std::fs::File::open("src/buffer.rs").unwrap();
let mut buf = vec![0_u8; 3];
buf.reserve(32);
let _x: usize = read(&input, spare_capacity(&mut buf)).unwrap();
let _x: (&mut [u8], &mut [MaybeUninit<u8>]) =
read(&input, buf.spare_capacity_mut()).unwrap();
let _x: usize = read(&input, &mut buf).unwrap();
let _x: usize = read(&input, &mut *buf).unwrap();
let _x: usize = read(&input, &mut buf[..]).unwrap();
let _x: usize = read(&input, &mut (*buf)[..]).unwrap();
let mut buf = [0, 0, 0];
let _x: usize = read(&input, &mut buf).unwrap();
let _x: usize = read(&input, &mut buf[..]).unwrap();
let mut buf = [
MaybeUninit::uninit(),
MaybeUninit::uninit(),
MaybeUninit::uninit(),
];
let _x: (&mut [u8], &mut [MaybeUninit<u8>]) = read(&input, &mut buf).unwrap();
let _x: (&mut [u8], &mut [MaybeUninit<u8>]) = read(&input, &mut buf[..]).unwrap();
let mut buf = vec![
MaybeUninit::uninit(),
MaybeUninit::uninit(),
MaybeUninit::uninit(),
];
let _x: (&mut [u8], &mut [MaybeUninit<u8>]) = read(&input, &mut buf).unwrap();
let _x: (&mut [u8], &mut [MaybeUninit<u8>]) = read(&input, &mut buf[..]).unwrap();
}
#[cfg(not(windows))]
#[test]
fn test_slice() {
use crate::io::read;
use std::io::{Seek, SeekFrom};
let mut input = std::fs::File::open("src/buffer.rs").unwrap();
let mut buf = [0_u8; 64];
let nread = read(&input, &mut buf).unwrap();
assert_eq!(nread, buf.len());
assert_eq!(
&buf[..58],
b"//! Utilities for functions that return data via buffers.\n"
);
input.seek(SeekFrom::End(-1)).unwrap();
let nread = read(&input, &mut buf).unwrap();
assert_eq!(nread, 1);
input.seek(SeekFrom::End(0)).unwrap();
let nread = read(&input, &mut buf).unwrap();
assert_eq!(nread, 0);
}
#[cfg(not(windows))]
#[test]
fn test_slice_uninit() {
use crate::io::read;
use core::mem::MaybeUninit;
use std::io::{Seek, SeekFrom};
let mut input = std::fs::File::open("src/buffer.rs").unwrap();
let mut buf = [MaybeUninit::<u8>::uninit(); 64];
let (init, uninit) = read(&input, &mut buf).unwrap();
assert_eq!(uninit.len(), 0);
assert_eq!(
&init[..58],
b"//! Utilities for functions that return data via buffers.\n"
);
assert_eq!(init.len(), buf.len());
assert_eq!(
unsafe { core::mem::transmute::<&mut [MaybeUninit<u8>], &mut [u8]>(&mut buf[..58]) },
b"//! Utilities for functions that return data via buffers.\n"
);
input.seek(SeekFrom::End(-1)).unwrap();
let (init, uninit) = read(&input, &mut buf).unwrap();
assert_eq!(init.len(), 1);
assert_eq!(uninit.len(), buf.len() - 1);
input.seek(SeekFrom::End(0)).unwrap();
let (init, uninit) = read(&input, &mut buf).unwrap();
assert_eq!(init.len(), 0);
assert_eq!(uninit.len(), buf.len());
}
#[cfg(not(windows))]
#[test]
fn test_spare_capacity() {
use crate::io::read;
use std::io::{Seek, SeekFrom};
let mut input = std::fs::File::open("src/buffer.rs").unwrap();
let mut buf = Vec::with_capacity(64);
let nread = read(&input, spare_capacity(&mut buf)).unwrap();
assert_eq!(nread, buf.capacity());
assert_eq!(nread, buf.len());
assert_eq!(
&buf[..58],
b"//! Utilities for functions that return data via buffers.\n"
);
buf.clear();
input.seek(SeekFrom::End(-1)).unwrap();
let nread = read(&input, spare_capacity(&mut buf)).unwrap();
assert_eq!(nread, 1);
assert_eq!(buf.len(), 1);
buf.clear();
input.seek(SeekFrom::End(0)).unwrap();
let nread = read(&input, spare_capacity(&mut buf)).unwrap();
assert_eq!(nread, 0);
assert!(buf.is_empty());
}
}