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