|
| 1 | +// This file is dual licensed under the terms of the Apache License, Version |
| 2 | +// 2.0, and the BSD License. See the LICENSE file in the root of this repository |
| 3 | +// for complete details. |
| 4 | + |
| 5 | +pub fn hex_decode(v: &str) -> Option<Vec<u8>> { |
| 6 | + if v.len() % 2 != 0 { |
| 7 | + return None; |
| 8 | + } |
| 9 | + |
| 10 | + let mut b = Vec::with_capacity(v.len() / 2); |
| 11 | + let v = v.as_bytes(); |
| 12 | + for i in (0..v.len()).step_by(2) { |
| 13 | + let high = match v[i] { |
| 14 | + b @ b'0'..=b'9' => b - b'0', |
| 15 | + b @ b'a'..=b'f' => b - b'a' + 10, |
| 16 | + b @ b'A'..=b'F' => b - b'A' + 10, |
| 17 | + _ => return None, |
| 18 | + }; |
| 19 | + |
| 20 | + let low = match v[i + 1] { |
| 21 | + b @ b'0'..=b'9' => b - b'0', |
| 22 | + b @ b'a'..=b'f' => b - b'a' + 10, |
| 23 | + b @ b'A'..=b'F' => b - b'A' + 10, |
| 24 | + _ => return None, |
| 25 | + }; |
| 26 | + |
| 27 | + b.push((high << 4) | low); |
| 28 | + } |
| 29 | + |
| 30 | + Some(b) |
| 31 | +} |
| 32 | + |
| 33 | +#[cfg(test)] |
| 34 | +mod tests { |
| 35 | + use super::hex_decode; |
| 36 | + |
| 37 | + #[test] |
| 38 | + fn test_hex_decode() { |
| 39 | + for (text, expected) in [ |
| 40 | + ("", Some(vec![])), |
| 41 | + ("00", Some(vec![0])), |
| 42 | + ("0", None), |
| 43 | + ("12-0", None), |
| 44 | + ("120-", None), |
| 45 | + ("ab", Some(vec![0xAB])), |
| 46 | + ("AB", Some(vec![0xAB])), |
| 47 | + ("ABCD", Some(vec![0xAB, 0xCD])), |
| 48 | + ] { |
| 49 | + assert_eq!(hex_decode(text), expected); |
| 50 | + } |
| 51 | + } |
| 52 | +} |
0 commit comments