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.
Unified · Split
| @@ -406,6 +406,23 @@ impl RawFormatter { · 405 unmodified lines | ||
| 406 | 406 | } |
| 407 | 407 | } |
| 408 | 408 | |
| 409 | + /// Creates a new instance of [`RawFormatter`] with the given buffer. | |
| 410 | + /// | |
| 411 | + /// # Safety | |
| 412 | + /// | |
| 413 | + /// The memory region starting at `buf` and extending for `len` bytes must be valid for writes | |
| 414 | + /// for the lifetime of the returned [`RawFormatter`]. | |
| 415 | + pub(crate) unsafe fn from_buffer(buf: *mut u8, len: usize) -> Self { | |
| 416 | + let pos = buf as usize; | |
| 417 | + // INVARIANT: We ensure that `end` is never less then `buf`, and the safety requirements | |
| 418 | + // guarantees that the memory region is valid for writes. | |
| 419 | + Self { | |
| 420 | + pos, | |
| 421 | + beg: pos, | |
| 422 | + end: pos.saturating_add(len), | |
| 423 | + } | |
| 424 | + } | |
| 425 | + | |
| 409 | 426 | /// Returns the current insert position. |
| 410 | 427 | /// |
| 411 | 428 | /// N.B. It may point to invalid memory. |
| @@ -439,3 +456,43 @@ impl fmt::Write for RawFormatter { · 27 unmodified lines | ||
| 439 | 456 | Ok(()) |
| 440 | 457 | } |
| 441 | 458 | } |
| 459 | + | |
| 460 | +/// Allows formatting of [`fmt::Arguments`] into a raw buffer. | |
| 461 | +/// | |
| 462 | +/// Fails if callers attempt to write more than will fit in the buffer. | |
| 463 | +pub(crate) struct Formatter(RawFormatter); | |
| 464 | + | |
| 465 | +impl Formatter { | |
| 466 | + /// Creates a new instance of [`Formatter`] with the given buffer. | |
| 467 | + /// | |
| 468 | + /// # Safety | |
| 469 | + /// | |
| 470 | + /// The memory region starting at `buf` and extending for `len` bytes must be valid for writes | |
| 471 | + /// for the lifetime of the returned [`Formatter`]. | |
| 472 | + #[allow(dead_code)] | |
| 473 | + pub(crate) unsafe fn from_buffer(buf: *mut u8, len: usize) -> Self { | |
| 474 | + // SAFETY: The safety requirements of this function satisfy those of the callee. | |
| 475 | + Self(unsafe { RawFormatter::from_buffer(buf, len) }) | |
| 476 | + } | |
| 477 | +} | |
| 478 | + | |
| 479 | +impl Deref for Formatter { | |
| 480 | + type Target = RawFormatter; | |
| 481 | + | |
| 482 | + fn deref(&self) -> &Self::Target { | |
| 483 | + &self.0 | |
| 484 | + } | |
| 485 | +} | |
| 486 | + | |
| 487 | +impl fmt::Write for Formatter { | |
| 488 | + fn write_str(&mut self, s: &str) -> fmt::Result { | |
| 489 | + self.0.write_str(s)?; | |
| 490 | + | |
| 491 | + // Fail the request if we go past the end of the buffer. | |
| 492 | + if self.0.pos > self.0.end { | |
| 493 | + Err(fmt::Error) | |
| 494 | + } else { | |
| 495 | + Ok(()) | |
| 496 | + } | |
| 497 | + } | |
| 498 | +} | |