| 463 | } |
| 464 | |
| 465 | void skip_ext(ReadContext &ctx, const FieldType &) { |
| 466 | // EXT fields in compatible mode are serialized with type_id followed by |
| 467 | // ext data. For named ext, meta_index is also written after type_id. |
| 468 | // We read the type_id, look up the registered ext harness, and call its |
| 469 | // read_data function to consume the data bytes. |
| 470 | |
| 471 | if (!ctx.is_compatible()) { |
| 472 | ctx.set_error(Error::unsupported( |
| 473 | "Ext skipping is only supported in compatible mode")); |
| 474 | return; |
| 475 | } |
| 476 | |
| 477 | // Read remote type_id from buffer - Java always writes type_id for ext |
| 478 | uint32_t remote_type_id = ctx.read_uint8(ctx.error()); |
| 479 | if (FORY_PREDICT_FALSE(ctx.has_error())) { |
| 480 | return; |
| 481 | } |
| 482 | |
| 483 | uint32_t user_type_id = 0; |
| 484 | switch (static_cast<TypeId>(remote_type_id)) { |
| 485 | case TypeId::ENUM: |
| 486 | case TypeId::STRUCT: |
| 487 | case TypeId::COMPATIBLE_STRUCT: |
| 488 | case TypeId::EXT: |
| 489 | case TypeId::TYPED_UNION: |
| 490 | user_type_id = ctx.read_var_uint32(ctx.error()); |
| 491 | if (FORY_PREDICT_FALSE(ctx.has_error())) { |
| 492 | return; |
| 493 | } |
| 494 | break; |
| 495 | default: |
| 496 | break; |
| 497 | } |
| 498 | TypeId remote_tid = static_cast<TypeId>(remote_type_id); |
| 499 | |
| 500 | const TypeInfo *type_info = nullptr; |
| 501 | |
| 502 | if (remote_tid == TypeId::NAMED_EXT) { |
| 503 | // Named ext in compatible mode: read TypeMeta inline using streaming |
| 504 | // protocol |
| 505 | auto type_info_res = ctx.read_type_meta(); |
| 506 | if (FORY_PREDICT_FALSE(!type_info_res.ok())) { |
| 507 | ctx.set_error(std::move(type_info_res).error()); |
| 508 | return; |
| 509 | } |
| 510 | type_info = type_info_res.value(); |
| 511 | } else { |
| 512 | // ID-based ext: look up by remote type_id we just read |
| 513 | auto type_info_res = ctx.type_resolver().get_user_type_info_by_id( |
| 514 | remote_type_id, user_type_id); |
| 515 | if (FORY_PREDICT_FALSE(!type_info_res.ok())) { |
| 516 | ctx.set_error(std::move(type_info_res).error()); |
| 517 | return; |
| 518 | } |
| 519 | type_info = type_info_res.value(); |
| 520 | } |
| 521 | |
| 522 | if (!type_info) { |
no test coverage detected