Coverage Report

Created: 2026-05-27 07:00

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/proc/self/cwd/base/attribute.h
Line
Count
Source
1
// Copyright 2022 Google LLC
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License");
4
// you may not use this file except in compliance with the License.
5
// You may obtain a copy of the License at
6
//
7
//     https://www.apache.org/licenses/LICENSE-2.0
8
//
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
// See the License for the specific language governing permissions and
13
// limitations under the License.
14
15
#ifndef THIRD_PARTY_CEL_CPP_BASE_ATTRIBUTE_H_
16
#define THIRD_PARTY_CEL_CPP_BASE_ATTRIBUTE_H_
17
18
#include <cstdint>
19
#include <memory>
20
#include <optional>
21
#include <string>
22
#include <utility>
23
#include <vector>
24
25
#include "absl/status/statusor.h"
26
#include "absl/strings/string_view.h"
27
#include "absl/types/optional.h"
28
#include "absl/types/span.h"
29
#include "absl/types/variant.h"
30
#include "base/kind.h"
31
32
namespace cel {
33
34
// AttributeQualifier represents a segment in
35
// attribute resolutuion path. A segment can be qualified by values of
36
// following types: string/int64_t/uint64_t/bool.
37
class AttributeQualifier final {
38
 private:
39
  struct ComparatorVisitor;
40
41
  using Variant = absl::variant<Kind, int64_t, uint64_t, std::string, bool>;
42
43
 public:
44
0
  static AttributeQualifier OfInt(int64_t value) {
45
0
    return AttributeQualifier(absl::in_place_type<int64_t>, std::move(value));
46
0
  }
47
48
0
  static AttributeQualifier OfUint(uint64_t value) {
49
0
    return AttributeQualifier(absl::in_place_type<uint64_t>, std::move(value));
50
0
  }
51
52
0
  static AttributeQualifier OfString(std::string value) {
53
0
    return AttributeQualifier(absl::in_place_type<std::string>,
54
0
                              std::move(value));
55
0
  }
56
57
0
  static AttributeQualifier OfBool(bool value) {
58
0
    return AttributeQualifier(absl::in_place_type<bool>, std::move(value));
59
0
  }
60
61
0
  AttributeQualifier() = default;
62
63
0
  AttributeQualifier(const AttributeQualifier&) = default;
64
0
  AttributeQualifier(AttributeQualifier&&) = default;
65
66
  AttributeQualifier& operator=(const AttributeQualifier&) = default;
67
0
  AttributeQualifier& operator=(AttributeQualifier&&) = default;
68
69
  Kind kind() const;
70
71
  // Family of Get... methods. Return values if requested type matches the
72
  // stored one.
73
0
  absl::optional<int64_t> GetInt64Key() const {
74
0
    return absl::holds_alternative<int64_t>(value_)
75
0
               ? absl::optional<int64_t>(absl::get<1>(value_))
76
0
               : absl::nullopt;
77
0
  }
78
79
0
  absl::optional<uint64_t> GetUint64Key() const {
80
0
    return absl::holds_alternative<uint64_t>(value_)
81
0
               ? absl::optional<uint64_t>(absl::get<2>(value_))
82
0
               : absl::nullopt;
83
0
  }
84
85
0
  absl::optional<absl::string_view> GetStringKey() const {
86
0
    return absl::holds_alternative<std::string>(value_)
87
0
               ? absl::optional<absl::string_view>(absl::get<3>(value_))
88
0
               : absl::nullopt;
89
0
  }
90
91
0
  absl::optional<bool> GetBoolKey() const {
92
0
    return absl::holds_alternative<bool>(value_)
93
0
               ? absl::optional<bool>(absl::get<4>(value_))
94
0
               : absl::nullopt;
95
0
  }
96
97
0
  bool operator==(const AttributeQualifier& other) const {
98
0
    return IsMatch(other);
99
0
  }
100
101
  bool operator<(const AttributeQualifier& other) const;
102
103
0
  bool IsMatch(absl::string_view other_key) const {
104
0
    absl::optional<absl::string_view> key = GetStringKey();
105
0
    return (key.has_value() && key.value() == other_key);
106
0
  }
107
108
  absl::StatusOr<std::string> AsString() const;
109
110
 private:
111
  friend class Attribute;
112
  friend struct ComparatorVisitor;
113
114
  template <typename T>
115
  AttributeQualifier(absl::in_place_type_t<T> in_place_type, T&& value)
116
0
      : value_(in_place_type, std::forward<T>(value)) {}
Unexecuted instantiation: cel::AttributeQualifier::AttributeQualifier<long>(std::__1::in_place_type_t<long>, long&&)
Unexecuted instantiation: cel::AttributeQualifier::AttributeQualifier<unsigned long>(std::__1::in_place_type_t<unsigned long>, unsigned long&&)
Unexecuted instantiation: cel::AttributeQualifier::AttributeQualifier<bool>(std::__1::in_place_type_t<bool>, bool&&)
Unexecuted instantiation: cel::AttributeQualifier::AttributeQualifier<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >(std::__1::in_place_type_t<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&&)
117
118
  bool IsMatch(const AttributeQualifier& other) const;
119
120
  // The previous implementation of Attribute preserved all value
121
  // instances, regardless of whether they are supported in this context or not.
122
  // We represented unsupported types by using the first alternative and thus
123
  // preserve backwards compatibility with the result of `type()` above.
124
  Variant value_;
125
};
126
127
// AttributeQualifierPattern matches a segment in
128
// attribute resolutuion path. AttributeQualifierPattern is capable of
129
// matching path elements of types string/int64/uint64/bool.
130
class AttributeQualifierPattern final {
131
 private:
132
  // Qualifier value. If not set, treated as wildcard.
133
  std::optional<AttributeQualifier> value_;
134
135
  explicit AttributeQualifierPattern(std::optional<AttributeQualifier> value)
136
0
      : value_(std::move(value)) {}
137
138
 public:
139
0
  static AttributeQualifierPattern OfInt(int64_t value) {
140
0
    return AttributeQualifierPattern(AttributeQualifier::OfInt(value));
141
0
  }
142
143
0
  static AttributeQualifierPattern OfUint(uint64_t value) {
144
0
    return AttributeQualifierPattern(AttributeQualifier::OfUint(value));
145
0
  }
146
147
0
  static AttributeQualifierPattern OfString(std::string value) {
148
0
    return AttributeQualifierPattern(
149
0
        AttributeQualifier::OfString(std::move(value)));
150
0
  }
151
152
0
  static AttributeQualifierPattern OfBool(bool value) {
153
0
    return AttributeQualifierPattern(AttributeQualifier::OfBool(value));
154
0
  }
155
156
0
  static AttributeQualifierPattern CreateWildcard() {
157
0
    return AttributeQualifierPattern(std::nullopt);
158
0
  }
159
160
  explicit AttributeQualifierPattern(AttributeQualifier qualifier)
161
      : AttributeQualifierPattern(
162
0
            std::optional<AttributeQualifier>(std::move(qualifier))) {}
163
164
0
  bool IsWildcard() const { return !value_.has_value(); }
165
166
0
  bool IsMatch(const AttributeQualifier& qualifier) const {
167
0
    if (IsWildcard()) return true;
168
0
    return value_.value() == qualifier;
169
0
  }
170
171
0
  bool IsMatch(absl::string_view other_key) const {
172
0
    if (!value_.has_value()) return true;
173
0
    return value_->IsMatch(other_key);
174
0
  }
175
};
176
177
// Attribute represents resolved attribute path.
178
class Attribute final {
179
 public:
180
  explicit Attribute(std::string variable_name)
181
0
      : Attribute(std::move(variable_name), {}) {}
182
183
  Attribute(std::string variable_name,
184
            std::vector<AttributeQualifier> qualifier_path)
185
0
      : impl_(std::make_shared<Impl>(std::move(variable_name),
186
0
                                     std::move(qualifier_path))) {}
187
188
0
  absl::string_view variable_name() const { return impl_->variable_name; }
189
190
0
  bool has_variable_name() const { return !impl_->variable_name.empty(); }
191
192
0
  absl::Span<const AttributeQualifier> qualifier_path() const {
193
0
    return impl_->qualifier_path;
194
0
  }
195
196
  bool operator==(const Attribute& other) const;
197
198
  bool operator<(const Attribute& other) const;
199
200
  const absl::StatusOr<std::string> AsString() const;
201
202
 private:
203
  struct Impl final {
204
    Impl(std::string variable_name,
205
         std::vector<AttributeQualifier> qualifier_path)
206
0
        : variable_name(std::move(variable_name)),
207
0
          qualifier_path(std::move(qualifier_path)) {}
208
209
    std::string variable_name;
210
    std::vector<AttributeQualifier> qualifier_path;
211
  };
212
213
  std::shared_ptr<const Impl> impl_;
214
};
215
216
// AttributePattern is a fully-qualified absolute attribute path pattern.
217
// Supported segments steps in the path are:
218
// - field selection;
219
// - map lookup by key;
220
// - list access by index.
221
class AttributePattern final {
222
 public:
223
  // MatchType enum specifies how closely pattern is matching the attribute:
224
  enum class MatchType {
225
    NONE,     // Pattern does not match attribute itself nor its children
226
    PARTIAL,  // Pattern matches an entity nested within attribute;
227
    FULL      // Pattern matches an attribute itself.
228
  };
229
230
  AttributePattern(std::string variable,
231
                   std::vector<AttributeQualifierPattern> qualifier_path)
232
      : variable_(std::move(variable)),
233
0
        qualifier_path_(std::move(qualifier_path)) {}
234
235
0
  absl::string_view variable() const { return variable_; }
236
237
0
  absl::Span<const AttributeQualifierPattern> qualifier_path() const {
238
0
    return qualifier_path_;
239
0
  }
240
241
  // Matches the pattern to an attribute.
242
  // Distinguishes between no-match, partial match and full match cases.
243
0
  MatchType IsMatch(const Attribute& attribute) const {
244
0
    MatchType result = MatchType::NONE;
245
0
    if (attribute.variable_name() != variable_) {
246
0
      return result;
247
0
    }
248
249
0
    auto max_index = qualifier_path().size();
250
0
    result = MatchType::FULL;
251
0
    if (qualifier_path().size() > attribute.qualifier_path().size()) {
252
0
      max_index = attribute.qualifier_path().size();
253
0
      result = MatchType::PARTIAL;
254
0
    }
255
256
0
    for (size_t i = 0; i < max_index; i++) {
257
0
      if (!(qualifier_path()[i].IsMatch(attribute.qualifier_path()[i]))) {
258
0
        return MatchType::NONE;
259
0
      }
260
0
    }
261
0
    return result;
262
0
  }
263
264
 private:
265
  std::string variable_;
266
  std::vector<AttributeQualifierPattern> qualifier_path_;
267
};
268
269
struct FieldSpecifier {
270
  int64_t number;
271
  std::string name;
272
};
273
274
using SelectQualifier = absl::variant<FieldSpecifier, AttributeQualifier>;
275
276
}  // namespace cel
277
278
#endif  // THIRD_PARTY_CEL_CPP_BASE_ATTRIBUTE_H_