field_mask_util.h 11 KB

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