@@ -458,49 +458,54 @@ class MapPatch : public BaseContainerPatch<Patch, MapPatch<Patch>> {
458
458
return (data_.add ().value ()[key], data_.patch ()->operator [](key));
459
459
}
460
460
461
- void apply (T& val) const {
462
- if (applyAssignOrClear (val)) {
463
- return ;
464
- }
465
- applyPatch (val, *data_.patchPrior ());
466
- val.insert (data_.add ()->begin (), data_.add ()->end ());
467
- erase_all (val, *data_.remove ());
468
- for (const auto & entry : *data_.put ()) {
469
- val.insert_or_assign (entry.first , entry.second );
461
+ template <class Visitor >
462
+ void customVisit (Visitor&& v) const {
463
+ if (false ) {
464
+ // Test whether the required methods exist in Visitor
465
+ v.assign (T{});
466
+ v.clear ();
467
+ v.patchIfSet (P{});
468
+ v.add (T{});
469
+ v.put (T{});
470
+ v.remove (std::unordered_set<typename T::key_type>{});
470
471
}
471
- applyPatch (val, *data_.patch ());
472
- }
473
472
474
- // / @copydoc AssignPatch::merge
475
- template <typename U>
476
- void merge (U&& next) {
477
- if (mergeAssignAndClear (std::forward<U>(next))) {
473
+ if (Base::template customVisitAssignAndClear (v)) {
478
474
return ;
479
475
}
480
476
481
- auto nextThrift = std::forward<U>(next).toThrift ();
482
- if (data_.add ()->empty () && data_.put ()->empty () &&
483
- data_.remove ()->empty ()) {
484
- mergePatches (*data_.patchPrior (), *nextThrift.patchPrior ());
485
- } else {
486
- for (auto && kv : *nextThrift.patchPrior ()) {
487
- // Move patches from patchPrior to patchAfter (aka patch) if current map
488
- // patch had given key added/remove/put
489
- patchByKey (kv.first ).merge (kv.second );
477
+ v.patchIfSet (*data_.patchPrior ());
478
+ v.add (*data_.add ());
479
+ v.remove (*data_.remove ());
480
+ v.put (*data_.put ());
481
+ v.patchIfSet (*data_.patch ());
482
+ }
483
+
484
+ void apply (T& val) const {
485
+ struct Visitor {
486
+ T& v;
487
+ void assign (const T& t) { v = t; }
488
+ void clear () { v.clear (); }
489
+ void patchIfSet (const P& kv) {
490
+ for (const auto & p : kv) {
491
+ auto it = v.find (p.first );
492
+ if (it != v.end ()) {
493
+ p.second .apply (it->second );
494
+ }
495
+ }
490
496
}
491
- }
492
- add (*nextThrift.add ());
493
- remove (*nextThrift.remove ());
494
- put (*nextThrift.put ());
495
- mergePatches (*data_.patch (), *nextThrift.patch ());
496
-
497
- // Cleanup keys that were removed in the final patch
498
- for (const auto & key : *data_.remove ()) {
499
- data_.patchPrior ()->erase (key);
500
- if (!isKeyModified (key)) {
501
- data_.patch ()->erase (key);
497
+ void remove (const std::unordered_set<typename T::key_type>& keys) {
498
+ erase_all (v, keys);
502
499
}
503
- }
500
+ void add (const T& t) { v.insert (t.begin (), t.end ()); }
501
+ void put (const T& t) {
502
+ for (const auto & entry : t) {
503
+ v.insert_or_assign (entry.first , entry.second );
504
+ }
505
+ }
506
+ };
507
+
508
+ return customVisit (Visitor{val});
504
509
}
505
510
506
511
private:
@@ -519,9 +524,10 @@ class MapPatch : public BaseContainerPatch<Patch, MapPatch<Patch>> {
519
524
}
520
525
}
521
526
522
- void mergePatches (P& ourPatch, P& otherPatch) {
523
- for (auto && el : otherPatch) {
524
- ourPatch[el.first ].merge (el.second );
527
+ // Needed for merge(...). We can consider making this a public API.
528
+ void patchIfSet (const P& patches) {
529
+ for (auto && ep : patches) {
530
+ patchByKey (ep.first ).merge (ep.second );
525
531
}
526
532
}
527
533
0 commit comments