You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

message_differencer.h 57 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972
  1. // Protocol Buffers - Google's data interchange format
  2. // Copyright 2008 Google Inc. All rights reserved.
  3. // https://developers.google.com/protocol-buffers/
  4. //
  5. // Redistribution and use in source and binary forms, with or without
  6. // modification, are permitted provided that the following conditions are
  7. // met:
  8. //
  9. // * Redistributions of source code must retain the above copyright
  10. // notice, this list of conditions and the following disclaimer.
  11. // * Redistributions in binary form must reproduce the above
  12. // copyright notice, this list of conditions and the following disclaimer
  13. // in the documentation and/or other materials provided with the
  14. // distribution.
  15. // * Neither the name of Google Inc. nor the names of its
  16. // contributors may be used to endorse or promote products derived from
  17. // this software without specific prior written permission.
  18. //
  19. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  20. // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  21. // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  22. // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  23. // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  24. // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  25. // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  26. // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  27. // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  28. // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  29. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  30. // Author: jschorr@google.com (Joseph Schorr)
  31. // Based on original Protocol Buffers design by
  32. // Sanjay Ghemawat, Jeff Dean, and others.
  33. //
  34. // This file defines static methods and classes for comparing Protocol
  35. // Messages.
  36. //
  37. // Aug. 2008: Added Unknown Fields Comparison for messages.
  38. // Aug. 2009: Added different options to compare repeated fields.
  39. // Apr. 2010: Moved field comparison to FieldComparator
  40. // Sep. 2020: Added option to output map keys in path
  41. #ifndef GOOGLE_PROTOBUF_UTIL_MESSAGE_DIFFERENCER_H__
  42. #define GOOGLE_PROTOBUF_UTIL_MESSAGE_DIFFERENCER_H__
  43. #include <functional>
  44. #include <map>
  45. #include <memory>
  46. #include <set>
  47. #include <string>
  48. #include <vector>
  49. #include <google/protobuf/descriptor.h> // FieldDescriptor
  50. #include <google/protobuf/message.h> // Message
  51. #include <google/protobuf/unknown_field_set.h>
  52. #include <google/protobuf/util/field_comparator.h>
  53. // Always include as last one, otherwise it can break compilation
  54. #include <google/protobuf/port_def.inc>
  55. namespace google
  56. {
  57. namespace protobuf
  58. {
  59. class DynamicMessageFactory;
  60. class FieldDescriptor;
  61. namespace io
  62. {
  63. class ZeroCopyOutputStream;
  64. class Printer;
  65. } // namespace io
  66. namespace util
  67. {
  68. class DefaultFieldComparator;
  69. class FieldContext; // declared below MessageDifferencer
  70. // Defines a collection of field descriptors.
  71. // In case of internal google codebase we are using absl::FixedArray instead
  72. // of vector. It significantly speeds up proto comparison (by ~30%) by
  73. // reducing the number of malloc/free operations
  74. typedef std::vector<const FieldDescriptor*> FieldDescriptorArray;
  75. // A basic differencer that can be used to determine
  76. // the differences between two specified Protocol Messages. If any differences
  77. // are found, the Compare method will return false, and any differencer reporter
  78. // specified via ReportDifferencesTo will have its reporting methods called (see
  79. // below for implementation of the report). Based off of the original
  80. // ProtocolDifferencer implementation in //net/proto/protocol-differencer.h
  81. // (Thanks Todd!).
  82. //
  83. // MessageDifferencer REQUIRES that compared messages be the same type, defined
  84. // as messages that share the same descriptor. If not, the behavior of this
  85. // class is undefined.
  86. //
  87. // People disagree on what MessageDifferencer should do when asked to compare
  88. // messages with different descriptors. Some people think it should always
  89. // return false. Others expect it to try to look for similar fields and
  90. // compare them anyway -- especially if the descriptors happen to be identical.
  91. // If we chose either of these behaviors, some set of people would find it
  92. // surprising, and could end up writing code expecting the other behavior
  93. // without realizing their error. Therefore, we forbid that usage.
  94. //
  95. // This class is implemented based on the proto2 reflection. The performance
  96. // should be good enough for normal usages. However, for places where the
  97. // performance is extremely sensitive, there are several alternatives:
  98. // - Comparing serialized string
  99. // Downside: false negatives (there are messages that are the same but their
  100. // serialized strings are different).
  101. // - Equals code generator by compiler plugin (net/proto2/contrib/equals_plugin)
  102. // Downside: more generated code; maintenance overhead for the additional rule
  103. // (must be in sync with the original proto_library).
  104. //
  105. // Note on handling of google.protobuf.Any: MessageDifferencer automatically
  106. // unpacks Any::value into a Message and compares its individual fields.
  107. // Messages encoded in a repeated Any cannot be compared using TreatAsMap.
  108. //
  109. // Note on thread-safety: MessageDifferencer is *not* thread-safe. You need to
  110. // guard it with a lock to use the same MessageDifferencer instance from
  111. // multiple threads. Note that it's fine to call static comparison methods
  112. // (like MessageDifferencer::Equals) concurrently, but it's not recommended for
  113. // performance critical code as it leads to extra allocations.
  114. class PROTOBUF_EXPORT MessageDifferencer
  115. {
  116. public:
  117. // Determines whether the supplied messages are equal. Equality is defined as
  118. // all fields within the two messages being set to the same value. Primitive
  119. // fields and strings are compared by value while embedded messages/groups
  120. // are compared as if via a recursive call. Use Compare() with IgnoreField()
  121. // if some fields should be ignored in the comparison. Use Compare() with
  122. // TreatAsSet() if there are repeated fields where ordering does not matter.
  123. //
  124. // This method REQUIRES that the two messages have the same
  125. // Descriptor (message1.GetDescriptor() == message2.GetDescriptor()).
  126. static bool Equals(const Message& message1, const Message& message2);
  127. // Determines whether the supplied messages are equivalent. Equivalency is
  128. // defined as all fields within the two messages having the same value. This
  129. // differs from the Equals method above in that fields with default values
  130. // are considered set to said value automatically. For details on how default
  131. // values are defined for each field type, see:
  132. // https://developers.google.com/protocol-buffers/docs/proto?csw=1#optional.
  133. // Also, Equivalent() ignores unknown fields. Use IgnoreField() and Compare()
  134. // if some fields should be ignored in the comparison.
  135. //
  136. // This method REQUIRES that the two messages have the same
  137. // Descriptor (message1.GetDescriptor() == message2.GetDescriptor()).
  138. static bool Equivalent(const Message& message1, const Message& message2);
  139. // Determines whether the supplied messages are approximately equal.
  140. // Approximate equality is defined as all fields within the two messages
  141. // being approximately equal. Primitive (non-float) fields and strings are
  142. // compared by value, floats are compared using MathUtil::AlmostEquals() and
  143. // embedded messages/groups are compared as if via a recursive call. Use
  144. // IgnoreField() and Compare() if some fields should be ignored in the
  145. // comparison.
  146. //
  147. // This method REQUIRES that the two messages have the same
  148. // Descriptor (message1.GetDescriptor() == message2.GetDescriptor()).
  149. static bool ApproximatelyEquals(const Message& message1, const Message& message2);
  150. // Determines whether the supplied messages are approximately equivalent.
  151. // Approximate equivalency is defined as all fields within the two messages
  152. // being approximately equivalent. As in
  153. // MessageDifferencer::ApproximatelyEquals, primitive (non-float) fields and
  154. // strings are compared by value, floats are compared using
  155. // MathUtil::AlmostEquals() and embedded messages/groups are compared as if
  156. // via a recursive call. However, fields with default values are considered
  157. // set to said value, as per MessageDiffencer::Equivalent. Use IgnoreField()
  158. // and Compare() if some fields should be ignored in the comparison.
  159. //
  160. // This method REQUIRES that the two messages have the same
  161. // Descriptor (message1.GetDescriptor() == message2.GetDescriptor()).
  162. static bool ApproximatelyEquivalent(const Message& message1, const Message& message2);
  163. // Identifies an individual field in a message instance. Used for field_path,
  164. // below.
  165. struct SpecificField
  166. {
  167. // For known fields, "field" is filled in and "unknown_field_number" is -1.
  168. // For unknown fields, "field" is NULL, "unknown_field_number" is the field
  169. // number, and "unknown_field_type" is its type.
  170. const FieldDescriptor* field = nullptr;
  171. int unknown_field_number = -1;
  172. UnknownField::Type unknown_field_type = UnknownField::Type::TYPE_VARINT;
  173. // If this a repeated field, "index" is the index within it. For unknown
  174. // fields, this is the index of the field among all unknown fields of the
  175. // same field number and type.
  176. int index = -1;
  177. // If "field" is a repeated field which is being treated as a map or
  178. // a set (see TreatAsMap() and TreatAsSet(), below), new_index indicates
  179. // the index the position to which the element has moved. If the element
  180. // has not moved, "new_index" will have the same value as "index".
  181. int new_index = -1;
  182. // If "field" is a map field, point to the map entry.
  183. const Message* map_entry1 = nullptr;
  184. const Message* map_entry2 = nullptr;
  185. // For unknown fields, these are the pointers to the UnknownFieldSet
  186. // containing the unknown fields. In certain cases (e.g. proto1's
  187. // MessageSet, or nested groups of unknown fields), these may differ from
  188. // the messages' internal UnknownFieldSets.
  189. const UnknownFieldSet* unknown_field_set1 = nullptr;
  190. const UnknownFieldSet* unknown_field_set2 = nullptr;
  191. // For unknown fields, these are the index of the field within the
  192. // UnknownFieldSets. One or the other will be -1 when
  193. // reporting an addition or deletion.
  194. int unknown_field_index1 = -1;
  195. int unknown_field_index2 = -1;
  196. };
  197. // Abstract base class from which all MessageDifferencer
  198. // reporters derive. The five Report* methods below will be called when
  199. // a field has been added, deleted, modified, moved, or matched. The third
  200. // argument is a vector of FieldDescriptor pointers which describes the chain
  201. // of fields that was taken to find the current field. For example, for a
  202. // field found in an embedded message, the vector will contain two
  203. // FieldDescriptors. The first will be the field of the embedded message
  204. // itself and the second will be the actual field in the embedded message
  205. // that was added/deleted/modified.
  206. // Fields will be reported in PostTraversalOrder.
  207. // For example, given following proto, if both baz and mooo are changed.
  208. // foo {
  209. // bar {
  210. // baz: 1
  211. // mooo: 2
  212. // }
  213. // }
  214. // ReportModified will be invoked with following order:
  215. // 1. foo.bar.baz or foo.bar.mooo
  216. // 2. foo.bar.mooo or foo.bar.baz
  217. // 2. foo.bar
  218. // 3. foo
  219. class PROTOBUF_EXPORT Reporter
  220. {
  221. public:
  222. Reporter();
  223. virtual ~Reporter();
  224. // Reports that a field has been added into Message2.
  225. virtual void ReportAdded(const Message& message1, const Message& message2, const std::vector<SpecificField>& field_path) = 0;
  226. // Reports that a field has been deleted from Message1.
  227. virtual void ReportDeleted(
  228. const Message& message1, const Message& message2, const std::vector<SpecificField>& field_path
  229. ) = 0;
  230. // Reports that the value of a field has been modified.
  231. virtual void ReportModified(
  232. const Message& message1, const Message& message2, const std::vector<SpecificField>& field_path
  233. ) = 0;
  234. // Reports that a repeated field has been moved to another location. This
  235. // only applies when using TreatAsSet or TreatAsMap() -- see below. Also
  236. // note that for any given field, ReportModified and ReportMoved are
  237. // mutually exclusive. If a field has been both moved and modified, then
  238. // only ReportModified will be called.
  239. virtual void ReportMoved(
  240. const Message& /* message1 */, const Message& /* message2 */, const std::vector<SpecificField>& /* field_path */
  241. )
  242. {
  243. }
  244. // Reports that two fields match. Useful for doing side-by-side diffs.
  245. // This function is mutually exclusive with ReportModified and ReportMoved.
  246. // Note that you must call set_report_matches(true) before calling Compare
  247. // to make use of this function.
  248. virtual void ReportMatched(
  249. const Message& /* message1 */, const Message& /* message2 */, const std::vector<SpecificField>& /* field_path */
  250. )
  251. {
  252. }
  253. // Reports that two fields would have been compared, but the
  254. // comparison has been skipped because the field was marked as
  255. // 'ignored' using IgnoreField(). This function is mutually
  256. // exclusive with all the other Report() functions.
  257. //
  258. // The contract of ReportIgnored is slightly different than the
  259. // other Report() functions, in that |field_path.back().index| is
  260. // always equal to -1, even if the last field is repeated. This is
  261. // because while the other Report() functions indicate where in a
  262. // repeated field the action (Addition, Deletion, etc...)
  263. // happened, when a repeated field is 'ignored', the differencer
  264. // simply calls ReportIgnored on the repeated field as a whole and
  265. // moves on without looking at its individual elements.
  266. //
  267. // Furthermore, ReportIgnored() does not indicate whether the
  268. // fields were in fact equal or not, as Compare() does not inspect
  269. // these fields at all. It is up to the Reporter to decide whether
  270. // the fields are equal or not (perhaps with a second call to
  271. // Compare()), if it cares.
  272. virtual void ReportIgnored(
  273. const Message& /* message1 */, const Message& /* message2 */, const std::vector<SpecificField>& /* field_path */
  274. )
  275. {
  276. }
  277. // Report that an unknown field is ignored. (see comment above).
  278. // Note this is a different function since the last SpecificField in field
  279. // path has a null field. This could break existing Reporter.
  280. virtual void ReportUnknownFieldIgnored(
  281. const Message& /* message1 */, const Message& /* message2 */, const std::vector<SpecificField>& /* field_path */
  282. )
  283. {
  284. }
  285. private:
  286. GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Reporter);
  287. };
  288. // MapKeyComparator is used to determine if two elements have the same key
  289. // when comparing elements of a repeated field as a map.
  290. class PROTOBUF_EXPORT MapKeyComparator
  291. {
  292. public:
  293. MapKeyComparator();
  294. virtual ~MapKeyComparator();
  295. virtual bool IsMatch(
  296. const Message& /* message1 */, const Message& /* message2 */, const std::vector<SpecificField>& /* parent_fields */
  297. ) const
  298. {
  299. GOOGLE_CHECK(false) << "IsMatch() is not implemented.";
  300. return false;
  301. }
  302. private:
  303. GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MapKeyComparator);
  304. };
  305. // Abstract base class from which all IgnoreCriteria derive.
  306. // By adding IgnoreCriteria more complex ignore logic can be implemented.
  307. // IgnoreCriteria are registered with AddIgnoreCriteria. For each compared
  308. // field IsIgnored is called on each added IgnoreCriteria until one returns
  309. // true or all return false.
  310. // IsIgnored is called for fields where at least one side has a value.
  311. class PROTOBUF_EXPORT IgnoreCriteria
  312. {
  313. public:
  314. IgnoreCriteria();
  315. virtual ~IgnoreCriteria();
  316. // Returns true if the field should be ignored.
  317. virtual bool IsIgnored(
  318. const Message& /* message1 */, const Message& /* message2 */, const FieldDescriptor* /* field */, const std::vector<SpecificField>& /* parent_fields */
  319. ) = 0;
  320. // Returns true if the unknown field should be ignored.
  321. // Note: This will be called for unknown fields as well in which case
  322. // field.field will be null.
  323. virtual bool IsUnknownFieldIgnored(
  324. const Message& /* message1 */, const Message& /* message2 */, const SpecificField& /* field */, const std::vector<SpecificField>& /* parent_fields */
  325. )
  326. {
  327. return false;
  328. }
  329. };
  330. // To add a Reporter, construct default here, then use ReportDifferencesTo or
  331. // ReportDifferencesToString.
  332. explicit MessageDifferencer();
  333. ~MessageDifferencer();
  334. enum MessageFieldComparison
  335. {
  336. EQUAL, // Fields must be present in both messages
  337. // for the messages to be considered the same.
  338. EQUIVALENT, // Fields with default values are considered set
  339. // for comparison purposes even if not explicitly
  340. // set in the messages themselves. Unknown fields
  341. // are ignored.
  342. };
  343. enum Scope
  344. {
  345. FULL, // All fields of both messages are considered in the comparison.
  346. PARTIAL // Only fields present in the first message are considered; fields
  347. // set only in the second message will be skipped during
  348. // comparison.
  349. };
  350. // DEPRECATED. Use FieldComparator::FloatComparison instead.
  351. enum FloatComparison
  352. {
  353. EXACT, // Floats and doubles are compared exactly.
  354. APPROXIMATE // Floats and doubles are compared using the
  355. // MathUtil::AlmostEquals method.
  356. };
  357. enum RepeatedFieldComparison
  358. {
  359. AS_LIST, // Repeated fields are compared in order. Differing values at
  360. // the same index are reported using ReportModified(). If the
  361. // repeated fields have different numbers of elements, the
  362. // unpaired elements are reported using ReportAdded() or
  363. // ReportDeleted().
  364. AS_SET, // Treat all the repeated fields as sets.
  365. // See TreatAsSet(), as below.
  366. AS_SMART_LIST, // Similar to AS_SET, but preserve the order and find the
  367. // longest matching sequence from the first matching
  368. // element. To use an optimal solution, call
  369. // SetMatchIndicesForSmartListCallback() to pass it in.
  370. AS_SMART_SET, // Similar to AS_SET, but match elements with fewest diffs.
  371. };
  372. // The elements of the given repeated field will be treated as a set for
  373. // diffing purposes, so different orderings of the same elements will be
  374. // considered equal. Elements which are present on both sides of the
  375. // comparison but which have changed position will be reported with
  376. // ReportMoved(). Elements which only exist on one side or the other are
  377. // reported with ReportAdded() and ReportDeleted() regardless of their
  378. // positions. ReportModified() is never used for this repeated field. If
  379. // the only differences between the compared messages is that some fields
  380. // have been moved, then the comparison returns true.
  381. //
  382. // Note that despite the name of this method, this is really
  383. // comparison as multisets: if one side of the comparison has a duplicate
  384. // in the repeated field but the other side doesn't, this will count as
  385. // a mismatch.
  386. //
  387. // If the scope of comparison is set to PARTIAL, then in addition to what's
  388. // above, extra values added to repeated fields of the second message will
  389. // not cause the comparison to fail.
  390. //
  391. // Note that set comparison is currently O(k * n^2) (where n is the total
  392. // number of elements, and k is the average size of each element). In theory
  393. // it could be made O(n * k) with a more complex hashing implementation. Feel
  394. // free to contribute one if the current implementation is too slow for you.
  395. // If partial matching is also enabled, the time complexity will be O(k * n^2
  396. // + n^3) in which n^3 is the time complexity of the maximum matching
  397. // algorithm.
  398. //
  399. // REQUIRES: field->is_repeated() and field not registered with TreatAsMap*
  400. void TreatAsSet(const FieldDescriptor* field);
  401. void TreatAsSmartSet(const FieldDescriptor* field);
  402. // The elements of the given repeated field will be treated as a list for
  403. // diffing purposes, so different orderings of the same elements will NOT be
  404. // considered equal.
  405. //
  406. // REQUIRES: field->is_repeated() and field not registered with TreatAsMap*
  407. void TreatAsList(const FieldDescriptor* field);
  408. // Note that the complexity is similar to treating as SET.
  409. void TreatAsSmartList(const FieldDescriptor* field);
  410. // The elements of the given repeated field will be treated as a map for
  411. // diffing purposes, with |key| being the map key. Thus, elements with the
  412. // same key will be compared even if they do not appear at the same index.
  413. // Differences are reported similarly to TreatAsSet(), except that
  414. // ReportModified() is used to report elements with the same key but
  415. // different values. Note that if an element is both moved and modified,
  416. // only ReportModified() will be called. As with TreatAsSet, if the only
  417. // differences between the compared messages is that some fields have been
  418. // moved, then the comparison returns true. See TreatAsSet for notes on
  419. // performance.
  420. //
  421. // REQUIRES: field->is_repeated()
  422. // REQUIRES: field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE
  423. // REQUIRES: key->containing_type() == field->message_type()
  424. void TreatAsMap(const FieldDescriptor* field, const FieldDescriptor* key);
  425. // Same as TreatAsMap except that this method will use multiple fields as
  426. // the key in comparison. All specified fields in 'key_fields' should be
  427. // present in the compared elements. Two elements will be treated as having
  428. // the same key iff they have the same value for every specified field. There
  429. // are two steps in the comparison process. The first one is key matching.
  430. // Every element from one message will be compared to every element from
  431. // the other message. Only fields in 'key_fields' are compared in this step
  432. // to decide if two elements have the same key. The second step is value
  433. // comparison. Those pairs of elements with the same key (with equal value
  434. // for every field in 'key_fields') will be compared in this step.
  435. // Time complexity of the first step is O(s * m * n ^ 2) where s is the
  436. // average size of the fields specified in 'key_fields', m is the number of
  437. // fields in 'key_fields' and n is the number of elements. If partial
  438. // matching is enabled, an extra O(n^3) will be incured by the maximum
  439. // matching algorithm. The second step is O(k * n) where k is the average
  440. // size of each element.
  441. void TreatAsMapWithMultipleFieldsAsKey(
  442. const FieldDescriptor* field,
  443. const std::vector<const FieldDescriptor*>& key_fields
  444. );
  445. // Same as TreatAsMapWithMultipleFieldsAsKey, except that each of the field
  446. // do not necessarily need to be a direct subfield. Each element in
  447. // key_field_paths indicate a path from the message being compared, listing
  448. // successive subfield to reach the key field.
  449. //
  450. // REQUIRES:
  451. // for key_field_path in key_field_paths:
  452. // key_field_path[0]->containing_type() == field->message_type()
  453. // for i in [0, key_field_path.size() - 1):
  454. // key_field_path[i+1]->containing_type() ==
  455. // key_field_path[i]->message_type()
  456. // key_field_path[i]->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE
  457. // !key_field_path[i]->is_repeated()
  458. void TreatAsMapWithMultipleFieldPathsAsKey(
  459. const FieldDescriptor* field,
  460. const std::vector<std::vector<const FieldDescriptor*>>& key_field_paths
  461. );
  462. // Uses a custom MapKeyComparator to determine if two elements have the same
  463. // key when comparing a repeated field as a map.
  464. // The caller is responsible to delete the key_comparator.
  465. // This method varies from TreatAsMapWithMultipleFieldsAsKey only in the
  466. // first key matching step. Rather than comparing some specified fields, it
  467. // will invoke the IsMatch method of the given 'key_comparator' to decide if
  468. // two elements have the same key.
  469. void TreatAsMapUsingKeyComparator(const FieldDescriptor* field, const MapKeyComparator* key_comparator);
  470. // Initiates and returns a new instance of MultipleFieldsMapKeyComparator.
  471. MapKeyComparator* CreateMultipleFieldsMapKeyComparator(
  472. const std::vector<std::vector<const FieldDescriptor*>>& key_field_paths
  473. );
  474. // Add a custom ignore criteria that is evaluated in addition to the
  475. // ignored fields added with IgnoreField.
  476. // Takes ownership of ignore_criteria.
  477. void AddIgnoreCriteria(IgnoreCriteria* ignore_criteria);
  478. // Indicates that any field with the given descriptor should be
  479. // ignored for the purposes of comparing two messages. This applies
  480. // to fields nested in the message structure as well as top level
  481. // ones. When the MessageDifferencer encounters an ignored field,
  482. // ReportIgnored is called on the reporter, if one is specified.
  483. //
  484. // The only place where the field's 'ignored' status is not applied is when
  485. // it is being used as a key in a field passed to TreatAsMap or is one of
  486. // the fields passed to TreatAsMapWithMultipleFieldsAsKey.
  487. // In this case it is compared in key matching but after that it's ignored
  488. // in value comparison.
  489. void IgnoreField(const FieldDescriptor* field);
  490. // Sets the field comparator used to determine differences between protocol
  491. // buffer fields. By default it's set to a DefaultFieldComparator instance.
  492. // MessageDifferencer doesn't take ownership over the passed object.
  493. // Note that this method must be called before Compare for the comparator to
  494. // be used.
  495. void set_field_comparator(FieldComparator* comparator);
  496. #ifdef PROTOBUF_FUTURE_BREAKING_CHANGES
  497. void set_field_comparator(DefaultFieldComparator* comparator);
  498. #endif // PROTOBUF_FUTURE_BREAKING_CHANGES
  499. // DEPRECATED. Pass a DefaultFieldComparator instance instead.
  500. // Sets the fraction and margin for the float comparison of a given field.
  501. // Uses MathUtil::WithinFractionOrMargin to compare the values.
  502. // NOTE: this method does nothing if differencer's field comparator has been
  503. // set to a custom object.
  504. //
  505. // REQUIRES: field->cpp_type == FieldDescriptor::CPPTYPE_DOUBLE or
  506. // field->cpp_type == FieldDescriptor::CPPTYPE_FLOAT
  507. // REQUIRES: float_comparison_ == APPROXIMATE
  508. void SetFractionAndMargin(const FieldDescriptor* field, double fraction, double margin);
  509. // Sets the type of comparison (as defined in the MessageFieldComparison
  510. // enumeration above) that is used by this differencer when determining how
  511. // to compare fields in messages.
  512. void set_message_field_comparison(MessageFieldComparison comparison);
  513. // Returns the current message field comparison used in this differencer.
  514. MessageFieldComparison message_field_comparison() const;
  515. // Tells the differencer whether or not to report matches. This method must
  516. // be called before Compare. The default for a new differencer is false.
  517. void set_report_matches(bool report_matches)
  518. {
  519. report_matches_ = report_matches;
  520. }
  521. // Tells the differencer whether or not to report moves (in a set or map
  522. // repeated field). This method must be called before Compare. The default for
  523. // a new differencer is true.
  524. void set_report_moves(bool report_moves)
  525. {
  526. report_moves_ = report_moves;
  527. }
  528. // Tells the differencer whether or not to report ignored values. This method
  529. // must be called before Compare. The default for a new differencer is true.
  530. void set_report_ignores(bool report_ignores)
  531. {
  532. report_ignores_ = report_ignores;
  533. }
  534. // Sets the scope of the comparison (as defined in the Scope enumeration
  535. // above) that is used by this differencer when determining which fields to
  536. // compare between the messages.
  537. void set_scope(Scope scope);
  538. // Returns the current scope used by this differencer.
  539. Scope scope() const;
  540. // DEPRECATED. Pass a DefaultFieldComparator instance instead.
  541. // Sets the type of comparison (as defined in the FloatComparison enumeration
  542. // above) that is used by this differencer when comparing float (and double)
  543. // fields in messages.
  544. // NOTE: this method does nothing if differencer's field comparator has been
  545. // set to a custom object.
  546. void set_float_comparison(FloatComparison comparison);
  547. // Sets the type of comparison for repeated field (as defined in the
  548. // RepeatedFieldComparison enumeration above) that is used by this
  549. // differencer when compare repeated fields in messages.
  550. void set_repeated_field_comparison(RepeatedFieldComparison comparison);
  551. // Returns the current repeated field comparison used by this differencer.
  552. RepeatedFieldComparison repeated_field_comparison() const;
  553. // Compares the two specified messages, returning true if they are the same,
  554. // false otherwise. If this method returns false, any changes between the
  555. // two messages will be reported if a Reporter was specified via
  556. // ReportDifferencesTo (see also ReportDifferencesToString).
  557. //
  558. // This method REQUIRES that the two messages have the same
  559. // Descriptor (message1.GetDescriptor() == message2.GetDescriptor()).
  560. bool Compare(const Message& message1, const Message& message2);
  561. // Same as above, except comparing only the list of fields specified by the
  562. // two vectors of FieldDescriptors.
  563. bool CompareWithFields(
  564. const Message& message1, const Message& message2, const std::vector<const FieldDescriptor*>& message1_fields, const std::vector<const FieldDescriptor*>& message2_fields
  565. );
  566. // Automatically creates a reporter that will output the differences
  567. // found (if any) to the specified output string pointer. Note that this
  568. // method must be called before Compare.
  569. void ReportDifferencesToString(std::string* output);
  570. // Tells the MessageDifferencer to report differences via the specified
  571. // reporter. Note that this method must be called before Compare for
  572. // the reporter to be used. It is the responsibility of the caller to delete
  573. // this object.
  574. // If the provided pointer equals NULL, the MessageDifferencer stops reporting
  575. // differences to any previously set reporters or output strings.
  576. void ReportDifferencesTo(Reporter* reporter);
  577. private:
  578. // Class for processing Any deserialization. This logic is used by both the
  579. // MessageDifferencer and StreamReporter classes.
  580. class UnpackAnyField
  581. {
  582. private:
  583. std::unique_ptr<DynamicMessageFactory> dynamic_message_factory_;
  584. public:
  585. UnpackAnyField() = default;
  586. ~UnpackAnyField() = default;
  587. // If "any" is of type google.protobuf.Any, extract its payload using
  588. // DynamicMessageFactory and store in "data".
  589. bool UnpackAny(const Message& any, std::unique_ptr<Message>* data);
  590. };
  591. public:
  592. // An implementation of the MessageDifferencer Reporter that outputs
  593. // any differences found in human-readable form to the supplied
  594. // ZeroCopyOutputStream or Printer. If a printer is used, the delimiter
  595. // *must* be '$'.
  596. //
  597. // WARNING: this reporter does not necessarily flush its output until it is
  598. // destroyed. As a result, it is not safe to assume the output is valid or
  599. // complete until after you destroy the reporter. For example, if you use a
  600. // StreamReporter to write to a StringOutputStream, the target string may
  601. // contain uninitialized data until the reporter is destroyed.
  602. class PROTOBUF_EXPORT StreamReporter : public Reporter
  603. {
  604. public:
  605. explicit StreamReporter(io::ZeroCopyOutputStream* output);
  606. explicit StreamReporter(io::Printer* printer); // delimiter '$'
  607. ~StreamReporter() override;
  608. // When set to true, the stream reporter will also output aggregates nodes
  609. // (i.e. messages and groups) whose subfields have been modified. When
  610. // false, will only report the individual subfields. Defaults to false.
  611. void set_report_modified_aggregates(bool report)
  612. {
  613. report_modified_aggregates_ = report;
  614. }
  615. // The following are implementations of the methods described above.
  616. void ReportAdded(const Message& message1, const Message& message2, const std::vector<SpecificField>& field_path) override;
  617. void ReportDeleted(const Message& message1, const Message& message2, const std::vector<SpecificField>& field_path) override;
  618. void ReportModified(const Message& message1, const Message& message2, const std::vector<SpecificField>& field_path) override;
  619. void ReportMoved(const Message& message1, const Message& message2, const std::vector<SpecificField>& field_path) override;
  620. void ReportMatched(const Message& message1, const Message& message2, const std::vector<SpecificField>& field_path) override;
  621. void ReportIgnored(const Message& message1, const Message& message2, const std::vector<SpecificField>& field_path) override;
  622. void ReportUnknownFieldIgnored(
  623. const Message& message1, const Message& message2, const std::vector<SpecificField>& field_path
  624. ) override;
  625. // Messages that are being compared must be provided to StreamReporter prior
  626. // to processing
  627. void SetMessages(const Message& message1, const Message& message2);
  628. protected:
  629. // Prints the specified path of fields to the buffer.
  630. virtual void PrintPath(const std::vector<SpecificField>& field_path, bool left_side);
  631. // Prints the value of fields to the buffer. left_side is true if the
  632. // given message is from the left side of the comparison, false if it
  633. // was the right. This is relevant only to decide whether to follow
  634. // unknown_field_index1 or unknown_field_index2 when an unknown field
  635. // is encountered in field_path.
  636. virtual void PrintValue(const Message& message, const std::vector<SpecificField>& field_path, bool left_side);
  637. // Prints the specified path of unknown fields to the buffer.
  638. virtual void PrintUnknownFieldValue(const UnknownField* unknown_field);
  639. // Just print a string
  640. void Print(const std::string& str);
  641. private:
  642. // helper function for PrintPath that contains logic for printing maps
  643. void PrintMapKey(bool left_side, const SpecificField& specific_field);
  644. io::Printer* printer_;
  645. bool delete_printer_;
  646. bool report_modified_aggregates_;
  647. const Message* message1_;
  648. const Message* message2_;
  649. MessageDifferencer::UnpackAnyField unpack_any_field_;
  650. GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(StreamReporter);
  651. };
  652. private:
  653. friend class SimpleFieldComparator;
  654. // A MapKeyComparator to be used in TreatAsMapUsingKeyComparator.
  655. // Implementation of this class needs to do field value comparison which
  656. // relies on some private methods of MessageDifferencer. That's why this
  657. // class is declared as a nested class of MessageDifferencer.
  658. class MultipleFieldsMapKeyComparator;
  659. // A MapKeyComparator for use with map_entries.
  660. class PROTOBUF_EXPORT MapEntryKeyComparator : public MapKeyComparator
  661. {
  662. public:
  663. explicit MapEntryKeyComparator(MessageDifferencer* message_differencer);
  664. bool IsMatch(
  665. const Message& message1, const Message& message2, const std::vector<SpecificField>& parent_fields
  666. ) const override;
  667. private:
  668. MessageDifferencer* message_differencer_;
  669. };
  670. // Returns true if field1's number() is less than field2's.
  671. static bool FieldBefore(const FieldDescriptor* field1, const FieldDescriptor* field2);
  672. // Retrieve all the set fields, including extensions.
  673. FieldDescriptorArray RetrieveFields(const Message& message, bool base_message);
  674. // Combine the two lists of fields into the combined_fields output vector.
  675. // All fields present in both lists will always be included in the combined
  676. // list. Fields only present in one of the lists will only appear in the
  677. // combined list if the corresponding fields_scope option is set to FULL.
  678. FieldDescriptorArray CombineFields(const FieldDescriptorArray& fields1, Scope fields1_scope, const FieldDescriptorArray& fields2, Scope fields2_scope);
  679. // Internal version of the Compare method which performs the actual
  680. // comparison. The parent_fields vector is a vector containing field
  681. // descriptors of all fields accessed to get to this comparison operation
  682. // (i.e. if the current message is an embedded message, the parent_fields
  683. // vector will contain the field that has this embedded message).
  684. bool Compare(const Message& message1, const Message& message2, std::vector<SpecificField>* parent_fields);
  685. // Compares all the unknown fields in two messages.
  686. bool CompareUnknownFields(const Message& message1, const Message& message2, const UnknownFieldSet&, const UnknownFieldSet&, std::vector<SpecificField>* parent_fields);
  687. // Compares the specified messages for the requested field lists. The field
  688. // lists are modified depending on comparison settings, and then passed to
  689. // CompareWithFieldsInternal.
  690. bool CompareRequestedFieldsUsingSettings(
  691. const Message& message1, const Message& message2, const FieldDescriptorArray& message1_fields, const FieldDescriptorArray& message2_fields, std::vector<SpecificField>* parent_fields
  692. );
  693. // Compares the specified messages with the specified field lists.
  694. bool CompareWithFieldsInternal(const Message& message1, const Message& message2, const FieldDescriptorArray& message1_fields, const FieldDescriptorArray& message2_fields, std::vector<SpecificField>* parent_fields);
  695. // Compares the repeated fields, and report the error.
  696. bool CompareRepeatedField(const Message& message1, const Message& message2, const FieldDescriptor* field, std::vector<SpecificField>* parent_fields);
  697. // Compares map fields, and report the error.
  698. bool CompareMapField(const Message& message1, const Message& message2, const FieldDescriptor* field, std::vector<SpecificField>* parent_fields);
  699. // Helper for CompareRepeatedField and CompareMapField: compares and reports
  700. // differences element-wise. This is the implementation for non-map fields,
  701. // and can also compare map fields by using the underlying representation.
  702. bool CompareRepeatedRep(const Message& message1, const Message& message2, const FieldDescriptor* field, std::vector<SpecificField>* parent_fields);
  703. // Helper for CompareMapField: compare the map fields using map reflection
  704. // instead of sync to repeated.
  705. bool CompareMapFieldByMapReflection(const Message& message1, const Message& message2, const FieldDescriptor* field, std::vector<SpecificField>* parent_fields, DefaultFieldComparator* comparator);
  706. // Shorthand for CompareFieldValueUsingParentFields with NULL parent_fields.
  707. bool CompareFieldValue(const Message& message1, const Message& message2, const FieldDescriptor* field, int index1, int index2);
  708. // Compares the specified field on the two messages, returning
  709. // true if they are the same, false otherwise. For repeated fields,
  710. // this method only compares the value in the specified index. This method
  711. // uses Compare functions to recurse into submessages.
  712. // The parent_fields vector is used in calls to a Reporter instance calls.
  713. // It can be NULL, in which case the MessageDifferencer will create new
  714. // list of parent messages if it needs to recursively compare the given field.
  715. // To avoid confusing users you should not set it to NULL unless you modified
  716. // Reporter to handle the change of parent_fields correctly.
  717. bool CompareFieldValueUsingParentFields(
  718. const Message& message1, const Message& message2, const FieldDescriptor* field, int index1, int index2, std::vector<SpecificField>* parent_fields
  719. );
  720. // Compares the specified field on the two messages, returning comparison
  721. // result, as returned by appropriate FieldComparator.
  722. FieldComparator::ComparisonResult GetFieldComparisonResult(
  723. const Message& message1, const Message& message2, const FieldDescriptor* field, int index1, int index2, const FieldContext* field_context
  724. );
  725. // Check if the two elements in the repeated field are match to each other.
  726. // if the key_comprator is NULL, this function returns true when the two
  727. // elements are equal.
  728. bool IsMatch(const FieldDescriptor* repeated_field, const MapKeyComparator* key_comparator, const Message* message1, const Message* message2, const std::vector<SpecificField>& parent_fields, Reporter* reporter, int index1, int index2);
  729. // Returns true when this repeated field has been configured to be treated
  730. // as a Set / SmartSet / SmartList.
  731. bool IsTreatedAsSet(const FieldDescriptor* field);
  732. bool IsTreatedAsSmartSet(const FieldDescriptor* field);
  733. bool IsTreatedAsSmartList(const FieldDescriptor* field);
  734. // When treating as SMART_LIST, it uses MatchIndicesPostProcessorForSmartList
  735. // by default to find the longest matching sequence from the first matching
  736. // element. The callback takes two vectors showing the matching indices from
  737. // the other vector, where -1 means an unmatch.
  738. void SetMatchIndicesForSmartListCallback(
  739. std::function<void(std::vector<int>*, std::vector<int>*)> callback
  740. );
  741. // Returns true when this repeated field is to be compared as a subset, ie.
  742. // has been configured to be treated as a set or map and scope is set to
  743. // PARTIAL.
  744. bool IsTreatedAsSubset(const FieldDescriptor* field);
  745. // Returns true if this field is to be ignored when this
  746. // MessageDifferencer compares messages.
  747. bool IsIgnored(const Message& message1, const Message& message2, const FieldDescriptor* field, const std::vector<SpecificField>& parent_fields);
  748. // Returns true if this unknown field is to be ignored when this
  749. // MessageDifferencer compares messages.
  750. bool IsUnknownFieldIgnored(const Message& message1, const Message& message2, const SpecificField& field, const std::vector<SpecificField>& parent_fields);
  751. // Returns MapKeyComparator* when this field has been configured to be treated
  752. // as a map or its is_map() return true. If not, returns NULL.
  753. const MapKeyComparator* GetMapKeyComparator(
  754. const FieldDescriptor* field
  755. ) const;
  756. // Attempts to match indices of a repeated field, so that the contained values
  757. // match. Clears output vectors and sets their values to indices of paired
  758. // messages, ie. if message1[0] matches message2[1], then match_list1[0] == 1
  759. // and match_list2[1] == 0. The unmatched indices are indicated by -1.
  760. // Assumes the repeated field is not treated as a simple list.
  761. // This method returns false if the match failed. However, it doesn't mean
  762. // that the comparison succeeds when this method returns true (you need to
  763. // double-check in this case).
  764. bool MatchRepeatedFieldIndices(
  765. const Message& message1, const Message& message2, const FieldDescriptor* repeated_field, const MapKeyComparator* key_comparator, const std::vector<SpecificField>& parent_fields, std::vector<int>* match_list1, std::vector<int>* match_list2
  766. );
  767. // Checks if index is equal to new_index in all the specific fields.
  768. static bool CheckPathChanged(const std::vector<SpecificField>& parent_fields);
  769. // CHECKs that the given repeated field can be compared according to
  770. // new_comparison.
  771. void CheckRepeatedFieldComparisons(
  772. const FieldDescriptor* field,
  773. const RepeatedFieldComparison& new_comparison
  774. );
  775. // Defines a map between field descriptors and their MapKeyComparators.
  776. // Used for repeated fields when they are configured as TreatAsMap.
  777. typedef std::map<const FieldDescriptor*, const MapKeyComparator*>
  778. FieldKeyComparatorMap;
  779. // Defines a set to store field descriptors. Used for repeated fields when
  780. // they are configured as TreatAsSet.
  781. typedef std::set<const FieldDescriptor*> FieldSet;
  782. typedef std::map<const FieldDescriptor*, RepeatedFieldComparison> FieldMap;
  783. Reporter* reporter_;
  784. DefaultFieldComparator default_field_comparator_;
  785. MessageFieldComparison message_field_comparison_;
  786. Scope scope_;
  787. RepeatedFieldComparison repeated_field_comparison_;
  788. FieldMap repeated_field_comparisons_;
  789. // Keeps track of MapKeyComparators that are created within
  790. // MessageDifferencer. These MapKeyComparators should be deleted
  791. // before MessageDifferencer is destroyed.
  792. // When TreatAsMap or TreatAsMapWithMultipleFieldsAsKey is called, we don't
  793. // store the supplied FieldDescriptors directly. Instead, a new
  794. // MapKeyComparator is created for comparison purpose.
  795. std::vector<MapKeyComparator*> owned_key_comparators_;
  796. FieldKeyComparatorMap map_field_key_comparator_;
  797. MapEntryKeyComparator map_entry_key_comparator_;
  798. std::vector<IgnoreCriteria*> ignore_criteria_;
  799. // Reused multiple times in RetrieveFields to avoid extra allocations
  800. std::vector<const FieldDescriptor*> tmp_message_fields_;
  801. FieldSet ignored_fields_;
  802. union
  803. {
  804. DefaultFieldComparator* default_impl;
  805. FieldComparator* base;
  806. } field_comparator_ = {&default_field_comparator_};
  807. enum
  808. {
  809. kFCDefault,
  810. kFCBase
  811. } field_comparator_kind_ = kFCDefault;
  812. bool report_matches_;
  813. bool report_moves_;
  814. bool report_ignores_;
  815. std::string* output_string_;
  816. // Callback to post-process the matched indices to support SMART_LIST.
  817. std::function<void(std::vector<int>*, std::vector<int>*)>
  818. match_indices_for_smart_list_callback_;
  819. MessageDifferencer::UnpackAnyField unpack_any_field_;
  820. GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageDifferencer);
  821. };
  822. // This class provides extra information to the FieldComparator::Compare
  823. // function.
  824. class PROTOBUF_EXPORT FieldContext
  825. {
  826. public:
  827. explicit FieldContext(
  828. std::vector<MessageDifferencer::SpecificField>* parent_fields
  829. ) :
  830. parent_fields_(parent_fields)
  831. {
  832. }
  833. std::vector<MessageDifferencer::SpecificField>* parent_fields() const
  834. {
  835. return parent_fields_;
  836. }
  837. private:
  838. std::vector<MessageDifferencer::SpecificField>* parent_fields_;
  839. };
  840. } // namespace util
  841. } // namespace protobuf
  842. } // namespace google
  843. #include <google/protobuf/port_undef.inc>
  844. #endif // GOOGLE_PROTOBUF_UTIL_MESSAGE_DIFFERENCER_H__