| 410 | /// Read collection data for polymorphic or shared-ref elements. |
| 411 | template <typename T, typename Container> |
| 412 | inline Container read_collection_data_slow(ReadContext &ctx, uint32_t length) { |
| 413 | Container result; |
| 414 | if (length == 0) { |
| 415 | return result; |
| 416 | } |
| 417 | if (FORY_PREDICT_FALSE(!reserve_collection(result, ctx, length))) { |
| 418 | return result; |
| 419 | } |
| 420 | |
| 421 | constexpr bool elem_is_polymorphic = is_polymorphic_v<T>; |
| 422 | |
| 423 | uint8_t bitmap = ctx.read_uint8(ctx.error()); |
| 424 | if (FORY_PREDICT_FALSE(ctx.has_error())) { |
| 425 | return result; |
| 426 | } |
| 427 | |
| 428 | // IMPORTANT: collection readers must obey the ref/null bits written on the |
| 429 | // wire, not the local container traits that may describe a different ref |
| 430 | // policy. Shared xlang tests intentionally deserialize one ref policy and |
| 431 | // then serialize another local payload. DO NOT REMOVE this comment. |
| 432 | bool track_ref = (bitmap & COLL_TRACKING_REF) != 0; |
| 433 | bool has_null = (bitmap & COLL_HAS_NULL) != 0; |
| 434 | bool is_decl_type = (bitmap & COLL_DECL_ELEMENT_TYPE) != 0; |
| 435 | bool is_same_type = (bitmap & COLL_IS_SAME_TYPE) != 0; |
| 436 | |
| 437 | // Read element type info if IS_SAME_TYPE && !IS_DECL_ELEMENT_TYPE |
| 438 | const TypeInfo *elem_type_info = nullptr; |
| 439 | if (is_same_type && !is_decl_type) { |
| 440 | elem_type_info = ctx.read_any_type_info(ctx.error()); |
| 441 | if (FORY_PREDICT_FALSE(ctx.has_error())) { |
| 442 | return result; |
| 443 | } |
| 444 | } |
| 445 | |
| 446 | // Read elements |
| 447 | if (is_same_type) { |
| 448 | if (track_ref) { |
| 449 | for (uint32_t i = 0; i < length; ++i) { |
| 450 | if (FORY_PREDICT_FALSE(ctx.has_error())) { |
| 451 | return result; |
| 452 | } |
| 453 | if constexpr (elem_is_polymorphic) { |
| 454 | // Use RefMode::Tracking to read ref flag per element |
| 455 | auto elem = Serializer<T>::read_with_type_info(ctx, RefMode::Tracking, |
| 456 | *elem_type_info); |
| 457 | collection_insert(result, std::move(elem)); |
| 458 | } else { |
| 459 | auto elem = Serializer<T>::read(ctx, RefMode::Tracking, false); |
| 460 | collection_insert(result, std::move(elem)); |
| 461 | } |
| 462 | } |
| 463 | } else if (!has_null) { |
| 464 | for (uint32_t i = 0; i < length; ++i) { |
| 465 | if (FORY_PREDICT_FALSE(ctx.has_error())) { |
| 466 | return result; |
| 467 | } |
| 468 | if constexpr (elem_is_polymorphic) { |
| 469 | auto elem = Serializer<T>::read_with_type_info(ctx, RefMode::None, |
nothing calls this directly
no test coverage detected