Skip to content

Commit 4fbf3c2

Browse files
authored
Merge pull request #8 from ChrisRega/feature/0.6.0-better-error-handling
Feature/0.6.0 better error handling
2 parents 53db14c + 2b24ba6 commit 4fbf3c2

File tree

6 files changed

+186
-54
lines changed

6 files changed

+186
-54
lines changed

.github/workflows/coverage.yml

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
name: coverage instrument based
2+
3+
on: [ push, pull_request ]
4+
5+
jobs:
6+
build:
7+
8+
runs-on: ubuntu-latest
9+
10+
steps:
11+
- uses: actions/checkout@v2
12+
- name: Install latest nightly
13+
uses: actions-rs/toolchain@v1
14+
with:
15+
toolchain: nightly
16+
override: true
17+
components: rustfmt, clippy, llvm-tools-preview
18+
19+
- name: Install lcov
20+
run: sudo apt-get install lcov
21+
22+
- name: install grcov
23+
run: cargo install grcov
24+
25+
- uses: actions/checkout@v2
26+
with:
27+
fetch-depth: 0
28+
29+
- name: Run grcov
30+
env:
31+
PROJECT_NAME: "json-diff"
32+
RUSTDOCFLAGS: "-Cinstrument-coverage -Ccodegen-units=1 -Copt-level=0 -Clink-dead-code -Coverflow-checks=off -Zpanic_abort_tests -Cpanic=abort"
33+
RUSTFLAGS: "-Cinstrument-coverage -Ccodegen-units=1 -Copt-level=0 -Clink-dead-code -Coverflow-checks=off -Zpanic_abort_tests -Cpanic=abort"
34+
CARGO_INCREMENTAL: 0
35+
run: |
36+
cargo +nightly build --verbose
37+
cargo +nightly test --verbose
38+
grcov . -s . --binary-path ./target/debug/ -t lcov --llvm --branch --ignore-not-existing --ignore="/*" --ignore="target/*" --ignore="tests/*" -o lcov.info
39+
40+
- name: Push grcov results to Coveralls via GitHub Action
41+
uses: coverallsapp/[email protected]
42+
with:
43+
github-token: ${{ secrets.GITHUB_TOKEN }}
44+
path-to-lcov: "lcov.info"

README.md

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@
33
[![Crates.io](https://img.shields.io/crates/d/json_diff_ng?style=flat)](https://crates.io/crates/json_diff_ng)
44
[![Documentation](https://docs.rs/json_diff_ng/badge.svg)](https://docs.rs/json_diff_ng)
55
![CI](https://github.com/ChrisRega/json-diff/actions/workflows/rust.yml/badge.svg?branch=master "CI")
6-
[![License](https://img.shields.io/badge/license-MIT-blue?style=flat)](LICENSE)
6+
[![Coverage Status](https://coveralls.io/repos/github/ChrisRega/json-diff/badge.svg?branch=master)](https://coveralls.io/github/ChrisRega/json-diff?branch=master)
7+
[![License](https://img.shields.io/github/license/ChrisRega/json-diff)](LICENSE)
78

89
## Contributors:
910

@@ -12,31 +13,34 @@
1213
</a>
1314

1415
## Library
16+
1517
json_diff_ng can be used to get diffs of json-serializable structures in rust.
1618

1719
### Usage example
20+
1821
```rust
1922
use json_diff::compare_strs;
2023
let data1 = r#"["a",{"c": ["d","f"] },"b"]"#;
2124
let data2 = r#"["b",{"c": ["e","d"] },"a"]"#;
22-
let diffs = compare_strs(data1, data2, true, &[]).unwrap();
25+
let diffs = compare_strs(data1, data2, true, & []).unwrap();
2326
assert!(!diffs.is_empty());
2427
let diffs = diffs.unequal_values.get_diffs();
2528
assert_eq!(diffs.len(), 1);
2629
assert_eq!(
27-
diffs.first().unwrap().to_string(),
28-
r#".[0].c.[1].("f" != "e")"#
30+
diffs.first().unwrap().to_string(),
31+
r#".[0].c.[1].("f" != "e")"#
2932
);
3033
```
3134

3235
See [docs.rs](https://docs.rs/json_diff_ng) for more details.
3336

34-
3537
## CLI
36-
json-diff is a command line utility to compare two jsons.
38+
39+
json-diff is a command line utility to compare two jsons.
3740

3841
Input can be fed as inline strings or through files.
39-
For readability, output is neatly differentiated into three categories: keys with different values, and keys not present in either of the objects.
42+
For readability, output is neatly differentiated into three categories: keys with different values, and keys not present
43+
in either of the objects.
4044
Only missing or unequal keys are printed in output to reduce the verbosity.
4145

4246
Usage Example:
@@ -50,5 +54,6 @@ file : read input from json files
5054
direct : read input from command line
5155

5256
### Installation
57+
5358
`$ cargo install json_diff_ng`
5459

src/enums.rs

Lines changed: 39 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
1+
use std::collections::HashMap;
12
use std::fmt::{Display, Formatter};
23

4+
use serde_json::Value;
35
use thiserror::Error;
46
use vg_errortools::FatIOError;
57

@@ -19,10 +21,6 @@ impl From<String> for Error {
1921
}
2022
}
2123

22-
use std::collections::HashMap;
23-
24-
use serde_json::Value;
25-
2624
#[derive(Debug, PartialEq)]
2725
pub enum DiffTreeNode {
2826
Null,
@@ -123,13 +121,23 @@ impl<'a> PathElement<'a> {
123121
}
124122
}
125123

126-
/// A view on a single end-node of the [`DiffKeyNode`] tree.
124+
/// A view on a single end-node of the [`DiffTreeNode`] tree.
127125
#[derive(Clone, Debug, Default, PartialEq, Eq)]
128126
pub struct DiffEntry<'a> {
129127
pub path: Vec<PathElement<'a>>,
130128
pub values: Option<(&'a serde_json::Value, &'a serde_json::Value)>,
131129
}
132130

131+
impl<'a> DiffEntry<'a> {
132+
pub fn resolve<'b>(&'a self, value: &'b serde_json::Value) -> Option<&'b serde_json::Value> {
133+
let mut return_value = value;
134+
for a in &self.path {
135+
return_value = a.resolve(return_value)?;
136+
}
137+
Some(return_value)
138+
}
139+
}
140+
133141
impl Display for DiffEntry<'_> {
134142
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
135143
for element in &self.path {
@@ -158,3 +166,29 @@ impl Display for PathElement<'_> {
158166
}
159167
}
160168
}
169+
170+
#[cfg(test)]
171+
mod test {
172+
use serde_json::json;
173+
174+
use crate::compare_serde_values;
175+
use crate::sort::sort_value;
176+
177+
#[test]
178+
fn test_resolve() {
179+
let data1 = json! {["a",{"c": ["d","f"] },"b"]};
180+
let data2 = json! {["b",{"c": ["e","d"] },"a"]};
181+
let diffs = compare_serde_values(&data1, &data2, true, &[]).unwrap();
182+
assert!(!diffs.is_empty());
183+
let data1_sorted = sort_value(&data1, &[]);
184+
let data2_sorted = sort_value(&data2, &[]);
185+
186+
let all_diffs = diffs.all_diffs();
187+
assert_eq!(all_diffs.len(), 1);
188+
let (_type, diff) = all_diffs.first().unwrap();
189+
let val = diff.resolve(&data1_sorted);
190+
assert_eq!(val.unwrap().as_str().unwrap(), "f");
191+
let val = diff.resolve(&data2_sorted);
192+
assert_eq!(val.unwrap().as_str().unwrap(), "e");
193+
}
194+
}

src/lib.rs

Lines changed: 41 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,17 +23,54 @@
2323
//! a flat list of [`DiffEntry`] which is more easily usable. The path in the json is collapsed into a vector of [`PathElement`] which can be used to follow the diff.
2424
//! Similarly, all diffs after an operation can be collected using [`Mismatch::all_diffs`].
2525
//!
26+
//! ### Just print everything
27+
//!
28+
//! ```rust
29+
//! use serde_json::json;
30+
//! use json_diff_ng::compare_serde_values;
31+
//! use json_diff_ng::sort::sort_value;
32+
//! let data1 = json! {["a",{"c": ["d","f"] },"b"]};
33+
//! let data2 = json! {["b",{"c": ["e","d"] },"a"]};
34+
//! let diffs = compare_serde_values(&data1, &data2, true, &[]).unwrap();
35+
//! for (d_type, d_path) in diffs.all_diffs() {
36+
//! let _message = format!("{d_type}: {d_path}");
37+
//! }
38+
//! ```
39+
//!
40+
//! ### Traversing the diff result JSONs
41+
//! ```rust
42+
//! use serde_json::json;
43+
//! use json_diff_ng::compare_serde_values;
44+
//! use json_diff_ng::sort::sort_value;
45+
//! let data1 = json! {["a",{"c": ["d","f"] },"b"]};
46+
//! let data2 = json! {["b",{"c": ["e","d"] },"a"]};
47+
//! let diffs = compare_serde_values(&data1, &data2, true, &[]).unwrap();
48+
//! assert!(!diffs.is_empty());
49+
//! // since we sorted for comparison, if we want to resolve the path, we need a sorted result as well.
50+
//! let data1_sorted = sort_value(&data1, &[]);
51+
//! let data2_sorted = sort_value(&data2, &[]);
52+
//! let all_diffs = diffs.all_diffs();
53+
//! assert_eq!(all_diffs.len(), 1);
54+
//! let (_type, diff) = all_diffs.first().unwrap();
55+
//! let val = diff.resolve(&data1_sorted);
56+
//! assert_eq!(val.unwrap().as_str().unwrap(), "f");
57+
//! let val = diff.resolve(&data2_sorted);
58+
//! assert_eq!(val.unwrap().as_str().unwrap(), "e");
59+
//! ```
2660
//!
2761
28-
pub mod enums;
29-
pub mod mismatch;
30-
pub mod process;
31-
pub mod sort;
3262
pub use enums::DiffEntry;
3363
pub use enums::DiffTreeNode;
3464
pub use enums::DiffType;
3565
pub use enums::Error;
66+
pub use enums::PathElement;
3667
pub use mismatch::Mismatch;
3768
pub use process::compare_serde_values;
3869
pub use process::compare_strs;
70+
71+
pub mod enums;
72+
pub mod mismatch;
73+
pub mod process;
74+
pub mod sort;
75+
3976
pub type Result<T> = std::result::Result<T, Error>;

0 commit comments

Comments
 (0)