1 // SPDX-License-Identifier: GPL-2.0
3 //! String representations.
7 /// Allows formatting of [`fmt::Arguments`] into a raw buffer.
9 /// It does not fail if callers write past the end of the buffer so that they can calculate the
10 /// size required to fit everything.
14 /// The memory region between `pos` (inclusive) and `end` (exclusive) is valid for writes if `pos`
15 /// is less than `end`.
16 pub(crate) struct RawFormatter {
17 // Use `usize` to use `saturating_*` functions.
25 /// Creates a new instance of [`RawFormatter`] with the given buffer pointers.
29 /// If `pos` is less than `end`, then the region between `pos` (inclusive) and `end`
30 /// (exclusive) must be valid for writes for the lifetime of the returned [`RawFormatter`].
31 pub(crate) unsafe fn from_ptrs(pos: *mut u8, end: *mut u8) -> Self {
32 // INVARIANT: The safety requirements guarantee the type invariants.
40 /// Returns the current insert position.
42 /// N.B. It may point to invalid memory.
43 pub(crate) fn pos(&self) -> *mut u8 {
48 impl fmt::Write for RawFormatter {
49 fn write_str(&mut self, s: &str) -> fmt::Result {
50 // `pos` value after writing `len` bytes. This does not have to be bounded by `end`, but we
51 // don't want it to wrap around to 0.
52 let pos_new = self.pos.saturating_add(s.len());
54 // Amount that we can copy. `saturating_sub` ensures we get 0 if `pos` goes past `end`.
55 let len_to_copy = core::cmp::min(pos_new, self.end).saturating_sub(self.pos);
58 // SAFETY: If `len_to_copy` is non-zero, then we know `pos` has not gone past `end`
59 // yet, so it is valid for write per the type invariants.
61 core::ptr::copy_nonoverlapping(
62 s.as_bytes().as_ptr(),