/* * Copyright (C) 2021 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef HDC_SERIAL_STRUCT_DEFINE_H #define HDC_SERIAL_STRUCT_DEFINE_H #include #include #include #include #include #include #include #include #include #include // static file define. No need not modify. by zako namespace Hdc { // clang-format off namespace SerialStruct { namespace SerialDetail { template struct MemPtr { }; template struct MemPtr { using type = T; using MemberType = U; }; template struct MessageImpl { public: MessageImpl(Fields &&... fields) : _fields(std::move(fields)...) { } template void Visit(Handler &&handler) const { VisitImpl(std::forward(handler), std::make_index_sequence()); } private: std::tuple _fields; template void VisitImpl(Handler &&handler, std::index_sequence) const { (handler(std::get(_fields)), ...); } }; template struct FieldImpl { using type = typename SerialDetail::MemPtr::type; using MemberType = typename SerialDetail::MemPtr::MemberType; constexpr static const uint32_t TAG = Tag; constexpr static const uint32_t FLAGS = Flags; const std::string field_name; static decltype(auto) get(const type &value) { return value.*MemPtr; } static decltype(auto) get(type &value) { return value.*MemPtr; } }; template struct OneofFieldImpl { using type = typename SerialDetail::MemPtr::type; using MemberType = typename SerialDetail::MemPtr::MemberType; constexpr static const uint32_t TAG = Tag; constexpr static const size_t INDEX = Index; constexpr static const uint32_t FLAGS = Flags; const std::string field_name; static decltype(auto) get(const type &value) { return value.*MemPtr; } static decltype(auto) get(type &value) { return value.*MemPtr; } }; template struct MapFieldImpl { using type = typename SerialDetail::MemPtr::type; using MemberType = typename SerialDetail::MemPtr::MemberType; constexpr static const uint32_t TAG = Tag; constexpr static const uint32_t KEY_FLAGS = KeyFlags; constexpr static const uint32_t VALUE_FLAGS = ValueFlags; const std::string field_name; static decltype(auto) get(const type &value) { return value.*MemPtr; } static decltype(auto) get(type &value) { return value.*MemPtr; } }; } enum class WireType : uint32_t { VARINT = 0, FIXED64 = 1, LENGTH_DELIMETED = 2, START_GROUP = 3, END_GROUP = 4, FIXED32 = 5, }; enum Flags { NO = 0, S = 1, F = 2 }; template struct FlagsType { }; template struct Descriptor { static_assert(sizeof(T) == 0, "You need to implement descriptor for your own types"); static void type() { } }; template constexpr auto Message(Fields &&... fields) { return SerialDetail::MessageImpl(std::forward(fields)...); } template constexpr auto Field(const std::string &fieldName) { return SerialDetail::FieldImpl { fieldName }; } template constexpr auto OneofField(const std::string &fieldName) { return SerialDetail::OneofFieldImpl { fieldName }; } template constexpr auto MapField(const std::string &fieldName) { return SerialDetail::MapFieldImpl { fieldName }; } template const auto &MessageType() { static const auto message = Descriptor::type(); return message; } template struct Serializer; struct Writer { virtual void Write(const void *bytes, size_t size) = 0; }; struct Reader { virtual size_t Read(void *bytes, size_t size) = 0; }; namespace SerialDetail { template struct HasSerializePacked : public std::false_type { }; template struct HasSerializePacked().SerializePacked( std::declval(), std::declval(), std::declval()))>> : public std::true_type { }; template constexpr bool HAS_SERIALIZE_PACKED_V = HasSerializePacked::value; template struct HasParsePacked : public std::false_type { }; template struct HasParsePacked().ParsePacked( std::declval(), std::declval(), std::declval()))>> : public std::true_type { }; template constexpr bool HAS_PARSE_PACKED_V = HasParsePacked::value; static uint32_t MakeTagWireType(uint32_t tag, WireType wireType) { return (tag << 3) | static_cast(wireType); // 3:tag type offset } static inline void ReadTagWireType(uint32_t tagKey, uint32_t &tag, WireType &wireType) { wireType = static_cast(tagKey & 0b0111); tag = tagKey >> 3; // 3:tag type offset } static uint32_t MakeZigzagValue(int32_t value) { return (static_cast(value) << 1) ^ static_cast(value >> 31); //31:uint32_t val offset } static uint64_t MakeZigzagValue(int64_t value) { return (static_cast(value) << 1) ^ static_cast(value >> 63); // 63:uint32_t val offset } static int32_t ReadZigzagValue(uint32_t value) { return static_cast((value >> 1) ^ (~(value & 1) + 1)); } static int64_t ReadZigzagValue(uint64_t value) { return static_cast((value >> 1) ^ (~(value & 1) + 1)); } template To BitCast(From from) { static_assert(sizeof(To) == sizeof(From), ""); static_assert(std::is_trivially_copyable_v, ""); static_assert(std::is_trivially_copyable_v, ""); To to; memcpy_s(&to, sizeof(To), &from, sizeof(from)); return to; } struct WriterSizeCollector : public Writer { void Write(const void *, size_t size) override { byte_size += size; } size_t byte_size = 0; }; struct LimitedReader : public Reader { LimitedReader(Reader &parent, size_t sizeLimit) : _parent(parent), _size_limit(sizeLimit) { } size_t Read(void *bytes, size_t size) override { auto sizeToRead = std::min(size, _size_limit); auto readSize = _parent.Read(bytes, sizeToRead); _size_limit -= readSize; return readSize; } size_t AvailableBytes() const { return _size_limit; } private: Reader &_parent; size_t _size_limit; }; static bool ReadByte(uint8_t &value, Reader &in) { return in.Read(&value, 1) == 1; } static void WriteVarint(uint32_t value, Writer &out) { constexpr uint8_t bytesSize = 5; constexpr uint8_t bytesOffset = 7; uint8_t b[bytesSize] {}; for (size_t i = 0; i < bytesSize; ++i) { b[i] = value & 0b0111'1111; value >>= bytesOffset; if (value) { b[i] |= 0b1000'0000; } else { out.Write(b, i + 1); break; } } } static void WriteVarint(uint64_t value, Writer &out) { constexpr uint8_t bytesSize = 10; constexpr uint8_t bytesOffset = 7; uint8_t b[bytesSize] {}; for (size_t i = 0; i < bytesSize; ++i) { b[i] = value & 0b0111'1111; value >>= bytesOffset; if (value) { b[i] |= 0b1000'0000; } else { out.Write(b, i + 1); break; } } } #if defined(HOST_MAC) static void WriteVarint(unsigned long value, Writer &out) { WriteVarint(static_cast(value), out); } #endif static bool ReadVarint(uint32_t &value, Reader &in) { value = 0; constexpr uint8_t bytesSize = 5; constexpr uint8_t bytesOffset = 7; for (size_t c = 0; c < bytesSize; ++c) { uint8_t x; if (!ReadByte(x, in)) { return false; } value |= static_cast(x & 0b0111'1111) << bytesOffset * c; if (!(x & 0b1000'0000)) { return true; } } return false; } static bool ReadVarint(uint64_t &value, Reader &in) { value = 0; constexpr uint8_t bytesSize = 10; constexpr uint8_t bytesOffset = 7; for (size_t c = 0; c < bytesSize; ++c) { uint8_t x; if (!ReadByte(x, in)) { return false; } value |= static_cast(x & 0b0111'1111) << bytesOffset * c; if (!(x & 0b1000'0000)) { return true; } } return false; } #if defined(HOST_MAC) static bool ReadVarint(unsigned long &value, Reader &in) { uint64_t intermediateValue; if (ReadVarint(intermediateValue, in)) { value = static_cast(intermediateValue); return true; } return false; } #endif static void WriteFixed(uint32_t value, Writer &out) { #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ out.Write(&value, sizeof(value)); #else static_assert(false, "Not a little-endian"); #endif } static void WriteFixed(uint64_t value, Writer &out) { #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ out.Write(&value, sizeof(value)); #else static_assert(false, "Not a little-endian"); #endif } static void WriteFixed(double value, Writer &out) { WriteFixed(BitCast(value), out); } static void WriteFixed(float value, Writer &out) { WriteFixed(BitCast(value), out); } static void WriteVarint(int32_t value, Writer &out) { WriteVarint(BitCast(value), out); } static void WriteVarint(int64_t value, Writer &out) { WriteVarint(BitCast(value), out); } static void WriteSignedVarint(int32_t value, Writer &out) { WriteVarint(MakeZigzagValue(value), out); } static void WriteSignedVarint(int64_t value, Writer &out) { WriteVarint(MakeZigzagValue(value), out); } static void WriteSignedFixed(int32_t value, Writer &out) { WriteFixed(static_cast(value), out); } static void WriteSignedFixed(int64_t value, Writer &out) { WriteFixed(static_cast(value), out); } static void WriteTagWriteType(uint32_t tag, WireType wireType, Writer &out) { WriteVarint(MakeTagWireType(tag, wireType), out); } static bool ReadFixed(uint32_t &value, Reader &in) { #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ return in.Read(&value, sizeof(value)) == sizeof(value); #else static_assert(false, "Not a little-endian"); #endif } static bool ReadFixed(uint64_t &value, Reader &in) { #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ return in.Read(&value, sizeof(value)) == sizeof(value); #else static_assert(false, "Not a little-endian"); #endif } static bool ReadFixed(double &value, Reader &in) { uint64_t intermediateValue; if (ReadFixed(intermediateValue, in)) { value = BitCast(intermediateValue); return true; } return false; } static bool ReadFixed(float &value, Reader &in) { uint32_t intermediateValue; if (ReadFixed(intermediateValue, in)) { value = BitCast(intermediateValue); return true; } return false; } static bool ReadVarint(int32_t &value, Reader &in) { uint32_t intermediateValue; if (ReadVarint(intermediateValue, in)) { value = BitCast(intermediateValue); return true; } return false; } static bool ReadVarint(int64_t &value, Reader &in) { uint64_t intermediateValue; if (ReadVarint(intermediateValue, in)) { value = BitCast(intermediateValue); return true; } return false; } static bool ReadSignedVarint(int32_t &value, Reader &in) { uint32_t intermediateValue; if (ReadVarint(intermediateValue, in)) { value = ReadZigzagValue(intermediateValue); return true; } return false; } static bool ReadSignedVarint(int64_t &value, Reader &in) { uint64_t intermediateValue; if (ReadVarint(intermediateValue, in)) { value = ReadZigzagValue(intermediateValue); return true; } return false; } static bool ReadSignedFixed(int32_t &value, Reader &in) { uint32_t intermediateValue; if (ReadFixed(intermediateValue, in)) { value = static_cast(intermediateValue); return true; } return false; } static bool ReadSignedFixed(int64_t &value, Reader &in) { uint64_t intermediateValue; if (ReadFixed(intermediateValue, in)) { value = static_cast(intermediateValue); return true; } return false; } template void WriteField(const T &value, const SerialDetail::OneofFieldImpl &, Writer &out) { using OneOf = SerialDetail::OneofFieldImpl; Serializer::template SerializeOneof( OneOf::TAG, OneOf::get(value), FlagsType(), out); } template void WriteField(const T &value, const SerialDetail::MapFieldImpl &, Writer &out) { using Map = SerialDetail::MapFieldImpl; Serializer::SerializeMap( Map::TAG, Map::get(value), FlagsType(), FlagsType(), out); } template void WriteField(const T &value, const SerialDetail::FieldImpl &, Writer &out) { using Field = SerialDetail::FieldImpl; Serializer::Serialize( Field::TAG, Field::get(value), FlagsType(), out); } template void WriteMessage(const T &value, const SerialDetail::MessageImpl &message, Writer &out) { message.Visit([&](const auto &field) { WriteField(value, field, out); }); } template void WriteRepeated(uint32_t tag, It begin, It end, Writer &out) { if (begin == end) { return; } if constexpr (SerialDetail::HAS_SERIALIZE_PACKED_V, ValueType, FlagsType, Writer>) { WriteVarint(MakeTagWireType(tag, WireType::LENGTH_DELIMETED), out); WriterSizeCollector sizeCollector; for (auto it = begin; it != end; ++it) { Serializer::SerializePacked(*it, FlagsType {}, sizeCollector); } WriteVarint(sizeCollector.byte_size, out); for (auto it = begin; it != end; ++it) { Serializer::SerializePacked(*it, FlagsType {}, out); } } else { for (auto it = begin; it != end; ++it) { Serializer::Serialize(tag, *it, FlagsType(), out); } } } template void WriteMapKeyValue(const std::pair &value, Writer &out) { Serializer::Serialize(1, value.first, FlagsType {}, out, true); Serializer::Serialize(2, value.second, FlagsType {}, out, true); // 2:tag value } template void WriteMap(uint32_t tag, const T &value, Writer &out) { auto begin = std::begin(value); auto end = std::end(value); for (auto it = begin; it != end; ++it) { WriteTagWriteType(tag, WireType::LENGTH_DELIMETED, out); WriterSizeCollector sizeCollector; WriteMapKeyValue(*it, sizeCollector); WriteVarint(sizeCollector.byte_size, out); WriteMapKeyValue(*it, out); } } template bool ReadMapKeyValue(std::pair &value, Reader &in) { static const auto pairAsMessage = Message(Field<1, &std::pair::first, KeyFlags>("key"), Field<2, &std::pair::second, ValueFlags>("value")); return ReadMessage(value, pairAsMessage, in); } template bool ReadMap(WireType wireType, T &value, Reader &in) { if (wireType != WireType::LENGTH_DELIMETED) { return false; } size_t size; if (ReadVarint(size, in)) { LimitedReader limitedIn(in, size); while (limitedIn.AvailableBytes() > 0) { std::pair item; if (!ReadMapKeyValue(item, limitedIn)) { return false; } value.insert(std::move(item)); } return true; } return false; } template bool ReadRepeated(WireType wireType, OutputIt output_it, Reader &in) { if constexpr (SerialDetail::HAS_PARSE_PACKED_V, ValueType, FlagsType, Reader>) { if (wireType != WireType::LENGTH_DELIMETED) { return false; } size_t size; if (ReadVarint(size, in)) { LimitedReader limitedIn(in, size); while (limitedIn.AvailableBytes() > 0) { ValueType value; if (!Serializer::ParsePacked(value, FlagsType(), limitedIn)) { return false; } output_it = value; ++output_it; } return true; } return false; } else { ValueType value; if (Serializer::Parse(wireType, value, FlagsType(), in)) { output_it = value; ++output_it; return true; } return false; } } template void ReadField(T &value, uint32_t tag, WireType wireType, const SerialDetail::OneofFieldImpl &, Reader &in) { if (Tag != tag) { return; } using OneOf = SerialDetail::OneofFieldImpl; Serializer::template ParseOneof( wireType, OneOf::get(value), FlagsType(), in); } template void ReadField(T &value, uint32_t tag, WireType wireType, const SerialDetail::MapFieldImpl &, Reader &in) { if (Tag != tag) { return; } using Map = SerialDetail::MapFieldImpl; Serializer::ParseMap( wireType, Map::get(value), FlagsType(), FlagsType(), in); } template void ReadField(T &value, uint32_t tag, WireType wireType, const SerialDetail::FieldImpl &, Reader &in) { if (Tag != tag) { return; } using Field = SerialDetail::FieldImpl; Serializer::Parse(wireType, Field::get(value), FlagsType(), in); } template bool ReadMessage(T &value, const MessageImpl &message, Reader &in) { uint32_t tagKey; while (ReadVarint(tagKey, in)) { uint32_t tag; WireType wireType; ReadTagWireType(tagKey, tag, wireType); message.Visit([&](const auto &field) { ReadField(value, tag, wireType, field, in); }); } return true; } } template struct Serializer { // Commion Serializer threat type as Message static void Serialize(uint32_t tag, const T &value, FlagsType<>, Writer &out, bool force = false) { SerialDetail::WriterSizeCollector sizeCollector; SerialDetail::WriteMessage(value, MessageType(), sizeCollector); if (!force && sizeCollector.byte_size == 0) { return; } SerialDetail::WriteTagWriteType(tag, WireType::LENGTH_DELIMETED, out); SerialDetail::WriteVarint(sizeCollector.byte_size, out); SerialDetail::WriteMessage(value, MessageType(), out); } static bool Parse(WireType wireType, T &value, FlagsType<>, Reader &in) { if (wireType != WireType::LENGTH_DELIMETED) { return false; } size_t size; if (SerialDetail::ReadVarint(size, in)) { SerialDetail::LimitedReader limitedIn(in, size); return SerialDetail::ReadMessage(value, MessageType(), limitedIn); } return false; } }; template<> struct Serializer { static void Serialize(uint32_t tag, int32_t value, FlagsType<>, Writer &out, bool force = false) { (void)force; SerialDetail::WriteTagWriteType(tag, WireType::VARINT, out); SerialDetail::WriteVarint(value, out); } static void Serialize(uint32_t tag, int32_t value, FlagsType, Writer &out, bool force = false) { (void)force; SerialDetail::WriteTagWriteType(tag, WireType::VARINT, out); SerialDetail::WriteSignedVarint(value, out); } static void Serialize( uint32_t tag, int32_t value, FlagsType, Writer &out, bool force = false) { (void)force; SerialDetail::WriteTagWriteType(tag, WireType::FIXED32, out); SerialDetail::WriteSignedFixed(value, out); } static void SerializePacked(int32_t value, FlagsType<>, Writer &out) { SerialDetail::WriteVarint(value, out); } static void SerializePacked(int32_t value, FlagsType, Writer &out) { SerialDetail::WriteSignedVarint(value, out); } static void SerializePacked(int32_t value, FlagsType, Writer &out) { SerialDetail::WriteSignedFixed(value, out); } static bool Parse(WireType wire_type, int32_t &value, FlagsType<>, Reader &in) { if (wire_type != WireType::VARINT) return false; return SerialDetail::ReadVarint(value, in); } static bool Parse(WireType wire_type, int32_t &value, FlagsType, Reader &in) { if (wire_type != WireType::VARINT) return false; return SerialDetail::ReadSignedVarint(value, in); } static bool Parse(WireType wire_type, int32_t &value, FlagsType, Reader &in) { if (wire_type != WireType::FIXED32) return false; return SerialDetail::ReadSignedFixed(value, in); } static bool ParsePacked(int32_t &value, FlagsType<>, Reader &in) { return SerialDetail::ReadVarint(value, in); } static bool ParsePacked(int32_t &value, FlagsType, Reader &in) { return SerialDetail::ReadSignedVarint(value, in); } static bool ParsePacked(int32_t &value, FlagsType, Reader &in) { return SerialDetail::ReadSignedFixed(value, in); } }; template<> struct Serializer { static void Serialize(uint32_t tag, uint32_t value, FlagsType<>, Writer &out, bool force = false) { (void)force; SerialDetail::WriteTagWriteType(tag, WireType::VARINT, out); SerialDetail::WriteVarint(value, out); } static void Serialize(uint32_t tag, uint32_t value, FlagsType, Writer &out, bool force = false) { (void)force; SerialDetail::WriteTagWriteType(tag, WireType::FIXED32, out); SerialDetail::WriteFixed(value, out); } static void SerializePacked(uint32_t value, FlagsType<>, Writer &out) { SerialDetail::WriteVarint(value, out); } static void SerializePacked(uint32_t value, FlagsType, Writer &out) { SerialDetail::WriteFixed(value, out); } static bool Parse(WireType wire_type, uint32_t &value, FlagsType<>, Reader &in) { if (wire_type != WireType::VARINT) return false; return SerialDetail::ReadVarint(value, in); } static bool Parse(WireType wire_type, uint32_t &value, FlagsType, Reader &in) { if (wire_type != WireType::FIXED32) return false; return SerialDetail::ReadFixed(value, in); } static bool ParsePacked(uint32_t &value, FlagsType<>, Reader &in) { return SerialDetail::ReadVarint(value, in); } static bool ParsePacked(uint32_t &value, FlagsType, Reader &in) { return SerialDetail::ReadFixed(value, in); } }; template<> struct Serializer { static void Serialize(uint32_t tag, int64_t value, FlagsType<>, Writer &out, bool force = false) { (void)force; SerialDetail::WriteTagWriteType(tag, WireType::VARINT, out); SerialDetail::WriteVarint(value, out); } static void Serialize(uint32_t tag, int64_t value, FlagsType, Writer &out, bool force = false) { (void)force; SerialDetail::WriteTagWriteType(tag, WireType::VARINT, out); SerialDetail::WriteSignedVarint(value, out); } static void Serialize( uint32_t tag, int64_t value, FlagsType, Writer &out, bool force = false) { (void)force; SerialDetail::WriteTagWriteType(tag, WireType::FIXED64, out); SerialDetail::WriteSignedFixed(value, out); } static void SerializePacked(int64_t value, FlagsType<>, Writer &out) { SerialDetail::WriteVarint(value, out); } static void SerializePacked(int64_t value, FlagsType, Writer &out) { SerialDetail::WriteSignedVarint(value, out); } static void SerializePacked(int64_t value, FlagsType, Writer &out) { SerialDetail::WriteSignedFixed(value, out); } static bool Parse(WireType wire_type, int64_t &value, FlagsType<>, Reader &in) { if (wire_type != WireType::VARINT) return false; return SerialDetail::ReadVarint(value, in); } static bool Parse(WireType wire_type, int64_t &value, FlagsType, Reader &in) { if (wire_type != WireType::VARINT) return false; return SerialDetail::ReadSignedVarint(value, in); } static bool Parse(WireType wire_type, int64_t &value, FlagsType, Reader &in) { if (wire_type != WireType::FIXED64) return false; return SerialDetail::ReadSignedFixed(value, in); } static bool ParsePacked(int64_t &value, FlagsType<>, Reader &in) { return SerialDetail::ReadVarint(value, in); } static bool ParsePacked(int64_t &value, FlagsType, Reader &in) { return SerialDetail::ReadSignedVarint(value, in); } static bool ParsePacked(int64_t &value, FlagsType, Reader &in) { return SerialDetail::ReadSignedFixed(value, in); } }; template<> struct Serializer { static void Serialize(uint32_t tag, uint64_t value, FlagsType<>, Writer &out, bool force = false) { (void)force; SerialDetail::WriteTagWriteType(tag, WireType::VARINT, out); SerialDetail::WriteVarint(value, out); } static void Serialize(uint32_t tag, uint64_t value, FlagsType, Writer &out, bool force = false) { if (!force && value == UINT64_C(0)) return; SerialDetail::WriteTagWriteType(tag, WireType::FIXED64, out); SerialDetail::WriteFixed(value, out); } static void SerializePacked(uint64_t value, FlagsType<>, Writer &out) { SerialDetail::WriteVarint(value, out); } static void SerializePacked(uint64_t value, FlagsType, Writer &out) { SerialDetail::WriteFixed(value, out); } static bool Parse(WireType wire_type, uint64_t &value, FlagsType<>, Reader &in) { if (wire_type != WireType::VARINT) return false; return SerialDetail::ReadVarint(value, in); } static bool Parse(WireType wire_type, uint64_t &value, FlagsType, Reader &in) { if (wire_type != WireType::FIXED64) return false; return SerialDetail::ReadFixed(value, in); } static bool ParsePacked(uint64_t &value, FlagsType<>, Reader &in) { return SerialDetail::ReadVarint(value, in); } static bool ParsePacked(uint64_t &value, FlagsType, Reader &in) { return SerialDetail::ReadFixed(value, in); } }; template<> struct Serializer { static void Serialize(uint32_t tag, double value, FlagsType<>, Writer &out, bool force = false) { if (!force && std::fpclassify(value) == FP_ZERO) { return; } SerialDetail::WriteTagWriteType(tag, WireType::FIXED64, out); SerialDetail::WriteFixed(value, out); } static void SerializePacked(double value, FlagsType<>, Writer &out) { SerialDetail::WriteFixed(value, out); } static bool Parse(WireType wire_type, double &value, FlagsType<>, Reader &in) { if (wire_type != WireType::FIXED64) { return false; } return SerialDetail::ReadFixed(value, in); } static bool ParsePacked(double &value, FlagsType<>, Reader &in) { return SerialDetail::ReadFixed(value, in); } }; template<> struct Serializer { static void Serialize(uint32_t tag, float value, FlagsType<>, Writer &out, bool force = false) { if (!force && std::fpclassify(value) == FP_ZERO) { return; } SerialDetail::WriteTagWriteType(tag, WireType::FIXED32, out); SerialDetail::WriteFixed(value, out); } static void SerializePacked(float value, FlagsType<>, Writer &out) { SerialDetail::WriteFixed(value, out); } static bool Parse(WireType wire_type, float &value, FlagsType<>, Reader &in) { if (wire_type != WireType::FIXED32) { return false; } return SerialDetail::ReadFixed(value, in); } static bool ParsePacked(float &value, FlagsType<>, Reader &in) { return SerialDetail::ReadFixed(value, in); } }; template<> struct Serializer { static void Serialize(uint32_t tag, bool value, FlagsType<>, Writer &out, bool force = false) { Serializer::Serialize(tag, value ? 1 : 0, FlagsType(), out, force); } static void SerializePacked(bool value, FlagsType<>, Writer &out) { Serializer::SerializePacked(value ? 1 : 0, FlagsType(), out); } static bool Parse(WireType wire_type, bool &value, FlagsType<>, Reader &in) { uint32_t intermedaite_value; if (Serializer::Parse(wire_type, intermedaite_value, FlagsType<>(), in)) { value = static_cast(intermedaite_value); return true; } return false; } static bool ParsePacked(bool &value, FlagsType<>, Reader &in) { uint32_t intermedaite_value; if (Serializer::ParsePacked(intermedaite_value, FlagsType<>(), in)) { value = static_cast(intermedaite_value); return true; } return false; } }; template struct Serializer>> { using U = std::underlying_type_t; static void Serialize(uint32_t tag, T value, FlagsType<>, Writer &out, bool force = false) { Serializer::Serialize(tag, static_cast(value), FlagsType<>(), out, force); } static void SerializePacked(T value, FlagsType<>, Writer &out) { Serializer::SerializePacked(static_cast(value), FlagsType<>(), out); } static bool Parse(WireType wire_type, T &value, FlagsType<>, Reader &in) { U intermedaite_value; if (Serializer::Parse(wire_type, intermedaite_value, FlagsType<>(), in)) { value = static_cast(intermedaite_value); return true; } return false; } static bool ParsePacked(T &value, FlagsType<>, Reader &in) { U intermedaite_value; if (Serializer::ParsePacked(intermedaite_value, FlagsType<>(), in)) { value = static_cast(intermedaite_value); return true; } return false; } }; template<> struct Serializer { static void Serialize(uint32_t tag, const std::string &value, FlagsType<>, Writer &out, bool force = false) { (void)force; SerialDetail::WriteTagWriteType(tag, WireType::LENGTH_DELIMETED, out); SerialDetail::WriteVarint(value.size(), out); out.Write(value.data(), value.size()); } static bool Parse(WireType wire_type, std::string &value, FlagsType<>, Reader &in) { if (wire_type != WireType::LENGTH_DELIMETED) { return false; } size_t size; if (SerialDetail::ReadVarint(size, in)) { value.resize(size); if (in.Read(value.data(), size) == size) { return true; } } return false; } }; template struct Serializer> { template static void Serialize(uint32_t tag, const std::vector &value, FlagsType, Writer &out) { SerialDetail::WriteRepeated(tag, value.begin(), value.end(), out); } template static bool Parse(WireType wire_type, std::vector &value, FlagsType, Reader &in) { return SerialDetail::ReadRepeated(wire_type, std::back_inserter(value), in); } }; template struct Serializer> { template static void Serialize(uint32_t tag, const std::optional &value, FlagsType, Writer &out) { if (!value.has_value()) { return; } Serializer::Serialize(tag, *value, FlagsType(), out); } template static bool Parse(WireType wire_type, std::optional &value, FlagsType, Reader &in) { return Serializer::Parse(wire_type, value.emplace(), FlagsType(), in); } }; template struct Serializer> { template static void SerializeOneof(uint32_t tag, const std::variant &value, FlagsType, Writer &out) { if (value.index() != Index) return; Serializer>>::Serialize( tag, std::get(value), FlagsType(), out); } template static bool ParseOneof(WireType wire_type, std::variant &value, FlagsType, Reader &in) { return Serializer>>::Parse( wire_type, value.template emplace(), FlagsType(), in); } }; template struct Serializer> { template static void SerializeMap( uint32_t tag, const std::map &value, FlagsType, FlagsType, Writer &out) { SerialDetail::WriteMap(tag, value, out); } template static bool ParseMap( WireType wire_type, std::map &value, FlagsType, FlagsType, Reader &in) { return SerialDetail::ReadMap(wire_type, value, in); } }; struct StringWriter : public Writer { StringWriter(std::string &out) : _out(out) { } void Write(const void *bytes, size_t size) override { _out.append(reinterpret_cast(bytes), size); } private: std::string &_out; }; struct StringReader : public Reader { StringReader(const std::string &in) : _in(in), _pos(0) { } size_t Read(void *bytes, size_t size) override { size_t readSize = std::min(size, _in.size() - _pos); if (memcpy_s(bytes, size, _in.data() + _pos, readSize) != EOK) { return readSize; } _pos += readSize; return readSize; } private: const std::string &_in; size_t _pos; }; // mytype begin, just support base type, but really use protobuf raw type(uint32) template<> struct Serializer { static void Serialize(uint32_t tag, uint8_t value, FlagsType<>, Writer &out, bool force = false) { Serializer::Serialize(tag, value, FlagsType(), out, force); } static void SerializePacked(uint8_t value, FlagsType<>, Writer &out) { Serializer::SerializePacked(value, FlagsType(), out); } static bool Parse(WireType wire_type, uint8_t &value, FlagsType<>, Reader &in) { uint32_t intermedaite_value; if (Serializer::Parse(wire_type, intermedaite_value, FlagsType<>(), in)) { value = static_cast(intermedaite_value); return true; } return false; } static bool ParsePacked(uint8_t &value, FlagsType<>, Reader &in) { uint32_t intermedaite_value; if (Serializer::ParsePacked(intermedaite_value, FlagsType<>(), in)) { value = static_cast(intermedaite_value); return true; } return false; } }; template<> struct Serializer { static void Serialize(uint32_t tag, uint16_t value, FlagsType<>, Writer &out, bool force = false) { Serializer::Serialize(tag, value, FlagsType(), out, force); } static void SerializePacked(uint16_t value, FlagsType<>, Writer &out) { Serializer::SerializePacked(value, FlagsType(), out); } static bool Parse(WireType wire_type, uint16_t &value, FlagsType<>, Reader &in) { uint32_t intermedaite_value; if (Serializer::Parse(wire_type, intermedaite_value, FlagsType<>(), in)) { value = static_cast(intermedaite_value); return true; } return false; } static bool ParsePacked(uint16_t &value, FlagsType<>, Reader &in) { uint32_t intermedaite_value; if (Serializer::ParsePacked(intermedaite_value, FlagsType<>(), in)) { value = static_cast(intermedaite_value); return true; } return false; } }; // mytype finish template std::string SerializeToString(const T &value) { std::string out; StringWriter stringOut(out); SerialDetail::WriteMessage(value, MessageType(), stringOut); return out; } template bool ParseFromString(T &value, const std::string &in) { StringReader stringIn(in); return SerialDetail::ReadMessage(value, MessageType(), stringIn); } } // clang-format on } // Hdc #endif // HDC_SERIAL_STRUCT_DEFINE_H