| 281 | |
| 282 | template <typename ValueType> |
| 283 | absl::StatusOr<Value> ListSortByAssociatedKeysNative( |
| 284 | const ListValue& list, const ListValue& keys, |
| 285 | const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool, |
| 286 | google::protobuf::MessageFactory* absl_nonnull message_factory, |
| 287 | google::protobuf::Arena* absl_nonnull arena) { |
| 288 | CEL_ASSIGN_OR_RETURN(size_t size, list.Size()); |
| 289 | // If the list is empty or has a single element, we can return it as is. |
| 290 | if (size < 2) { |
| 291 | return list; |
| 292 | } |
| 293 | std::vector<ValueType> keys_vec; |
| 294 | absl::Status status = keys.ForEach( |
| 295 | [&keys_vec](const Value& value) -> absl::StatusOr<bool> { |
| 296 | if (auto typed_value = value.As<ValueType>(); typed_value.has_value()) { |
| 297 | keys_vec.push_back(*typed_value); |
| 298 | } else { |
| 299 | return absl::InvalidArgumentError( |
| 300 | "sort(): list elements must have the same type"); |
| 301 | } |
| 302 | return true; |
| 303 | }, |
| 304 | descriptor_pool, message_factory, arena); |
| 305 | if (!status.ok()) { |
| 306 | return ErrorValue(status); |
| 307 | } |
| 308 | ABSL_ASSERT(keys_vec.size() == size); // Already checked by the caller. |
| 309 | std::vector<int64_t> sorted_indices(keys_vec.size()); |
| 310 | std::iota(sorted_indices.begin(), sorted_indices.end(), 0); |
| 311 | std::sort( |
| 312 | sorted_indices.begin(), sorted_indices.end(), |
| 313 | [&](int64_t a, int64_t b) -> bool { return keys_vec[a] < keys_vec[b]; }); |
| 314 | |
| 315 | // Now sorted_indices contains the indices of the keys in sorted order. |
| 316 | // We can use it to build the sorted list. |
| 317 | auto builder = NewListValueBuilder(arena); |
| 318 | for (const auto& index : sorted_indices) { |
| 319 | CEL_ASSIGN_OR_RETURN( |
| 320 | Value value, list.Get(index, descriptor_pool, message_factory, arena)); |
| 321 | CEL_RETURN_IF_ERROR(builder->Add(value)); |
| 322 | } |
| 323 | return std::move(*builder).Build(); |
| 324 | } |
| 325 | |
| 326 | // Internal function used for the implementation of sort() and sortBy(). |
| 327 | // |