flams_utils/
settings.rs

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