summaryrefslogtreecommitdiff
path: root/systems/_config/src/rw.rs
blob: 36ea00cef366b7d72abc335216ff823f73a988ce (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
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
use crate::error::ConfigError;
use serde::{Deserialize, Serialize};
use std::path::Path;

pub async fn read_config<C>(path: impl AsRef<Path>) -> Result<C, ConfigError>
where
    C: for<'a> Deserialize<'a>,
{
    let path_ref = path.as_ref();
    let ext = path_ref
        .extension()
        .and_then(|ext| ext.to_str())
        .unwrap_or("json");
    let format = ext_fmt(&ext.to_lowercase());

    let content = std::fs::read_to_string(path_ref).map_err(ConfigError::ConfigReadFailed)?;

    match format {
        Format::Yaml => {
            serde_yaml::from_str(&content).map_err(|e| ConfigError::Other(e.to_string()))
        }
        Format::Toml => toml::from_str(&content).map_err(|e| ConfigError::Other(e.to_string())),
        Format::Json => {
            serde_json::from_str(&content).map_err(|e| ConfigError::Other(e.to_string()))
        }
    }
}

pub async fn write_config<C>(path: impl AsRef<Path>, config: &C) -> Result<(), ConfigError>
where
    C: Serialize,
{
    let path_ref = path.as_ref();
    let ext = path_ref
        .extension()
        .and_then(|ext| ext.to_str())
        .unwrap_or("json");
    let format = ext_fmt(&ext.to_lowercase());

    let content = match format {
        Format::Yaml => {
            serde_yaml::to_string(config).map_err(|e| ConfigError::Other(e.to_string()))?
        }
        Format::Toml => toml::to_string(config).map_err(|e| ConfigError::Other(e.to_string()))?,
        Format::Json => {
            serde_json::to_string_pretty(config).map_err(|e| ConfigError::Other(e.to_string()))?
        }
    };

    std::fs::write(path_ref, content).map_err(ConfigError::ConfigWriteFailed)
}

enum Format {
    Yaml,
    Toml,
    Json,
}

fn ext_fmt(ext: &str) -> Format {
    match ext {
        "yaml" | "yml" => Format::Yaml,
        "toml" | "tml" => Format::Toml,
        "json" => Format::Json,
        _ => Format::Json,
    }
}