| 855 | } |
| 856 | |
| 857 | uint64_t BinaryAnnotator::BuildStruct(const uint64_t struct_offset, |
| 858 | std::vector<BinaryRegion> ®ions, |
| 859 | const std::string referring_field_name, |
| 860 | const reflection::Object *const object) { |
| 861 | if (!object->is_struct()) { return struct_offset; } |
| 862 | uint64_t offset = struct_offset; |
| 863 | |
| 864 | // Loop over all the fields in increasing order |
| 865 | ForAllFields(object, /*reverse=*/false, [&](const reflection::Field *field) { |
| 866 | if (IsScalar(field->type()->base_type())) { |
| 867 | // Structure Field value |
| 868 | const uint64_t type_size = GetTypeSize(field->type()->base_type()); |
| 869 | const BinaryRegionType region_type = |
| 870 | GetRegionType(field->type()->base_type()); |
| 871 | |
| 872 | BinaryRegionComment comment; |
| 873 | comment.type = BinaryRegionCommentType::StructField; |
| 874 | comment.name = referring_field_name + "." + field->name()->str(); |
| 875 | comment.default_value = "of '" + object->name()->str() + "' (" + |
| 876 | std::string(reflection::EnumNameBaseType( |
| 877 | field->type()->base_type())) + |
| 878 | ")"; |
| 879 | |
| 880 | if (!IsValidRead(offset, type_size)) { |
| 881 | const uint64_t remaining = RemainingBytes(offset); |
| 882 | SetError(comment, BinaryRegionStatus::ERROR_INCOMPLETE_BINARY, |
| 883 | std::to_string(type_size)); |
| 884 | regions.push_back(MakeBinaryRegion(offset, remaining, |
| 885 | BinaryRegionType::Unknown, remaining, |
| 886 | 0, comment)); |
| 887 | |
| 888 | // TODO(dbaileychess): Should I bail out here? This sets offset to the |
| 889 | // end of the binary. So all other reads in the loop should fail. |
| 890 | offset += remaining; |
| 891 | return; |
| 892 | } |
| 893 | |
| 894 | regions.push_back( |
| 895 | MakeBinaryRegion(offset, type_size, region_type, 0, 0, comment)); |
| 896 | offset += type_size; |
| 897 | } else if (field->type()->base_type() == reflection::BaseType::Obj) { |
| 898 | // Structs are stored inline, even when nested. |
| 899 | offset = BuildStruct(offset, regions, |
| 900 | referring_field_name + "." + field->name()->str(), |
| 901 | schema_->objects()->Get(field->type()->index())); |
| 902 | } else if (field->type()->base_type() == reflection::BaseType::Array) { |
| 903 | const bool is_scalar = IsScalar(field->type()->element()); |
| 904 | const uint64_t type_size = GetTypeSize(field->type()->element()); |
| 905 | const BinaryRegionType region_type = |
| 906 | GetRegionType(field->type()->element()); |
| 907 | |
| 908 | // Arrays are just repeated structures. |
| 909 | for (uint16_t i = 0; i < field->type()->fixed_length(); ++i) { |
| 910 | if (is_scalar) { |
| 911 | BinaryRegionComment array_comment; |
| 912 | array_comment.type = BinaryRegionCommentType::ArrayField; |
| 913 | array_comment.name = |
| 914 | referring_field_name + "." + field->name()->str(); |
nothing calls this directly
no test coverage detected