| 595 | class DecodeProtoOp : public OpKernel { |
| 596 | public: |
| 597 | explicit DecodeProtoOp(OpKernelConstruction* context) : OpKernel(context) { |
| 598 | string descriptor_source; |
| 599 | OP_REQUIRES_OK(context, |
| 600 | context->GetAttr("descriptor_source", &descriptor_source)); |
| 601 | |
| 602 | // We always get back a desc_pool, but we may not own it. If we own it, |
| 603 | // owned_desc_pool_ will be filled in. |
| 604 | DescriptorPool const* desc_pool; |
| 605 | OP_REQUIRES_OK(context, GetDescriptorPool(context->env(), descriptor_source, |
| 606 | &desc_pool, &owned_desc_pool_)); |
| 607 | |
| 608 | string message_type; |
| 609 | OP_REQUIRES_OK(context, context->GetAttr("message_type", &message_type)); |
| 610 | |
| 611 | const Descriptor* message_desc = |
| 612 | desc_pool->FindMessageTypeByName(message_type); |
| 613 | OP_REQUIRES(context, message_desc != nullptr, |
| 614 | errors::InvalidArgument("No descriptor found for message type ", |
| 615 | message_type)); |
| 616 | |
| 617 | std::vector<string> field_names; |
| 618 | OP_REQUIRES_OK(context, context->GetAttr("field_names", &field_names)); |
| 619 | std::vector<DataType> output_types; |
| 620 | OP_REQUIRES_OK(context, context->GetAttr("output_types", &output_types)); |
| 621 | OP_REQUIRES( |
| 622 | context, field_names.size() == output_types.size(), |
| 623 | errors::InvalidArgument("field_names and output_types attributes must " |
| 624 | "have the same length")); |
| 625 | |
| 626 | // Gather the field descriptors and check that requested output types match. |
| 627 | int field_index = 0; |
| 628 | std::vector<const FieldDescriptor*> field_descs; |
| 629 | std::vector<const FieldDescriptor*> exts; |
| 630 | absl::flat_hash_map<string, const FieldDescriptor*> ext_name_to_field; |
| 631 | std::vector<const FieldDescriptor*>::iterator ext_it = exts.begin(); |
| 632 | for (const string& name : field_names) { |
| 633 | auto fd = message_desc->FindFieldByName(name); |
| 634 | if (fd == nullptr) { |
| 635 | // If field can't be found in original message, try to find a matching |
| 636 | // extension (by its full_name). First check a hashmap for a matching |
| 637 | // extension, and if not found, then iterate through available |
| 638 | // extensions to find a match (updating the hashmap while iterating.) |
| 639 | auto lookup_result = ext_name_to_field.find(name); |
| 640 | if (lookup_result != ext_name_to_field.end()) { |
| 641 | fd = lookup_result->second; |
| 642 | } else { |
| 643 | if (ext_it == exts.begin()) { |
| 644 | desc_pool->FindAllExtensions(message_desc, &exts); |
| 645 | ext_it = exts.begin(); |
| 646 | } |
| 647 | while (ext_it != exts.end()) { |
| 648 | auto ext_name = (*ext_it)->full_name(); |
| 649 | auto ext_field = *ext_it; |
| 650 | ++ext_it; |
| 651 | |
| 652 | ext_name_to_field.insert({ext_name, ext_field}); |
| 653 | if (ext_name == name) { |
| 654 | fd = ext_field; |
nothing calls this directly
no test coverage detected