axl_lib/config/
config_file.rs1use anyhow::Result;
2use serde::{Deserialize, Serialize};
3use std::{
4 fs,
5 path::{Path, PathBuf},
6};
7use tracing::{info, instrument};
8
9#[derive(Serialize, Deserialize, Debug, Clone, Default)]
10pub struct AxlContext {
11 pub config_path: PathBuf,
12 pub config: AxlConfig,
13}
14
15#[derive(Serialize, Deserialize, Debug, Clone, Default, PartialEq, Eq)]
19pub struct AxlConfig {
20 pub general: GeneralConfig,
21}
22
23#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
24pub struct GeneralConfig {
25 #[serde(default = "art_default")]
26 pub show_art: Option<bool>,
27 #[serde(default = "version_default")]
28 pub show_version: bool,
29}
30
31impl Default for GeneralConfig {
32 fn default() -> Self {
33 Self {
34 show_art: art_default(),
35 show_version: version_default(),
36 }
37 }
38}
39
40const fn art_default() -> Option<bool> {
41 None
43}
44
45const fn version_default() -> bool {
46 true
47}
48
49impl AxlConfig {
50 #[instrument(err)]
51 pub fn from_file(config_path: &Path) -> Result<Self> {
52 let config_string = &fs::read_to_string(config_path)?;
53 let mut loaded_config = if !config_string.trim().is_empty() {
54 serde_yaml::from_str(config_string)?
55 } else {
56 let mut config = Self::default();
57 config.general.show_version = true;
58 config
59 };
60
61 let env_show_art = std::env::var("AXL_SHOW_ART").map_or(None, |val| Some(val == "true"));
62 if env_show_art.is_some() {
63 loaded_config.general.show_art = env_show_art;
64 }
65 info!("config: {:#?}", loaded_config);
66 Ok(loaded_config)
67 }
68}
69
70#[cfg(test)]
71mod tests {
72 use anyhow::Result;
73 use assert_fs::{prelude::FileWriteStr, NamedTempFile};
74 use rstest::{fixture, rstest};
75 use similar_asserts::assert_eq;
76
77 use crate::config::config_file::GeneralConfig;
78
79 use super::AxlConfig;
80
81 #[fixture]
82 fn config_file_full() -> NamedTempFile {
83 let file = NamedTempFile::new("config_file_test_1.txt")
85 .expect("test fixture tmp file can be created");
86 file.write_str(
87 "general:
88 show_art: true
89 show_version: false",
90 )
91 .expect("test fixture tmp file can be written to");
92 file
93 }
94
95 #[fixture]
96 fn config_file_empty() -> NamedTempFile {
97 let file = NamedTempFile::new("config_file_test_empty.txt")
99 .expect("test fixture tmp file can be created");
100 file.write_str("")
101 .expect("test fixture tmp file can be written to");
102 file
103 }
104
105 #[rstest]
106 fn should_read_config_from_file(
107 #[from(config_file_full)] config_file: NamedTempFile,
108 ) -> Result<()> {
109 let loaded_config = AxlConfig::from_file(config_file.path())?;
110
111 assert_eq!(
112 loaded_config,
113 AxlConfig {
114 general: GeneralConfig {
115 show_art: Some(true),
116 show_version: false,
117 }
118 }
119 );
120
121 Ok(())
122 }
123
124 #[rstest]
125 fn should_default_empty_config_file(
126 #[from(config_file_empty)] config_file: NamedTempFile,
127 ) -> Result<()> {
128 let loaded_config = AxlConfig::from_file(config_file.path())?;
129
130 assert_eq!(
131 loaded_config,
132 AxlConfig {
133 general: GeneralConfig {
134 show_art: None,
135 show_version: true
136 }
137 }
138 );
139
140 Ok(())
141 }
142}