From fffed679eeea119c8f972954518c142ec95bda4a Mon Sep 17 00:00:00 2001 From: Wedson Almeida Filho Date: Thu, 10 Nov 2022 17:41:32 +0100 Subject: rust: str: add `Formatter` type Add the `Formatter` type, which leverages `RawFormatter`, but fails if callers attempt to write more than will fit in the buffer. In order to so, implement the `RawFormatter::from_buffer()` constructor as well. Co-developed-by: Adam Bratschi-Kaye Signed-off-by: Adam Bratschi-Kaye Signed-off-by: Wedson Almeida Filho Reviewed-by: Gary Guo [Reworded, adapted for upstream and applied latest changes] Signed-off-by: Miguel Ojeda --- rust/kernel/str.rs | 57 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) (limited to 'rust/kernel') diff --git a/rust/kernel/str.rs b/rust/kernel/str.rs index a995db36486f..ce207d1b3d2a 100644 --- a/rust/kernel/str.rs +++ b/rust/kernel/str.rs @@ -406,6 +406,23 @@ impl RawFormatter { } } + /// Creates a new instance of [`RawFormatter`] with the given buffer. + /// + /// # Safety + /// + /// The memory region starting at `buf` and extending for `len` bytes must be valid for writes + /// for the lifetime of the returned [`RawFormatter`]. + pub(crate) unsafe fn from_buffer(buf: *mut u8, len: usize) -> Self { + let pos = buf as usize; + // INVARIANT: We ensure that `end` is never less then `buf`, and the safety requirements + // guarantees that the memory region is valid for writes. + Self { + pos, + beg: pos, + end: pos.saturating_add(len), + } + } + /// Returns the current insert position. /// /// N.B. It may point to invalid memory. @@ -439,3 +456,43 @@ impl fmt::Write for RawFormatter { Ok(()) } } + +/// Allows formatting of [`fmt::Arguments`] into a raw buffer. +/// +/// Fails if callers attempt to write more than will fit in the buffer. +pub(crate) struct Formatter(RawFormatter); + +impl Formatter { + /// Creates a new instance of [`Formatter`] with the given buffer. + /// + /// # Safety + /// + /// The memory region starting at `buf` and extending for `len` bytes must be valid for writes + /// for the lifetime of the returned [`Formatter`]. + #[allow(dead_code)] + pub(crate) unsafe fn from_buffer(buf: *mut u8, len: usize) -> Self { + // SAFETY: The safety requirements of this function satisfy those of the callee. + Self(unsafe { RawFormatter::from_buffer(buf, len) }) + } +} + +impl Deref for Formatter { + type Target = RawFormatter; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl fmt::Write for Formatter { + fn write_str(&mut self, s: &str) -> fmt::Result { + self.0.write_str(s)?; + + // Fail the request if we go past the end of the buffer. + if self.0.pos > self.0.end { + Err(fmt::Error) + } else { + Ok(()) + } + } +} -- cgit v1.2.3