1#![allow(clippy::ptr_as_ptr, clippy::borrow_as_ptr, clippy::missing_errors_doc)]
4
5use core::iter;
6
7#[cfg(feature = "alloc")]
8#[allow(unused_imports)]
9use alloc::{
10 borrow::{Cow, ToOwned},
11 boxed::Box,
12 rc::Rc,
13 string::String,
14 sync::Arc,
15 vec::Vec,
16};
17
18#[cfg_attr(feature = "alloc", doc = "\n[`encode`]: crate::encode")]
33#[cfg_attr(not(feature = "alloc"), doc = "\n[`encode`]: crate::encode_to_slice")]
34#[deprecated(note = "use `ToHexExt` instead")]
35pub trait ToHex {
36 fn encode_hex<T: iter::FromIterator<char>>(&self) -> T;
39
40 fn encode_hex_upper<T: iter::FromIterator<char>>(&self) -> T;
43}
44
45#[cfg(feature = "alloc")]
61pub trait ToHexExt {
62 fn encode_hex(&self) -> String;
65
66 fn encode_hex_upper(&self) -> String;
69
70 fn encode_hex_with_prefix(&self) -> String;
73
74 fn encode_hex_upper_with_prefix(&self) -> String;
77}
78
79struct BytesToHexChars<'a, const UPPER: bool> {
80 inner: core::slice::Iter<'a, u8>,
81 next: Option<char>,
82}
83
84impl<'a, const UPPER: bool> BytesToHexChars<'a, UPPER> {
85 fn new(inner: &'a [u8]) -> Self {
86 BytesToHexChars {
87 inner: inner.iter(),
88 next: None,
89 }
90 }
91}
92
93impl<const UPPER: bool> Iterator for BytesToHexChars<'_, UPPER> {
94 type Item = char;
95
96 fn next(&mut self) -> Option<Self::Item> {
97 match self.next.take() {
98 Some(current) => Some(current),
99 None => self.inner.next().map(|byte| {
100 let (high, low) = crate::byte2hex::<UPPER>(*byte);
101 self.next = Some(low as char);
102 high as char
103 }),
104 }
105 }
106}
107
108#[inline]
109fn encode_to_iter<T: iter::FromIterator<char>, const UPPER: bool>(source: &[u8]) -> T {
110 BytesToHexChars::<UPPER>::new(source).collect()
111}
112
113#[allow(deprecated)]
114impl<T: AsRef<[u8]>> ToHex for T {
115 #[inline]
116 fn encode_hex<U: iter::FromIterator<char>>(&self) -> U {
117 encode_to_iter::<_, false>(self.as_ref())
118 }
119
120 #[inline]
121 fn encode_hex_upper<U: iter::FromIterator<char>>(&self) -> U {
122 encode_to_iter::<_, true>(self.as_ref())
123 }
124}
125
126#[cfg(feature = "alloc")]
127impl<T: AsRef<[u8]>> ToHexExt for T {
128 #[inline]
129 fn encode_hex(&self) -> String {
130 crate::encode(self)
131 }
132
133 #[inline]
134 fn encode_hex_upper(&self) -> String {
135 crate::encode_upper(self)
136 }
137
138 #[inline]
139 fn encode_hex_with_prefix(&self) -> String {
140 crate::encode_prefixed(self)
141 }
142
143 #[inline]
144 fn encode_hex_upper_with_prefix(&self) -> String {
145 crate::encode_upper_prefixed(self)
146 }
147}
148
149pub trait FromHex: Sized {
163 type Error;
165
166 fn from_hex<T: AsRef<[u8]>>(hex: T) -> Result<Self, Self::Error>;
172}
173
174#[cfg(feature = "alloc")]
175impl<T: FromHex> FromHex for Box<T> {
176 type Error = T::Error;
177
178 #[inline]
179 fn from_hex<U: AsRef<[u8]>>(hex: U) -> Result<Self, Self::Error> {
180 FromHex::from_hex(hex.as_ref()).map(Self::new)
181 }
182}
183
184#[cfg(feature = "alloc")]
185impl<T> FromHex for Cow<'_, T>
186where
187 T: ToOwned + ?Sized,
188 T::Owned: FromHex,
189{
190 type Error = <T::Owned as FromHex>::Error;
191
192 #[inline]
193 fn from_hex<U: AsRef<[u8]>>(hex: U) -> Result<Self, Self::Error> {
194 FromHex::from_hex(hex.as_ref()).map(Cow::Owned)
195 }
196}
197
198#[cfg(feature = "alloc")]
199impl<T: FromHex> FromHex for Rc<T> {
200 type Error = T::Error;
201
202 #[inline]
203 fn from_hex<U: AsRef<[u8]>>(hex: U) -> Result<Self, Self::Error> {
204 FromHex::from_hex(hex.as_ref()).map(Self::new)
205 }
206}
207
208#[cfg(feature = "alloc")]
209impl<T: FromHex> FromHex for Arc<T> {
210 type Error = T::Error;
211
212 #[inline]
213 fn from_hex<U: AsRef<[u8]>>(hex: U) -> Result<Self, Self::Error> {
214 FromHex::from_hex(hex.as_ref()).map(Self::new)
215 }
216}
217
218#[cfg(feature = "alloc")]
219impl FromHex for Vec<u8> {
220 type Error = crate::FromHexError;
221
222 #[inline]
223 fn from_hex<T: AsRef<[u8]>>(hex: T) -> Result<Self, Self::Error> {
224 crate::decode(hex.as_ref())
225 }
226}
227
228#[cfg(feature = "alloc")]
229impl FromHex for Vec<i8> {
230 type Error = crate::FromHexError;
231
232 #[inline]
233 fn from_hex<T: AsRef<[u8]>>(hex: T) -> Result<Self, Self::Error> {
234 crate::decode(hex.as_ref()).map(|vec| unsafe { core::mem::transmute::<Vec<u8>, Self>(vec) })
236 }
237}
238
239#[cfg(feature = "alloc")]
240impl FromHex for Box<[u8]> {
241 type Error = crate::FromHexError;
242
243 #[inline]
244 fn from_hex<T: AsRef<[u8]>>(hex: T) -> Result<Self, Self::Error> {
245 <Vec<u8>>::from_hex(hex).map(Vec::into_boxed_slice)
246 }
247}
248
249#[cfg(feature = "alloc")]
250impl FromHex for Box<[i8]> {
251 type Error = crate::FromHexError;
252
253 #[inline]
254 fn from_hex<T: AsRef<[u8]>>(hex: T) -> Result<Self, Self::Error> {
255 <Vec<i8>>::from_hex(hex).map(Vec::into_boxed_slice)
256 }
257}
258
259impl<const N: usize> FromHex for [u8; N] {
260 type Error = crate::FromHexError;
261
262 #[inline]
263 fn from_hex<T: AsRef<[u8]>>(hex: T) -> Result<Self, Self::Error> {
264 crate::decode_to_array(hex.as_ref())
265 }
266}
267
268impl<const N: usize> FromHex for [i8; N] {
269 type Error = crate::FromHexError;
270
271 #[inline]
272 fn from_hex<T: AsRef<[u8]>>(hex: T) -> Result<Self, Self::Error> {
273 crate::decode_to_array(hex.as_ref())
275 .map(|buf| unsafe { *(&buf as *const [u8; N] as *const [i8; N]) })
276 }
277}