serdeio 0.6.0

Tiny IO utility library for Rust to serialize/deserialize Serde compatible structs
Documentation
use std::io::{BufRead, BufReader, BufWriter, Read, Write};

use serde::{Serialize, de::DeserializeOwned};

use crate::Error;

pub fn read<T: DeserializeOwned>(reader: impl Read) -> Result<Vec<T>, Error> {
    let reader = BufReader::new(reader);
    let mut records: Vec<T> = Vec::new();
    for line in reader.lines() {
        let line = line?;
        let record: T = serde_json::from_str(&line)?;
        records.push(record);
    }
    Ok(records)
}

pub fn write<'a, T: Serialize + 'a>(
    writer: impl Write,
    records: impl IntoIterator<Item = &'a T>,
) -> Result<(), Error> {
    let mut writer = BufWriter::new(writer);
    for record in records {
        let line = serde_json::to_string(record)?;
        writer.write_all(line.as_bytes())?;
        writer.write_all(b"\n")?;
    }
    writer.flush()?;
    Ok(())
}

#[cfg(test)]
mod test {
    use std::io::Cursor;

    use serde::{Deserialize, Serialize};

    use super::{read, write};

    #[derive(Debug, Deserialize, Serialize, PartialEq, Eq)]
    struct Record {
        id: u32,
        name: String,
        items: Vec<String>,
    }

    #[test]
    fn test_read() {
        let data = r#"
            {"id": 1, "name": "foo", "items": ["a", "b", "c"]}
            {"id": 2, "name": "bar", "items": ["d", "e", "f"]}
        "#
        .trim();
        let cursor = Cursor::new(data);
        let records: Vec<Record> = read(cursor).unwrap();

        let expected = vec![
            Record {
                id: 1,
                name: "foo".to_owned(),
                items: vec!["a".to_owned(), "b".to_owned(), "c".to_owned()],
            },
            Record {
                id: 2,
                name: "bar".to_owned(),
                items: vec!["d".to_owned(), "e".to_owned(), "f".to_owned()],
            },
        ];

        assert_eq!(expected, records);
    }

    #[test]
    fn test_write() {
        let records = vec![
            Record {
                id: 1,
                name: "foo".to_owned(),
                items: vec!["a".to_owned(), "b".to_owned(), "c".to_owned()],
            },
            Record {
                id: 2,
                name: "bar".to_owned(),
                items: vec!["d".to_owned(), "e".to_owned(), "f".to_owned()],
            },
        ];
        let mut cursor = Cursor::new(Vec::new());
        write(&mut cursor, &records).unwrap();
        let data = String::from_utf8(cursor.into_inner())
            .unwrap()
            .trim()
            .to_string();
        let expected = r#"
{"id":1,"name":"foo","items":["a","b","c"]}
{"id":2,"name":"bar","items":["d","e","f"]}"#
            .trim();
        assert_eq!(expected, data);
    }
}