56 lines · rust
1// SPDX-License-Identifier: GPL-2.02 3use core::fmt::{self, Write};4 5use crate::error::Result;6use crate::prelude::EINVAL;7 8/// A mutable reference to a byte buffer where a string can be written into.9///10/// # Invariants11///12/// `buffer` is always null terminated.13pub(crate) struct RawWriter<'a> {14 buffer: &'a mut [u8],15 pos: usize,16}17 18impl<'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` for32 // at least `N` bytes.33 unsafe { core::slice::from_raw_parts_mut(a.as_mut_ptr().cast::<u8>(), N) },34 )35 }36}37 38impl 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 terminator44 if self.pos + len > self.buffer.len() - 1 {45 return Err(fmt::Error);46 }47 48 // INVARIANT: We are not overwriting the last byte49 self.buffer[self.pos..self.pos + len].copy_from_slice(bytes);50 51 self.pos += len;52 53 Ok(())54 }55}56