hexutil/
lib.rs

1#![cfg_attr(not(feature = "std"), no_std)]
2#![cfg_attr(not(feature = "std"), feature(alloc))]
3
4#[cfg(not(feature = "std"))]
5extern crate alloc;
6
7#[cfg(feature = "std")]
8use std::fmt::Write;
9
10#[cfg(not(feature = "std"))]
11use core::fmt::Write;
12#[cfg(not(feature = "std"))]
13use alloc::{String, Vec};
14#[cfg(not(feature = "std"))]
15use alloc::string::ToString;
16
17#[derive(Debug)]
18/// Errors exhibited from `read_hex`.
19pub enum ParseHexError {
20    InvalidCharacter,
21    TooLong,
22    TooShort,
23    Other
24}
25
26/// Return `s` without the `0x` at the beginning of it, if any.
27pub fn clean_0x(s: &str) -> &str {
28    if s.starts_with("0x") {
29        &s[2..]
30    } else {
31        s
32    }
33}
34
35/// Parses a given hex string and return a list of bytes if
36/// succeeded. The string can optionally start by `0x`, which
37/// indicates that it is a hex representation.
38pub fn read_hex(s: &str) -> Result<Vec<u8>, ParseHexError> {
39    if s.starts_with("0x") {
40        return read_hex(&s[2..s.len()]);
41    }
42
43    if s.len() & 1 == 1 {
44        let mut new_s = "0".to_string();
45        new_s.push_str(s);
46        return read_hex(&new_s);
47    }
48
49    let mut res = Vec::<u8>::new();
50
51    let mut cur = 0;
52    let mut len = 0;
53    for c in s.chars() {
54        len += 1;
55        let v_option = c.to_digit(16);
56        if v_option.is_none() {
57            return Err(ParseHexError::InvalidCharacter);
58        }
59        let v = v_option.unwrap();
60        if len == 1 {
61            cur += v * 16;
62        } else { // len == 2
63            cur += v;
64        }
65        if len == 2 {
66            res.push(cur as u8);
67            cur = 0;
68            len = 0;
69        }
70    }
71
72    return Ok(res);
73}
74
75/// Given a bytearray, get a Ethereum-compatible string hex.
76pub fn to_hex(a: &[u8]) -> String {
77    let mut s = String::new();
78    write!(s, "0x").unwrap();
79    for v in a {
80        write!(s, "{:02x}", *v).unwrap();
81    }
82    s
83}
84
85#[cfg(test)]
86mod tests {
87    use super::read_hex;
88
89    #[test]
90    fn read_hex_zero() {
91        assert_eq!(read_hex("0x0").unwrap(), vec![0u8]);
92        assert_eq!(read_hex("0").unwrap(), vec![0u8]);
93    }
94}