1use core::borrow::Borrow;
8
9pub use out_bytes::OutBytes;
10
11use super::Case;
12
13pub trait AsOutBytes: out_bytes::Sealed {
26 fn as_out_bytes(&self) -> &OutBytes;
28
29 fn as_mut_out_bytes(&mut self) -> &mut OutBytes;
31}
32
33pub trait FixedLenBuf: Sized + AsOutBytes {
37 fn uninit() -> Self;
42}
43
44mod out_bytes {
48 use super::AsOutBytes;
49
50 #[repr(transparent)]
61 pub struct OutBytes([u8]);
62
63 impl OutBytes {
64 #[cfg_attr(rust_v_1_46, track_caller)]
72 pub(crate) fn assume_init(&self, len: usize) -> &[u8] { &self.0[..len] }
73
74 #[cfg_attr(rust_v_1_46, track_caller)]
80 pub(crate) fn write(&mut self, pos: usize, bytes: &[u8]) {
81 self.0[pos..(pos + bytes.len())].copy_from_slice(bytes);
82 }
83
84 pub(crate) fn len(&self) -> usize { self.0.len() }
86
87 fn from_bytes(slice: &[u8]) -> &Self {
88 unsafe { &*(slice as *const [u8] as *const Self) }
96 }
97
98 fn from_mut_bytes(slice: &mut [u8]) -> &mut Self {
99 unsafe { &mut *(slice as *mut [u8] as *mut Self) }
107 }
108 }
109
110 macro_rules! impl_from_array {
111 ($($len:expr),* $(,)?) => {
112 $(
113 impl super::FixedLenBuf for [u8; $len] {
114 fn uninit() -> Self {
115 [0u8; $len]
116 }
117 }
118
119 impl AsOutBytes for [u8; $len] {
120 fn as_out_bytes(&self) -> &OutBytes {
121 OutBytes::from_bytes(self)
122 }
123
124 fn as_mut_out_bytes(&mut self) -> &mut OutBytes {
125 OutBytes::from_mut_bytes(self)
126 }
127 }
128
129 impl Sealed for [u8; $len] {}
130
131 impl<'a> super::super::display::DisplayHex for &'a [u8; $len / 2] {
132 type Display = super::super::display::DisplayArray<core::slice::Iter<'a, u8>, [u8; $len]>;
133 fn as_hex(self) -> Self::Display {
134 super::super::display::DisplayArray::new(self.iter())
135 }
136
137 fn hex_reserve_suggestion(self) -> usize {
138 $len
139 }
140 }
141 )*
142 }
143 }
144
145 impl<T: AsOutBytes + ?Sized> AsOutBytes for &'_ mut T {
146 fn as_out_bytes(&self) -> &OutBytes { (**self).as_out_bytes() }
147
148 fn as_mut_out_bytes(&mut self) -> &mut OutBytes { (**self).as_mut_out_bytes() }
149 }
150
151 impl<T: AsOutBytes + ?Sized> Sealed for &'_ mut T {}
152
153 impl AsOutBytes for OutBytes {
154 fn as_out_bytes(&self) -> &OutBytes { self }
155
156 fn as_mut_out_bytes(&mut self) -> &mut OutBytes { self }
157 }
158
159 impl Sealed for OutBytes {}
160
161 impl_from_array!(
164 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 40, 64, 66, 128, 130, 256, 512,
165 1024, 2048, 4096, 8192
166 );
167
168 pub trait Sealed {}
170}
171
172pub struct BufEncoder<T: AsOutBytes> {
178 buf: T,
179 pos: usize,
180}
181
182impl<T: AsOutBytes> BufEncoder<T> {
183 #[inline]
188 pub fn new(buf: T) -> Self { BufEncoder { buf, pos: 0 } }
189
190 #[inline]
196 #[cfg_attr(rust_v_1_46, track_caller)]
197 pub fn put_byte(&mut self, byte: u8, case: Case) {
198 self.buf.as_mut_out_bytes().write(self.pos, &super::byte_to_hex(byte, case.table()));
199 self.pos += 2;
200 }
201
202 #[inline]
208 #[cfg_attr(rust_v_1_46, track_caller)]
209 pub fn put_bytes<I>(&mut self, bytes: I, case: Case)
210 where
211 I: IntoIterator,
212 I::Item: Borrow<u8>,
213 {
214 self.put_bytes_inner(bytes.into_iter(), case)
215 }
216
217 #[inline]
218 #[cfg_attr(rust_v_1_46, track_caller)]
219 fn put_bytes_inner<I>(&mut self, bytes: I, case: Case)
220 where
221 I: Iterator,
222 I::Item: Borrow<u8>,
223 {
224 if let Some(max) = bytes.size_hint().1 {
226 assert!(max <= self.space_remaining());
227 }
228 for byte in bytes {
229 self.put_byte(*byte.borrow(), case);
230 }
231 }
232
233 #[must_use = "this may write only part of the input buffer"]
238 #[inline]
239 #[cfg_attr(rust_v_1_46, track_caller)]
240 pub fn put_bytes_min<'a>(&mut self, bytes: &'a [u8], case: Case) -> &'a [u8] {
241 let to_write = self.space_remaining().min(bytes.len());
242 self.put_bytes(&bytes[..to_write], case);
243 &bytes[to_write..]
244 }
245
246 #[inline]
248 pub fn is_full(&self) -> bool { self.pos == self.buf.as_out_bytes().len() }
249
250 #[inline]
252 pub fn as_str(&self) -> &str {
253 core::str::from_utf8(self.buf.as_out_bytes().assume_init(self.pos))
254 .expect("we only write ASCII")
255 }
256
257 #[inline]
259 pub fn clear(&mut self) { self.pos = 0; }
260
261 #[inline]
265 pub fn space_remaining(&self) -> usize { (self.buf.as_out_bytes().len() - self.pos) / 2 }
266}
267
268#[cfg(test)]
269mod tests {
270 use super::*;
271
272 #[test]
273 fn empty() {
274 let mut buf = [0u8; 2];
275 let encoder = BufEncoder::new(&mut buf);
276 assert_eq!(encoder.as_str(), "");
277 assert!(!encoder.is_full());
278 }
279
280 #[test]
281 fn single_byte_exact_buf() {
282 let mut buf = [0u8; 2];
283 let mut encoder = BufEncoder::new(&mut buf);
284 assert_eq!(encoder.space_remaining(), 1);
285 encoder.put_byte(42, Case::Lower);
286 assert_eq!(encoder.as_str(), "2a");
287 assert_eq!(encoder.space_remaining(), 0);
288 assert!(encoder.is_full());
289 encoder.clear();
290 assert_eq!(encoder.space_remaining(), 1);
291 assert!(!encoder.is_full());
292 encoder.put_byte(42, Case::Upper);
293 assert_eq!(encoder.as_str(), "2A");
294 assert_eq!(encoder.space_remaining(), 0);
295 assert!(encoder.is_full());
296 }
297
298 #[test]
299 fn single_byte_oversized_buf() {
300 let mut buf = [0u8; 4];
301 let mut encoder = BufEncoder::new(&mut buf);
302 assert_eq!(encoder.space_remaining(), 2);
303 encoder.put_byte(42, Case::Lower);
304 assert_eq!(encoder.space_remaining(), 1);
305 assert_eq!(encoder.as_str(), "2a");
306 assert!(!encoder.is_full());
307 encoder.clear();
308 assert_eq!(encoder.space_remaining(), 2);
309 encoder.put_byte(42, Case::Upper);
310 assert_eq!(encoder.as_str(), "2A");
311 assert_eq!(encoder.space_remaining(), 1);
312 assert!(!encoder.is_full());
313 }
314
315 #[test]
316 fn two_bytes() {
317 let mut buf = [0u8; 4];
318 let mut encoder = BufEncoder::new(&mut buf);
319 encoder.put_byte(42, Case::Lower);
320 assert_eq!(encoder.space_remaining(), 1);
321 encoder.put_byte(255, Case::Lower);
322 assert_eq!(encoder.space_remaining(), 0);
323 assert_eq!(encoder.as_str(), "2aff");
324 assert!(encoder.is_full());
325 encoder.clear();
326 assert!(!encoder.is_full());
327 encoder.put_byte(42, Case::Upper);
328 encoder.put_byte(255, Case::Upper);
329 assert_eq!(encoder.as_str(), "2AFF");
330 assert!(encoder.is_full());
331 }
332
333 #[test]
334 fn put_bytes_min() {
335 let mut buf = [0u8; 2];
336 let mut encoder = BufEncoder::new(&mut buf);
337 let remainder = encoder.put_bytes_min(b"", Case::Lower);
338 assert_eq!(remainder, b"");
339 assert_eq!(encoder.as_str(), "");
340 let remainder = encoder.put_bytes_min(b"*", Case::Lower);
341 assert_eq!(remainder, b"");
342 assert_eq!(encoder.as_str(), "2a");
343 encoder.clear();
344 let remainder = encoder.put_bytes_min(&[42, 255], Case::Lower);
345 assert_eq!(remainder, &[255]);
346 assert_eq!(encoder.as_str(), "2a");
347 }
348
349 #[test]
350 fn same_as_fmt() {
351 use core::fmt::{self, Write};
352
353 struct Writer {
354 buf: [u8; 2],
355 pos: usize,
356 }
357
358 impl Writer {
359 fn as_str(&self) -> &str { core::str::from_utf8(&self.buf[..self.pos]).unwrap() }
360 }
361
362 impl Write for Writer {
363 fn write_str(&mut self, s: &str) -> fmt::Result {
364 assert!(self.pos <= 2);
365 if s.len() > 2 - self.pos {
366 Err(fmt::Error)
367 } else {
368 self.buf[self.pos..(self.pos + s.len())].copy_from_slice(s.as_bytes());
369 self.pos += s.len();
370 Ok(())
371 }
372 }
373 }
374
375 let mut writer = Writer { buf: [0u8; 2], pos: 0 };
376 let mut buf = [0u8; 2];
377 let mut encoder = BufEncoder::new(&mut buf);
378
379 for i in 0..=255 {
380 write!(writer, "{:02x}", i).unwrap();
381 encoder.put_byte(i, Case::Lower);
382 assert_eq!(encoder.as_str(), writer.as_str());
383 writer.pos = 0;
384 encoder.clear();
385 }
386 for i in 0..=255 {
387 write!(writer, "{:02X}", i).unwrap();
388 encoder.put_byte(i, Case::Upper);
389 assert_eq!(encoder.as_str(), writer.as_str());
390 writer.pos = 0;
391 encoder.clear();
392 }
393 }
394}