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 "fields/array_field.h"
18
19 #include "fields/custom_field.h"
20 #include "fields/scalar_field.h"
21 #include "util.h"
22
23 const std::string ArrayField::kFieldType = "ArrayField";
24
ArrayField(std::string name,int element_size,int array_size,ParseLocation loc)25 ArrayField::ArrayField(std::string name, int element_size, int array_size, ParseLocation loc)
26 : PacketField(name, loc), element_field_(new ScalarField("val", element_size, loc)), element_size_(element_size),
27 array_size_(array_size) {
28 if (element_size > 64 || element_size < 0)
29 ERROR(this) << __func__ << ": Not implemented for element size = " << element_size;
30 if (element_size % 8 != 0) {
31 ERROR(this) << "Can only have arrays with elements that are byte aligned (" << element_size << ")";
32 }
33 }
34
ArrayField(std::string name,TypeDef * type_def,int array_size,ParseLocation loc)35 ArrayField::ArrayField(std::string name, TypeDef* type_def, int array_size, ParseLocation loc)
36 : PacketField(name, loc), element_field_(type_def->GetNewField("val", loc)),
37 element_size_(element_field_->GetSize()), array_size_(array_size) {
38 if (!element_size_.empty() && element_size_.bits() % 8 != 0) {
39 ERROR(this) << "Can only have arrays with elements that are byte aligned (" << element_size_ << ")";
40 }
41 }
42
GetFieldType() const43 const std::string& ArrayField::GetFieldType() const {
44 return ArrayField::kFieldType;
45 }
46
GetSize() const47 Size ArrayField::GetSize() const {
48 if (!element_size_.empty() && !element_size_.has_dynamic()) {
49 return Size(array_size_ * element_size_.bits());
50 }
51 return Size();
52 }
53
GetBuilderSize() const54 Size ArrayField::GetBuilderSize() const {
55 if (!element_size_.empty() && !element_size_.has_dynamic()) {
56 return GetSize();
57 } else if (element_field_->BuilderParameterMustBeMoved()) {
58 std::string ret = "[this](){ size_t length = 0; for (const auto& elem : " + GetName() +
59 "_) { length += elem->size() * 8; } return length; }()";
60 return ret;
61 } else {
62 std::string ret = "[this](){ size_t length = 0; for (const auto& elem : " + GetName() +
63 "_) { length += elem.size() * 8; } return length; }()";
64 return ret;
65 }
66 }
67
GetStructSize() const68 Size ArrayField::GetStructSize() const {
69 if (!element_size_.empty() && !element_size_.has_dynamic()) {
70 return GetSize();
71 } else if (element_field_->BuilderParameterMustBeMoved()) {
72 std::string ret = "[this](){ size_t length = 0; for (const auto& elem : to_fill->" + GetName() +
73 "_) { length += elem->size() * 8; } return length; }()";
74 return ret;
75 } else {
76 std::string ret = "[this](){ size_t length = 0; for (const auto& elem : to_fill->" + GetName() +
77 "_) { length += elem.size() * 8; } return length; }()";
78 return ret;
79 }
80 }
81
GetDataType() const82 std::string ArrayField::GetDataType() const {
83 return "std::array<" + element_field_->GetDataType() + "," + std::to_string(array_size_) + ">";
84 }
85
GenExtractor(std::ostream & s,int num_leading_bits,bool for_struct) const86 void ArrayField::GenExtractor(std::ostream& s, int num_leading_bits, bool for_struct) const {
87 s << GetDataType() << "::iterator ret_it = " << GetName() << "_ptr->begin();";
88 s << "auto " << element_field_->GetName() << "_it = " << GetName() << "_it;";
89 if (!element_size_.empty()) {
90 s << "while (" << element_field_->GetName() << "_it.NumBytesRemaining() >= " << element_size_.bytes();
91 s << " && ret_it < " << GetName() << "_ptr->end()) {";
92 } else {
93 s << "while (" << element_field_->GetName() << "_it.NumBytesRemaining() > 0 ";
94 s << " && ret_it < " << GetName() << "_ptr->end()) {";
95 }
96 if (element_field_->BuilderParameterMustBeMoved()) {
97 s << element_field_->GetDataType() << " " << element_field_->GetName() << "_ptr;";
98 } else {
99 s << "auto " << element_field_->GetName() << "_ptr = ret_it;";
100 }
101 element_field_->GenExtractor(s, num_leading_bits, for_struct);
102 if (element_field_->BuilderParameterMustBeMoved()) {
103 s << "*ret_it = std::move(" << element_field_->GetName() << "_ptr);";
104 }
105 s << "ret_it++;";
106 s << "}";
107 }
108
GetGetterFunctionName() const109 std::string ArrayField::GetGetterFunctionName() const {
110 std::stringstream ss;
111 ss << "Get" << util::UnderscoreToCamelCase(GetName());
112 return ss.str();
113 }
114
GenGetter(std::ostream & s,Size start_offset,Size end_offset) const115 void ArrayField::GenGetter(std::ostream& s, Size start_offset, Size end_offset) const {
116 s << GetDataType() << " " << GetGetterFunctionName() << "() {";
117 s << "ASSERT(was_validated_);";
118 s << "size_t end_index = size();";
119 s << "auto to_bound = begin();";
120
121 int num_leading_bits = GenBounds(s, start_offset, end_offset, GetSize());
122 s << GetDataType() << " " << GetName() << "_value{};";
123 s << GetDataType() << "* " << GetName() << "_ptr = &" << GetName() << "_value;";
124 GenExtractor(s, num_leading_bits, false);
125
126 s << "return " << GetName() << "_value;";
127 s << "}\n";
128 }
129
GetBuilderParameterType() const130 std::string ArrayField::GetBuilderParameterType() const {
131 std::stringstream ss;
132 if (element_field_->BuilderParameterMustBeMoved()) {
133 ss << "std::array<" << element_field_->GetDataType() << "," << array_size_ << ">";
134 } else {
135 ss << "const std::array<" << element_field_->GetDataType() << "," << array_size_ << ">&";
136 }
137 return ss.str();
138 }
139
BuilderParameterMustBeMoved() const140 bool ArrayField::BuilderParameterMustBeMoved() const {
141 return element_field_->BuilderParameterMustBeMoved();
142 }
143
GenBuilderMember(std::ostream & s) const144 bool ArrayField::GenBuilderMember(std::ostream& s) const {
145 s << "std::array<" << element_field_->GetDataType() << "," << array_size_ << "> " << GetName();
146 return true;
147 }
148
HasParameterValidator() const149 bool ArrayField::HasParameterValidator() const {
150 return false;
151 }
152
GenParameterValidator(std::ostream &) const153 void ArrayField::GenParameterValidator(std::ostream&) const {
154 // Array length is validated by the compiler
155 }
156
GenInserter(std::ostream & s) const157 void ArrayField::GenInserter(std::ostream& s) const {
158 s << "for (const auto& val_ : " << GetName() << "_) {";
159 element_field_->GenInserter(s);
160 s << "}\n";
161 }
162
GenValidator(std::ostream &) const163 void ArrayField::GenValidator(std::ostream&) const {
164 // NOTE: We could check if the element size divides cleanly into the array size, but we decided to forgo that
165 // in favor of just returning as many elements as possible in a best effort style.
166 //
167 // Other than that there is nothing that arrays need to be validated on other than length so nothing needs to
168 // be done here.
169 }
170
IsContainerField() const171 bool ArrayField::IsContainerField() const {
172 return true;
173 }
174
GetElementField() const175 const PacketField* ArrayField::GetElementField() const {
176 return element_field_;
177 }
178
GenStringRepresentation(std::ostream & s,std::string accessor) const179 void ArrayField::GenStringRepresentation(std::ostream& s, std::string accessor) const {
180 s << "\"ARRAY[\";";
181 s << "/* " << element_field_->GetDataType() << " " << element_field_->GetFieldType() << " */";
182
183 std::string arr_idx = "arridx_" + accessor;
184 std::string arr_size = std::to_string(array_size_);
185 s << "for (size_t index = 0; index < " << arr_size << "; index++) {";
186 std::string element_accessor = "(" + accessor + "[index])";
187 s << "ss << ((index == 0) ? \"\" : \", \") << ";
188
189 if (element_field_->GetFieldType() == CustomField::kFieldType) {
190 s << element_accessor << ".ToString()";
191 } else {
192 element_field_->GenStringRepresentation(s, element_accessor);
193 }
194
195 s << ";}";
196 s << "ss << \"]\"";
197 }
198
GetRustDataType() const199 std::string ArrayField::GetRustDataType() const {
200 return "[" + element_field_->GetRustDataType() + "; " + std::to_string(array_size_) + "]";
201 }
202
GenRustGetter(std::ostream & s,Size start_offset,Size,std::string) const203 void ArrayField::GenRustGetter(std::ostream& s, Size start_offset, Size, std::string) const {
204 s << "let " << GetName() << " = ";
205 s << "bytes[" << start_offset.bytes() << "..";
206 s << start_offset.bytes() + GetSize().bytes() << "].try_into()";
207 s << ".map_err(|_| Error::InvalidPacketError)?;";
208 }
209
GenRustWriter(std::ostream & s,Size start_offset,Size) const210 void ArrayField::GenRustWriter(std::ostream& s, Size start_offset, Size) const {
211 s << "&buffer[" << start_offset.bytes() << ".." << start_offset.bytes() + GetSize().bytes()
212 << "].copy_from_slice(&self." << GetName() << ");";
213 }
214