pub(crate) fn decode_ascii_hex(stream: &[u8]) -> Vec<u8> {
    let mut buffer = Vec::with_capacity(stream.len() / 2);

    let mut iter = stream.iter().filter(|&&b| !b.is_ascii_whitespace());

    loop {
        let mut n = match iter.next() {
            Some(&c @ b'0'..=b'9') => c - b'0',
            Some(&c @ b'A'..=b'F') => c - b'A' + 10,
            Some(&c @ b'a'..=b'f') => c - b'a' + 10,
            Some(b'>') | None => break,
            Some(..) => todo!(),
        } as u16;

        n *= 16;

        n += match iter.next() {
            Some(&c @ b'0'..=b'9') => c - b'0',
            Some(&c @ b'A'..=b'F') => c - b'A' + 10,
            Some(&c @ b'a'..=b'f') => c - b'a' + 10,
            Some(b'>') | None => break,
            Some(..) => todo!(),
        } as u16;

        buffer.extend_from_slice(&n.to_be_bytes());
    }

    buffer
}

fn decode_ascii_85_digit(digit: u8, n: &mut u32, count: &mut u8, result: &mut Vec<u8>) {
    *n *= 85;

    if digit == b'z' {
        if *count == 0 {
            result.extend_from_slice(&[0, 0, 0, 0]);
        } else {
            todo!()
        }
    } else {
        *n += (digit - b'!') as u32;
    }

    *count += 1;
}

pub(crate) fn decode_ascii_85(mut stream: &[u8]) -> Vec<u8> {
    if stream.starts_with(b"<~") {
        stream = &stream[2..];
    }

    let mut buffer = Vec::with_capacity((stream.len() / 5) * 4);

    let mut iter = stream.iter().filter(|&&b| !b.is_ascii_whitespace());

    let mut n: u32 = 0;
    let mut count = 0;

    while let Some(&digit) = iter.next() {
        if digit == b'~' {
            if iter.next() != Some(&b'>') {
                todo!()
            }

            break;
        }

        decode_ascii_85_digit(digit, &mut n, &mut count, &mut buffer);

        if count == 5 {
            buffer.extend_from_slice(&n.to_be_bytes());
            count = 0;
            n = 0;
        }
    }

    if count != 0 {
        let to_remove = 5 - count as usize;
        while count != 5 {
            decode_ascii_85_digit(b'u', &mut n, &mut count, &mut buffer);
        }

        buffer.extend_from_slice(&n.to_be_bytes());

        buffer.drain((buffer.len() - to_remove)..);
    }

    buffer
}

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

    #[test]
    fn ascii_85() {
        assert_eq!(
            decode_ascii_85(b"<~9jqo^F*2M7/c~>"),
            [77, 97, 110, 32, 115, 117, 114, 101, 46],
        );

        assert_eq!(
            String::from_utf8(decode_ascii_85(
                br#"9jqo^BlbD-BleB1DJ+*+F(f,q/0JhKF<GL>Cj@.4Gp$d7F!,L7@<6@)/0JDEF<G%<+EV:2F!,
            O<DJ+*.@<*K0@<6L(Df-\0Ec5e;DffZ(EZee.Bl.9pF"AGXBPCsi+DGm>@3BB/F*&OCAfu2/AKY
            i(DIb:@FD,*)+C]U=@3BN#EcYf8ATD3s@q?d$AftVqCh[NqF<G:8+EV:.+Cf>-FD5W8ARlolDIa
            l(DId<j@<?3r@:F%a+D58'ATD4$Bl@l3De:,-DJs`8ARoFb/0JMK@qB4^F!,R<AKZ&-DfTqBG%G
            >uD.RTpAKYo'+CT/5+Cei#DII?(E,9)oF*2M7/c~>"#
            ))
            .unwrap(),
            r#"Man is distinguished, not only by his reason, but by this singular passion from other animals, which is a lust of the mind, that by a perseverance of delight in the continued and indefatigable generation of knowledge, exceeds the short vehemence of any carnal pleasure."#
        );
    }
}