pub trait Provider {
// Required methods
fn metadata(&self) -> Metadata;
fn data(&self) -> Result<BTreeMap<Profile, BTreeMap<String, Value>>, Error>;
// Provided method
fn profile(&self) -> Option<Profile> { ... }
}Expand description
Trait implemented by configuration source providers.
For an overview of built-in providers, see the top-level docs.
§Overview
A Provider reads from a source to provide configuration data for
Figments (Provider::data()). A Provider also provides Metadata
to identify the source of its configuration data (Provider::metadata()).
A provider may also optionally set a Profile for the Figment it is
merged (but not joined) into by implementing Provider::profile().
§Nesting
A Provider meant to be consumed externally should allow for optional
nesting when sensible. The general pattern
is to allow a Profile to be specified. If one is not, read the
configuration data as a Map<Profile, Dict>, thus using the top-level keys
as profiles. If one is specified, read the data as Dict and
Profile::collect() into the specified profile.
§Example
Implementing a Provider requires implementing methods that provide both of
these pieces of data. The first, Provider::metadata() identifies the
provider’s configuration sources, if any, and allows the provider to
customize how paths to keys are interpolated. The second,
Provider::data(), actually reads the configuration and returns the data.
As an example, consider a provider that reads configuration from a
networked store at some Url. A Provider implementation for such a
provider may resemble the following:
use figment::{Provider, Metadata, Profile, Error, value::{Map, Dict}};
/// A provider that fetches its data from a given URL.
struct NetProvider {
/// The profile to emit data to if nesting is disabled.
profile: Option<Profile>,
/// The url to fetch data from.
url: Url
};
impl Provider for NetProvider {
/// Returns metadata with kind `Network`, custom source `self.url`,
/// and interpolator that returns a URL of `url/a/b/c` for key `a.b.c`.
fn metadata(&self) -> Metadata {
let url = self.url.clone();
Metadata::named("Network")
.source(self.url.as_str())
.interpolater(move |profile, keys| match profile.is_custom() {
true => format!("{}/{}/{}", url, profile, keys.join("/")),
false => format!("{}/{}", url, keys.join("/")),
})
}
/// Fetches the data from `self.url`. Note that `Dict`, `Map`, and
/// `Profile` are `Deserialize`, so we can deserialized to them.
fn data(&self) -> Result<Map<Profile, Dict>, Error> {
fn fetch<'a, T: Deserialize<'a>>(url: &Url) -> Result<T, Error> {
/* fetch from the network, deserialize into `T` */
}
match &self.profile {
// Don't nest: `fetch` into a `Dict`.
Some(profile) => Ok(profile.collect(fetch(&self.url)?)),
// Nest: `fetch` into a `Map<Profile, Dict>`.
None => fetch(&self.url),
}
}
}Required Methods§
Provided Methods§
Implementations on Foreign Types§
Source§impl<K, V> Provider for (K, V)
This is exactly equivalent to Serialized::global(K, V).
impl<K, V> Provider for (K, V)
This is exactly equivalent to Serialized::global(K, V).