1 /*
2 * Copyright 2019 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "struct_def.h"
18
19 #include "fields/all_fields.h"
20 #include "util.h"
21
StructDef(std::string name,FieldList fields)22 StructDef::StructDef(std::string name, FieldList fields) : StructDef(name, fields, nullptr) {}
StructDef(std::string name,FieldList fields,StructDef * parent)23 StructDef::StructDef(std::string name, FieldList fields, StructDef* parent)
24 : ParentDef(name, fields, parent), total_size_(GetSize(true)) {}
25
GetNewField(const std::string & name,ParseLocation loc) const26 PacketField* StructDef::GetNewField(const std::string& name, ParseLocation loc) const {
27 if (fields_.HasBody()) {
28 return new VariableLengthStructField(name, name_, loc);
29 } else {
30 return new StructField(name, name_, total_size_, loc);
31 }
32 }
33
GetDefinitionType() const34 TypeDef::Type StructDef::GetDefinitionType() const {
35 return TypeDef::Type::STRUCT;
36 }
37
GenSpecialize(std::ostream & s) const38 void StructDef::GenSpecialize(std::ostream& s) const {
39 if (parent_ == nullptr) {
40 return;
41 }
42 s << "static " << name_ << "* Specialize(" << parent_->name_ << "* parent) {";
43 s << "ASSERT(" << name_ << "::IsInstance(*parent));";
44 s << "return static_cast<" << name_ << "*>(parent);";
45 s << "}";
46 }
47
GenParse(std::ostream & s) const48 void StructDef::GenParse(std::ostream& s) const {
49 std::string iterator = (is_little_endian_ ? "Iterator<kLittleEndian>" : "Iterator<!kLittleEndian>");
50
51 if (fields_.HasBody()) {
52 s << "static std::optional<" << iterator << ">";
53 } else {
54 s << "static " << iterator;
55 }
56
57 s << " Parse(" << name_ << "* to_fill, " << iterator << " struct_begin_it ";
58
59 if (parent_ != nullptr) {
60 s << ", bool fill_parent = true) {";
61 } else {
62 s << ") {";
63 }
64 s << "auto to_bound = struct_begin_it;";
65
66 if (parent_ != nullptr) {
67 s << "if (fill_parent) {";
68 std::string parent_param = (parent_->parent_ == nullptr ? "" : ", true");
69 if (parent_->fields_.HasBody()) {
70 s << "auto parent_optional_it = " << parent_->name_ << "::Parse(to_fill, to_bound" << parent_param << ");";
71 if (fields_.HasBody()) {
72 s << "if (!parent_optional_it) { return {}; }";
73 } else {
74 s << "ASSERT(parent_optional_it);";
75 }
76 } else {
77 s << parent_->name_ << "::Parse(to_fill, to_bound" << parent_param << ");";
78 }
79 s << "}";
80 }
81
82 if (!fields_.HasBody()) {
83 s << "size_t end_index = struct_begin_it.NumBytesRemaining();";
84 if (parent_ != nullptr) {
85 s << "if (end_index < " << GetSize().bytes() << " - to_fill->" << parent_->name_ << "::size())";
86 } else {
87 s << "if (end_index < " << GetSize().bytes() << ")";
88 }
89 s << "{ return struct_begin_it.Subrange(0,0);}";
90 }
91
92 Size total_bits{0};
93 for (const auto& field : fields_) {
94 if (field->GetFieldType() != ReservedField::kFieldType && field->GetFieldType() != BodyField::kFieldType &&
95 field->GetFieldType() != FixedScalarField::kFieldType && field->GetFieldType() != SizeField::kFieldType &&
96 field->GetFieldType() != ChecksumStartField::kFieldType && field->GetFieldType() != ChecksumField::kFieldType &&
97 field->GetFieldType() != CountField::kFieldType) {
98 total_bits += field->GetSize().bits();
99 }
100 }
101 s << "{";
102 s << "if (to_bound.NumBytesRemaining() < " << total_bits.bytes() << ")";
103 if (!fields_.HasBody()) {
104 s << "{ return to_bound.Subrange(to_bound.NumBytesRemaining(),0);}";
105 } else {
106 s << "{ return {};}";
107 }
108 s << "}";
109 for (const auto& field : fields_) {
110 if (field->GetFieldType() != ReservedField::kFieldType && field->GetFieldType() != BodyField::kFieldType &&
111 field->GetFieldType() != FixedScalarField::kFieldType && field->GetFieldType() != SizeField::kFieldType &&
112 field->GetFieldType() != ChecksumStartField::kFieldType && field->GetFieldType() != ChecksumField::kFieldType &&
113 field->GetFieldType() != CountField::kFieldType) {
114 s << "{";
115 int num_leading_bits =
116 field->GenBounds(s, GetStructOffsetForField(field->GetName()), Size(), field->GetStructSize());
117 s << "auto " << field->GetName() << "_ptr = &to_fill->" << field->GetName() << "_;";
118 field->GenExtractor(s, num_leading_bits, true);
119 s << "}";
120 }
121 if (field->GetFieldType() == CountField::kFieldType || field->GetFieldType() == SizeField::kFieldType) {
122 s << field->GetDataType() << " " << field->GetName() << "_extracted;";
123 s << "{";
124 s << "if (to_bound.NumBytesRemaining() < " << field->GetSize().bytes() << ")";
125 if (!fields_.HasBody()) {
126 s << "{ return to_bound.Subrange(to_bound.NumBytesRemaining(),0);}";
127 } else {
128 s << "{ return {};}";
129 }
130 int num_leading_bits =
131 field->GenBounds(s, GetStructOffsetForField(field->GetName()), Size(), field->GetStructSize());
132 s << "auto " << field->GetName() << "_ptr = &" << field->GetName() << "_extracted;";
133 field->GenExtractor(s, num_leading_bits, true);
134 s << "}";
135 }
136 }
137 s << "return struct_begin_it + to_fill->" << name_ << "::size();";
138 s << "}";
139 }
140
GenParseFunctionPrototype(std::ostream & s) const141 void StructDef::GenParseFunctionPrototype(std::ostream& s) const {
142 s << "std::unique_ptr<" << name_ << "> Parse" << name_ << "(";
143 if (is_little_endian_) {
144 s << "Iterator<kLittleEndian>";
145 } else {
146 s << "Iterator<!kLittleEndian>";
147 }
148 s << "it);";
149 }
150
GenDefinition(std::ostream & s) const151 void StructDef::GenDefinition(std::ostream& s) const {
152 s << "class " << name_;
153 if (parent_ != nullptr) {
154 s << " : public " << parent_->name_;
155 } else {
156 if (is_little_endian_) {
157 s << " : public PacketStruct<kLittleEndian>";
158 } else {
159 s << " : public PacketStruct<!kLittleEndian>";
160 }
161 }
162 s << " {";
163 s << " public:";
164
165 GenConstructor(s);
166
167 s << " public:\n";
168 s << " virtual ~" << name_ << "() override = default;\n";
169
170 GenSerialize(s);
171 s << "\n";
172
173 GenParse(s);
174 s << "\n";
175
176 GenSize(s);
177 s << "\n";
178
179 GenInstanceOf(s);
180 s << "\n";
181
182 GenSpecialize(s);
183 s << "\n";
184
185 GenMembers(s);
186 s << "};\n";
187
188 if (fields_.HasBody()) {
189 GenParseFunctionPrototype(s);
190 }
191 s << "\n";
192 }
193
GenDefinitionPybind11(std::ostream & s) const194 void StructDef::GenDefinitionPybind11(std::ostream& s) const {
195 s << "py::class_<" << name_;
196 if (parent_ != nullptr) {
197 s << ", " << parent_->name_;
198 } else {
199 if (is_little_endian_) {
200 s << ", PacketStruct<kLittleEndian>";
201 } else {
202 s << ", PacketStruct<!kLittleEndian>";
203 }
204 }
205 s << ", std::shared_ptr<" << name_ << ">";
206 s << ">(m, \"" << name_ << "\")";
207 s << ".def(py::init<>())";
208 s << ".def(\"Serialize\", [](" << GetTypeName() << "& obj){";
209 s << "std::vector<uint8_t> bytes;";
210 s << "BitInserter bi(bytes);";
211 s << "obj.Serialize(bi);";
212 s << "return bytes;})";
213 s << ".def(\"Parse\", &" << name_ << "::Parse)";
214 s << ".def(\"size\", &" << name_ << "::size)";
215 for (const auto& field : fields_) {
216 if (field->GetBuilderParameterType().empty()) {
217 continue;
218 }
219 s << ".def_readwrite(\"" << field->GetName() << "\", &" << name_ << "::" << field->GetName() << "_)";
220 }
221 s << ";\n";
222 }
223
GenConstructor(std::ostream & s) const224 void StructDef::GenConstructor(std::ostream& s) const {
225 if (parent_ != nullptr) {
226 s << name_ << "(const " << parent_->name_ << "& parent) : " << parent_->name_ << "(parent) {}";
227 s << name_ << "() : " << parent_->name_ << "() {";
228 } else {
229 s << name_ << "() {";
230 }
231
232 // Get the list of parent params.
233 FieldList parent_params;
234 if (parent_ != nullptr) {
235 parent_params = parent_->GetParamList().GetFieldsWithoutTypes({
236 PayloadField::kFieldType,
237 BodyField::kFieldType,
238 });
239
240 // Set constrained parent fields to their correct values.
241 for (int i = 0; i < parent_params.size(); i++) {
242 const auto& field = parent_params[i];
243 const auto& constraint = parent_constraints_.find(field->GetName());
244 if (constraint != parent_constraints_.end()) {
245 s << parent_->name_ << "::" << field->GetName() << "_ = ";
246 if (field->GetFieldType() == ScalarField::kFieldType) {
247 s << std::get<int64_t>(constraint->second) << ";";
248 } else if (field->GetFieldType() == EnumField::kFieldType) {
249 s << std::get<std::string>(constraint->second) << ";";
250 } else {
251 ERROR(field) << "Constraints on non enum/scalar fields should be impossible.";
252 }
253 }
254 }
255 }
256
257 s << "}\n";
258 }
259
GetStructOffsetForField(std::string field_name) const260 Size StructDef::GetStructOffsetForField(std::string field_name) const {
261 auto size = Size(0);
262 for (auto it = fields_.begin(); it != fields_.end(); it++) {
263 // We've reached the field, end the loop.
264 if ((*it)->GetName() == field_name) break;
265 const auto& field = *it;
266 // When we need to parse this field, all previous fields should already be parsed.
267 if (field->GetStructSize().empty()) {
268 ERROR() << "Empty size for field " << (*it)->GetName() << " finding the offset for field: " << field_name;
269 }
270 size += field->GetStructSize();
271 }
272
273 // We need the offset until a body field.
274 if (parent_ != nullptr) {
275 auto parent_body_offset = static_cast<StructDef*>(parent_)->GetStructOffsetForField("body");
276 if (parent_body_offset.empty()) {
277 ERROR() << "Empty offset for body in " << parent_->name_ << " finding the offset for field: " << field_name;
278 }
279 size += parent_body_offset;
280 }
281
282 return size;
283 }
284