• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
GenToString(std::ostream & s) const48 void StructDef::GenToString(std::ostream& s) const {
49   s << "std::string ToString() {";
50   s << "std::stringstream ss;";
51   s << "ss << std::hex << std::showbase << \"" << name_ << " { \";";
52 
53   if (fields_.size() > 0) {
54     s << "ss";
55     bool firstfield = true;
56     for (const auto& field : fields_) {
57       if (field->GetFieldType() == ReservedField::kFieldType ||
58           field->GetFieldType() == ChecksumStartField::kFieldType ||
59           field->GetFieldType() == FixedScalarField::kFieldType || field->GetFieldType() == CountField::kFieldType ||
60           field->GetFieldType() == SizeField::kFieldType)
61         continue;
62 
63       s << (firstfield ? " << \"" : " << \", ") << field->GetName() << " = \" << ";
64 
65       field->GenStringRepresentation(s, field->GetName() + "_");
66 
67       if (firstfield) {
68         firstfield = false;
69       }
70     }
71     s << ";";
72   }
73 
74   s << "ss << \" }\";";
75   s << "return ss.str();";
76   s << "}\n";
77 }
78 
GenParse(std::ostream & s) const79 void StructDef::GenParse(std::ostream& s) const {
80   std::string iterator = (is_little_endian_ ? "Iterator<kLittleEndian>" : "Iterator<!kLittleEndian>");
81 
82   if (fields_.HasBody()) {
83     s << "static std::optional<" << iterator << ">";
84   } else {
85     s << "static " << iterator;
86   }
87 
88   s << " Parse(" << name_ << "* to_fill, " << iterator << " struct_begin_it ";
89 
90   if (parent_ != nullptr) {
91     s << ", bool fill_parent = true) {";
92   } else {
93     s << ") {";
94   }
95   s << "auto to_bound = struct_begin_it;";
96 
97   if (parent_ != nullptr) {
98     s << "if (fill_parent) {";
99     std::string parent_param = (parent_->parent_ == nullptr ? "" : ", true");
100     if (parent_->fields_.HasBody()) {
101       s << "auto parent_optional_it = " << parent_->name_ << "::Parse(to_fill, to_bound" << parent_param << ");";
102       if (fields_.HasBody()) {
103         s << "if (!parent_optional_it) { return {}; }";
104       } else {
105         s << "ASSERT(parent_optional_it);";
106       }
107     } else {
108       s << parent_->name_ << "::Parse(to_fill, to_bound" << parent_param << ");";
109     }
110     s << "}";
111   }
112 
113   if (!fields_.HasBody()) {
114     s << "size_t end_index = struct_begin_it.NumBytesRemaining();";
115     s << "if (end_index < " << GetSize().bytes() << ")";
116     s << "{ return struct_begin_it.Subrange(0,0);}";
117   }
118 
119   Size total_bits{0};
120   for (const auto& field : fields_) {
121     if (field->GetFieldType() != ReservedField::kFieldType && field->GetFieldType() != BodyField::kFieldType &&
122         field->GetFieldType() != FixedScalarField::kFieldType &&
123         field->GetFieldType() != ChecksumStartField::kFieldType && field->GetFieldType() != ChecksumField::kFieldType &&
124         field->GetFieldType() != CountField::kFieldType) {
125       total_bits += field->GetSize().bits();
126     }
127   }
128   s << "{";
129   s << "if (to_bound.NumBytesRemaining() < " << total_bits.bytes() << ")";
130   if (!fields_.HasBody()) {
131     s << "{ return to_bound.Subrange(to_bound.NumBytesRemaining(),0);}";
132   } else {
133     s << "{ return {};}";
134   }
135   s << "}";
136   for (const auto& field : fields_) {
137     if (field->GetFieldType() != ReservedField::kFieldType && field->GetFieldType() != BodyField::kFieldType &&
138         field->GetFieldType() != FixedScalarField::kFieldType && field->GetFieldType() != SizeField::kFieldType &&
139         field->GetFieldType() != ChecksumStartField::kFieldType && field->GetFieldType() != ChecksumField::kFieldType &&
140         field->GetFieldType() != CountField::kFieldType) {
141       s << "{";
142       int num_leading_bits =
143           field->GenBounds(s, GetStructOffsetForField(field->GetName()), Size(), field->GetStructSize());
144       s << "auto " << field->GetName() << "_ptr = &to_fill->" << field->GetName() << "_;";
145       field->GenExtractor(s, num_leading_bits, true);
146       s << "}";
147     }
148     if (field->GetFieldType() == CountField::kFieldType || field->GetFieldType() == SizeField::kFieldType) {
149       s << "{";
150       int num_leading_bits =
151           field->GenBounds(s, GetStructOffsetForField(field->GetName()), Size(), field->GetStructSize());
152       s << "auto " << field->GetName() << "_ptr = &to_fill->" << field->GetName() << "_extracted_;";
153       field->GenExtractor(s, num_leading_bits, true);
154       s << "}";
155     }
156   }
157   s << "return struct_begin_it + to_fill->size();";
158   s << "}";
159 }
160 
GenParseFunctionPrototype(std::ostream & s) const161 void StructDef::GenParseFunctionPrototype(std::ostream& s) const {
162   s << "std::unique_ptr<" << name_ << "> Parse" << name_ << "(";
163   if (is_little_endian_) {
164     s << "Iterator<kLittleEndian>";
165   } else {
166     s << "Iterator<!kLittleEndian>";
167   }
168   s << "it);";
169 }
170 
GenDefinition(std::ostream & s) const171 void StructDef::GenDefinition(std::ostream& s) const {
172   s << "class " << name_;
173   if (parent_ != nullptr) {
174     s << " : public " << parent_->name_;
175   } else {
176     if (is_little_endian_) {
177       s << " : public PacketStruct<kLittleEndian>";
178     } else {
179       s << " : public PacketStruct<!kLittleEndian>";
180     }
181   }
182   s << " {";
183   s << " public:";
184 
185   GenConstructor(s);
186 
187   s << " public:\n";
188   s << "  virtual ~" << name_ << "() = default;\n";
189 
190   GenSerialize(s);
191   s << "\n";
192 
193   GenParse(s);
194   s << "\n";
195 
196   GenSize(s);
197   s << "\n";
198 
199   GenInstanceOf(s);
200   s << "\n";
201 
202   GenSpecialize(s);
203   s << "\n";
204 
205   GenToString(s);
206   s << "\n";
207 
208   GenMembers(s);
209   for (const auto& field : fields_) {
210     if (field->GetFieldType() == CountField::kFieldType || field->GetFieldType() == SizeField::kFieldType) {
211       s << "\n private:\n";
212       s << " mutable " << field->GetDataType() << " " << field->GetName() << "_extracted_{0};";
213     }
214   }
215   s << "};\n";
216 
217   if (fields_.HasBody()) {
218     GenParseFunctionPrototype(s);
219   }
220   s << "\n";
221 }
222 
GenDefinitionPybind11(std::ostream & s) const223 void StructDef::GenDefinitionPybind11(std::ostream& s) const {
224   s << "py::class_<" << name_;
225   if (parent_ != nullptr) {
226     s << ", " << parent_->name_;
227   } else {
228     if (is_little_endian_) {
229       s << ", PacketStruct<kLittleEndian>";
230     } else {
231       s << ", PacketStruct<!kLittleEndian>";
232     }
233   }
234   s << ", std::shared_ptr<" << name_ << ">";
235   s << ">(m, \"" << name_ << "\")";
236   s << ".def(py::init<>())";
237   s << ".def(\"Serialize\", [](" << GetTypeName() << "& obj){";
238   s << "std::vector<uint8_t> bytes;";
239   s << "BitInserter bi(bytes);";
240   s << "obj.Serialize(bi);";
241   s << "return bytes;})";
242   s << ".def(\"Parse\", &" << name_ << "::Parse)";
243   s << ".def(\"size\", &" << name_ << "::size)";
244   for (const auto& field : fields_) {
245     if (field->GetBuilderParameterType().empty()) {
246       continue;
247     }
248     s << ".def_readwrite(\"" << field->GetName() << "\", &" << name_ << "::" << field->GetName() << "_)";
249   }
250   s << ";\n";
251 }
252 
GenConstructor(std::ostream & s) const253 void StructDef::GenConstructor(std::ostream& s) const {
254   if (parent_ != nullptr) {
255     s << name_ << "(const " << parent_->name_ << "& parent) : " << parent_->name_ << "(parent) {}";
256     s << name_ << "() : " << parent_->name_ << "() {";
257   } else {
258     s << name_ << "() {";
259   }
260 
261   // Get the list of parent params.
262   FieldList parent_params;
263   if (parent_ != nullptr) {
264     parent_params = parent_->GetParamList().GetFieldsWithoutTypes({
265         PayloadField::kFieldType,
266         BodyField::kFieldType,
267     });
268 
269     // Set constrained parent fields to their correct values.
270     for (const auto& field : parent_params) {
271       const auto& constraint = parent_constraints_.find(field->GetName());
272       if (constraint != parent_constraints_.end()) {
273         s << parent_->name_ << "::" << field->GetName() << "_ = ";
274         if (field->GetFieldType() == ScalarField::kFieldType) {
275           s << std::get<int64_t>(constraint->second) << ";";
276         } else if (field->GetFieldType() == EnumField::kFieldType) {
277           s << std::get<std::string>(constraint->second) << ";";
278         } else {
279           ERROR(field) << "Constraints on non enum/scalar fields should be impossible.";
280         }
281       }
282     }
283   }
284 
285   s << "}\n";
286 }
287 
GetStructOffsetForField(std::string field_name) const288 Size StructDef::GetStructOffsetForField(std::string field_name) const {
289   auto size = Size(0);
290   for (auto it = fields_.begin(); it != fields_.end(); it++) {
291     // We've reached the field, end the loop.
292     if ((*it)->GetName() == field_name) break;
293     const auto& field = *it;
294     // When we need to parse this field, all previous fields should already be parsed.
295     if (field->GetStructSize().empty()) {
296       ERROR() << "Empty size for field " << (*it)->GetName() << " finding the offset for field: " << field_name;
297     }
298     size += field->GetStructSize();
299   }
300 
301   // We need the offset until a body field.
302   if (parent_ != nullptr) {
303     auto parent_body_offset = static_cast<StructDef*>(parent_)->GetStructOffsetForField("body");
304     if (parent_body_offset.empty()) {
305       ERROR() << "Empty offset for body in " << parent_->name_ << " finding the offset for field: " << field_name;
306     }
307     size += parent_body_offset;
308   }
309 
310   return size;
311 }
312 
GenRustFieldNameAndType(std::ostream & s,bool include_fixed) const313 void StructDef::GenRustFieldNameAndType(std::ostream& s, bool include_fixed) const {
314   auto fields = fields_.GetFieldsWithoutTypes({
315       BodyField::kFieldType,
316       CountField::kFieldType,
317       PaddingField::kFieldType,
318       ReservedField::kFieldType,
319       SizeField::kFieldType,
320   });
321   for (const auto& field : fields) {
322     if (!include_fixed && field->GetFieldType() == FixedScalarField::kFieldType) {
323       continue;
324     }
325     field->GenRustNameAndType(s);
326     s << ", ";
327   }
328 }
329 
GenRustFieldNames(std::ostream & s) const330 void StructDef::GenRustFieldNames(std::ostream& s) const {
331   auto fields = fields_.GetFieldsWithoutTypes({
332       BodyField::kFieldType,
333       CountField::kFieldType,
334       PaddingField::kFieldType,
335       ReservedField::kFieldType,
336       SizeField::kFieldType,
337   });
338   for (const auto& field : fields) {
339     s << field->GetName();
340     s << ", ";
341   }
342 }
343 
GenRustDeclarations(std::ostream & s) const344 void StructDef::GenRustDeclarations(std::ostream& s) const {
345   s << "#[derive(Debug, Clone)] ";
346   s << "pub struct " << name_ << "{";
347 
348   // Generate struct fields
349   auto fields = fields_.GetFieldsWithoutTypes({
350       BodyField::kFieldType,
351       CountField::kFieldType,
352       PaddingField::kFieldType,
353       ReservedField::kFieldType,
354       SizeField::kFieldType,
355   });
356   for (const auto& field : fields) {
357     s << "pub ";
358     field->GenRustNameAndType(s);
359     s << ", ";
360   }
361   s << "}\n";
362 }
363 
GenRustImpls(std::ostream & s) const364 void StructDef::GenRustImpls(std::ostream& s) const {
365   s << "impl " << name_ << "{";
366 
367   s << "fn conforms(bytes: &[u8]) -> bool {";
368   GenRustConformanceCheck(s);
369   s << " true";
370   s << "}";
371 
372   s << "pub fn parse(bytes: &[u8]) -> Result<Self> {";
373   auto fields = fields_.GetFieldsWithoutTypes({
374       BodyField::kFieldType,
375   });
376 
377   for (const auto& field : fields) {
378     auto start_field_offset = GetOffsetForField(field->GetName(), false);
379     auto end_field_offset = GetOffsetForField(field->GetName(), true);
380 
381     if (start_field_offset.empty() && end_field_offset.empty()) {
382       ERROR(field) << "Field location for " << field->GetName() << " is ambiguous, "
383                    << "no method exists to determine field location from begin() or end().\n";
384     }
385 
386     field->GenBoundsCheck(s, start_field_offset, end_field_offset, name_);
387     field->GenRustGetter(s, start_field_offset, end_field_offset);
388   }
389 
390   fields = fields_.GetFieldsWithoutTypes({
391       BodyField::kFieldType,
392       CountField::kFieldType,
393       PaddingField::kFieldType,
394       ReservedField::kFieldType,
395       SizeField::kFieldType,
396   });
397 
398   s << "Ok(Self {";
399   for (const auto& field : fields) {
400     if (field->GetFieldType() == FixedScalarField::kFieldType) {
401       s << field->GetName() << ": ";
402       static_cast<FixedScalarField*>(field)->GenValue(s);
403     } else {
404       s << field->GetName();
405     }
406     s << ", ";
407   }
408   s << "})}\n";
409 
410   // write_to function
411   s << "fn write_to(&self, buffer: &mut [u8]) {";
412   GenRustWriteToFields(s);
413   s << "}\n";
414 
415   s << "fn get_total_size(&self) -> usize {";
416   GenSizeRetVal(s);
417   s << "}";
418   s << "}\n";
419 }
420 
GenRustDef(std::ostream & s) const421 void StructDef::GenRustDef(std::ostream& s) const {
422   GenRustDeclarations(s);
423   GenRustImpls(s);
424 }
425