1use core::{
22 fmt,
23 ops::{Index, RangeFrom, RangeTo},
24 str,
25};
26#[cfg(feature = "serde")]
27use {
28 core::{marker::PhantomData, str::FromStr},
29 serde::de,
30};
31
32pub enum ByteSliceFormatter<'a> {
36 Array(&'a [u8; 32]),
38 Dynamic(&'a [u8]),
43}
44
45impl ByteSliceFormatter<'_> {
46 fn len(&self) -> usize {
47 match self {
48 ByteSliceFormatter::Array(arr) => arr.len(),
49 ByteSliceFormatter::Dynamic(slice) => slice.len(),
50 }
51 }
52}
53
54impl Index<RangeTo<usize>> for ByteSliceFormatter<'_> {
55 type Output = <[u8] as Index<RangeTo<usize>>>::Output;
56
57 fn index(&self, index: RangeTo<usize>) -> &Self::Output {
58 match self {
59 ByteSliceFormatter::Array(arr) => &arr[index],
60 ByteSliceFormatter::Dynamic(slice) => &slice[index],
61 }
62 }
63}
64
65impl Index<RangeFrom<usize>> for ByteSliceFormatter<'_> {
66 type Output = <[u8] as Index<RangeFrom<usize>>>::Output;
67
68 fn index(&self, index: RangeFrom<usize>) -> &Self::Output {
69 match self {
70 ByteSliceFormatter::Array(arr) => &arr[index],
71 ByteSliceFormatter::Dynamic(slice) => &slice[index],
72 }
73 }
74}
75
76impl fmt::Display for ByteSliceFormatter<'_> {
77 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
78 const STACK_LEN: usize = 32;
79
80 let len = self.len();
81 let median = len.div_ceil(2);
82
83 let mut e1 = median;
84 let mut s2 = median;
85
86 if let Some(precision) = f.precision()
87 && precision < median
88 {
89 e1 = precision;
90 s2 = len - precision;
91 }
92
93 let out1_len = e1 * 2;
94 let out2_len = (len - s2) * 2;
95
96 let mut out1_vec;
97 let mut out2_vec;
98
99 let (out1, out2) = match self {
100 ByteSliceFormatter::Array(_arr) => (
101 &mut [0u8; STACK_LEN] as &mut [u8],
102 &mut [0u8; STACK_LEN] as &mut [u8],
103 ),
104 ByteSliceFormatter::Dynamic(slice) if slice.len() <= STACK_LEN => (
105 &mut [0u8; STACK_LEN] as &mut [u8],
106 &mut [0u8; STACK_LEN] as &mut [u8],
107 ),
108 ByteSliceFormatter::Dynamic(_slice) => {
109 out1_vec = alloc::vec![0u8; out1_len];
110 out2_vec = alloc::vec![0u8; out2_len];
111 (&mut out1_vec[..], &mut out2_vec[..])
112 }
113 };
114
115 let _ = hex::encode_to_slice(&self[..e1], &mut out1[..out1_len]);
116 let _ = hex::encode_to_slice(&self[s2..], &mut out2[..out2_len]);
117
118 let p1 = unsafe { str::from_utf8_unchecked(&out1[..out1_len]) };
119 let p2 = unsafe { str::from_utf8_unchecked(&out2[..out2_len]) };
120 let sep = if e1.ne(&s2) { ".." } else { Default::default() };
121
122 write!(f, "0x{p1}{sep}{p2}")
123 }
124}
125
126#[cfg(feature = "serde")]
127pub(crate) struct HexStrVisitor<T: FromStr>(PhantomData<T>);
128
129#[cfg(feature = "serde")]
130impl<T: FromStr> HexStrVisitor<T> {
131 pub fn new() -> Self {
132 Self(PhantomData)
133 }
134}
135
136#[cfg(feature = "serde")]
137impl<T: FromStr> de::Visitor<'_> for HexStrVisitor<T> {
138 type Value = T;
139
140 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
141 formatter.write_str("a string in hex format starting with 0x")
142 }
143
144 fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
145 where
146 E: de::Error,
147 {
148 value
149 .parse()
150 .map_err(|_| de::Error::invalid_value(de::Unexpected::Str(value), &self))
151 }
152}