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
#![cfg(feature = "async")]
use fieldx::fxstruct;
use std::sync::Arc;

#[fxstruct(mode(async), 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: Arc<String>,
}

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

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

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

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

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

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

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

    Ok(())
}

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

    assert!(foo.ok().await.is_err(), "Expected error for ok field");
    assert_eq!(
        *foo.ok().await.unwrap_err(),
        String::from("will never be there"),
        "Unexpected error message for ok field"
    );

    assert!(foo.writable().await.is_err(), "Expected error for writable field");
    assert_eq!(
        foo.writable().await.unwrap_err(),
        "no value".to_string(),
        "Unexpected error message for writable field"
    );
    foo.set_writable(42).await;
    assert_eq!(foo.writable().await, Ok(42), "Expected writable field to be set to 42");

    assert!(foo.shared().await.is_err(), "Expected error for shared field");
    assert_eq!(
        *foo.shared().await.unwrap_err(),
        String::from("this is a failed outcome"),
        "Unexpected error message for shared field"
    );

    Ok(())
}