summaryrefslogtreecommitdiffstats
path: root/examples/custom_format/main.rs
blob: c21bac2e01b58374018a349bb3e7d966694019e3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
use config::{Config, File, FileExtensions, 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 crippled, 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 crazy 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 FileExtensions for MyFormat {
    fn extensions(&self) -> &'static [&'static str] {
        &MY_FORMAT_EXT
    }
}