1919#include " eval/eval/attribute_trail.h"
2020#include " eval/internal/errors.h"
2121#include " internal/status_macros.h"
22+ #include " runtime/internal/attribute_matcher.h"
2223
2324namespace google ::api::expr::runtime {
2425
26+ using ::cel::Attribute;
27+ using ::cel::AttributePattern;
2528using ::cel::AttributeSet;
2629using ::cel::Cast;
2730using ::cel::ErrorValue;
@@ -31,25 +34,55 @@ using ::cel::InstanceOf;
3134using ::cel::UnknownValue;
3235using ::cel::Value;
3336using ::cel::base_internal::UnknownSet;
37+ using ::cel::runtime_internal::AttributeMatcher;
3438
3539using Accumulator = AttributeUtility::Accumulator;
40+ using MatchResult = AttributeMatcher::MatchResult;
41+
42+ DefaultAttributeMatcher::DefaultAttributeMatcher (
43+ absl::Span<const AttributePattern> unknown_patterns,
44+ absl::Span<const AttributePattern> missing_patterns)
45+ : unknown_patterns_(unknown_patterns),
46+ missing_patterns_ (missing_patterns) {}
47+
48+ DefaultAttributeMatcher::DefaultAttributeMatcher () = default;
49+
50+ AttributeMatcher::MatchResult MatchAgainstPatterns (
51+ absl::Span<const AttributePattern> patterns, const Attribute& attr) {
52+ MatchResult result = MatchResult::NONE ;
53+ for (const auto & pattern : patterns) {
54+ auto current_match = pattern.IsMatch (attr);
55+ if (current_match == cel::AttributePattern::MatchType::FULL ) {
56+ return MatchResult::FULL ;
57+ }
58+ if (current_match == cel::AttributePattern::MatchType::PARTIAL ) {
59+ result = MatchResult::PARTIAL ;
60+ }
61+ }
62+ return result;
63+ }
64+
65+ DefaultAttributeMatcher::MatchResult DefaultAttributeMatcher::CheckForUnknown (
66+ const Attribute& attr) const {
67+ return MatchAgainstPatterns (unknown_patterns_, attr);
68+ }
69+
70+ DefaultAttributeMatcher::MatchResult DefaultAttributeMatcher::CheckForMissing (
71+ const Attribute& attr) const {
72+ return MatchAgainstPatterns (missing_patterns_, attr);
73+ }
3674
3775bool AttributeUtility::CheckForMissingAttribute (
3876 const AttributeTrail& trail) const {
3977 if (trail.empty ()) {
4078 return false ;
4179 }
42-
43- for (const auto & pattern : missing_attribute_patterns_) {
44- // (b/161297249) Preserving existing behavior for now, will add a streamz
45- // for partial match, follow up with tightening up which fields are exposed
46- // to the condition (w/ ajay and jim)
47- if (pattern.IsMatch (trail.attribute ()) ==
48- cel::AttributePattern::MatchType::FULL ) {
49- return true ;
50- }
51- }
52- return false ;
80+ // Missing attributes are only treated as errors if the attribute exactly
81+ // matches (so no guard against passing partial state to a function as with
82+ // unknowns). This was initially a design oversight, but is difficult to
83+ // change now.
84+ return matcher_->CheckForMissing (trail.attribute ()) ==
85+ AttributeMatcher::MatchResult::FULL ;
5386}
5487
5588// Checks whether particular corresponds to any patterns that define unknowns.
@@ -58,13 +91,11 @@ bool AttributeUtility::CheckForUnknown(const AttributeTrail& trail,
5891 if (trail.empty ()) {
5992 return false ;
6093 }
61- for (const auto & pattern : unknown_patterns_) {
62- auto current_match = pattern.IsMatch (trail.attribute ());
63- if (current_match == cel::AttributePattern::MatchType::FULL ||
64- (use_partial &&
65- current_match == cel::AttributePattern::MatchType::PARTIAL )) {
66- return true ;
67- }
94+ MatchResult result = matcher_->CheckForUnknown (trail.attribute ());
95+
96+ if (result == MatchResult::FULL ||
97+ (use_partial && result == MatchResult::PARTIAL )) {
98+ return true ;
6899 }
69100 return false ;
70101}
0 commit comments