fieldx 0.2.3

Procedural macro for constructing structs with lazily initialized fields, builder pattern, and serde support with a focus on declarative syntax.
Documentation
use fieldx::fxstruct;
use std::rc::Rc;

#[fxstruct(mode(plain), fallible(off, error(String)))]
struct Foo<const FAIL: bool = false> {
    #[fieldx(lazy, fallible)]
    ok: i32,

    #[fieldx(lazy, fallible, get(copy), get_mut, set)]
    writable: u32,

    #[fieldx(lazy, fallible, get(clone))]
    shared: Rc<String>,
}

impl<const FAIL: bool> Foo<FAIL> {
    fn build_ok(&self) -> Result<i32, String> {
        if FAIL {
            Err("will never be there".to_string())
        }
        else {
            Ok(-42)
        }
    }

    fn build_writable(&self) -> Result<u32, String> {
        if FAIL {
            Err("no value".to_string())
        }
        else {
            Ok(12)
        }
    }

    fn build_shared(&self) -> Result<Rc<String>, String> {
        if FAIL {
            Err("this is a failed outcome".to_string())
        }
        else {
            Ok(Rc::new("shared".to_string()))
        }
    }
}

#[test]
fn fallible_ok() -> Result<(), Box<dyn std::error::Error>> {
    let mut foo = Foo::<false>::new();

    assert!(*foo.ok()? == -42);

    assert_eq!(foo.writable()?, 12);
    *foo.writable_mut()? = 42;
    assert_eq!(foo.writable()?, 42);

    assert_eq!(*foo.shared()?, "shared".to_string());

    Ok(())
}

#[test]
fn fallible_error() -> Result<(), Box<dyn std::error::Error>> {
    let mut foo = Foo::<true>::new();

    assert!(foo.ok().is_err());
    assert_eq!(*foo.ok().unwrap_err(), String::from("will never be there"));

    assert!(foo.writable().is_err());
    assert_eq!(foo.writable().unwrap_err(), "no value".to_string());
    foo.set_writable(42);
    assert_eq!(foo.writable()?, 42);

    assert!(foo.shared().is_err());
    assert_eq!(*foo.shared().unwrap_err(), String::from("this is a failed outcome"));

    Ok(())
}