Skip to content

Commit

Permalink
Merge pull request #479 from Elsoberanold/master
Browse files Browse the repository at this point in the history
docs: Example for conditionally loading sources
  • Loading branch information
matthiasbeyer authored Oct 22, 2023
2 parents 6946069 + b78bad6 commit 05f7d1e
Show file tree
Hide file tree
Showing 5 changed files with 110 additions and 1 deletion.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ config = "0.13.1"

Library provides out of the box support for most renowned data formats such as JSON or Yaml. Nonetheless, it contains an extensibility point - a `Format` trait that, once implemented, allows seamless integration with library's APIs using custom, less popular or proprietary data formats.

See [custom_format](https://github.com/mehcode/config-rs/tree/master/examples/custom_format) example for more information.
See [custom_file_format](https://github.com/mehcode/config-rs/tree/master/examples/custom_file_format) example for more information.

### More

Expand Down
27 changes: 27 additions & 0 deletions examples/custom_file_format/files/private.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEpQIBAAKCAQEA7P+5Ow3YfQJJ0W4DhwdJRUWi1cYOen7qQ+XPAtFOdbJcvIZe
T+D+fEENDpkDM+lOE1KtpehW4JOZ13ePLM0phktEf9hT1aB0Zc5LXB3M4YuW+lAW
iXF9moHWxa2DlpyGck7cSlVVKbdljP9AQOzMdTXi3JJUWlnqjeUSINnBqCW21nOh
frUZZbqBKOx7/iEgjdAsR7K5WAyVIXgbIipCAgWWjP3ejUjrl20QpXu06dGQF8O8
S7ztwLwtmdUJ5SBrhiub1Ocjr+DSUvIg8kOzUp9gQiMtV8RGTr4W0Bfr75ZwgAfC
oDNZ+D9S/rlZX0eJJd5rMobiQRE8qBk2oxWcxwIDAQABAoIBAQCtP3MEvGZZW+bi
de2WM7lYLkOOyi2jVkuiPshJYwBcAXrRRdiDxBHEezk0Rp6UwCQW9AWEloeLu9pm
LDw5n/CO/06ftl/ydk0gbuGgARjYd9ZyPUF8T75lyCxcbS8YVmvh+8wFesO6rxpJ
K/6od3Iu7KleXInVUo2oFKBf608pvp/80oSvCeNCK9vh64UUZnm2PfhzD47jYE+u
QEM/Ceb4LZ/6jf3SqXi/PpZu/IfDqc7JaBkuGIh4Zv+EQuSh6MYvkkn/51PmqOvf
KM+bCo8U6sGzvQkMJKDUXFPfTeKCaRFdYgYDm94CCGgaMtMUBt+lm2vG2tNuKH0b
a/J+x1ZBAoGBAPelu0V2T0Wg8WKjI6nbIWRbuPImAp35WyPikchqmi3hpnP68VxG
D9z0TNmfr5TAajKQ11SSReIEiwJPOwq1/5v0xmqYdhyWX2alAQq5xUAfJzMDN2Rg
ftO4qMcNoVeH4wAMwXc1gdRHjqWNZrz381y3Z4K/VWOm+BbG7JrejeE/AoGBAPT+
DLc///zfBEA94m6/I/78jL/+SsLM7LflPByO7JNrsQTm6mo1DvluGYmE34TP8aTb
dvt5KXb8gpsKS3Z9vD6FJTB0dNrSpTWEPKFTTp/VWTvwHuh8mF/r1KyngDW3IU3q
7mKkVHMrfnU23qYHODJDnS6WmL3X3tJJAUXDqlp5AoGAR/VlRBrLj/zjBvlGbJ2a
x1GLnPkEe6iwHe5A1A59vGU7+6loJprJEzf9eKLY3w1GDmld2FokajdNuR8Sldsq
acOnP+QLNeVP1UCO2/H86dPjjQQbPVR4pcabbDN+tTNr92C9eokWr3sXbO14c+JM
WZ2FO02jXzBuGBg3Ogz/BvsCgYEA69lCfotTMam0mu+4c2r5CTkxeocgi6Xh4SsC
km+ZGlabJJ/0XWhU0RUH6paK432YIF/SjEbY/x4Z0Y24lgp3VSyyX5JNCHeu6fUy
tQ/Q6hfmfsgryR5hRj5vEAN0bsGsgyk+cqHGVtUxOUAoWWcr11+2CqqZwnD1pjT3
z6SM8+kCgYEA3GPFdb/ILXwPSEFfHE5RGWa2jlns+xVvQTaymR6ZAtLPv2RkBKvw
Hwy8maCmWgw0+U/f8nMUDPVYYa/5Tyk5UzEVhtbAXGYzyY+Nk4IBFZZ+8P95RJBL
8jqfXxr2ZpYf9mEgZI8v8Pr013R3Vqkpy+B8jlfpvxFdOwSzkY42ur4=
-----END RSA PRIVATE KEY-----
9 changes: 9 additions & 0 deletions examples/custom_file_format/files/public.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA7P+5Ow3YfQJJ0W4DhwdJ
RUWi1cYOen7qQ+XPAtFOdbJcvIZeT+D+fEENDpkDM+lOE1KtpehW4JOZ13ePLM0p
hktEf9hT1aB0Zc5LXB3M4YuW+lAWiXF9moHWxa2DlpyGck7cSlVVKbdljP9AQOzM
dTXi3JJUWlnqjeUSINnBqCW21nOhfrUZZbqBKOx7/iEgjdAsR7K5WAyVIXgbIipC
AgWWjP3ejUjrl20QpXu06dGQF8O8S7ztwLwtmdUJ5SBrhiub1Ocjr+DSUvIg8kOz
Up9gQiMtV8RGTr4W0Bfr75ZwgAfCoDNZ+D9S/rlZX0eJJd5rMobiQRE8qBk2oxWc
xwIDAQAB
-----END PUBLIC KEY-----
73 changes: 73 additions & 0 deletions examples/custom_file_format/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
use config::{Config, File, FileStoredFormat, Format, Map, Value, ValueKind};
use std::io::{Error, ErrorKind};

/// The private and public key sources will be read into their associated variable:
#[derive(serde::Deserialize, Clone, Debug)]
pub struct Settings {
pub private_key: Option<String>,
pub public_key: Option<String>,
}

fn main() {
// Sourcing from two separate files for the `Settings` struct,:
let file_public_key = File::new("examples/custom_file_format/files/public.pem", PemFile);
let file_private_key = File::new("examples/custom_file_format/files/private.pem", PemFile);

// Provide the sources and build the config object:
// Both are marked as optional to avoid failure if the file doesn't exist.
let settings = Config::builder()
.add_source(file_public_key.required(false))
.add_source(file_private_key.required(false))
.build()
.unwrap();

// Deserialize the config object into your Settings struct:
let settings: Settings = settings.try_deserialize().unwrap();
println!("{:#?}", settings);
}

#[derive(Debug, Clone)]
pub struct PemFile;

impl Format for PemFile {
fn parse(
&self,
uri: Option<&String>,
text: &str,
) -> Result<Map<String, config::Value>, Box<dyn std::error::Error + Send + Sync>> {
// Store any valid keys into this map, they'll be merged with other sources into the final config map:
let mut result = Map::new();

// Identify the PEM encoded data type by the first occurrence found:
// NOTE: This example is kept simple, multiple or other encoded types are not handled.
let key_type = vec!["PUBLIC", "PRIVATE"]
.into_iter()
.find(|s| text.contains(s));
let key = match key_type {
Some("PRIVATE") => "private_key",
Some("PUBLIC") => "public_key",
// Otherwise fail with an error message (the filename is implicitly appended):
_ => {
return Err(Box::new(Error::new(
ErrorKind::InvalidData,
"PEM file did not contain a Private or Public key",
)))
}
};

result.insert(
key.to_owned(),
Value::new(uri, ValueKind::String(text.into())),
);

Ok(result)
}
}

// A slice of extensions associated to this format, when an extension
// is omitted from a file source, these will be tried implicitly:
impl FileStoredFormat for PemFile {
fn file_extensions(&self) -> &'static [&'static str] {
&["pem"]
}
}
File renamed without changes.

0 comments on commit 05f7d1e

Please sign in to comment.