fix alignment + refactor

Reviewed-on: #1
Co-authored-by: Persson-dev <sim16.prib@gmail.com>
Co-committed-by: Persson-dev <sim16.prib@gmail.com>
This commit was merged in pull request #1.
This commit is contained in:
2025-02-23 09:40:46 +00:00
committed by Simon Pribylski
parent ee865021c2
commit db0c5f3245
31 changed files with 831 additions and 1070 deletions

View File

@@ -0,0 +1,160 @@
#pragma once
namespace sp {
namespace details {
// ID information chunk
template <typename TBase, std::intmax_t TId>
class MessageImplStaticNumIdBase : public TBase {
public:
// Reuse the message ID type defined in the interface
using MsgIdType = typename TBase::MsgIdType;
protected:
virtual MsgIdType GetIdImpl() const override {
return static_cast<MsgIdType>(TId);
}
};
// Dispatch implementation chunk
template <typename TBase, typename TActual>
class MessageImplDispatchBase : public TBase {
public:
// Reuse the Handler type defined in the interface class
using Handler = typename TBase::HandlerType;
protected:
virtual void DispatchImpl(Handler& handler) override {
handler.Handle(static_cast<TActual&>(*this));
}
};
template <typename TBase, typename TFields>
class MessageImplFieldsBase : public TBase {
public:
using AllFields = typename details::FieldsBuilder<TFields>::Type;
template <typename... Args>
void Construct(Args... args) {
m_Fields = std::make_tuple(args...);
}
AllFields& GetFields() {
return m_Fields;
}
const AllFields& GetFields() const {
return m_Fields;
}
template <std::size_t FIndex>
auto& GetField() {
return std::get<FIndex>(GetFields()).GetValue();
}
template <std::size_t FIndex>
const auto& GetField() const {
return std::get<FIndex>(GetFields()).GetValue();
}
// allow use of enums
template <typename E, E FIndex>
const auto& GetField() const {
return std::get<static_cast<std::size_t>(FIndex)>(this->GetFields()).GetValue();
}
private:
AllFields m_Fields;
};
template <typename TBase>
class MessageImplFieldsReadBase : public TBase {
private:
// normal reading
template <typename TField>
void ReadField(Field<TField, 0>& field, DataBuffer& buffer) {
this->ReadData(field.GetValue(), buffer);
}
// reading field in bitfield
template <typename TFieldType, typename TField, int IAlignment>
void ReadField(Field<TField, IAlignment>& field, TFieldType data, std::size_t offset) {
static constexpr std::size_t TotalBitCount = sizeof(TFieldType) * 8;
// we suppose that the first element is at the highest bits
field.GetValue() = (data >> TotalBitCount - IAlignment - offset) & ((1 << IAlignment) - 1);
}
// reading bitfield
template <typename TContainer, typename TFirst, typename... TFields>
void ReadField(Field<BitField<TContainer, TFirst, TFields...>, 0>& field, DataBuffer& buffer) {
TContainer data;
this->ReadData(data, buffer);
std::size_t offset = 0;
TupleForEach(
[data, this, &offset](auto& field) {
this->ReadField(field, data, offset);
offset += field.GetAlignment();
},
field.GetValue().GetFields());
}
void ReadImpl(DataBuffer& buffer) override {
auto& allFields = this->GetFields();
TupleForEach([&buffer, this](auto& field) { this->ReadField(field, buffer); }, allFields);
}
};
template <typename TBase>
class MessageImplFieldsWriteBase : public TBase {
private:
// normal writing
template <typename TField>
void WriteField(Field<TField, 0>& field, DataBuffer& buffer) {
this->WriteData(field.GetValue(), buffer);
}
// writing field in bitfield
template <typename TFieldType, typename TField, int IAlignment>
void WriteField(Field<TField, IAlignment>& field, TFieldType& data, std::size_t offset) {
static constexpr std::size_t TotalBitCount = sizeof(TFieldType) * 8;
// we suppose that the first element is at the highest bits
data |= (field.GetValue() & ((1 << IAlignment) - 1)) << TotalBitCount - IAlignment - offset;
}
// writing bitfield
template <typename TContainer, typename TFirst, typename... TFields>
void WriteField(Field<BitField<TContainer, TFirst, TFields...>, 0>& field, DataBuffer& buffer) {
TContainer data = 0;
std::size_t offset = 0;
TupleForEach(
[&data, this, &offset](auto& field) {
this->WriteField(field, data, offset);
offset += field.GetAlignment();
},
field.GetValue().GetFields());
this->WriteData(data, buffer);
}
void WriteImpl(DataBuffer& buffer) override {
auto& allFields = this->GetFields();
TupleForEach([&buffer, this](auto& field) { this->WriteField(field, buffer); }, allFields);
}
};
template <typename TBase>
class MessageImplFieldsValidBase : public TBase {
protected:
bool ValidImpl() const override {
// Access fields via interface provided in previous chunk
// auto& allFields = TBase::GetFields();
//... // validate all the fields
return true;
}
};
} // namespace details
} // namespace sp