[PATCH v2 02/14] rust: str: introduce `BorrowFormatter`

Andreas Hindborg posted 14 patches 3 months ago
There is a newer version of this series
[PATCH v2 02/14] rust: str: introduce `BorrowFormatter`
Posted by Andreas Hindborg 3 months ago
Add `BorrowFormatter`, a formatter that writes to an array or slice buffer.
This formatter is backed by the existing `Formatter`.

Signed-off-by: Andreas Hindborg <a.hindborg@kernel.org>
---
 rust/kernel/str.rs | 36 +++++++++++++++++++++++++++++++++---
 1 file changed, 33 insertions(+), 3 deletions(-)

diff --git a/rust/kernel/str.rs b/rust/kernel/str.rs
index 488b0e97004ee..78b2f95eb3171 100644
--- a/rust/kernel/str.rs
+++ b/rust/kernel/str.rs
@@ -6,6 +6,7 @@
 use crate::prelude::*;
 use core::{
     fmt::{self, Write},
+    marker::PhantomData,
     ops::{self, Deref, DerefMut, Index},
 };
 
@@ -702,7 +703,7 @@ fn test_bstr_debug() -> Result {
 ///
 /// The memory region between `pos` (inclusive) and `end` (exclusive) is valid for writes if `pos`
 /// is less than `end`.
-pub(crate) struct RawFormatter {
+pub struct RawFormatter {
     // Use `usize` to use `saturating_*` functions.
     beg: usize,
     pos: usize,
@@ -760,7 +761,7 @@ pub(crate) fn pos(&self) -> *mut u8 {
     }
 
     /// Returns the number of bytes written to the formatter.
-    pub(crate) fn bytes_written(&self) -> usize {
+    pub fn bytes_written(&self) -> usize {
         self.pos - self.beg
     }
 }
@@ -794,7 +795,7 @@ fn write_str(&mut self, s: &str) -> fmt::Result {
 /// 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);
+pub struct Formatter(RawFormatter);
 
 impl Formatter {
     /// Creates a new instance of [`Formatter`] with the given buffer.
@@ -830,6 +831,35 @@ fn write_str(&mut self, s: &str) -> fmt::Result {
     }
 }
 
+/// A mutable reference to a byte buffer where a string can be written into.
+pub struct BorrowFormatter<'a>(Formatter, PhantomData<&'a mut ()>);
+
+impl<'a> BorrowFormatter<'a> {
+    /// Create a new [`Self`] instance.
+    pub fn new(buffer: &'a mut [u8]) -> Result<BorrowFormatter<'a>> {
+        Ok(Self(
+            // SAFETY: `buffer` is valid for writes for the entire length for
+            // the lifetime of `Self`.
+            unsafe { Formatter::from_buffer(buffer.as_mut_ptr(), buffer.len()) },
+            PhantomData,
+        ))
+    }
+}
+
+impl Deref for BorrowFormatter<'_> {
+    type Target = Formatter;
+
+    fn deref(&self) -> &Self::Target {
+        &self.0
+    }
+}
+
+impl DerefMut for BorrowFormatter<'_> {
+    fn deref_mut(&mut self) -> &mut Self::Target {
+        &mut self.0
+    }
+}
+
 /// 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
Re: [PATCH v2 02/14] rust: str: introduce `BorrowFormatter`
Posted by Alice Ryhl 3 months ago
On Tue, Jul 08, 2025 at 09:44:57PM +0200, Andreas Hindborg wrote:
> Add `BorrowFormatter`, a formatter that writes to an array or slice buffer.
> This formatter is backed by the existing `Formatter`.
> 
> Signed-off-by: Andreas Hindborg <a.hindborg@kernel.org>

I don't think we need a separate BorrowFormatter. We can instead add a
lifetime to Formatter and give it a safe constructor from a mutable
slice.

Alice
Re: [PATCH v2 02/14] rust: str: introduce `BorrowFormatter`
Posted by Andreas Hindborg 2 months, 4 weeks ago
"Alice Ryhl" <aliceryhl@google.com> writes:

> On Tue, Jul 08, 2025 at 09:44:57PM +0200, Andreas Hindborg wrote:
>> Add `BorrowFormatter`, a formatter that writes to an array or slice buffer.
>> This formatter is backed by the existing `Formatter`.
>>
>> Signed-off-by: Andreas Hindborg <a.hindborg@kernel.org>
>
> I don't think we need a separate BorrowFormatter. We can instead add a
> lifetime to Formatter and give it a safe constructor from a mutable
> slice.

Ah, good idea.


Best regards,
Andreas Hindborg