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
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
extern crate preftool;
extern crate preftool_file;
extern crate toml;

use preftool::*;
use preftool_file::*;
use std::io::{Error, ErrorKind, Read, Result};
use toml::Value;

const TOML_EXTENSIONS: &[&str] = &[".toml"];

#[derive(Clone)]
pub struct TomlConfigFormat;

impl TomlConfigFormat {
  fn populate(builder: &mut ConfigurationProviderBuilder, value: Value, path: &ConfigKey) {
    match value {
      Value::String(s) => {
        builder.add(path, s);
      }
      Value::Integer(i) => {
        builder.add(path, i.to_string());
      }
      Value::Float(f) => {
        builder.add(path, f.to_string());
      }
      Value::Boolean(b) => {
        builder.add(path, b.to_string());
      }
      Value::Datetime(d) => {
        builder.add(path, d.to_string());
      }
      Value::Array(a) => {
        for (i, value) in a.into_iter().enumerate() {
          let index = i.to_string();
          let sub_path = path.combine(index);
          Self::populate(builder, value, &sub_path);
        }
      }
      Value::Table(t) => {
        for (key, value) in t.into_iter() {
          let sub_path = path.combine(key);
          Self::populate(builder, value, &sub_path);
        }
      }
    }
  }
}

impl ConfigurationFileFormat for TomlConfigFormat {
  type Provider = DefaultConfigurationProvider;

  #[inline]
  fn default_suffixes() -> &'static [&'static str] {
    TOML_EXTENSIONS
  }

  fn get_config<R: Read>(mut reader: R) -> Result<Self::Provider> {
    let mut content = String::new();
    reader.read_to_string(&mut content)?;

    let value: Value = match toml::from_str(&content) {
      Ok(v) => Ok(v),
      Err(e) => Err(Error::new(ErrorKind::InvalidData, e)),
    }?;

    let mut builder = ConfigurationProviderBuilder::new();
    TomlConfigFormat::populate(&mut builder, value, &ConfigKey::empty());
    Ok(builder.build())
  }
}