FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

GitHub Viewer

/// Used for marking indices in decoder arrays that are invalid characters /// /// Only useful externally when testing alphabets like in /// [tests/alphabet.rs](https://github.com/rogusdev/fast32/blob/main/tests/alphabets.rs) pub const INVALID_BYTE: u8 = u8::MAX; pub const U8_MASK_BOT_5: u8 = 0b00011111; pub const U8_MASK_BOT_4: u8 = 0b00001111; pub const U8_MASK_TOP_4: u8 = 0b11110000; pub const U8_MASK_TOP_3: u8 = 0b11100000; pub const U8_MASK_BOT_2: u8 = 0b00000011; pub const U8_MASK_TOP_1: u8 = 0b10000000; pub const U8_MASK_BOT_1: u8 = 0b00000001; pub const U8_MASK_TOP_2: u8 = 0b11000000; pub const U8_MASK_BOT_3: u8 = 0b00000111; pub const U8_MASK_TOP_5: u8 = 0b11111000; pub const U8_MASK_BOT_6: u8 = 0b00111111; pub const U8_MASK_TOP_6: u8 = 0b11111100; pub fn bits_or_err_u8(dec: &[u8; 256], a: &[u8], i: usize) -> Result { let c = a[i]; let o = dec[c as usize]; if o == INVALID_BYTE { Err(DecodeError::InvalidChar { char: c as char, index: i, }) } else { Ok(o) } } pub fn bits_or_err_u64(dec: &[u8; 256], a: &[u8], i: usize) -> Result { let c = a[i]; let o = dec[c as usize]; if o == INVALID_BYTE { Err(DecodeError::InvalidChar { char: c as char, index: i, }) } else { Ok(o as u64) } } pub fn bits_or_err_u128(dec: &[u8; 256], a: &[u8], i: usize) -> Result { let c = a[i]; let o = dec[c as usize]; if o == INVALID_BYTE { Err(DecodeError::InvalidChar { char: c as char, index: i, }) } else { Ok(o as u128) } } /// Error generated when decoding invalid data /// /// `InvalidChar`: a character to be decoded is either: /// /// 1. not in the decoding list of characters at all or /// 1. positioned at the end of a sequence such that this char is impossible /// (contains bits in positions, at the end, that make this not actually properly encoded data) /// /// `InvalidLength`: The remainder of the length of the sequence to be decoded /// is an impossible length for valid decodable sequences /// (e.g. official base64 can *never* generate unpadded encoded sequences of strings /// with a length remainder of 1, when divided by 4 -- only 2, 3, or 4) /// /// Note that for decoding integers, invalid length is simply that /// the length is too long for that size of integer. #[derive(Debug, Clone, PartialEq)] pub enum DecodeError { InvalidChar { char: char, index: usize }, InvalidLength { length: usize }, // FIXME: adding this decreases decode_u64 performance by >50%! // InvalidBits { byte: u8, index: usize }, } impl std::fmt::Display for DecodeError { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { match self { Self::InvalidChar { char, index } => { write!(f, "Invalid char of '{char}' at position {index}") } Self::InvalidLength { length } => { write!(f, "Invalid length of {length}") } // Self::InvalidBits { byte, index } => { // write!(f, "Invalid bits in {byte} at position {index}") // } } } } impl std::error::Error for DecodeError {} /// Build a new decoder array for the given bits (encoder array size), exactly of the encoder array /// /// **You should use [`fast32::make_base32_alpha`](crate::make_base32_alpha) /// or [`fast32::make_base64_alpha`](crate::make_base64_alpha) instead of this!** /// (Those macros invoke this function as appropriate.) /// /// Example: /// ``` /// use fast32::decoder_map_simple; /// use fast32::base32::Alphabet32Nopad; /// /// const ENC_RFC4648_LOWER: &'static [u8; 32] = b"abcdefghijklmnopqrstuvwxyz234567"; /// const DEC_RFC4648_LOWER: [u8; 256] = decoder_map_simple(ENC_RFC4648_LOWER); /// pub const RFC4648_LOWER_NOPAD: Alphabet32Nopad = Alphabet32Nopad::new(ENC_RFC4648_LOWER, &DEC_RFC4648_LOWER); /// /// assert_eq!(RFC4648_LOWER_NOPAD.encode_u64(31), "7"); /// assert_eq!(RFC4648_LOWER_NOPAD.decode_u64_str("7").unwrap(), 31); /// ``` /// /// See more in [tests/alphabet.rs](https://github.com/rogusdev/fast32/blob/main/tests/alphabets.rs) pub const fn decoder_map_simple(enc: &[u8; B]) -> [u8; 256] { let mut dec = [INVALID_BYTE; 256]; let mut i = 0; while i < B { dec[enc[i] as usize] = i as u8; i += 1; } dec } const fn enc_index(enc: &[u8; B], c: u8) -> u8 { let mut j = 0; while j < B { if enc[j] == c { return j as u8; } j += 1; } INVALID_BYTE } /// Build a new decoder array for the given bits (encoder array size), with additional character translations /// /// **You should use [`fast32::make_base32_alpha`](crate::make_base32_alpha) /// or [`fast32::make_base64_alpha`](crate::make_base64_alpha) instead of this!** /// (Those macros invoke this function as appropriate.) /// /// Example: /// ``` /// use fast32::decoder_map; /// use fast32::base32::Alphabet32Nopad; /// /// const ENC_CROCKFORD_LOWER: &'static [u8; 32] = b"0123456789abcdefghjkmnpqrstvwxyz"; /// const DEC_CROCKFORD_LOWER: [u8; 256] = decoder_map( /// ENC_CROCKFORD_LOWER, /// b"iloABCDEFGHIJKLMNOPQRSTVWXYZ", /// b"110abcdefgh1jk1mn0pqrstvwxyz", /// ); /// pub const CROCKFORD_LOWER: Alphabet32Nopad = Alphabet32Nopad::new(ENC_CROCKFORD_LOWER, &DEC_CROCKFORD_LOWER); /// /// assert_eq!(CROCKFORD_LOWER.encode_u64(31), "z"); /// assert_eq!(CROCKFORD_LOWER.decode_u64_str("z").unwrap(), 31); /// ``` /// /// See more in [tests/alphabet.rs](https://github.com/rogusdev/fast32/blob/main/tests/alphabets.rs) pub const fn decoder_map( enc: &[u8; B], from: &[u8; N], to: &[u8; N], ) -> [u8; 256] { let mut dec = decoder_map_simple(enc); let mut i = 0; while i < N { if enc_index(enc, from[i]) != INVALID_BYTE { panic!("Re-mapping a char from encoder!") } let j = enc_index(enc, to[i]); if j == INVALID_BYTE { panic!("Missing mapped char in encoder!") } dec[from[i] as usize] = j; i += 1; } dec }

Back | FazBrowse Home | New Git URL