1#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
2pub enum Case {
3 #[default]
4 Lower,
5 Upper,
6}
7
8#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
10pub struct DisplayOptions {
11 pub with_prefix: bool,
14 pub case: Case,
16}
17
18#[derive(Debug, Clone, Copy)]
20pub struct Hex<T> {
21 options: DisplayOptions,
22 data: T,
23}
24
25impl<T: AsRef<[u8]>> core::fmt::Display for Hex<T> {
26 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
27 if self.options.with_prefix {
28 write!(f, "0x")?;
29 }
30 match self.options.case {
31 Case::Lower => {
32 for byte in self.data.as_ref() {
33 write!(f, "{byte:02x}")?;
34 }
35 }
36 Case::Upper => {
37 for byte in self.data.as_ref() {
38 write!(f, "{byte:02X}")?;
39 }
40 }
41 }
42 Ok(())
43 }
44}
45
46impl<T: AsRef<[u8]>> Hex<T> {
47 pub fn new(data: T) -> Self {
49 Self::new_with_options(data, DisplayOptions::default())
50 }
51
52 pub fn new_with_options(data: T, options: DisplayOptions) -> Self {
54 Self { options, data }
55 }
56}
57
58impl<T> Hex<T> {
59 pub fn with_options(mut self, options: DisplayOptions) -> Self {
61 self.options = options;
62 self
63 }
64
65 pub fn with_prefix(mut self, with_prefix: bool) -> Self {
67 self.options.with_prefix = with_prefix;
68 self
69 }
70
71 pub fn with_case(mut self, case: Case) -> Self {
73 self.options.case = case;
74 self
75 }
76}
77
78pub fn hex<T: AsRef<[u8]>>(data: T) -> Hex<T> {
80 Hex::new(data)
81}