Common/Environment/Requires.rs
1//! # Requires Trait
2//!
3//! Defines the `Requires` trait, which is the heart of the capability-based
4//! dependency injection system.
5
6use std::sync::Arc;
7
8use super::Environment::Environment;
9
10/// A trait that enables an environment (`Self`) to provide a specific
11/// capability (`Capability`).
12///
13/// This is the central mechanism for dependency injection. An `ActionEffect`
14/// can be generic over an environment `TEnvironment` as long as it has the
15/// bound `TEnvironment: Requires<MyCapability>`. The effect can then call
16/// `Environment.Require()` to receive a shared instance of the service it needs
17/// to perform its operation.
18///
19/// The `Capability` is typically a trait object, such as
20/// `dyn FileSystemReader`.
21pub trait Requires<Capability:?Sized>: Environment {
22 /// Returns the required capability from the environment, wrapped in an
23 /// `Arc` for safe, shared ownership.
24 fn Require(&self) -> Arc<Capability>;
25}
26
27/// A blanket implementation that allows an `Arc<TEnvironment>` to provide a
28/// capability if the inner environment `TEnvironment` can provide it.
29///
30/// This is a crucial piece of ergonomics that allows code to call `.Require()`
31/// directly on a shared `Arc<TEnvironment>` reference without needing to
32/// dereference it first, simplifying effect implementation logic.
33impl<TEnvironment:Requires<Capability> + ?Sized, Capability:?Sized> Requires<Capability> for Arc<TEnvironment> {
34 /// Fulfills the requirement by dereferencing the `Arc` and calling the
35 /// `Require` method on the inner environment `TEnvironment`.
36 fn Require(&self) -> Arc<Capability> { (**self).Require() }
37}