1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
//! Builder is a struct to build a key/value mapping based on a list
//! of "k=v" pairs, where the value might come from stdin, a file, etc.
use std::{
fs,
io::{self, Read},
};
use serde_json::{Map, Value};
pub trait KvPairParse {
fn to_map(&self) -> Map<String, Value>;
}
impl KvPairParse for Vec<String> {
fn to_map(&self) -> Map<String, Value> {
let mut map = Map::new();
for entry in self {
if let Some((key, value)) = entry.split_once('=') {
let key = key.trim().to_string();
let value = value.trim();
let parsed_value = if value.starts_with('@') {
// Read from file
let file_path = value.strip_prefix('@').unwrap();
match fs::read_to_string(file_path) {
Ok(content) => Value::String(content),
Err(err) => {
eprintln!("Error reading file '{file_path}': {err}");
Value::Null
}
}
} else if value.starts_with('-') {
// Read from stdin
let mut stdin_content = String::new();
match io::stdin().read_to_string(&mut stdin_content) {
Ok(_) => Value::String(stdin_content),
Err(err) => {
eprintln!("Error reading from stdin: {err}");
Value::Null
}
}
} else {
// Direct value
Value::String(value.to_string())
};
map.insert(key, parsed_value);
} else {
eprintln!("Invalid key=value format: '{entry}'");
}
}
map
}
}
impl KvPairParse for &Vec<String> {
fn to_map(&self) -> Map<String, Value> {
// Leverage the implementation for Vec<String>
(*self).to_map()
}
}