|
||||
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__
[ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |