zqlu 0.3.0

zqlu is a convenient text-based format for public keys
Documentation
use codeckit::Base62 as UpstreamBase62;

pub fn encode(input: &[u8]) -> String {
    let leading_zeroes = input.iter().take_while(|&&x| x == 0).count();
    if leading_zeroes == 0 {
        return UpstreamBase62::encode(input);
    }

    let rest = &input[leading_zeroes..];
    let rest = if rest.is_empty() {
        String::new()
    } else {
        UpstreamBase62::encode(rest)
    };

    format!("{}{}", "0".repeat(leading_zeroes), rest)
}

pub fn decode(input: &str) -> Vec<u8> {
    let leading_zeroes = input.bytes().take_while(|&x| x == b'0').count();
    let rest = &input[leading_zeroes..];
    let mut out = vec![0; leading_zeroes];
    if !rest.is_empty() {
        out.extend_from_slice(&UpstreamBase62::decode(rest));
    }
    out
}

#[cfg(test)]
mod tests {
    use super::{decode, encode};

    #[test]
    fn keeps_encoding_for_non_leading_zero_input() {
        let input = [0x12, 0x34, 0x56];
        assert_eq!(encode(&input), codeckit::Base62::encode(&input));
    }

    #[test]
    fn rewrites_leading_zero_marker_to_zero_digit() {
        assert_eq!(encode(&[0]), "0");
        assert_eq!(encode(&[0, 0]), "00");
        assert_eq!(encode(&[0, 1]), "01");
        assert_eq!(encode(&[0, 0, 0xff]), "0047");
    }

    #[test]
    fn decode_restores_leading_zero_bytes() {
        assert_eq!(decode("0"), vec![0]);
        assert_eq!(decode("00"), vec![0, 0]);
        assert_eq!(decode("01"), vec![0, 1]);
        assert_eq!(decode("0047"), vec![0, 0, 0xff]);
    }

    #[test]
    fn round_trips_byte_sequences_with_leading_zeroes() {
        for input in [
            vec![0],
            vec![0, 1],
            vec![0, 0, 1],
            vec![0, 0xff],
            vec![0, 0, 0xff],
            vec![0, 0x12, 0x34, 0x56],
        ] {
            assert_eq!(decode(&encode(&input)), input);
        }
    }
}