field_mask_util.h 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245
  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. // Defines utilities for the FieldMask well known type.
  31. #ifndef GOOGLE_PROTOBUF_UTIL_FIELD_MASK_UTIL_H__
  32. #define GOOGLE_PROTOBUF_UTIL_FIELD_MASK_UTIL_H__
  33. #include <string>
  34. #include <google/protobuf/descriptor.h>
  35. #include <google/protobuf/field_mask.pb.h>
  36. #include <google/protobuf/stubs/stringpiece.h>
  37. namespace google {
  38. namespace protobuf {
  39. namespace util {
  40. class LIBPROTOBUF_EXPORT FieldMaskUtil {
  41. typedef google::protobuf::FieldMask FieldMask;
  42. public:
  43. // Converts FieldMask to/from string, formatted by separating each path
  44. // with a comma (e.g., "foo_bar,baz.quz").
  45. static string ToString(const FieldMask& mask);
  46. static void FromString(StringPiece str, FieldMask* out);
  47. // Converts FieldMask to/from string, formatted according to proto3 JSON
  48. // spec for FieldMask (e.g., "fooBar,baz.quz"). If the field name is not
  49. // style conforming (i.e., not snake_case when converted to string, or not
  50. // camelCase when converted from string), the conversion will fail.
  51. static bool ToJsonString(const FieldMask& mask, string* out);
  52. static bool FromJsonString(StringPiece str, FieldMask* out);
  53. // Get the descriptors of the fields which the given path from the message
  54. // descriptor traverses, if field_descriptors is not null.
  55. // Return false if the path is not valid, and the content of field_descriptors
  56. // is unspecified.
  57. static bool GetFieldDescriptors(
  58. const Descriptor* descriptor, StringPiece path,
  59. std::vector<const FieldDescriptor*>* field_descriptors);
  60. // Checks whether the given path is valid for type T.
  61. template <typename T>
  62. static bool IsValidPath(StringPiece path) {
  63. return GetFieldDescriptors(T::descriptor(), path, nullptr);
  64. }
  65. // Checks whether the given FieldMask is valid for type T.
  66. template <typename T>
  67. static bool IsValidFieldMask(const FieldMask& mask) {
  68. for (int i = 0; i < mask.paths_size(); ++i) {
  69. if (!GetFieldDescriptors(T::descriptor(), mask.paths(i), nullptr))
  70. return false;
  71. }
  72. return true;
  73. }
  74. // Adds a path to FieldMask after checking whether the given path is valid.
  75. // This method check-fails if the path is not a valid path for type T.
  76. template <typename T>
  77. static void AddPathToFieldMask(StringPiece path, FieldMask* mask) {
  78. GOOGLE_CHECK(IsValidPath<T>(path));
  79. mask->add_paths(path);
  80. }
  81. // Creates a FieldMask with all fields of type T. This FieldMask only
  82. // contains fields of T but not any sub-message fields.
  83. template <typename T>
  84. static FieldMask GetFieldMaskForAllFields() {
  85. FieldMask out;
  86. InternalGetFieldMaskForAllFields(T::descriptor(), &out);
  87. return out;
  88. }
  89. template <typename T>
  90. PROTOBUF_RUNTIME_DEPRECATED("Use *out = GetFieldMaskForAllFields() instead")
  91. static void GetFieldMaskForAllFields(FieldMask* out) {
  92. InternalGetFieldMaskForAllFields(T::descriptor(), out);
  93. }
  94. // Converts a FieldMask to the canonical form. It will:
  95. // 1. Remove paths that are covered by another path. For example,
  96. // "foo.bar" is covered by "foo" and will be removed if "foo"
  97. // is also in the FieldMask.
  98. // 2. Sort all paths in alphabetical order.
  99. static void ToCanonicalForm(const FieldMask& mask, FieldMask* out);
  100. // Creates an union of two FieldMasks.
  101. static void Union(const FieldMask& mask1, const FieldMask& mask2,
  102. FieldMask* out);
  103. // Creates an intersection of two FieldMasks.
  104. static void Intersect(const FieldMask& mask1, const FieldMask& mask2,
  105. FieldMask* out);
  106. // Subtracts mask2 from mask1 base of type T.
  107. template <typename T>
  108. static void Subtract(const FieldMask& mask1, const FieldMask& mask2,
  109. FieldMask* out) {
  110. InternalSubtract(T::descriptor(), mask1, mask2, out);
  111. }
  112. // Returns true if path is covered by the given FieldMask. Note that path
  113. // "foo.bar" covers all paths like "foo.bar.baz", "foo.bar.quz.x", etc.
  114. // Also note that parent paths are not covered by explicit child path, i.e.
  115. // "foo.bar" does NOT cover "foo", even if "bar" is the only child.
  116. static bool IsPathInFieldMask(StringPiece path, const FieldMask& mask);
  117. class MergeOptions;
  118. // Merges fields specified in a FieldMask into another message. See the
  119. // comments in MergeOptions regarding compatibility with
  120. // google/protobuf/field_mask.proto
  121. static void MergeMessageTo(const Message& source, const FieldMask& mask,
  122. const MergeOptions& options, Message* destination);
  123. class TrimOptions;
  124. // Removes from 'message' any field that is not represented in the given
  125. // FieldMask. If the FieldMask is empty, does nothing.
  126. static void TrimMessage(const FieldMask& mask, Message* message);
  127. // Removes from 'message' any field that is not represented in the given
  128. // FieldMask with customized TrimOptions.
  129. // If the FieldMask is empty, does nothing.
  130. static void TrimMessage(const FieldMask& mask, Message* message,
  131. const TrimOptions& options);
  132. private:
  133. friend class SnakeCaseCamelCaseTest;
  134. // Converts a field name from snake_case to camelCase:
  135. // 1. Every character after "_" will be converted to uppercase.
  136. // 2. All "_"s are removed.
  137. // The conversion will fail if:
  138. // 1. The field name contains uppercase letters.
  139. // 2. Any character after a "_" is not a lowercase letter.
  140. // If the conversion succeeds, it's guaranteed that the resulted
  141. // camelCase name will yield the original snake_case name when
  142. // converted using CamelCaseToSnakeCase().
  143. //
  144. // Note that the input can contain characters not allowed in C identifiers.
  145. // For example, "foo_bar,baz_quz" will be converted to "fooBar,bazQuz"
  146. // successfully.
  147. static bool SnakeCaseToCamelCase(StringPiece input, string* output);
  148. // Converts a field name from camelCase to snake_case:
  149. // 1. Every uppercase letter is converted to lowercase with a additional
  150. // preceding "-".
  151. // The conversion will fail if:
  152. // 1. The field name contains "_"s.
  153. // If the conversion succeeds, it's guaranteed that the resulted
  154. // snake_case name will yield the original camelCase name when
  155. // converted using SnakeCaseToCamelCase().
  156. //
  157. // Note that the input can contain characters not allowed in C identifiers.
  158. // For example, "fooBar,bazQuz" will be converted to "foo_bar,baz_quz"
  159. // successfully.
  160. static bool CamelCaseToSnakeCase(StringPiece input, string* output);
  161. static void InternalGetFieldMaskForAllFields(const Descriptor* descriptor,
  162. FieldMask* out);
  163. static void InternalSubtract(const Descriptor* descriptor,
  164. const FieldMask& mask1, const FieldMask& mask2,
  165. FieldMask* out);
  166. };
  167. // Note that for compatibility with the defined behaviour for FieldMask in
  168. // google/protobuf/field_mask.proto, set replace_message_fields and
  169. // replace_repeated_fields to 'true'. The default options are not compatible
  170. // with google/protobuf/field_mask.proto.
  171. class LIBPROTOBUF_EXPORT FieldMaskUtil::MergeOptions {
  172. public:
  173. MergeOptions()
  174. : replace_message_fields_(false), replace_repeated_fields_(false) {}
  175. // When merging message fields, the default behavior is to merge the
  176. // content of two message fields together. If you instead want to use
  177. // the field from the source message to replace the corresponding field
  178. // in the destination message, set this flag to true. When this flag is set,
  179. // specified submessage fields that are missing in source will be cleared in
  180. // destination.
  181. void set_replace_message_fields(bool value) {
  182. replace_message_fields_ = value;
  183. }
  184. bool replace_message_fields() const { return replace_message_fields_; }
  185. // The default merging behavior will append entries from the source
  186. // repeated field to the destination repeated field. If you only want
  187. // to keep the entries from the source repeated field, set this flag
  188. // to true.
  189. void set_replace_repeated_fields(bool value) {
  190. replace_repeated_fields_ = value;
  191. }
  192. bool replace_repeated_fields() const { return replace_repeated_fields_; }
  193. private:
  194. bool replace_message_fields_;
  195. bool replace_repeated_fields_;
  196. };
  197. class LIBPROTOBUF_EXPORT FieldMaskUtil::TrimOptions {
  198. public:
  199. TrimOptions()
  200. : keep_required_fields_(false) {}
  201. // When trimming message fields, the default behavior is to trim required
  202. // fields of the present message if they are not specified in the field mask.
  203. // If you instead want to keep required fields of the present message even
  204. // they are not speicifed in the field mask, set this flag to true.
  205. void set_keep_required_fields(bool value) {
  206. keep_required_fields_ = value;
  207. }
  208. bool keep_required_fields() const { return keep_required_fields_; }
  209. private:
  210. bool keep_required_fields_;
  211. };
  212. } // namespace util
  213. } // namespace protobuf
  214. } // namespace google
  215. #endif // GOOGLE_PROTOBUF_UTIL_FIELD_MASK_UTIL_H__