| 220 | } |
| 221 | |
| 222 | void PerformLookup(ExecutionFrameBase& frame, const Value& container, |
| 223 | const Value& key, const AttributeTrail& container_trail, |
| 224 | bool enable_optional_types, Value& result, |
| 225 | AttributeTrail& trail) { |
| 226 | if (frame.unknown_processing_enabled()) { |
| 227 | AttributeUtility::Accumulator unknowns = |
| 228 | frame.attribute_utility().CreateAccumulator(); |
| 229 | unknowns.MaybeAdd(container); |
| 230 | unknowns.MaybeAdd(key); |
| 231 | |
| 232 | if (!unknowns.IsEmpty()) { |
| 233 | result = std::move(unknowns).Build(); |
| 234 | return; |
| 235 | } |
| 236 | |
| 237 | trail = container_trail.Step(AttributeQualifierFromValue(key)); |
| 238 | |
| 239 | if (frame.attribute_utility().CheckForUnknownExact(trail)) { |
| 240 | result = frame.attribute_utility().CreateUnknownSet(trail.attribute()); |
| 241 | return; |
| 242 | } |
| 243 | } |
| 244 | |
| 245 | if (InstanceOf<ErrorValue>(container)) { |
| 246 | result = container; |
| 247 | return; |
| 248 | } |
| 249 | if (InstanceOf<ErrorValue>(key)) { |
| 250 | result = key; |
| 251 | return; |
| 252 | } |
| 253 | |
| 254 | if (enable_optional_types && container.IsOptional()) { |
| 255 | const auto& optional_value = container.GetOptional(); |
| 256 | if (!optional_value.HasValue()) { |
| 257 | result = cel::OptionalValue::None(); |
| 258 | return; |
| 259 | } |
| 260 | Value value; |
| 261 | optional_value.Value(&value); |
| 262 | LookupInContainer(value, key, frame, result); |
| 263 | if (auto error_value = cel::As<cel::ErrorValue>(result); |
| 264 | error_value && cel::IsNoSuchKey(*error_value)) { |
| 265 | result = cel::OptionalValue::None(); |
| 266 | return; |
| 267 | } |
| 268 | result = cel::OptionalValue::Of(std::move(result), frame.arena()); |
| 269 | return; |
| 270 | } |
| 271 | |
| 272 | LookupInContainer(container, key, frame, result); |
| 273 | } |
| 274 | |
| 275 | // ContainerAccessStep performs message field access specified by Expr::Select |
| 276 | // message. |
no test coverage detected