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

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

Merge "PDL: Add variable-size CustomField(s)"

parents 5aa96430 4e6d9006
Loading
Loading
Loading
Loading
+36 −0
Original line number Diff line number Diff line
#include <array>

#include "packet/bit_inserter.h"
#include "packet/iterator.h"

namespace bluetooth {
namespace packet {
// Checks a custom type has all the necessary static functions with the correct signatures.
template <typename T>
class CustomTypeChecker {
 public:
  template <class C, void (*)(const C&, BitInserter&)>
  struct SerializeChecker {};

  template <class C, size_t (*)(const C&)>
  struct SizeChecker {};

  template <class C, Iterator<true> (*)(std::vector<C>& vec, Iterator<true> it)>
  struct ParseChecker {};

  template <class C, Iterator<false> (*)(std::vector<C>& vec, Iterator<false> it)>
  struct ParseCheckerBigEndian {};

  template <class C>
  static int Test(SerializeChecker<C, &C::Serialize>*, SizeChecker<C, &C::Size>*, ParseChecker<C, &C::Parse>*);

  template <class C>
  static int Test(SerializeChecker<C, &C::Serialize>*, SizeChecker<C, &C::Size>*, ParseCheckerBigEndian<C, &C::Parse>*);

  template <class C>
  static char Test(...);

  static constexpr bool value = (sizeof(Test<T>(0, 0, 0)) == sizeof(int));
};
}  // namespace packet
}  // namespace bluetooth
+7 −0
Original line number Diff line number Diff line
@@ -18,6 +18,8 @@

#include "util.h"

CustomFieldDef::CustomFieldDef(std::string name, std::string include) : TypeDef(name), include_(include) {}

CustomFieldDef::CustomFieldDef(std::string name, std::string include, int size)
    : TypeDef(name, size), include_(include) {
  if (size % 8 != 0) {
@@ -50,3 +52,8 @@ void CustomFieldDef::GenUsing(std::ostream& s) const {
  }
  s << GetTypeName() << ";";
}

void CustomFieldDef::GenCustomFieldCheck(std::ostream& s) const {
  s << "static_assert(CustomTypeChecker<" << name_ << ">::value, \"";
  s << name_ << " is not a valid custom field type. Please see README for more details.\");";
}
+4 −0
Original line number Diff line number Diff line
@@ -24,6 +24,8 @@

class CustomFieldDef : public TypeDef {
 public:
  CustomFieldDef(std::string name, std::string include);

  CustomFieldDef(std::string name, std::string include, int size);

  virtual PacketField* GetNewField(const std::string& name, ParseLocation loc) const override;
@@ -34,5 +36,7 @@ class CustomFieldDef : public TypeDef {

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

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

  const std::string include_;
};
+47 −14
Original line number Diff line number Diff line
@@ -20,25 +20,33 @@
ArrayField::ArrayField(std::string name, int element_size, std::string size_modifier, ParseLocation loc)
    : PacketField(loc, name), element_size_(element_size), size_modifier_(size_modifier) {
  // 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.";
  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(loc, name), element_size_(element_size), fixed_size_(fixed_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.";
  if (element_size % 8 != 0) {
    ERROR(this) << "Can only have arrays with elements that are byte aligned (" << element_size << ")";
  }
}

ArrayField::ArrayField(std::string name, TypeDef* type_def, std::string size_modifier, ParseLocation loc)
    : PacketField(loc, name), element_size_(type_def->size_), type_def_(type_def), size_modifier_(size_modifier) {
  // If it is an enum array, make sure that the enum definition is byte aligned.
  if (type_def_->size_ % 8 != 0) ERROR(this) << "Can only have arrays with elements that are byte aligned.";
  // 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(loc, name), element_size_(type_def->size_), type_def_(type_def), fixed_size_(fixed_size) {
  // If it is an enum array, make sure that the enum definition is byte aligned.
  if (type_def_->size_ % 8 != 0) ERROR(this) << "Can only have arrays with elements that are byte aligned.";
  // 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_ << ")";
  }
}

PacketField::Type ArrayField::GetFieldType() const {
@@ -69,8 +77,12 @@ Size ArrayField::GetSize() const {
  }

  if (IsCustomFieldArray()) {
    if (type_def_->size_ != -1) {
      return "(Get" + util::UnderscoreToCamelCase(size_field_->GetName()) + "() * " +
             std::to_string(type_def_->size_ / 8) + ")";
    } else {
      return Size();
    }
  }

  // size_field_ is of type COUNT and it is an enum array
@@ -78,6 +90,17 @@ Size ArrayField::GetSize() const {
         ")";
}

Size ArrayField::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 ArrayField::GetType() const {
  if (type_def_ != nullptr) {
    return "std::vector<" + type_def_->name_ + ">";
@@ -113,10 +136,16 @@ void ArrayField::GenGetter(std::ostream& s, Size start_offset, Size end_offset)

  // Add the element size so that we will extract as many elements as we can.
  s << GetType() << " ret;";
  if (element_size_ != -1) {
    std::string type = (type_def_ != nullptr) ? type_def_->name_ : util::GetTypeForSize(element_size_);
    s << "while (it + sizeof(" << type << ") <= array_end) {";
    s << "ret.push_back(it.extract<" << type << ">());";
    s << "}";
  } else {
    s << "while (it < array_end) {";
    s << "it = " << type_def_->name_ << "::Parse(ret, it);";
    s << "}";
  }

  s << "return ret;";
  s << "}\n";
@@ -152,7 +181,7 @@ void ArrayField::GenParameterValidator(std::ostream& s) const {
    return;
  }

  s << "ASSERT(" << GetName() << ".size() == " << fixed_size_ << ");";
  s << "ASSERT(" << GetName() << "_.size() == " << fixed_size_ << ");";
}

void ArrayField::GenInserter(std::ostream& s) const {
@@ -160,7 +189,11 @@ void ArrayField::GenInserter(std::ostream& s) const {
  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 << type_def_->name_ << "::Serialize(val, i);";
    } else {
      s << "insert(val, i);";
    }
  } else {
    s << "insert(val, i, " << element_size_ << ");";
  }
+3 −1
Original line number Diff line number Diff line
@@ -37,6 +37,8 @@ class ArrayField : public PacketField {

  virtual Size GetSize() const override;

  virtual Size GetBuilderSize() const override;

  virtual std::string GetType() const override;

  virtual void GenGetter(std::ostream& s, Size start_offset, Size end_offset) const override;
@@ -63,7 +65,7 @@ class ArrayField : public PacketField {

  const std::string name_;

  const int element_size_{-1};  // units is bits
  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.
Loading