diff --git a/rust/kernel/print.rs b/rust/kernel/print.rs index 328d893f87aafe..e75fe088f284e9 100644 --- a/rust/kernel/print.rs +++ b/rust/kernel/print.rs @@ -6,50 +6,17 @@ //! //! Reference: -use core::cmp; use core::fmt; -use crate::bindings; use crate::c_types::{c_char, c_void}; +use crate::{bindings, str::Formatter}; // Called from `vsprintf` with format specifier `%pA`. #[no_mangle] unsafe fn rust_fmt_argument(buf: *mut c_char, end: *mut c_char, ptr: *const c_void) -> *mut c_char { use fmt::Write; - // Use `usize` to use `saturating_*` functions. - struct Writer { - buf: usize, - end: usize, - } - - impl Write for Writer { - fn write_str(&mut self, s: &str) -> fmt::Result { - // `buf` value after writing `len` bytes. This does not have to be bounded - // by `end`, but we don't want it to wrap around to 0. - let buf_new = self.buf.saturating_add(s.len()); - - // Amount that we can copy. `saturating_sub` ensures we get 0 if - // `buf` goes past `end`. - let len_to_copy = cmp::min(buf_new, self.end).saturating_sub(self.buf); - - // SAFETY: In any case, `buf` is non-null and properly aligned. - // If `len_to_copy` is non-zero, then we know `buf` has not past - // `end` yet and so is valid. - unsafe { - core::ptr::copy_nonoverlapping( - s.as_bytes().as_ptr(), - self.buf as *mut u8, - len_to_copy, - ) - }; - - self.buf = buf_new; - Ok(()) - } - } - - let mut w = Writer { + let mut w = Formatter { buf: buf as _, end: end as _, }; diff --git a/rust/kernel/str.rs b/rust/kernel/str.rs index eb2e2d7ef8475f..446d60a2edfc5e 100644 --- a/rust/kernel/str.rs +++ b/rust/kernel/str.rs @@ -373,3 +373,29 @@ mod tests { assert_eq!(unchecked_str, "🐧"); } } + +// Use `usize` to use `saturating_*` functions. +pub(crate) struct Formatter { + pub(crate) buf: usize, + pub(crate) end: usize, +} + +impl fmt::Write for Formatter { + fn write_str(&mut self, s: &str) -> fmt::Result { + // `buf` value after writing `len` bytes. This does not have to be bounded by `end`, but we + // don't want it to wrap around to 0. + let buf_new = self.buf.saturating_add(s.len()); + + // Amount that we can copy. `saturating_sub` ensures we get 0 if `buf` goes past `end`. + let len_to_copy = core::cmp::min(buf_new, self.end).saturating_sub(self.buf); + + // SAFETY: In any case, `buf` is non-null and properly aligned. If `len_to_copy` is + // non-zero, then we know `buf` has not past `end` yet and so is valid. + unsafe { + core::ptr::copy_nonoverlapping(s.as_bytes().as_ptr(), self.buf as *mut u8, len_to_copy) + }; + + self.buf = buf_new; + Ok(()) + } +}