preserves 4.996.0

Implementation of the Preserves serialization format via serde.
Documentation
use preserves::error::{is_eof_io_error, is_syntax_io_error};
use preserves::symbol::Symbol;
use preserves::value::de::from_value as deserialize_from_value;
use preserves::value::BinarySource;
use preserves::value::BytesBinarySource;
use preserves::value::IOBinarySource;
use preserves::value::IOValue;
use preserves::value::PackedWriter;
use preserves::value::Reader;
use preserves::value::ToplevelWhitespaceMode;
use std::io;
use std::iter::Iterator;

mod samples;
use samples::*;

fn decode_all(bytes: &'_ [u8]) -> io::Result<Vec<IOValue>> {
    BytesBinarySource::new(bytes)
        .packed_iovalues()
        .configured(true)
        .collect()
}

fn parse_all(text: &str) -> io::Result<Vec<IOValue>> {
    BytesBinarySource::new(text.as_bytes())
        .text_iovalues()
        .configured(true)
        .collect()
}

#[test]
fn compare_text_with_packed() -> io::Result<()> {
    use io::prelude::*;
    let from_text = {
        let mut fh = std::fs::File::open("./tests/samples.pr").unwrap();
        let mut contents = String::new();
        fh.read_to_string(&mut contents)?;
        BytesBinarySource::new(contents.as_bytes())
            .text_iovalues()
            .demand_next(true)?
    };
    let from_packed = {
        let mut fh = std::fs::File::open("./tests/samples.bin").unwrap();
        IOBinarySource::new(&mut fh)
            .packed_iovalues()
            .demand_next(true)?
    };
    assert_eq!(from_text, from_packed);
    Ok(())
}

#[test]
fn compare_deserialize_text_with_packed() -> io::Result<()> {
    use io::prelude::*;
    let from_text = {
        let mut fh = std::fs::File::open("./tests/samples.pr").unwrap();
        let mut contents = String::new();
        fh.read_to_string(&mut contents)?;
        let tests: TestCases = preserves::de::from_text(&contents)?;
        tests
    };
    let from_packed = {
        let mut fh = std::fs::File::open("./tests/samples.bin").unwrap();
        let tests: TestCases = preserves::de::from_read(&mut fh)?;
        tests
    };
    assert_eq!(from_text, from_packed);
    Ok(())
}

#[test]
fn read_write_read_text() -> io::Result<()> {
    use io::prelude::*;
    let from_text = {
        let mut fh = std::fs::File::open("./tests/samples.pr").unwrap();
        let mut contents = String::new();
        fh.read_to_string(&mut contents)?;
        preserves::value::text::annotated_iovalue_from_str(&contents)?
    };
    let roundtripped = {
        let mut bs = Vec::new();
        let mut w = preserves::value::TextWriter::new(&mut bs);
        preserves::ser::to_writer(&mut w, &from_text)?;
        let s = String::from_utf8(bs).unwrap();
        preserves::value::text::annotated_iovalue_from_str(&s)?
    };
    let roundtripped_indented = {
        let mut bs = Vec::new();
        let mut w = preserves::value::TextWriter::new(&mut bs);
        w.indentation = 4;
        preserves::ser::to_writer(&mut w, &from_text)?;
        let s = String::from_utf8(bs).unwrap();
        preserves::value::text::annotated_iovalue_from_str(&s)?
    };
    assert_eq!(from_text, roundtripped);
    assert_eq!(from_text, roundtripped_indented);
    Ok(())
}

#[test]
fn deserialize_serialize_deserialize_text() -> io::Result<()> {
    use io::prelude::*;
    let from_text = {
        let mut fh = std::fs::File::open("./tests/samples.pr").unwrap();
        let mut contents = String::new();
        fh.read_to_string(&mut contents)?;
        let tests: TestCases = preserves::de::from_text(&contents)?;
        tests
    };
    let roundtripped = {
        let mut bs = Vec::new();
        let mut w = preserves::value::TextWriter::new(&mut bs);
        preserves::ser::to_writer(&mut w, &from_text)?;
        let s = String::from_utf8(bs).unwrap();
        preserves::de::from_text(&s)?
    };
    assert_eq!(from_text, roundtripped);
    Ok(())
}

#[test]
fn run() -> io::Result<()> {
    let mut fh = std::fs::File::open("./tests/samples.bin").unwrap();
    let mut src = IOBinarySource::new(&mut fh);
    let mut d = src.packed_iovalues().configured(true);
    let tests: TestCases = deserialize_from_value(&d.next().unwrap().unwrap()).unwrap();

    for (Symbol(name), case) in tests.tests {
        println!("{:?} ==> {:?}", name, case);
        match case {
            TestCase::Test(bin, val) => {
                assert_eq!(
                    &decode_all(&PackedWriter::encode_iovalue(&val)?[..])?,
                    &[val.clone()]
                );
                assert_eq!(&decode_all(&bin[..])?, &[val.clone()]);
                assert_eq!(&PackedWriter::encode_iovalue(&val)?, &bin);
            }
            TestCase::NondeterministicTest(bin, val) => {
                assert_eq!(&PackedWriter::encode_iovalue(&val)?, &bin);
                assert_eq!(
                    &decode_all(&PackedWriter::encode_iovalue(&val)?[..])?,
                    &[val.clone()]
                );
                assert_eq!(&decode_all(&bin[..])?, &[val.clone()]);
            }
            TestCase::ParseError(text) => {
                match parse_all(&text) {
                    Ok(_) => panic!("Unexpected success"),
                    Err(e) => {
                        if is_syntax_io_error(&e) {
                            // all is OK
                        } else {
                            panic!("Unexpected error {:?}", e)
                        }
                    }
                }
            }
            TestCase::ParseShort(text) => {
                assert!(if let Err(e) = BytesBinarySource::new(text.as_bytes())
                    .text_iovalues()
                    .toplevel_whitespace_mode(ToplevelWhitespaceMode::Value)
                    .configured(true)
                    .next()
                    .unwrap()
                {
                    is_eof_io_error(&e)
                } else {
                    false
                })
            }
            TestCase::ParseEOF(text) => {
                assert!(BytesBinarySource::new(text.as_bytes())
                    .text_iovalues()
                    .toplevel_whitespace_mode(ToplevelWhitespaceMode::Value)
                    .configured(true)
                    .next()
                    .is_none());
            }
            TestCase::DecodeError(bin) => {
                match decode_all(&bin[..]) {
                    Ok(_) => panic!("Unexpected success"),
                    Err(e) => {
                        if is_syntax_io_error(&e) {
                            // all is OK
                        } else {
                            panic!("Unexpected error {:?}", e)
                        }
                    }
                }
            }
            TestCase::DecodeShort(bin) => {
                assert!(if let Err(e) = BytesBinarySource::new(&bin)
                    .packed_iovalues()
                    .configured(true)
                    .next()
                    .unwrap()
                {
                    is_eof_io_error(&e)
                } else {
                    false
                })
            }
            TestCase::DecodeEOF(bin) => {
                assert!(BytesBinarySource::new(&bin)
                    .packed_iovalues()
                    .configured(true)
                    .next()
                    .is_none());
            }
        }
    }
    Ok(())
}