easy_hex/
decode.rs

1use hex::FromHexError;
2
3use crate::encode::SMALL_SER_LEN;
4
5pub(crate) const SMALL_DES_LEN: usize = SMALL_SER_LEN / 2;
6
7fn fast_deserialize<V>(v: &str, out: impl FnOnce(&[u8]) -> V) -> Result<V, FromHexError> {
8    if v.len() % 2 != 0 {
9        return Err(FromHexError::OddLength);
10    }
11
12    let byte_len = v.len() / 2;
13    let mut array;
14    let mut vec;
15    let buf;
16    if byte_len <= SMALL_DES_LEN {
17        array = [0; SMALL_DES_LEN];
18        buf = &mut array[..byte_len];
19    } else {
20        vec = vec![0; byte_len];
21        buf = &mut vec[..];
22    }
23    hex::decode_to_slice(v, buf)?;
24
25    Ok(out(buf))
26}
27
28pub(crate) fn fast_deserialize_into<T>(v: &str) -> Result<T, FromHexError>
29where
30    T: for<'a> TryFrom<&'a [u8]>,
31{
32    fast_deserialize(v, |buf| {
33        T::try_from(buf).map_err(|_| FromHexError::InvalidStringLength)
34    })?
35}
36
37/// Decodes a hex string to a byte container.
38///
39/// This accepts both lower and upper case strings.
40pub fn decode_into<T>(v: &str) -> Result<T, FromHexError>
41where
42    T: for<'a> TryFrom<&'a [u8]>,
43{
44    fast_deserialize_into(v)
45}
46
47/// Decodes a hex string to a byte slice.
48///
49/// This accepts both lower and upper case strings.
50/// The resulting byte slice is passed to the closure.
51pub fn decode<V>(v: &str, out: impl FnOnce(&[u8]) -> V) -> Result<V, FromHexError> {
52    fast_deserialize(v, out)
53}