Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

docs: Example for conditionally loading sources #479

Merged
merged 1 commit into from
Oct 22, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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.