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