buni-rs 1.0.0

Reference Buni deserializer in Rust
Documentation
use crate::deserialize::{literal, Item};
use crate::error::Result;
use crate::DeserializeError;
use nom::Finish;
use serde::Deserialize;

mod iterators;
mod deserialize;
mod sequence_deserializer;
mod map_deserializer;
mod enum_deserializer;

use crate::deserialize::adapter::iterators::{DynIndexTracker, DynIter, IterAdapter, IterClone};
pub use deserialize::Deserializer;

pub fn from_str<'a, T: Deserialize<'a>>(input: &str) -> Result<T, DeserializeError<&str>> {
    match literal(input).finish()?.1 {
        Item::List(items) => {
            Ok(T::deserialize(&mut Deserializer::new(items.into_iter()))?)
        },
        _ => Err(DeserializeError::ExpectedList)
    }
}

#[test]
fn test_map() {
    use std::collections::HashMap;
    let mut expected = HashMap::new();
    expected.insert("a".to_string(), 1);
    expected.insert("b".to_string(), 2);

    assert_eq!(
        from_str::<HashMap<String, i32>>(r#"(a(1),b(2))"#).unwrap(),
        expected
    );
}

#[test]
fn test_struct() {
    #[derive(Deserialize)]
    #[derive(Debug)]
    #[derive(PartialEq)]
    struct Test {
        int: u32,
        seq: Vec<String>,
        nested: Option<Box<Self>>
    }

    let expected = Test {
        int: 1,
        seq: vec!["a".into(), "b".into()],
        nested: Some(Box::new(Test {
            int: 50,
            seq: vec!["c".into(), "d".into()],
            nested: None,
        })),
    };

    assert_eq!(from_str::<Test>(r#"(
            int(
                1
            )
            seq(
                a,b
            )
            nested(
                int(50),
                seq(c,d),
                nested(null)
            )
        )"#).unwrap(), expected);
}

#[test]
fn test_enum() {
    #[derive(Deserialize)]
    #[derive(Debug)]
    #[derive(PartialEq)]
    enum E {
        Unit,
        Newtype(u32),
        Tuple(u32, u32),
        Struct { a: u32, b: u32 },
    }

    let expected = E::Unit;
    assert_eq!(from_str::<E>(r#"(Unit)"#).unwrap(), expected);

    let expected = E::Newtype(1);
    assert_eq!(from_str::<E>(r#"(Newtype(1))"#).unwrap(), expected);

    let expected = E::Tuple(1, 2);
    assert_eq!(from_str::<E>(r#"(Tuple(1,2))"#).unwrap(), expected);

    let expected = E::Struct { a: 1, b: 5 };
    assert_eq!(from_str::<E>(r#"(Struct(a(1),b(5)))"#).unwrap(), expected);
}

pub fn from_iter<'a, T: Deserialize<'a>, I: IterClone<'a, char> + 'a>(iter: I) -> Result<T, DeserializeError<IterAdapter<'a, char>>> {
    match literal(
        IterAdapter {
            inner: DynIndexTracker {
                inner: DynIter {
                    inner: Box::new(iter),
                }.enumerate(),
                index: 0,
                length: 0,
            },
        }
    ).finish()?.1 {
        Item::List(items) => {
            Ok(T::deserialize(&mut Deserializer::new(items.into_iter()))?)
        },
        _ => Err(DeserializeError::ExpectedList)
    }
}