bl_save 0.2.0

Read Blockland save files.
Documentation
use crate::cp1252::BYTE_TO_CHAR;

pub fn collapse(dst: &mut String, chars: impl IntoIterator<Item = char>) {
    let mut chars = chars.into_iter();

    loop {
        match chars.next() {
            Some('\\') => collapse_one(dst, &mut chars),
            Some(c) => dst.push(c),
            None => break,
        }
    }
}

fn collapse_one(dst: &mut String, mut chars: impl Iterator<Item = char>) {
    match chars.next() {
        Some('x') => match chars.next() {
            Some(hex1) => match chars.next() {
                Some(hex2) => {
                    let mut src = String::with_capacity(2);
                    src.push(hex1);
                    src.push(hex2);
                    match u8::from_str_radix(&src, 16) {
                        Ok(byte) => dst.push(BYTE_TO_CHAR[usize::from(byte)]),
                        Err(_) => {
                            dst.push_str("\\x");
                            dst.push(hex1);
                            dst.push(hex2)
                        }
                    }
                }
                None => {
                    dst.push_str("\\x");
                    dst.push(hex1)
                }
            },
            None => dst.push_str("\\x"),
        },
        Some('c') => match chars.next() {
            Some('r') => dst.push(char::from(15)),
            Some('p') => dst.push(char::from(16)),
            Some('o') => dst.push(char::from(17)),
            Some('0') => {
                if dst.is_empty() {
                    dst.push(char::from(2));
                }
                dst.push(char::from(1))
            }
            Some('1') => dst.push(char::from(2)),
            Some('2') => dst.push(char::from(3)),
            Some('3') => dst.push(char::from(4)),
            Some('4') => dst.push(char::from(5)),
            Some('5') => dst.push(char::from(6)),
            Some('6') => dst.push(char::from(7)),
            Some('7') => dst.push(char::from(0xb)),
            Some('8') => dst.push(char::from(0xc)),
            Some('9') => dst.push(char::from(0xe)),
            Some(c) => {
                dst.push_str("\\c");
                dst.push(c)
            }
            None => dst.push_str("\\c"),
        },
        Some('r') => dst.push('\r'),
        Some('n') => dst.push('\n'),
        Some('t') => dst.push('\t'),
        Some(b) => dst.push(b),
        None => dst.push('\\'),
    }
}