portaldi 0.6.3

An ergonomic lightweight compile-time depencency injection library.
Documentation
use async_trait::async_trait;
use portaldi::*;

#[tokio::main]
async fn main() {
    use app::*;

    let created = HogeCreateCmd::di().execute("test").await;

    let found = HogeQuery::di().load(created.id).await;

    assert_eq!(created, found)
}

mod app {
    use super::*;
    use super::{domain::*, repo::*};

    #[derive(DIPortal)]
    pub struct HogeCreateCmd {
        hoge_service: DI<HogeService>,
        hoge_repo: DI<dyn HogeRepository>,
    }

    impl HogeCreateCmd {
        pub async fn execute(&self, name: &str) -> Hoge {
            let new_hoge = self.hoge_service.create(name).await;
            self.hoge_repo.save(&new_hoge).await;
            new_hoge
        }
    }

    #[derive(DIPortal)]
    pub struct HogeQuery {
        hoge_repo: DI<dyn HogeRepository>,
    }

    impl HogeQuery {
        pub async fn load(&self, id: u8) -> Hoge {
            self.hoge_repo
                .get(id)
                .await
                .expect(format!("hoge not found for {}", id).as_str())
        }
    }
}
mod domain {
    use super::*;

    #[derive(PartialEq, Debug, Clone)]
    pub struct Hoge {
        pub id: u8,
        pub name: String,
    }

    #[derive(DIPortal)]
    pub struct HogeService {}

    impl HogeService {
        pub async fn create(&self, name: &str) -> Hoge {
            Hoge {
                id: 1,
                name: name.into(),
            }
        }
    }

    #[async_trait]
    pub trait HogeRepository: DITarget {
        async fn save(&self, hoge: &Hoge) -> ();
        async fn get(&self, id: u8) -> Option<Hoge>;
    }
}
mod repo {
    use super::*;
    use crate::domain::*;
    use std::{collections::HashMap, sync::Mutex};

    #[derive(Default)]
    struct InMemoryHogeRepository {
        datas: Mutex<HashMap<u8, Hoge>>,
    }

    #[portaldi::provider(HogeRepository)]
    impl DIPortal for InMemoryHogeRepository {
        fn create_for_di(_container: &DIContainer) -> Self {
            InMemoryHogeRepository::default()
        }
    }

    #[async_trait]
    impl HogeRepository for InMemoryHogeRepository {
        async fn save(&self, hoge: &Hoge) -> () {
            println!("save in repository");
            self.datas.lock().unwrap().insert(hoge.id, hoge.clone());
        }
        async fn get(&self, id: u8) -> Option<Hoge> {
            println!("get from repository");
            self.datas.lock().unwrap().get(&id).map(|v| v.clone())
        }
    }
}