ttb 0.1.0

A crate for saving and loading of tinytown build files
Documentation
use {
    std::{
        io::{
            Cursor,
        },
    },
    ttb::{
        Reader,
        ReaderEvent,
        Writer,
    },
    proptest::{
        prelude::*,
        test_runner::{
            Config,
        },
        arbitrary::any,
        sample::Index,
        proptest,
    },
    regenboog::{
        RgbaU8,
    },
};

fn read_write_case(
    build_name: &str,
    build_description: &str,
    type_names: &[String],
    palette: &[RgbaU8],
    bricks: &[(Index, i32, i32, i32, u8, Index)],
) {
    let mut buf = Vec::new();
    let write_cursor = Cursor::new(&mut buf);
    let mut writer = Writer::new(write_cursor);
    writer.write_header(build_name, build_description, palette).unwrap();
    for &(tyid_idx, x, y, z, orientation, color_id_idx) in bricks {
        let tyid = tyid_idx.index(type_names.len());
        let color_id = color_id_idx.index(palette.len()) as u8;
        writer.write_brick(&type_names[tyid], x, y, z, orientation, color_id).unwrap();
    }
    writer.finish().unwrap();
    {
        use std::io::Write;
        let mut f = std::fs::File::create("/tmp/testcaseoutput").unwrap();
        f.write_all(&buf[..]).unwrap();
    }
    let read_cursor = Cursor::new(&buf);
    let mut reader = Reader::new(read_cursor);
    {
        let event = reader.next_event().unwrap();
        assert_eq!(event, Some(ReaderEvent::Meta {
            build_name,
            build_description,
        }));
    }
    for (id, &color) in palette.into_iter().enumerate() {
        let event = reader.next_event().unwrap();
        assert_eq!(event, Some(ReaderEvent::Color {
            id: id as u8,
            color,
        }));
    }
    for &(tyid_idx, x, y, z, orientation, color_id_idx) in bricks {
        let tyid = tyid_idx.index(type_names.len());
        let color_id = color_id_idx.index(palette.len()) as u8;
        let event = reader.next_event().unwrap();
        assert_eq!(event, Some(ReaderEvent::Brick {
            brick_type: &type_names[tyid],
            x,
            y,
            z,
            orientation,
            color_id,
        }));
    }
}

proptest! {
    #![proptest_config(Config::with_cases(2))]
    #[test]
    fn read_write_big(
        mut build_name in ".{0,255}",
        mut build_desc in ".{0,65535}",
        mut type_names in proptest::collection::vec(".{0,255}", 1..1024),
        palette in proptest::collection::vec([any::<u8>(); 4].prop_map(|x| RgbaU8::from(x)), 1..256),
        bricks in proptest::collection::vec((any::<Index>(), any::<i32>(), any::<i32>(), any::<i32>(), 0u8..4, any::<Index>()), 0..5000),
    ) {
        while build_name.len() > 255 { build_name.pop().unwrap(); }
        while build_desc.len() > 65535 { build_desc.pop().unwrap(); }
        for type_name in &mut type_names {
            while type_name.len() > 255 {
                type_name.pop().unwrap();
            }
        }
        read_write_case(&build_name, &build_desc, &type_names, &palette, &bricks);
    }
}

proptest! {
    #![proptest_config(Config::with_cases(128))]
    #[test]
    fn read_write_small(
        mut build_name in ".{0,255}",
        mut build_desc in ".{0,255}",
        mut type_names in proptest::collection::vec(".{0,255}", 1..16),
        palette in proptest::collection::vec([any::<u8>(); 4].prop_map(|x| RgbaU8::from(x)), 1..256),
        bricks in proptest::collection::vec((any::<Index>(), any::<i32>(), any::<i32>(), any::<i32>(), 0u8..4, any::<Index>()), 0..800),
    ) {
        while build_name.len() > 255 { build_name.pop().unwrap(); }
        while build_desc.len() > 65535 { build_desc.pop().unwrap(); }
        for type_name in &mut type_names {
            while type_name.len() > 255 {
                type_name.pop().unwrap();
            }
        }
        read_write_case(&build_name, &build_desc, &type_names, &palette, &bricks);
    }
}

proptest! {
    #![proptest_config(Config::with_cases(512))]
    #[test]
    fn read_write_tiny(
        mut build_name in ".{0,255}",
        mut build_desc in ".{0,255}",
        mut type_names in proptest::collection::vec(".{0,255}", 1..4),
        palette in proptest::collection::vec([any::<u8>(); 4].prop_map(|x| RgbaU8::from(x)), 1..256),
        bricks in proptest::collection::vec((any::<Index>(), any::<i32>(), any::<i32>(), any::<i32>(), 0u8..4, any::<Index>()), 0..128),
    ) {
        while build_name.len() > 255 { build_name.pop().unwrap(); }
        while build_desc.len() > 65535 { build_desc.pop().unwrap(); }
        for type_name in &mut type_names {
            while type_name.len() > 255 {
                type_name.pop().unwrap();
            }
        }
        read_write_case(&build_name, &build_desc, &type_names, &palette, &bricks);
    }
}