Skip to main content

Source

Trait Source 

Source
pub trait Source {
    // Required methods
    fn name(&self) -> &str;
    fn deserialize(
        &self,
        seed: &mut dyn for<'de> FnMut(&mut dyn Deserializer<'de>) -> Result<(), Error>,
    ) -> Result<(), Error>;

    // Provided method
    fn category(&self) -> Category { ... }
}
Expand description

A named origin of raw configuration data.

The sources module provides implementations for the common cases: JsonStr, TomlStr, EnvSource and CliSource (each behind a feature). Implement this trait yourself to support a format the built-ins miss (XML, a database, a secret store, etc.).

§Contract

  • deserialize is called inline from Config::build and is synchronous. If your source needs I/O or async work, do it on construction (the way sources::TomlStr reads a file in the file-loading helper) and store the materialized data on the struct.
  • To surface a parse/load error, convert it through <erased_serde::Error as serde::de::Error>::custom(my_error).
  • category defaults to Category::Custom("user"). Override it to a built-in bucket or your own Custom("...") label so provenance maps render the source the way you want.

§Example: a custom in-memory source

The shape any source ends up using: build a serde_json::Value (or any type that implements serde::Deserializer) and erase it through erased_serde. The built-in env source uses exactly this pattern.

use provcfg::erased_serde;
use provcfg::{Category, Config, Configurable, Source};

#[derive(Configurable, serde::Deserialize, Clone, Default)]
struct Settings {
    host: String,
}

struct MapSource {
    name: String,
    data: serde_json::Value,
}

impl Source for MapSource {
    fn name(&self) -> &str {
        &self.name
    }

    fn category(&self) -> Category {
        Category::Custom("map")
    }

    fn deserialize(
        &self,
        seed: &mut dyn for<'de> FnMut(
            &mut dyn erased_serde::Deserializer<'de>,
        ) -> Result<(), erased_serde::Error>,
    ) -> Result<(), erased_serde::Error> {
        let mut erased = <dyn erased_serde::Deserializer>::erase(&self.data);
        seed(&mut erased)
    }
}

let settings = Config::new()
    .add_source(MapSource {
        name: "demo".into(),
        data: serde_json::json!({ "host": "from-map" }),
    })
    .build::<SettingsProv>()
    .unwrap();

assert_eq!(settings.host.value(), "from-map");
assert_eq!(settings.host.source().category(), Category::Custom("map"));

Required Methods§

Source

fn name(&self) -> &str

Human-readable label for this source, surfaced in Error messages.

Source

fn deserialize( &self, seed: &mut dyn for<'de> FnMut(&mut dyn Deserializer<'de>) -> Result<(), Error>, ) -> Result<(), Error>

Hand this source’s raw data to seed as a type-erased deserializer. Called once per Config::build.

Provided Methods§

Source

fn category(&self) -> Category

The Category bucket this source belongs to. Defaults to Category::Custom("user").

Dyn Compatibility§

This trait is dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety".

Implementors§