//! # Runtime dependency injection.
//!
//! By default, services provided by the [`Injector`] use thread-safe pointers.
//! This is because [`Arc<T>`](std::sync::Arc) is used to hold instances of the
//! services. This can be changed to [`Rc<T>`](std::rc::Rc) by disabling
//! default features and enabling the "rc" feature:
//!
//! ```text
//! [dependencies.runtime_injector]
//! version = "*" # Replace with the version you want to use
//! default-features = false
//! features = ["rc"]
//! ```
//!
//! ## Getting started
//!
//! If you are unfamiliar with dependency injection, then you may want to check
//! about how a container can help
//! [simplify your application][ioc]. Otherwise,
//! check out the [getting started guide][getting-started]
//!
//! [ioc]: crate::docs::inversion_of_control
//! [getting-started]: crate::docs::getting_started
//!
//! ## Dependency injection at runtime (rather than compile-time)
//!
//! Runtime dependency injection allows for advanced configuration of services
//! during runtime rather than needing to decide what services your application
//! will use at compile time. This means you can read a config when your
//! application starts, decide what implementations you want to use for your
//! interfaces, and assign those at runtime. This is also slightly slower than
//! compile-time dependency injection, so if pointer indirection, dynamic
//! dispatch, or heap allocations are a concern, then a compile-time dependency
//! injection library might work better instead. However, in asynchronous,
//! I/O-based applications like a web server, the additional overhead is
//! probably insignificant compared to the additional flexibility you get with
//! runtime_injector.
//!
//! ## Interfaces
//!
//! Using interfaces allows you to write your services without worrying about
//! how its dependencies are implemented. You can think of them like generic
//! type parameters for your service, except rather than needing to add a new
//! type parameter, you use a service pointer to the interface for your
//! dependency. This makes your code easier to read and faster to write, and
//! keeps your services decoupled from their dependencies and dependents.
//!
//! Interfaces are implemented as trait objects in runtime_injector. For
//! instance, you may define a trait `UserDatabase` and implement it for
//! several different types. [`Svc<dyn UserDatabase>`](crate::Svc<T>) is a
//! reference-counted service pointer to an implementation of your trait.
//! Similarly, `dyn UserDatabase` is your interface. You can read more about
//! how interfaces work and how they're created in the
//! [type-level docs](crate::Interface).
//!
//! ## Service lifetimes
//!
//! Lifetimes of services created by the [`Injector`] are controlled by the
//! [`Provider`] used to construct those lifetimes. Currently, there are three
//! built-in service provider types:
//!
//! - **[Transient](crate::TransientProvider):** A service is created each time
//! it is requested. This will never return the same instance of a service
//! more than once.
//! - **[Singleton](crate::SingletonProvider):** A service is created only the
//! first time it is requested, then that single instance is reused for each
//! future request.
//! - **[Constant](crate::ConstantProvider):** Used for services that are not
//! created using a service factory and instead can have their instance
//! provided to the container directly. This behaves similar to singleton in
//! that the same instance is provided each time the service is requested.
//!
//! Custom service providers can also be created by implementing either the
//! [`TypedProvider`] or [`Provider`] trait.
//!
//! ## Fallible service factories
//!
//! Not all types can always be successfully created. Sometimes, creating an
//! instance of a service might fail. Rather than panicking on error, it's
//! possible to instead return a [`Result<T, E>`] from your constructors and
//! inject the result as a [`Svc<T>`]. Read more in the
//! [docs for `IntoFallible`](crate::IntoFallible).
//!
//! ## Owned service pointers
//!
//! In general, providers need to be able to provide their services via
//! reference-counted service pointers, or [`Svc<T>`]. The issue with this is
//! that you cannot get mutable or owned access to the contents of those
//! pointers since they are shared pointers. As a result, you may need to clone
//! some dependencies in your constructors if you want to be able to own them.
//!
//! If your dependency is a transient service, then it might make more sense
//! to inject it as a [`Box<T>`] than clone it from a reference-counted service
//! pointer. In these cases, you can request a [`Box<T>`] directly from the
//! injector and avoid needing to clone your dependency entirely!
//!
//! ## Custom target-specific arguments
//!
//! Sometimes it's useful to be able to pass a specific value into your
//! services. For example, if you're writing a database service and you need a
//! connection string, you could define a new `ConnectionString` struct as a
//! newtype for [`String`], but that would be a bit excessive for passing in a
//! single value. If you had several arguments you needed to pass in this way,
//! then that would mean you would need a new type for each one.
//!
//! Rather than creating a bunch of newtypes, you can use [`Arg<T>`] to pass in
//! pre-defined values directly to your services. For example, you can use
//! `Arg<String>` to pass in your connection string, plus you can use
//! `Arg<usize>` to set the max size of your connection pool, and another
//! `Arg<String>` in your logging service to set your logging format without
//! needing to worry about accidentally using your connection string as your
//! logging format!
//!
//! ## Example
//!
//! ```
//! use runtime_injector::{
//! define_module, Module, interface, Injector, Svc, IntoSingleton,
//! TypedProvider, IntoTransient, constant
//! };
//! use std::error::Error;
//!
//! // Some type that represents a user
//! struct User;
//!
//! // This is our interface. In practice, multiple structs can implement this
//! // trait, and we don't care what the concrete type is most of the time in
//! // our other services as long as it implements this trait. Because of this,
//! // we're going to use dynamic dispatch later so that we can determine the
//! // concrete type at runtime (vs. generics, which are determined instead at
//! // compile time).
//! //
//! // The `Send` and `Sync` supertrait requirements are only necessary when
//! // compiling with the "arc" feature to allow for service pointer
//! // downcasting.
//! trait DataService: Send + Sync {
//! fn get_user(&self, user_id: &str) -> Option<User>;
//! }
//!
//! // We can use a data service which connects to a SQL database.
//! #[derive(Default)]
//! struct SqlDataService;
//! impl DataService for SqlDataService {
//! fn get_user(&self, _user_id: &str) -> Option<User> { todo!() }
//! }
//!
//! // ... Or we can mock out the data service entirely!
//! #[derive(Default)]
//! struct MockDataService;
//! impl DataService for MockDataService {
//! fn get_user(&self, _user_id: &str) -> Option<User> { Some(User) }
//! }
//!
//! // Specify which types implement the DataService interface. This does not
//! // determine the actual implementation used. It only registers the types as
//! // possible implementations of the DataService interface.
//! interface!(dyn DataService = [SqlDataService, MockDataService]);
//!
//! // Here's another service our application uses. This service depends on our
//! // data service, however it doesn't care how that service is actually
//! // implemented as long as it works. Because of that, we're using dynamic
//! // dispatch to allow the implementation to be determined at runtime.
//! struct UserService {
//! data_service: Svc<dyn DataService>,
//! }
//!
//! impl UserService {
//! // This is just a normal constructor. The only requirement is that each
//! // parameter is a valid injectable dependency.
//! pub fn new(data_service: Svc<dyn DataService>) -> Self {
//! UserService { data_service }
//! }
//!
//! pub fn get_user(&self, user_id: &str) -> Option<User> {
//! // UserService doesn't care how the user is actually retrieved
//! self.data_service.get_user(user_id)
//! }
//! }
//!
//! fn main() -> Result<(), Box<dyn Error>> {
//! // This is where we register our services. Each call to `.provide` adds
//! // a new service provider to our container, however nothing is actually
//! // created until it is requested. This means we can add providers for
//! // types we aren't actually going to use without worrying about
//! // constructing instances of those types that we aren't actually using.
//! let mut builder = Injector::builder();
//!
//! // We can manually add providers to our builder
//! builder.provide(UserService::new.singleton());
//!
//! struct Foo(Svc<dyn DataService>);
//!
//! // Alternatively, modules can be used to group providers and
//! // configurations together, and can be defined via the
//! // define_module! macro
//! let module = define_module! {
//! services = [
//! // Simple tuple structs can be registered as services directly without
//! // defining any additional constructors
//! Foo.singleton(),
//!
//! // Note that we can register closures as providers as well
//! (|_: Svc<dyn DataService>| "Hello, world!").singleton(),
//! (|_: Option<Svc<i32>>| 120.9).transient(),
//!
//! // Since we know our dependency is transient, we can request an
//! // owned pointer to it rather than a reference-counted pointer
//! (|value: Box<f32>| format!("{}", value)).transient(),
//!
//! // We can also provide constant values directly to our services
//! constant(8usize),
//! ],
//! interfaces = {
//! // Let's choose to use the MockDataService as our data service
//! dyn DataService = [MockDataService::default.singleton()],
//! },
//! };
//!
//! // You can easily add a module to your builder
//! builder.add_module(module);
//!
//! // Now that we've registered all our providers and implementations, we
//! // can start relying on our container to create our services for us!
//! let injector = builder.build();
//! let user_service: Svc<UserService> = injector.get()?;
//! let _user = user_service.get_user("john");
//!
//! Ok(())
//! }
//! ```
compile_error!;
compile_error!;
pub use *;
pub use *;
pub use *;
pub use *;
pub use *;
pub use *;
pub use *;