1use std::collections::HashMap;
2
3use anyhow::{Context, Result};
4use camino::{Utf8Path, Utf8PathBuf};
5use serde::Deserialize;
6
7use crate::Root;
8
9#[derive(Deserialize, Default, Debug, Clone, PartialEq, Eq)]
11pub struct ConfigFile {
12 pub stems: HashMap<String, ConfigStem>,
14
15 pub schema_directory: Option<Utf8PathBuf>,
17}
18
19#[derive(Deserialize, Debug, Clone, PartialEq, Eq, Hash)]
20#[serde(try_from = "Utf8PathBuf")]
21struct _Root(Root);
22
23impl TryFrom<Utf8PathBuf> for _Root {
24 type Error = <Root as TryFrom<Utf8PathBuf>>::Error;
25 fn try_from(value: Utf8PathBuf) -> std::result::Result<Self, Self::Error> {
26 Root::try_from(value).map(_Root)
27 }
28}
29
30#[derive(Deserialize, Debug, Clone, PartialEq, Eq)]
32pub struct ConfigStem {
33 root: _Root,
34 schema: Utf8PathBuf,
35}
36
37impl ConfigStem {
38 pub fn root(&self) -> &Root {
40 &self.root.0
41 }
42
43 pub fn schema(&self) -> &Utf8Path {
46 &self.schema
47 }
48}
49
50impl ConfigFile {
51 pub fn load(path: impl AsRef<Utf8Path>) -> Result<Self> {
54 let path = path.as_ref();
55 let config_context = || format!("Reading config file {path:?}");
56 let config_data = std::fs::read_to_string(path).with_context(config_context)?;
57 config_data.as_str().try_into()
58 }
59}
60
61impl TryFrom<&str> for ConfigFile {
62 type Error = anyhow::Error;
63
64 fn try_from(value: &str) -> Result<Self, Self::Error> {
65 Ok(toml::from_str(value)?)
66 }
67}