Skip to content

Commit 9935675

Browse files
committed
add toml parser to configuration file system
1 parent a27277c commit 9935675

File tree

4 files changed

+153
-1
lines changed

4 files changed

+153
-1
lines changed

Cargo.lock

Lines changed: 56 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

application/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ positioned-io = "0.3.5"
8383
rmp-serde = "1.3.1"
8484
accept-header = "0.2.3"
8585
mime = "0.3.17"
86+
toml = { version = "0.9.11", features = ["preserve_order"] }
8687

8788
[target.'cfg(unix)'.dependencies]
8889
users = "0.11.0"

application/src/server/configuration/process/mod.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ mod ini;
99
mod json;
1010
mod plain;
1111
mod properties;
12+
mod toml;
1213
mod xml;
1314
mod yaml;
1415

@@ -27,6 +28,7 @@ pub enum ServerConfigurationFileParser {
2728
Ini,
2829
Json,
2930
Xml,
31+
Toml,
3032
}
3133

3234
#[derive(ToSchema, Deserialize, Clone, Debug)]
@@ -386,6 +388,9 @@ impl ProcessConfiguration {
386388
ServerConfigurationFileParser::File => {
387389
plain::PlainFileParser::process_file(&file_content, config, server).await?
388390
}
391+
ServerConfigurationFileParser::Toml => {
392+
toml::TomlFileParser::process_file(&file_content, config, server).await?
393+
}
389394
};
390395

391396
server
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
use super::ServerConfigurationFile;
2+
use serde::Deserialize;
3+
4+
pub struct TomlFileParser;
5+
6+
#[async_trait::async_trait]
7+
impl super::ProcessConfigurationFileParser for TomlFileParser {
8+
async fn process_file(
9+
content: &str,
10+
config: &ServerConfigurationFile,
11+
server: &crate::server::Server,
12+
) -> Result<Vec<u8>, anyhow::Error> {
13+
tracing::debug!(
14+
server = %server.uuid,
15+
"processing toml file"
16+
);
17+
18+
let mut toml = if content.trim().is_empty() {
19+
toml::Value::Table(toml::map::Map::new())
20+
} else {
21+
toml::from_str(content).unwrap_or_else(|_| toml::Value::Table(toml::map::Map::new()))
22+
};
23+
24+
for replacement in &config.replace {
25+
let value = match &replacement.replace_with {
26+
serde_json::Value::String(_) => {
27+
let resolved = ServerConfigurationFile::replace_all_placeholders(
28+
server,
29+
&replacement.replace_with,
30+
)
31+
.await?;
32+
33+
toml::de::ValueDeserializer::parse(&resolved).map_or_else(
34+
|_| toml::Value::String(resolved.to_string()),
35+
|v| {
36+
toml::Value::deserialize(v)
37+
.unwrap_or_else(|_| toml::Value::String(resolved.to_string()))
38+
},
39+
)
40+
}
41+
other => toml::Value::try_from(other.clone())
42+
.unwrap_or_else(|_| toml::Value::String(other.to_string())),
43+
};
44+
45+
let path: Vec<&str> = replacement.r#match.split('.').collect();
46+
set_nested_value(
47+
&mut toml,
48+
&path,
49+
value,
50+
replacement.insert_new.unwrap_or(true),
51+
replacement.update_existing,
52+
);
53+
}
54+
55+
Ok(toml::to_string_pretty(&toml)?.into_bytes())
56+
}
57+
}
58+
59+
pub fn set_nested_value(
60+
toml: &mut toml::Value,
61+
path: &[&str],
62+
value: toml::Value,
63+
insert_new: bool,
64+
update_existing: bool,
65+
) {
66+
if path.is_empty() {
67+
return;
68+
}
69+
70+
if !toml.is_table() {
71+
*toml = toml::Value::Table(toml::map::Map::new());
72+
}
73+
74+
let map = toml.as_table_mut().unwrap();
75+
76+
if path.len() == 1 {
77+
let key = path[0].to_string();
78+
let exists = map.contains_key(&key);
79+
80+
if (exists && update_existing) || (!exists && insert_new) {
81+
map.insert(key, value);
82+
}
83+
return;
84+
}
85+
86+
let child = map
87+
.entry(path[0].to_string())
88+
.or_insert_with(|| toml::Value::Table(toml::map::Map::new()));
89+
90+
set_nested_value(child, &path[1..], value, insert_new, update_existing);
91+
}

0 commit comments

Comments
 (0)