Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-10-02 09:07:06

0001 // Protocol Buffers - Google's data interchange format
0002 // Copyright 2008 Google Inc.  All rights reserved.
0003 //
0004 // Use of this source code is governed by a BSD-style
0005 // license that can be found in the LICENSE file or at
0006 // https://developers.google.com/open-source/licenses/bsd
0007 
0008 // Author: jschorr@google.com (Joseph Schorr)
0009 //  Based on original Protocol Buffers design by
0010 //  Sanjay Ghemawat, Jeff Dean, and others.
0011 //
0012 // This file defines static methods and classes for comparing Protocol
0013 // Messages.
0014 //
0015 // Aug. 2008: Added Unknown Fields Comparison for messages.
0016 // Aug. 2009: Added different options to compare repeated fields.
0017 // Apr. 2010: Moved field comparison to FieldComparator
0018 // Sep. 2020: Added option to output map keys in path
0019 
0020 #ifndef GOOGLE_PROTOBUF_UTIL_MESSAGE_DIFFERENCER_H__
0021 #define GOOGLE_PROTOBUF_UTIL_MESSAGE_DIFFERENCER_H__
0022 
0023 #include <functional>
0024 #include <memory>
0025 #include <string>
0026 #include <vector>
0027 
0028 #include "absl/base/macros.h"
0029 #include "absl/container/fixed_array.h"
0030 #include "absl/container/flat_hash_map.h"
0031 #include "absl/container/flat_hash_set.h"
0032 #include "absl/log/absl_check.h"
0033 #include "google/protobuf/descriptor.h"  // FieldDescriptor
0034 #include "google/protobuf/message.h"     // Message
0035 #include "google/protobuf/text_format.h"
0036 #include "google/protobuf/unknown_field_set.h"
0037 #include "google/protobuf/util/field_comparator.h"
0038 
0039 // Always include as last one, otherwise it can break compilation
0040 #include "google/protobuf/port_def.inc"
0041 
0042 namespace google {
0043 namespace protobuf {
0044 
0045 class DynamicMessageFactory;
0046 class FieldDescriptor;
0047 
0048 namespace io {
0049 class ZeroCopyOutputStream;
0050 class Printer;
0051 }  // namespace io
0052 
0053 namespace util {
0054 
0055 class DefaultFieldComparator;
0056 class FieldContext;  // declared below MessageDifferencer
0057 
0058 // A basic differencer that can be used to determine
0059 // the differences between two specified Protocol Messages. If any differences
0060 // are found, the Compare method will return false, and any differencer reporter
0061 // specified via ReportDifferencesTo will have its reporting methods called (see
0062 // below for implementation of the report). Based off of the original
0063 // ProtocolDifferencer implementation in //net/proto/protocol-differencer.h
0064 // (Thanks Todd!).
0065 //
0066 // MessageDifferencer REQUIRES that compared messages be the same type, defined
0067 // as messages that share the same descriptor.  If not, the behavior of this
0068 // class is undefined.
0069 //
0070 // People disagree on what MessageDifferencer should do when asked to compare
0071 // messages with different descriptors.  Some people think it should always
0072 // return false.  Others expect it to try to look for similar fields and
0073 // compare them anyway -- especially if the descriptors happen to be identical.
0074 // If we chose either of these behaviors, some set of people would find it
0075 // surprising, and could end up writing code expecting the other behavior
0076 // without realizing their error.  Therefore, we forbid that usage.
0077 //
0078 // This class is implemented based on the proto2 reflection. The performance
0079 // should be good enough for normal usages. However, for places where the
0080 // performance is extremely sensitive, there are several alternatives:
0081 // - Comparing serialized string
0082 // Downside: false negatives (there are messages that are the same but their
0083 // serialized strings are different).
0084 // - Equals code generator by compiler plugin (net/proto2/contrib/equals_plugin)
0085 // Downside: more generated code; maintenance overhead for the additional rule
0086 // (must be in sync with the original proto_library).
0087 //
0088 // Note on handling of google.protobuf.Any: MessageDifferencer automatically
0089 // unpacks Any::value into a Message and compares its individual fields.
0090 // Messages encoded in a repeated Any cannot be compared using TreatAsMap.
0091 //
0092 // Note on thread-safety: MessageDifferencer is *not* thread-safe. You need to
0093 // guard it with a lock to use the same MessageDifferencer instance from
0094 // multiple threads. Note that it's fine to call static comparison methods
0095 // (like MessageDifferencer::Equals) concurrently, but it's not recommended for
0096 // performance critical code as it leads to extra allocations.
0097 class PROTOBUF_EXPORT MessageDifferencer {
0098  public:
0099   // Determines whether the supplied messages are equal. Equality is defined as
0100   // all fields within the two messages being set to the same value. Primitive
0101   // fields and strings are compared by value while embedded messages/groups
0102   // are compared as if via a recursive call. Use Compare() with IgnoreField()
0103   // if some fields should be ignored in the comparison. Use Compare() with
0104   // TreatAsSet() if there are repeated fields where ordering does not matter.
0105   //
0106   // This method REQUIRES that the two messages have the same
0107   // Descriptor (message1.GetDescriptor() == message2.GetDescriptor()).
0108   static bool Equals(const Message& message1, const Message& message2);
0109 
0110   // Determines whether the supplied messages are equivalent. Equivalency is
0111   // defined as all fields within the two messages having the same value. This
0112   // differs from the Equals method above in that fields with default values
0113   // are considered set to said value automatically. For details on how default
0114   // values are defined for each field type, see:
0115   // https://developers.google.com/protocol-buffers/docs/proto?csw=1#optional.
0116   // Also, Equivalent() ignores unknown fields. Use IgnoreField() and Compare()
0117   // if some fields should be ignored in the comparison.
0118   //
0119   // This method REQUIRES that the two messages have the same
0120   // Descriptor (message1.GetDescriptor() == message2.GetDescriptor()).
0121   static bool Equivalent(const Message& message1, const Message& message2);
0122 
0123   // Determines whether the supplied messages are approximately equal.
0124   // Approximate equality is defined as all fields within the two messages
0125   // being approximately equal.  Primitive (non-float) fields and strings are
0126   // compared by value, floats are compared using MathUtil::AlmostEquals() and
0127   // embedded messages/groups are compared as if via a recursive call. Use
0128   // IgnoreField() and Compare() if some fields should be ignored in the
0129   // comparison.
0130   //
0131   // This method REQUIRES that the two messages have the same
0132   // Descriptor (message1.GetDescriptor() == message2.GetDescriptor()).
0133   static bool ApproximatelyEquals(const Message& message1,
0134                                   const Message& message2);
0135 
0136   // Determines whether the supplied messages are approximately equivalent.
0137   // Approximate equivalency is defined as all fields within the two messages
0138   // being approximately equivalent. As in
0139   // MessageDifferencer::ApproximatelyEquals, primitive (non-float) fields and
0140   // strings are compared by value, floats are compared using
0141   // MathUtil::AlmostEquals() and embedded messages/groups are compared as if
0142   // via a recursive call. However, fields with default values are considered
0143   // set to said value, as per MessageDiffencer::Equivalent. Use IgnoreField()
0144   // and Compare() if some fields should be ignored in the comparison.
0145   //
0146   // This method REQUIRES that the two messages have the same
0147   // Descriptor (message1.GetDescriptor() == message2.GetDescriptor()).
0148   static bool ApproximatelyEquivalent(const Message& message1,
0149                                       const Message& message2);
0150 
0151   // Identifies an individual field in a message instance.  Used for field_path,
0152   // below.
0153   struct SpecificField {
0154     // The messages that contain this field. They are always set. They are valid
0155     // only during a call to Reporter::Report* methods.
0156     //
0157     // If the original messages are of type google.protobuf.Any, these fields
0158     // will store the unpacked payloads, and unpacked_any will become > 0.  More
0159     // precisely, unpacked_any defines the nesting level of Any.  For example,
0160     // if the original message packs another Any, then unpacked_any=2, assuming
0161     // the differencer unpacked both of them.
0162     //
0163     // When an Any object packs a non-Any proto object whose field includes
0164     // Any, then unpacked_any=1. Thus, in most practical applications,
0165     // unpacked_any will be 0 or 1.
0166     const Message* message1 = nullptr;
0167     const Message* message2 = nullptr;
0168     int unpacked_any = 0;
0169 
0170     // For known fields, "field" is filled in and "unknown_field_number" is -1.
0171     // For unknown fields, "field" is NULL, "unknown_field_number" is the field
0172     // number, and "unknown_field_type" is its type.
0173     const FieldDescriptor* field = nullptr;
0174     int unknown_field_number = -1;
0175     UnknownField::Type unknown_field_type = UnknownField::Type::TYPE_VARINT;
0176 
0177     // If this a repeated field, "index" is the index within it.  For unknown
0178     // fields, this is the index of the field among all unknown fields of the
0179     // same field number and type.
0180     int index = -1;
0181 
0182     // If "field" is a repeated field which is being treated as a map or
0183     // a set (see TreatAsMap() and TreatAsSet(), below), new_index indicates
0184     // the index the position to which the element has moved.  If the element
0185     // has not moved, "new_index" will have the same value as "index".
0186     int new_index = -1;
0187 
0188     // If "field" is a map field, point to the map entry.
0189     const Message* map_entry1 = nullptr;
0190     const Message* map_entry2 = nullptr;
0191 
0192     // For unknown fields, these are the pointers to the UnknownFieldSet
0193     // containing the unknown fields. In certain cases (e.g. proto1's
0194     // MessageSet, or nested groups of unknown fields), these may differ from
0195     // the messages' internal UnknownFieldSets.
0196     const UnknownFieldSet* unknown_field_set1 = nullptr;
0197     const UnknownFieldSet* unknown_field_set2 = nullptr;
0198 
0199     // For unknown fields, these are the index of the field within the
0200     // UnknownFieldSets. One or the other will be -1 when
0201     // reporting an addition or deletion.
0202     int unknown_field_index1 = -1;
0203     int unknown_field_index2 = -1;
0204 
0205     // Was this field added to the diffing because set_force_compare_no_presence
0206     // was called on the MessageDifferencer object.
0207     bool forced_compare_no_presence_ = false;
0208   };
0209 
0210   // Abstract base class from which all MessageDifferencer
0211   // reporters derive. The five Report* methods below will be called when
0212   // a field has been added, deleted, modified, moved, or matched. The third
0213   // argument is a vector of FieldDescriptor pointers which describes the chain
0214   // of fields that was taken to find the current field. For example, for a
0215   // field found in an embedded message, the vector will contain two
0216   // FieldDescriptors. The first will be the field of the embedded message
0217   // itself and the second will be the actual field in the embedded message
0218   // that was added/deleted/modified.
0219   // Fields will be reported in PostTraversalOrder.
0220   // For example, given following proto, if both baz and mooo are changed.
0221   // foo {
0222   //   bar {
0223   //     baz: 1
0224   //     mooo: 2
0225   //   }
0226   // }
0227   // ReportModified will be invoked with following order:
0228   // 1. foo.bar.baz or foo.bar.mooo
0229   // 2. foo.bar.mooo or foo.bar.baz
0230   // 2. foo.bar
0231   // 3. foo
0232   class PROTOBUF_EXPORT Reporter {
0233    public:
0234     Reporter();
0235     Reporter(const Reporter&) = delete;
0236     Reporter& operator=(const Reporter&) = delete;
0237     virtual ~Reporter();
0238 
0239     // Reports that a field has been added into Message2.
0240     virtual void ReportAdded(const Message& message1, const Message& message2,
0241                              const std::vector<SpecificField>& field_path) {}
0242 
0243     // Reports that a field has been deleted from Message1.
0244     virtual void ReportDeleted(const Message& message1, const Message& message2,
0245                                const std::vector<SpecificField>& field_path) {}
0246 
0247     // Reports that the value of a field has been modified.
0248     virtual void ReportModified(const Message& message1,
0249                                 const Message& message2,
0250                                 const std::vector<SpecificField>& field_path) {}
0251 
0252     // Reports that a repeated field has been moved to another location.  This
0253     // only applies when using TreatAsSet or TreatAsMap()  -- see below. Also
0254     // note that for any given field, ReportModified and ReportMoved are
0255     // mutually exclusive. If a field has been both moved and modified, then
0256     // only ReportModified will be called.
0257     virtual void ReportMoved(
0258         const Message& /* message1 */, const Message& /* message2 */,
0259         const std::vector<SpecificField>& /* field_path */) {}
0260 
0261     // Reports that two fields match. Useful for doing side-by-side diffs.
0262     // This function is mutually exclusive with ReportModified and ReportMoved.
0263     // Note that you must call set_report_matches(true) before calling Compare
0264     // to make use of this function.
0265     virtual void ReportMatched(
0266         const Message& /* message1 */, const Message& /* message2 */,
0267         const std::vector<SpecificField>& /* field_path */) {}
0268 
0269     // Reports that two fields would have been compared, but the
0270     // comparison has been skipped because the field was marked as
0271     // 'ignored' using IgnoreField().  This function is mutually
0272     // exclusive with all the other Report() functions.
0273     //
0274     // The contract of ReportIgnored is slightly different than the
0275     // other Report() functions, in that |field_path.back().index| is
0276     // always equal to -1, even if the last field is repeated. This is
0277     // because while the other Report() functions indicate where in a
0278     // repeated field the action (Addition, Deletion, etc...)
0279     // happened, when a repeated field is 'ignored', the differencer
0280     // simply calls ReportIgnored on the repeated field as a whole and
0281     // moves on without looking at its individual elements.
0282     //
0283     // Furthermore, ReportIgnored() does not indicate whether the
0284     // fields were in fact equal or not, as Compare() does not inspect
0285     // these fields at all. It is up to the Reporter to decide whether
0286     // the fields are equal or not (perhaps with a second call to
0287     // Compare()), if it cares.
0288     virtual void ReportIgnored(
0289         const Message& /* message1 */, const Message& /* message2 */,
0290         const std::vector<SpecificField>& /* field_path */) {}
0291 
0292     // Report that an unknown field is ignored. (see comment above).
0293     // Note this is a different function since the last SpecificField in field
0294     // path has a null field.  This could break existing Reporter.
0295     virtual void ReportUnknownFieldIgnored(
0296         const Message& /* message1 */, const Message& /* message2 */,
0297         const std::vector<SpecificField>& /* field_path */) {}
0298   };
0299 
0300   // MapKeyComparator is used to determine if two elements have the same key
0301   // when comparing elements of a repeated field as a map.
0302   class PROTOBUF_EXPORT MapKeyComparator {
0303    public:
0304     MapKeyComparator();
0305     MapKeyComparator(const MapKeyComparator&) = delete;
0306     MapKeyComparator& operator=(const MapKeyComparator&) = delete;
0307     virtual ~MapKeyComparator();
0308 
0309     // This method should be overridden by every implementation.  The arg
0310     // unmapped_any is nonzero the original messages provided by the user are of
0311     // type google.protobuf.Any.
0312     //
0313     // More precisely, unpacked_any defines the nesting level of Any.  For
0314     // example, if Any packs another Any then unpacked_any=2, assuming the
0315     // patcher unpacked both.  Note that when an Any object packs a non-Any
0316     // proto object whose field includes Any, then unpacked_any=1. Thus, in most
0317     // practical applications, unpacked_any will be 0 or 1.
0318     virtual bool IsMatch(const Message& message1, const Message& message2,
0319                          int /* unmapped_any */,
0320                          const std::vector<SpecificField>& fields) const {
0321       ABSL_CHECK(false) << "IsMatch() is not implemented.";
0322       return false;
0323     }
0324   };
0325 
0326   // Abstract base class from which all IgnoreCriteria derive.
0327   // By adding IgnoreCriteria more complex ignore logic can be implemented.
0328   // IgnoreCriteria are registered with AddIgnoreCriteria. For each compared
0329   // field IsIgnored is called on each added IgnoreCriteria until one returns
0330   // true or all return false.
0331   // IsIgnored is called for fields where at least one side has a value.
0332   class PROTOBUF_EXPORT IgnoreCriteria {
0333    public:
0334     IgnoreCriteria();
0335     virtual ~IgnoreCriteria();
0336 
0337     // Returns true if the field should be ignored.
0338     virtual bool IsIgnored(
0339         const Message& /* message1 */, const Message& /* message2 */,
0340         const FieldDescriptor* /* field */,
0341         const std::vector<SpecificField>& /* parent_fields */) = 0;
0342 
0343     // Returns true if the unknown field should be ignored.
0344     // Note: This will be called for unknown fields as well in which case
0345     //       field.field will be null.
0346     virtual bool IsUnknownFieldIgnored(
0347         const Message& /* message1 */, const Message& /* message2 */,
0348         const SpecificField& /* field */,
0349         const std::vector<SpecificField>& /* parent_fields */) {
0350       return false;
0351     }
0352   };
0353 
0354   // To add a Reporter, construct default here, then use ReportDifferencesTo or
0355   // ReportDifferencesToString.
0356   explicit MessageDifferencer();
0357   MessageDifferencer(const MessageDifferencer&) = delete;
0358   MessageDifferencer& operator=(const MessageDifferencer&) = delete;
0359 
0360   ~MessageDifferencer();
0361 
0362   enum MessageFieldComparison {
0363     EQUAL,       // Fields must be present in both messages
0364                  // for the messages to be considered the same.
0365     EQUIVALENT,  // Fields with default values are considered set
0366                  // for comparison purposes even if not explicitly
0367                  // set in the messages themselves.  Unknown fields
0368                  // are ignored.
0369   };
0370 
0371   enum Scope {
0372     FULL,    // All fields of both messages are considered in the comparison.
0373     PARTIAL  // Only fields present in the first message are considered; fields
0374              // set only in the second message will be skipped during
0375              // comparison.
0376   };
0377 
0378   // DEPRECATED. Use FieldComparator::FloatComparison instead.
0379   enum FloatComparison {
0380     EXACT,       // Floats and doubles are compared exactly.
0381     APPROXIMATE  // Floats and doubles are compared using the
0382                  // MathUtil::AlmostEquals method.
0383   };
0384 
0385   enum RepeatedFieldComparison {
0386     AS_LIST,  // Repeated fields are compared in order.  Differing values at
0387               // the same index are reported using ReportModified().  If the
0388               // repeated fields have different numbers of elements, the
0389               // unpaired elements are reported using ReportAdded() or
0390               // ReportDeleted().
0391     AS_SET,   // Treat all the repeated fields as sets.
0392               // See TreatAsSet(), as below.
0393     AS_SMART_LIST,  // Similar to AS_SET, but preserve the order and find the
0394                     // longest matching sequence from the first matching
0395                     // element. To use an optimal solution, call
0396                     // SetMatchIndicesForSmartListCallback() to pass it in.
0397     AS_SMART_SET,   // Similar to AS_SET, but match elements with fewest diffs.
0398   };
0399 
0400   // The elements of the given repeated field will be treated as a set for
0401   // diffing purposes, so different orderings of the same elements will be
0402   // considered equal.  Elements which are present on both sides of the
0403   // comparison but which have changed position will be reported with
0404   // ReportMoved().  Elements which only exist on one side or the other are
0405   // reported with ReportAdded() and ReportDeleted() regardless of their
0406   // positions.  ReportModified() is never used for this repeated field.  If
0407   // the only differences between the compared messages is that some fields
0408   // have been moved, then the comparison returns true.
0409   //
0410   // Note that despite the name of this method, this is really
0411   // comparison as multisets: if one side of the comparison has a duplicate
0412   // in the repeated field but the other side doesn't, this will count as
0413   // a mismatch.
0414   //
0415   // If the scope of comparison is set to PARTIAL, then in addition to what's
0416   // above, extra values added to repeated fields of the second message will
0417   // not cause the comparison to fail.
0418   //
0419   // Note that set comparison is currently O(k * n^2) (where n is the total
0420   // number of elements, and k is the average size of each element). In theory
0421   // it could be made O(n * k) with a more complex hashing implementation. Feel
0422   // free to contribute one if the current implementation is too slow for you.
0423   // If partial matching is also enabled, the time complexity will be O(k * n^2
0424   // + n^3) in which n^3 is the time complexity of the maximum matching
0425   // algorithm.
0426   //
0427   // REQUIRES: field->is_repeated() and field not registered with TreatAsMap*
0428   void TreatAsSet(const FieldDescriptor* field);
0429   void TreatAsSmartSet(const FieldDescriptor* field);
0430 
0431   // The elements of the given repeated field will be treated as a list for
0432   // diffing purposes, so different orderings of the same elements will NOT be
0433   // considered equal.
0434   //
0435   // REQUIRES: field->is_repeated() and field not registered with TreatAsMap*
0436   void TreatAsList(const FieldDescriptor* field);
0437   // Note that the complexity is similar to treating as SET.
0438   void TreatAsSmartList(const FieldDescriptor* field);
0439 
0440   // The elements of the given repeated field will be treated as a map for
0441   // diffing purposes, with |key| being the map key.  Thus, elements with the
0442   // same key will be compared even if they do not appear at the same index.
0443   // Differences are reported similarly to TreatAsSet(), except that
0444   // ReportModified() is used to report elements with the same key but
0445   // different values.  Note that if an element is both moved and modified,
0446   // only ReportModified() will be called.  As with TreatAsSet, if the only
0447   // differences between the compared messages is that some fields have been
0448   // moved, then the comparison returns true. See TreatAsSet for notes on
0449   // performance.
0450   //
0451   // REQUIRES:  field->is_repeated()
0452   // REQUIRES:  field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE
0453   // REQUIRES:  key->containing_type() == field->message_type()
0454   void TreatAsMap(const FieldDescriptor* field, const FieldDescriptor* key);
0455   // Same as TreatAsMap except that this method will use multiple fields as
0456   // the key in comparison. All specified fields in 'key_fields' should be
0457   // present in the compared elements. Two elements will be treated as having
0458   // the same key iff they have the same value for every specified field. There
0459   // are two steps in the comparison process. The first one is key matching.
0460   // Every element from one message will be compared to every element from
0461   // the other message. Only fields in 'key_fields' are compared in this step
0462   // to decide if two elements have the same key. The second step is value
0463   // comparison. Those pairs of elements with the same key (with equal value
0464   // for every field in 'key_fields') will be compared in this step.
0465   // Time complexity of the first step is O(s * m * n ^ 2) where s is the
0466   // average size of the fields specified in 'key_fields', m is the number of
0467   // fields in 'key_fields' and n is the number of elements. If partial
0468   // matching is enabled, an extra O(n^3) will be incured by the maximum
0469   // matching algorithm. The second step is O(k * n) where k is the average
0470   // size of each element.
0471   void TreatAsMapWithMultipleFieldsAsKey(
0472       const FieldDescriptor* field,
0473       const std::vector<const FieldDescriptor*>& key_fields);
0474   // Same as TreatAsMapWithMultipleFieldsAsKey, except that each of the field
0475   // do not necessarily need to be a direct subfield. Each element in
0476   // key_field_paths indicate a path from the message being compared, listing
0477   // successive subfield to reach the key field.
0478   //
0479   // REQUIRES:
0480   //   for key_field_path in key_field_paths:
0481   //     key_field_path[0]->containing_type() == field->message_type()
0482   //     for i in [0, key_field_path.size() - 1):
0483   //       key_field_path[i+1]->containing_type() ==
0484   //           key_field_path[i]->message_type()
0485   //       key_field_path[i]->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE
0486   //       !key_field_path[i]->is_repeated()
0487   void TreatAsMapWithMultipleFieldPathsAsKey(
0488       const FieldDescriptor* field,
0489       const std::vector<std::vector<const FieldDescriptor*> >& key_field_paths);
0490 
0491   // Uses a custom MapKeyComparator to determine if two elements have the same
0492   // key when comparing a repeated field as a map.
0493   // The caller is responsible to delete the key_comparator.
0494   // This method varies from TreatAsMapWithMultipleFieldsAsKey only in the
0495   // first key matching step. Rather than comparing some specified fields, it
0496   // will invoke the IsMatch method of the given 'key_comparator' to decide if
0497   // two elements have the same key.
0498   void TreatAsMapUsingKeyComparator(const FieldDescriptor* field,
0499                                     const MapKeyComparator* key_comparator);
0500 
0501   // Initiates and returns a new instance of MultipleFieldsMapKeyComparator.
0502   MapKeyComparator* CreateMultipleFieldsMapKeyComparator(
0503       const std::vector<std::vector<const FieldDescriptor*> >& key_field_paths);
0504 
0505   // Add a custom ignore criteria that is evaluated in addition to the
0506   // ignored fields added with IgnoreField.
0507 #ifndef PROTOBUF_FUTURE_REMOVE_ADD_IGNORE_CRITERIA
0508   ABSL_DEPRECATE_AND_INLINE()
0509   void AddIgnoreCriteria(IgnoreCriteria* ignore_criteria) {
0510     AddIgnoreCriteria(absl::WrapUnique(ignore_criteria));
0511   }
0512 #endif  // !PROTOBUF_FUTURE_REMOVE_ADD_IGNORE_CRITERIA
0513 
0514   void AddIgnoreCriteria(std::unique_ptr<IgnoreCriteria> ignore_criteria);
0515 
0516   // Indicates that any field with the given descriptor should be
0517   // ignored for the purposes of comparing two messages. This applies
0518   // to fields nested in the message structure as well as top level
0519   // ones. When the MessageDifferencer encounters an ignored field,
0520   // ReportIgnored is called on the reporter, if one is specified.
0521   //
0522   // The only place where the field's 'ignored' status is not applied is when
0523   // it is being used as a key in a field passed to TreatAsMap or is one of
0524   // the fields passed to TreatAsMapWithMultipleFieldsAsKey.
0525   // In this case it is compared in key matching but after that it's ignored
0526   // in value comparison.
0527   void IgnoreField(const FieldDescriptor* field);
0528 
0529   // Sets the field comparator used to determine differences between protocol
0530   // buffer fields. By default it's set to a DefaultFieldComparator instance.
0531   // MessageDifferencer doesn't take ownership over the passed object.
0532   // Note that this method must be called before Compare for the comparator to
0533   // be used.
0534   void set_field_comparator(FieldComparator* comparator);
0535   void set_field_comparator(DefaultFieldComparator* comparator);
0536 
0537   // DEPRECATED. Pass a DefaultFieldComparator instance instead.
0538   // Sets the fraction and margin for the float comparison of a given field.
0539   // Uses MathUtil::WithinFractionOrMargin to compare the values.
0540   // NOTE: this method does nothing if differencer's field comparator has been
0541   //       set to a custom object.
0542   //
0543   // REQUIRES: field->cpp_type == FieldDescriptor::CPPTYPE_DOUBLE or
0544   //           field->cpp_type == FieldDescriptor::CPPTYPE_FLOAT
0545   // REQUIRES: float_comparison_ == APPROXIMATE
0546   void SetFractionAndMargin(const FieldDescriptor* field, double fraction,
0547                             double margin);
0548 
0549   // Sets the type of comparison (as defined in the MessageFieldComparison
0550   // enumeration above) that is used by this differencer when determining how
0551   // to compare fields in messages.
0552   void set_message_field_comparison(MessageFieldComparison comparison);
0553 
0554   // Returns the current message field comparison used in this differencer.
0555   MessageFieldComparison message_field_comparison() const;
0556 
0557   // Tells the differencer whether or not to report matches. This method must
0558   // be called before Compare. The default for a new differencer is false.
0559   void set_report_matches(bool report_matches) {
0560     report_matches_ = report_matches;
0561   }
0562 
0563   // Tells the differencer whether or not to report moves (in a set or map
0564   // repeated field). This method must be called before Compare. The default for
0565   // a new differencer is true.
0566   void set_report_moves(bool report_moves) { report_moves_ = report_moves; }
0567 
0568   // Tells the differencer whether or not to report ignored values. This method
0569   // must be called before Compare. The default for a new differencer is true.
0570   void set_report_ignores(bool report_ignores) {
0571     report_ignores_ = report_ignores;
0572   }
0573 
0574   // Sets the scope of the comparison (as defined in the Scope enumeration
0575   // above) that is used by this differencer when determining which fields to
0576   // compare between the messages.
0577   void set_scope(Scope scope);
0578 
0579   // Returns the current scope used by this differencer.
0580   Scope scope() const;
0581 
0582   // Only affects PARTIAL diffing. When set, all non-repeated no-presence fields
0583   // which are set to their default value (which is the same as being unset) in
0584   // message1 but are set to a non-default value in message2 will also be used
0585   // in the comparison.
0586   void set_force_compare_no_presence(bool value);
0587 
0588   // If set, the fields in message1 that equal the fields passed here will be
0589   // treated as required for comparison, even if they are absent.
0590   void set_require_no_presence_fields(
0591       const google::protobuf::TextFormat::Parser::UnsetFieldsMetadata& fields) {
0592     require_no_presence_fields_ = fields;
0593   }
0594 
0595   // DEPRECATED. Pass a DefaultFieldComparator instance instead.
0596   // Sets the type of comparison (as defined in the FloatComparison enumeration
0597   // above) that is used by this differencer when comparing float (and double)
0598   // fields in messages.
0599   // NOTE: this method does nothing if differencer's field comparator has been
0600   //       set to a custom object.
0601   void set_float_comparison(FloatComparison comparison);
0602 
0603   // Sets the type of comparison for repeated field (as defined in the
0604   // RepeatedFieldComparison enumeration above) that is used by this
0605   // differencer when compare repeated fields in messages.
0606   void set_repeated_field_comparison(RepeatedFieldComparison comparison);
0607 
0608   // Returns the current repeated field comparison used by this differencer.
0609   RepeatedFieldComparison repeated_field_comparison() const;
0610 
0611   // Compares the two specified messages, returning true if they are the same,
0612   // false otherwise. If this method returns false, any changes between the
0613   // two messages will be reported if a Reporter was specified via
0614   // ReportDifferencesTo (see also ReportDifferencesToString).
0615   //
0616   // This method REQUIRES that the two messages have the same
0617   // Descriptor (message1.GetDescriptor() == message2.GetDescriptor()).
0618   bool Compare(const Message& message1, const Message& message2);
0619 
0620   // Same as above, except comparing only the list of fields specified by the
0621   // two vectors of FieldDescriptors.
0622   bool CompareWithFields(
0623       const Message& message1, const Message& message2,
0624       const std::vector<const FieldDescriptor*>& message1_fields,
0625       const std::vector<const FieldDescriptor*>& message2_fields);
0626 
0627   // Automatically creates a reporter that will output the differences
0628   // found (if any) to the specified output string pointer. Note that this
0629   // method must be called before Compare.
0630   void ReportDifferencesToString(std::string* output);
0631 
0632   // Tells the MessageDifferencer to report differences via the specified
0633   // reporter. Note that this method must be called before Compare for
0634   // the reporter to be used. It is the responsibility of the caller to delete
0635   // this object.
0636   // If the provided pointer equals NULL, the MessageDifferencer stops reporting
0637   // differences to any previously set reporters or output strings.
0638   void ReportDifferencesTo(Reporter* reporter);
0639 
0640   // Returns the list of fields which was automatically added to the list of
0641   // compared fields by calling set_force_compare_no_presence and caused the
0642   // last call to Compare to fail.
0643   const absl::flat_hash_set<std::string>& NoPresenceFieldsCausingFailure() {
0644     return force_compare_failure_triggering_fields_;
0645   }
0646 
0647  private:
0648   // Class for processing Any deserialization.  This logic is used by both the
0649   // MessageDifferencer and StreamReporter classes.
0650   class UnpackAnyField {
0651    private:
0652     std::unique_ptr<DynamicMessageFactory> dynamic_message_factory_;
0653 
0654    public:
0655     UnpackAnyField() = default;
0656     ~UnpackAnyField() = default;
0657     // If "any" is of type google.protobuf.Any, extract its payload using
0658     // DynamicMessageFactory and store in "data".
0659     bool UnpackAny(const Message& any, std::unique_ptr<Message>* data);
0660   };
0661 
0662  public:
0663   // An implementation of the MessageDifferencer Reporter that outputs
0664   // any differences found in human-readable form to the supplied
0665   // ZeroCopyOutputStream or Printer. If a printer is used, the delimiter
0666   // *must* be '$'.
0667   //
0668   // WARNING: this reporter does not necessarily flush its output until it is
0669   // destroyed. As a result, it is not safe to assume the output is valid or
0670   // complete until after you destroy the reporter. For example, if you use a
0671   // StreamReporter to write to a StringOutputStream, the target string may
0672   // contain uninitialized data until the reporter is destroyed.
0673   class PROTOBUF_EXPORT StreamReporter : public Reporter {
0674    public:
0675     explicit StreamReporter(io::ZeroCopyOutputStream* output);
0676     explicit StreamReporter(io::Printer* printer);  // delimiter '$'
0677     StreamReporter(const StreamReporter&) = delete;
0678     StreamReporter& operator=(const StreamReporter&) = delete;
0679     ~StreamReporter() override;
0680 
0681     // When set to true, the stream reporter will also output aggregates nodes
0682     // (i.e. messages and groups) whose subfields have been modified. When
0683     // false, will only report the individual subfields. Defaults to false.
0684     void set_report_modified_aggregates(bool report) {
0685       report_modified_aggregates_ = report;
0686     }
0687 
0688     // The following are implementations of the methods described above.
0689 
0690     void ReportAdded(const Message& message1, const Message& message2,
0691                      const std::vector<SpecificField>& field_path) override;
0692 
0693     void ReportDeleted(const Message& message1, const Message& message2,
0694                        const std::vector<SpecificField>& field_path) override;
0695 
0696     void ReportModified(const Message& message1, const Message& message2,
0697                         const std::vector<SpecificField>& field_path) override;
0698 
0699     void ReportMoved(const Message& message1, const Message& message2,
0700                      const std::vector<SpecificField>& field_path) override;
0701 
0702     void ReportMatched(const Message& message1, const Message& message2,
0703                        const std::vector<SpecificField>& field_path) override;
0704 
0705     void ReportIgnored(const Message& message1, const Message& message2,
0706                        const std::vector<SpecificField>& field_path) override;
0707 
0708     void ReportUnknownFieldIgnored(
0709         const Message& message1, const Message& message2,
0710         const std::vector<SpecificField>& field_path) override;
0711 
0712     // Messages that are being compared must be provided to StreamReporter prior
0713     // to processing
0714     void SetMessages(const Message& message1, const Message& message2);
0715 
0716    protected:
0717     // Prints the specified path of fields to the buffer.
0718     virtual void PrintPath(const std::vector<SpecificField>& field_path,
0719                            bool left_side);
0720 
0721     // Prints the value of fields to the buffer.  left_side is true if the
0722     // given message is from the left side of the comparison, false if it
0723     // was the right.  This is relevant only to decide whether to follow
0724     // unknown_field_index1 or unknown_field_index2 when an unknown field
0725     // is encountered in field_path.
0726     virtual void PrintValue(const Message& message,
0727                             const std::vector<SpecificField>& field_path,
0728                             bool left_side);
0729 
0730     // Prints the specified path of unknown fields to the buffer.
0731     virtual void PrintUnknownFieldValue(const UnknownField* unknown_field);
0732 
0733     // Just print a string
0734     void Print(const std::string& str);
0735 
0736    private:
0737     // helper function for PrintPath that contains logic for printing maps
0738     void PrintMapKey(bool left_side, const SpecificField& specific_field);
0739 
0740     io::Printer* printer_;
0741     bool delete_printer_;
0742     bool report_modified_aggregates_;
0743     const Message* message1_;
0744     const Message* message2_;
0745   };
0746 
0747  private:
0748   friend class SimpleFieldComparator;
0749 
0750   // A MapKeyComparator to be used in TreatAsMapUsingKeyComparator.
0751   // Implementation of this class needs to do field value comparison which
0752   // relies on some private methods of MessageDifferencer. That's why this
0753   // class is declared as a nested class of MessageDifferencer.
0754   class MultipleFieldsMapKeyComparator;
0755 
0756   // A MapKeyComparator for use with map_entries.
0757   class PROTOBUF_EXPORT MapEntryKeyComparator : public MapKeyComparator {
0758    public:
0759     explicit MapEntryKeyComparator(MessageDifferencer* message_differencer);
0760     bool IsMatch(
0761         const Message& message1, const Message& message2, int unpacked_any,
0762         const std::vector<SpecificField>& parent_fields) const override;
0763 
0764    private:
0765     MessageDifferencer* message_differencer_;
0766   };
0767 
0768   // Returns true if field1's number() is less than field2's.
0769   static bool FieldBefore(const FieldDescriptor* field1,
0770                           const FieldDescriptor* field2);
0771 
0772   // Retrieve all the set fields, including extensions.
0773   std::vector<const FieldDescriptor*> RetrieveFields(const Message& message,
0774                                                      bool base_message);
0775 
0776   // Combine the two lists of fields into the combined_fields output vector.
0777   // All fields present in both lists will always be included in the combined
0778   // list.  Fields only present in one of the lists will only appear in the
0779   // combined list if the corresponding fields_scope option is set to FULL.
0780   std::vector<const FieldDescriptor*> CombineFields(
0781       const Message& message1,
0782       const std::vector<const FieldDescriptor*>& fields1, Scope fields1_scope,
0783       const std::vector<const FieldDescriptor*>& fields2, Scope fields2_scope);
0784 
0785   // Internal version of the Compare method which performs the actual
0786   // comparison. The parent_fields vector is a vector containing field
0787   // descriptors of all fields accessed to get to this comparison operation
0788   // (i.e. if the current message is an embedded message, the parent_fields
0789   // vector will contain the field that has this embedded message).
0790   bool Compare(const Message& message1, const Message& message2,
0791                int unpacked_any, std::vector<SpecificField>* parent_fields);
0792 
0793   // Compares all the unknown fields in two messages.
0794   bool CompareUnknownFields(const Message& message1, const Message& message2,
0795                             const UnknownFieldSet&, const UnknownFieldSet&,
0796                             std::vector<SpecificField>* parent_fields);
0797 
0798   // Compares the specified messages for the requested field lists. The field
0799   // lists are modified depending on comparison settings, and then passed to
0800   // CompareWithFieldsInternal.
0801   bool CompareRequestedFieldsUsingSettings(
0802       const Message& message1, const Message& message2, int unpacked_any,
0803       const std::vector<const FieldDescriptor*>& message1_fields,
0804       const std::vector<const FieldDescriptor*>& message2_fields,
0805       std::vector<SpecificField>* parent_fields);
0806 
0807   // Compares the specified messages with the specified field lists.
0808   bool CompareWithFieldsInternal(
0809       const Message& message1, const Message& message2, int unpacked_any,
0810       const std::vector<const FieldDescriptor*>& message1_fields,
0811       const std::vector<const FieldDescriptor*>& message2_fields,
0812       std::vector<SpecificField>* parent_fields);
0813 
0814   // Compares the repeated fields, and report the error.
0815   bool CompareRepeatedField(const Message& message1, const Message& message2,
0816                             int unpacked_any, const FieldDescriptor* field,
0817                             std::vector<SpecificField>* parent_fields);
0818 
0819   // Compares map fields, and report the error.
0820   bool CompareMapField(const Message& message1, const Message& message2,
0821                        int unpacked_any, const FieldDescriptor* field,
0822                        std::vector<SpecificField>* parent_fields);
0823 
0824   // Helper for CompareRepeatedField and CompareMapField: compares and reports
0825   // differences element-wise. This is the implementation for non-map fields,
0826   // and can also compare map fields by using the underlying representation.
0827   bool CompareRepeatedRep(const Message& message1, const Message& message2,
0828                           int unpacked_any, const FieldDescriptor* field,
0829                           std::vector<SpecificField>* parent_fields);
0830 
0831   // Helper for CompareMapField: compare the map fields using map reflection
0832   // instead of sync to repeated.
0833   bool CompareMapFieldByMapReflection(const Message& message1,
0834                                       const Message& message2, int unpacked_any,
0835                                       const FieldDescriptor* field,
0836                                       std::vector<SpecificField>* parent_fields,
0837                                       DefaultFieldComparator* comparator);
0838 
0839   // Shorthand for CompareFieldValueUsingParentFields with NULL parent_fields.
0840   bool CompareFieldValue(const Message& message1, const Message& message2,
0841                          int unpacked_any, const FieldDescriptor* field,
0842                          int index1, int index2);
0843 
0844   // Compares the specified field on the two messages, returning
0845   // true if they are the same, false otherwise. For repeated fields,
0846   // this method only compares the value in the specified index. This method
0847   // uses Compare functions to recurse into submessages.
0848   // The parent_fields vector is used in calls to a Reporter instance calls.
0849   // It can be NULL, in which case the MessageDifferencer will create new
0850   // list of parent messages if it needs to recursively compare the given field.
0851   // To avoid confusing users you should not set it to NULL unless you modified
0852   // Reporter to handle the change of parent_fields correctly.
0853   bool CompareFieldValueUsingParentFields(
0854       const Message& message1, const Message& message2, int unpacked_any,
0855       const FieldDescriptor* field, int index1, int index2,
0856       std::vector<SpecificField>* parent_fields);
0857 
0858   // Compares the specified field on the two messages, returning comparison
0859   // result, as returned by appropriate FieldComparator.
0860   FieldComparator::ComparisonResult GetFieldComparisonResult(
0861       const Message& message1, const Message& message2,
0862       const FieldDescriptor* field, int index1, int index2,
0863       const FieldContext* field_context);
0864 
0865   // Check if the two elements in the repeated field are match to each other.
0866   // if the key_comprator is NULL, this function returns true when the two
0867   // elements are equal.
0868   bool IsMatch(const FieldDescriptor* repeated_field,
0869                const MapKeyComparator* key_comparator, const Message* message1,
0870                const Message* message2, int unpacked_any,
0871                const std::vector<SpecificField>& parent_fields,
0872                Reporter* reporter, int index1, int index2);
0873 
0874   // Returns true when this repeated field has been configured to be treated
0875   // as a Set / SmartSet / SmartList.
0876   bool IsTreatedAsSet(const FieldDescriptor* field);
0877   bool IsTreatedAsSmartSet(const FieldDescriptor* field);
0878 
0879   bool IsTreatedAsSmartList(const FieldDescriptor* field);
0880   // When treating as SMART_LIST, it uses MatchIndicesPostProcessorForSmartList
0881   // by default to find the longest matching sequence from the first matching
0882   // element. The callback takes two vectors showing the matching indices from
0883   // the other vector, where -1 means an unmatch.
0884   void SetMatchIndicesForSmartListCallback(
0885       std::function<void(std::vector<int>*, std::vector<int>*)> callback);
0886 
0887   // Returns true when this repeated field is to be compared as a subset, ie.
0888   // has been configured to be treated as a set or map and scope is set to
0889   // PARTIAL.
0890   bool IsTreatedAsSubset(const FieldDescriptor* field);
0891 
0892   // Returns true if this field is to be ignored when this
0893   // MessageDifferencer compares messages.
0894   bool IsIgnored(const Message& message1, const Message& message2,
0895                  const FieldDescriptor* field,
0896                  const std::vector<SpecificField>& parent_fields);
0897 
0898   // Returns true if this unknown field is to be ignored when this
0899   // MessageDifferencer compares messages.
0900   bool IsUnknownFieldIgnored(const Message& message1, const Message& message2,
0901                              const SpecificField& field,
0902                              const std::vector<SpecificField>& parent_fields);
0903 
0904   // Returns MapKeyComparator* when this field has been configured to be treated
0905   // as a map or its is_map() return true.  If not, returns NULL.
0906   const MapKeyComparator* GetMapKeyComparator(
0907       const FieldDescriptor* field) const;
0908 
0909   // Attempts to match indices of a repeated field, so that the contained values
0910   // match. Clears output vectors and sets their values to indices of paired
0911   // messages, ie. if message1[0] matches message2[1], then match_list1[0] == 1
0912   // and match_list2[1] == 0. The unmatched indices are indicated by -1.
0913   // Assumes the repeated field is not treated as a simple list.
0914   // This method returns false if the match failed. However, it doesn't mean
0915   // that the comparison succeeds when this method returns true (you need to
0916   // double-check in this case).
0917   bool MatchRepeatedFieldIndices(
0918       const Message& message1, const Message& message2, int unpacked_any,
0919       const FieldDescriptor* repeated_field,
0920       const MapKeyComparator* key_comparator,
0921       const std::vector<SpecificField>& parent_fields,
0922       std::vector<int>* match_list1, std::vector<int>* match_list2);
0923 
0924   // Checks if index is equal to new_index in all the specific fields.
0925   static bool CheckPathChanged(const std::vector<SpecificField>& parent_fields);
0926 
0927   // ABSL_CHECKs that the given repeated field can be compared according to
0928   // new_comparison.
0929   void CheckRepeatedFieldComparisons(
0930       const FieldDescriptor* field,
0931       const RepeatedFieldComparison& new_comparison);
0932 
0933   // Whether we should still compare the field despite its absence in message1.
0934   bool ShouldCompareNoPresence(const Message& message1,
0935                                const Reflection& reflection1,
0936                                const FieldDescriptor* field2) const;
0937 
0938   // We move this code out of line to reduce stack cost of the caller.
0939   // The map lookups and string copies are costly in stack space.
0940   PROTOBUF_NOINLINE void ForceCompareField(const FieldDescriptor* field);
0941 
0942   Reporter* reporter_;
0943   DefaultFieldComparator default_field_comparator_;
0944   MessageFieldComparison message_field_comparison_;
0945   Scope scope_;
0946   absl::flat_hash_set<const FieldDescriptor*> force_compare_no_presence_fields_;
0947   google::protobuf::TextFormat::Parser::UnsetFieldsMetadata require_no_presence_fields_;
0948   absl::flat_hash_set<std::string> force_compare_failure_triggering_fields_;
0949   RepeatedFieldComparison repeated_field_comparison_;
0950 
0951   absl::flat_hash_map<const FieldDescriptor*, RepeatedFieldComparison>
0952       repeated_field_comparisons_;
0953   // Keeps track of MapKeyComparators that are created within
0954   // MessageDifferencer. These MapKeyComparators should be deleted
0955   // before MessageDifferencer is destroyed.
0956   // When TreatAsMap or TreatAsMapWithMultipleFieldsAsKey is called, we don't
0957   // store the supplied FieldDescriptors directly. Instead, a new
0958   // MapKeyComparator is created for comparison purpose.
0959   std::vector<MapKeyComparator*> owned_key_comparators_;
0960   absl::flat_hash_map<const FieldDescriptor*, const MapKeyComparator*>
0961       map_field_key_comparator_;
0962   MapEntryKeyComparator map_entry_key_comparator_;
0963   std::vector<std::unique_ptr<IgnoreCriteria>> ignore_criteria_;
0964   // Reused multiple times in RetrieveFields to avoid extra allocations
0965   std::vector<const FieldDescriptor*> tmp_message_fields_;
0966 
0967   absl::flat_hash_set<const FieldDescriptor*> ignored_fields_;
0968 
0969   union {
0970     DefaultFieldComparator* default_impl;
0971     FieldComparator* base;
0972   } field_comparator_ = {&default_field_comparator_};
0973   enum { kFCDefault, kFCBase } field_comparator_kind_ = kFCDefault;
0974 
0975   bool report_matches_;
0976   bool report_moves_;
0977   bool report_ignores_;
0978   bool force_compare_no_presence_ = false;
0979 
0980   std::string* output_string_;
0981 
0982   // Callback to post-process the matched indices to support SMART_LIST.
0983   std::function<void(std::vector<int>*, std::vector<int>*)>
0984       match_indices_for_smart_list_callback_;
0985 
0986   MessageDifferencer::UnpackAnyField unpack_any_field_;
0987 };
0988 
0989 // This class provides extra information to the FieldComparator::Compare
0990 // function.
0991 class PROTOBUF_EXPORT FieldContext {
0992  public:
0993   explicit FieldContext(
0994       std::vector<MessageDifferencer::SpecificField>* parent_fields)
0995       : parent_fields_(parent_fields) {}
0996 
0997   std::vector<MessageDifferencer::SpecificField>* parent_fields() const {
0998     return parent_fields_;
0999   }
1000 
1001  private:
1002   std::vector<MessageDifferencer::SpecificField>* parent_fields_;
1003 };
1004 
1005 }  // namespace util
1006 }  // namespace protobuf
1007 }  // namespace google
1008 
1009 #include "google/protobuf/port_undef.inc"
1010 
1011 #endif  // GOOGLE_PROTOBUF_UTIL_MESSAGE_DIFFERENCER_H__