Available on nightly only.
Expand description

Contains the Provider trait and accompanying API, which enable trait objects to provide data based on typed requests, an alternate form of runtime reflection.

Provider and Demand

Provider and the associated APIs support generic, type-driven access to data, and a mechanism for implementers to provide such data. The key parts of the interface are the Provider trait for objects which can provide data, and the request_value and request_ref functions for requesting data from an object which implements Provider. Generally, end users should not call request_* directly, they are helper functions for intermediate implementers to use to implement a user-facing interface.

Typically, a data provider is a trait object of a trait which extends Provider. A user will request data from a trait object by specifying the type of the data.

Data flow

  • A user requests an object of a specific type, which is delegated to request_value or request_ref
  • request_* creates a Demand object and passes it to Provider::provide
  • The data provider’s implementation of Provider::provide tries providing values of different types using Demand::provide_*. If the type matches the type requested by the user, the value will be stored in the Demand object.
  • request_* unpacks the Demand object and returns any stored value to the user.

Examples

use error_stack::provider::{request_ref, Demand, Provider};

// Definition of MyTrait, a data provider.
trait MyTrait: Provider {
    // ...
}

// Methods on `MyTrait` trait objects.
impl dyn MyTrait + '_ {
    /// Get a reference to a field of the implementing struct.
    pub fn get_context_by_ref<T: ?Sized + 'static>(&self) -> Option<&T> {
        request_ref::<T, _>(self)
    }
}

// Downstream implementation of `MyTrait` and `Provider`.
impl MyTrait for SomeConcreteType {
    // ...
}

impl Provider for SomeConcreteType {
    fn provide<'a>(&'a self, demand: &mut Demand<'a>) {
        // Provide a string reference. We could provide multiple values with
        // different types here.
        demand.provide_ref::<String>(&self.some_string);
    }
}

// Downstream usage of `MyTrait`.
fn use_my_trait(obj: &dyn MyTrait) {
    // Request a &String from obj.
    let _ = obj.get_context_by_ref::<String>().unwrap();
}

In this example, if the concrete type of obj in use_my_trait is SomeConcreteType, then the get_context_ref call will return a reference to obj.some_string with type &String.

Structs

A helper object for providing data by type.

Traits

Trait implemented by a type which can dynamically provide values based on type.

Functions

Request a reference from the Provider.

Request a value from the Provider.