Split ARRAY into fixed size ARRAY and VECTOR

Test: bluetooth_packet_parser_test
Change-Id: I438d7583fdb99054528b99a3a3a12ec58d115cb3
diff --git a/gd/hci/hci_layer_test.cc b/gd/hci/hci_layer_test.cc
index 5b5d3d7..a5b8f51 100644
--- a/gd/hci/hci_layer_test.cc
+++ b/gd/hci/hci_layer_test.cc
@@ -330,9 +330,9 @@
   ASSERT_EQ(0, hal->GetNumSentCommands());
 
   // Send the response event
-  std::vector<uint8_t> supported_commands;
+  std::array<uint8_t, 64> supported_commands;
   for (uint8_t i = 0; i < 64; i++) {
-    supported_commands.push_back(i);
+    supported_commands[i] = i;
   }
   hal->callbacks->hciEventReceived(
       GetPacketBytes(ReadLocalSupportedCommandsCompleteBuilder::Create(num_packets, error_code, supported_commands)));
diff --git a/gd/packet/parser/Android.bp b/gd/packet/parser/Android.bp
index 63aaa7a..4dc4950 100644
--- a/gd/packet/parser/Android.bp
+++ b/gd/packet/parser/Android.bp
@@ -2,6 +2,7 @@
     name: "bluetooth_packetgen",
     srcs: [
         "fields/array_field.cc",
+        "fields/vector_field.cc",
         "fields/body_field.cc",
         "fields/checksum_field.cc",
         "fields/checksum_start_field.cc",
diff --git a/gd/packet/parser/fields/all_fields.h b/gd/packet/parser/fields/all_fields.h
index 5797076..91323ea 100644
--- a/gd/packet/parser/fields/all_fields.h
+++ b/gd/packet/parser/fields/all_fields.h
@@ -31,3 +31,4 @@
 #include "fields/reserved_field.h"
 #include "fields/scalar_field.h"
 #include "fields/size_field.h"
+#include "fields/vector_field.h"
diff --git a/gd/packet/parser/fields/array_field.cc b/gd/packet/parser/fields/array_field.cc
index 612f874..a39236f 100644
--- a/gd/packet/parser/fields/array_field.cc
+++ b/gd/packet/parser/fields/array_field.cc
@@ -19,16 +19,6 @@
 
 const std::string ArrayField::kFieldType = "ArrayField";
 
-ArrayField::ArrayField(std::string name, int element_size, std::string size_modifier, ParseLocation loc)
-    : PacketField(name, loc), element_size_(element_size), size_modifier_(size_modifier) {
-  // Make sure the element_size is a multiple of 8.
-  if (element_size_ > 64 || element_size_ < 0)
-    ERROR(this) << __func__ << ": Not implemented for element size = " << element_size_;
-  if (element_size % 8 != 0) {
-    ERROR(this) << "Can only have arrays with elements that are byte aligned (" << element_size << ")";
-  }
-}
-
 ArrayField::ArrayField(std::string name, int element_size, int fixed_size, ParseLocation loc)
     : PacketField(name, loc), element_size_(element_size), fixed_size_(fixed_size) {
   if (element_size_ > 64 || element_size_ < 0)
@@ -39,14 +29,6 @@
   }
 }
 
-ArrayField::ArrayField(std::string name, TypeDef* type_def, std::string size_modifier, ParseLocation loc)
-    : PacketField(name, loc), element_size_(type_def->size_), type_def_(type_def), size_modifier_(size_modifier) {
-  // If the element type is not variable sized, make sure that it is byte aligned.
-  if (type_def_->size_ != -1 && type_def_->size_ % 8 != 0) {
-    ERROR(this) << "Can only have arrays with elements that are byte aligned (" << type_def_->size_ << ")";
-  }
-}
-
 ArrayField::ArrayField(std::string name, TypeDef* type_def, int fixed_size, ParseLocation loc)
     : PacketField(name, loc), element_size_(type_def->size_), type_def_(type_def), fixed_size_(fixed_size) {
   // If the element type is not variable sized, make sure that it is byte aligned.
@@ -60,44 +42,15 @@
 }
 
 Size ArrayField::GetSize() const {
-  if (IsFixedSize() && element_size_ != -1) {
+  if (element_size_ != -1) {
     return Size(fixed_size_ * element_size_);
   }
-
-  // If there is no size field, then it is of unknown size.
-  if (size_field_ == nullptr) {
-    return Size();
-  }
-
-  // size_field_ is of type SIZE
-  if (size_field_->GetFieldType() == SizeField::kFieldType) {
-    std::string ret = "(Get" + util::UnderscoreToCamelCase(size_field_->GetName()) + "() * 8)";
-    if (!size_modifier_.empty()) ret += size_modifier_;
-    return ret;
-  }
-
-  // size_field_ is of type COUNT and it is a scalar array
-  if (type_def_ == nullptr) {
-    return "(Get" + util::UnderscoreToCamelCase(size_field_->GetName()) + "() * " + std::to_string(element_size_) + ")";
-  }
-
-  if (IsCustomFieldArray()) {
-    if (type_def_->size_ != -1) {
-      return "(Get" + util::UnderscoreToCamelCase(size_field_->GetName()) + "() * " + std::to_string(type_def_->size_) +
-             ")";
-    } else {
-      return Size();
-    }
-  }
-
-  // size_field_ is of type COUNT and it is an enum array
-  return "(Get" + util::UnderscoreToCamelCase(size_field_->GetName()) + "() * " + std::to_string(type_def_->size_) +
-         ")";
+  return Size();
 }
 
 Size ArrayField::GetBuilderSize() const {
   if (element_size_ != -1) {
-    std::string ret = "(" + GetName() + "_.size() * " + std::to_string(element_size_) + ")";
+    std::string ret = "(" + std::to_string(fixed_size_) + " * " + std::to_string(element_size_) + ")";
     return ret;
   } else {
     std::string ret = "[this](){ size_t length = 0; for (const auto& elem : " + GetName() +
@@ -108,9 +61,9 @@
 
 std::string ArrayField::GetDataType() const {
   if (type_def_ != nullptr) {
-    return "std::vector<" + type_def_->name_ + ">";
+    return "std::array<" + type_def_->name_ + "," + std::to_string(fixed_size_) + ">";
   }
-  return "std::vector<" + util::GetTypeForSize(element_size_) + ">";
+  return "std::array<" + util::GetTypeForSize(element_size_) + "," + std::to_string(fixed_size_) + ">";
 }
 
 void ArrayField::GenExtractor(std::ostream& s, Size start_offset, Size end_offset) const {
@@ -120,15 +73,19 @@
   s << "auto it = subview.begin();";
 
   // Add the element size so that we will extract as many elements as we can.
-  s << GetDataType() << " vec;";
+  s << GetDataType() << " ret;";
   if (element_size_ != -1) {
     std::string type = (type_def_ != nullptr) ? type_def_->name_ : util::GetTypeForSize(element_size_);
+    s << GetDataType() << "::iterator ret_it = ret.begin();";
     s << "while (it + sizeof(" << type << ") <= subview.end()) {";
-    s << "vec.push_back(it.extract<" << type << ">());";
+    s << "*ret_it = it.extract<" << type << ">();";
+    s << "ret_it++;";
     s << "}";
   } else {
+    s << "std::size_t ret_idx = 0;";
     s << "while (it < subview.end()) {";
-    s << "it = " << type_def_->name_ << "::Parse(vec, it);";
+    s << "it = " << type_def_->name_ << "::ParseArray(ret, &ret_idx, it);";
+    s << "ret_idx++;";
     s << "}";
   }
 }
@@ -136,49 +93,37 @@
 void ArrayField::GenGetter(std::ostream& s, Size start_offset, Size end_offset) const {
   s << GetDataType();
   s << " Get" << util::UnderscoreToCamelCase(GetName()) << "() {";
-  s << "ASSERT(was_validated_);";
 
   GenExtractor(s, start_offset, end_offset);
 
-  s << "return vec;";
+  s << "return ret;";
   s << "}\n";
 }
 
 bool ArrayField::GenBuilderParameter(std::ostream& s) const {
   if (type_def_ != nullptr) {
-    s << "const std::vector<" << type_def_->GetTypeName() << ">& " << GetName();
+    s << "const std::array<" << type_def_->GetTypeName() << "," << fixed_size_ << ">& " << GetName();
   } else {
-    s << "const std::vector<" << util::GetTypeForSize(element_size_) << ">& " << GetName();
+    s << "const std::array<" << util::GetTypeForSize(element_size_) << "," << fixed_size_ << ">& " << GetName();
   }
   return true;
 }
 
 bool ArrayField::GenBuilderMember(std::ostream& s) const {
   if (type_def_ != nullptr) {
-    s << "std::vector<" << type_def_->GetTypeName() << "> " << GetName();
+    s << "std::array<" << type_def_->GetTypeName() << "," << fixed_size_ << "> " << GetName();
   } else {
-    s << "std::vector<" << util::GetTypeForSize(element_size_) << "> " << GetName();
+    s << "std::array<" << util::GetTypeForSize(element_size_) << "," << fixed_size_ << "> " << GetName();
   }
   return true;
 }
 
 bool ArrayField::HasParameterValidator() const {
-  if (fixed_size_ == -1) {
-    // Does not have parameter validator yet.
-    // TODO: See comment in GenParameterValidator
-    return false;
-  }
-  return true;
+  return false;
 }
 
-void ArrayField::GenParameterValidator(std::ostream& s) const {
-  if (fixed_size_ == -1) {
-    // No Parameter validator if its dynamically size.
-    // TODO: Maybe add a validator to ensure that the size isn't larger than what the size field can hold.
-    return;
-  }
-
-  s << "ASSERT(" << GetName() << "_.size() == " << fixed_size_ << ");";
+void ArrayField::GenParameterValidator(std::ostream&) const {
+  // Array length is validated by the compiler
 }
 
 void ArrayField::GenInserter(std::ostream& s) const {
@@ -212,24 +157,3 @@
 bool ArrayField::IsCustomFieldArray() const {
   return type_def_ != nullptr && type_def_->GetDefinitionType() == TypeDef::Type::CUSTOM;
 }
-
-bool ArrayField::IsFixedSize() const {
-  return fixed_size_ != -1;
-}
-
-void ArrayField::SetSizeField(const SizeField* size_field) {
-  if (size_field->GetFieldType() == CountField::kFieldType && !size_modifier_.empty()) {
-    ERROR(this, size_field) << "Can not use count field to describe array with a size modifier."
-                            << " Use size instead";
-  }
-
-  if (IsFixedSize()) {
-    ERROR(this, size_field) << "Can not use size field with a fixed size array.";
-  }
-
-  size_field_ = size_field;
-}
-
-const std::string& ArrayField::GetSizeModifier() const {
-  return size_modifier_;
-}
diff --git a/gd/packet/parser/fields/array_field.h b/gd/packet/parser/fields/array_field.h
index d650ba7..679823f 100644
--- a/gd/packet/parser/fields/array_field.h
+++ b/gd/packet/parser/fields/array_field.h
@@ -25,12 +25,8 @@
 
 class ArrayField : public PacketField {
  public:
-  ArrayField(std::string name, int element_size, std::string size_modifier, ParseLocation loc);
-
   ArrayField(std::string name, int element_size, int fixed_size, ParseLocation loc);
 
-  ArrayField(std::string name, TypeDef* type_def, std::string size_modifier, ParseLocation loc);
-
   ArrayField(std::string name, TypeDef* type_def, int fixed_size, ParseLocation loc);
 
   static const std::string kFieldType;
@@ -63,12 +59,6 @@
 
   bool IsCustomFieldArray() const;
 
-  bool IsFixedSize() const;
-
-  void SetSizeField(const SizeField* size_field);
-
-  const std::string& GetSizeModifier() const;
-
   const std::string name_;
 
   const int element_size_{-1};  // in bits
@@ -76,8 +66,4 @@
 
   // Fixed size array or dynamic size, size is always in bytes, unless it is count.
   const int fixed_size_{-1};
-  const SizeField* size_field_{nullptr};
-
-  // Size modifier is only used when size_field_ is of type SIZE and is not used with COUNT.
-  std::string size_modifier_{""};
 };
diff --git a/gd/packet/parser/fields/vector_field.cc b/gd/packet/parser/fields/vector_field.cc
new file mode 100644
index 0000000..6fc7f69
--- /dev/null
+++ b/gd/packet/parser/fields/vector_field.cc
@@ -0,0 +1,188 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "fields/vector_field.h"
+#include "util.h"
+
+const std::string VectorField::kFieldType = "VectorField";
+
+VectorField::VectorField(std::string name, int element_size, std::string size_modifier, ParseLocation loc)
+    : PacketField(name, loc), element_size_(element_size), size_modifier_(size_modifier) {
+  if (element_size_ > 64 || element_size_ < 0)
+    ERROR(this) << __func__ << ": Not implemented for element size = " << element_size_;
+  // Make sure the element_size is a multiple of 8.
+  if (element_size % 8 != 0) {
+    ERROR(this) << "Can only have arrays with elements that are byte aligned (" << element_size << ")";
+  }
+}
+
+VectorField::VectorField(std::string name, TypeDef* type_def, std::string size_modifier, ParseLocation loc)
+    : PacketField(name, loc), element_size_(type_def->size_), type_def_(type_def), size_modifier_(size_modifier) {
+  // If the element type is not variable sized, make sure that it is byte aligned.
+  if (type_def_->size_ != -1 && type_def_->size_ % 8 != 0) {
+    ERROR(this) << "Can only have arrays with elements that are byte aligned (" << type_def_->size_ << ")";
+  }
+}
+
+const std::string& VectorField::GetFieldType() const {
+  return VectorField::kFieldType;
+}
+
+Size VectorField::GetSize() const {
+  // If there is no size field, then it is of unknown size.
+  if (size_field_ == nullptr) {
+    return Size();
+  }
+
+  // size_field_ is of type SIZE
+  if (size_field_->GetFieldType() == SizeField::kFieldType) {
+    std::string ret = "(Get" + util::UnderscoreToCamelCase(size_field_->GetName()) + "() * 8)";
+    if (!size_modifier_.empty()) ret += size_modifier_;
+    return ret;
+  }
+
+  // size_field_ is of type COUNT and it is a scalar array
+  if (type_def_ == nullptr) {
+    return "(Get" + util::UnderscoreToCamelCase(size_field_->GetName()) + "() * " + std::to_string(element_size_) + ")";
+  }
+
+  if (IsCustomFieldArray()) {
+    if (type_def_->size_ != -1) {
+      return "(Get" + util::UnderscoreToCamelCase(size_field_->GetName()) + "() * " + std::to_string(type_def_->size_) +
+             ")";
+    } else {
+      return Size();
+    }
+  }
+
+  // size_field_ is of type COUNT and it is an enum array
+  return "(Get" + util::UnderscoreToCamelCase(size_field_->GetName()) + "() * " + std::to_string(type_def_->size_) +
+         ")";
+}
+
+Size VectorField::GetBuilderSize() const {
+  if (element_size_ != -1) {
+    std::string ret = "(" + GetName() + "_.size() * " + std::to_string(element_size_) + ")";
+    return ret;
+  } else {
+    std::string ret = "[this](){ size_t length = 0; for (const auto& elem : " + GetName() +
+                      "_) { length += elem.size() * 8; } return length; }()";
+    return ret;
+  }
+}
+
+std::string VectorField::GetDataType() const {
+  if (type_def_ != nullptr) {
+    return "std::vector<" + type_def_->name_ + ">";
+  }
+  return "std::vector<" + util::GetTypeForSize(element_size_) + ">";
+}
+
+void VectorField::GenExtractor(std::ostream& s, Size start_offset, Size end_offset) const {
+  GenBounds(s, start_offset, end_offset, GetSize());
+
+  s << " auto subview = GetLittleEndianSubview(field_begin, field_end); ";
+  s << "auto it = subview.begin();";
+
+  // Add the element size so that we will extract as many elements as we can.
+  s << GetDataType() << " ret;";
+  if (element_size_ != -1) {
+    std::string type = (type_def_ != nullptr) ? type_def_->name_ : util::GetTypeForSize(element_size_);
+    s << "while (it + sizeof(" << type << ") <= subview.end()) {";
+    s << "ret.push_back(it.extract<" << type << ">());";
+    s << "}";
+  } else {
+    s << "while (it < subview.end()) {";
+    s << "it = " << type_def_->name_ << "::Parse(ret, it);";
+    s << "}";
+  }
+}
+
+void VectorField::GenGetter(std::ostream& s, Size start_offset, Size end_offset) const {
+  s << GetDataType();
+  s << " Get" << util::UnderscoreToCamelCase(GetName()) << "() {";
+
+  GenExtractor(s, start_offset, end_offset);
+
+  s << "return ret;";
+  s << "}\n";
+}
+
+bool VectorField::GenBuilderParameter(std::ostream& s) const {
+  if (type_def_ != nullptr) {
+    s << "const std::vector<" << type_def_->GetTypeName() << ">& " << GetName();
+  } else {
+    s << "const std::vector<" << util::GetTypeForSize(element_size_) << ">& " << GetName();
+  }
+  return true;
+}
+
+bool VectorField::HasParameterValidator() const {
+  // Does not have parameter validator yet.
+  // TODO: See comment in GenParameterValidator
+  return false;
+}
+
+void VectorField::GenParameterValidator(std::ostream&) const {
+  // No Parameter validator if its dynamically size.
+  // TODO: Maybe add a validator to ensure that the size isn't larger than what the size field can hold.
+  return;
+}
+
+void VectorField::GenInserter(std::ostream& s) const {
+  s << "for (const auto& val : " << GetName() << "_) {";
+  if (IsEnumArray()) {
+    s << "insert(static_cast<" << util::GetTypeForSize(type_def_->size_) << ">(val), i, " << type_def_->size_ << ");";
+  } else if (IsCustomFieldArray()) {
+    if (type_def_->size_ == -1) {
+      s << "val.Serialize(i);";
+    } else {
+      s << "insert(val, i);";
+    }
+  } else {
+    s << "insert(val, i, " << element_size_ << ");";
+  }
+  s << "}\n";
+}
+
+void VectorField::GenValidator(std::ostream&) const {
+  // NOTE: We could check if the element size divides cleanly into the array size, but we decided to forgo that
+  // in favor of just returning as many elements as possible in a best effort style.
+  //
+  // Other than that there is nothing that arrays need to be validated on other than length so nothing needs to
+  // be done here.
+}
+
+bool VectorField::IsEnumArray() const {
+  return type_def_ != nullptr && type_def_->GetDefinitionType() == TypeDef::Type::ENUM;
+}
+
+bool VectorField::IsCustomFieldArray() const {
+  return type_def_ != nullptr && type_def_->GetDefinitionType() == TypeDef::Type::CUSTOM;
+}
+
+void VectorField::SetSizeField(const SizeField* size_field) {
+  if (size_field->GetFieldType() == CountField::kFieldType && !size_modifier_.empty()) {
+    ERROR(this, size_field) << "Can not use count field to describe array with a size modifier."
+                            << " Use size instead";
+  }
+
+  size_field_ = size_field;
+}
+
+const std::string& VectorField::GetSizeModifier() const {
+  return size_modifier_;
+}
diff --git a/gd/packet/parser/fields/vector_field.h b/gd/packet/parser/fields/vector_field.h
new file mode 100644
index 0000000..34f4b31
--- /dev/null
+++ b/gd/packet/parser/fields/vector_field.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include "custom_field_def.h"
+#include "enum_def.h"
+#include "fields/count_field.h"
+#include "fields/packet_field.h"
+#include "fields/size_field.h"
+#include "parse_location.h"
+
+class VectorField : public PacketField {
+ public:
+  VectorField(std::string name, int element_size, std::string size_modifier, ParseLocation loc);
+
+  VectorField(std::string name, TypeDef* type_def, std::string size_modifier, ParseLocation loc);
+
+  static const std::string kFieldType;
+
+  virtual const std::string& GetFieldType() const override;
+
+  virtual Size GetSize() const override;
+
+  virtual Size GetBuilderSize() const override;
+
+  virtual std::string GetDataType() const override;
+
+  virtual void GenExtractor(std::ostream& s, Size start_offset, Size end_offset) const override;
+
+  virtual void GenGetter(std::ostream& s, Size start_offset, Size end_offset) const override;
+
+  virtual bool GenBuilderParameter(std::ostream& s) const override;
+
+  virtual bool HasParameterValidator() const override;
+
+  virtual void GenParameterValidator(std::ostream& s) const override;
+
+  virtual void GenInserter(std::ostream& s) const override;
+
+  virtual void GenValidator(std::ostream&) const override;
+
+  bool IsEnumArray() const;
+
+  bool IsCustomFieldArray() const;
+
+  void SetSizeField(const SizeField* size_field);
+
+  const std::string& GetSizeModifier() const;
+
+  const std::string name_;
+
+  const int element_size_{-1};  // in bits
+  const TypeDef* type_def_{nullptr};
+
+  // Fixed size array or dynamic size, size is always in bytes, unless it is count.
+  const SizeField* size_field_{nullptr};
+
+  // Size modifier is only used when size_field_ is of type SIZE and is not used with COUNT.
+  std::string size_modifier_{""};
+};
diff --git a/gd/packet/parser/language_y.yy b/gd/packet/parser/language_y.yy
index b1fb6bc..cc9d214 100644
--- a/gd/packet/parser/language_y.yy
+++ b/gd/packet/parser/language_y.yy
@@ -560,15 +560,15 @@
 array_field_definition
   : IDENTIFIER ':' INTEGER '[' ']'
     {
-      DEBUG() << "Array field defined name=" << *$1 << " element_size=" << $3;
-      $$ = new ArrayField(*$1, $3, "", LOC);
+      DEBUG() << "Vector field defined name=" << *$1 << " element_size=" << $3;
+      $$ = new VectorField(*$1, $3, "", LOC);
       delete $1;
     }
   | IDENTIFIER ':' INTEGER '[' SIZE_MODIFIER ']'
     {
-      DEBUG() << "Array field defined name=" << *$1 << " element_size=" << $3
+      DEBUG() << "Vector field defined name=" << *$1 << " element_size=" << $3
              << " size_modifier=" << *$5;
-      $$ = new ArrayField(*$1, $3, *$5, LOC);
+      $$ = new VectorField(*$1, $3, *$5, LOC);
       delete $1;
       delete $5;
     }
@@ -581,9 +581,9 @@
     }
   | IDENTIFIER ':' IDENTIFIER '[' ']'
     {
-      DEBUG() << "Array field defined name=" << *$1 << " type=" << *$3;
+      DEBUG() << "Vector field defined name=" << *$1 << " type=" << *$3;
       if (auto type_def = decls->GetTypeDef(*$3)) {
-        $$ = new ArrayField(*$1, type_def, "", LOC);
+        $$ = new VectorField(*$1, type_def, "", LOC);
       } else {
         ERRORLOC(LOC) << "Can't find type used in array field.";
       }
@@ -592,10 +592,10 @@
     }
   | IDENTIFIER ':' IDENTIFIER '[' SIZE_MODIFIER ']'
     {
-      DEBUG() << "Array field defined name=" << *$1 << " type=" << *$3
+      DEBUG() << "Vector field defined name=" << *$1 << " type=" << *$3
              << " size_modifier=" << *$5;
       if (auto type_def = decls->GetTypeDef(*$3)) {
-        $$ = new ArrayField(*$1, type_def, *$5, LOC);
+        $$ = new VectorField(*$1, type_def, *$5, LOC);
       } else {
         ERRORLOC(LOC) << "Can't find type used in array field.";
       }
diff --git a/gd/packet/parser/parent_def.cc b/gd/packet/parser/parent_def.cc
index cbbbe04..32121b5 100644
--- a/gd/packet/parser/parent_def.cc
+++ b/gd/packet/parser/parent_def.cc
@@ -90,9 +90,9 @@
       continue;
     }
 
-    if (var_len_field->GetFieldType() == ArrayField::kFieldType) {
-      const auto& array_field = static_cast<ArrayField*>(var_len_field);
-      array_field->SetSizeField(size_field);
+    if (var_len_field->GetFieldType() == VectorField::kFieldType) {
+      const auto& vector_field = static_cast<VectorField*>(var_len_field);
+      vector_field->SetSizeField(size_field);
       continue;
     }
 
@@ -216,8 +216,8 @@
   FieldList params;
 
   std::set<std::string> param_types = {
-      ScalarField::kFieldType, EnumField::kFieldType,    ArrayField::kFieldType,
-      CustomField::kFieldType, PayloadField::kFieldType,
+      ScalarField::kFieldType, EnumField::kFieldType,   ArrayField::kFieldType,
+      VectorField::kFieldType, CustomField::kFieldType, PayloadField::kFieldType,
   };
 
   if (parent_ != nullptr) {
@@ -335,22 +335,22 @@
         s << "ASSERT(payload_bytes < (static_cast<size_t>(1) << " << field->GetSize().bits() << "));";
         s << "insert(static_cast<" << field->GetDataType() << ">(payload_bytes), i," << field->GetSize().bits() << ");";
       } else {
-        if (sized_field->GetFieldType() != ArrayField::kFieldType) {
+        if (sized_field->GetFieldType() != VectorField::kFieldType) {
           ERROR(field) << __func__ << ": Unhandled sized field type for " << field_name;
         }
-        const auto& array_name = field_name + "_";
-        const ArrayField* array = (ArrayField*)sized_field;
-        s << "size_t " << array_name + "bytes =  0;";
-        if (array->element_size_ == -1) {
-          s << "for (auto elem : " << array_name << ") {";
-          s << array_name + "bytes += elem.size(); }";
+        const auto& vector_name = field_name + "_";
+        const VectorField* vector = (VectorField*)sized_field;
+        s << "size_t " << vector_name + "bytes =  0;";
+        if (vector->element_size_ == -1) {
+          s << "for (auto elem : " << vector_name << ") {";
+          s << vector_name + "bytes += elem.size(); }";
         } else {
-          s << array_name + "bytes = ";
-          s << array_name << ".size() * (" << array->element_size_ << " / 8);";
+          s << vector_name + "bytes = ";
+          s << vector_name << ".size() * (" << vector->element_size_ << " / 8);";
         }
-        s << "ASSERT(" << array_name + "bytes < (1 << " << field->GetSize().bits() << "));";
-        s << "insert(" << array_name << "bytes";
-        s << array->GetSizeModifier() << ", i, ";
+        s << "ASSERT(" << vector_name + "bytes < (1 << " << field->GetSize().bits() << "));";
+        s << "insert(" << vector_name << "bytes";
+        s << vector->GetSizeModifier() << ", i, ";
         s << field->GetSize().bits() << ");";
       }
     } else if (field->GetFieldType() == ChecksumStartField::kFieldType) {
@@ -366,8 +366,8 @@
       s << "[shared_checksum_ptr](uint8_t byte){ shared_checksum_ptr->AddByte(byte);},";
       s << "[shared_checksum_ptr](){ return static_cast<uint64_t>(shared_checksum_ptr->GetChecksum());}));";
     } else if (field->GetFieldType() == CountField::kFieldType) {
-      const auto& array_name = ((SizeField*)field)->GetSizedFieldName() + "_";
-      s << "insert(" << array_name << ".size(), i, " << field->GetSize().bits() << ");";
+      const auto& vector_name = ((SizeField*)field)->GetSizedFieldName() + "_";
+      s << "insert(" << vector_name << ".size(), i, " << field->GetSize().bits() << ");";
     } else {
       field->GenInserter(s);
     }
diff --git a/gd/packet/parser/test/generated_packet_test.cc b/gd/packet/parser/test/generated_packet_test.cc
index 43e74be..2bf1c7e 100644
--- a/gd/packet/parser/test/generated_packet_test.cc
+++ b/gd/packet/parser/test/generated_packet_test.cc
@@ -443,7 +443,7 @@
 }
 
 TEST(GeneratedPacketTest, testFixedArrayEnum) {
-  std::vector<ForArrays> fixed_array{
+  std::array<ForArrays, 5> fixed_array{
       {ForArrays::ONE, ForArrays::TWO, ForArrays::ONE_TWO, ForArrays::TWO_THREE, ForArrays::FFFF}};
   auto packet = FixedArrayEnumBuilder::Create(fixed_array);
   ASSERT_EQ(fixed_array_enum.size(), packet->size());
@@ -546,12 +546,12 @@
 }
 
 TEST(GeneratedPacketTest, testFixedSizeByteArray) {
-  constexpr int byte_array_size = 32;
-  std::vector<uint8_t> byte_array(byte_array_size);
+  constexpr std::size_t byte_array_size = 32;
+  std::array<uint8_t, byte_array_size> byte_array;
   for (uint8_t i = 0; i < byte_array_size; i++) byte_array[i] = i;
 
   constexpr int word_array_size = 8;
-  std::vector<uint32_t> word_array(word_array_size);
+  std::array<uint32_t, word_array_size> word_array;
   for (uint32_t i = 0; i < word_array_size; i++) word_array[i] = i;
 
   auto packet = PacketWithFixedArraysOfBytesBuilder::Create(byte_array, word_array);
@@ -583,19 +583,6 @@
   }
 }
 
-TEST(GeneratedPacketTest, testFixedSizeArrayValidatorDeath) {
-  constexpr int byte_array_size = 33;
-  std::vector<uint8_t> byte_array(byte_array_size);
-  for (uint8_t i = 0; i < byte_array_size; i++) byte_array[i] = i;
-
-  constexpr int word_array_size = 8;
-  std::vector<uint32_t> word_array(word_array_size);
-  for (uint32_t i = 0; i < word_array_size; i++) word_array[i] = i;
-
-  std::unique_ptr<PacketWithFixedArraysOfBytesBuilder> packet;
-  ASSERT_DEATH(packet = PacketWithFixedArraysOfBytesBuilder::Create(byte_array, word_array), "size");
-}
-
 vector<uint8_t> one_variable{
     0x03, 'o', 'n', 'e',  // "one"
 };
@@ -670,12 +657,8 @@
 };
 
 TEST(GeneratedPacketTest, testFixedArrayVariableLength) {
-  std::vector<Variable> fixed_array;
-  fixed_array.emplace_back("one");
-  fixed_array.emplace_back("two");
-  fixed_array.emplace_back("three");
-  fixed_array.emplace_back("four");
-  fixed_array.emplace_back("five");
+  std::array<Variable, 5> fixed_array{std::string("one"), std::string("two"), std::string("three"), std::string("four"),
+                                      std::string("five")};
 
   auto packet = FixedArrayVariableBuilder::Create(fixed_array);
   ASSERT_EQ(fixed_array_variable.size(), packet->size());
diff --git a/gd/packet/parser/test/variable.h b/gd/packet/parser/test/variable.h
index 36361e2..056eac6 100644
--- a/gd/packet/parser/test/variable.h
+++ b/gd/packet/parser/test/variable.h
@@ -20,6 +20,7 @@
 
 #include <stdint.h>
 #include <optional>
+#include <sstream>
 #include <string>
 
 #include "packet/bit_inserter.h"
@@ -43,8 +44,30 @@
   size_t size() const;
 
   static Iterator<true> Parse(std::vector<Variable>& vec, Iterator<true> it);
+  template <std::size_t arr_size>
+  static Iterator<true> ParseArray(std::array<Variable, arr_size>& arr, std::size_t* arr_idx, Iterator<true> it);
 };
 
+template <std::size_t arr_size>
+Iterator<true> Variable::ParseArray(std::array<Variable, arr_size>& arr, std::size_t* arr_idx, Iterator<true> it) {
+  if (it.NumBytesRemaining() < 1) {
+    return it;
+  }
+  size_t data_length = it.extract<uint8_t>();
+  if (data_length > 255) {
+    return it + it.NumBytesRemaining();
+  }
+  if (it.NumBytesRemaining() < data_length) {
+    return it + it.NumBytesRemaining();
+  }
+  std::stringstream ss;
+  for (size_t i = 0; i < data_length; i++) {
+    ss << it.extract<char>();
+  }
+  arr[*arr_idx] = ss.str();
+  return it;
+}
+
 }  // namespace test
 }  // namespace parser
 }  // namespace packet