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_ << "() override = 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 (int i = 0; i < parent_params.size(); i++) {
271 const auto& field = parent_params[i];
272 const auto& constraint = parent_constraints_.find(field->GetName());
273 if (constraint != parent_constraints_.end()) {
274 s << parent_->name_ << "::" << field->GetName() << "_ = ";
275 if (field->GetFieldType() == ScalarField::kFieldType) {
276 s << std::get<int64_t>(constraint->second) << ";";
277 } else if (field->GetFieldType() == EnumField::kFieldType) {
278 s << std::get<std::string>(constraint->second) << ";";
279 } else {
280 ERROR(field) << "Constraints on non enum/scalar fields should be impossible.";
281 }
282 }
283 }
284 }
285
286 s << "}\n";
287 }
288
GetStructOffsetForField(std::string field_name) const289 Size StructDef::GetStructOffsetForField(std::string field_name) const {
290 auto size = Size(0);
291 for (auto it = fields_.begin(); it != fields_.end(); it++) {
292 // We've reached the field, end the loop.
293 if ((*it)->GetName() == field_name) break;
294 const auto& field = *it;
295 // When we need to parse this field, all previous fields should already be parsed.
296 if (field->GetStructSize().empty()) {
297 ERROR() << "Empty size for field " << (*it)->GetName() << " finding the offset for field: " << field_name;
298 }
299 size += field->GetStructSize();
300 }
301
302 // We need the offset until a body field.
303 if (parent_ != nullptr) {
304 auto parent_body_offset = static_cast<StructDef*>(parent_)->GetStructOffsetForField("body");
305 if (parent_body_offset.empty()) {
306 ERROR() << "Empty offset for body in " << parent_->name_ << " finding the offset for field: " << field_name;
307 }
308 size += parent_body_offset;
309 }
310
311 return size;
312 }
313