muter 0.7.0

utility for converting data between various formats and encodings
Documentation
#![allow(unknown_lints)]
#![allow(bare_trait_objects)]

use codec::helpers::codecs::ChunkedDecoder;
use codec::helpers::codecs::PaddedDecoder;
use codec::helpers::codecs::PaddedEncoder;
use codec::helpers::codecs::StatelessEncoder;
use codec::CodecSettings;
use codec::CodecTransform;
use codec::Direction;
use codec::Error;
use codec::TransformableCodec;
use std::cmp;
use std::collections::BTreeMap;
use std::io;

#[derive(Default)]
pub struct Base32TransformFactory {}

#[derive(Default)]
pub struct Base32HexTransformFactory {}

pub const BASE32: [u8; 32] = [
    b'A', b'B', b'C', b'D', b'E', b'F', b'G', b'H', b'I', b'J', b'K', b'L', b'M', b'N', b'O', b'P',
    b'Q', b'R', b'S', b'T', b'U', b'V', b'W', b'X', b'Y', b'Z', b'2', b'3', b'4', b'5', b'6', b'7',
];

pub const BASE32HEX: [u8; 32] = [
    b'0', b'1', b'2', b'3', b'4', b'5', b'6', b'7', b'8', b'9', b'A', b'B', b'C', b'D', b'E', b'F',
    b'G', b'H', b'I', b'J', b'K', b'L', b'M', b'N', b'O', b'P', b'Q', b'R', b'S', b'T', b'U', b'V',
];
pub const REV: [i8; 256] = [
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
    -1, -1, 26, 27, 28, 29, 30, 31, -1, -1, -1, -1, -1, 0, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8,
    9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1, -1,
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
];

pub const REVHEX: [i8; 256] = [
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
    0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, 0, -1, -1, -1, 10, 11, 12, 13, 14, 15, 16, 17, 18,
    19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
];

fn forward_transform(inp: &[u8], outp: &mut [u8], arr: &[u8; 32]) -> (usize, usize) {
    let (is, os) = (5, 8);
    let bits = is * 8 / os;
    let mask = (1u64 << bits) - 1;
    let n = cmp::min(inp.len() / is, outp.len() / os);
    for (i, j) in (0..n).map(|x| (x * is, x * os)) {
        let x: u64 = inp[i..i + is]
            .iter()
            .enumerate()
            .map(|(k, &v)| u64::from(v) << ((is - 1 - k) * 8))
            .sum();

        for (k, val) in outp[j..j + os].iter_mut().enumerate().take(os) {
            *val = arr[(x >> ((os - 1 - k) * bits) & mask) as usize];
        }
    }
    (n * is, n * os)
}

impl Base32TransformFactory {
    pub fn new() -> Self {
        Base32TransformFactory {}
    }

    fn factory_for(
        name: &'static str,
        forward: &'static [u8; 32],
        reverse: &'static [i8; 256],
        r: Box<io::BufRead>,
        s: CodecSettings,
    ) -> Result<Box<io::BufRead>, Error> {
        let pad = match (s.bool_arg("pad")?, s.bool_arg("nopad")?) {
            (true, true) => {
                return Err(Error::IncompatibleParameters("pad".into(), "nopad".into()))
            }
            (_, false) => Some(b'='),
            (false, true) => None,
        };
        let codec = match s.dir {
            Direction::Forward => PaddedEncoder::new(
                StatelessEncoder::new(move |inp, out| forward_transform(inp, out, forward), 8),
                5,
                8,
                pad,
            )
            .into_bufread(r, s.bufsize),
            Direction::Reverse => PaddedDecoder::new(
                ChunkedDecoder::new(s.strict, name, 8, 5, reverse),
                8,
                5,
                pad,
            )
            .into_bufread(r, s.bufsize),
        };
        Ok(codec)
    }
}

impl CodecTransform for Base32TransformFactory {
    fn factory(&self, r: Box<io::BufRead>, s: CodecSettings) -> Result<Box<io::BufRead>, Error> {
        Base32TransformFactory::factory_for(self.name(), &BASE32, &REV, r, s)
    }

    fn options(&self) -> BTreeMap<String, String> {
        let mut map = BTreeMap::new();
        map.insert("pad".to_string(), tr!("pad incomplete sequences with ="));
        map.insert(
            "nopad".to_string(),
            tr!("do not pad incomplete sequences with ="),
        );
        map
    }

    fn can_reverse(&self) -> bool {
        true
    }

    fn name(&self) -> &'static str {
        "base32"
    }
}

impl Base32HexTransformFactory {
    pub fn new() -> Self {
        Base32HexTransformFactory {}
    }
}

impl CodecTransform for Base32HexTransformFactory {
    fn factory(&self, r: Box<io::BufRead>, s: CodecSettings) -> Result<Box<io::BufRead>, Error> {
        Base32TransformFactory::factory_for(self.name(), &BASE32HEX, &REVHEX, r, s)
    }

    fn options(&self) -> BTreeMap<String, String> {
        let mut map = BTreeMap::new();
        map.insert("pad".to_string(), tr!("pad incomplete sequences with ="));
        map.insert(
            "nopad".to_string(),
            tr!("do not pad incomplete sequences with ="),
        );
        map
    }

    fn can_reverse(&self) -> bool {
        true
    }

    fn name(&self) -> &'static str {
        "base32hex"
    }
}

#[cfg(test)]
mod tests {
    use chain::Chain;
    use codec::registry::CodecRegistry;
    use codec::tests;

    fn check(name: &str, inp: &[u8], outp: &[u8]) {
        let reg = CodecRegistry::new();
        for i in vec![5, 6, 7, 8, 512] {
            let c = Chain::new(&reg, name, i, true);
            assert_eq!(c.transform(inp.to_vec()).unwrap(), outp);
        }

        let rev = format!("-{}", name);
        for i in vec![8, 9, 10, 11, 512] {
            let c = Chain::new(&reg, &rev, i, true);
            assert_eq!(c.transform(outp.to_vec()).unwrap(), inp);
            let c = Chain::new(&reg, &rev, i, false);
            assert_eq!(c.transform(outp.to_vec()).unwrap(), inp);
        }
    }

    #[test]
    fn encodes_bytes_base32() {
        check("base32", b"", b"");
        check("base32", b"f", b"MY======");
        check("base32", b"fo", b"MZXQ====");
        check("base32", b"foo", b"MZXW6===");
        check("base32", b"foob", b"MZXW6YQ=");
        check("base32", b"fooba", b"MZXW6YTB");
        check("base32", b"foobar", b"MZXW6YTBOI======");
        check("base32,pad", b"", b"");
        check("base32,pad", b"f", b"MY======");
        check("base32,pad", b"fo", b"MZXQ====");
        check("base32,pad", b"foo", b"MZXW6===");
        check("base32,pad", b"foob", b"MZXW6YQ=");
        check("base32,pad", b"fooba", b"MZXW6YTB");
        check("base32,pad", b"foobar", b"MZXW6YTBOI======");
        check("base32,nopad", b"", b"");
        check("base32,nopad", b"f", b"MY");
        check("base32,nopad", b"fo", b"MZXQ");
        check("base32,nopad", b"foo", b"MZXW6");
        check("base32,nopad", b"foob", b"MZXW6YQ");
        check("base32,nopad", b"fooba", b"MZXW6YTB");
        check("base32,nopad", b"foobar", b"MZXW6YTBOI");
    }

    #[test]
    fn encodes_bytes_base32hex() {
        check("base32hex", b"", b"");
        check("base32hex", b"f", b"CO======");
        check("base32hex", b"fo", b"CPNG====");
        check("base32hex", b"foo", b"CPNMU===");
        check("base32hex", b"foob", b"CPNMUOG=");
        check("base32hex", b"fooba", b"CPNMUOJ1");
        check("base32hex", b"foobar", b"CPNMUOJ1E8======");
        check("base32hex,pad", b"", b"");
        check("base32hex,pad", b"f", b"CO======");
        check("base32hex,pad", b"fo", b"CPNG====");
        check("base32hex,pad", b"foo", b"CPNMU===");
        check("base32hex,pad", b"foob", b"CPNMUOG=");
        check("base32hex,pad", b"fooba", b"CPNMUOJ1");
        check("base32hex,pad", b"foobar", b"CPNMUOJ1E8======");
        check("base32hex,nopad", b"", b"");
        check("base32hex,nopad", b"f", b"CO");
        check("base32hex,nopad", b"fo", b"CPNG");
        check("base32hex,nopad", b"foo", b"CPNMU");
        check("base32hex,nopad", b"foob", b"CPNMUOG");
        check("base32hex,nopad", b"fooba", b"CPNMUOJ1");
        check("base32hex,nopad", b"foobar", b"CPNMUOJ1E8");
    }

    #[test]
    fn default_tests_base32() {
        tests::round_trip("base32");
        tests::round_trip_stripped_whitespace("base32");
        tests::basic_configuration("base32");
        tests::invalid_data("base32");
    }

    #[test]
    fn default_tests_base32hex() {
        tests::round_trip("base32hex");
        tests::round_trip_stripped_whitespace("base32hex");
        tests::basic_configuration("base32hex");
        tests::invalid_data("base32hex");
    }

    #[test]
    fn known_values() {
        check("base32", tests::BYTE_SEQ, b"AAAQEAYEAUDAOCAJBIFQYDIOB4IBCEQTCQKRMFYYDENBWHA5DYPSAIJCEMSCKJRHFAUSUKZMFUXC6MBRGIZTINJWG44DSOR3HQ6T4P2AIFBEGRCFIZDUQSKKJNGE2TSPKBIVEU2UKVLFOWCZLJNVYXK6L5QGCYTDMRSWMZ3INFVGW3DNNZXXA4LSON2HK5TXPB4XU634PV7H7AEBQKBYJBMGQ6EITCULRSGY5D4QSGJJHFEVS2LZRGM2TOOJ3HU7UCQ2FI5EUWTKPKFJVKV2ZLNOV6YLDMVTWS23NN5YXG5LXPF5X274BQOCYPCMLRWHZDE4VS6MZXHM7UGR2LJ5JVOW27MNTWW33TO55X7A4HROHZHF43T6R2PK5PWO33XP6DY7F47U6X3PP6HZ7L57Z7P674======");
        check("base32hex", tests::BYTE_SEQ, b"000G40O40K30E209185GO38E1S8124GJ2GAHC5OO34D1M70T3OFI08924CI2A9H750KIKAPC5KN2UC1H68PJ8D9M6SS3IEHR7GUJSFQ085146H258P3KGIAA9D64QJIFA18L4KQKALB5EM2PB9DLONAUBTG62OJ3CHIMCPR8D5L6MR3DDPNN0SBIEDQ7ATJNF1SNKURSFLV7V041GA1O91C6GU48J2KBHI6OT3SGI699754LIQBPH6CQJEE9R7KVK2GQ58T4KMJAFA59LALQPBDELUOB3CLJMIQRDDTON6TBNF5TNQVS1GE2OF2CBHM7P34SLIUCPN7CVK6HQB9T9LEMQVCDJMMRRJETTNV0S7HE7P75SRJUHQFATFMERRNFU3OV5SVKUNRFFU7PVBTVPVFUVS======");
    }
}