| 1 | //! Utilities to help with buffering. |
| 2 | |
| 3 | #![allow (unsafe_code)] |
| 4 | |
| 5 | use core::mem::MaybeUninit; |
| 6 | use 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 ] |
| 15 | pub(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: *mut MaybeUninit = buf.as_mut_ptr(); |
| 21 | let uninit_len: usize = buf.len() - init_len; |
| 22 | let init: &mut [u8] = slice::from_raw_parts_mut(data:buf_ptr.cast::<u8>(), init_len); |
| 23 | let uninit: &mut [MaybeUninit] = slice::from_raw_parts_mut(data:buf_ptr.add(count:init_len), uninit_len); |
| 24 | (init, uninit) |
| 25 | } |
| 26 | |
| 27 | #[cfg (test)] |
| 28 | mod 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 | } |
| 75 | |