|
23 | 23 |
|
24 | 24 | #include "absl/status/status.h" |
25 | 25 | #include "absl/status/statusor.h" |
| 26 | +#include "absl/strings/str_format.h" |
26 | 27 | #include "absl/strings/string_view.h" |
27 | 28 | #include "absl/types/optional.h" |
28 | 29 | #include "base/function_adapter.h" |
@@ -211,6 +212,33 @@ absl::StatusOr<Value> OptionalOptIndexOptionalValue( |
211 | 212 | return ErrorValue{runtime_internal::CreateNoMatchingOverloadError("_[?_]")}; |
212 | 213 | } |
213 | 214 |
|
| 215 | +absl::StatusOr<Value> ListUnwrapOpt(ValueManager& value_manager, |
| 216 | + const ListValue& list) { |
| 217 | + CEL_ASSIGN_OR_RETURN(auto builder, |
| 218 | + value_manager.NewListValueBuilder(ListType())); |
| 219 | + CEL_ASSIGN_OR_RETURN(auto list_size, list.Size()); |
| 220 | + builder->Reserve(list_size); |
| 221 | + |
| 222 | + absl::Status status = list.ForEach( |
| 223 | + value_manager, [&](const Value& value) -> absl::StatusOr<bool> { |
| 224 | + if (auto optional_value = value.AsOptional(); optional_value) { |
| 225 | + if (optional_value->HasValue()) { |
| 226 | + CEL_RETURN_IF_ERROR(builder->Add(optional_value->Value())); |
| 227 | + } |
| 228 | + } else { |
| 229 | + return absl::InvalidArgumentError(absl::StrFormat( |
| 230 | + "optional.unwrap() expected a list(optional(T)), but %s " |
| 231 | + "was found in the list.", |
| 232 | + value.GetTypeName())); |
| 233 | + } |
| 234 | + return true; |
| 235 | + }); |
| 236 | + if (!status.ok()) { |
| 237 | + return ErrorValue(status); |
| 238 | + } |
| 239 | + return std::move(*builder).Build(); |
| 240 | +} |
| 241 | + |
214 | 242 | absl::Status RegisterOptionalTypeFunctions(FunctionRegistry& registry, |
215 | 243 | const RuntimeOptions& options) { |
216 | 244 | if (!options.enable_qualified_type_identifiers) { |
@@ -274,6 +302,16 @@ absl::Status RegisterOptionalTypeFunctions(FunctionRegistry& registry, |
274 | 302 | Value>::CreateDescriptor("_[?_]", false), |
275 | 303 | BinaryFunctionAdapter<absl::StatusOr<Value>, OpaqueValue, Value>:: |
276 | 304 | WrapFunction(&OptionalOptIndexOptionalValue))); |
| 305 | + CEL_RETURN_IF_ERROR(registry.Register( |
| 306 | + UnaryFunctionAdapter<absl::StatusOr<Value>, ListValue>::CreateDescriptor( |
| 307 | + "optional.unwrap", false), |
| 308 | + UnaryFunctionAdapter<absl::StatusOr<Value>, ListValue>::WrapFunction( |
| 309 | + &ListUnwrapOpt))); |
| 310 | + CEL_RETURN_IF_ERROR(registry.Register( |
| 311 | + UnaryFunctionAdapter<absl::StatusOr<Value>, ListValue>::CreateDescriptor( |
| 312 | + "unwrapOpt", true), |
| 313 | + UnaryFunctionAdapter<absl::StatusOr<Value>, ListValue>::WrapFunction( |
| 314 | + &ListUnwrapOpt))); |
277 | 315 | return absl::OkStatus(); |
278 | 316 | } |
279 | 317 |
|
|
0 commit comments