1use core::fmt::{self, Write};
9
10#[must_use]
12pub const fn format_buffer_capacity() -> usize {
13 crate::config::BUFFER_SIZE
14}
15
16const CAPACITY: usize = format_buffer_capacity();
17
18pub struct FormatBuffer {
25 inner: heapless::String<CAPACITY>,
26 truncated: bool,
27}
28
29impl FormatBuffer {
30 #[must_use]
32 pub fn new() -> Self {
33 Self {
34 inner: heapless::String::new(),
35 truncated: false,
36 }
37 }
38
39 #[must_use]
41 pub fn as_str(&self) -> &str {
42 self.inner.as_str()
43 }
44
45 #[must_use]
47 pub fn truncated(&self) -> bool {
48 self.truncated
49 }
50}
51
52impl Default for FormatBuffer {
53 fn default() -> Self {
54 Self::new()
55 }
56}
57
58impl Write for FormatBuffer {
59 fn write_str(&mut self, s: &str) -> fmt::Result {
60 if self.truncated {
61 return Ok(());
62 }
63 match self.inner.push_str(s) {
64 Ok(()) => Ok(()),
65 Err(()) => {
66 self.truncated = true;
67 let target_len = CAPACITY.saturating_sub(3);
71 let room = target_len.saturating_sub(self.inner.len());
76 let mut cut = s.len().min(room);
77 while cut > 0 && !s.is_char_boundary(cut) {
78 cut -= 1;
79 }
80 let _ = self.inner.push_str(&s[..cut]);
81 let mut trunc_at = self.inner.len().min(target_len);
85 while trunc_at > 0 && !self.inner.as_str().is_char_boundary(trunc_at) {
86 trunc_at -= 1;
87 }
88 self.inner.truncate(trunc_at);
89 let _ = self.inner.push('\u{2026}');
90 Ok(())
91 }
92 }
93 }
94}
95
96#[cfg(test)]
97mod tests {
98 use super::*;
99 use core::fmt::Write;
100
101 #[test]
102 fn small_payload_fits() {
103 let mut b = FormatBuffer::new();
104 write!(b, "hello {}", 42).unwrap();
105 assert_eq!(b.as_str(), "hello 42");
106 assert!(!b.truncated());
107 }
108
109 #[test]
110 fn overflow_truncates_and_appends_ellipsis() {
111 let mut b = FormatBuffer::new();
112 let pad = "x".repeat(CAPACITY * 2);
113 write!(b, "{}", pad).unwrap();
114 assert!(b.truncated());
115 assert!(b.as_str().ends_with('\u{2026}'));
116 assert!(b.as_str().len() <= CAPACITY);
117 }
118
119 #[test]
122 fn an_overflowing_write_keeps_what_fits() {
123 let mut b = FormatBuffer::new();
124 let pad = "y".repeat(CAPACITY * 2);
125 write!(b, "{} {}", 6, pad).unwrap();
126 assert!(b.truncated());
127 assert!(b.as_str().starts_with("6 yyy"), "got {:?}", b.as_str());
128 assert!(b.as_str().ends_with('\u{2026}'));
129 assert!(b.as_str().len() <= CAPACITY);
130 assert!(
131 b.as_str().len() >= CAPACITY - 3,
132 "fills the buffer: {}",
133 b.as_str().len()
134 );
135 }
136
137 #[test]
139 fn an_overflowing_write_does_not_split_a_character() {
140 let mut b = FormatBuffer::new();
141 let pad = "\u{00e9}".repeat(CAPACITY);
142 write!(b, "x{}", pad).unwrap();
143 assert!(b.as_str().ends_with('\u{2026}'));
144 assert!(b.as_str().len() <= CAPACITY);
145 }
146
147 #[test]
148 fn capacity_matches_feature_default() {
149 assert_eq!(format_buffer_capacity(), 256);
151 }
152}