#pragma once #include "macro_map.h" #include #include #include #include #include #include #include #include #include "optionalVersion.h" struct AbsolutePath; enum class SerializeFormat { Json, MessagePack }; // A tag type that can be used to write `null` to json. struct JsonNull { void swap(JsonNull& arg) noexcept; }; class Reader { public: virtual ~Reader() {} virtual SerializeFormat Format() const = 0; virtual bool IsBool() = 0; virtual bool IsNull() = 0; virtual bool IsArray() = 0; virtual bool IsInt() = 0; virtual bool IsInt64() = 0; virtual bool IsUint64() = 0; virtual bool IsDouble() = 0; virtual bool IsNumber() = 0; virtual bool IsString() = 0; virtual void GetNull() = 0; virtual bool GetBool() = 0; virtual int GetInt() = 0; virtual uint32_t GetUint32() = 0; virtual int64_t GetInt64() = 0; virtual uint64_t GetUint64() = 0; virtual double GetDouble() = 0; virtual std::string GetString() = 0; virtual bool HasMember(const char* x) = 0; virtual std::unique_ptr operator[](const char* x) = 0; virtual void IterMap( std::function fn) = 0; virtual void IterArray(std::function fn) = 0; virtual void DoMember(const char* name, std::function fn) = 0; virtual std::string ToString() const = 0; }; class Writer { public: virtual ~Writer() {} virtual SerializeFormat Format() const = 0; virtual void Null() = 0; virtual void Bool(bool x) = 0; virtual void Int(int x) = 0; virtual void Uint32(uint32_t x) = 0; virtual void Int64(int64_t x) = 0; virtual void Uint64(uint64_t x) = 0; virtual void Double(double x) = 0; virtual void String(const char* x) = 0; virtual void String(const char* x, size_t len) = 0; virtual void StartArray(size_t) = 0; virtual void EndArray() = 0; virtual void StartObject() = 0; virtual void EndObject() = 0; virtual void Key(const char* name) = 0; }; struct optionals_mandatory_tag {}; #define REFLECT_MEMBER_START() ReflectMemberStart(visitor, value) #define REFLECT_MEMBER_END() ReflectMemberEnd(visitor, value); #define REFLECT_MEMBER_END1(value) ReflectMemberEnd(visitor, value); #define REFLECT_MEMBER(name) ReflectMember(visitor, #name, value.name) #define REFLECT_MEMBER_OPTIONALS(name) \ ReflectMember(visitor, #name, value.name, optionals_mandatory_tag{}) #define REFLECT_MEMBER2(name, value) ReflectMember(visitor, name, value) #define MAKE_REFLECT_TYPE_PROXY(type_name) \ MAKE_REFLECT_TYPE_PROXY2(type_name, std::underlying_type::type) #define MAKE_REFLECT_TYPE_PROXY2(type, as_type) \ inline void Reflect(Reader& visitor, type& value) { \ as_type value0; \ ::Reflect(visitor, value0); \ value = static_cast(value0); \ } \ inline void Reflect(Writer& visitor, type& value) { \ auto value0 = static_cast(value); \ ::Reflect(visitor, value0); \ } #define _MAPPABLE_REFLECT_MEMBER(name) REFLECT_MEMBER(name); #define _MAPPABLE_REFLECT_MEMBER_OPTIONALS(name) REFLECT_MEMBER_OPTIONALS(name); #define MAKE_REFLECT_EMPTY_STRUCT(type, ...) \ template \ void Reflect(TVisitor& visitor, type& value) { \ REFLECT_MEMBER_START(); \ REFLECT_MEMBER_END(); \ } #define MAKE_REFLECT_STRUCT(type, ...) \ template \ void Reflect(TVisitor& visitor, type& value) { \ REFLECT_MEMBER_START(); \ MACRO_MAP(_MAPPABLE_REFLECT_MEMBER, __VA_ARGS__) \ REFLECT_MEMBER_END(); \ } #define _MAPPABLE_SWAP_MEMBER(name) std::swap(name,arg.name); #define MAKE_SWAP_METHOD(type, ...) \ void swap(type& arg) noexcept{ \ MACRO_MAP(_MAPPABLE_SWAP_MEMBER, __VA_ARGS__) \ } #define MAKE_REFLECT_STRUCT_OPTIONALS_MANDATORY(type, ...) \ template \ void Reflect(TVisitor& visitor, type& value) { \ REFLECT_MEMBER_START(); \ MACRO_MAP(_MAPPABLE_REFLECT_MEMBER_OPTIONALS, __VA_ARGS__) \ REFLECT_MEMBER_END(); \ } // clang-format off // Config has many fields, we need to support at least its number of fields. #define NUM_VA_ARGS_IMPL(_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,N,...) N #define NUM_VA_ARGS(...) NUM_VA_ARGS_IMPL(__VA_ARGS__,30,29,28,27,26,25,24,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1) // clang-format on #define _MAPPABLE_REFLECT_ARRAY(name) Reflect(visitor, value.name); // Reflects the struct so it is serialized as an array instead of an object. // This currently only supports writers. #define MAKE_REFLECT_STRUCT_WRITER_AS_ARRAY(type, ...) \ inline void Reflect(Writer& visitor, type& value) { \ visitor.StartArray(NUM_VA_ARGS(__VA_ARGS__)); \ MACRO_MAP(_MAPPABLE_REFLECT_ARRAY, __VA_ARGS__) \ visitor.EndArray(); \ } //// Elementary types void Reflect(Reader& visitor, uint8_t& value); void Reflect(Writer& visitor, uint8_t& value); void Reflect(Reader& visitor, short& value); void Reflect(Writer& visitor, short& value); void Reflect(Reader& visitor, unsigned short& value); void Reflect(Writer& visitor, unsigned short& value); void Reflect(Reader& visitor, int& value); void Reflect(Writer& visitor, int& value); void Reflect(Reader& visitor, unsigned& value); void Reflect(Writer& visitor, unsigned& value); void Reflect(Reader& visitor, long& value); void Reflect(Writer& visitor, long& value); void Reflect(Reader& visitor, unsigned long& value); void Reflect(Writer& visitor, unsigned long& value); void Reflect(Reader& visitor, long long& value); void Reflect(Writer& visitor, long long& value); void Reflect(Reader& visitor, unsigned long long& value); void Reflect(Writer& visitor, unsigned long long& value); void Reflect(Reader& visitor, double& value); void Reflect(Writer& visitor, double& value); void Reflect(Reader& visitor, bool& value); void Reflect(Writer& visitor, bool& value); void Reflect(Reader& visitor, std::string& value); void Reflect(Writer& visitor, std::string& value); void Reflect(Reader& visitor, JsonNull& value); void Reflect(Writer& visitor, JsonNull& value); void Reflect(Reader& visitor, SerializeFormat& value); void Reflect(Writer& visitor, SerializeFormat& value); //// Type constructors template void Reflect(Reader& visitor, optional& value) { if (visitor.IsNull()) { visitor.GetNull(); return; } T real_value; Reflect(visitor, real_value); value = std::move(real_value); } template void Reflect(Writer& visitor, optional& value) { if (value) Reflect(visitor, *value); else visitor.Null(); } template void ReflectMember(Writer& visitor, const char* name, optional& value) { // For TypeScript optional property key?: value in the spec, // We omit both key and value if value is std::nullopt (null) for JsonWriter // to reduce output. But keep it for other serialization formats. if (value || visitor.Format() != SerializeFormat::Json) { visitor.Key(name); Reflect(visitor, value); } } template void ReflectMember(Writer& visitor, const char* name, T& value, optionals_mandatory_tag) { visitor.Key(name); Reflect(visitor, value); } template void ReflectMember(Reader& visitor, const char* name, T& value, optionals_mandatory_tag) { Reflect(visitor, value); } template void Reflect(Reader& visitor, std::map& value) { visitor.IterMap([&](const char* name,Reader& entry) { T entry_value; Reflect(entry, entry_value); value[name]=(std::move(entry_value)); }); } template void Reflect(Writer& visitor, std::map& value) { REFLECT_MEMBER_START(); for (auto& it : value) { visitor.Key(it.first.c_str()); Reflect(visitor, it.second); } REFLECT_MEMBER_END(); } // std::vector template void Reflect(Reader& visitor, std::vector& values) { visitor.IterArray([&](Reader& entry) { T entry_value; Reflect(entry, entry_value); values.push_back(std::move(entry_value)); }); } template void Reflect(Writer& visitor, std::vector& values) { visitor.StartArray(values.size()); for (auto& value : values) Reflect(visitor, value); visitor.EndArray(); } // ReflectMember inline void DefaultReflectMemberStart(Writer& visitor) { visitor.StartObject(); } inline void DefaultReflectMemberStart(Reader& visitor) {} template bool ReflectMemberStart(Reader& visitor, T& value) { return false; } template bool ReflectMemberStart(Writer& visitor, T& value) { visitor.StartObject(); return true; } template void ReflectMemberEnd(Reader& visitor, T& value) {} template void ReflectMemberEnd(Writer& visitor, T& value) { visitor.EndObject(); } template void ReflectMember(Reader& visitor, const char* name, T& value) { visitor.DoMember(name, [&](Reader& child) { Reflect(child, value); }); } template void ReflectMember(Writer& visitor, const char* name, T& value) { visitor.Key(name); Reflect(visitor, value); } template void Reflect(Writer& visitor, std::pair< optional<_Ty1>, optional<_Ty2> >& value) { if (value.first) { Reflect(visitor, value.first); } else { Reflect(visitor, value.second); } } template void Reflect(Reader& visitor, std::pair< optional, optional<_Ty2> >& value) { if(visitor.IsBool()) { Reflect(visitor, value.first); return; } Reflect(visitor, value.second); } template void Reflect(Reader& visitor, std::pair< optional, optional<_Ty2> >& value) { if (visitor.IsString()) { Reflect(visitor, value.first); return; } Reflect(visitor, value.second); } template void Reflect(Reader& visitor, std::pair< optional<_Ty1>, optional<_Ty2> >& value) { try { Reflect(visitor, value.second); } catch (...) { Reflect(visitor, value.first); } }