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 | /// Returns the current insert position. | 426 | /// Returns the current insert position. |
| 410 | /// | 427 | /// |
| 411 | /// N.B. It may point to invalid memory. | 428 | /// N.B. It may point to invalid memory. |
| @@ -439,3 +456,43 @@ impl fmt::Write for RawFormatter { · 27 unmodified lines | |||
| 439 | Ok(()) | 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 | } | ||