From 80a9b8a3bc5f8f137059352322ac379b9ece914f Mon Sep 17 00:00:00 2001 From: Justin King Date: Mon, 28 Sep 2026 17:40:08 -0700 Subject: [PATCH] Cleanup `AttributeQualifier` and `AttributeQualifierPattern` and introduce `AttributeQualifierView` PiperOrigin-RevId: 989943852 --- base/BUILD | 16 +- base/attribute.cc | 486 ++++++++++----- base/attribute.h | 789 +++++++++++++++++++++--- base/attribute_test.cc | 80 +++ eval/public/cel_attribute_test.cc | 8 +- extensions/protobuf/internal/qualify.cc | 6 +- 6 files changed, 1152 insertions(+), 233 deletions(-) create mode 100644 base/attribute_test.cc diff --git a/base/BUILD b/base/BUILD index 600889182..739fc96de 100644 --- a/base/BUILD +++ b/base/BUILD @@ -38,12 +38,24 @@ cc_library( "@com_google_absl//absl/base:no_destructor", "@com_google_absl//absl/base:nullability", "@com_google_absl//absl/container:btree", + "@com_google_absl//absl/functional:overload", + "@com_google_absl//absl/log:absl_check", + "@com_google_absl//absl/meta:type_traits", "@com_google_absl//absl/status", "@com_google_absl//absl/status:statusor", "@com_google_absl//absl/strings", - "@com_google_absl//absl/types:optional", + "@com_google_absl//absl/types:optional_ref", "@com_google_absl//absl/types:span", - "@com_google_absl//absl/types:variant", + ], +) + +cc_test( + name = "attribute_test", + srcs = ["attribute_test.cc"], + deps = [ + ":attributes", + "//internal:testing", + "@com_google_absl//absl/strings:string_view", ], ) diff --git a/base/attribute.cc b/base/attribute.cc index f750a1850..97fa75fa7 100644 --- a/base/attribute.cc +++ b/base/attribute.cc @@ -17,13 +17,17 @@ #include #include #include +#include +#include #include "absl/base/macros.h" #include "absl/base/nullability.h" +#include "absl/log/absl_check.h" +#include "absl/meta/type_traits.h" #include "absl/status/status.h" #include "absl/status/statusor.h" #include "absl/strings/str_cat.h" -#include "absl/types/variant.h" +#include "absl/strings/string_view.h" #include "base/kind.h" #include "internal/status_macros.h" @@ -36,14 +40,10 @@ class AttributeStringPrinter { public: // String representation for the given qualifier is appended to output. // output must be non-null. - explicit AttributeStringPrinter(std::string* output, Kind type) - : output_(*output), type_(type) {} + explicit AttributeStringPrinter(std::string* output) : output_(*output) {} - absl::Status operator()(const Kind& ignored) const { - // Attributes are represented as a variant, with illegal attribute - // qualifiers represented with their type as the first alternative. - return absl::InvalidArgumentError( - absl::StrCat("Unsupported attribute qualifier ", KindToString(type_))); + absl::Status operator()(std::monostate) const { + return absl::InvalidArgumentError("bad attribute qualifier"); } absl::Status operator()(int64_t index) { @@ -68,22 +68,19 @@ class AttributeStringPrinter { private: std::string& output_; - Kind type_; }; // Visitor for appending string representation for different qualifier kinds. class AttributeQualifierStringPrinter { public: // String representation for the given qualifier is appended to output. - explicit AttributeQualifierStringPrinter(std::string* absl_nonnull output, - Kind type) - : output_(*output), type_(type) {} + explicit AttributeQualifierStringPrinter(std::string* absl_nonnull output) + : output_(*output) {} - absl::Status operator()(const Kind& ignored) const { + absl::Status operator()(std::monostate) const { // Attributes are represented as a variant, with illegal attribute // qualifiers represented with their type as the first alternative. - return absl::InvalidArgumentError( - absl::StrCat("Unsupported attribute qualifier ", KindToString(type_))); + return absl::InvalidArgumentError("bad attribute qualifier"); } absl::Status operator()(int64_t index) { @@ -108,140 +105,24 @@ class AttributeQualifierStringPrinter { private: std::string& output_; - Kind type_; }; struct AttributeQualifierTypeVisitor final { - Kind operator()(const Kind& type) const { return type; } - - Kind operator()(int64_t ignored) const { - static_cast(ignored); - return Kind::kInt64; - } - - Kind operator()(uint64_t ignored) const { - static_cast(ignored); - return Kind::kUint64; - } - - Kind operator()(const std::string& ignored) const { - static_cast(ignored); - return Kind::kString; - } - - Kind operator()(bool ignored) const { - static_cast(ignored); - return Kind::kBool; - } -}; - -struct AttributeQualifierTypeComparator final { - const Kind lhs; - - bool operator()(const Kind& rhs) const { - return static_cast(lhs) < static_cast(rhs); - } - - bool operator()(int64_t) const { return false; } - - bool operator()(uint64_t other) const { return false; } - - bool operator()(const std::string&) const { return false; } - - bool operator()(bool other) const { return false; } -}; - -struct AttributeQualifierIntComparator final { - const int64_t lhs; - - bool operator()(const Kind&) const { return true; } - - bool operator()(int64_t rhs) const { return lhs < rhs; } + Kind operator()(std::monostate) const { return Kind::kNull; } - bool operator()(uint64_t) const { return true; } + Kind operator()(int64_t) const { return Kind::kInt64; } - bool operator()(const std::string&) const { return true; } + Kind operator()(uint64_t) const { return Kind::kUint64; } - bool operator()(bool) const { return false; } -}; - -struct AttributeQualifierUintComparator final { - const uint64_t lhs; - - bool operator()(const Kind&) const { return true; } - - bool operator()(int64_t) const { return false; } - - bool operator()(uint64_t rhs) const { return lhs < rhs; } - - bool operator()(const std::string&) const { return true; } - - bool operator()(bool) const { return false; } -}; - -struct AttributeQualifierStringComparator final { - const std::string& lhs; - - bool operator()(const Kind&) const { return true; } - - bool operator()(int64_t) const { return false; } - - bool operator()(uint64_t) const { return false; } + Kind operator()(const std::string&) const { return Kind::kString; } - bool operator()(const std::string& rhs) const { return lhs < rhs; } - - bool operator()(bool) const { return false; } -}; - -struct AttributeQualifierBoolComparator final { - const bool lhs; - - bool operator()(const Kind&) const { return true; } - - bool operator()(int64_t) const { return true; } - - bool operator()(uint64_t) const { return true; } - - bool operator()(const std::string&) const { return true; } - - bool operator()(bool rhs) const { return lhs < rhs; } + Kind operator()(bool) const { return Kind::kBool; } }; } // namespace -struct AttributeQualifier::ComparatorVisitor final { - const AttributeQualifier::Variant& rhs; - - bool operator()(const Kind& lhs) const { - return absl::visit(AttributeQualifierTypeComparator{lhs}, rhs); - } - - bool operator()(int64_t lhs) const { - return absl::visit(AttributeQualifierIntComparator{lhs}, rhs); - } - - bool operator()(uint64_t lhs) const { - return absl::visit(AttributeQualifierUintComparator{lhs}, rhs); - } - - bool operator()(const std::string& lhs) const { - return absl::visit(AttributeQualifierStringComparator{lhs}, rhs); - } - - bool operator()(bool lhs) const { - return absl::visit(AttributeQualifierBoolComparator{lhs}, rhs); - } -}; - Kind AttributeQualifier::kind() const { - return absl::visit(AttributeQualifierTypeVisitor{}, value_); -} - -bool AttributeQualifier::operator<(const AttributeQualifier& other) const { - // The order is not publicly documented because it is subject to change. - // Currently we sort in the following order, with each type being sorted - // against itself: bool, int, uint, string, type. - return absl::visit(ComparatorVisitor{other.value_}, value_); + return std::visit(AttributeQualifierTypeVisitor{}, value_); } bool Attribute::operator==(const Attribute& other) const { @@ -296,7 +177,7 @@ bool Attribute::operator<(const Attribute& other) const { return false; } -const absl::StatusOr Attribute::AsString() const { +absl::StatusOr Attribute::AsString() const { if (variable_name().empty()) { return absl::InvalidArgumentError( "Only ident rooted attributes are supported."); @@ -305,26 +186,335 @@ const absl::StatusOr Attribute::AsString() const { std::string result = std::string(variable_name()); for (const auto& qualifier : qualifier_path()) { - CEL_RETURN_IF_ERROR(absl::visit( - AttributeStringPrinter(&result, qualifier.kind()), qualifier.value_)); + CEL_RETURN_IF_ERROR(std::visit(AttributeStringPrinter(&result), + common_internal::AsVariant(qualifier))); } return result; } +std::string AttributeQualifier::ToString() const { + std::string result; + absl::Status status = + std::visit(AttributeQualifierStringPrinter{&result}, value_); + ABSL_DCHECK_OK(status) << "bad attribute qualifier"; + status.IgnoreError(); + return result; +} + bool AttributeQualifier::IsMatch(const AttributeQualifier& other) const { - if (absl::holds_alternative(value_) || - absl::holds_alternative(other.value_)) { + ABSL_DCHECK(*this) << "bad attribute qualifier"; + ABSL_DCHECK(other) << "bad attribute qualifier"; + if (std::holds_alternative(value_) || + std::holds_alternative(other.value_)) { return false; } - return value_ == other.value_; + return *this == other; } -absl::StatusOr AttributeQualifier::AsString() const { - std::string result; - CEL_RETURN_IF_ERROR( - absl::visit(AttributeQualifierStringPrinter(&result, kind()), value_)); - return result; +bool AttributeQualifier::IsMatch(absl::string_view other_key) const { + ABSL_DCHECK(*this) << "bad attribute qualifier"; + if (auto string = AsString(); string.has_value()) { + return *string == other_key; + } + return false; +} + +bool AttributeQualifierPattern::IsMatch( + const AttributeQualifier& qualifier) const { + ABSL_DCHECK(*this) << "bad attribute qualifier pattern"; + ABSL_DCHECK(qualifier) << "bad attribute qualifier"; + if (!*this || !qualifier) { + return false; + } + if (IsWildcard()) { + return true; + } + return *this == qualifier; +} + +bool AttributeQualifierPattern::IsMatch(absl::string_view other_key) const { + ABSL_DCHECK(*this) << "bad attribute qualifier pattern"; + if (IsWildcard()) { + return true; + } + if (auto string = AsString(); string.has_value()) { + return *string == other_key; + } + return false; +} + +namespace { + +struct AttributeQualifierEqualTo { + bool operator()(const std::monostate&, const std::monostate&) const { + return false; + } + + template + std::enable_if_t, std::monostate>, + bool> + operator()(const std::monostate&, const T&) const { + return false; + } + + template + std::enable_if_t, std::monostate>, + bool> + operator()(const T&, const std::monostate&) const { + return false; + } + + bool operator()(bool lhs, bool rhs) const { return lhs == rhs; } + + bool operator()(bool, int64_t) const { return false; } + + bool operator()(bool, uint64_t) const { return false; } + + bool operator()(bool, absl::string_view) const { return false; } + + bool operator()(int64_t, bool) const { return false; } + + bool operator()(int64_t lhs, int64_t rhs) const { return lhs == rhs; } + + bool operator()(int64_t, uint64_t) const { return false; } + + bool operator()(int64_t, absl::string_view) const { return false; } + + bool operator()(uint64_t, bool) const { return false; } + + bool operator()(uint64_t, int64_t) const { return false; } + + bool operator()(uint64_t lhs, uint64_t rhs) const { return lhs == rhs; } + + bool operator()(uint64_t, absl::string_view) const { return false; } + + bool operator()(absl::string_view, bool) const { return false; } + + bool operator()(absl::string_view, int64_t) const { return false; } + + bool operator()(absl::string_view, uint64_t) const { return false; } + + bool operator()(absl::string_view lhs, absl::string_view rhs) const { + return lhs == rhs; + } + + bool operator()(const common_internal::WildcardType&, + const common_internal::WildcardType&) const { + return true; + } + + template + std::enable_if_t< + !std::is_same_v, common_internal::WildcardType> && + !std::is_same_v, std::monostate>, + bool> + operator()(const common_internal::WildcardType&, const T&) const { + return false; + } + + template + std::enable_if_t< + !std::is_same_v, common_internal::WildcardType> && + !std::is_same_v, std::monostate>, + bool> + operator()(const T&, const common_internal::WildcardType&) const { + return false; + } +}; + +struct AttributeQualifierLess { + bool operator()(const std::monostate&, const std::monostate&) const { + return false; + } + + template + std::enable_if_t, std::monostate>, + bool> + operator()(const std::monostate&, const T&) const { + return true; + } + + template + std::enable_if_t, std::monostate>, + bool> + operator()(const T&, const std::monostate&) const { + return false; + } + + bool operator()(bool lhs, bool rhs) const { return lhs < rhs; } + + bool operator()(bool, int64_t) const { return false; } + + bool operator()(bool, uint64_t) const { return false; } + + bool operator()(bool, absl::string_view) const { return false; } + + bool operator()(int64_t, bool) const { return true; } + + bool operator()(int64_t lhs, int64_t rhs) const { return lhs < rhs; } + + bool operator()(int64_t, uint64_t) const { return true; } + + bool operator()(int64_t, absl::string_view) const { return true; } + + bool operator()(uint64_t, bool) const { return true; } + + bool operator()(uint64_t, int64_t) const { return false; } + + bool operator()(uint64_t lhs, uint64_t rhs) const { return lhs < rhs; } + + bool operator()(uint64_t, absl::string_view) const { return true; } + + bool operator()(absl::string_view, bool) const { return true; } + + bool operator()(absl::string_view, int64_t) const { return false; } + + bool operator()(absl::string_view, uint64_t) const { return false; } + + bool operator()(absl::string_view lhs, absl::string_view rhs) const { + return lhs < rhs; + } + + bool operator()(const common_internal::WildcardType&, + const common_internal::WildcardType&) const { + return false; + } + + template + std::enable_if_t< + !std::is_same_v, common_internal::WildcardType> && + !std::is_same_v, std::monostate>, + bool> + operator()(const common_internal::WildcardType&, const T&) const { + return false; + } + + template + std::enable_if_t< + !std::is_same_v, common_internal::WildcardType> && + !std::is_same_v, std::monostate>, + bool> + operator()(const T&, const common_internal::WildcardType&) const { + return true; + } +}; + +} // namespace + +bool operator==(const AttributeQualifier& lhs, const AttributeQualifier& rhs) { + return std::visit(AttributeQualifierEqualTo{}, + common_internal::AsVariant(lhs), + common_internal::AsVariant(rhs)); +} + +bool operator==(const AttributeQualifierView& lhs, + const AttributeQualifierView& rhs) { + return std::visit(AttributeQualifierEqualTo{}, + common_internal::AsVariant(lhs), + common_internal::AsVariant(rhs)); +} + +bool operator==(const AttributeQualifierPattern& lhs, + const AttributeQualifierPattern& rhs) { + return std::visit(AttributeQualifierEqualTo{}, + common_internal::AsVariant(lhs), + common_internal::AsVariant(rhs)); +} + +bool operator==(const AttributeQualifier& lhs, + const AttributeQualifierView& rhs) { + return std::visit(AttributeQualifierEqualTo{}, + common_internal::AsVariant(lhs), + common_internal::AsVariant(rhs)); +} + +bool operator==(const AttributeQualifier& lhs, + const AttributeQualifierPattern& rhs) { + return std::visit(AttributeQualifierEqualTo{}, + common_internal::AsVariant(lhs), + common_internal::AsVariant(rhs)); +} + +bool operator==(const AttributeQualifierView& lhs, + const AttributeQualifier& rhs) { + return std::visit(AttributeQualifierEqualTo{}, + common_internal::AsVariant(lhs), + common_internal::AsVariant(rhs)); +} + +bool operator==(const AttributeQualifierView& lhs, + const AttributeQualifierPattern& rhs) { + return std::visit(AttributeQualifierEqualTo{}, + common_internal::AsVariant(lhs), + common_internal::AsVariant(rhs)); +} + +bool operator==(const AttributeQualifierPattern& lhs, + const AttributeQualifier& rhs) { + return std::visit(AttributeQualifierEqualTo{}, + common_internal::AsVariant(lhs), + common_internal::AsVariant(rhs)); +} + +bool operator==(const AttributeQualifierPattern& lhs, + const AttributeQualifierView& rhs) { + return std::visit(AttributeQualifierEqualTo{}, + common_internal::AsVariant(lhs), + common_internal::AsVariant(rhs)); +} + +bool operator<(const AttributeQualifier& lhs, const AttributeQualifier& rhs) { + return std::visit(AttributeQualifierLess{}, common_internal::AsVariant(lhs), + common_internal::AsVariant(rhs)); +} + +bool operator<(const AttributeQualifierView& lhs, + const AttributeQualifierView& rhs) { + return std::visit(AttributeQualifierLess{}, common_internal::AsVariant(lhs), + common_internal::AsVariant(rhs)); +} + +bool operator<(const AttributeQualifierPattern& lhs, + const AttributeQualifierPattern& rhs) { + return std::visit(AttributeQualifierLess{}, common_internal::AsVariant(lhs), + common_internal::AsVariant(rhs)); +} + +bool operator<(const AttributeQualifier& lhs, + const AttributeQualifierView& rhs) { + return std::visit(AttributeQualifierLess{}, common_internal::AsVariant(lhs), + common_internal::AsVariant(rhs)); +} + +bool operator<(const AttributeQualifier& lhs, + const AttributeQualifierPattern& rhs) { + return std::visit(AttributeQualifierLess{}, common_internal::AsVariant(lhs), + common_internal::AsVariant(rhs)); +} + +bool operator<(const AttributeQualifierView& lhs, + const AttributeQualifier& rhs) { + return std::visit(AttributeQualifierLess{}, common_internal::AsVariant(lhs), + common_internal::AsVariant(rhs)); +} + +bool operator<(const AttributeQualifierView& lhs, + const AttributeQualifierPattern& rhs) { + return std::visit(AttributeQualifierLess{}, common_internal::AsVariant(lhs), + common_internal::AsVariant(rhs)); +} + +bool operator<(const AttributeQualifierPattern& lhs, + const AttributeQualifier& rhs) { + return std::visit(AttributeQualifierLess{}, common_internal::AsVariant(lhs), + common_internal::AsVariant(rhs)); +} + +bool operator<(const AttributeQualifierPattern& lhs, + const AttributeQualifierView& rhs) { + return std::visit(AttributeQualifierLess{}, common_internal::AsVariant(lhs), + common_internal::AsVariant(rhs)); } } // namespace cel diff --git a/base/attribute.h b/base/attribute.h index 69dcaf161..a0877fc96 100644 --- a/base/attribute.h +++ b/base/attribute.h @@ -15,47 +15,95 @@ #ifndef THIRD_PARTY_CEL_CPP_BASE_ATTRIBUTE_H_ #define THIRD_PARTY_CEL_CPP_BASE_ATTRIBUTE_H_ +#include #include #include #include #include #include +#include #include +#include "absl/base/attributes.h" +#include "absl/base/macros.h" +#include "absl/functional/overload.h" +#include "absl/log/absl_check.h" #include "absl/status/statusor.h" #include "absl/strings/string_view.h" -#include "absl/types/optional.h" +#include "absl/types/optional_ref.h" #include "absl/types/span.h" -#include "absl/types/variant.h" #include "base/kind.h" namespace cel { -// AttributeQualifier represents a segment in -// attribute resolutuion path. A segment can be qualified by values of +namespace common_internal { +class AttributeMatcherNode; +struct WildcardType {}; +using AttributeQualifierVariant = + std::variant; +using AttributeQualifierPatternVariant = + std::variant; +using AttributeQualifierViewVariant = + std::variant; +} // namespace common_internal + +class AttributeQualifier; +class AttributeQualifierPattern; +class Attribute; +class AttributePattern; +class AttributeQualifierView; + +namespace common_internal { +[[nodiscard]] +const AttributeQualifierVariant& AsVariant( + const AttributeQualifier& qualifier ABSL_ATTRIBUTE_LIFETIME_BOUND); +[[nodiscard]] +AttributeQualifierVariant&& AsVariant( + AttributeQualifier&& qualifier ABSL_ATTRIBUTE_LIFETIME_BOUND); +[[nodiscard]] +const AttributeQualifierPatternVariant& AsVariant( + const AttributeQualifierPattern& qualifier ABSL_ATTRIBUTE_LIFETIME_BOUND); +[[nodiscard]] +AttributeQualifierPatternVariant&& AsVariant( + AttributeQualifierPattern&& qualifier ABSL_ATTRIBUTE_LIFETIME_BOUND); +[[nodiscard]] +const AttributeQualifierViewVariant& AsVariant( + const AttributeQualifierView& qualifier ABSL_ATTRIBUTE_LIFETIME_BOUND); +[[nodiscard]] +AttributeQualifierViewVariant&& AsVariant( + AttributeQualifierView&& qualifier ABSL_ATTRIBUTE_LIFETIME_BOUND); +} // namespace common_internal + +// AttributeQualifier represents a segment in the +// attribute resolution path. A segment can be qualified by values of // following types: string/int64_t/uint64_t/bool. -class AttributeQualifier final { - private: - struct ComparatorVisitor; - - using Variant = absl::variant; - +class AttributeQualifier { public: static AttributeQualifier OfInt(int64_t value) { - return AttributeQualifier(absl::in_place_type, std::move(value)); + return AttributeQualifier(std::in_place_type, std::move(value)); } static AttributeQualifier OfUint(uint64_t value) { - return AttributeQualifier(absl::in_place_type, std::move(value)); + return AttributeQualifier(std::in_place_type, std::move(value)); + } + + static AttributeQualifier OfString(const char* value) { + return OfString(absl::string_view(value)); } static AttributeQualifier OfString(std::string value) { - return AttributeQualifier(absl::in_place_type, + return AttributeQualifier(std::in_place_type, std::move(value)); } + static AttributeQualifier OfString(absl::string_view value) { + return AttributeQualifier(std::in_place_type, + std::string(value)); + } + static AttributeQualifier OfBool(bool value) { - return AttributeQualifier(absl::in_place_type, std::move(value)); + return AttributeQualifier(std::in_place_type, std::move(value)); } AttributeQualifier() = default; @@ -68,55 +116,126 @@ class AttributeQualifier final { Kind kind() const; - // Family of Get... methods. Return values if requested type matches the - // stored one. - absl::optional GetInt64Key() const { - return absl::holds_alternative(value_) - ? absl::optional(absl::get<1>(value_)) - : absl::nullopt; + [[nodiscard]] + std::string ToString() const; + + ABSL_DEPRECATE_AND_INLINE() + std::optional GetInt64Key() const { return AsInt(); } + + ABSL_DEPRECATE_AND_INLINE() + std::optional GetUint64Key() const { return AsUint(); } + + ABSL_DEPRECATED("Use AsString") + std::optional GetStringKey() const { + if (auto string = AsString(); string.has_value()) { + return *string; + } + return std::nullopt; } - absl::optional GetUint64Key() const { - return absl::holds_alternative(value_) - ? absl::optional(absl::get<2>(value_)) - : absl::nullopt; + ABSL_DEPRECATE_AND_INLINE() + std::optional GetBoolKey() const { return AsBool(); } + + explicit operator bool() const { + return !std::holds_alternative(value_); } - absl::optional GetStringKey() const { - return absl::holds_alternative(value_) - ? absl::optional(absl::get<3>(value_)) - : absl::nullopt; + [[nodiscard]] + bool IsBool() const { + return std::holds_alternative(value_); } - absl::optional GetBoolKey() const { - return absl::holds_alternative(value_) - ? absl::optional(absl::get<4>(value_)) - : absl::nullopt; + [[nodiscard]] + bool IsInt() const { + return std::holds_alternative(value_); } - bool operator==(const AttributeQualifier& other) const { - return IsMatch(other); + [[nodiscard]] + bool IsUint() const { + return std::holds_alternative(value_); } - bool operator<(const AttributeQualifier& other) const; + [[nodiscard]] + bool IsString() const { + return std::holds_alternative(value_); + } - bool IsMatch(absl::string_view other_key) const { - absl::optional key = GetStringKey(); - return (key.has_value() && key.value() == other_key); + [[nodiscard]] + bool GetBool() const { + ABSL_DCHECK(IsBool()); + return std::get(value_); } - absl::StatusOr AsString() const; + [[nodiscard]] + int64_t GetInt() const { + ABSL_DCHECK(IsInt()); + return std::get(value_); + } - private: - friend class Attribute; - friend struct ComparatorVisitor; + [[nodiscard]] + uint64_t GetUint() const { + ABSL_DCHECK(IsUint()); + return std::get(value_); + } - template - AttributeQualifier(absl::in_place_type_t in_place_type, T&& value) - : value_(in_place_type, std::forward(value)) {} + [[nodiscard]] + const std::string& GetString() const { + ABSL_DCHECK(IsString()); + return std::get(value_); + } + + [[nodiscard]] + std::optional AsBool() const { + if (const auto* value = std::get_if(&value_); value != nullptr) { + return *value; + } + return std::nullopt; + } + [[nodiscard]] + std::optional AsInt() const { + if (const auto* value = std::get_if(&value_); value != nullptr) { + return *value; + } + return std::nullopt; + } + + [[nodiscard]] + std::optional AsUint() const { + if (const auto* value = std::get_if(&value_); value != nullptr) { + return *value; + } + return std::nullopt; + } + + [[nodiscard]] + absl::optional_ref AsString() const { + if (const auto* value = std::get_if(&value_); + value != nullptr) { + return *value; + } + return std::nullopt; + } + + [[nodiscard]] bool IsMatch(const AttributeQualifier& other) const; + [[nodiscard]] + bool IsMatch(absl::string_view other_key) const; + + private: + friend const common_internal::AttributeQualifierVariant& + common_internal::AsVariant(const AttributeQualifier& qualifier); + friend common_internal::AttributeQualifierVariant&& + common_internal::AsVariant(AttributeQualifier&& qualifier); + + template + explicit AttributeQualifier(std::in_place_type_t in_place_type, + Args&&... args) + : value_(in_place_type, std::forward(args)...) {} + + using Variant = common_internal::AttributeQualifierVariant; + // The previous implementation of Attribute preserved all value // instances, regardless of whether they are supported in this context or not. // We represented unsupported types by using the first alternative and thus @@ -124,58 +243,580 @@ class AttributeQualifier final { Variant value_; }; -// AttributeQualifierPattern matches a segment in -// attribute resolutuion path. AttributeQualifierPattern is capable of -// matching path elements of types string/int64/uint64/bool. -class AttributeQualifierPattern final { +class AttributeQualifierView { + public: + static AttributeQualifierView OfInt(int64_t value) { + return AttributeQualifierView(std::in_place_type, + std::move(value)); + } + + static AttributeQualifierView OfUint(uint64_t value) { + return AttributeQualifierView(std::in_place_type, + std::move(value)); + } + + static AttributeQualifierView OfString(const char* value) { + return OfString(absl::string_view(value)); + } + + static AttributeQualifierView OfString(absl::string_view value) { + return AttributeQualifierView(std::in_place_type, + std::move(value)); + } + + static AttributeQualifierView OfString(std::string&&) = delete; + + static AttributeQualifierView OfBool(bool value) { + return AttributeQualifierView(std::in_place_type, std::move(value)); + } + + AttributeQualifierView() = default; + AttributeQualifierView(const AttributeQualifierView&) = default; + AttributeQualifierView& operator=(const AttributeQualifierView&) = default; + + // NOLINTNEXTLINE(google-explicit-constructor) + AttributeQualifierView( + const AttributeQualifier& other ABSL_ATTRIBUTE_LIFETIME_BOUND) + : value_(std::visit( + absl::Overload( + [](std::monostate value) -> Variant { + return Variant(std::in_place_type, value); + }, + [](bool value) -> Variant { + return Variant(std::in_place_type, value); + }, + [](int64_t value) -> Variant { + return Variant(std::in_place_type, value); + }, + [](uint64_t value) -> Variant { + return Variant(std::in_place_type, value); + }, + [](const std::string& value) -> Variant { + return Variant(std::in_place_type, value); + }), + common_internal::AsVariant(other))) {} + + // NOLINTNEXTLINE(google-explicit-constructor) + AttributeQualifierView& operator=( + const AttributeQualifier& other ABSL_ATTRIBUTE_LIFETIME_BOUND) { + return *this = AttributeQualifierView(other); + } + + AttributeQualifierView& operator=(AttributeQualifier&&) = delete; + + ABSL_DEPRECATE_AND_INLINE() + std::optional GetInt64Key() const { return AsInt(); } + + ABSL_DEPRECATE_AND_INLINE() + std::optional GetUint64Key() const { return AsUint(); } + + ABSL_DEPRECATE_AND_INLINE() + std::optional GetStringKey() const { return AsString(); } + + ABSL_DEPRECATE_AND_INLINE() + std::optional GetBoolKey() const { return AsBool(); } + + [[nodiscard]] + bool IsBool() const { + return std::holds_alternative(value_); + } + + [[nodiscard]] + bool IsInt() const { + return std::holds_alternative(value_); + } + + [[nodiscard]] + bool IsUint() const { + return std::holds_alternative(value_); + } + + [[nodiscard]] + bool IsString() const { + return std::holds_alternative(value_); + } + + [[nodiscard]] + bool GetBool() const { + ABSL_DCHECK(IsBool()); + return std::get(value_); + } + + [[nodiscard]] + int64_t GetInt() const { + ABSL_DCHECK(IsInt()); + return std::get(value_); + } + + [[nodiscard]] + uint64_t GetUint() const { + ABSL_DCHECK(IsUint()); + return std::get(value_); + } + + [[nodiscard]] + absl::string_view GetString() const { + ABSL_DCHECK(IsString()); + return std::get(value_); + } + + [[nodiscard]] + std::optional AsBool() const { + if (const auto* value = std::get_if(&value_); value != nullptr) { + return *value; + } + return std::nullopt; + } + + [[nodiscard]] + std::optional AsInt() const { + if (const auto* value = std::get_if(&value_); value != nullptr) { + return *value; + } + return std::nullopt; + } + + [[nodiscard]] + std::optional AsUint() const { + if (const auto* value = std::get_if(&value_); value != nullptr) { + return *value; + } + return std::nullopt; + } + + [[nodiscard]] + std::optional AsString() const { + if (const auto* value = std::get_if(&value_); + value != nullptr) { + return *value; + } + return std::nullopt; + } + private: - // Qualifier value. If not set, treated as wildcard. - std::optional value_; + friend const common_internal::AttributeQualifierViewVariant& + common_internal::AsVariant(const AttributeQualifierView& qualifier); + friend common_internal::AttributeQualifierViewVariant&& + common_internal::AsVariant(AttributeQualifierView&& qualifier); - explicit AttributeQualifierPattern(std::optional value) - : value_(std::move(value)) {} + using Variant = common_internal::AttributeQualifierViewVariant; + template + AttributeQualifierView(std::in_place_type_t in_place_type, T&& value) + : value_(in_place_type, std::forward(value)) {} + + Variant value_; +}; + +// AttributeQualifierPattern matches a segment in +// attribute resolution path. AttributeQualifierPattern is capable of +// matching path elements of types string/int64/uint64/bool. +class AttributeQualifierPattern { public: static AttributeQualifierPattern OfInt(int64_t value) { - return AttributeQualifierPattern(AttributeQualifier::OfInt(value)); + return AttributeQualifierPattern(std::in_place_type, value); } static AttributeQualifierPattern OfUint(uint64_t value) { - return AttributeQualifierPattern(AttributeQualifier::OfUint(value)); + return AttributeQualifierPattern(std::in_place_type, value); + } + + static AttributeQualifierPattern OfString(const char* value) { + return OfString(absl::string_view(value)); } static AttributeQualifierPattern OfString(std::string value) { - return AttributeQualifierPattern( - AttributeQualifier::OfString(std::move(value))); + return AttributeQualifierPattern(std::in_place_type, + std::move(value)); + } + + static AttributeQualifierPattern OfString(absl::string_view value) { + return AttributeQualifierPattern(std::in_place_type, + std::string(value)); } static AttributeQualifierPattern OfBool(bool value) { - return AttributeQualifierPattern(AttributeQualifier::OfBool(value)); + return AttributeQualifierPattern(std::in_place_type, value); + } + + ABSL_DEPRECATE_AND_INLINE() + static AttributeQualifierPattern CreateWildcard() { return Wildcard(); } + + static AttributeQualifierPattern Wildcard() { + return AttributeQualifierPattern(std::in_place_type); + } + + // NOLINTNEXTLINE(google-explicit-constructor) + AttributeQualifierPattern(const AttributeQualifier& value) + : value_(std::visit( + absl::Overload( + [](std::monostate value) -> Variant { + return Variant(std::in_place_type, value); + }, + [](bool value) -> Variant { + return Variant(std::in_place_type, value); + }, + [](int64_t value) -> Variant { + return Variant(std::in_place_type, value); + }, + [](uint64_t value) -> Variant { + return Variant(std::in_place_type, value); + }, + [](const std::string& value) -> Variant { + return Variant(std::in_place_type, value); + }), + common_internal::AsVariant(value))) {} + + // NOLINTNEXTLINE(google-explicit-constructor) + AttributeQualifierPattern(AttributeQualifier&& value) + : value_(std::visit( + absl::Overload( + [](std::monostate value) -> Variant { + return Variant(std::in_place_type, value); + }, + [](bool value) -> Variant { + return Variant(std::in_place_type, value); + }, + [](int64_t value) -> Variant { + return Variant(std::in_place_type, value); + }, + [](uint64_t value) -> Variant { + return Variant(std::in_place_type, value); + }, + [](std::string&& value) -> Variant { + return Variant(std::in_place_type, + std::move(value)); + }), + common_internal::AsVariant(std::move(value)))) {} + + explicit operator bool() const { + return !std::holds_alternative(value_); + } + + [[nodiscard]] + bool IsBool() const { + return std::holds_alternative(value_); + } + + [[nodiscard]] + bool IsInt() const { + return std::holds_alternative(value_); + } + + [[nodiscard]] + bool IsUint() const { + return std::holds_alternative(value_); + } + + [[nodiscard]] + bool IsString() const { + return std::holds_alternative(value_); + } + + [[nodiscard]] + bool IsWildcard() const { + return std::holds_alternative(value_); } - static AttributeQualifierPattern CreateWildcard() { - return AttributeQualifierPattern(std::nullopt); + [[nodiscard]] + bool GetBool() const { + ABSL_DCHECK(IsBool()); + return std::get(value_); } - explicit AttributeQualifierPattern(AttributeQualifier qualifier) - : AttributeQualifierPattern( - std::optional(std::move(qualifier))) {} + [[nodiscard]] + int64_t GetInt() const { + ABSL_DCHECK(IsInt()); + return std::get(value_); + } - bool IsWildcard() const { return !value_.has_value(); } + [[nodiscard]] + uint64_t GetUint() const { + ABSL_DCHECK(IsUint()); + return std::get(value_); + } - bool IsMatch(const AttributeQualifier& qualifier) const { - if (IsWildcard()) return true; - return value_.value() == qualifier; + [[nodiscard]] + const std::string& GetString() const { + ABSL_DCHECK(IsString()); + return std::get(value_); + } + + [[nodiscard]] + std::optional AsBool() const { + if (const auto* value = std::get_if(&value_); value != nullptr) { + return *value; + } + return std::nullopt; } - bool IsMatch(absl::string_view other_key) const { - if (!value_.has_value()) return true; - return value_->IsMatch(other_key); + [[nodiscard]] + std::optional AsInt() const { + if (const auto* value = std::get_if(&value_); value != nullptr) { + return *value; + } + return std::nullopt; + } + + [[nodiscard]] + std::optional AsUint() const { + if (const auto* value = std::get_if(&value_); value != nullptr) { + return *value; + } + return std::nullopt; } + + [[nodiscard]] + absl::optional_ref AsString() const { + if (const auto* value = std::get_if(&value_); + value != nullptr) { + return *value; + } + return std::nullopt; + } + + [[nodiscard]] + std::optional ToQualifier() const { + return std::visit( + absl::Overload( + [](std::monostate) -> std::optional { + return AttributeQualifier(); + }, + [](bool value) -> std::optional { + return AttributeQualifier::OfBool(value); + }, + [](int64_t value) -> std::optional { + return AttributeQualifier::OfInt(value); + }, + [](uint64_t value) -> std::optional { + return AttributeQualifier::OfUint(value); + }, + [](const std::string& value) -> std::optional { + return AttributeQualifier::OfString(value); + }, + [](common_internal::WildcardType value) + -> std::optional { return std::nullopt; }), + value_); + } + + [[nodiscard]] + std::optional ToQualifierView() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return std::visit( + absl::Overload( + [](std::monostate) -> std::optional { + return AttributeQualifierView(); + }, + [](bool value) -> std::optional { + return AttributeQualifierView::OfBool(value); + }, + [](int64_t value) -> std::optional { + return AttributeQualifierView::OfInt(value); + }, + [](uint64_t value) -> std::optional { + return AttributeQualifierView::OfUint(value); + }, + [](const std::string& value) + -> std::optional { + return AttributeQualifierView::OfString(value); + }, + [](common_internal::WildcardType value) + -> std::optional { + return std::nullopt; + }), + value_); + } + + [[nodiscard]] + bool IsMatch(const AttributeQualifier& qualifier) const; + + [[nodiscard]] + bool IsMatch(absl::string_view other_key) const; + + private: + friend const common_internal::AttributeQualifierPatternVariant& + common_internal::AsVariant(const AttributeQualifierPattern& qualifier); + friend common_internal::AttributeQualifierPatternVariant&& + common_internal::AsVariant(AttributeQualifierPattern&& qualifier); + + using Variant = common_internal::AttributeQualifierPatternVariant; + using WildcardType = common_internal::WildcardType; + + template + explicit AttributeQualifierPattern(std::in_place_type_t in_place_type, + Args&&... args) + : value_(in_place_type, std::forward(args)...) {} + + // Qualifier value. If not set, treated as wildcard. + common_internal::AttributeQualifierPatternVariant value_; }; +[[nodiscard]] +bool operator==(const AttributeQualifier& lhs, const AttributeQualifier& rhs); + +[[nodiscard]] +bool operator==(const AttributeQualifierView& lhs, + const AttributeQualifierView& rhs); + +[[nodiscard]] +bool operator==(const AttributeQualifierPattern& lhs, + const AttributeQualifierPattern& rhs); + +[[nodiscard]] +bool operator==(const AttributeQualifier& lhs, + const AttributeQualifierView& rhs); + +[[nodiscard]] +bool operator==(const AttributeQualifier& lhs, + const AttributeQualifierPattern& rhs); + +[[nodiscard]] +bool operator==(const AttributeQualifierView& lhs, + const AttributeQualifier& rhs); + +[[nodiscard]] +bool operator==(const AttributeQualifierView& lhs, + const AttributeQualifierPattern& rhs); + +[[nodiscard]] +bool operator==(const AttributeQualifierPattern& lhs, + const AttributeQualifier& rhs); + +[[nodiscard]] +bool operator==(const AttributeQualifierPattern& lhs, + const AttributeQualifierView& rhs); + +[[nodiscard]] +inline bool operator!=(const AttributeQualifier& lhs, + const AttributeQualifier& rhs) { + return !operator==(lhs, rhs); +} + +[[nodiscard]] +inline bool operator!=(const AttributeQualifierView& lhs, + const AttributeQualifierView& rhs) { + return !operator==(lhs, rhs); +} + +[[nodiscard]] +inline bool operator!=(const AttributeQualifierPattern& lhs, + const AttributeQualifierPattern& rhs) { + return !operator==(lhs, rhs); +} + +[[nodiscard]] +inline bool operator!=(const AttributeQualifier& lhs, + const AttributeQualifierView& rhs) { + return !operator==(lhs, rhs); +} + +[[nodiscard]] +inline bool operator!=(const AttributeQualifier& lhs, + const AttributeQualifierPattern& rhs) { + return !operator==(lhs, rhs); +} + +[[nodiscard]] +inline bool operator!=(const AttributeQualifierView& lhs, + const AttributeQualifier& rhs) { + return !operator==(lhs, rhs); +} + +[[nodiscard]] +inline bool operator!=(const AttributeQualifierView& lhs, + const AttributeQualifierPattern& rhs) { + return !operator==(lhs, rhs); +} + +[[nodiscard]] +inline bool operator!=(const AttributeQualifierPattern& lhs, + const AttributeQualifier& rhs) { + return !operator==(lhs, rhs); +} + +[[nodiscard]] +inline bool operator!=(const AttributeQualifierPattern& lhs, + const AttributeQualifierView& rhs) { + return !operator==(lhs, rhs); +} + +[[nodiscard]] +bool operator<(const AttributeQualifier& lhs, const AttributeQualifier& rhs); + +[[nodiscard]] +bool operator<(const AttributeQualifierView& lhs, + const AttributeQualifierView& rhs); + +[[nodiscard]] +bool operator<(const AttributeQualifierPattern& lhs, + const AttributeQualifierPattern& rhs); + +[[nodiscard]] +bool operator<(const AttributeQualifier& lhs, + const AttributeQualifierView& rhs); + +[[nodiscard]] +bool operator<(const AttributeQualifier& lhs, + const AttributeQualifierPattern& rhs); + +[[nodiscard]] +bool operator<(const AttributeQualifierView& lhs, + const AttributeQualifier& rhs); + +[[nodiscard]] +bool operator<(const AttributeQualifierView& lhs, + const AttributeQualifierPattern& rhs); + +[[nodiscard]] +bool operator<(const AttributeQualifierPattern& lhs, + const AttributeQualifier& rhs); + +[[nodiscard]] +bool operator<(const AttributeQualifierPattern& lhs, + const AttributeQualifierView& rhs); + +namespace common_internal { + +[[nodiscard]] +inline const AttributeQualifierVariant& AsVariant( + const AttributeQualifier& qualifier ABSL_ATTRIBUTE_LIFETIME_BOUND) { + return qualifier.value_; +} + +[[nodiscard]] +inline AttributeQualifierVariant&& AsVariant( + AttributeQualifier&& qualifier ABSL_ATTRIBUTE_LIFETIME_BOUND) { + return std::move(qualifier.value_); +} + +[[nodiscard]] +inline const AttributeQualifierPatternVariant& AsVariant( + const AttributeQualifierPattern& qualifier ABSL_ATTRIBUTE_LIFETIME_BOUND) { + return qualifier.value_; +} + +[[nodiscard]] +inline AttributeQualifierPatternVariant&& AsVariant( + AttributeQualifierPattern&& qualifier ABSL_ATTRIBUTE_LIFETIME_BOUND) { + return std::move(qualifier.value_); +} + +[[nodiscard]] +inline const AttributeQualifierViewVariant& AsVariant( + const AttributeQualifierView& qualifier ABSL_ATTRIBUTE_LIFETIME_BOUND) { + return qualifier.value_; +} + +[[nodiscard]] +inline AttributeQualifierViewVariant&& AsVariant( + AttributeQualifierView&& qualifier ABSL_ATTRIBUTE_LIFETIME_BOUND) { + return std::move(qualifier.value_); +} + +} // namespace common_internal + // Attribute represents resolved attribute path. -class Attribute final { +class Attribute { public: explicit Attribute(std::string variable_name) : Attribute(std::move(variable_name), {}) {} @@ -197,7 +838,7 @@ class Attribute final { bool operator<(const Attribute& other) const; - const absl::StatusOr AsString() const; + absl::StatusOr AsString() const; private: struct Impl final { @@ -218,7 +859,7 @@ class Attribute final { // - field selection; // - map lookup by key; // - list access by index. -class AttributePattern final { +class AttributePattern { public: // MatchType enum specifies how closely pattern is matching the attribute: enum class MatchType { @@ -271,7 +912,7 @@ struct FieldSpecifier { std::string name; }; -using SelectQualifier = absl::variant; +using SelectQualifier = std::variant; } // namespace cel diff --git a/base/attribute_test.cc b/base/attribute_test.cc new file mode 100644 index 000000000..d4b36f9f5 --- /dev/null +++ b/base/attribute_test.cc @@ -0,0 +1,80 @@ +// Copyright 2022 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "base/attribute.h" + +#include + +#include "absl/strings/string_view.h" +#include "internal/testing.h" + +namespace cel { +namespace { + +using ::testing::Optional; + +TEST(AttributeQualifierView, Bool) { + AttributeQualifierView qualifier = AttributeQualifierView::OfBool(true); + EXPECT_TRUE(qualifier.IsBool()); + EXPECT_FALSE(qualifier.IsInt()); + EXPECT_FALSE(qualifier.IsUint()); + EXPECT_FALSE(qualifier.IsString()); + EXPECT_TRUE(qualifier.GetBool()); + EXPECT_THAT(qualifier.AsBool(), Optional(true)); + EXPECT_THAT(qualifier.AsInt(), std::nullopt); + EXPECT_THAT(qualifier.AsUint(), std::nullopt); + EXPECT_THAT(qualifier.AsString(), std::nullopt); +} + +TEST(AttributeQualifierView, Int) { + AttributeQualifierView qualifier = AttributeQualifierView::OfInt(1); + EXPECT_FALSE(qualifier.IsBool()); + EXPECT_TRUE(qualifier.IsInt()); + EXPECT_FALSE(qualifier.IsUint()); + EXPECT_FALSE(qualifier.IsString()); + EXPECT_EQ(qualifier.GetInt(), 1); + EXPECT_THAT(qualifier.AsBool(), std::nullopt); + EXPECT_THAT(qualifier.AsInt(), Optional(1)); + EXPECT_THAT(qualifier.AsUint(), std::nullopt); + EXPECT_THAT(qualifier.AsString(), std::nullopt); +} + +TEST(AttributeQualifierView, Uint) { + AttributeQualifierView qualifier = AttributeQualifierView::OfUint(1); + EXPECT_FALSE(qualifier.IsBool()); + EXPECT_FALSE(qualifier.IsInt()); + EXPECT_TRUE(qualifier.IsUint()); + EXPECT_FALSE(qualifier.IsString()); + EXPECT_EQ(qualifier.GetUint(), 1); + EXPECT_THAT(qualifier.AsBool(), std::nullopt); + EXPECT_THAT(qualifier.AsInt(), std::nullopt); + EXPECT_THAT(qualifier.AsUint(), Optional(1)); + EXPECT_THAT(qualifier.AsString(), std::nullopt); +} + +TEST(AttributeQualifierView, String) { + AttributeQualifierView qualifier = AttributeQualifierView::OfString("foo"); + EXPECT_FALSE(qualifier.IsBool()); + EXPECT_FALSE(qualifier.IsInt()); + EXPECT_FALSE(qualifier.IsUint()); + EXPECT_TRUE(qualifier.IsString()); + EXPECT_EQ(qualifier.GetString(), "foo"); + EXPECT_THAT(qualifier.AsBool(), std::nullopt); + EXPECT_THAT(qualifier.AsInt(), std::nullopt); + EXPECT_THAT(qualifier.AsUint(), std::nullopt); + EXPECT_THAT(qualifier.AsString(), Optional(absl::string_view("foo"))); +} + +} // namespace +} // namespace cel diff --git a/eval/public/cel_attribute_test.cc b/eval/public/cel_attribute_test.cc index b72189332..424dae92f 100644 --- a/eval/public/cel_attribute_test.cc +++ b/eval/public/cel_attribute_test.cc @@ -52,7 +52,7 @@ TEST(CelAttributeQualifierTest, TestBoolAccess) { EXPECT_FALSE(qualifier.GetUint64Key().has_value()); EXPECT_TRUE(qualifier.GetBoolKey().has_value()); EXPECT_THAT(qualifier.GetBoolKey().value(), Eq(true)); - EXPECT_THAT(qualifier.AsString(), IsOkAndHolds("true")); + EXPECT_THAT(qualifier.ToString(), "true"); } TEST(CelAttributeQualifierTest, TestInt64Access) { @@ -64,7 +64,7 @@ TEST(CelAttributeQualifierTest, TestInt64Access) { EXPECT_TRUE(qualifier.GetInt64Key().has_value()); EXPECT_THAT(qualifier.GetInt64Key().value(), Eq(-1)); - EXPECT_THAT(qualifier.AsString(), IsOkAndHolds("-1")); + EXPECT_THAT(qualifier.ToString(), "-1"); } TEST(CelAttributeQualifierTest, TestUint64Access) { @@ -76,7 +76,7 @@ TEST(CelAttributeQualifierTest, TestUint64Access) { EXPECT_TRUE(qualifier.GetUint64Key().has_value()); EXPECT_THAT(qualifier.GetUint64Key().value(), Eq(1UL)); - EXPECT_THAT(qualifier.AsString(), IsOkAndHolds("1")); + EXPECT_THAT(qualifier.ToString(), "1"); } TEST(CelAttributeQualifierTest, TestStringAccess) { @@ -89,7 +89,7 @@ TEST(CelAttributeQualifierTest, TestStringAccess) { EXPECT_TRUE(qualifier.GetStringKey().has_value()); EXPECT_THAT(qualifier.GetStringKey().value(), Eq("test")); - EXPECT_THAT(qualifier.AsString(), IsOkAndHolds("test")); + EXPECT_THAT(qualifier.ToString(), "test"); } void TestAllInequalities(const CelAttributeQualifier& qualifier) { diff --git a/extensions/protobuf/internal/qualify.cc b/extensions/protobuf/internal/qualify.cc index 37ad30011..1d53dac0d 100644 --- a/extensions/protobuf/internal/qualify.cc +++ b/extensions/protobuf/internal/qualify.cc @@ -339,11 +339,7 @@ absl::StatusOr ProtoQualifyState::CheckMapIn qualifier)); if (!value_ref.has_value()) { - std::string key_string; - absl::StatusOr key_string_or = qualifier.AsString(); - if (key_string_or.ok()) { - key_string = *key_string_or; - } + std::string key_string = qualifier.ToString(); return runtime_internal::CreateNoSuchKeyError(key_string); } return std::move(value_ref).value();