1 // SPDX-License-Identifier: GPL-2.0 2 3 use core::fmt::{self, Write}; 4 5 use crate::error::Result; 6 use crate::prelude::EINVAL; 7 8 /// A mutable reference to a byte buffer where a string can be written into. 9 /// 10 /// # Invariants 11 /// 12 /// `buffer` is always null terminated. 13 pub(crate) struct RawWriter<'a> { 14 buffer: &'a mut [u8], 15 pos: usize, 16 } 17 18 impl<'a> RawWriter<'a> { 19 /// Create a new `RawWriter` instance. 20 fn new(buffer: &'a mut [u8]) -> Result<RawWriter<'a>> { 21 *(buffer.last_mut().ok_or(EINVAL)?) = 0; 22 23 // INVARIANT: We null terminated the buffer above. 24 Ok(Self { buffer, pos: 0 }) 25 } 26 27 pub(crate) fn from_array<const N: usize>( 28 a: &'a mut [core::ffi::c_char; N], 29 ) -> Result<RawWriter<'a>> { 30 Self::new( 31 // SAFETY: the buffer of `a` is valid for read and write as `u8` for 32 // at least `N` bytes. 33 unsafe { core::slice::from_raw_parts_mut(a.as_mut_ptr().cast::<u8>(), N) }, 34 ) 35 } 36 } 37 38 impl Write for RawWriter<'_> { 39 fn write_str(&mut self, s: &str) -> fmt::Result { 40 let bytes = s.as_bytes(); 41 let len = bytes.len(); 42 43 // We do not want to overwrite our null terminator 44 if self.pos + len > self.buffer.len() - 1 { 45 return Err(fmt::Error); 46 } 47 48 // INVARIANT: We are not overwriting the last byte 49 self.buffer[self.pos..self.pos + len].copy_from_slice(bytes); 50 51 self.pos += len; 52 53 Ok(()) 54 } 55 } 56