1#![allow(unsafe_code)]
4
5#[cfg(feature = "alloc")]
6use alloc::vec::Vec;
7use core::mem::MaybeUninit;
8use core::slice;
9
10pub trait Buffer<T>: private::Sealed<T> {}
96
97impl<T> Buffer<T> for &mut [T] {}
99impl<T, const N: usize> Buffer<T> for &mut [T; N] {}
100#[cfg(feature = "alloc")]
101impl<T> Buffer<T> for &mut Vec<T> {}
102impl<T> Buffer<T> for &mut [MaybeUninit<T>] {}
103impl<T, const N: usize> Buffer<T> for &mut [MaybeUninit<T>; N] {}
104#[cfg(feature = "alloc")]
105impl<T> Buffer<T> for &mut Vec<MaybeUninit<T>> {}
106#[cfg(feature = "alloc")]
107impl<'a, T> Buffer<T> for SpareCapacity<'a, T> {}
108
109impl<T> private::Sealed<T> for &mut [T] {
110 type Output = usize;
111
112 #[inline]
113 fn parts_mut(&mut self) -> (*mut T, usize) {
114 (self.as_mut_ptr(), self.len())
115 }
116
117 #[inline]
118 unsafe fn assume_init(self, len: usize) -> Self::Output {
119 len
120 }
121}
122
123impl<T, const N: usize> private::Sealed<T> for &mut [T; N] {
124 type Output = usize;
125
126 #[inline]
127 fn parts_mut(&mut self) -> (*mut T, usize) {
128 (self.as_mut_ptr(), N)
129 }
130
131 #[inline]
132 unsafe fn assume_init(self, len: usize) -> Self::Output {
133 len
134 }
135}
136
137#[cfg(feature = "alloc")]
141impl<T> private::Sealed<T> for &mut Vec<T> {
142 type Output = usize;
143
144 #[inline]
145 fn parts_mut(&mut self) -> (*mut T, usize) {
146 (self.as_mut_ptr(), self.len())
147 }
148
149 #[inline]
150 unsafe fn assume_init(self, len: usize) -> Self::Output {
151 len
152 }
153}
154
155impl<'a, T> private::Sealed<T> for &'a mut [MaybeUninit<T>] {
156 type Output = (&'a mut [T], &'a mut [MaybeUninit<T>]);
157
158 #[inline]
159 fn parts_mut(&mut self) -> (*mut T, usize) {
160 (self.as_mut_ptr().cast(), self.len())
161 }
162
163 #[inline]
164 unsafe fn assume_init(self, len: usize) -> Self::Output {
165 let (init, uninit) = self.split_at_mut(len);
166
167 let init = slice::from_raw_parts_mut(init.as_mut_ptr().cast::<T>(), init.len());
169
170 (init, uninit)
171 }
172}
173
174impl<'a, T, const N: usize> private::Sealed<T> for &'a mut [MaybeUninit<T>; N] {
175 type Output = (&'a mut [T], &'a mut [MaybeUninit<T>]);
176
177 #[inline]
178 fn parts_mut(&mut self) -> (*mut T, usize) {
179 (self.as_mut_ptr().cast(), self.len())
180 }
181
182 #[inline]
183 unsafe fn assume_init(self, len: usize) -> Self::Output {
184 let (init, uninit) = self.split_at_mut(len);
185
186 let init = slice::from_raw_parts_mut(init.as_mut_ptr().cast::<T>(), init.len());
188
189 (init, uninit)
190 }
191}
192
193#[cfg(feature = "alloc")]
194impl<'a, T> private::Sealed<T> for &'a mut Vec<MaybeUninit<T>> {
195 type Output = (&'a mut [T], &'a mut [MaybeUninit<T>]);
196
197 #[inline]
198 fn parts_mut(&mut self) -> (*mut T, usize) {
199 (self.as_mut_ptr().cast(), self.len())
200 }
201
202 #[inline]
203 unsafe fn assume_init(self, len: usize) -> Self::Output {
204 let (init, uninit) = self.split_at_mut(len);
205
206 let init = slice::from_raw_parts_mut(init.as_mut_ptr().cast::<T>(), init.len());
208
209 (init, uninit)
210 }
211}
212
213#[cfg(feature = "alloc")]
221#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
222pub struct SpareCapacity<'a, T>(&'a mut Vec<T>);
223
224#[cfg(feature = "alloc")]
254#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
255pub fn spare_capacity<'a, T>(v: &'a mut Vec<T>) -> SpareCapacity<'a, T> {
256 debug_assert_ne!(
257 v.capacity(),
258 0,
259 "`extend` uses spare capacity, and never allocates new memory, so the `Vec` passed to it \
260 should have some spare capacity."
261 );
262
263 SpareCapacity(v)
264}
265
266#[cfg(feature = "alloc")]
267impl<'a, T> private::Sealed<T> for SpareCapacity<'a, T> {
268 type Output = usize;
272
273 #[inline]
274 fn parts_mut(&mut self) -> (*mut T, usize) {
275 let spare = self.0.spare_capacity_mut();
276 (spare.as_mut_ptr().cast(), spare.len())
277 }
278
279 #[inline]
280 unsafe fn assume_init(self, len: usize) -> Self::Output {
281 self.0.set_len(self.0.len() + len);
283 len
284 }
285}
286
287mod private {
288 pub trait Sealed<T> {
289 type Output;
291
292 fn parts_mut(&mut self) -> (*mut T, usize);
300
301 unsafe fn assume_init(self, len: usize) -> Self::Output;
307 }
308}
309
310#[cfg(test)]
311mod tests {
312 #[allow(unused_imports)]
313 use super::*;
314
315 #[cfg(not(windows))]
316 #[test]
317 fn test_compilation() {
318 use crate::io::read;
319 use core::mem::MaybeUninit;
320
321 let input = std::fs::File::open("Cargo.toml").unwrap();
322
323 let mut buf = vec![0_u8; 3];
324 buf.reserve(32);
325 let _x: usize = read(&input, spare_capacity(&mut buf)).unwrap();
326 let _x: (&mut [u8], &mut [MaybeUninit<u8>]) =
327 read(&input, buf.spare_capacity_mut()).unwrap();
328 let _x: usize = read(&input, &mut buf).unwrap();
329 let _x: usize = read(&input, &mut *buf).unwrap();
330 let _x: usize = read(&input, &mut buf[..]).unwrap();
331 let _x: usize = read(&input, &mut (*buf)[..]).unwrap();
332
333 let mut buf = [0, 0, 0];
334 let _x: usize = read(&input, &mut buf).unwrap();
335 let _x: usize = read(&input, &mut buf[..]).unwrap();
336
337 let mut buf = [
338 MaybeUninit::uninit(),
339 MaybeUninit::uninit(),
340 MaybeUninit::uninit(),
341 ];
342 let _x: (&mut [u8], &mut [MaybeUninit<u8>]) = read(&input, &mut buf).unwrap();
343 let _x: (&mut [u8], &mut [MaybeUninit<u8>]) = read(&input, &mut buf[..]).unwrap();
344
345 let mut buf = vec![
346 MaybeUninit::uninit(),
347 MaybeUninit::uninit(),
348 MaybeUninit::uninit(),
349 ];
350 let _x: (&mut [u8], &mut [MaybeUninit<u8>]) = read(&input, &mut buf).unwrap();
351 let _x: (&mut [u8], &mut [MaybeUninit<u8>]) = read(&input, &mut buf[..]).unwrap();
352 }
353
354 #[cfg(not(windows))]
355 #[test]
356 fn test_slice() {
357 use crate::io::read;
358 use std::io::{Seek, SeekFrom};
359
360 let mut input = std::fs::File::open("Cargo.toml").unwrap();
361
362 let mut buf = [0_u8; 64];
363 let nread = read(&input, &mut buf).unwrap();
364 assert_eq!(nread, buf.len());
365 assert_eq!(&buf[..9], b"[package]");
366 input.seek(SeekFrom::End(-1)).unwrap();
367 let nread = read(&input, &mut buf).unwrap();
368 assert_eq!(nread, 1);
369 input.seek(SeekFrom::End(0)).unwrap();
370 let nread = read(&input, &mut buf).unwrap();
371 assert_eq!(nread, 0);
372 }
373
374 #[cfg(not(windows))]
375 #[test]
376 fn test_slice_uninit() {
377 use crate::io::read;
378 use core::mem::MaybeUninit;
379 use std::io::{Seek, SeekFrom};
380
381 let mut input = std::fs::File::open("Cargo.toml").unwrap();
382
383 let mut buf = [MaybeUninit::<u8>::uninit(); 64];
384 let (init, uninit) = read(&input, &mut buf).unwrap();
385 assert_eq!(uninit.len(), 0);
386 assert_eq!(&init[..9], b"[package]");
387 assert_eq!(init.len(), buf.len());
388 assert_eq!(
389 unsafe { core::mem::transmute::<&mut [MaybeUninit<u8>], &mut [u8]>(&mut buf[..9]) },
390 b"[package]"
391 );
392 input.seek(SeekFrom::End(-1)).unwrap();
393 let (init, uninit) = read(&input, &mut buf).unwrap();
394 assert_eq!(init.len(), 1);
395 assert_eq!(uninit.len(), buf.len() - 1);
396 input.seek(SeekFrom::End(0)).unwrap();
397 let (init, uninit) = read(&input, &mut buf).unwrap();
398 assert_eq!(init.len(), 0);
399 assert_eq!(uninit.len(), buf.len());
400 }
401
402 #[cfg(not(windows))]
403 #[test]
404 fn test_spare_capacity() {
405 use crate::io::read;
406 use std::io::{Seek, SeekFrom};
407
408 let mut input = std::fs::File::open("Cargo.toml").unwrap();
409
410 let mut buf = Vec::with_capacity(64);
411 let nread = read(&input, spare_capacity(&mut buf)).unwrap();
412 assert_eq!(nread, buf.capacity());
413 assert_eq!(nread, buf.len());
414 assert_eq!(&buf[..9], b"[package]");
415 buf.clear();
416 input.seek(SeekFrom::End(-1)).unwrap();
417 let nread = read(&input, spare_capacity(&mut buf)).unwrap();
418 assert_eq!(nread, 1);
419 assert_eq!(buf.len(), 1);
420 buf.clear();
421 input.seek(SeekFrom::End(0)).unwrap();
422 let nread = read(&input, spare_capacity(&mut buf)).unwrap();
423 assert_eq!(nread, 0);
424 assert!(buf.is_empty());
425 }
426}