| 1 | // SPDX-License-Identifier: GPL-2.0 |
| 2 | |
| 3 | //! String representations. |
| 4 | |
| 5 | use fmt; |
| 6 | |
| 7 | /// Allows formatting of [`fmt::Arguments`] into a raw buffer. |
| 8 | /// |
| 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. |
| 11 | /// |
| 12 | /// # Invariants |
| 13 | /// |
| 14 | /// The memory region between `pos` (inclusive) and `end` (exclusive) is valid for writes if `pos` |
| 15 | /// is less than `end`. |
| 16 | pub |
| 17 | // Use `usize` to use `saturating_*` functions. |
| 18 | #[allow(dead_code)] |
| 19 | beg: usize, |
| 20 | pos: usize, |
| 21 | end: usize, |
| 22 | |
| 23 | |
| 24 | |
| 25 | /// Creates a new instance of [`RawFormatter`] with the given buffer pointers. |
| 26 | /// |
| 27 | /// # Safety |
| 28 | /// |
| 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 unsafe |
| 32 | // INVARIANT: The safety requierments guarantee the type invariants. |
| 33 | Self |
| 34 | beg: pos as _, |
| 35 | pos: pos as _, |
| 36 | end: end as _, |
| 37 | |
| 38 | |
| 39 | |
| 40 | /// Returns the current insert position. |
| 41 | /// |
| 42 | /// N.B. It may point to invalid memory. |
| 43 | pub *mut u8 |
| 44 | self.pos as _ |
| 45 | |
| 46 | |
| 47 | |
| 48 | |
| 49 | |
| 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; |
| 53 | |
| 54 | // Amount that we can copy. `saturating_sub` ensures we get 0 if `pos` goes past `end`. |
| 55 | let len_to_copy = min.saturating_sub; |
| 56 | |
| 57 | if len_to_copy > 0 |
| 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. |
| 60 | unsafe |
| 61 | copy_nonoverlapping |
| 62 | s.as_bytes.as_ptr, |
| 63 | self.pos as *mut u8, |
| 64 | len_to_copy, |
| 65 | |
| 66 | ; |
| 67 | |
| 68 | |
| 69 | self.pos = pos_new; |
| 70 | Ok |
| 71 | |
| 72 |