[PATCH v2 03/14] rust: str: introduce `NullBorrowFormatter`

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Add `NullBorrowFormatter`, a formatter that writes a null terminated string
to an array or slice buffer. Because this type needs to manage the trailing
null marker, the existing formatters cannot be used to implement this type.

Signed-off-by: Andreas Hindborg <a.hindborg@xxxxxxxxxx>
---
 rust/kernel/str.rs | 59 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 59 insertions(+)

diff --git a/rust/kernel/str.rs b/rust/kernel/str.rs
index 78b2f95eb3171..05d79cf40c201 100644
--- a/rust/kernel/str.rs
+++ b/rust/kernel/str.rs
@@ -860,6 +860,65 @@ fn deref_mut(&mut self) -> &mut Self::Target {
     }
 }
 
+/// A mutable reference to a byte buffer where a string can be written into.
+///
+/// The buffer will be automatically null terminated after the last written character.
+///
+/// # Invariants
+///
+/// `buffer` is always null terminated.
+pub(crate) struct NullBorrowFormatter<'a> {
+    buffer: &'a mut [u8],
+    pos: usize,
+}
+
+impl<'a> NullBorrowFormatter<'a> {
+    /// Create a new [`Self`] instance.
+    pub(crate) fn new(buffer: &'a mut [u8]) -> Result<NullBorrowFormatter<'a>> {
+        *(buffer.first_mut().ok_or(EINVAL)?) = 0;
+
+        // INVARIANT: We null terminated the buffer above.
+        Ok(Self { buffer, pos: 0 })
+    }
+
+    #[expect(dead_code)]
+    pub(crate) fn from_array<const N: usize>(
+        a: &'a mut [crate::ffi::c_char; N],
+    ) -> Result<NullBorrowFormatter<'a>> {
+        Self::new(
+            // SAFETY: the buffer of `a` is valid for read and write as `u8` for
+            // at least `N` bytes.
+            unsafe { core::slice::from_raw_parts_mut(a.as_mut_ptr().cast::<u8>(), N) },
+        )
+    }
+
+    /// Return the position of the write pointer in the underlying buffer.
+    #[expect(dead_code)]
+    pub(crate) fn pos(&self) -> usize {
+        self.pos
+    }
+}
+
+impl Write for NullBorrowFormatter<'_> {
+    fn write_str(&mut self, s: &str) -> fmt::Result {
+        let bytes = s.as_bytes();
+        let len = bytes.len();
+
+        // We want space for a null terminator
+        if self.pos + len > self.buffer.len() - 1 {
+            return Err(fmt::Error);
+        }
+
+        self.buffer[self.pos..self.pos + len].copy_from_slice(bytes);
+        self.pos += len;
+
+        // INVARIANT: The buffer is null terminated.
+        self.buffer[self.pos] = 0;
+
+        Ok(())
+    }
+}
+
 /// An owned string that is guaranteed to have exactly one `NUL` byte, which is at the end.
 ///
 /// Used for interoperability with kernel APIs that take C strings.

-- 
2.47.2






[Index of Archives]     [Linux RAID]     [Linux SCSI]     [Linux ATA RAID]     [IDE]     [Linux Wireless]     [Linux Kernel]     [ATH6KL]     [Linux Bluetooth]     [Linux Netdev]     [Kernel Newbies]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Device Mapper]

  Powered by Linux