@@ -101,20 +101,16 @@ pub fn diff(old_document: &Document, new_document: &Document) -> VecDeque<Patch>
101
101
// Both nodes are elements, compare their tag and attributes for equality, then append their children to the stack
102
102
( Node :: Element ( ref old) , Node :: Element ( ref new) ) => {
103
103
// If the names are different, replace the old element with the new
104
- if old. namespace != new. namespace || old . tag != new . tag {
104
+ if old. name != new. name {
105
105
patches. push_back ( Patch :: Replace {
106
106
node : old_cursor. node ,
107
- replacement : Node :: Element ( Element {
108
- namespace : new. namespace ,
109
- tag : new. tag ,
110
- attributes : old. attributes ,
111
- } ) ,
107
+ replacement : Node :: Element ( new. clone ( ) ) ,
112
108
} ) ;
109
+ } else {
110
+ // Check for changes to the attributes
111
+ let mut attr_changes = diff_attributes ( old_cursor. node , old, new) ;
112
+ patches. append ( & mut attr_changes) ;
113
113
}
114
- // Check for changes to the attributes
115
- let mut attr_changes =
116
- diff_attributes ( old_cursor. node , old, new, old_document, new_document) ;
117
- patches. append ( & mut attr_changes) ;
118
114
// Add the children of both nodes to the worklist
119
115
let depth = old_cursor. depth + 1 ;
120
116
let parent = old_cursor. child ;
@@ -159,23 +155,10 @@ pub fn diff(old_document: &Document, new_document: &Document) -> VecDeque<Patch>
159
155
// The old node was a leaf and the new node is an element; determine if this is a simple swap, addition, or removal
160
156
// by looking forward in the stack to future cursors which are at the same depth.
161
157
( Node :: Leaf ( _) , Node :: Element ( ref new) ) => {
162
- let replacement = Element {
163
- namespace : new. namespace ,
164
- tag : new. tag ,
165
- attributes : AttributeList :: new ( ) ,
166
- } ;
167
- let mut attr_changes = diff_attributes (
168
- old_cursor. node ,
169
- & replacement,
170
- new,
171
- old_document,
172
- new_document,
173
- ) ;
174
158
patches. push_back ( Patch :: Replace {
175
159
node : old_cursor. node ,
176
- replacement : Node :: Element ( replacement ) ,
160
+ replacement : Node :: Element ( new . clone ( ) ) ,
177
161
} ) ;
178
- patches. append ( & mut attr_changes) ;
179
162
let depth = old_cursor. depth + 1 ;
180
163
let parent = old_cursor. child ;
181
164
let new_children = new_document. children ( new_cursor. node ) ;
@@ -407,99 +390,58 @@ pub fn diff(old_document: &Document, new_document: &Document) -> VecDeque<Patch>
407
390
patches
408
391
}
409
392
410
- fn diff_attributes (
411
- node : NodeRef ,
412
- old : & Element ,
413
- new : & Element ,
414
- old_document : & Document ,
415
- new_document : & Document ,
416
- ) -> VecDeque < Patch > {
417
- use std:: collections:: hash_map:: Entry ;
418
-
393
+ fn diff_attributes ( node : NodeRef , old : & Element , new : & Element ) -> VecDeque < Patch > {
419
394
let mut patches = VecDeque :: new ( ) ;
395
+
420
396
let mut old_attribute_names = FxHashSet :: default ( ) ;
421
397
let mut new_attribute_names = FxHashSet :: default ( ) ;
422
398
let mut old_attributes = FxHashMap :: default ( ) ;
423
399
let mut new_attributes = FxHashMap :: default ( ) ;
424
400
425
- let old_attrs = old. attributes ( & old_document . attribute_lists ) ;
426
- let new_attrs = new. attributes ( & new_document . attribute_lists ) ;
401
+ let old_attrs = old. attributes ( ) ;
402
+ let new_attrs = new. attributes ( ) ;
427
403
428
- for oattr in old_attrs {
429
- let old_attr = & old_document. attrs [ * oattr] ;
430
- old_attribute_names. insert ( ( old_attr. namespace , old_attr. name ) ) ;
431
- match old_attributes. entry ( ( old_attr. namespace , old_attr. name ) ) {
432
- Entry :: Vacant ( entry) => {
433
- entry. insert ( vec ! [ ( * oattr, & old_attr. value) ] ) ;
434
- }
435
- Entry :: Occupied ( mut entry) => {
436
- let values = entry. get_mut ( ) ;
437
- if values. iter ( ) . copied ( ) . any ( |( _, v) | v == & old_attr. value ) {
438
- continue ;
439
- }
440
- values. push ( ( * oattr, & old_attr. value ) ) ;
441
- }
442
- }
404
+ for attr in old_attrs {
405
+ old_attribute_names. insert ( attr. name ) ;
406
+ old_attributes. insert ( attr. name , & attr. value ) ;
443
407
}
444
408
445
- for nattr in new_attrs {
446
- let new_attr = & new_document. attrs [ * nattr] ;
447
- new_attribute_names. insert ( ( new_attr. namespace , new_attr. name ) ) ;
448
- match new_attributes. entry ( ( new_attr. namespace , new_attr. name ) ) {
449
- Entry :: Vacant ( entry) => {
450
- entry. insert ( vec ! [ ( * nattr, & new_attr. value) ] ) ;
451
- }
452
- Entry :: Occupied ( mut entry) => {
453
- let values = entry. get_mut ( ) ;
454
- if values. iter ( ) . copied ( ) . any ( |( _, v) | v == & new_attr. value ) {
455
- continue ;
456
- }
457
- values. push ( ( * nattr, & new_attr. value ) ) ;
458
- }
459
- }
409
+ for attr in new_attrs {
410
+ new_attribute_names. insert ( attr. name ) ;
411
+ new_attributes. insert ( attr. name , & attr. value ) ;
460
412
}
461
413
462
414
// Additions (in new, not in old)
463
415
for diff in new_attribute_names. difference ( & old_attribute_names) {
464
416
// Issue patch to add this attribute to the old
465
- patches. extend ( new_attributes[ & diff] . iter ( ) . copied ( ) . map ( |( _, value) | {
466
- Patch :: AddAttributeTo {
467
- node,
468
- attr : Attribute {
469
- namespace : diff. 0 ,
470
- name : diff. 1 ,
471
- value : value. clone ( ) ,
472
- } ,
473
- }
474
- } ) ) ;
417
+ let value = new_attributes[ & diff] ;
418
+ patches. push_back ( Patch :: AddAttributeTo {
419
+ node,
420
+ name : * diff,
421
+ value : value. clone ( ) ,
422
+ } ) ;
475
423
}
476
424
477
425
// Removals (in old, not in new)
478
426
for diff in old_attribute_names. difference ( & new_attribute_names) {
479
427
// Issue patch to remove this attribute from the old
480
- patches. push_back ( Patch :: RemoveAttributeByName {
481
- node,
482
- namespace : diff. 0 ,
483
- name : diff. 1 ,
484
- } ) ;
428
+ patches. push_back ( Patch :: RemoveAttributeByName { node, name : * diff } ) ;
485
429
}
486
430
487
431
// Modifications (in both)
488
432
for diff in old_attribute_names. intersection ( & new_attribute_names) {
489
- let old_values = & old_attributes[ & diff] ;
490
- let new_values = & new_attributes[ & diff] ;
433
+ let old_value = old_attributes[ & diff] ;
434
+ let new_value = new_attributes[ & diff] ;
491
435
492
- // If no values have changed, we're done
493
- if old_values
494
- . iter ( )
495
- . map ( |( _, v) | v)
496
- . eq ( new_values. iter ( ) . map ( |( _, v) | v) )
497
- {
436
+ if old_value == new_value {
498
437
continue ;
499
438
}
500
439
501
- // Otherwise, for each value change, issue a patch to remove the old value and add the new
502
- todo ! ( )
440
+ patches. push_back ( Patch :: UpdateAttribute {
441
+ node,
442
+ name : * diff,
443
+ value : new_value. clone ( ) ,
444
+ } ) ;
503
445
}
504
446
505
447
patches
@@ -518,20 +460,9 @@ fn recursively_append(src: NodeRef, src_document: &Document) -> VecDeque<Patch>
518
460
node : Node :: Leaf ( s. clone ( ) ) ,
519
461
} ) ,
520
462
Node :: Element ( ref elem) => {
521
- let element = Element {
522
- namespace : elem. namespace ,
523
- tag : elem. tag ,
524
- attributes : AttributeList :: new ( ) ,
525
- } ;
526
463
patches. push_back ( Patch :: CreateAndMoveTo {
527
- node : Node :: Element ( element ) ,
464
+ node : Node :: Element ( elem . clone ( ) ) ,
528
465
} ) ;
529
- for attr in elem. attributes . as_slice ( & src_document. attribute_lists ) {
530
- let attribute = & src_document. attrs [ * attr] ;
531
- patches. push_back ( Patch :: AddAttribute {
532
- attr : attribute. clone ( ) ,
533
- } ) ;
534
- }
535
466
}
536
467
// Ignore the root
537
468
Node :: Root => ( ) ,
0 commit comments