1#![no_std]
2
3use core::fmt::{self, Write};
19
20pub struct CharBuf<const N: usize> {
22 buf: [char; N],
23 len: usize,
24}
25
26impl<const N: usize> CharBuf<N> {
27 pub const fn new() -> Self {
29 CharBuf {
30 buf: ['\0'; N],
31 len: 0,
32 }
33 }
34}
35
36impl<const N: usize> Default for CharBuf<N> {
37 fn default() -> Self {
38 CharBuf::new()
39 }
40}
41
42impl<const N: usize> fmt::Debug for CharBuf<N> {
43 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
44 f.write_char('"')?;
45 for c in self.buf.split_at(self.len).0.iter() {
46 f.write_char(*c)?;
47 }
48 f.write_char('"')
49 }
50}
51
52impl<const N: usize> fmt::Write for CharBuf<N> {
53 fn write_str(&mut self, s: &str) -> fmt::Result {
62 let mut chars = s.chars();
63 self.buf
64 .split_at_mut(self.len)
65 .1
66 .iter_mut()
67 .zip(chars.by_ref())
68 .for_each(|(x, c)| {
69 *x = c;
70 self.len += 1;
71 });
72 if chars.next().is_some() {
73 Err(fmt::Error)
74 } else {
75 Ok(())
76 }
77 }
78}
79
80impl<const N1: usize, const N2: usize> PartialEq<CharBuf<N2>> for CharBuf<N1> {
81 fn eq(&self, other: &CharBuf<N2>) -> bool {
82 self.len == other.len
83 && self
84 .buf
85 .split_at(self.len)
86 .0
87 .iter()
88 .zip(other.buf.split_at(other.len).0.iter())
89 .all(|(x, y)| x == y)
90 }
91}
92
93impl<const N: usize> Eq for CharBuf<N> {}
94
95impl<const N: usize> PartialEq<str> for CharBuf<N> {
96 fn eq(&self, other: &str) -> bool {
97 let mut buf = self.buf.split_at(self.len).0.iter();
98 let mut chars = other.chars();
99 buf.by_ref().all(|x| {
100 if let Some(c) = chars.next() {
101 *x == c
102 } else {
103 false
104 }
105 }) && chars.next().is_none()
106 }
107}
108
109impl<const N: usize> PartialEq<&str> for CharBuf<N> {
110 fn eq(&self, other: &&str) -> bool {
111 *self == **other
112 }
113}
114
115impl<const N: usize> PartialEq<CharBuf<N>> for str {
116 fn eq(&self, other: &CharBuf<N>) -> bool {
117 *other == *self
118 }
119}
120
121impl<const N: usize> PartialEq<CharBuf<N>> for &str {
122 fn eq(&self, other: &CharBuf<N>) -> bool {
123 *other == **self
124 }
125}
126
127#[cfg(test)]
128mod tests {
129 use super::*;
130 use fmt::Write;
131
132 const N1: usize = 3;
133 const N2: usize = 5;
134 type CharBufN1 = CharBuf<N1>;
135 type CharBufN2 = CharBuf<N2>;
136
137 #[test]
138 fn new() {
139 let w1 = CharBufN1::new();
140 let w2 = CharBufN2::new();
141
142 assert_eq!(w1.buf, ['\0'; N1]);
143 assert_eq!(w1.len, 0);
144
145 assert_eq!(w2.buf, ['\0'; N2]);
146 assert_eq!(w2.len, 0);
147 }
148
149 #[test]
150 fn default() {
151 let w1 = CharBufN1::default();
152 let w2 = CharBufN2::default();
153
154 assert_eq!(w1.buf, ['\0'; N1]);
155 assert_eq!(w1.len, 0);
156
157 assert_eq!(w2.buf, ['\0'; N2]);
158 assert_eq!(w2.len, 0);
159 }
160
161 #[test]
162 fn debug() {
163 let mut w1a = CharBufN1::new();
164 let mut w1b = CharBufN1::new();
165
166 let mut w2a = CharBufN2::new();
167 let mut w2b = CharBufN2::new();
168
169 write!(w1a, "a").unwrap();
170 write!(w1b, "{:?}", w1a).unwrap();
171
172 assert_eq!(w1a.buf, ['a', '\0', '\0']);
173 assert_eq!(w1b.buf, ['"', 'a', '"']);
174
175 write!(w2a, "a").unwrap();
176 write!(w2b, "{:?}", w2a).unwrap();
177
178 assert_eq!(w2a.buf, ['a', '\0', '\0', '\0', '\0']);
179 assert_eq!(w2b.buf, ['"', 'a', '"', '\0', '\0']);
180 }
181
182 #[test]
183 fn write() {
184 let mut w1 = CharBufN1::new();
185 let mut w2 = CharBufN2::new();
186
187 write!(w1, "a").unwrap();
188 write!(w2, "a").unwrap();
189
190 assert_eq!(w1.buf, ['a', '\0', '\0']);
191 assert_eq!(w1.len, 1);
192
193 assert_eq!(w2.buf, ['a', '\0', '\0', '\0', '\0']);
194 assert_eq!(w2.len, 1);
195
196 write!(w1, "{:?}", [(); 0]).unwrap();
197 write!(w2, "{:?}", [(); 0]).unwrap();
198
199 assert_eq!(w1.buf, ['a', '[', ']']);
200 assert_eq!(w1.len, 3);
201
202 assert_eq!(w2.buf, ['a', '[', ']', '\0', '\0']);
203 assert_eq!(w2.len, 3);
204
205 let mut w1 = CharBufN1::new();
206 let mut w2 = CharBufN2::new();
207
208 write!(w1, "{:?}", [0]).unwrap();
209 write!(w2, "{:?}", [0]).unwrap();
210
211 assert_eq!(w1.buf, ['[', '0', ']']);
212 assert_eq!(w1.len, 3);
213
214 assert_eq!(w2.buf, ['[', '0', ']', '\0', '\0']);
215 assert_eq!(w2.len, 3);
216
217 assert_eq!(write!(w1, "!"), Err(fmt::Error));
218 assert_eq!(write!(w2, "!"), Ok(()));
219
220 assert_eq!(w1.buf, ['[', '0', ']']);
221 assert_eq!(w1.len, 3);
222
223 assert_eq!(w2.buf, ['[', '0', ']', '!', '\0']);
224 assert_eq!(w2.len, 4);
225 }
226
227 #[test]
228 fn eq() {
229 let mut w1 = CharBufN1::new();
230 let mut w2 = CharBufN2::new();
231
232 write!(w1, "ab").unwrap();
233 write!(w2, "ab").unwrap();
234
235 assert_eq!(w1, "ab");
236 assert_eq!(w1, *"ab");
237
238 assert_eq!(w2, "ab");
239 assert_eq!(w2, *"ab");
240
241 assert_eq!(w1, w2);
242 assert_eq!(w2, w1);
243
244 write!(w2, "c").unwrap();
245
246 assert_eq!("ab", w1);
247 assert_eq!(*"ab", w1);
248
249 assert_eq!("abc", w2);
250 assert_eq!(*"abc", w2);
251
252 assert_ne!(w1, w2);
253 assert_ne!(w2, w1);
254
255 assert_ne!(w1, "a");
256 assert_ne!(w1, *"a");
257
258 assert_ne!(w1, "abc");
259 assert_ne!(w1, *"abc");
260 }
261}