1 /*
2  * Copyright (c) 2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "abc_field_processor.h"
17 #include "abc2program_log.h"
18 #include "abc_literal_array_processor.h"
19 #include "file-inl.h"
20 #include "literal_data_accessor.h"
21 
22 namespace panda::abc2program {
23 
AbcFieldProcessor(panda_file::File::EntityId entity_id, Abc2ProgramEntityContainer &entity_container, pandasm::Record &record)24 AbcFieldProcessor::AbcFieldProcessor(panda_file::File::EntityId entity_id, Abc2ProgramEntityContainer &entity_container,
25                                      pandasm::Record &record)
26     : AbcFileEntityProcessor(entity_id, entity_container), record_(record),
27       type_converter_(entity_container),
28       field_(pandasm::Field(LANG_ECMA))
29 {
30     field_data_accessor_ = std::make_unique<panda_file::FieldDataAccessor>(*file_, entity_id_);
31 }
32 
FillProgramData()33 void AbcFieldProcessor::FillProgramData()
34 {
35     FillFieldData();
36     record_.field_list.emplace_back(std::move(field_));
37 }
38 
FillFieldData()39 void AbcFieldProcessor::FillFieldData()
40 {
41     FillFieldName();
42     FillFieldType();
43     FillFieldMetaData();
44 }
45 
FillFieldName()46 void AbcFieldProcessor::FillFieldName()
47 {
48     panda_file::File::EntityId field_name_id = field_data_accessor_->GetNameId();
49     field_.name = GetStringById(field_name_id);
50 }
51 
FillFieldType()52 void AbcFieldProcessor::FillFieldType()
53 {
54     uint32_t field_type = field_data_accessor_->GetType();
55     field_.type = type_converter_.FieldTypeToPandasmType(field_type);
56 }
57 
FillFieldMetaData()58 void AbcFieldProcessor::FillFieldMetaData()
59 {
60     field_.metadata->SetFieldType(field_.type);
61     FillFieldAttributes();
62     FillMetaDataValue();
63 }
64 
FillFieldAttributes()65 void AbcFieldProcessor::FillFieldAttributes()
66 {
67     if (field_data_accessor_->IsExternal()) {
68         field_.metadata->SetAttribute(ABC_ATTR_EXTERNAL);
69     }
70     if (field_data_accessor_->IsStatic()) {
71         field_.metadata->SetAttribute(ABC_ATTR_STATIC);
72     }
73 }
74 
FillU32MetaData()75 void AbcFieldProcessor::FillU32MetaData()
76 {
77     uint32_t val = field_data_accessor_->GetValue<uint32_t>().value();
78     if (record_.name == ES_MODULE_RECORD || field_.name == MODULE_RECORD_IDX) {
79         entity_container_.AddModuleLiteralArrayId(val);
80         auto module_literal_array_id_name = entity_container_.GetLiteralArrayIdName(val);
81         field_.metadata->SetValue(pandasm::ScalarValue::Create<pandasm::Value::Type::LITERALARRAY>(
82             module_literal_array_id_name));
83     } else if (record_.name == ES_SCOPE_NAMES_RECORD || field_.name == SCOPE_NAMES) {
84         entity_container_.AddUnnestedLiteralArrayId(val);
85         auto literal_array_id_name = entity_container_.GetLiteralArrayIdName(val);
86         field_.metadata->SetValue(pandasm::ScalarValue::Create<pandasm::Value::Type::LITERALARRAY>(
87             literal_array_id_name));
88     } else if (field_.name == MODULE_REQUEST_PAHSE_IDX) {
89         entity_container_.AddModuleRequestPhaseId(val);
90         auto module_literal_array_id_name = entity_container_.GetLiteralArrayIdName(val);
91         field_.metadata->SetValue(pandasm::ScalarValue::Create<pandasm::Value::Type::LITERALARRAY>(
92             module_literal_array_id_name));
93     } else if (field_.name == JSON_FILE_CONTENT) {
94         auto json_string_id = panda_file::File::EntityId(val);
95         field_.metadata->SetValue(pandasm::ScalarValue::Create<pandasm::Value::Type::STRING>(
96             entity_container_.GetStringById(json_string_id)));
97     } else {
98         field_.metadata->SetValue(pandasm::ScalarValue::Create<pandasm::Value::Type::U32>(val));
99     }
100 }
101 
FillStringMetaData()102 void AbcFieldProcessor::FillStringMetaData()
103 {
104     std::optional<uint32_t> string_offset_val = field_data_accessor_->GetValue<uint32_t>();
105     if (string_offset_val.has_value()) {
106         std::string_view val {reinterpret_cast<const char *>(
107             file_->GetStringData(panda_file::File::EntityId(string_offset_val.value())).data)};
108         field_.metadata->SetValue(pandasm::ScalarValue::Create<pandasm::Value::Type::STRING>(val));
109     }
110 }
111 
FillLiteralArrayMetaData()112 void AbcFieldProcessor::FillLiteralArrayMetaData()
113 {
114     std::optional<uint32_t> litarray_offset_val = field_data_accessor_->GetValue<uint32_t>();
115     if (litarray_offset_val.has_value()) {
116         panda_file::LiteralDataAccessor literal_data_accessor(*file_, file_->GetLiteralArraysId());
117         AbcLiteralArrayProcessor abcLitarrayProcessor{panda_file::File::EntityId{litarray_offset_val.value()},
118                                                       entity_container_, literal_data_accessor};
119         abcLitarrayProcessor.FillProgramData();
120         std::string name = entity_container_.GetLiteralArrayIdName(litarray_offset_val.value());
121         field_.metadata->SetValue(pandasm::ScalarValue::Create<pandasm::Value::Type::LITERALARRAY>(
122             std::string_view {name}));
123     }
124 }
125 
FillMetaDataValue()126 void AbcFieldProcessor::FillMetaDataValue()
127 {
128     switch (field_.type.GetId()) {
129         case panda_file::Type::TypeId::U32: {
130             FillU32MetaData();
131             break;
132         }
133         case panda_file::Type::TypeId::U8: {
134             const uint8_t val = field_data_accessor_->GetValue<uint8_t>().value();
135             field_.metadata->SetValue(pandasm::ScalarValue::Create<pandasm::Value::Type::U8>(val));
136             break;
137         }
138         case panda_file::Type::TypeId::F64: {
139             std::optional<double> val = field_data_accessor_->GetValue<double>();
140             if (val.has_value()) {
141                 field_.metadata->SetValue(pandasm::ScalarValue::Create<pandasm::Value::Type::F64>(val.value()));
142             }
143             break;
144         }
145         case panda_file::Type::TypeId::U1: {
146             std::optional<bool> val = field_data_accessor_->GetValue<bool>();
147             if (val.has_value()) {
148                 field_.metadata->SetValue(pandasm::ScalarValue::Create<pandasm::Value::Type::U1>(val.value()));
149             }
150             break;
151         }
152         case panda_file::Type::TypeId::REFERENCE: {
153             if (field_.type.GetName() == "panda.String") {
154                 FillStringMetaData();
155             }
156             if (field_.type.IsArray()) {
157                 FillLiteralArrayMetaData();
158             }
159             break;
160         }
161         default:
162             UNREACHABLE();
163     }
164 }
165 
FillFieldAnnotations()166 void AbcFieldProcessor::FillFieldAnnotations()
167 {
168     log::Unimplemented(__PRETTY_FUNCTION__);
169 }
170 
171 }  // namespace panda::abc2program
172