ba2 3.0.1

A Rust library for working with the Bethesda archive file format
Documentation
use bstr::BString;

#[must_use]
const fn build_lookup_table() -> [u8; 256] {
    let mut table = [0u8; u8::MAX as usize + 1];
    let mut i: u8 = 0;
    loop {
        table[i as usize] = i;
        match i {
            u8::MAX => break,
            _ => i += 1,
        };
    }

    table['/' as usize] = b'\\';

    let offset = b'a' - b'A';
    let mut i = b'A';
    loop {
        table[i as usize] = i + offset;
        match i {
            b'Z' => break,
            _ => i += 1,
        };
    }

    table
}

#[must_use]
fn map_byte(b: u8) -> u8 {
    const LUT: [u8; 256] = build_lookup_table();
    LUT[b as usize]
}

pub(crate) fn normalize_path(path: &mut BString) {
    for b in path.iter_mut() {
        *b = map_byte(*b);
    }

    while path.last().is_some_and(|&x| x == b'\\') {
        path.pop();
    }

    while path.first().is_some_and(|&x| x == b'\\') {
        path.remove(0);
    }

    if path.is_empty() || path.len() >= 260 {
        path.clear();
        path.push(b'.');
    }
}

#[cfg(test)]
mod tests {
    use super::map_byte;

    #[test]
    fn test_mapping() {
        macro_rules! test {
            ($l:literal, $r:literal) => {
                assert_eq!(map_byte($l as u8), $r as u8);
            };
        }

        test!('A', 'a');
        test!('a', 'a');
        test!('Z', 'z');
        test!('z', 'z');
        test!('/', '\\');
        test!('\\', '\\');
        test!('.', '.');
        test!(255, 255);
    }
}