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)]
18pub enum ParseHexError {
20 InvalidCharacter,
21 TooLong,
22 TooShort,
23 Other
24}
25
26pub fn clean_0x(s: &str) -> &str {
28 if s.starts_with("0x") {
29 &s[2..]
30 } else {
31 s
32 }
33}
34
35pub 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 { 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
75pub 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}