Skip to content

Commit 05f7d1e

Browse files
Merge pull request #479 from Elsoberanold/master
docs: Example for conditionally loading sources
2 parents 6946069 + b78bad6 commit 05f7d1e

File tree

5 files changed

+110
-1
lines changed

5 files changed

+110
-1
lines changed

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ config = "0.13.1"
4848

4949
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.
5050

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

5353
### More
5454

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
-----BEGIN RSA PRIVATE KEY-----
2+
MIIEpQIBAAKCAQEA7P+5Ow3YfQJJ0W4DhwdJRUWi1cYOen7qQ+XPAtFOdbJcvIZe
3+
T+D+fEENDpkDM+lOE1KtpehW4JOZ13ePLM0phktEf9hT1aB0Zc5LXB3M4YuW+lAW
4+
iXF9moHWxa2DlpyGck7cSlVVKbdljP9AQOzMdTXi3JJUWlnqjeUSINnBqCW21nOh
5+
frUZZbqBKOx7/iEgjdAsR7K5WAyVIXgbIipCAgWWjP3ejUjrl20QpXu06dGQF8O8
6+
S7ztwLwtmdUJ5SBrhiub1Ocjr+DSUvIg8kOzUp9gQiMtV8RGTr4W0Bfr75ZwgAfC
7+
oDNZ+D9S/rlZX0eJJd5rMobiQRE8qBk2oxWcxwIDAQABAoIBAQCtP3MEvGZZW+bi
8+
de2WM7lYLkOOyi2jVkuiPshJYwBcAXrRRdiDxBHEezk0Rp6UwCQW9AWEloeLu9pm
9+
LDw5n/CO/06ftl/ydk0gbuGgARjYd9ZyPUF8T75lyCxcbS8YVmvh+8wFesO6rxpJ
10+
K/6od3Iu7KleXInVUo2oFKBf608pvp/80oSvCeNCK9vh64UUZnm2PfhzD47jYE+u
11+
QEM/Ceb4LZ/6jf3SqXi/PpZu/IfDqc7JaBkuGIh4Zv+EQuSh6MYvkkn/51PmqOvf
12+
KM+bCo8U6sGzvQkMJKDUXFPfTeKCaRFdYgYDm94CCGgaMtMUBt+lm2vG2tNuKH0b
13+
a/J+x1ZBAoGBAPelu0V2T0Wg8WKjI6nbIWRbuPImAp35WyPikchqmi3hpnP68VxG
14+
D9z0TNmfr5TAajKQ11SSReIEiwJPOwq1/5v0xmqYdhyWX2alAQq5xUAfJzMDN2Rg
15+
ftO4qMcNoVeH4wAMwXc1gdRHjqWNZrz381y3Z4K/VWOm+BbG7JrejeE/AoGBAPT+
16+
DLc///zfBEA94m6/I/78jL/+SsLM7LflPByO7JNrsQTm6mo1DvluGYmE34TP8aTb
17+
dvt5KXb8gpsKS3Z9vD6FJTB0dNrSpTWEPKFTTp/VWTvwHuh8mF/r1KyngDW3IU3q
18+
7mKkVHMrfnU23qYHODJDnS6WmL3X3tJJAUXDqlp5AoGAR/VlRBrLj/zjBvlGbJ2a
19+
x1GLnPkEe6iwHe5A1A59vGU7+6loJprJEzf9eKLY3w1GDmld2FokajdNuR8Sldsq
20+
acOnP+QLNeVP1UCO2/H86dPjjQQbPVR4pcabbDN+tTNr92C9eokWr3sXbO14c+JM
21+
WZ2FO02jXzBuGBg3Ogz/BvsCgYEA69lCfotTMam0mu+4c2r5CTkxeocgi6Xh4SsC
22+
km+ZGlabJJ/0XWhU0RUH6paK432YIF/SjEbY/x4Z0Y24lgp3VSyyX5JNCHeu6fUy
23+
tQ/Q6hfmfsgryR5hRj5vEAN0bsGsgyk+cqHGVtUxOUAoWWcr11+2CqqZwnD1pjT3
24+
z6SM8+kCgYEA3GPFdb/ILXwPSEFfHE5RGWa2jlns+xVvQTaymR6ZAtLPv2RkBKvw
25+
Hwy8maCmWgw0+U/f8nMUDPVYYa/5Tyk5UzEVhtbAXGYzyY+Nk4IBFZZ+8P95RJBL
26+
8jqfXxr2ZpYf9mEgZI8v8Pr013R3Vqkpy+B8jlfpvxFdOwSzkY42ur4=
27+
-----END RSA PRIVATE KEY-----
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
-----BEGIN PUBLIC KEY-----
2+
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA7P+5Ow3YfQJJ0W4DhwdJ
3+
RUWi1cYOen7qQ+XPAtFOdbJcvIZeT+D+fEENDpkDM+lOE1KtpehW4JOZ13ePLM0p
4+
hktEf9hT1aB0Zc5LXB3M4YuW+lAWiXF9moHWxa2DlpyGck7cSlVVKbdljP9AQOzM
5+
dTXi3JJUWlnqjeUSINnBqCW21nOhfrUZZbqBKOx7/iEgjdAsR7K5WAyVIXgbIipC
6+
AgWWjP3ejUjrl20QpXu06dGQF8O8S7ztwLwtmdUJ5SBrhiub1Ocjr+DSUvIg8kOz
7+
Up9gQiMtV8RGTr4W0Bfr75ZwgAfCoDNZ+D9S/rlZX0eJJd5rMobiQRE8qBk2oxWc
8+
xwIDAQAB
9+
-----END PUBLIC KEY-----

examples/custom_file_format/main.rs

+73
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
use config::{Config, File, FileStoredFormat, Format, Map, Value, ValueKind};
2+
use std::io::{Error, ErrorKind};
3+
4+
/// The private and public key sources will be read into their associated variable:
5+
#[derive(serde::Deserialize, Clone, Debug)]
6+
pub struct Settings {
7+
pub private_key: Option<String>,
8+
pub public_key: Option<String>,
9+
}
10+
11+
fn main() {
12+
// Sourcing from two separate files for the `Settings` struct,:
13+
let file_public_key = File::new("examples/custom_file_format/files/public.pem", PemFile);
14+
let file_private_key = File::new("examples/custom_file_format/files/private.pem", PemFile);
15+
16+
// Provide the sources and build the config object:
17+
// Both are marked as optional to avoid failure if the file doesn't exist.
18+
let settings = Config::builder()
19+
.add_source(file_public_key.required(false))
20+
.add_source(file_private_key.required(false))
21+
.build()
22+
.unwrap();
23+
24+
// Deserialize the config object into your Settings struct:
25+
let settings: Settings = settings.try_deserialize().unwrap();
26+
println!("{:#?}", settings);
27+
}
28+
29+
#[derive(Debug, Clone)]
30+
pub struct PemFile;
31+
32+
impl Format for PemFile {
33+
fn parse(
34+
&self,
35+
uri: Option<&String>,
36+
text: &str,
37+
) -> Result<Map<String, config::Value>, Box<dyn std::error::Error + Send + Sync>> {
38+
// Store any valid keys into this map, they'll be merged with other sources into the final config map:
39+
let mut result = Map::new();
40+
41+
// Identify the PEM encoded data type by the first occurrence found:
42+
// NOTE: This example is kept simple, multiple or other encoded types are not handled.
43+
let key_type = vec!["PUBLIC", "PRIVATE"]
44+
.into_iter()
45+
.find(|s| text.contains(s));
46+
let key = match key_type {
47+
Some("PRIVATE") => "private_key",
48+
Some("PUBLIC") => "public_key",
49+
// Otherwise fail with an error message (the filename is implicitly appended):
50+
_ => {
51+
return Err(Box::new(Error::new(
52+
ErrorKind::InvalidData,
53+
"PEM file did not contain a Private or Public key",
54+
)))
55+
}
56+
};
57+
58+
result.insert(
59+
key.to_owned(),
60+
Value::new(uri, ValueKind::String(text.into())),
61+
);
62+
63+
Ok(result)
64+
}
65+
}
66+
67+
// A slice of extensions associated to this format, when an extension
68+
// is omitted from a file source, these will be tried implicitly:
69+
impl FileStoredFormat for PemFile {
70+
fn file_extensions(&self) -> &'static [&'static str] {
71+
&["pem"]
72+
}
73+
}
File renamed without changes.

0 commit comments

Comments
 (0)