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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
use std::fmt;
use std::io::{self, Error, ErrorKind};
use serde_json::{self, Map, Value};
pub struct Pair {
pub a: Value,
pub b: Value,
}
impl Pair {
fn clean_string(s: &str) -> Result<Value, serde_json::Error> {
let mut result = s.trim().trim_matches('"').to_owned();
result.retain(|c| c != '\\');
serde_json::from_str(&result)
}
pub fn new(s: &str) -> io::Result<Pair> {
let separator = " => ";
let index = s
.find(separator)
.ok_or(Error::new(ErrorKind::InvalidInput, "Wrong input"))?;
let a = Pair::clean_string(&s[..index])?;
let b = Pair::clean_string(&s[index + separator.len()..])?;
Ok(Pair { a, b })
}
}
pub struct Line {
pub diff: char,
pub depth: usize,
pub contents: String,
}
impl fmt::Display for Line {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let diff = match self.diff {
'.' => "".to_owned(),
_ => format!("{} ", self.diff),
};
write!(f, "{}{}{}", " ".repeat(self.depth * 2), diff, self.contents)
}
}
impl Line {
pub fn new(diff: char, contents: String) -> Line {
Line {
diff,
depth: 0,
contents,
}
}
}
pub fn parse_environment(env: &Value) -> Option<Value> {
let mut result: Map<String, Value> = Map::new();
for t in env.as_array()?.iter() {
let map = t.as_object()?;
result.insert(
map.get("name")?.as_str()?.to_owned(),
map.get("value")?.to_owned(),
);
}
return Some(json!(&result));
}
pub fn wrap(lines: Vec<Line>, name: &str) -> Vec<Line> {
let mut result: Vec<Line> = vec![];
if !lines.is_empty() {
result.push(Line::new('.', format!("{}{{", name)));
for mut line in lines {
line.depth += 1;
result.push(line);
}
result.push(Line::new('.', "}".to_owned()));
}
result
}
pub fn zip_to_end(a: Vec<Value>, b: Vec<Value>) -> Vec<(Option<Value>, Option<Value>)> {
let mut result = Vec::<(Option<Value>, Option<Value>)>::new();
let mut iter_a = a.into_iter();
let mut iter_b = b.into_iter();
loop {
let next_a = iter_a.next();
let next_b = iter_b.next();
if next_a.is_none() && next_b.is_none() {
break;
}
result.push((next_a, next_b));
}
result
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn parse_environment_array() {
let env = json!([
{"name": "foo", "value": "bar"},
{"name": "baz", "value": "qux"},
]);
let result = json!({
"foo": "bar",
"baz": "qux",
});
assert_eq!(parse_environment(&env).unwrap(), result);
}
}