| 307 | } |
| 308 | |
| 309 | absl::StatusOr<Value> FallbackSelect( |
| 310 | const Value& root, absl::Span<const SelectQualifier> select_path, |
| 311 | bool presence_test, |
| 312 | const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool, |
| 313 | google::protobuf::MessageFactory* absl_nonnull message_factory, |
| 314 | google::protobuf::Arena* absl_nonnull arena) { |
| 315 | const Value* elem = &root; |
| 316 | Value result; |
| 317 | |
| 318 | for (const auto& instruction : |
| 319 | select_path.subspan(0, select_path.size() - 1)) { |
| 320 | CEL_ASSIGN_OR_RETURN(result, |
| 321 | ApplyQualifier(*elem, instruction, descriptor_pool, |
| 322 | message_factory, arena)); |
| 323 | if (result->Is<ErrorValue>()) { |
| 324 | return result; |
| 325 | } |
| 326 | elem = &result; |
| 327 | } |
| 328 | |
| 329 | const auto& last_instruction = select_path.back(); |
| 330 | if (presence_test) { |
| 331 | return absl::visit( |
| 332 | absl::Overload( |
| 333 | [&](const FieldSpecifier& field_specifier) |
| 334 | -> absl::StatusOr<Value> { |
| 335 | if (!elem->Is<StructValue>()) { |
| 336 | return cel::ErrorValue( |
| 337 | cel::runtime_internal::CreateNoMatchingOverloadError( |
| 338 | "<select>")); |
| 339 | } |
| 340 | CEL_ASSIGN_OR_RETURN( |
| 341 | bool present, |
| 342 | elem->GetStruct().HasFieldByName(field_specifier.name)); |
| 343 | return cel::BoolValue(present); |
| 344 | }, |
| 345 | [&](const AttributeQualifier& qualifier) -> absl::StatusOr<Value> { |
| 346 | if (!elem->Is<MapValue>() || qualifier.kind() != Kind::kString) { |
| 347 | return cel::ErrorValue( |
| 348 | cel::runtime_internal::CreateNoMatchingOverloadError( |
| 349 | "has")); |
| 350 | } |
| 351 | |
| 352 | return elem->GetMap().Has( |
| 353 | StringValue(arena, *qualifier.GetStringKey()), |
| 354 | descriptor_pool, message_factory, arena); |
| 355 | }), |
| 356 | last_instruction); |
| 357 | } |
| 358 | |
| 359 | return ApplyQualifier(*elem, last_instruction, descriptor_pool, |
| 360 | message_factory, arena); |
| 361 | } |
| 362 | |
| 363 | absl::StatusOr<std::vector<SelectQualifier>> SelectInstructionsFromCall( |
| 364 | const CallExpr& call) { |
no test coverage detected