• 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 
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