Skip to content

Commit bce14bc

Browse files
committed
* moved functions from main to lib to use it as a library
* removed a few unwraps in favour of Result inside the lib
1 parent 6d51448 commit bce14bc

File tree

4 files changed

+222
-212
lines changed

4 files changed

+222
-212
lines changed

Cargo.toml

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,19 @@ repository = "https://github.com/ksceriath/json-diff"
1111
keywords = ["cli", "diff", "json"]
1212
categories = ["command-line-utilities"]
1313

14+
[lib]
15+
name = "json_diff"
16+
path = "src/lib.rs"
17+
crate-type = ["lib"]
18+
19+
[[bin]]
20+
name = "json_diff"
21+
path = "src/main.rs"
22+
1423
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
1524

1625
[dependencies]
1726
serde_json = "1.0.41"
1827
maplit = "1.0.2"
1928
colored = "1.9.0"
20-
structopt = "0.3.5"
29+
structopt = "0.3.5"

src/constants.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
use std::fmt;
21
use colored::*;
2+
use std::fmt;
33

44
#[derive(Debug)]
55
pub enum Message {

src/lib.rs

Lines changed: 196 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,196 @@
1+
pub mod constants;
2+
pub mod ds;
3+
mod process;
4+
5+
use colored::*;
6+
use constants::Message;
7+
use ds::{key_node::KeyNode, mismatch::Mismatch};
8+
use std::io::{self, Write};
9+
10+
pub fn compare_jsons(a: &str, b: &str) -> Result<Mismatch, serde_json::Error> {
11+
let value1 = serde_json::from_str(a)?;
12+
let value2 = serde_json::from_str(b)?;
13+
Ok(process::match_json(&value1, &value2))
14+
}
15+
16+
pub fn display_output(result: Mismatch) -> Result<(), std::io::Error> {
17+
let no_mismatch = Mismatch {
18+
left_only_keys: KeyNode::Nil,
19+
right_only_keys: KeyNode::Nil,
20+
keys_in_both: KeyNode::Nil,
21+
};
22+
23+
let stdout = io::stdout();
24+
let mut handle = io::BufWriter::new(stdout.lock());
25+
Ok(if no_mismatch == result {
26+
writeln!(handle, "\n{}", Message::NoMismatch)?;
27+
} else {
28+
match result.keys_in_both {
29+
KeyNode::Node(_) => {
30+
let mut keys = Vec::new();
31+
result.keys_in_both.absolute_keys(&mut keys, None);
32+
writeln!(handle, "\n{}:", Message::Mismatch)?;
33+
for key in keys {
34+
writeln!(handle, "{}", key)?;
35+
}
36+
}
37+
KeyNode::Value(_, _) => writeln!(handle, "{}", Message::RootMismatch)?,
38+
KeyNode::Nil => (),
39+
}
40+
match result.left_only_keys {
41+
KeyNode::Node(_) => {
42+
let mut keys = Vec::new();
43+
result.left_only_keys.absolute_keys(&mut keys, None);
44+
writeln!(handle, "\n{}:", Message::LeftExtra)?;
45+
for key in keys {
46+
writeln!(handle, "{}", key.red().bold())?;
47+
}
48+
}
49+
KeyNode::Value(_, _) => (),
50+
KeyNode::Nil => (),
51+
}
52+
match result.right_only_keys {
53+
KeyNode::Node(_) => {
54+
let mut keys = Vec::new();
55+
result.right_only_keys.absolute_keys(&mut keys, None);
56+
writeln!(handle, "\n{}:", Message::RightExtra)?;
57+
for key in keys {
58+
writeln!(handle, "{}", key.green().bold())?;
59+
}
60+
}
61+
KeyNode::Value(_, _) => (),
62+
KeyNode::Nil => (),
63+
}
64+
})
65+
}
66+
67+
#[cfg(test)]
68+
mod tests {
69+
use super::*;
70+
71+
use maplit::hashmap;
72+
use serde_json::json;
73+
74+
#[test]
75+
fn nested_diff() {
76+
let data1 = r#"{
77+
"a":"b",
78+
"b":{
79+
"c":{
80+
"d":true,
81+
"e":5,
82+
"f":9,
83+
"h":{
84+
"i":true,
85+
"j":false
86+
}
87+
}
88+
}
89+
}"#;
90+
let data2 = r#"{
91+
"a":"b",
92+
"b":{
93+
"c":{
94+
"d":true,
95+
"e":6,
96+
"g":0,
97+
"h":{
98+
"i":false,
99+
"k":false
100+
}
101+
}
102+
}
103+
}"#;
104+
105+
let expected_left = KeyNode::Node(hashmap! {
106+
"b".to_string() => KeyNode::Node(hashmap! {
107+
"c".to_string() => KeyNode::Node(hashmap! {
108+
"f".to_string() => KeyNode::Nil,
109+
"h".to_string() => KeyNode::Node( hashmap! {
110+
"j".to_string() => KeyNode::Nil,
111+
}
112+
),
113+
}
114+
),
115+
}),
116+
});
117+
let expected_right = KeyNode::Node(hashmap! {
118+
"b".to_string() => KeyNode::Node(hashmap! {
119+
"c".to_string() => KeyNode::Node(hashmap! {
120+
"g".to_string() => KeyNode::Nil,
121+
"h".to_string() => KeyNode::Node(hashmap! {
122+
"k".to_string() => KeyNode::Nil,
123+
}
124+
)
125+
}
126+
)
127+
}
128+
)
129+
});
130+
let expected_uneq = KeyNode::Node(hashmap! {
131+
"b".to_string() => KeyNode::Node(hashmap! {
132+
"c".to_string() => KeyNode::Node(hashmap! {
133+
"e".to_string() => KeyNode::Value(json!(5), json!(6)),
134+
"h".to_string() => KeyNode::Node(hashmap! {
135+
"i".to_string() => KeyNode::Value(json!(true), json!(false)),
136+
}
137+
)
138+
}
139+
)
140+
}
141+
)
142+
});
143+
let expected = Mismatch::new(expected_left, expected_right, expected_uneq);
144+
145+
let mismatch = compare_jsons(data1, data2).unwrap();
146+
assert_eq!(mismatch, expected, "Diff was incorrect.");
147+
}
148+
149+
#[test]
150+
fn no_diff() {
151+
let data1 = r#"{
152+
"a":"b",
153+
"b":{
154+
"c":{
155+
"d":true,
156+
"e":5,
157+
"f":9,
158+
"h":{
159+
"i":true,
160+
"j":false
161+
}
162+
}
163+
}
164+
}"#;
165+
let data2 = r#"{
166+
"a":"b",
167+
"b":{
168+
"c":{
169+
"d":true,
170+
"e":5,
171+
"f":9,
172+
"h":{
173+
"i":true,
174+
"j":false
175+
}
176+
}
177+
}
178+
}"#;
179+
180+
assert_eq!(
181+
compare_jsons(data1, data2).unwrap(),
182+
Mismatch::new(KeyNode::Nil, KeyNode::Nil, KeyNode::Nil)
183+
);
184+
}
185+
186+
#[test]
187+
fn no_json() {
188+
let data1 = r#"{}"#;
189+
let data2 = r#"{}"#;
190+
191+
assert_eq!(
192+
compare_jsons(data1, data2).unwrap(),
193+
Mismatch::new(KeyNode::Nil, KeyNode::Nil, KeyNode::Nil)
194+
);
195+
}
196+
}

0 commit comments

Comments
 (0)