1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
//! There are one type can be provider of services: `ServiceProvider`. It used as store for dependencies with
//! `Instance` and `Singleton` lifetimes, and for declaring all dependencies using `.add_*()` methods. It can be forked to
//! create a local scope with local instances.
//!
//! There are four lifetimes for dependencies:
//! 1. `Transient`. Service will be created when resolves. Can depend on dependencies with anything lifetime.
//! 2. `Singleton`. Service will be created once at `ServiceProvider` when it resolved (lazy). Can depend on dependencies
//! with anything lifetime. Cannot depend on services from forked `ServiceProvider` instances.
//! 3. `Instance`. Dependency was created outside of `ServiceProvider` and can be used by any other dependency.
//!
//! How to work:
//! 1. Declare your structs.
//! 2. Create constructors and add `#[inject]` macro on its.
//! 3. Create a `ServiceProvider` object.
//! 4. Add your services and dependencies using `ServiceProvider::add_*` methods.
//! 5. Fork `ServiceProvider` if you need to create local scope.
//! 6. Get service from provider using `.resolve()` method.
//! 7. Work with service.
//!
//! Example:
//! ```rust
//! use std::rc::Rc;
//! use teloc::*;
//!
//! struct ConstService {
//!     number: Rc<i32>,
//! }
//! #[inject]
//! impl ConstService {
//!     pub fn new(number: Rc<i32>) -> Self {
//!         ConstService { number }
//!     }
//! }
//!
//! // derive macro can be used when all fields implement `Dependency` trait,
//! // but we do not recommend use it in production code
//! #[derive(Dependency)]
//! struct Controller {
//!     number_service: ConstService,
//! }
//!
//! // Create `ServiceProvider` struct that store itself all dependencies
//! let container = ServiceProvider::new()
//!     // Add dependency with `Singleton` lifetime. More about lifetimes see above.
//!     .add_transient::<ConstService>()
//!     // Add dependency with `Transient` lifetime. More about lifetimes see above.
//!     .add_transient::<Controller>();
//! // Fork `ServiceProvider`. It creates a new `ServiceProvider` which will have
//! // access to the dependencies from parent `ServiceProvider`.
//! let scope = container
//!     // .fork() method creates a local mutable scope with self parent immutable `ServiceProvider`.
//!     .fork()
//!     // Add an instance of `Rc<i32>` that will be used when `ConstService` will be initialized.
//!     .add_instance(Rc::new(10));
//! let controller: Controller = scope.resolve();
//! assert_eq!(*controller.number_service.number, 10);
//! ```

#![deny(unsafe_code)]

#[cfg(feature = "actix-support")]
mod actix_support;
mod container;
mod dependency;
pub mod dev;
mod get_dependencies;
mod index;
mod resolver;
mod service_provider;

#[cfg(feature = "actix-support")]
pub use actix_support::DiActixHandler;

pub use {
    dependency::Dependency,
    resolver::Resolver,
    service_provider::ServiceProvider,
    teloc_macros::{inject, Dependency},
};

#[doc(hidden)]
pub mod reexport {
    pub use {frunk, frunk::HList};
}