osmgraphing/multi_ch_constructor/
configs.rs

1use crate::{helpers::err, io::SupportingFileExts, multi_ch_constructor::defaults};
2use serde::Deserialize;
3use std::{
4    fs::OpenOptions,
5    path::{Path, PathBuf},
6};
7
8#[derive(Clone, Debug, Deserialize)]
9#[serde(from = "ProtoConfig")]
10pub struct Config {
11    pub fmi_graph: PathBuf,
12    pub ch_fmi_graph: PathBuf,
13    pub contraction_ratio: String,
14    pub dim: usize,
15    pub cost_accuracy: f64,
16    pub num_threads: usize,
17    pub is_printing_osm_ids: bool,
18    pub is_using_external_edge_ids: bool,
19}
20
21impl SupportingFileExts for Config {
22    fn supported_exts<'a>() -> &'a [&'a str] {
23        &["yaml"]
24    }
25}
26
27impl Config {
28    pub fn try_from_str(yaml_str: &str) -> err::Result<Config> {
29        let proto_cfg: ProtoConfig = {
30            match serde_yaml::from_str(yaml_str) {
31                Ok(proto_cfg) => proto_cfg,
32                Err(e) => {
33                    return Err(err::Msg::from(format!(
34                        "Serde couldn't read yaml-str due to error: {}",
35                        e
36                    )))
37                }
38            }
39        };
40        Ok(Config::from(proto_cfg))
41    }
42
43    pub fn from_str(yaml_str: &str) -> Config {
44        match Config::try_from_str(yaml_str) {
45            Ok(cfg) => cfg,
46            Err(msg) => panic!("{}", msg),
47        }
48    }
49
50    pub fn try_from_yaml<P: AsRef<Path> + ?Sized>(path: &P) -> err::Result<Config> {
51        let path = path.as_ref();
52        let file = {
53            Config::find_supported_ext(path)?;
54            match OpenOptions::new().read(true).open(path) {
55                Ok(file) => file,
56                Err(e) => {
57                    return Err(err::Msg::from(format!(
58                        "Couldn't open {} due to error: {}",
59                        path.display(),
60                        e
61                    )))
62                }
63            }
64        };
65
66        let proto_cfg: ProtoConfig = match serde_yaml::from_reader(file) {
67            Ok(proto_cfg) => proto_cfg,
68            Err(e) => {
69                return Err(err::Msg::from(format!(
70                    "Serde couldn't read {} due to error: {}",
71                    path.display(),
72                    e
73                )))
74            }
75        };
76        Ok(Config::from(proto_cfg))
77    }
78
79    pub fn from_yaml<P: AsRef<Path> + ?Sized>(path: &P) -> Config {
80        match Config::try_from_yaml(path) {
81            Ok(cfg) => cfg,
82            Err(msg) => panic!("{}", msg),
83        }
84    }
85}
86
87impl From<ProtoConfig> for Config {
88    fn from(proto_cfg: ProtoConfig) -> Config {
89        Config {
90            fmi_graph: proto_cfg.fmi_graph,
91            ch_fmi_graph: proto_cfg.ch_fmi_graph,
92            contraction_ratio: proto_cfg
93                .contraction_ratio
94                .unwrap_or(String::from(defaults::CONTRACTION_RATIO)),
95            dim: proto_cfg.dim,
96            cost_accuracy: proto_cfg.cost_accuracy.unwrap_or(defaults::COST_ACCURACY),
97            num_threads: proto_cfg.num_threads.unwrap_or(defaults::NUM_THREADS),
98            is_printing_osm_ids: proto_cfg.is_printing_osm_ids,
99            is_using_external_edge_ids: proto_cfg.is_using_external_edge_ids,
100        }
101    }
102}
103
104/// Don't deny unknown fields to allow multiple configs in one yaml-file.
105#[derive(Debug, Deserialize)]
106#[serde(try_from = "RawConfig")]
107pub struct ProtoConfig {
108    pub fmi_graph: PathBuf,
109    pub ch_fmi_graph: PathBuf,
110    pub contraction_ratio: Option<String>,
111    pub dim: usize,
112    pub min_cost: Option<f64>,
113    pub cost_accuracy: Option<f64>,
114    pub num_threads: Option<usize>,
115    pub is_printing_osm_ids: bool,
116    pub is_using_external_edge_ids: bool,
117}
118
119impl From<RawConfig> for ProtoConfig {
120    fn from(raw_cfg: RawConfig) -> ProtoConfig {
121        let raw_cfg = raw_cfg.multi_ch_constructor;
122
123        ProtoConfig {
124            fmi_graph: raw_cfg.fmi_graph,
125            ch_fmi_graph: raw_cfg.ch_fmi_graph,
126            contraction_ratio: raw_cfg.contraction_ratio,
127            dim: raw_cfg.dim,
128            min_cost: raw_cfg.min_cost,
129            cost_accuracy: raw_cfg.cost_accuracy,
130            num_threads: raw_cfg.num_threads,
131            is_printing_osm_ids: raw_cfg.is_printing_osm_ids,
132            is_using_external_edge_ids: raw_cfg.is_using_external_edge_ids,
133        }
134    }
135}
136
137/// Don't deny unknown fields to allow multiple configs in one yaml-file.
138#[derive(Debug, Deserialize)]
139pub struct RawConfig {
140    #[serde(rename = "multi-ch-constructor")]
141    pub multi_ch_constructor: RawContent,
142}
143
144#[derive(Debug, Deserialize)]
145#[serde(deny_unknown_fields)]
146pub struct RawContent {
147    #[serde(rename = "fmi-graph")]
148    pub fmi_graph: PathBuf,
149    #[serde(rename = "contracted-graph")]
150    pub ch_fmi_graph: PathBuf,
151    #[serde(rename = "dimension")]
152    pub dim: usize,
153    #[serde(rename = "minimum-cost")]
154    pub min_cost: Option<f64>,
155    #[serde(rename = "cost-accuracy")]
156    pub cost_accuracy: Option<f64>,
157    #[serde(rename = "contraction-ratio")]
158    pub contraction_ratio: Option<String>,
159    #[serde(rename = "number_of_threads")]
160    pub num_threads: Option<usize>,
161    #[serde(rename = "is_printing_osm-ids")]
162    pub is_printing_osm_ids: bool,
163    #[serde(rename = "is_using_external_edge-ids")]
164    pub is_using_external_edge_ids: bool,
165}