rustix/
buffer.rs

1//! Utilities to help with buffering.
2
3#![allow(unsafe_code)]
4
5use core::mem::MaybeUninit;
6use core::slice;
7
8/// Split an uninitialized byte slice into initialized and uninitialized parts.
9///
10/// # Safety
11///
12/// `init_len` must not be greater than `buf.len()`, and at least `init_len`
13/// bytes must be initialized.
14#[inline]
15pub(super) unsafe fn split_init(
16    buf: &mut [MaybeUninit<u8>],
17    init_len: usize,
18) -> (&mut [u8], &mut [MaybeUninit<u8>]) {
19    debug_assert!(init_len <= buf.len());
20    let buf_ptr = buf.as_mut_ptr();
21    let uninit_len = buf.len() - init_len;
22    let init = slice::from_raw_parts_mut(buf_ptr.cast::<u8>(), init_len);
23    let uninit = slice::from_raw_parts_mut(buf_ptr.add(init_len), uninit_len);
24    (init, uninit)
25}
26
27#[cfg(test)]
28mod tests {
29    use super::*;
30
31    #[test]
32    fn test_split_init() {
33        let mut input_array = [
34            MaybeUninit::new(0_u8),
35            MaybeUninit::new(1_u8),
36            MaybeUninit::new(2_u8),
37            MaybeUninit::new(3_u8),
38        ];
39        let input_array_clone = input_array.clone();
40        let input_array_ptr = input_array.as_ptr();
41        let output_array = [0_u8, 1_u8, 2_u8, 3_u8];
42
43        unsafe {
44            let (init, uninit) = split_init(&mut input_array, 0);
45            assert_eq!(init, &[]);
46            assert_eq!(uninit.len(), input_array_clone.len());
47            assert_eq!(uninit.as_ptr(), input_array_ptr);
48
49            let (init, uninit) = split_init(&mut input_array, input_array_clone.len());
50            assert_eq!(init, &output_array[..]);
51            assert_eq!(init.as_ptr(), input_array_ptr.cast());
52            assert_eq!(uninit.len(), 0);
53            assert_eq!(
54                uninit.as_ptr(),
55                input_array_ptr.add(input_array_clone.len())
56            );
57
58            let (init, uninit) = split_init(&mut input_array, 2);
59            assert_eq!(init, &output_array[..2]);
60            assert_eq!(init.as_ptr(), input_array_ptr.cast());
61            assert_eq!(uninit.len(), 2);
62            assert_eq!(uninit.as_ptr(), input_array_ptr.add(2));
63        }
64    }
65
66    #[test]
67    fn test_split_init_empty() {
68        unsafe {
69            let (init, uninit) = split_init(&mut [], 0);
70            assert!(init.is_empty());
71            assert!(uninit.is_empty());
72        }
73    }
74}