#pragma once #include #include #include #include #include #include #include "yunq/yunq.h" namespace yunq { class Serializer { public: Serializer(glcr::ByteBuffer& bytes, uint64_t offset, uint64_t num_fields) : buffer_(bytes), offset_(offset), next_extension_(kHeaderSize + (8 * num_fields)), core_size_(next_extension_), caps_() {} Serializer(glcr::ByteBuffer& bytes, uint64_t offset, uint64_t num_fields, glcr::CapBuffer& caps) : buffer_(bytes), offset_(offset), next_extension_(kHeaderSize + (8 * num_fields)), core_size_(next_extension_), caps_(caps) {} template void WriteField(uint64_t field_index, const T& value); template void WriteRepeated(uint64_t field_index, const glcr::Vector& value); void WriteCapability(uint64_t field_index, uint64_t value); void WriteRepeatedCapability(uint64_t field_index, const glcr::Vector& value); template void WriteMessage(uint64_t field_index, const T& value); template void WriteRepeatedMessage(uint64_t field_index, const glcr::Vector& value); void WriteHeader(); uint64_t size() const { return next_extension_; } private: glcr::ByteBuffer& buffer_; uint64_t offset_; uint64_t next_extension_; uint64_t core_size_; uint64_t next_cap_ = 0; glcr::Optional> caps_; uint64_t field_offset(uint64_t field_index) const { return offset_ + kHeaderSize + (8 * field_index); } }; template <> void Serializer::WriteField(uint64_t field_index, const uint64_t& value); template <> void Serializer::WriteField(uint64_t field_index, const int64_t& value); template <> void Serializer::WriteField(uint64_t field_index, const glcr::String& value); template <> void Serializer::WriteRepeated(uint64_t field_index, const glcr::Vector& value); template void Serializer::WriteMessage(uint64_t field_index, const T& value) { uint64_t length = 0; if (caps_) { length = value.SerializeToBytes(buffer_, offset_ + next_extension_, caps_.value().get()); } else { length = value.SerializeToBytes(buffer_, offset_ + next_extension_); } ExtensionPointer ptr{ .offset = (uint32_t)next_extension_, .length = (uint32_t)length, }; next_extension_ += length; buffer_.WriteAt(field_offset(field_index), ptr); } template void Serializer::WriteRepeatedMessage(uint64_t field_index, const glcr::Vector& value) { uint64_t next_offset = next_extension_; uint64_t length = 0; for (T& message : value) { uint64_t msg_length = 0; if (caps_) { msg_length = message.SerializeToBytes(buffer_, offset_ + next_offset, caps_.value().get()); } else { msg_length = message.SerializeToBytes(buffer_, offset_ + next_offset); } length += msg_length; next_offset += msg_length; } ExtensionPointer ptr{ .offset = (uint32_t)next_extension_, .length = (uint32_t)length, }; next_extension_ += length; buffer_.WriteAt(field_offset(field_index), ptr); } } // namespace yunq