libscilo/config/instantiated_config/
try_from.rs

1//! This module contains [`TryFrom`] implementations for various types into [`InstantiatedConfig`].
2
3use std::{
4    path::{Path, PathBuf},
5    str::FromStr,
6};
7
8use regex::Regex;
9
10use crate::{
11    ConfigError, InstantiatedConfig, LintCheck, RootDirs,
12    config::{file::ConfigFile, parse::parse_config_file},
13};
14
15impl TryFrom<&ConfigFile> for InstantiatedConfig {
16    type Error = ConfigError;
17
18    fn try_from(value: &ConfigFile) -> Result<Self, Self::Error> {
19        // use the defaults if a non-required option is specified in the ConfigFile
20        let defaults = Self::default();
21
22        let root_dirs = RootDirs::from(value.root_dirs.clone());
23
24        // this complicated iteration and mapping will automatically return a `ConfigError`
25        // if there is a typo or other misspecification in the configuration file.
26        let lints = match &value.lints {
27            Some(lint_list) => {
28                // map the string to the enum variant using the `strum` crate
29                // and map a `strum::ParseError` into a `ConfigError` if there is an
30                // error in the string conversion.
31                lint_list
32                    .iter()
33                    .map(|lint_code| {
34                        LintCheck::from_str(lint_code)
35                            .map_err(|_| ConfigError::UnknownLintCode(lint_code.clone()))
36                    })
37                    .collect::<Result<Vec<_>, ConfigError>>()?
38            }
39            None => defaults.lints,
40        };
41
42        let root_files = match &value.root_files {
43            Some(files) => files.iter().map(PathBuf::from).collect(),
44            None => defaults.root_files,
45        };
46
47        // this regex parsing might fail, which means that we need to use a
48        // `TryFrom` instead of a `From`
49        let code_results_subdir_regex = match &value.code_results_subdir_regex {
50            Some(str) => match Regex::new(str) {
51                Ok(re) => Some(re),
52                Err(_) => {
53                    return Err(ConfigError::RegexError {
54                        name: "code_results_subdir_regex".to_string(),
55                        value: str.clone(),
56                    });
57                }
58            },
59            None => defaults.code_results_subdir_regex,
60        };
61
62        let readme_names = match &value.readme_names {
63            Some(val) => Some(val.clone()),
64            None => defaults.readme_names.clone(),
65        };
66
67        let workflow_names = match &value.workflow_names {
68            Some(val) => Some(val.clone()),
69            None => defaults.workflow_names.clone(),
70        };
71
72        let ignored = match &value.ignored {
73            Some(dirs) => dirs.iter().map(PathBuf::from).collect(),
74            None => defaults.ignored
75        };
76
77        Ok(Self {
78            root_dirs,
79            code_results_subdir_regex,
80            lints,
81            root_files,
82            readme_names,
83            workflow_names,
84            ignored,
85        })
86    }
87}
88
89impl TryFrom<ConfigFile> for InstantiatedConfig {
90    type Error = ConfigError;
91
92    fn try_from(value: ConfigFile) -> Result<Self, Self::Error> {
93        Self::try_from(&value)
94    }
95}
96
97impl TryFrom<&Path> for InstantiatedConfig {
98    type Error = ConfigError;
99
100    fn try_from(value: &Path) -> Result<Self, Self::Error> {
101        let cfg_file = parse_config_file(value)?;
102        InstantiatedConfig::try_from(cfg_file)
103    }
104}
105
106impl TryFrom<&PathBuf> for InstantiatedConfig {
107    type Error = ConfigError;
108
109    fn try_from(value: &PathBuf) -> Result<Self, Self::Error> {
110        let cfg_file = parse_config_file(value.as_path())?;
111        InstantiatedConfig::try_from(cfg_file)
112    }
113}
114
115impl TryFrom<PathBuf> for InstantiatedConfig {
116    type Error = ConfigError;
117
118    fn try_from(value: PathBuf) -> Result<Self, Self::Error> {
119        Self::try_from(&value)
120    }
121}