| use config::{Config, File, FileStoredFormat, Format, Map, Value, ValueKind}; |
| |
| fn main() { |
| let config = Config::builder() |
| .add_source(File::from_str("bad", MyFormat)) |
| .add_source(File::from_str("good", MyFormat)) |
| .build(); |
| |
| match config { |
| Ok(cfg) => println!("A config: {:#?}", cfg), |
| Err(e) => println!("An error: {}", e), |
| } |
| } |
| |
| #[derive(Debug, Clone)] |
| pub struct MyFormat; |
| |
| impl Format for MyFormat { |
| fn parse( |
| &self, |
| uri: Option<&String>, |
| text: &str, |
| ) -> Result<Map<String, config::Value>, Box<dyn std::error::Error + Send + Sync>> { |
| // Let's assume our format is somewhat malformed, but this is fine |
| // In real life anything can be used here - nom, serde or other. |
| // |
| // For some more real-life examples refer to format implementation within the library code |
| let mut result = Map::new(); |
| |
| if text == "good" { |
| result.insert( |
| "key".to_string(), |
| Value::new(uri, ValueKind::String(text.into())), |
| ); |
| } else { |
| println!("Something went wrong in {:?}", uri); |
| } |
| |
| Ok(result) |
| } |
| } |
| |
| // As strange as it seems for config sourced from a string, legacy demands its sacrifice |
| // It is only required for File source, custom sources can use Format without caring for extensions |
| static MY_FORMAT_EXT: Vec<&'static str> = vec![]; |
| impl FileStoredFormat for MyFormat { |
| fn file_extensions(&self) -> &'static [&'static str] { |
| &MY_FORMAT_EXT |
| } |
| } |