Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-31 10:12:04

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   // Takes ownership of ignore_criteria.
0508   void AddIgnoreCriteria(IgnoreCriteria* ignore_criteria) {
0509     AddIgnoreCriteria(absl::WrapUnique(ignore_criteria));
0510   }
0511   void AddIgnoreCriteria(std::unique_ptr<IgnoreCriteria> ignore_criteria);
0512 
0513   // Indicates that any field with the given descriptor should be
0514   // ignored for the purposes of comparing two messages. This applies
0515   // to fields nested in the message structure as well as top level
0516   // ones. When the MessageDifferencer encounters an ignored field,
0517   // ReportIgnored is called on the reporter, if one is specified.
0518   //
0519   // The only place where the field's 'ignored' status is not applied is when
0520   // it is being used as a key in a field passed to TreatAsMap or is one of
0521   // the fields passed to TreatAsMapWithMultipleFieldsAsKey.
0522   // In this case it is compared in key matching but after that it's ignored
0523   // in value comparison.
0524   void IgnoreField(const FieldDescriptor* field);
0525 
0526   // Sets the field comparator used to determine differences between protocol
0527   // buffer fields. By default it's set to a DefaultFieldComparator instance.
0528   // MessageDifferencer doesn't take ownership over the passed object.
0529   // Note that this method must be called before Compare for the comparator to
0530   // be used.
0531   void set_field_comparator(FieldComparator* comparator);
0532   void set_field_comparator(DefaultFieldComparator* comparator);
0533 
0534   // DEPRECATED. Pass a DefaultFieldComparator instance instead.
0535   // Sets the fraction and margin for the float comparison of a given field.
0536   // Uses MathUtil::WithinFractionOrMargin to compare the values.
0537   // NOTE: this method does nothing if differencer's field comparator has been
0538   //       set to a custom object.
0539   //
0540   // REQUIRES: field->cpp_type == FieldDescriptor::CPPTYPE_DOUBLE or
0541   //           field->cpp_type == FieldDescriptor::CPPTYPE_FLOAT
0542   // REQUIRES: float_comparison_ == APPROXIMATE
0543   void SetFractionAndMargin(const FieldDescriptor* field, double fraction,
0544                             double margin);
0545 
0546   // Sets the type of comparison (as defined in the MessageFieldComparison
0547   // enumeration above) that is used by this differencer when determining how
0548   // to compare fields in messages.
0549   void set_message_field_comparison(MessageFieldComparison comparison);
0550 
0551   // Returns the current message field comparison used in this differencer.
0552   MessageFieldComparison message_field_comparison() const;
0553 
0554   // Tells the differencer whether or not to report matches. This method must
0555   // be called before Compare. The default for a new differencer is false.
0556   void set_report_matches(bool report_matches) {
0557     report_matches_ = report_matches;
0558   }
0559 
0560   // Tells the differencer whether or not to report moves (in a set or map
0561   // repeated field). This method must be called before Compare. The default for
0562   // a new differencer is true.
0563   void set_report_moves(bool report_moves) { report_moves_ = report_moves; }
0564 
0565   // Tells the differencer whether or not to report ignored values. This method
0566   // must be called before Compare. The default for a new differencer is true.
0567   void set_report_ignores(bool report_ignores) {
0568     report_ignores_ = report_ignores;
0569   }
0570 
0571   // Sets the scope of the comparison (as defined in the Scope enumeration
0572   // above) that is used by this differencer when determining which fields to
0573   // compare between the messages.
0574   void set_scope(Scope scope);
0575 
0576   // Returns the current scope used by this differencer.
0577   Scope scope() const;
0578 
0579   // Only affects PARTIAL diffing. When set, all non-repeated no-presence fields
0580   // which are set to their default value (which is the same as being unset) in
0581   // message1 but are set to a non-default value in message2 will also be used
0582   // in the comparison.
0583   void set_force_compare_no_presence(bool value);
0584 
0585   // If set, the fields in message1 that equal the fields passed here will be
0586   // treated as required for comparison, even if they are absent.
0587   void set_require_no_presence_fields(
0588       const google::protobuf::TextFormat::Parser::UnsetFieldsMetadata& fields) {
0589     require_no_presence_fields_ = fields;
0590   }
0591 
0592   // DEPRECATED. Pass a DefaultFieldComparator instance instead.
0593   // Sets the type of comparison (as defined in the FloatComparison enumeration
0594   // above) that is used by this differencer when comparing float (and double)
0595   // fields in messages.
0596   // NOTE: this method does nothing if differencer's field comparator has been
0597   //       set to a custom object.
0598   void set_float_comparison(FloatComparison comparison);
0599 
0600   // Sets the type of comparison for repeated field (as defined in the
0601   // RepeatedFieldComparison enumeration above) that is used by this
0602   // differencer when compare repeated fields in messages.
0603   void set_repeated_field_comparison(RepeatedFieldComparison comparison);
0604 
0605   // Returns the current repeated field comparison used by this differencer.
0606   RepeatedFieldComparison repeated_field_comparison() const;
0607 
0608   // Compares the two specified messages, returning true if they are the same,
0609   // false otherwise. If this method returns false, any changes between the
0610   // two messages will be reported if a Reporter was specified via
0611   // ReportDifferencesTo (see also ReportDifferencesToString).
0612   //
0613   // This method REQUIRES that the two messages have the same
0614   // Descriptor (message1.GetDescriptor() == message2.GetDescriptor()).
0615   bool Compare(const Message& message1, const Message& message2);
0616 
0617   // Same as above, except comparing only the list of fields specified by the
0618   // two vectors of FieldDescriptors.
0619   bool CompareWithFields(
0620       const Message& message1, const Message& message2,
0621       const std::vector<const FieldDescriptor*>& message1_fields,
0622       const std::vector<const FieldDescriptor*>& message2_fields);
0623 
0624   // Automatically creates a reporter that will output the differences
0625   // found (if any) to the specified output string pointer. Note that this
0626   // method must be called before Compare.
0627   void ReportDifferencesToString(std::string* output);
0628 
0629   // Tells the MessageDifferencer to report differences via the specified
0630   // reporter. Note that this method must be called before Compare for
0631   // the reporter to be used. It is the responsibility of the caller to delete
0632   // this object.
0633   // If the provided pointer equals NULL, the MessageDifferencer stops reporting
0634   // differences to any previously set reporters or output strings.
0635   void ReportDifferencesTo(Reporter* reporter);
0636 
0637   // Returns the list of fields which was automatically added to the list of
0638   // compared fields by calling set_force_compare_no_presence and caused the
0639   // last call to Compare to fail.
0640   const absl::flat_hash_set<std::string>& NoPresenceFieldsCausingFailure() {
0641     return force_compare_failure_triggering_fields_;
0642   }
0643 
0644  private:
0645   // Class for processing Any deserialization.  This logic is used by both the
0646   // MessageDifferencer and StreamReporter classes.
0647   class UnpackAnyField {
0648    private:
0649     std::unique_ptr<DynamicMessageFactory> dynamic_message_factory_;
0650 
0651    public:
0652     UnpackAnyField() = default;
0653     ~UnpackAnyField() = default;
0654     // If "any" is of type google.protobuf.Any, extract its payload using
0655     // DynamicMessageFactory and store in "data".
0656     bool UnpackAny(const Message& any, std::unique_ptr<Message>* data);
0657   };
0658 
0659  public:
0660   // An implementation of the MessageDifferencer Reporter that outputs
0661   // any differences found in human-readable form to the supplied
0662   // ZeroCopyOutputStream or Printer. If a printer is used, the delimiter
0663   // *must* be '$'.
0664   //
0665   // WARNING: this reporter does not necessarily flush its output until it is
0666   // destroyed. As a result, it is not safe to assume the output is valid or
0667   // complete until after you destroy the reporter. For example, if you use a
0668   // StreamReporter to write to a StringOutputStream, the target string may
0669   // contain uninitialized data until the reporter is destroyed.
0670   class PROTOBUF_EXPORT StreamReporter : public Reporter {
0671    public:
0672     explicit StreamReporter(io::ZeroCopyOutputStream* output);
0673     explicit StreamReporter(io::Printer* printer);  // delimiter '$'
0674     StreamReporter(const StreamReporter&) = delete;
0675     StreamReporter& operator=(const StreamReporter&) = delete;
0676     ~StreamReporter() override;
0677 
0678     // When set to true, the stream reporter will also output aggregates nodes
0679     // (i.e. messages and groups) whose subfields have been modified. When
0680     // false, will only report the individual subfields. Defaults to false.
0681     void set_report_modified_aggregates(bool report) {
0682       report_modified_aggregates_ = report;
0683     }
0684 
0685     // The following are implementations of the methods described above.
0686 
0687     void ReportAdded(const Message& message1, const Message& message2,
0688                      const std::vector<SpecificField>& field_path) override;
0689 
0690     void ReportDeleted(const Message& message1, const Message& message2,
0691                        const std::vector<SpecificField>& field_path) override;
0692 
0693     void ReportModified(const Message& message1, const Message& message2,
0694                         const std::vector<SpecificField>& field_path) override;
0695 
0696     void ReportMoved(const Message& message1, const Message& message2,
0697                      const std::vector<SpecificField>& field_path) override;
0698 
0699     void ReportMatched(const Message& message1, const Message& message2,
0700                        const std::vector<SpecificField>& field_path) override;
0701 
0702     void ReportIgnored(const Message& message1, const Message& message2,
0703                        const std::vector<SpecificField>& field_path) override;
0704 
0705     void ReportUnknownFieldIgnored(
0706         const Message& message1, const Message& message2,
0707         const std::vector<SpecificField>& field_path) override;
0708 
0709     // Messages that are being compared must be provided to StreamReporter prior
0710     // to processing
0711     void SetMessages(const Message& message1, const Message& message2);
0712 
0713    protected:
0714     // Prints the specified path of fields to the buffer.
0715     virtual void PrintPath(const std::vector<SpecificField>& field_path,
0716                            bool left_side);
0717 
0718     // Prints the value of fields to the buffer.  left_side is true if the
0719     // given message is from the left side of the comparison, false if it
0720     // was the right.  This is relevant only to decide whether to follow
0721     // unknown_field_index1 or unknown_field_index2 when an unknown field
0722     // is encountered in field_path.
0723     virtual void PrintValue(const Message& message,
0724                             const std::vector<SpecificField>& field_path,
0725                             bool left_side);
0726 
0727     // Prints the specified path of unknown fields to the buffer.
0728     virtual void PrintUnknownFieldValue(const UnknownField* unknown_field);
0729 
0730     // Just print a string
0731     void Print(const std::string& str);
0732 
0733    private:
0734     // helper function for PrintPath that contains logic for printing maps
0735     void PrintMapKey(bool left_side, const SpecificField& specific_field);
0736 
0737     io::Printer* printer_;
0738     bool delete_printer_;
0739     bool report_modified_aggregates_;
0740     const Message* message1_;
0741     const Message* message2_;
0742     MessageDifferencer::UnpackAnyField unpack_any_field_;
0743   };
0744 
0745  private:
0746   friend class SimpleFieldComparator;
0747 
0748   // A MapKeyComparator to be used in TreatAsMapUsingKeyComparator.
0749   // Implementation of this class needs to do field value comparison which
0750   // relies on some private methods of MessageDifferencer. That's why this
0751   // class is declared as a nested class of MessageDifferencer.
0752   class MultipleFieldsMapKeyComparator;
0753 
0754   // A MapKeyComparator for use with map_entries.
0755   class PROTOBUF_EXPORT MapEntryKeyComparator : public MapKeyComparator {
0756    public:
0757     explicit MapEntryKeyComparator(MessageDifferencer* message_differencer);
0758     bool IsMatch(
0759         const Message& message1, const Message& message2, int unpacked_any,
0760         const std::vector<SpecificField>& parent_fields) const override;
0761 
0762    private:
0763     MessageDifferencer* message_differencer_;
0764   };
0765 
0766   // Returns true if field1's number() is less than field2's.
0767   static bool FieldBefore(const FieldDescriptor* field1,
0768                           const FieldDescriptor* field2);
0769 
0770   // Retrieve all the set fields, including extensions.
0771   std::vector<const FieldDescriptor*> RetrieveFields(const Message& message,
0772                                                      bool base_message);
0773 
0774   // Combine the two lists of fields into the combined_fields output vector.
0775   // All fields present in both lists will always be included in the combined
0776   // list.  Fields only present in one of the lists will only appear in the
0777   // combined list if the corresponding fields_scope option is set to FULL.
0778   std::vector<const FieldDescriptor*> CombineFields(
0779       const Message& message1,
0780       const std::vector<const FieldDescriptor*>& fields1, Scope fields1_scope,
0781       const std::vector<const FieldDescriptor*>& fields2, Scope fields2_scope);
0782 
0783   // Internal version of the Compare method which performs the actual
0784   // comparison. The parent_fields vector is a vector containing field
0785   // descriptors of all fields accessed to get to this comparison operation
0786   // (i.e. if the current message is an embedded message, the parent_fields
0787   // vector will contain the field that has this embedded message).
0788   bool Compare(const Message& message1, const Message& message2,
0789                int unpacked_any, std::vector<SpecificField>* parent_fields);
0790 
0791   // Compares all the unknown fields in two messages.
0792   bool CompareUnknownFields(const Message& message1, const Message& message2,
0793                             const UnknownFieldSet&, const UnknownFieldSet&,
0794                             std::vector<SpecificField>* parent_fields);
0795 
0796   // Compares the specified messages for the requested field lists. The field
0797   // lists are modified depending on comparison settings, and then passed to
0798   // CompareWithFieldsInternal.
0799   bool CompareRequestedFieldsUsingSettings(
0800       const Message& message1, const Message& message2, int unpacked_any,
0801       const std::vector<const FieldDescriptor*>& message1_fields,
0802       const std::vector<const FieldDescriptor*>& message2_fields,
0803       std::vector<SpecificField>* parent_fields);
0804 
0805   // Compares the specified messages with the specified field lists.
0806   bool CompareWithFieldsInternal(
0807       const Message& message1, const Message& message2, int unpacked_any,
0808       const std::vector<const FieldDescriptor*>& message1_fields,
0809       const std::vector<const FieldDescriptor*>& message2_fields,
0810       std::vector<SpecificField>* parent_fields);
0811 
0812   // Compares the repeated fields, and report the error.
0813   bool CompareRepeatedField(const Message& message1, const Message& message2,
0814                             int unpacked_any, const FieldDescriptor* field,
0815                             std::vector<SpecificField>* parent_fields);
0816 
0817   // Compares map fields, and report the error.
0818   bool CompareMapField(const Message& message1, const Message& message2,
0819                        int unpacked_any, const FieldDescriptor* field,
0820                        std::vector<SpecificField>* parent_fields);
0821 
0822   // Helper for CompareRepeatedField and CompareMapField: compares and reports
0823   // differences element-wise. This is the implementation for non-map fields,
0824   // and can also compare map fields by using the underlying representation.
0825   bool CompareRepeatedRep(const Message& message1, const Message& message2,
0826                           int unpacked_any, const FieldDescriptor* field,
0827                           std::vector<SpecificField>* parent_fields);
0828 
0829   // Helper for CompareMapField: compare the map fields using map reflection
0830   // instead of sync to repeated.
0831   bool CompareMapFieldByMapReflection(const Message& message1,
0832                                       const Message& message2, int unpacked_any,
0833                                       const FieldDescriptor* field,
0834                                       std::vector<SpecificField>* parent_fields,
0835                                       DefaultFieldComparator* comparator);
0836 
0837   // Shorthand for CompareFieldValueUsingParentFields with NULL parent_fields.
0838   bool CompareFieldValue(const Message& message1, const Message& message2,
0839                          int unpacked_any, const FieldDescriptor* field,
0840                          int index1, int index2);
0841 
0842   // Compares the specified field on the two messages, returning
0843   // true if they are the same, false otherwise. For repeated fields,
0844   // this method only compares the value in the specified index. This method
0845   // uses Compare functions to recurse into submessages.
0846   // The parent_fields vector is used in calls to a Reporter instance calls.
0847   // It can be NULL, in which case the MessageDifferencer will create new
0848   // list of parent messages if it needs to recursively compare the given field.
0849   // To avoid confusing users you should not set it to NULL unless you modified
0850   // Reporter to handle the change of parent_fields correctly.
0851   bool CompareFieldValueUsingParentFields(
0852       const Message& message1, const Message& message2, int unpacked_any,
0853       const FieldDescriptor* field, int index1, int index2,
0854       std::vector<SpecificField>* parent_fields);
0855 
0856   // Compares the specified field on the two messages, returning comparison
0857   // result, as returned by appropriate FieldComparator.
0858   FieldComparator::ComparisonResult GetFieldComparisonResult(
0859       const Message& message1, const Message& message2,
0860       const FieldDescriptor* field, int index1, int index2,
0861       const FieldContext* field_context);
0862 
0863   // Check if the two elements in the repeated field are match to each other.
0864   // if the key_comprator is NULL, this function returns true when the two
0865   // elements are equal.
0866   bool IsMatch(const FieldDescriptor* repeated_field,
0867                const MapKeyComparator* key_comparator, const Message* message1,
0868                const Message* message2, int unpacked_any,
0869                const std::vector<SpecificField>& parent_fields,
0870                Reporter* reporter, int index1, int index2);
0871 
0872   // Returns true when this repeated field has been configured to be treated
0873   // as a Set / SmartSet / SmartList.
0874   bool IsTreatedAsSet(const FieldDescriptor* field);
0875   bool IsTreatedAsSmartSet(const FieldDescriptor* field);
0876 
0877   bool IsTreatedAsSmartList(const FieldDescriptor* field);
0878   // When treating as SMART_LIST, it uses MatchIndicesPostProcessorForSmartList
0879   // by default to find the longest matching sequence from the first matching
0880   // element. The callback takes two vectors showing the matching indices from
0881   // the other vector, where -1 means an unmatch.
0882   void SetMatchIndicesForSmartListCallback(
0883       std::function<void(std::vector<int>*, std::vector<int>*)> callback);
0884 
0885   // Returns true when this repeated field is to be compared as a subset, ie.
0886   // has been configured to be treated as a set or map and scope is set to
0887   // PARTIAL.
0888   bool IsTreatedAsSubset(const FieldDescriptor* field);
0889 
0890   // Returns true if this field is to be ignored when this
0891   // MessageDifferencer compares messages.
0892   bool IsIgnored(const Message& message1, const Message& message2,
0893                  const FieldDescriptor* field,
0894                  const std::vector<SpecificField>& parent_fields);
0895 
0896   // Returns true if this unknown field is to be ignored when this
0897   // MessageDifferencer compares messages.
0898   bool IsUnknownFieldIgnored(const Message& message1, const Message& message2,
0899                              const SpecificField& field,
0900                              const std::vector<SpecificField>& parent_fields);
0901 
0902   // Returns MapKeyComparator* when this field has been configured to be treated
0903   // as a map or its is_map() return true.  If not, returns NULL.
0904   const MapKeyComparator* GetMapKeyComparator(
0905       const FieldDescriptor* field) const;
0906 
0907   // Attempts to match indices of a repeated field, so that the contained values
0908   // match. Clears output vectors and sets their values to indices of paired
0909   // messages, ie. if message1[0] matches message2[1], then match_list1[0] == 1
0910   // and match_list2[1] == 0. The unmatched indices are indicated by -1.
0911   // Assumes the repeated field is not treated as a simple list.
0912   // This method returns false if the match failed. However, it doesn't mean
0913   // that the comparison succeeds when this method returns true (you need to
0914   // double-check in this case).
0915   bool MatchRepeatedFieldIndices(
0916       const Message& message1, const Message& message2, int unpacked_any,
0917       const FieldDescriptor* repeated_field,
0918       const MapKeyComparator* key_comparator,
0919       const std::vector<SpecificField>& parent_fields,
0920       std::vector<int>* match_list1, std::vector<int>* match_list2);
0921 
0922   // Checks if index is equal to new_index in all the specific fields.
0923   static bool CheckPathChanged(const std::vector<SpecificField>& parent_fields);
0924 
0925   // ABSL_CHECKs that the given repeated field can be compared according to
0926   // new_comparison.
0927   void CheckRepeatedFieldComparisons(
0928       const FieldDescriptor* field,
0929       const RepeatedFieldComparison& new_comparison);
0930 
0931   // Whether we should still compare the field despite its absence in message1.
0932   bool ShouldCompareNoPresence(const Message& message1,
0933                                const Reflection& reflection1,
0934                                const FieldDescriptor* field2) const;
0935 
0936   Reporter* reporter_;
0937   DefaultFieldComparator default_field_comparator_;
0938   MessageFieldComparison message_field_comparison_;
0939   Scope scope_;
0940   absl::flat_hash_set<const FieldDescriptor*> force_compare_no_presence_fields_;
0941   google::protobuf::TextFormat::Parser::UnsetFieldsMetadata require_no_presence_fields_;
0942   absl::flat_hash_set<std::string> force_compare_failure_triggering_fields_;
0943   RepeatedFieldComparison repeated_field_comparison_;
0944 
0945   absl::flat_hash_map<const FieldDescriptor*, RepeatedFieldComparison>
0946       repeated_field_comparisons_;
0947   // Keeps track of MapKeyComparators that are created within
0948   // MessageDifferencer. These MapKeyComparators should be deleted
0949   // before MessageDifferencer is destroyed.
0950   // When TreatAsMap or TreatAsMapWithMultipleFieldsAsKey is called, we don't
0951   // store the supplied FieldDescriptors directly. Instead, a new
0952   // MapKeyComparator is created for comparison purpose.
0953   std::vector<MapKeyComparator*> owned_key_comparators_;
0954   absl::flat_hash_map<const FieldDescriptor*, const MapKeyComparator*>
0955       map_field_key_comparator_;
0956   MapEntryKeyComparator map_entry_key_comparator_;
0957   std::vector<std::unique_ptr<IgnoreCriteria>> ignore_criteria_;
0958   // Reused multiple times in RetrieveFields to avoid extra allocations
0959   std::vector<const FieldDescriptor*> tmp_message_fields_;
0960 
0961   absl::flat_hash_set<const FieldDescriptor*> ignored_fields_;
0962 
0963   union {
0964     DefaultFieldComparator* default_impl;
0965     FieldComparator* base;
0966   } field_comparator_ = {&default_field_comparator_};
0967   enum { kFCDefault, kFCBase } field_comparator_kind_ = kFCDefault;
0968 
0969   bool report_matches_;
0970   bool report_moves_;
0971   bool report_ignores_;
0972   bool force_compare_no_presence_ = false;
0973 
0974   std::string* output_string_;
0975 
0976   // Callback to post-process the matched indices to support SMART_LIST.
0977   std::function<void(std::vector<int>*, std::vector<int>*)>
0978       match_indices_for_smart_list_callback_;
0979 
0980   MessageDifferencer::UnpackAnyField unpack_any_field_;
0981 };
0982 
0983 // This class provides extra information to the FieldComparator::Compare
0984 // function.
0985 class PROTOBUF_EXPORT FieldContext {
0986  public:
0987   explicit FieldContext(
0988       std::vector<MessageDifferencer::SpecificField>* parent_fields)
0989       : parent_fields_(parent_fields) {}
0990 
0991   std::vector<MessageDifferencer::SpecificField>* parent_fields() const {
0992     return parent_fields_;
0993   }
0994 
0995  private:
0996   std::vector<MessageDifferencer::SpecificField>* parent_fields_;
0997 };
0998 
0999 }  // namespace util
1000 }  // namespace protobuf
1001 }  // namespace google
1002 
1003 #include "google/protobuf/port_undef.inc"
1004 
1005 #endif  // GOOGLE_PROTOBUF_UTIL_MESSAGE_DIFFERENCER_H__