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

Commit 599c416a authored by Henri Chataing's avatar Henri Chataing
Browse files

bluetooth_packetgen: Generate additional struct constructor

Generate a constructor with initializers for all
struct fields and parent struct fields. Fields with constraint
values are automatically filled in.

Test: atest --host bluetooth_packet_test
Change-Id: Ia15230c6cdaedbf9ca23f94c4418f41a05603f89
parent 7321894c
Loading
Loading
Loading
Loading
+93 −1
Original line number Diff line number Diff line
@@ -182,6 +182,7 @@ void StructDef::GenDefinition(std::ostream& s) const {
  s << " {";
  s << " public:";

  GenDefaultConstructor(s);
  GenConstructor(s);

  s << " public:\n";
@@ -250,7 +251,8 @@ void StructDef::GenDefinitionPybind11(std::ostream& s) const {
  s << ";\n";
}

void StructDef::GenConstructor(std::ostream& s) const {
// Generate constructor which provides default values for all struct fields.
void StructDef::GenDefaultConstructor(std::ostream& s) const {
  if (parent_ != nullptr) {
    s << name_ << "(const " << parent_->name_ << "& parent) : " << parent_->name_ << "(parent) {}";
    s << name_ << "() : " << parent_->name_ << "() {";
@@ -285,6 +287,96 @@ void StructDef::GenConstructor(std::ostream& s) const {
  s << "}\n";
}

// Generate constructor which inputs initial field values for all struct fields.
void StructDef::GenConstructor(std::ostream& s) const {
  // Fetch the list of parameters and parent paremeters.
  // GetParamList returns the list of all inherited fields that do not
  // have a constrained value.
  FieldList parent_params;
  FieldList params = GetParamList().GetFieldsWithoutTypes({
      PayloadField::kFieldType,
      BodyField::kFieldType,
  });

  if (parent_ != nullptr) {
    parent_params = parent_->GetParamList().GetFieldsWithoutTypes({
        PayloadField::kFieldType,
        BodyField::kFieldType,
    });
  }

  // Generate constructor parameters for struct fields.
  s << name_ << "(";
  bool add_comma = false;
  for (auto const& field : params) {
    if (add_comma) {
      s << ", ";
    }
    field->GenBuilderParameter(s);
    add_comma = true;
  }

  s << ")" << std::endl;

  if (params.size() > 0) {
    s << " : ";
  }

  // Invoke parent constructor with correct field values.
  if (parent_ != nullptr) {
    s << parent_->name_ << "(";
    add_comma = false;
    for (auto const& field : parent_params) {
      if (add_comma) {
        s << ", ";
      }

      // Check for fields with constraint value.
      const auto& constraint = parent_constraints_.find(field->GetName());
      if (constraint != parent_constraints_.end()) {
        s << "/* " << field->GetName() << " */ ";
        if (field->GetFieldType() == ScalarField::kFieldType) {
          s << std::get<int64_t>(constraint->second);
        } else if (field->GetFieldType() == EnumField::kFieldType) {
          s << std::get<std::string>(constraint->second);
        } else {
          ERROR(field) << "Constraints on non enum/scalar fields should be impossible.";
        }
      } else if (field->BuilderParameterMustBeMoved()) {
        s << "std::move(" << field->GetName() << ")";
      } else {
        s << field->GetName();
      }

      add_comma = true;
    }

    s << ")";
  }

  // Initialize remaining fields.
  add_comma = parent_ != nullptr;
  for (auto const& field : params) {
    if (parent_params.GetField(field->GetName()) != nullptr) {
      continue;
    }
    if (add_comma) {
      s << ", ";
    }

    if (field->BuilderParameterMustBeMoved()) {
      s << field->GetName() << "_(std::move(" << field->GetName() << "))";
    } else {
      s << field->GetName() << "_(" << field->GetName() << ")";
    }

    add_comma = true;
  }

  s << std::endl;
  s << "{}\n";
}

Size StructDef::GetStructOffsetForField(std::string field_name) const {
  auto size = Size(0);
  for (auto it = fields_.begin(); it != fields_.end(); it++) {
+1 −0
Original line number Diff line number Diff line
@@ -46,6 +46,7 @@ class StructDef : public ParentDef {

  void GenDefinitionPybind11(std::ostream& s) const;

  void GenDefaultConstructor(std::ostream& s) const;
  void GenConstructor(std::ostream& s) const;

  Size GetStructOffsetForField(std::string field_name) const;
+11 −22
Original line number Diff line number Diff line
@@ -1493,8 +1493,7 @@ vector<uint8_t> one_four_byte_struct{
};

TEST(GeneratedPacketTest, testOneFourByteStruct) {
  FourByteStruct four_byte_struct;
  four_byte_struct.four_bytes_ = 0xd4d3d2d1;
  FourByteStruct four_byte_struct(0xd4d3d2d1);

  auto packet = OneFourByteStructBuilder::Create(four_byte_struct);
  ASSERT_EQ(one_four_byte_struct.size(), packet->size());
@@ -1521,8 +1520,7 @@ vector<uint8_t> generic_struct_two{
};

TEST(GeneratedPacketTest, testOneGenericStructTwo) {
  TwoByteStruct two_byte_struct;
  two_byte_struct.two_bytes_ = 0x0201;
  TwoByteStruct two_byte_struct(0x0201);
  std::unique_ptr<TwoByteStruct> two_byte_struct_ptr = std::make_unique<TwoByteStruct>(two_byte_struct);

  auto packet = OneGenericStructBuilder::Create(std::move(two_byte_struct_ptr));
@@ -1558,8 +1556,7 @@ vector<uint8_t> generic_struct_four{
};

TEST(GeneratedPacketTest, testOneGenericStructFour) {
  FourByteStruct four_byte_struct;
  four_byte_struct.four_bytes_ = 0x04030201;
  FourByteStruct four_byte_struct(0x04030201);
  std::unique_ptr<FourByteStruct> four_byte_struct_p = std::make_unique<FourByteStruct>(four_byte_struct);
  ASSERT_EQ(four_byte_struct.four_bytes_, four_byte_struct_p->four_bytes_);

@@ -1599,17 +1596,13 @@ TEST(GeneratedPacketTest, testOneGenericStructArray) {
  std::vector<std::unique_ptr<UnusedParentStruct>> parent_vector;
  std::unique_ptr<FourByteStruct> fbs;
  std::unique_ptr<TwoByteStruct> tbs;
  fbs = std::make_unique<FourByteStruct>();
  fbs->four_bytes_ = 0xa4a3a2a1;
  fbs = std::make_unique<FourByteStruct>(0xa4a3a2a1);
  parent_vector.push_back(std::move(fbs));
  fbs = std::make_unique<FourByteStruct>();
  fbs->four_bytes_ = 0xb4b3b2b2;
  fbs = std::make_unique<FourByteStruct>(0xb4b3b2b2);
  parent_vector.push_back(std::move(fbs));
  tbs = std::make_unique<TwoByteStruct>();
  tbs->two_bytes_ = 0xc2c3;
  tbs = std::make_unique<TwoByteStruct>(0xc2c3);
  parent_vector.push_back(std::move(tbs));
  fbs = std::make_unique<FourByteStruct>();
  fbs->four_bytes_ = 0xd4d3d2d4;
  fbs = std::make_unique<FourByteStruct>(0xd4d3d2d4);
  parent_vector.push_back(std::move(fbs));

  std::vector<std::unique_ptr<UnusedParentStruct>> vector_copy;
@@ -1656,17 +1649,13 @@ TEST(GeneratedPacketTest, testOneGenericStructFourArray) {
  std::array<std::unique_ptr<UnusedParentStruct>, 4> parent_vector;
  std::unique_ptr<FourByteStruct> fbs;
  std::unique_ptr<TwoByteStruct> tbs;
  fbs = std::make_unique<FourByteStruct>();
  fbs->four_bytes_ = 0xa4a3a2a1;
  fbs = std::make_unique<FourByteStruct>(0xa4a3a2a1);
  parent_vector[0] = std::move(fbs);
  fbs = std::make_unique<FourByteStruct>();
  fbs->four_bytes_ = 0xb4b3b2b2;
  fbs = std::make_unique<FourByteStruct>(0xb4b3b2b2);
  parent_vector[1] = std::move(fbs);
  tbs = std::make_unique<TwoByteStruct>();
  tbs->two_bytes_ = 0xc2c3;
  tbs = std::make_unique<TwoByteStruct>(0xc2c3);
  parent_vector[2] = std::move(tbs);
  fbs = std::make_unique<FourByteStruct>();
  fbs->four_bytes_ = 0xd4d3d2d4;
  fbs = std::make_unique<FourByteStruct>(0xd4d3d2d4);
  parent_vector[3] = std::move(fbs);

  std::array<std::unique_ptr<UnusedParentStruct>, 4> vector_copy;
+3 −3
Original line number Diff line number Diff line
@@ -334,11 +334,11 @@ struct OnlyFourByteStruct : AtLeastFourByteStruct (struct_type = ZERO_BYTE) {
}

struct SixByteStruct : AtLeastFourByteStruct (struct_type = TWO_BYTE) {
  two_bytes : 16,
  two_more_bytes : 16,
}

struct EightByteStruct : AtLeastFourByteStruct (struct_type = FOUR_BYTE) {
  four_bytes : 32,
  four_more_bytes : 32,
}

packet OneFourByteStruct {
@@ -436,7 +436,7 @@ struct AtLeastFourByteStructNoZero : UnusedParentStructNoZero (struct_type = AT_
}

struct EightByteStructNoZero : AtLeastFourByteStructNoZero (struct_type = FOUR_BYTE, length = 9) {
  four_bytes : 32,
  four_more_bytes : 32,
}

packet OneGenericStructArrayNoZero {