1use std::borrow::Cow;
2use std::fmt;
3use std::sync::Arc;
4
5const DEFAULT_SEPARATOR: &str = ":";
6
7pub trait BufferFormatter: Send + 'static {
26 fn get_separator(&self) -> &str;
31
32 fn format_byte(&self, byte: &u8) -> String;
34
35 fn format_buffer(&self, buffer: &[u8]) -> String {
37 buffer
38 .iter()
39 .map(|b| self.format_byte(b))
40 .collect::<Vec<String>>()
41 .join(self.get_separator())
42 }
43}
44
45impl BufferFormatter for Box<dyn BufferFormatter> {
46 #[inline]
47 fn get_separator(&self) -> &str {
48 (**self).get_separator()
49 }
50
51 #[inline]
52 fn format_byte(&self, byte: &u8) -> String {
53 (**self).format_byte(byte)
54 }
55}
56
57impl<T: BufferFormatter + ?Sized + Sync> BufferFormatter for Arc<T> {
58 #[inline]
59 fn get_separator(&self) -> &str {
60 (**self).get_separator()
61 }
62
63 #[inline]
64 fn format_byte(&self, byte: &u8) -> String {
65 (**self).format_byte(byte)
66 }
67}
68
69macro_rules! define_formatter {
74 (
75 $(#[$struct_meta:meta])*
76 $name:ident,
77 $format_expr:expr
78 ) => {
79 $(#[$struct_meta])*
80 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
81 pub struct $name {
82 separator: Cow<'static, str>,
83 }
84
85 impl $name {
86 #[doc = concat!("`", stringify!($name), "`")]
88 pub fn new(provided_separator: Option<&str>) -> Self {
91 Self {
92 separator: provided_separator
93 .map(|s| Cow::Owned(s.to_string()))
94 .unwrap_or(Cow::Borrowed(DEFAULT_SEPARATOR)),
95 }
96 }
97
98 #[doc = concat!("`", stringify!($name), "`")]
100 pub fn new_static(provided_separator: Option<&'static str>) -> Self {
104 Self {
105 separator: provided_separator
106 .map(Cow::Borrowed)
107 .unwrap_or(Cow::Borrowed(DEFAULT_SEPARATOR)),
108 }
109 }
110
111 #[doc = concat!("`", stringify!($name), "`")]
113 pub fn new_owned(provided_separator: Option<String>) -> Self {
116 Self {
117 separator: provided_separator
118 .map(Cow::Owned)
119 .unwrap_or(Cow::Borrowed(DEFAULT_SEPARATOR)),
120 }
121 }
122
123 #[doc = concat!("`", stringify!($name), "`")]
125 pub fn new_default() -> Self {
127 Self {
128 separator: Cow::Borrowed(DEFAULT_SEPARATOR),
129 }
130 }
131 }
132
133 impl BufferFormatter for $name {
134 #[inline]
135 fn get_separator(&self) -> &str {
136 &self.separator
137 }
138
139 #[inline]
140 fn format_byte(&self, byte: &u8) -> String {
141 $format_expr(byte)
142 }
143 }
144
145 impl BufferFormatter for Box<$name> {
146 #[inline]
147 fn get_separator(&self) -> &str {
148 (**self).get_separator()
149 }
150
151 #[inline]
152 fn format_byte(&self, byte: &u8) -> String {
153 (**self).format_byte(byte)
154 }
155 }
156
157 impl Default for $name {
158 fn default() -> Self {
159 Self::new_default()
160 }
161 }
162
163 impl From<Cow<'static, str>> for $name {
164 fn from(separator: Cow<'static, str>) -> Self {
165 Self { separator }
166 }
167 }
168
169 impl From<&str> for $name {
170 fn from(separator: &str) -> Self {
171 Self::new(Some(separator))
172 }
173 }
174
175 impl From<String> for $name {
176 fn from(separator: String) -> Self {
177 Self::new_owned(Some(separator))
178 }
179 }
180
181 impl From<Option<&str>> for $name {
182 fn from(separator: Option<&str>) -> Self {
183 Self::new(separator)
184 }
185 }
186
187 impl From<Option<String>> for $name {
188 fn from(separator: Option<String>) -> Self {
189 Self::new_owned(separator)
190 }
191 }
192
193 impl fmt::Display for $name {
194 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
195 write!(f, "{}(separator: {:?})", stringify!($name), self.separator)
196 }
197 }
198 };
199}
200
201define_formatter!(
206 DecimalFormatter,
208 |byte: &u8| format!("{byte}")
209);
210
211define_formatter!(
212 OctalFormatter,
214 |byte: &u8| format!("{byte:03o}")
215);
216
217define_formatter!(
218 UppercaseHexadecimalFormatter,
220 |byte: &u8| format!("{byte:02X}")
221);
222
223define_formatter!(
224 LowercaseHexadecimalFormatter,
226 |byte: &u8| format!("{byte:02x}")
227);
228
229define_formatter!(
230 BinaryFormatter,
232 |byte: &u8| format!("{byte:08b}")
233);
234
235#[cfg(test)]
240mod tests {
241 use crate::buffer_formatter::BinaryFormatter;
242 use crate::buffer_formatter::BufferFormatter;
243 use crate::buffer_formatter::DecimalFormatter;
244 use crate::buffer_formatter::LowercaseHexadecimalFormatter;
245 use crate::buffer_formatter::OctalFormatter;
246 use crate::buffer_formatter::UppercaseHexadecimalFormatter;
247 use std::borrow::Cow;
248 use std::sync::Arc;
249 use std::thread;
250
251 const FORMATTING_TEST_VALUES: &[u8] = &[10, 11, 12, 13, 14, 15, 16, 17, 18];
252
253 #[test]
254 fn test_buffer_formatting() {
255 let lowercase_hexadecimal = LowercaseHexadecimalFormatter::new_default();
256 let uppercase_hexadecimal = UppercaseHexadecimalFormatter::new_default();
257 let decimal = DecimalFormatter::new_default();
258 let octal = OctalFormatter::new_default();
259 let binary = BinaryFormatter::new_default();
260
261 assert_eq!(
262 lowercase_hexadecimal.format_buffer(FORMATTING_TEST_VALUES),
263 String::from("0a:0b:0c:0d:0e:0f:10:11:12")
264 );
265 assert_eq!(
266 uppercase_hexadecimal.format_buffer(FORMATTING_TEST_VALUES),
267 String::from("0A:0B:0C:0D:0E:0F:10:11:12")
268 );
269 assert_eq!(
270 decimal.format_buffer(FORMATTING_TEST_VALUES),
271 String::from("10:11:12:13:14:15:16:17:18")
272 );
273 assert_eq!(
274 octal.format_buffer(FORMATTING_TEST_VALUES),
275 String::from("012:013:014:015:016:017:020:021:022")
276 );
277 assert_eq!(
278 binary.format_buffer(FORMATTING_TEST_VALUES),
279 String::from(
280 "00001010:00001011:00001100:00001101:00001110:00001111:00010000:00010001:00010010"
281 )
282 );
283 }
284
285 #[test]
286 fn test_custom_separator() {
287 let lowercase_hexadecimal = LowercaseHexadecimalFormatter::new(Some("-"));
288 let uppercase_hexadecimal = UppercaseHexadecimalFormatter::new(Some("-"));
289 let decimal = DecimalFormatter::new(Some("-"));
290 let octal = OctalFormatter::new(Some("-"));
291 let binary = BinaryFormatter::new(Some("-"));
292
293 assert_eq!(
294 lowercase_hexadecimal.format_buffer(FORMATTING_TEST_VALUES),
295 String::from("0a-0b-0c-0d-0e-0f-10-11-12")
296 );
297 assert_eq!(
298 uppercase_hexadecimal.format_buffer(FORMATTING_TEST_VALUES),
299 String::from("0A-0B-0C-0D-0E-0F-10-11-12")
300 );
301 assert_eq!(
302 decimal.format_buffer(FORMATTING_TEST_VALUES),
303 String::from("10-11-12-13-14-15-16-17-18")
304 );
305 assert_eq!(
306 octal.format_buffer(FORMATTING_TEST_VALUES),
307 String::from("012-013-014-015-016-017-020-021-022")
308 );
309 assert_eq!(
310 binary.format_buffer(FORMATTING_TEST_VALUES),
311 String::from(
312 "00001010-00001011-00001100-00001101-00001110-00001111-00010000-00010001-00010010"
313 )
314 );
315 }
316
317 #[test]
318 fn test_static_separator() {
319 let lowercase_hexadecimal = LowercaseHexadecimalFormatter::new_static(Some("-"));
321 let uppercase_hexadecimal = UppercaseHexadecimalFormatter::new_static(Some("-"));
322 let decimal = DecimalFormatter::new_static(Some("-"));
323 let octal = OctalFormatter::new_static(Some("-"));
324 let binary = BinaryFormatter::new_static(Some("-"));
325
326 assert_eq!(
327 lowercase_hexadecimal.format_buffer(FORMATTING_TEST_VALUES),
328 String::from("0a-0b-0c-0d-0e-0f-10-11-12")
329 );
330 assert_eq!(
331 uppercase_hexadecimal.format_buffer(FORMATTING_TEST_VALUES),
332 String::from("0A-0B-0C-0D-0E-0F-10-11-12")
333 );
334 assert_eq!(
335 decimal.format_buffer(FORMATTING_TEST_VALUES),
336 String::from("10-11-12-13-14-15-16-17-18")
337 );
338 assert_eq!(
339 octal.format_buffer(FORMATTING_TEST_VALUES),
340 String::from("012-013-014-015-016-017-020-021-022")
341 );
342 assert_eq!(
343 binary.format_buffer(FORMATTING_TEST_VALUES),
344 String::from(
345 "00001010-00001011-00001100-00001101-00001110-00001111-00010000-00010001-00010010"
346 )
347 );
348 }
349
350 #[test]
351 fn test_owned_separator() {
352 let runtime_sep = String::from(" | ");
354 let formatter = DecimalFormatter::new_owned(Some(runtime_sep));
355 assert_eq!(
356 formatter.format_buffer(FORMATTING_TEST_VALUES),
357 String::from("10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18")
358 );
359
360 let formatter = OctalFormatter::new_owned(None);
362 assert_eq!(formatter.get_separator(), ":");
363 }
364
365 #[test]
366 fn test_from_cow() {
367 let sep_borrowed: Cow<'static, str> = Cow::Borrowed(" | ");
369 let formatter = DecimalFormatter::from(sep_borrowed);
370 assert_eq!(formatter.get_separator(), " | ");
371
372 let sep_owned: Cow<'static, str> = Cow::Owned(String::from(" | "));
374 let formatter = OctalFormatter::from(sep_owned);
375 assert_eq!(formatter.get_separator(), " | ");
376
377 let formatter: UppercaseHexadecimalFormatter = Cow::Borrowed("-").into();
379 assert_eq!(
380 formatter.format_buffer(FORMATTING_TEST_VALUES),
381 String::from("0A-0B-0C-0D-0E-0F-10-11-12")
382 );
383
384 let lowercase_hex: LowercaseHexadecimalFormatter = Cow::Borrowed(" ").into();
386 let binary: BinaryFormatter = Cow::<'static, str>::Owned(String::from(",")).into();
387
388 assert_eq!(lowercase_hex.get_separator(), " ");
389 assert_eq!(binary.get_separator(), ",");
390 }
391
392 #[test]
393 fn test_from_static_str() {
394 let formatter = DecimalFormatter::from("-");
396 assert_eq!(formatter.get_separator(), "-");
397 assert_eq!(
398 formatter.format_buffer(FORMATTING_TEST_VALUES),
399 String::from("10-11-12-13-14-15-16-17-18")
400 );
401
402 let formatter: OctalFormatter = " | ".into();
404 assert_eq!(formatter.get_separator(), " | ");
405
406 let runtime_string = String::from(" -> ");
408 let runtime_str: &str = runtime_string.as_str();
409 let formatter: UppercaseHexadecimalFormatter = runtime_str.into();
410 assert_eq!(formatter.get_separator(), " -> ");
411 assert_eq!(
412 formatter.format_buffer(FORMATTING_TEST_VALUES),
413 String::from("0A -> 0B -> 0C -> 0D -> 0E -> 0F -> 10 -> 11 -> 12")
414 );
415
416 let _decimal: DecimalFormatter = " ".into();
418 let _octal: OctalFormatter = ",".into();
419 let _uppercase_hex: UppercaseHexadecimalFormatter = "-".into();
420 let _lowercase_hex: LowercaseHexadecimalFormatter = "::".into();
421 let _binary: BinaryFormatter = "_".into();
422 }
423
424 #[test]
425 fn test_from_string() {
426 let separator = String::from(" -> ");
428 let formatter = DecimalFormatter::from(separator);
429 assert_eq!(formatter.get_separator(), " -> ");
430 assert_eq!(
431 formatter.format_buffer(FORMATTING_TEST_VALUES),
432 String::from("10 -> 11 -> 12 -> 13 -> 14 -> 15 -> 16 -> 17 -> 18")
433 );
434
435 let formatter: UppercaseHexadecimalFormatter = String::from(" ").into();
437 assert_eq!(
438 formatter.format_buffer(FORMATTING_TEST_VALUES),
439 String::from("0A 0B 0C 0D 0E 0F 10 11 12")
440 );
441
442 let _decimal: DecimalFormatter = String::from("-").into();
444 let _octal: OctalFormatter = String::from(",").into();
445 let _uppercase_hex: UppercaseHexadecimalFormatter = String::from("::").into();
446 let _lowercase_hex: LowercaseHexadecimalFormatter = String::from(" | ").into();
447 let _binary: BinaryFormatter = String::from("_").into();
448 }
449
450 #[test]
451 fn test_from_option_static_str() {
452 let formatter = DecimalFormatter::from(Some("-"));
454 assert_eq!(formatter.get_separator(), "-");
455
456 let formatter = OctalFormatter::from(None as Option<&str>);
458 assert_eq!(formatter.get_separator(), ":");
459
460 let formatter: UppercaseHexadecimalFormatter = Some(" ").into();
462 assert_eq!(formatter.get_separator(), " ");
463
464 let formatter: LowercaseHexadecimalFormatter = (None as Option<&str>).into();
465 assert_eq!(formatter.get_separator(), ":");
466
467 let runtime_string = String::from(" | ");
469 let runtime_str: &str = runtime_string.as_str();
470 let formatter: BinaryFormatter = Some(runtime_str).into();
471 assert_eq!(formatter.get_separator(), " | ");
472
473 let _decimal: DecimalFormatter = Some("->").into();
475 let _octal: OctalFormatter = (None as Option<&str>).into();
476 let _uppercase_hex: UppercaseHexadecimalFormatter = Some(",").into();
477 let _lowercase_hex: LowercaseHexadecimalFormatter = Some("::").into();
478 let _binary: BinaryFormatter = (None as Option<&str>).into();
479 }
480
481 #[test]
482 fn test_from_option_string() {
483 let separator = Some(String::from(" | "));
485 let formatter = DecimalFormatter::from(separator);
486 assert_eq!(formatter.get_separator(), " | ");
487
488 let formatter = BinaryFormatter::from(None as Option<String>);
490 assert_eq!(formatter.get_separator(), ":");
491
492 let formatter: UppercaseHexadecimalFormatter = Some(String::from("-")).into();
494 assert_eq!(formatter.get_separator(), "-");
495
496 let formatter: OctalFormatter = (None as Option<String>).into();
497 assert_eq!(formatter.get_separator(), ":");
498
499 let _decimal: DecimalFormatter = Some(String::from("::")).into();
501 let _octal: OctalFormatter = (None as Option<String>).into();
502 let _uppercase_hex: UppercaseHexadecimalFormatter = Some(String::from(" ")).into();
503 let _lowercase_hex: LowercaseHexadecimalFormatter = Some(String::from(",")).into();
504 let _binary: BinaryFormatter = (None as Option<String>).into();
505 }
506
507 #[test]
508 fn test_format_byte() {
509 let decimal = DecimalFormatter::new_default();
511 let octal = OctalFormatter::new_default();
512 let uppercase_hex = UppercaseHexadecimalFormatter::new_default();
513 let lowercase_hex = LowercaseHexadecimalFormatter::new_default();
514 let binary = BinaryFormatter::new_default();
515
516 let byte = 255u8;
517 assert_eq!(decimal.format_byte(&byte), "255");
518 assert_eq!(octal.format_byte(&byte), "377");
519 assert_eq!(uppercase_hex.format_byte(&byte), "FF");
520 assert_eq!(lowercase_hex.format_byte(&byte), "ff");
521 assert_eq!(binary.format_byte(&byte), "11111111");
522
523 let byte = 0u8;
524 assert_eq!(decimal.format_byte(&byte), "0");
525 assert_eq!(octal.format_byte(&byte), "000");
526 assert_eq!(uppercase_hex.format_byte(&byte), "00");
527 assert_eq!(lowercase_hex.format_byte(&byte), "00");
528 assert_eq!(binary.format_byte(&byte), "00000000");
529 }
530
531 #[test]
532 fn test_edge_cases() {
533 let formatter = DecimalFormatter::new_default();
534
535 assert_eq!(formatter.format_buffer(&[]), "");
537
538 assert_eq!(formatter.format_buffer(&[42]), "42");
540
541 let formatter = DecimalFormatter::new(Some(" -> "));
543 assert_eq!(formatter.format_buffer(&[1, 2, 3]), "1 -> 2 -> 3");
544
545 let formatter = DecimalFormatter::new(Some(""));
547 assert_eq!(formatter.format_buffer(&[10, 11, 12]), "101112");
548 }
549
550 #[test]
551 fn test_default_trait() {
552 let decimal = DecimalFormatter::default();
554 let octal = OctalFormatter::default();
555 let uppercase_hex = UppercaseHexadecimalFormatter::default();
556 let lowercase_hex = LowercaseHexadecimalFormatter::default();
557 let binary = BinaryFormatter::default();
558
559 assert_eq!(decimal.get_separator(), ":");
561 assert_eq!(octal.get_separator(), ":");
562 assert_eq!(uppercase_hex.get_separator(), ":");
563 assert_eq!(lowercase_hex.get_separator(), ":");
564 assert_eq!(binary.get_separator(), ":");
565 }
566
567 #[test]
568 fn test_clone() {
569 let original = DecimalFormatter::new(Some("-"));
571 let cloned = original.clone();
572
573 assert_eq!(original.get_separator(), cloned.get_separator());
574 assert_eq!(
575 original.format_buffer(&[1, 2, 3]),
576 cloned.format_buffer(&[1, 2, 3])
577 );
578
579 let original_result = original.format_buffer(&[10, 20]);
581 let cloned_result = cloned.format_buffer(&[10, 20]);
582 assert_eq!(original_result, cloned_result);
583 }
584
585 fn assert_unpin<T: Unpin>() {}
586
587 #[test]
588 fn test_unpin() {
589 assert_unpin::<BinaryFormatter>();
590 assert_unpin::<DecimalFormatter>();
591 assert_unpin::<LowercaseHexadecimalFormatter>();
592 assert_unpin::<UppercaseHexadecimalFormatter>();
593 assert_unpin::<OctalFormatter>();
594 }
595
596 #[test]
597 fn test_trait_object_safety() {
598 let lowercase_hexadecimal: Box<dyn BufferFormatter> =
600 Box::new(LowercaseHexadecimalFormatter::new(None));
601 let uppercase_hexadecimal: Box<dyn BufferFormatter> =
602 Box::new(UppercaseHexadecimalFormatter::new(None));
603 let decimal: Box<dyn BufferFormatter> = Box::new(DecimalFormatter::new(None));
604 let octal: Box<dyn BufferFormatter> = Box::new(OctalFormatter::new(None));
605 let binary: Box<dyn BufferFormatter> = Box::new(BinaryFormatter::new(None));
606
607 assert_eq!(lowercase_hexadecimal.get_separator(), ":");
609 assert!(!lowercase_hexadecimal.format_buffer(b"test").is_empty());
610
611 assert_eq!(uppercase_hexadecimal.get_separator(), ":");
612 assert!(!uppercase_hexadecimal.format_buffer(b"test").is_empty());
613
614 assert_eq!(decimal.get_separator(), ":");
615 assert!(!decimal.format_buffer(b"test").is_empty());
616
617 assert_eq!(octal.get_separator(), ":");
618 assert!(!octal.format_buffer(b"test").is_empty());
619
620 assert_eq!(binary.get_separator(), ":");
621 assert!(!binary.format_buffer(b"test").is_empty());
622 }
623
624 fn assert_buffer_formatter<T: BufferFormatter>() {}
625
626 #[test]
627 fn test_box() {
628 assert_buffer_formatter::<Box<dyn BufferFormatter>>();
629 assert_buffer_formatter::<Box<LowercaseHexadecimalFormatter>>();
630 assert_buffer_formatter::<Box<UppercaseHexadecimalFormatter>>();
631 assert_buffer_formatter::<Box<DecimalFormatter>>();
632 assert_buffer_formatter::<Box<OctalFormatter>>();
633 assert_buffer_formatter::<Box<BinaryFormatter>>();
634 }
635
636 #[test]
637 fn test_arc() {
638 assert_buffer_formatter::<Arc<LowercaseHexadecimalFormatter>>();
639 assert_buffer_formatter::<Arc<UppercaseHexadecimalFormatter>>();
640 assert_buffer_formatter::<Arc<DecimalFormatter>>();
641 assert_buffer_formatter::<Arc<OctalFormatter>>();
642 assert_buffer_formatter::<Arc<BinaryFormatter>>();
643 assert_buffer_formatter::<Arc<dyn BufferFormatter + Sync>>();
644 }
645
646 fn assert_send<T: Send>() {}
647
648 #[test]
649 fn test_send() {
650 assert_send::<LowercaseHexadecimalFormatter>();
651 assert_send::<UppercaseHexadecimalFormatter>();
652 assert_send::<DecimalFormatter>();
653 assert_send::<OctalFormatter>();
654 assert_send::<BinaryFormatter>();
655
656 assert_send::<Box<dyn BufferFormatter>>();
657 assert_send::<Box<LowercaseHexadecimalFormatter>>();
658 assert_send::<Box<UppercaseHexadecimalFormatter>>();
659 assert_send::<Box<DecimalFormatter>>();
660 assert_send::<Box<OctalFormatter>>();
661 assert_send::<Box<BinaryFormatter>>();
662
663 assert_send::<Arc<LowercaseHexadecimalFormatter>>();
665 assert_send::<Arc<UppercaseHexadecimalFormatter>>();
666 assert_send::<Arc<DecimalFormatter>>();
667 assert_send::<Arc<OctalFormatter>>();
668 assert_send::<Arc<BinaryFormatter>>();
669 assert_send::<Arc<dyn BufferFormatter + Sync>>();
670 }
671
672 #[test]
673 fn test_arc_impl() {
674 let formatter = Arc::new(DecimalFormatter::new(Some(" -> ")));
676 assert_eq!(formatter.get_separator(), " -> ");
677 assert_eq!(
678 formatter.format_buffer(FORMATTING_TEST_VALUES),
679 String::from("10 -> 11 -> 12 -> 13 -> 14 -> 15 -> 16 -> 17 -> 18")
680 );
681
682 let formatter_clone = Arc::clone(&formatter);
684 assert_eq!(formatter_clone.format_buffer(&[42, 43]), "42 -> 43");
685
686 let octal = Arc::new(OctalFormatter::new_default());
688 assert_eq!(octal.format_buffer(&[8, 9, 10]), "010:011:012");
689
690 let uppercase_hex = Arc::new(UppercaseHexadecimalFormatter::new(Some(",")));
691 assert_eq!(uppercase_hex.format_buffer(&[255, 254]), "FF,FE");
692
693 let lowercase_hex = Arc::new(LowercaseHexadecimalFormatter::new(Some(" ")));
694 assert_eq!(lowercase_hex.format_buffer(&[0xAB, 0xCD]), "ab cd");
695
696 let binary = Arc::new(BinaryFormatter::new(Some("|")));
697 assert_eq!(binary.format_buffer(&[3, 7]), "00000011|00000111");
698 }
699
700 #[test]
701 fn test_arc_trait_object() {
702 let formatter: Arc<dyn BufferFormatter + Sync> = Arc::new(DecimalFormatter::new(Some("-")));
704
705 assert_eq!(formatter.get_separator(), "-");
706 assert_eq!(formatter.format_buffer(&[1, 2, 3]), "1-2-3");
707
708 let formatters: Vec<Arc<dyn BufferFormatter + Sync>> = vec![
710 Arc::new(DecimalFormatter::new_default()),
711 Arc::new(OctalFormatter::new_default()),
712 Arc::new(UppercaseHexadecimalFormatter::new_default()),
713 Arc::new(LowercaseHexadecimalFormatter::new_default()),
714 Arc::new(BinaryFormatter::new_default()),
715 ];
716
717 let data = vec![10u8];
718 let results: Vec<String> = formatters.iter().map(|f| f.format_buffer(&data)).collect();
719
720 assert_eq!(results[0], "10"); assert_eq!(results[1], "012"); assert_eq!(results[2], "0A"); assert_eq!(results[3], "0a"); assert_eq!(results[4], "00001010"); let formatter_clone = Arc::clone(&formatters[0]);
728 assert_eq!(formatter_clone.format_buffer(&[42]), "42");
729 }
730
731 #[test]
732 fn test_arc_thread_safety() {
733 let formatter = Arc::new(DecimalFormatter::new(Some(" | ")));
735 let formatter_clone = Arc::clone(&formatter);
736
737 let handle = thread::spawn(move || formatter_clone.format_buffer(&[1, 2, 3, 4, 5]));
738
739 let result = handle.join().unwrap();
740 assert_eq!(result, "1 | 2 | 3 | 4 | 5");
741
742 assert_eq!(formatter.format_buffer(&[10, 20]), "10 | 20");
744 }
745
746 #[test]
747 fn test_arc_wrapper_types() {
748 let arc_formatter = Arc::new(OctalFormatter::new(Some("-")));
750 assert_eq!(arc_formatter.format_buffer(&[8, 9]), "010-011");
751
752 let arc_trait: Arc<dyn BufferFormatter + Sync> = Arc::new(DecimalFormatter::new(Some(" ")));
754 assert_eq!(arc_trait.format_buffer(&[1, 2, 3]), "1 2 3");
755 }
756
757 #[test]
758 fn test_partial_eq() {
759 let formatter1 = DecimalFormatter::new(Some("-"));
761 let formatter2 = DecimalFormatter::new(Some("-"));
762 assert_eq!(formatter1, formatter2);
763
764 let formatter3 = DecimalFormatter::new_default();
766 let formatter4 = DecimalFormatter::new(None);
767 assert_eq!(formatter3, formatter4);
768
769 let formatter5 = DecimalFormatter::new(Some("-"));
771 let formatter6 = DecimalFormatter::new(Some(":"));
772 assert_ne!(formatter5, formatter6);
773
774 let octal1 = OctalFormatter::new(Some(" "));
777 let octal2 = OctalFormatter::new(Some(" "));
778 assert_eq!(octal1, octal2);
779
780 let formatter7 = UppercaseHexadecimalFormatter::new_static(Some("-"));
782 let formatter8 = UppercaseHexadecimalFormatter::new(Some("-"));
783 assert_eq!(formatter7, formatter8);
784
785 let formatter9 = LowercaseHexadecimalFormatter::new_owned(Some(String::from(",")));
787 let formatter10 = LowercaseHexadecimalFormatter::new(Some(","));
788 assert_eq!(formatter9, formatter10);
789 }
790
791 #[test]
792 fn test_hash() {
793 use std::collections::HashMap;
794
795 let formatter1 = DecimalFormatter::new(Some("-"));
797 let formatter2 = DecimalFormatter::new(Some("-"));
798
799 let mut map = HashMap::new();
800 map.insert(formatter1, "first");
801 map.insert(formatter2, "second"); assert_eq!(map.len(), 1);
804 assert_eq!(map.get(&DecimalFormatter::new(Some("-"))), Some(&"second"));
805
806 use std::collections::HashSet;
808 let mut set = HashSet::new();
809 set.insert(OctalFormatter::new(Some(":")));
810 set.insert(OctalFormatter::new(Some(":")));
811 set.insert(OctalFormatter::new(Some("-")));
812
813 assert_eq!(set.len(), 2); let mut decimal_set = HashSet::new();
817 decimal_set.insert(DecimalFormatter::new_default());
818 decimal_set.insert(DecimalFormatter::new(Some("-")));
819 assert_eq!(decimal_set.len(), 2);
820
821 let mut octal_set = HashSet::new();
822 octal_set.insert(OctalFormatter::new_default());
823 assert_eq!(octal_set.len(), 1);
824
825 let mut upper_hex_set = HashSet::new();
826 upper_hex_set.insert(UppercaseHexadecimalFormatter::new(Some(" ")));
827 assert_eq!(upper_hex_set.len(), 1);
828
829 let mut lower_hex_set = HashSet::new();
830 lower_hex_set.insert(LowercaseHexadecimalFormatter::new(Some(" ")));
831 assert_eq!(lower_hex_set.len(), 1);
832
833 let mut binary_set = HashSet::new();
834 binary_set.insert(BinaryFormatter::new_static(Some(",")));
835 assert_eq!(binary_set.len(), 1);
836 }
837
838 #[test]
839 fn test_display() {
840 let formatter = DecimalFormatter::new(Some("-"));
842 assert_eq!(
843 format!("{}", formatter),
844 "DecimalFormatter(separator: \"-\")"
845 );
846
847 let formatter = OctalFormatter::new_default();
848 assert_eq!(format!("{}", formatter), "OctalFormatter(separator: \":\")");
849
850 let formatter = UppercaseHexadecimalFormatter::new(Some(" | "));
851 assert_eq!(
852 format!("{}", formatter),
853 "UppercaseHexadecimalFormatter(separator: \" | \")"
854 );
855
856 let formatter = LowercaseHexadecimalFormatter::new(Some(""));
857 assert_eq!(
858 format!("{}", formatter),
859 "LowercaseHexadecimalFormatter(separator: \"\")"
860 );
861
862 let formatter = BinaryFormatter::new_owned(Some(String::from(" -> ")));
863 assert_eq!(
864 format!("{}", formatter),
865 "BinaryFormatter(separator: \" -> \")"
866 );
867
868 let formatter = DecimalFormatter::new_static(Some("::"));
870 let output = format!("Using formatter: {}", formatter);
871 assert_eq!(
872 output,
873 "Using formatter: DecimalFormatter(separator: \"::\")"
874 );
875 }
876
877 #[test]
878 fn test_display_with_special_characters() {
879 let formatter = DecimalFormatter::new(Some("\n"));
884 assert_eq!(
885 format!("{}", formatter),
886 "DecimalFormatter(separator: \"\\n\")"
887 );
888
889 let formatter = OctalFormatter::new(Some("\t"));
891 assert_eq!(
892 format!("{}", formatter),
893 "OctalFormatter(separator: \"\\t\")"
894 );
895
896 let formatter = UppercaseHexadecimalFormatter::new(Some("\r"));
898 assert_eq!(
899 format!("{}", formatter),
900 "UppercaseHexadecimalFormatter(separator: \"\\r\")"
901 );
902
903 let formatter = LowercaseHexadecimalFormatter::new(Some("\""));
905 assert_eq!(
906 format!("{}", formatter),
907 "LowercaseHexadecimalFormatter(separator: \"\\\"\")"
908 );
909
910 let formatter = BinaryFormatter::new(Some("\\"));
912 assert_eq!(
913 format!("{}", formatter),
914 "BinaryFormatter(separator: \"\\\\\")"
915 );
916
917 let formatter = DecimalFormatter::new(Some("\n\t\r\"\\"));
919 assert_eq!(
920 format!("{}", formatter),
921 "DecimalFormatter(separator: \"\\n\\t\\r\\\"\\\\\")"
922 );
923
924 let malicious_sep = "\nINFO: Fake log entry";
926 let formatter = OctalFormatter::new(Some(malicious_sep));
927 let output = format!("{}", formatter);
928 assert!(output.contains("\\n"));
930 assert!(!output.contains("\nINFO"));
931 assert_eq!(
932 output,
933 "OctalFormatter(separator: \"\\nINFO: Fake log entry\")"
934 );
935
936 let formatter = UppercaseHexadecimalFormatter::new(Some("→\u{200B}←")); let output = format!("{}", formatter);
939 assert!(output.contains("separator:"));
941 }
942}