srcdmp 0.1.0-alpha.1

Amazing code snapshot tool and library
Documentation
use std::collections::HashMap;

/// The SDMP-7 tier-1 lookup table.
///
/// Maps a byte index (`0x00..=0x7F`) to a Unicode character.
/// `None` means the slot is either RESERVED (indices without a mapping)
/// or the escape byte (`0x7F`).
///
/// # Contents
///
/// | Range | Mapped Characters |
/// | :--- | :--- |
/// | `0x00..=0x04` | Control: NUL, TAB, LF, CR, space |
/// | `0x05..=0x1E` | RESERVED |
/// | `0x1F..=0x38` | Lowercase `a`–`z` |
/// | `0x39..=0x52` | Uppercase `A`–`Z` |
/// | `0x53..=0x5C` | Digits `0`–`9` |
/// | `0x5D..=0x7B` | Punctuation and operators |
/// | `0x7C..=0x7E` | RESERVED |
/// | `0x7F` | Escape sentinel |
///
/// # Examples
///
/// ```rust
/// use srcdmp::raw::table::TIER1_DECODE;
///
/// assert_eq!(TIER1_DECODE[0x04], Some(' '));
/// assert_eq!(TIER1_DECODE[0x26], Some('h'));
/// assert_eq!(TIER1_DECODE[0x7F], None); // escape byte
/// ```
pub const TIER1_DECODE: [Option<char>; 128] = {
    let mut t = [None; 128];

    t[0x00] = Some('\0');
    t[0x01] = Some('\t');
    t[0x02] = Some('\n');
    t[0x03] = Some('\r');
    t[0x04] = Some(' ');

    t[0x1F] = Some('a');
    t[0x20] = Some('b');
    t[0x21] = Some('c');
    t[0x22] = Some('d');
    t[0x23] = Some('e');
    t[0x24] = Some('f');
    t[0x25] = Some('g');
    t[0x26] = Some('h');
    t[0x27] = Some('i');
    t[0x28] = Some('j');
    t[0x29] = Some('k');
    t[0x2A] = Some('l');
    t[0x2B] = Some('m');
    t[0x2C] = Some('n');
    t[0x2D] = Some('o');
    t[0x2E] = Some('p');
    t[0x2F] = Some('q');
    t[0x30] = Some('r');
    t[0x31] = Some('s');
    t[0x32] = Some('t');
    t[0x33] = Some('u');
    t[0x34] = Some('v');
    t[0x35] = Some('w');
    t[0x36] = Some('x');
    t[0x37] = Some('y');
    t[0x38] = Some('z');

    t[0x39] = Some('A');
    t[0x3A] = Some('B');
    t[0x3B] = Some('C');
    t[0x3C] = Some('D');
    t[0x3D] = Some('E');
    t[0x3E] = Some('F');
    t[0x3F] = Some('G');
    t[0x40] = Some('H');
    t[0x41] = Some('I');
    t[0x42] = Some('J');
    t[0x43] = Some('K');
    t[0x44] = Some('L');
    t[0x45] = Some('M');
    t[0x46] = Some('N');
    t[0x47] = Some('O');
    t[0x48] = Some('P');
    t[0x49] = Some('Q');
    t[0x4A] = Some('R');
    t[0x4B] = Some('S');
    t[0x4C] = Some('T');
    t[0x4D] = Some('U');
    t[0x4E] = Some('V');
    t[0x4F] = Some('W');
    t[0x50] = Some('X');
    t[0x51] = Some('Y');
    t[0x52] = Some('Z');

    t[0x53] = Some('0');
    t[0x54] = Some('1');
    t[0x55] = Some('2');
    t[0x56] = Some('3');
    t[0x57] = Some('4');
    t[0x58] = Some('5');
    t[0x59] = Some('6');
    t[0x5A] = Some('7');
    t[0x5B] = Some('8');
    t[0x5C] = Some('9');

    t[0x5D] = Some('(');
    t[0x5E] = Some(')');
    t[0x5F] = Some('{');
    t[0x60] = Some('}');
    t[0x61] = Some('[');
    t[0x62] = Some(']');
    t[0x63] = Some('.');
    t[0x64] = Some(',');
    t[0x65] = Some(';');
    t[0x66] = Some(':');
    t[0x67] = Some('=');
    t[0x68] = Some('+');
    t[0x69] = Some('-');
    t[0x6A] = Some('*');
    t[0x6B] = Some('/');
    t[0x6C] = Some('%');
    t[0x6D] = Some('<');
    t[0x6E] = Some('>');
    t[0x6F] = Some('!');
    t[0x70] = Some('&');
    t[0x71] = Some('|');
    t[0x72] = Some('^');
    t[0x73] = Some('~');
    t[0x74] = Some('?');
    t[0x75] = Some('@');
    t[0x76] = Some('#');
    t[0x77] = Some('_');
    t[0x78] = Some('\\');
    t[0x79] = Some('"');
    t[0x7A] = Some('\'');
    t[0x7B] = Some('`');

    t
};

/// The escape byte sentinel for SDMP-7.
///
/// When the decoder encounters `0x7F`, the next byte is interpreted
/// as a raw UTF-8 byte rather than a tier-1 table index. This allows
/// encoding characters not present in the tier-1 table.
pub const ESCAPE: u8 = 0x7F;

/// Build a reverse mapping from character to tier-1 byte index.
///
/// The returned map can be used by the SDMP-7 encoder to quickly
/// look up the encoded byte for common ASCII characters.
///
/// # Examples
///
/// ```rust
/// use srcdmp::raw::table::build_tier1_encode;
///
/// let encode = build_tier1_encode();
/// assert_eq!(encode[&'h'], 0x26);
/// assert_eq!(encode[&' '], 0x04);
/// assert!(encode.get(&'é').is_none());
/// ```
#[must_use]
pub fn build_tier1_encode() -> HashMap<char, u8> {
    let mut map = HashMap::new();
    for (index, slot) in TIER1_DECODE.iter().enumerate() {
        if let Some(c) = slot {
            map.insert(*c, index as u8);
        }
    }
    map
}