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