Linux Audio

Check our new training course

Loading...
Note: File does not exist in v4.10.11.
 1// SPDX-License-Identifier: GPL-2.0
 2
 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/// # Invariants
11///
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 [crate::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
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 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}