use config::{Config, File, FileStoredFormat, Format, Map, Value, ValueKind};
use std::io::{Error, ErrorKind};
#[derive(serde::Deserialize, Clone, Debug)]
pub struct Settings {
pub private_key: Option<String>,
pub public_key: Option<String>,
}
fn main() {
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);
let settings = Config::builder()
.add_source(file_public_key.required(false))
.add_source(file_private_key.required(false))
.build()
.unwrap();
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>> {
let mut result = Map::new();
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",
_ => {
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)
}
}
impl FileStoredFormat for PemFile {
fn file_extensions(&self) -> &'static [&'static str] {
&["pem"]
}
}