miniconf 0.20.1

Serialize/deserialize/access reflection for trees
Documentation
use miniconf::{KeyError, Leaf, SerdeError, Tree, ValueError, json_core};

mod common;
use common::*;

#[derive(PartialEq, Debug, Clone, Default, Tree)]
struct Inner {
    data: u32,
}

#[derive(Debug, Clone, Default, Tree)]
struct Settings {
    value: Option<Inner>,
}

#[test]
fn just_option() {
    assert_eq!(paths::<Option::<u32>, 1>(), [""]);
}

#[test]
fn option_get_set_none() {
    let mut settings = Settings::default();
    let mut data = [0; 100];

    // Check that if the option is None, the value cannot be get or set.
    settings.value.take();
    assert_eq!(
        json_core::get(&settings, "/value_foo", &mut data),
        Err(KeyError::NotFound.into())
    );
    assert_eq!(
        json_core::get(&settings, "/value", &mut data),
        Err(ValueError::Absent.into())
    );
    // The Absent field indicates at which depth the variant was absent
    assert_eq!(
        json_core::set(&mut settings, "/value/data", b"5"),
        Err(ValueError::Absent.into())
    );
}

#[test]
fn option_get_set_some() {
    let mut settings = Settings::default();

    // Check that if the option is Some, the value can be get or set.
    settings.value.replace(Inner { data: 5 });

    set_get(&mut settings, "/value/data", b"7");
    assert_eq!(settings.value.unwrap().data, 7);
}

#[test]
fn option_iterate_some_none() {
    assert_eq!(paths::<Settings, 3>(), ["/value/data"]);
}

#[test]
fn option_test_normal_option() {
    #[derive(Copy, Clone, Default, Tree)]
    struct S {
        data: Leaf<Option<u32>>,
    }
    assert_eq!(paths::<S, 1>(), ["/data"]);

    let mut s = S::default();
    assert!(s.data.is_none());

    set_get(&mut s, "/data", b"7");
    assert_eq!(*s.data, Some(7));

    set_get(&mut s, "/data", b"null");
    assert!(s.data.is_none());
}

#[test]
fn option_test_defer_option() {
    #[derive(Copy, Clone, Default, Tree)]
    struct S {
        data: Option<u32>,
    }
    assert_eq!(paths::<S, 1>(), ["/data"]);

    let mut s = S::default();
    assert!(s.data.is_none());

    assert!(json_core::set(&mut s, "/data", b"7").is_err());
    s.data = Some(0);
    set_get(&mut s, "/data", b"7");
    assert_eq!(s.data, Some(7));

    assert!(json_core::set(&mut s, "/data", b"null").is_err());
}

#[test]
fn option_absent() {
    #[derive(Copy, Clone, Default, Tree)]
    struct I(());

    #[derive(Copy, Clone, Default, Tree)]
    struct S {
        d: Option<u32>,
        dm: Option<I>,
    }

    let mut s = S::default();
    assert_eq!(
        json_core::set(&mut s, "/d", b"7"),
        Err(ValueError::Absent.into())
    );
    // Check precedence
    assert_eq!(
        json_core::set(&mut s, "/d", b""),
        Err(ValueError::Absent.into())
    );
    assert_eq!(
        json_core::set(&mut s, "/d/foo", b"7"),
        Err(ValueError::Absent.into())
    );
    assert_eq!(
        json_core::set(&mut s, "", b"7"),
        Err(KeyError::TooShort.into())
    );
    s.d = Some(3);
    assert_eq!(json_core::set(&mut s, "/d", b"7"), Ok(1));
    assert_eq!(
        json_core::set(&mut s, "/d/foo", b"7"),
        Err(KeyError::TooLong.into())
    );
    assert!(matches!(
        json_core::set(&mut s, "/d", b""),
        Err(SerdeError::Inner(_))
    ));
    assert_eq!(json_core::set(&mut s, "/d", b"7 "), Ok(2));
    assert_eq!(json_core::set(&mut s, "/d", b" 7"), Ok(2));
    assert!(matches!(
        json_core::set(&mut s, "/d", b"7i"),
        Err(SerdeError::Finalization(_))
    ));
}

#[test]
fn array_option() {
    // This tests that no invalid bounds are inferred for Options and Options in arrays.
    #[allow(dead_code)]
    #[derive(Copy, Clone, Default, Tree)]
    struct S {
        a: Option<u32>,
        b: [Leaf<Option<u32>>; 1],
        c: [Option<u32>; 1],
        d: [Option<Leaf<u32>>; 1],
    }
}