/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_ |