1 // Protocol Buffers - Google's data interchange format 2 // Copyright 2023 Google Inc. All rights reserved. 3 // 4 // Use of this source code is governed by a BSD-style 5 // license that can be found in the LICENSE file or at 6 // https://developers.google.com/open-source/licenses/bsd 7 8 #ifndef GOOGLE_PROTOBUF_FEATURE_RESOLVER_H__ 9 #define GOOGLE_PROTOBUF_FEATURE_RESOLVER_H__ 10 11 #include <memory> 12 #include <string> 13 #include <utility> 14 #include <vector> 15 16 #include "absl/container/flat_hash_set.h" 17 #include "absl/status/status.h" 18 #include "absl/status/statusor.h" 19 #include "absl/strings/string_view.h" 20 #include "absl/types/span.h" 21 #include "google/protobuf/descriptor.h" 22 #include "google/protobuf/descriptor.pb.h" 23 #include "google/protobuf/dynamic_message.h" 24 25 // Must be included last. 26 #include "google/protobuf/port_def.inc" 27 28 namespace google { 29 namespace protobuf { 30 31 // These helpers implement the unique behaviors of edition features. For more 32 // details, see go/protobuf-editions-features. 33 class PROTOBUF_EXPORT FeatureResolver { 34 public: 35 FeatureResolver(FeatureResolver&&) = default; 36 FeatureResolver& operator=(FeatureResolver&&) = delete; 37 38 // Compiles a set of FeatureSet extensions into a mapping of edition to unique 39 // defaults. This is the most complicated part of feature resolution, and by 40 // abstracting this out into an intermediate message, we can make feature 41 // resolution significantly more portable. 42 static absl::StatusOr<FeatureSetDefaults> CompileDefaults( 43 const Descriptor* feature_set, 44 absl::Span<const FieldDescriptor* const> extensions, 45 Edition minimum_edition, Edition maximum_edition); 46 47 // Creates a new FeatureResolver at a specific edition. This calculates the 48 // default feature set for that edition, using the output of CompileDefaults. 49 static absl::StatusOr<FeatureResolver> Create( 50 Edition edition, const FeatureSetDefaults& defaults); 51 52 // Creates a new feature set using inheritance and default behavior. This is 53 // designed to be called recursively, and the parent feature set is expected 54 // to be a fully merged one. The returned FeatureSet will be fully resolved 55 // for any extensions that were used to construct the defaults. 56 absl::StatusOr<FeatureSet> MergeFeatures( 57 const FeatureSet& merged_parent, const FeatureSet& unmerged_child) const; 58 59 // Validates an unresolved FeatureSet object to make sure they obey the 60 // lifetime requirements. This needs to run *within* the pool being built, so 61 // that the descriptors of any feature extensions are known and can be 62 // validated. `pool_descriptor` should point to the FeatureSet descriptor 63 // inside the pool, or nullptr if one doesn't exist, 64 // 65 // This will return error messages for any explicitly set features used before 66 // their introduction or after their removal. Warnings will be included for 67 // any explicitly set features that have been deprecated. 68 struct ValidationResults { 69 std::vector<std::string> errors; 70 std::vector<std::string> warnings; 71 }; 72 static ValidationResults ValidateFeatureLifetimes( 73 Edition edition, const FeatureSet& features, 74 const Descriptor* pool_descriptor); 75 76 private: FeatureResolver(FeatureSet defaults)77 explicit FeatureResolver(FeatureSet defaults) 78 : defaults_(std::move(defaults)) {} 79 80 FeatureSet defaults_; 81 }; 82 83 } // namespace protobuf 84 } // namespace google 85 86 #endif // GOOGLE_PROTOBUF_FEATURE_RESOLVER_H__ 87 88 #include "google/protobuf/port_undef.inc" 89