flams_utils/
settings.rs

1use std::{
2    ops::{Add, AddAssign},
3    path::{Path, PathBuf},
4};
5
6#[derive(Debug, Default, Clone)]
7#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
8pub struct SettingsSpec {
9    #[cfg_attr(feature = "serde", serde(default))]
10    pub mathhubs: Vec<PathBuf>,
11    #[cfg_attr(feature = "serde", serde(default))]
12    pub debug: Option<bool>,
13    #[cfg_attr(feature = "serde", serde(default))]
14    pub server: ServerSettings,
15    #[cfg_attr(feature = "serde", serde(default))]
16    pub log_dir: Option<Box<Path>>,
17    #[cfg_attr(feature = "serde", serde(default))]
18    pub temp_dir: Option<Box<Path>>,
19    #[cfg_attr(feature = "serde", serde(default))]
20    pub buildqueue: BuildQueueSettings,
21    #[cfg_attr(feature = "serde", serde(skip))]
22    pub lsp: bool,
23    #[cfg_attr(feature = "serde", serde(default))]
24    pub database: Option<Box<Path>>,
25    #[cfg_attr(feature = "serde", serde(default))]
26    pub rdf_database: Option<Box<Path>>,
27    #[cfg_attr(feature = "serde", serde(default))]
28    pub gitlab: GitlabSettings,
29    #[cfg_attr(feature = "serde", serde(default))]
30    pub stack_size: Option<u8>,
31}
32impl Add for SettingsSpec {
33    type Output = Self;
34    fn add(self, rhs: Self) -> Self::Output {
35        Self {
36            mathhubs: if self.mathhubs.is_empty() {
37                rhs.mathhubs
38            } else {
39                self.mathhubs
40            }, //self.mathhubs.into_iter().chain(rhs.mathhubs.into_iter()).collect(),
41            debug: self.debug.or(rhs.debug),
42            server: self.server + rhs.server,
43            log_dir: self.log_dir.or(rhs.log_dir),
44            temp_dir: self.temp_dir.or(rhs.temp_dir),
45            database: self.database.or(rhs.database),
46            rdf_database: self.rdf_database.or(rhs.rdf_database),
47            stack_size: self.stack_size.or(rhs.stack_size),
48            buildqueue: self.buildqueue + rhs.buildqueue,
49            gitlab: self.gitlab + rhs.gitlab,
50            lsp: self.lsp || rhs.lsp,
51        }
52    }
53}
54impl AddAssign for SettingsSpec {
55    fn add_assign(&mut self, rhs: Self) {
56        if self.mathhubs.is_empty() {
57            self.mathhubs = rhs.mathhubs;
58        }
59        self.debug = self.debug.or(rhs.debug);
60        self.lsp = self.lsp || rhs.lsp;
61        self.server += rhs.server;
62        if self.log_dir.is_none() {
63            self.log_dir = rhs.log_dir;
64        }
65        if self.stack_size.is_none() {
66            self.stack_size = rhs.stack_size;
67        }
68        if self.temp_dir.is_none() {
69            self.temp_dir = rhs.temp_dir;
70        }
71        if self.database.is_none() {
72            self.database = rhs.database;
73        }
74        if self.rdf_database.is_none() {
75            self.rdf_database = rhs.rdf_database;
76        }
77        self.gitlab += rhs.gitlab;
78        self.buildqueue += rhs.buildqueue;
79    }
80}
81
82impl SettingsSpec {
83    #[allow(clippy::missing_panics_doc)]
84    #[must_use]
85    pub fn from_envs() -> Self {
86        Self {
87            mathhubs: Vec::new(),
88            debug: std::env::var("FLAMS_DEBUG")
89                .ok()
90                .and_then(|s| s.parse().ok()),
91            log_dir: std::env::var("FLAMS_LOG_DIR")
92                .ok()
93                .map(|s| PathBuf::from(s).into_boxed_path()),
94            temp_dir: std::env::var("FLAMS_TEMP_DIR")
95                .ok()
96                .map(|s| PathBuf::from(s).into_boxed_path()),
97            database: std::env::var("FLAMS_DATABASE")
98                .ok()
99                .map(|s| PathBuf::from(s).into_boxed_path()),
100            rdf_database: std::env::var("FLAMS_RDF_DATABASE")
101                .ok()
102                .map(|s| PathBuf::from(s).into_boxed_path()),
103            stack_size: std::env::var("FLAMS_STACK_SIZE").ok().map(|s| {
104                s.parse().expect(
105                    "Could not parse stack size parameter (environment variable FLAMS_STACK_SIZE)",
106                )
107            }),
108            server: ServerSettings {
109                port: std::env::var("FLAMS_PORT")
110                    .ok()
111                    .and_then(|s| s.parse().ok())
112                    .unwrap_or_default(),
113                ip: std::env::var("FLAMS_IP").ok().map(|s| {
114                    s.parse()
115                        .expect("Could not parse IP address (environment variable FLAMS_IP)")
116                }),
117                external_url: std::env::var("FLAMS_EXTERNAL_URL").ok(),
118                admin_pwd: std::env::var("FLAMS_ADMIN_PWD").ok(),
119            },
120            buildqueue: BuildQueueSettings {
121                num_threads: std::env::var("FLAMS_NUM_THREADS")
122                    .ok()
123                    .and_then(|s| s.parse().ok()),
124            },
125            gitlab: GitlabSettings {
126                url: std::env::var("FLAMS_GITLAB_URL").ok().map(|s| {
127                    s.parse()
128                        .expect("Could not parse URL (environment variable FLAMS_GITLAB_URL)")
129                }),
130                token: std::env::var("FLAMS_GITLAB_TOKEN").ok().map(Into::into),
131                app_id: std::env::var("FLAMS_GITLAB_APP_ID").ok().map(Into::into),
132                app_secret: std::env::var("FLAMS_GITLAB_APP_SECRET")
133                    .ok()
134                    .map(Into::into),
135                redirect_url: std::env::var("FLAMS_GITLAB_REDIRECT_URL")
136                    .ok()
137                    .map(Into::into),
138            },
139            lsp: false,
140        }
141    }
142}
143
144#[derive(Debug, Default, Clone)]
145#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
146pub struct ServerSettings {
147    #[cfg_attr(feature = "serde", serde(default))]
148    pub port: u16,
149    #[cfg_attr(feature = "serde", serde(default))]
150    pub ip: Option<std::net::IpAddr>,
151    #[cfg_attr(feature = "serde", serde(default))]
152    pub admin_pwd: Option<String>,
153    #[cfg_attr(feature = "serde", serde(default))]
154    pub external_url: Option<String>,
155}
156impl Add for ServerSettings {
157    type Output = Self;
158    fn add(self, rhs: Self) -> Self::Output {
159        Self {
160            port: if self.port == 0 { rhs.port } else { self.port },
161            ip: self.ip.or(rhs.ip),
162            admin_pwd: self.admin_pwd.or(rhs.admin_pwd),
163            external_url: self.external_url.or(rhs.external_url),
164        }
165    }
166}
167impl AddAssign for ServerSettings {
168    fn add_assign(&mut self, rhs: Self) {
169        if self.port == 0 {
170            self.port = rhs.port;
171        }
172        if self.ip.is_none() {
173            self.ip = rhs.ip;
174        }
175        if self.admin_pwd.is_none() {
176            self.admin_pwd = rhs.admin_pwd;
177        }
178        if self.external_url.is_none() {
179            self.external_url = rhs.external_url;
180        }
181    }
182}
183
184#[derive(Debug, Default, Clone)]
185#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
186pub struct BuildQueueSettings {
187    #[cfg_attr(feature = "serde", serde(default))]
188    pub num_threads: Option<u8>,
189}
190impl Add for BuildQueueSettings {
191    type Output = Self;
192    fn add(self, rhs: Self) -> Self::Output {
193        Self {
194            num_threads: self.num_threads.or(rhs.num_threads),
195        }
196    }
197}
198impl AddAssign for BuildQueueSettings {
199    fn add_assign(&mut self, rhs: Self) {
200        if self.num_threads.is_none() {
201            self.num_threads = rhs.num_threads;
202        }
203    }
204}
205
206#[derive(Debug, Default, Clone)]
207#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
208pub struct GitlabSettings {
209    #[cfg_attr(feature = "serde", serde(default))]
210    pub url: Option<url::Url>,
211    #[cfg_attr(feature = "serde", serde(default))]
212    pub token: Option<Box<str>>,
213    #[cfg_attr(feature = "serde", serde(default))]
214    pub app_id: Option<Box<str>>,
215    #[cfg_attr(feature = "serde", serde(default))]
216    pub app_secret: Option<Box<str>>,
217    #[cfg_attr(feature = "serde", serde(default))]
218    pub redirect_url: Option<Box<str>>,
219}
220
221impl Add for GitlabSettings {
222    type Output = Self;
223    fn add(self, rhs: Self) -> Self::Output {
224        Self {
225            url: self.url.or(rhs.url),
226            token: self.token.or(rhs.token),
227            app_id: self.app_id.or(rhs.app_id),
228            app_secret: self.app_secret.or(rhs.app_secret),
229            redirect_url: self.redirect_url.or(rhs.redirect_url),
230        }
231    }
232}
233impl AddAssign for GitlabSettings {
234    fn add_assign(&mut self, rhs: Self) {
235        if self.url.is_none() {
236            self.url = rhs.url;
237        }
238        if self.token.is_none() {
239            self.token = rhs.token;
240        }
241        if self.app_id.is_none() {
242            self.app_id = rhs.app_id;
243        }
244        if self.app_secret.is_none() {
245            self.app_secret = rhs.app_secret;
246        }
247        if self.redirect_url.is_none() {
248            self.redirect_url = rhs.redirect_url;
249        }
250    }
251}