use super::funejson::Value; fn digit_value(b: u8) -> i64 { match b { b'0'..=b'9' => (b - b'0') as i64, b'a'..=b'f' => (b - b'a' + 10) as i64, b'A'..=b'F' => (b - b'A' + 10) as i64, _ => -1, } } /// Hexadecimal text back to bytes, either case, strictly. /// /// A 0x prefix, whitespace or an odd digit count is an error, not skipped. /// Characters are checked before the length, so the answer for non-ASCII /// input does not depend on how a language counts its length. /// /// # Panics /// Panics on any character that is not a hex digit, or an odd digit count. pub fn hex_decode(text: &str) -> Vec { let mut digits = Vec::with_capacity(text.len()); for &b in text.as_bytes() { let d = digit_value(b); if d < 0 { panic!("hex text may only contain the digits 0-9, a-f and A-F"); } digits.push(d); } if digits.len() % 2 != 0 { panic!("hex text must have an even number of digits, received {}", digits.len()); } digits.chunks(2).map(|pair| pair[0] * 16 + pair[1]).collect() } pub fn fune_vector(args: &[Value]) -> Value { let text = match &args[0] { Value::Str(s) => s.as_str(), _ => panic!("hex text must be a string"), }; Value::Arr(hex_decode(text).into_iter().map(Value::Int).collect()) }