Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

rust: str: introduce `NullTerminatedFormatter`

Add `NullTerminatedFormatter`, 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.

Reviewed-by: Alice Ryhl <aliceryhl@google.com>
Reviewed-by: Daniel Almeida <daniel.almeida@collabora.com>
Signed-off-by: Andreas Hindborg <a.hindborg@kernel.org>
Link: https://lore.kernel.org/r/20250902-rnull-up-v6-16-v7-4-b5212cc89b98@kernel.org
Signed-off-by: Jens Axboe <axboe@kernel.dk>

authored by

Andreas Hindborg and committed by
Jens Axboe
cdde7a19 8c5ac71c

+49
+49
rust/kernel/str.rs
··· 871 871 } 872 872 } 873 873 874 + /// A mutable reference to a byte buffer where a string can be written into. 875 + /// 876 + /// The buffer will be automatically null terminated after the last written character. 877 + /// 878 + /// # Invariants 879 + /// 880 + /// * The first byte of `buffer` is always zero. 881 + /// * The length of `buffer` is at least 1. 882 + pub(crate) struct NullTerminatedFormatter<'a> { 883 + buffer: &'a mut [u8], 884 + } 885 + 886 + impl<'a> NullTerminatedFormatter<'a> { 887 + /// Create a new [`Self`] instance. 888 + #[expect(dead_code)] 889 + pub(crate) fn new(buffer: &'a mut [u8]) -> Option<NullTerminatedFormatter<'a>> { 890 + *(buffer.first_mut()?) = 0; 891 + 892 + // INVARIANT: 893 + // - We wrote zero to the first byte above. 894 + // - If buffer was not at least length 1, `buffer.first_mut()` would return None. 895 + Some(Self { buffer }) 896 + } 897 + } 898 + 899 + impl Write for NullTerminatedFormatter<'_> { 900 + fn write_str(&mut self, s: &str) -> fmt::Result { 901 + let bytes = s.as_bytes(); 902 + let len = bytes.len(); 903 + 904 + // We want space for a zero. By type invariant, buffer length is always at least 1, so no 905 + // underflow. 906 + if len > self.buffer.len() - 1 { 907 + return Err(fmt::Error); 908 + } 909 + 910 + let buffer = core::mem::take(&mut self.buffer); 911 + // We break the zero start invariant for a short while. 912 + buffer[..len].copy_from_slice(bytes); 913 + // INVARIANT: We checked above that buffer will have size at least 1 after this assignment. 914 + self.buffer = &mut buffer[len..]; 915 + 916 + // INVARIANT: We write zero to the first byte of the buffer. 917 + self.buffer[0] = 0; 918 + 919 + Ok(()) 920 + } 921 + } 922 + 874 923 /// An owned string that is guaranteed to have exactly one `NUL` byte, which is at the end. 875 924 /// 876 925 /// Used for interoperability with kernel APIs that take C strings.