xref: /linux/rust/kernel/block/mq/raw_writer.rs (revision c532de5a67a70f8533d495f8f2aaa9a0491c3ad0)
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