#include "ProtoHelper.h" std::optional findFieldWithProtobufTag(AnyRef ref, uint32_t tag) { auto info = ref.reflectType(); for (int i = 0; i < info->fields.size(); i++) { if (tag == info->fields[i].protobufTag) { return std::make_optional(ref.getField(i)); } } return std::nullopt; } void decodeField(std::shared_ptr reader, AnyRef any) { auto fieldInfo = any.reflectType(); if (fieldInfo->kind == ReflectTypeKind::Optional) { auto optionalRef = AnyOptionalRef(any); optionalRef.emplaceEmpty(); return decodeField(reader, optionalRef.get()); } if (fieldInfo->kind == ReflectTypeKind::Class) { // Handle submessage auto lastMaxPosition = reader->maxPosition; auto messageSize = reader->decodeVarInt(); reader->maxPosition = messageSize + reader->pos; while (reader->next()) { auto res = findFieldWithProtobufTag(any, reader->currentTag); if (res.has_value()) { decodeField(reader, res.value()); } else { reader->skip(); } } reader->maxPosition = lastMaxPosition; return; } else if (any.is>()) { reader->decodeVector(*any.as>()); } // Handle repeated else if (fieldInfo->kind == ReflectTypeKind::Vector) { auto aVec = AnyVectorRef(any); aVec.emplace_back(); auto value = aVec.at(aVec.size() - 1); auto valInfo = value.reflectType(); // Represents packed repeated encoding if (valInfo->kind == ReflectTypeKind::Primitive && !value.is() && !value.is>()) { // *any.as() = reader->decodeVarInt(); reader->skip(); } else { decodeField(reader, value); } } else if (fieldInfo->kind == ReflectTypeKind::Enum) { *any.as() = reader->decodeVarInt(); } else if (any.is()) { reader->decodeString(*any.as()); } else if (any.is()) { *any.as() = reader->decodeVarInt(); } else if (any.is()) { *any.as() = reader->decodeVarInt(); } else if (any.is()) { *any.as() = reader->decodeVarInt(); } else if (any.is()) { *any.as() = reader->decodeVarInt(); } else { reader->skip(); } } void decodeProtobuf(std::shared_ptr reader, AnyRef any) { while (reader->next()) { auto res = findFieldWithProtobufTag(any, reader->currentTag); if (res.has_value()) { decodeField(reader, res.value()); } else { reader->skip(); } } } void encodeProtobuf(std::shared_ptr writer, AnyRef any, uint32_t protobufTag) { auto info = any.reflectType(); // Handle optionals, only encode if have value if (info->kind == ReflectTypeKind::Optional) { auto optionalRef = AnyOptionalRef(any); if (!optionalRef.has_value()) { return; } else { return encodeProtobuf(writer, optionalRef.get(), protobufTag); } } if (info->kind == ReflectTypeKind::Class) { uint32_t startMsgPosition; // 0 - default value, indicating top level message if (protobufTag > 0) { startMsgPosition = writer->startMessage(); } for (int i = 0; i < info->fields.size(); i++) { auto field = any.getField(i); encodeProtobuf(writer, field, info->fields[i].protobufTag); } if (protobufTag > 0) { writer->finishMessage(protobufTag, startMsgPosition); } } else if (any.is>()) { writer->addVector(protobufTag, *any.as>()); } else if (info->kind == ReflectTypeKind::Vector) { auto aVec = AnyVectorRef(any); auto size = aVec.size(); for (size_t i = 0; i < size; i++) { auto valueAt = aVec.at(i); encodeProtobuf(writer, valueAt, protobufTag); } } else if (info->kind == ReflectTypeKind::Enum) { writer->addVarInt(protobufTag, *any.as()); } else if (info->kind == ReflectTypeKind::Primitive) { if (any.is()) { writer->addString(protobufTag, *any.as()); } else if (any.is()) { writer->addVarInt(protobufTag, *any.as()); } else if (any.is()) { writer->addVarInt(protobufTag, *any.as()); } else if (any.is()) { writer->addVarInt(protobufTag, *any.as()); } else if (any.is()) { writer->addVarInt(protobufTag, *any.as()); } } }