1use std::{fs, io};
4
5use serde::{Deserialize, Serialize};
6use thiserror::Error;
7use tytanic_utils::result::{io_not_found, ResultEx};
8
9pub const MANIFEST_TOOL_KEY: &str = crate::TOOL_NAME;
11
12pub const CONFIG_SUB_DIRECTORY: &str = crate::TOOL_NAME;
14
15#[derive(Debug, Default, Clone, PartialEq, Eq, Hash, Deserialize, Serialize)]
18#[serde(deny_unknown_fields)]
19#[serde(rename_all = "kebab-case")]
20pub struct SystemConfig {}
21
22impl SystemConfig {
23 pub fn collect_user() -> Result<Option<Self>, Error> {
27 let Some(config_dir) = dirs::config_dir() else {
28 tracing::warn!("couldn't retrieve user config home");
29 return Ok(None);
30 };
31
32 let config = config_dir.join(CONFIG_SUB_DIRECTORY).join("config.toml");
33 let Some(content) = fs::read_to_string(config).ignore(io_not_found)? else {
34 return Ok(None);
35 };
36
37 Ok(toml::from_str(&content)?)
38 }
39}
40
41#[derive(Debug, Clone, PartialEq, Deserialize)]
43#[serde(deny_unknown_fields)]
44#[serde(rename_all = "kebab-case")]
45pub struct ProjectConfig {
46 #[serde(rename = "tests", default = "default_unit_tests_root")]
50 pub unit_tests_root: String,
51
52 #[serde(rename = "default")]
54 pub defaults: ProjectDefaults,
55}
56
57impl Default for ProjectConfig {
58 fn default() -> Self {
59 Self {
60 unit_tests_root: default_unit_tests_root(),
61 defaults: ProjectDefaults::default(),
62 }
63 }
64}
65
66fn default_unit_tests_root() -> String {
67 String::from("tests")
68}
69
70#[derive(Debug, Clone, PartialEq, Deserialize)]
71#[serde(deny_unknown_fields)]
72#[serde(rename_all = "kebab-case")]
73pub struct ProjectDefaults {
74 #[serde(rename = "dir", default = "default_direction")]
76 pub direction: Direction,
77
78 #[serde(default = "default_ppi")]
82 pub ppi: f32,
83
84 #[serde(default = "default_max_delta")]
88 pub max_delta: u8,
89
90 #[serde(default = "default_max_deviations")]
94 pub max_deviations: usize,
95}
96
97impl Default for ProjectDefaults {
98 fn default() -> Self {
99 Self {
100 direction: default_direction(),
101 ppi: default_ppi(),
102 max_delta: default_max_delta(),
103 max_deviations: default_max_deviations(),
104 }
105 }
106}
107
108fn default_direction() -> Direction {
109 Direction::Ltr
110}
111
112fn default_ppi() -> f32 {
113 144.0
114}
115
116fn default_max_delta() -> u8 {
117 1
118}
119
120fn default_max_deviations() -> usize {
121 0
122}
123
124#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash, Deserialize)]
126#[serde(rename_all = "kebab-case")]
127pub enum Direction {
128 #[default]
130 Ltr,
131
132 Rtl,
134}
135
136#[derive(Debug, Error)]
138pub enum Error {
139 #[error("a toml parsing error occurred")]
141 Toml(#[from] toml::de::Error),
142
143 #[error("an io error occurred")]
145 Io(#[from] io::Error),
146}