• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 use super::LOGGING_TAG_MAX_LEN;
2 use std::ffi::CStr;
3 use std::mem::MaybeUninit;
4 
5 // FIXME: When `maybe_uninit_uninit_array` is stabilized, use it instead of this helper
uninit_array<const N: usize, T>() -> [MaybeUninit<T>; N]6 pub fn uninit_array<const N: usize, T>() -> [MaybeUninit<T>; N] {
7     // SAFETY: Array contains MaybeUninit, which is fine to be uninit
8     unsafe { MaybeUninit::uninit().assume_init() }
9 }
10 
11 // FIXME: Remove when maybe_uninit_slice is stabilized to provide MaybeUninit::slice_assume_init_ref()
slice_assume_init_ref<T>(slice: &[MaybeUninit<T>]) -> &[T]12 pub unsafe fn slice_assume_init_ref<T>(slice: &[MaybeUninit<T>]) -> &[T] {
13     &*(slice as *const [MaybeUninit<T>] as *const [T])
14 }
15 
16 /// Fills up `storage` with `tag` and a necessary NUL terminator, optionally ellipsizing the input
17 /// `tag` if it's too large.
18 ///
19 /// Returns a [`CStr`] containing the initialized portion of `storage`, including its NUL
20 /// terminator.
fill_tag_bytes<'a>( storage: &'a mut [MaybeUninit<u8>; LOGGING_TAG_MAX_LEN + 1], tag: &[u8], ) -> &'a CStr21 pub fn fill_tag_bytes<'a>(
22     storage: &'a mut [MaybeUninit<u8>; LOGGING_TAG_MAX_LEN + 1],
23     tag: &[u8],
24 ) -> &'a CStr {
25     // FIXME: Simplify when maybe_uninit_fill with MaybeUninit::fill_from() is stabilized
26     let initialized = if tag.len() > LOGGING_TAG_MAX_LEN {
27         for (input, output) in tag
28             .iter()
29             // Elipsize the last two characters (TODO: use special … character)?
30             .take(LOGGING_TAG_MAX_LEN - 2)
31             .chain(b"..\0")
32             .zip(storage.iter_mut())
33         {
34             output.write(*input);
35         }
36         storage.as_slice()
37     } else {
38         for (input, output) in tag.iter().chain(b"\0").zip(storage.iter_mut()) {
39             output.write(*input);
40         }
41         &storage[..tag.len() + 1]
42     };
43 
44     // SAFETY: The above code ensures that `initialized` only refers to a portion of the `array`
45     // slice that was initialized, thus it is safe to cast those `MaybeUninit<u8>`s to `u8`:
46     let initialized = unsafe { slice_assume_init_ref(initialized) };
47     CStr::from_bytes_with_nul(initialized).expect("Unreachable: we wrote a nul terminator")
48 }
49