summaryrefslogtreecommitdiffstats
path: root/vendor/ct-codecs/src/hex.rs
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/ct-codecs/src/hex.rs')
-rw-r--r--vendor/ct-codecs/src/hex.rs94
1 files changed, 94 insertions, 0 deletions
diff --git a/vendor/ct-codecs/src/hex.rs b/vendor/ct-codecs/src/hex.rs
new file mode 100644
index 000000000..a371b82c5
--- /dev/null
+++ b/vendor/ct-codecs/src/hex.rs
@@ -0,0 +1,94 @@
+use crate::error::*;
+use crate::{Decoder, Encoder};
+
+pub struct Hex;
+
+impl Encoder for Hex {
+ #[inline]
+ fn encoded_len(bin_len: usize) -> Result<usize, Error> {
+ bin_len.checked_mul(2).ok_or(Error::Overflow)
+ }
+
+ fn encode<IN: AsRef<[u8]>>(hex: &mut [u8], bin: IN) -> Result<&[u8], Error> {
+ let bin = bin.as_ref();
+ let bin_len = bin.len();
+ let hex_maxlen = hex.len();
+ if hex_maxlen < bin_len.checked_shl(1).ok_or(Error::Overflow)? {
+ return Err(Error::Overflow);
+ }
+ for (i, v) in bin.iter().enumerate() {
+ let (b, c) = ((v >> 4) as u16, (v & 0xf) as u16);
+ let x = (((87 + c + (((c.wrapping_sub(10)) >> 8) & !38)) as u8) as u16) << 8
+ | ((87 + b + (((b.wrapping_sub(10)) >> 8) & !38)) as u8) as u16;
+ hex[i * 2] = x as u8;
+ hex[i * 2 + 1] = (x >> 8) as u8;
+ }
+ Ok(&hex[..bin_len * 2])
+ }
+}
+
+impl Decoder for Hex {
+ fn decode<'t, IN: AsRef<[u8]>>(
+ bin: &'t mut [u8],
+ hex: IN,
+ ignore: Option<&[u8]>,
+ ) -> Result<&'t [u8], Error> {
+ let hex = hex.as_ref();
+ let bin_maxlen = bin.len();
+ let mut bin_pos = 0;
+ let mut state = false;
+ let mut c_acc = 0;
+ for &c in hex {
+ let c_num = c ^ 48;
+ let c_num0 = ((c_num as u16).wrapping_sub(10) >> 8) as u8;
+ let c_alpha = (c & !32).wrapping_sub(55);
+ let c_alpha0 = (((c_alpha as u16).wrapping_sub(10)
+ ^ ((c_alpha as u16).wrapping_sub(16)))
+ >> 8) as u8;
+ if (c_num0 | c_alpha0) == 0 {
+ match ignore {
+ Some(ignore) if ignore.contains(&c) => continue,
+ _ => return Err(Error::InvalidInput),
+ };
+ }
+ let c_val = (c_num0 & c_num) | (c_alpha0 & c_alpha);
+ if bin_pos >= bin_maxlen {
+ return Err(Error::Overflow);
+ }
+ if !state {
+ c_acc = c_val << 4;
+ } else {
+ bin[bin_pos] = c_acc | c_val;
+ bin_pos += 1;
+ }
+ state = !state;
+ }
+ if state {
+ return Err(Error::InvalidInput);
+ }
+ Ok(&bin[..bin_pos])
+ }
+}
+
+#[cfg(feature = "std")]
+#[test]
+fn test_hex() {
+ let bin = [1u8, 5, 11, 15, 19, 131];
+ let hex = Hex::encode_to_string(&bin).unwrap();
+ let expected = "01050b0f1383";
+ assert_eq!(hex, expected);
+ let bin2 = Hex::decode_to_vec(&hex, None).unwrap();
+ assert_eq!(bin, &bin2[..]);
+}
+
+#[test]
+fn test_hex_no_std() {
+ let bin = [1u8, 5, 11, 15, 19, 131];
+ let expected = "01050b0f1383";
+ let mut hex = [0u8; 12];
+ let hex = Hex::encode_to_str(&mut hex, &bin).unwrap();
+ assert_eq!(&hex, &expected);
+ let mut bin2 = [0u8; 6];
+ let bin2 = Hex::decode(&mut bin2, &hex, None).unwrap();
+ assert_eq!(bin, bin2);
+}