Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ab990d04 authored by Treehugger Robot's avatar Treehugger Robot Committed by Gerrit Code Review
Browse files

Merge "PDL: Use std::optional to signal Parse failure"

parents 9e0dea31 217857f4
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -33,7 +33,7 @@ class CustomTypeChecker {
  template <class C, size_t (C::*)() const>
  struct SizeChecker {};

  template <class C, bool little_endian, Iterator<little_endian> (*)(C* vec, Iterator<little_endian> it)>
  template <class C, bool little_endian, std::optional<Iterator<little_endian>> (*)(C* vec, Iterator<little_endian> it)>
  struct ParseChecker {};

  template <class C, bool little_endian>
+8 −1
Original line number Diff line number Diff line
@@ -40,8 +40,14 @@ std::string CustomField::GetDataType() const {
}

void CustomField::GenExtractor(std::ostream& s, int) const {
  s << GetName() << "_it = ";
  s << "auto optional_it = ";
  s << GetDataType() << "::Parse( " << GetName() << "_ptr, " << GetName() << "_it);";
  s << "if (optional_it) {";
  s << GetName() << "_it = *optional_it;";
  s << "} else {";
  s << GetName() << "_it = " << GetName() << "_it + " << GetName() << "_it.NumBytesRemaining();";
  s << GetName() << "_ptr = nullptr;";
  s << "}";
}

void CustomField::GenGetter(std::ostream& s, Size start_offset, Size end_offset) const {
@@ -55,6 +61,7 @@ void CustomField::GenGetter(std::ostream& s, Size start_offset, Size end_offset)
  s << " = std::make_unique<" << GetDataType() << ">();";
  s << GetDataType() << "* " << GetName() << "_ptr = " << GetName() << "_value.get();";
  GenExtractor(s, num_leading_bits);
  s << "if (" << GetName() << "_ptr == nullptr) {" << GetName() << "_value.reset(); }";
  s << "return " << GetName() << "_value;";
  s << "}\n";
}
+12 −2
Original line number Diff line number Diff line
@@ -82,17 +82,27 @@ std::string VectorField::GetDataType() const {

void VectorField::GenExtractor(std::ostream& s, int num_leading_bits) const {
  s << "auto " << element_field_->GetName() << "_it = " << GetName() << "_it;";
  if (size_field_ != nullptr && size_field_->GetFieldType() == CountField::kFieldType) {
    s << "size_t " << element_field_->GetName() << "_count = ";
    s << "Get" + util::UnderscoreToCamelCase(size_field_->GetName()) + "();";
  }
  s << "while (";
  if (size_field_ != nullptr && size_field_->GetFieldType() == CountField::kFieldType) {
    s << "(" << element_field_->GetName() << "_count-- > 0) && ";
  }
  if (!element_size_.empty() && !element_size_.has_dynamic()) {
    s << "while (" << element_field_->GetName() << "_it.NumBytesRemaining() >= " << element_size_.bytes() << ") {";
    s << element_field_->GetName() << "_it.NumBytesRemaining() >= " << element_size_.bytes() << ") {";
  } else {
    s << "while (" << element_field_->GetName() << "_it.NumBytesRemaining() > 0) {";
    s << element_field_->GetName() << "_it.NumBytesRemaining() > 0) {";
  }
  s << element_field_->GetDataType() << " " << element_field_->GetName() << "_value;";
  s << element_field_->GetDataType() << "* " << element_field_->GetName() << "_ptr = &" << element_field_->GetName()
    << "_value;";
  element_field_->GenExtractor(s, num_leading_bits);
  s << "if (" << element_field_->GetName() << "_ptr != nullptr) { ";
  s << GetName() << "_ptr->push_back(" << element_field_->GetName() << "_value);";
  s << "}";
  s << "}";
}

void VectorField::GenGetter(std::ostream& s, Size start_offset, Size end_offset) const {
+189 −8
Original line number Diff line number Diff line
@@ -619,6 +619,19 @@ TEST(GeneratedPacketTest, testOneVariableField) {
  ASSERT_EQ(one->data, variable_one.data);
}

vector<uint8_t> fou_variable{
    0x04, 'f', 'o', 'u',  // too short
};

TEST(GeneratedPacketTest, testOneVariableFieldTooShort) {
  std::shared_ptr<std::vector<uint8_t>> packet_bytes = std::make_shared<std::vector<uint8_t>>(fou_variable);
  PacketView<kLittleEndian> packet_bytes_view(packet_bytes);
  auto view = OneVariableView::Create(packet_bytes_view);
  ASSERT_TRUE(view.IsValid());
  auto one = view.GetOne();
  ASSERT_EQ(one, nullptr);
}

vector<uint8_t> sized_array_variable{
    0x0e,                           // _size_
    0x03, 'o', 'n', 'e',            // "one"
@@ -654,6 +667,55 @@ TEST(GeneratedPacketTest, testSizedArrayVariableLength) {
  }
}

vector<uint8_t> sized_array_variable_too_short{
    0x0e,                           // _size_
    0x03, 'o', 'n', 'e',            // "one"
    0x03, 't', 'w', 'o',            // "two"
    0x06, 't', 'h', 'r', 'e', 'e',  // "three" needs another letter to be length 6
};

TEST(GeneratedPacketTest, testSizedArrayVariableLengthLastBad) {
  std::vector<Variable> sized_array;
  sized_array.emplace_back("one");
  sized_array.emplace_back("two");

  std::shared_ptr<std::vector<uint8_t>> packet_bytes =
      std::make_shared<std::vector<uint8_t>>(sized_array_variable_too_short);

  PacketView<kLittleEndian> packet_bytes_view(packet_bytes);
  auto view = SizedArrayVariableView::Create(packet_bytes_view);
  ASSERT_TRUE(view.IsValid());
  auto array = view.GetVariableArray();
  ASSERT_EQ(sized_array.size(), array.size());
  for (size_t i = 0; i < sized_array.size(); i++) {
    ASSERT_EQ(array[i].data, sized_array[i].data);
  }
}

vector<uint8_t> sized_array_variable_first_too_short{
    0x0e,                           // _size_
    0x02, 'o', 'n', 'e',            // "on"
    0x03, 't', 'w', 'o',            // "two"
    0x05, 't', 'h', 'r', 'e', 'e',  // "three"
};

TEST(GeneratedPacketTest, testSizedArrayVariableLengthFirstBad) {
  std::vector<Variable> sized_array;
  sized_array.emplace_back("on");

  std::shared_ptr<std::vector<uint8_t>> packet_bytes =
      std::make_shared<std::vector<uint8_t>>(sized_array_variable_first_too_short);

  PacketView<kLittleEndian> packet_bytes_view(packet_bytes);
  auto view = SizedArrayVariableView::Create(packet_bytes_view);
  ASSERT_TRUE(view.IsValid());
  auto array = view.GetVariableArray();
  ASSERT_EQ(sized_array.size(), array.size());
  for (size_t i = 0; i < sized_array.size(); i++) {
    ASSERT_EQ(array[i].data, sized_array[i].data);
  }
}

vector<uint8_t> fixed_array_variable{
    0x03, 'o', 'n', 'e',            // "one"
    0x03, 't', 'w', 'o',            // "two"
@@ -688,6 +750,31 @@ TEST(GeneratedPacketTest, testFixedArrayVariableLength) {
  }
}

vector<uint8_t> fixed_array_variable_too_short{
    0x03, 'o', 'n', 'e',            // "one"
    0x03, 't', 'w', 'o',            // "two"
    0x05, 't', 'h', 'r', 'e', 'e',  // "three"
    0x04, 'f', 'o', 'u', 'r',       // "four"
    0x05, 'f', 'i', 'v', 'e',       // "five"
};

TEST(GeneratedPacketTest, testFixedArrayVariableLengthTooShort) {
  std::array<Variable, 5> fixed_array{std::string("one"), std::string("two"), std::string("three"),
                                      std::string("four")};

  std::shared_ptr<std::vector<uint8_t>> packet_bytes =
      std::make_shared<std::vector<uint8_t>>(fixed_array_variable_too_short);

  PacketView<kLittleEndian> packet_bytes_view(packet_bytes);
  auto view = FixedArrayVariableView::Create(packet_bytes_view);
  ASSERT_TRUE(view.IsValid());
  auto array = view.GetVariableArray();
  ASSERT_EQ(fixed_array.size(), array.size());
  for (size_t i = 0; i < fixed_array.size(); i++) {
    ASSERT_EQ(array[i].data, fixed_array[i].data);
  }
}

vector<uint8_t> count_array_variable{
    0x04,                           // _count_
    0x03, 'o', 'n', 'e',            // "one"
@@ -725,6 +812,61 @@ TEST(GeneratedPacketTest, testCountArrayVariableLength) {
  }
}

vector<uint8_t> count_array_variable_extra{
    0x04,                           // _count_
    0x03, 'o', 'n', 'e',            // "one"
    0x03, 't', 'w', 'o',            // "two"
    0x05, 't', 'h', 'r', 'e', 'e',  // "three"
    0x04, 'f', 'o', 'u', 'r',       // "four"
    0x04, 'x', 't', 'r', 'a',       // "xtra"
};

TEST(GeneratedPacketTest, testCountArrayVariableLengthExtraData) {
  std::vector<Variable> count_array;
  count_array.emplace_back("one");
  count_array.emplace_back("two");
  count_array.emplace_back("three");
  count_array.emplace_back("four");

  std::shared_ptr<std::vector<uint8_t>> packet_bytes =
      std::make_shared<std::vector<uint8_t>>(count_array_variable_extra);

  PacketView<kLittleEndian> packet_bytes_view(packet_bytes);
  auto view = CountArrayVariableView::Create(packet_bytes_view);
  ASSERT_TRUE(view.IsValid());
  auto array = view.GetVariableArray();
  ASSERT_EQ(count_array.size(), array.size());
  for (size_t i = 0; i < count_array.size(); i++) {
    ASSERT_EQ(array[i].data, count_array[i].data);
  }
}

vector<uint8_t> count_array_variable_too_few{
    0x04,                           // _count_
    0x03, 'o', 'n', 'e',            // "one"
    0x03, 't', 'w', 'o',            // "two"
    0x05, 't', 'h', 'r', 'e', 'e',  // "three"
};

TEST(GeneratedPacketTest, testCountArrayVariableLengthMissingData) {
  std::vector<Variable> count_array;
  count_array.emplace_back("one");
  count_array.emplace_back("two");
  count_array.emplace_back("three");

  std::shared_ptr<std::vector<uint8_t>> packet_bytes =
      std::make_shared<std::vector<uint8_t>>(count_array_variable_too_few);

  PacketView<kLittleEndian> packet_bytes_view(packet_bytes);
  auto view = CountArrayVariableView::Create(packet_bytes_view);
  ASSERT_TRUE(view.IsValid());
  auto array = view.GetVariableArray();
  ASSERT_EQ(count_array.size(), array.size());
  for (size_t i = 0; i < count_array.size(); i++) {
    ASSERT_EQ(array[i].data, count_array[i].data);
  }
}

vector<uint8_t> one_struct{
    0x01, 0x02, 0x03,  // id = 0x01, count = 0x0302
};
@@ -795,13 +937,13 @@ TEST(GeneratedPacketTest, testTwoStructs) {
  ASSERT_EQ(two.count_, count_array[1].count_);
}

vector<uint8_t> array_of_struct{
vector<uint8_t> array_or_vector_of_struct{
    0x04,              // _count_
    0x01, 0x01, 0x02,  // id, id * 0x0201
    0x02, 0x02, 0x04, 0x03, 0x03, 0x06, 0x04, 0x04, 0x08,
};

TEST(GeneratedPacketTest, testArrayOfStruct) {
TEST(GeneratedPacketTest, testVectorOfStruct) {
  std::vector<TwoRelatedNumbers> count_array;
  for (uint8_t i = 1; i < 5; i++) {
    TwoRelatedNumbers trn;
@@ -813,20 +955,59 @@ TEST(GeneratedPacketTest, testArrayOfStruct) {
  // Make a copy
  std::vector<TwoRelatedNumbers> copy_array(count_array);

  auto packet = ArrayOfStructBuilder::Create(count_array);
  auto packet = VectorOfStructBuilder::Create(count_array);

  // Change the original vector to make sure a copy was made.
  count_array[0].id_ = count_array[0].id_ + 1;

  ASSERT_EQ(array_or_vector_of_struct.size(), packet->size());

  std::shared_ptr<std::vector<uint8_t>> packet_bytes = std::make_shared<std::vector<uint8_t>>();
  BitInserter it(*packet_bytes);
  packet->Serialize(it);

  ASSERT_EQ(array_or_vector_of_struct.size(), packet_bytes->size());
  for (size_t i = 0; i < array_or_vector_of_struct.size(); i++) {
    ASSERT_EQ(array_or_vector_of_struct[i], packet_bytes->at(i));
  }

  PacketView<kLittleEndian> packet_bytes_view(packet_bytes);
  auto view = VectorOfStructView::Create(packet_bytes_view);
  ASSERT_TRUE(view.IsValid());
  auto array = view.GetArray();
  ASSERT_EQ(copy_array.size(), array.size());
  for (size_t i = 0; i < copy_array.size(); i++) {
    ASSERT_EQ(array[i].id_, copy_array[i].id_);
    ASSERT_EQ(array[i].count_, copy_array[i].count_);
  }
}

TEST(GeneratedPacketTest, testArrayOfStruct) {
  std::array<TwoRelatedNumbers, 4> count_array;
  for (uint8_t i = 1; i < 5; i++) {
    TwoRelatedNumbers trn;
    trn.id_ = i;
    trn.count_ = 0x0201 * i;
    count_array[i - 1] = trn;
  }

  // Make a copy
  std::array<TwoRelatedNumbers, 4> copy_array(count_array);

  auto packet = ArrayOfStructBuilder::Create(4, count_array);

  // Change the original vector to make sure a copy was made.
  count_array[0].id_ = count_array[0].id_ + 1;

  ASSERT_EQ(array_of_struct.size(), packet->size());
  ASSERT_EQ(array_or_vector_of_struct.size(), packet->size());

  std::shared_ptr<std::vector<uint8_t>> packet_bytes = std::make_shared<std::vector<uint8_t>>();
  BitInserter it(*packet_bytes);
  packet->Serialize(it);

  ASSERT_EQ(array_of_struct.size(), packet_bytes->size());
  for (size_t i = 0; i < array_of_struct.size(); i++) {
    ASSERT_EQ(array_of_struct[i], packet_bytes->at(i));
  ASSERT_EQ(array_or_vector_of_struct.size(), packet_bytes->size());
  for (size_t i = 0; i < array_or_vector_of_struct.size(); i++) {
    ASSERT_EQ(array_or_vector_of_struct[i], packet_bytes->at(i));
  }

  PacketView<kLittleEndian> packet_bytes_view(packet_bytes);
@@ -899,7 +1080,7 @@ TEST(GeneratedPacketTest, testArrayOfStructAndAnother) {
  another.count_ = 0x0201 * 4;

  auto packet = ArrayOfStructAndAnotherBuilder::Create(count_array, another);
  ASSERT_EQ(array_of_struct.size(), packet->size());
  ASSERT_EQ(array_or_vector_of_struct.size(), packet->size());

  std::shared_ptr<std::vector<uint8_t>> packet_bytes = std::make_shared<std::vector<uint8_t>>();
  BitInserter it(*packet_bytes);
+6 −1
Original line number Diff line number Diff line
@@ -180,11 +180,16 @@ packet TwoStructs {
  two : TwoRelatedNumbers,
}

packet ArrayOfStruct {
packet VectorOfStruct {
  _count_(array) : 8,
  array : TwoRelatedNumbers[],
}

packet ArrayOfStruct {
  the_count : 8,
  array : TwoRelatedNumbers[4],
}

struct StructWithFixedTypes {
  four_bits : FourBits,
  _reserved_ : 4,
Loading