@@ -4,18 +4,22 @@ use float_cmp::{ApproxEq, F64Margin};
44use serde_json:: Value ;
55use std:: { collections:: HashSet , fmt} ;
66
7- pub ( crate ) fn diff < ' a > ( lhs : & ' a Value , rhs : & ' a Value , config : & ' a Config ) -> Vec < Difference < ' a > > {
7+ pub ( crate ) fn diff < ' a > (
8+ lhs : & ' a Value ,
9+ rhs : & ' a Value ,
10+ config : & ' a Config ,
11+ ) -> Vec < DifferenceRef < ' a > > {
812 let mut acc = vec ! [ ] ;
9- diff_with ( lhs, rhs, config, Path :: Root , & mut acc) ;
13+ diff_with ( lhs, rhs, config, PathRef :: Root , & mut acc) ;
1014 acc
1115}
1216
1317fn diff_with < ' a > (
1418 lhs : & ' a Value ,
1519 rhs : & ' a Value ,
1620 config : & ' a Config ,
17- path : Path < ' a > ,
18- acc : & mut Vec < Difference < ' a > > ,
21+ path : PathRef < ' a > ,
22+ acc : & mut Vec < DifferenceRef < ' a > > ,
1923) {
2024 let mut folder = DiffFolder {
2125 rhs,
@@ -30,16 +34,16 @@ fn diff_with<'a>(
3034#[ derive( Debug ) ]
3135struct DiffFolder < ' a , ' b > {
3236 rhs : & ' a Value ,
33- path : Path < ' a > ,
34- acc : & ' b mut Vec < Difference < ' a > > ,
37+ path : PathRef < ' a > ,
38+ acc : & ' b mut Vec < DifferenceRef < ' a > > ,
3539 config : & ' a Config ,
3640}
3741
3842macro_rules! direct_compare {
3943 ( $name: ident) => {
4044 fn $name( & mut self , lhs: & ' a Value ) {
4145 if self . rhs != lhs {
42- self . acc. push( Difference {
46+ self . acc. push( DifferenceRef {
4347 lhs: Some ( lhs) ,
4448 rhs: Some ( & self . rhs) ,
4549 path: self . path. clone( ) ,
@@ -64,7 +68,7 @@ impl<'a> DiffFolder<'a, '_> {
6468 } ,
6569 } ;
6670 if !is_equal {
67- self . acc . push ( Difference {
71+ self . acc . push ( DifferenceRef {
6872 lhs : Some ( lhs) ,
6973 rhs : Some ( self . rhs ) ,
7074 path : self . path . clone ( ) ,
@@ -101,7 +105,7 @@ impl<'a> DiffFolder<'a, '_> {
101105 let rhs_len = rhs. len ( ) ;
102106
103107 if self . config . compare_mode == CompareMode :: Strict && lhs_len != rhs_len {
104- self . acc . push ( Difference {
108+ self . acc . push ( DifferenceRef {
105109 lhs : Some ( lhs) ,
106110 rhs : Some ( self . rhs ) ,
107111 path : self . path . clone ( ) ,
@@ -124,7 +128,7 @@ impl<'a> DiffFolder<'a, '_> {
124128 . filter ( |lhs_item| diff ( lhs_item, rhs_item, self . config ) . is_empty ( ) )
125129 . count ( ) ;
126130 if lhs_matching_items_count < rhs_item_count {
127- self . acc . push ( Difference {
131+ self . acc . push ( DifferenceRef {
128132 lhs : Some ( lhs) ,
129133 rhs : Some ( self . rhs ) ,
130134 path : self . path . clone ( ) ,
@@ -134,7 +138,7 @@ impl<'a> DiffFolder<'a, '_> {
134138 }
135139 }
136140 } else {
137- self . acc . push ( Difference {
141+ self . acc . push ( DifferenceRef {
138142 lhs : Some ( lhs) ,
139143 rhs : Some ( self . rhs ) ,
140144 path : self . path . clone ( ) ,
@@ -154,12 +158,12 @@ impl<'a> DiffFolder<'a, '_> {
154158 match self . config . compare_mode {
155159 CompareMode :: Inclusive => {
156160 for ( idx, rhs) in rhs. iter ( ) . enumerate ( ) {
157- let path = self . path . append ( Key :: Idx ( idx) ) ;
161+ let path = self . path . append ( KeyRef :: Idx ( idx) ) ;
158162
159163 if let Some ( lhs) = lhs. get ( idx) {
160164 diff_with ( lhs, rhs, self . config , path, self . acc )
161165 } else {
162- self . acc . push ( Difference {
166+ self . acc . push ( DifferenceRef {
163167 lhs : None ,
164168 rhs : Some ( self . rhs ) ,
165169 path,
@@ -175,22 +179,22 @@ impl<'a> DiffFolder<'a, '_> {
175179 . chain ( lhs. indexes ( ) )
176180 . collect :: < HashSet < _ > > ( ) ;
177181 for key in all_keys {
178- let path = self . path . append ( Key :: Idx ( key) ) ;
182+ let path = self . path . append ( KeyRef :: Idx ( key) ) ;
179183
180184 match ( lhs. get ( key) , rhs. get ( key) ) {
181185 ( Some ( lhs) , Some ( rhs) ) => {
182186 diff_with ( lhs, rhs, self . config , path, self . acc ) ;
183187 }
184188 ( None , Some ( rhs) ) => {
185- self . acc . push ( Difference {
189+ self . acc . push ( DifferenceRef {
186190 lhs : None ,
187191 rhs : Some ( rhs) ,
188192 path,
189193 config : self . config . clone ( ) ,
190194 } ) ;
191195 }
192196 ( Some ( lhs) , None ) => {
193- self . acc . push ( Difference {
197+ self . acc . push ( DifferenceRef {
194198 lhs : Some ( lhs) ,
195199 rhs : None ,
196200 path,
@@ -205,7 +209,7 @@ impl<'a> DiffFolder<'a, '_> {
205209 }
206210 }
207211 } else {
208- self . acc . push ( Difference {
212+ self . acc . push ( DifferenceRef {
209213 lhs : Some ( lhs) ,
210214 rhs : Some ( self . rhs ) ,
211215 path : self . path . clone ( ) ,
@@ -221,12 +225,12 @@ impl<'a> DiffFolder<'a, '_> {
221225 match self . config . compare_mode {
222226 CompareMode :: Inclusive => {
223227 for ( key, rhs) in rhs. iter ( ) {
224- let path = self . path . append ( Key :: Field ( key) ) ;
228+ let path = self . path . append ( KeyRef :: Field ( key) ) ;
225229
226230 if let Some ( lhs) = lhs. get ( key) {
227231 diff_with ( lhs, rhs, self . config , path, self . acc )
228232 } else {
229- self . acc . push ( Difference {
233+ self . acc . push ( DifferenceRef {
230234 lhs : None ,
231235 rhs : Some ( self . rhs ) ,
232236 path,
@@ -238,22 +242,22 @@ impl<'a> DiffFolder<'a, '_> {
238242 CompareMode :: Strict => {
239243 let all_keys = rhs. keys ( ) . chain ( lhs. keys ( ) ) . collect :: < HashSet < _ > > ( ) ;
240244 for key in all_keys {
241- let path = self . path . append ( Key :: Field ( key) ) ;
245+ let path = self . path . append ( KeyRef :: Field ( key) ) ;
242246
243247 match ( lhs. get ( key) , rhs. get ( key) ) {
244248 ( Some ( lhs) , Some ( rhs) ) => {
245249 diff_with ( lhs, rhs, self . config , path, self . acc ) ;
246250 }
247251 ( None , Some ( rhs) ) => {
248- self . acc . push ( Difference {
252+ self . acc . push ( DifferenceRef {
249253 lhs : None ,
250254 rhs : Some ( rhs) ,
251255 path,
252256 config : self . config . clone ( ) ,
253257 } ) ;
254258 }
255259 ( Some ( lhs) , None ) => {
256- self . acc . push ( Difference {
260+ self . acc . push ( DifferenceRef {
257261 lhs : Some ( lhs) ,
258262 rhs : None ,
259263 path,
@@ -268,7 +272,7 @@ impl<'a> DiffFolder<'a, '_> {
268272 }
269273 }
270274 } else {
271- self . acc . push ( Difference {
275+ self . acc . push ( DifferenceRef {
272276 lhs : Some ( lhs) ,
273277 rhs : Some ( self . rhs ) ,
274278 path : self . path . clone ( ) ,
@@ -278,15 +282,35 @@ impl<'a> DiffFolder<'a, '_> {
278282 }
279283}
280284
285+ /// Represents a difference between two JSON values.
286+ #[ derive( Debug , PartialEq , Clone ) ]
287+ pub struct Difference {
288+ path : Path ,
289+ lhs : Option < Value > ,
290+ rhs : Option < Value > ,
291+ config : Config ,
292+ }
293+
294+ impl < ' a > From < DifferenceRef < ' a > > for Difference {
295+ fn from ( diff : DifferenceRef < ' a > ) -> Self {
296+ Difference {
297+ path : Path :: from ( diff. path ) ,
298+ lhs : diff. lhs . cloned ( ) ,
299+ rhs : diff. rhs . cloned ( ) ,
300+ config : diff. config . clone ( ) ,
301+ }
302+ }
303+ }
304+
281305#[ derive( Debug , PartialEq ) ]
282- pub ( crate ) struct Difference < ' a > {
283- path : Path < ' a > ,
306+ pub ( crate ) struct DifferenceRef < ' a > {
307+ path : PathRef < ' a > ,
284308 lhs : Option < & ' a Value > ,
285309 rhs : Option < & ' a Value > ,
286310 config : Config ,
287311}
288312
289- impl fmt:: Display for Difference < ' _ > {
313+ impl fmt:: Display for DifferenceRef < ' _ > {
290314 fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
291315 let json_to_string = |json : & Value | serde_json:: to_string_pretty ( json) . unwrap ( ) ;
292316
@@ -330,30 +354,46 @@ impl fmt::Display for Difference<'_> {
330354 }
331355}
332356
357+ /// Represents a path to a JSON value in a tree structure.
333358#[ derive( Debug , Clone , PartialEq ) ]
334- enum Path < ' a > {
359+ enum Path {
335360 Root ,
336- Keys ( Vec < Key < ' a > > ) ,
361+ Keys ( Vec < Key > ) ,
337362}
338363
339- impl < ' a > Path < ' a > {
340- fn append ( & self , next : Key < ' a > ) -> Path < ' a > {
364+ impl < ' a > From < PathRef < ' a > > for Path {
365+ fn from ( path : PathRef < ' a > ) -> Self {
366+ match path {
367+ PathRef :: Root => Path :: Root ,
368+ PathRef :: Keys ( keys) => Path :: Keys ( keys. into_iter ( ) . map ( Key :: from) . collect ( ) ) ,
369+ }
370+ }
371+ }
372+
373+ #[ derive( Debug , Clone , PartialEq ) ]
374+ enum PathRef < ' a > {
375+ Root ,
376+ Keys ( Vec < KeyRef < ' a > > ) ,
377+ }
378+
379+ impl < ' a > PathRef < ' a > {
380+ fn append ( & self , next : KeyRef < ' a > ) -> PathRef < ' a > {
341381 match self {
342- Path :: Root => Path :: Keys ( vec ! [ next] ) ,
343- Path :: Keys ( list) => {
382+ PathRef :: Root => PathRef :: Keys ( vec ! [ next] ) ,
383+ PathRef :: Keys ( list) => {
344384 let mut copy = list. clone ( ) ;
345385 copy. push ( next) ;
346- Path :: Keys ( copy)
386+ PathRef :: Keys ( copy)
347387 }
348388 }
349389 }
350390}
351391
352- impl fmt:: Display for Path < ' _ > {
392+ impl fmt:: Display for PathRef < ' _ > {
353393 fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
354394 match self {
355- Path :: Root => write ! ( f, "(root)" ) ,
356- Path :: Keys ( keys) => {
395+ PathRef :: Root => write ! ( f, "(root)" ) ,
396+ PathRef :: Keys ( keys) => {
357397 for key in keys {
358398 write ! ( f, "{}" , key) ?;
359399 }
@@ -363,17 +403,33 @@ impl fmt::Display for Path<'_> {
363403 }
364404}
365405
406+ /// Represents a key in a JSON object or an index in a JSON array.
407+ #[ derive( Debug , Clone , PartialEq , Eq ) ]
408+ enum Key {
409+ Idx ( usize ) ,
410+ Field ( String ) ,
411+ }
412+
413+ impl < ' a > From < KeyRef < ' a > > for Key {
414+ fn from ( key : KeyRef < ' a > ) -> Self {
415+ match key {
416+ KeyRef :: Idx ( idx) => Key :: Idx ( idx) ,
417+ KeyRef :: Field ( field) => Key :: Field ( field. to_owned ( ) ) ,
418+ }
419+ }
420+ }
421+
366422#[ derive( Debug , Copy , Clone , PartialEq ) ]
367- enum Key < ' a > {
423+ enum KeyRef < ' a > {
368424 Idx ( usize ) ,
369425 Field ( & ' a str ) ,
370426}
371427
372- impl fmt:: Display for Key < ' _ > {
428+ impl fmt:: Display for KeyRef < ' _ > {
373429 fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
374430 match self {
375- Key :: Idx ( idx) => write ! ( f, "[{}]" , idx) ,
376- Key :: Field ( key) => write ! ( f, ".{}" , key) ,
431+ KeyRef :: Idx ( idx) => write ! ( f, "[{}]" , idx) ,
432+ KeyRef :: Field ( key) => write ! ( f, ".{}" , key) ,
377433 }
378434 }
379435}
0 commit comments