diff options
Diffstat (limited to 'graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/serializer.h')
-rw-r--r-- | graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/serializer.h | 378 |
1 files changed, 378 insertions, 0 deletions
diff --git a/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/serializer.h b/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/serializer.h new file mode 100644 index 0000000000..71b6bede59 --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/serializer.h @@ -0,0 +1,378 @@ +#pragma once + +#include "macro_map.h" +#ifdef boost +#include "optional.hpp" +#else +#include <boost/optional.hpp> +#endif + +#include <cassert> +#include <memory> +#include <string> +#include <type_traits> +#include <vector> +#include <functional> +#include <map> +#include <algorithm> + + +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<Reader> operator[](const char* x) = 0; + virtual void IterMap( std::function<void(const char*, Reader&)> fn) = 0; + virtual void IterArray(std::function<void(Reader&)> fn) = 0; + virtual void DoMember(const char* name, std::function<void(Reader&)> 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_name>::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<type>(value0); \ + } \ + inline void Reflect(Writer& visitor, type& value) { \ + auto value0 = static_cast<as_type>(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 <typename TVisitor> \ + void Reflect(TVisitor& visitor, type& value) { \ + REFLECT_MEMBER_START(); \ + REFLECT_MEMBER_END(); \ + } + +#define MAKE_REFLECT_STRUCT(type, ...) \ + template <typename TVisitor> \ + 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 <typename TVisitor> \ + 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 <typename T> +void Reflect(Reader& visitor, boost::optional<T>& value) { + if (visitor.IsNull()) { + visitor.GetNull(); + return; + } + T real_value; + Reflect(visitor, real_value); + value = std::move(real_value); +} +template <typename T> +void Reflect(Writer& visitor, boost::optional<T>& value) { + if (value) + Reflect(visitor, *value); + else + visitor.Null(); +} + + +template <typename T> +void ReflectMember(Writer& visitor, const char* name, boost::optional<T>& 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 <typename T> +void ReflectMember(Writer& visitor, + const char* name, + T& value, + optionals_mandatory_tag) { + visitor.Key(name); + Reflect(visitor, value); +} +template <typename T> +void ReflectMember(Reader& visitor, + const char* name, + T& value, + optionals_mandatory_tag) { + Reflect(visitor, value); +} + +template<class T > +void Reflect(Reader& visitor, std::map<std::string, T>& value) +{ + visitor.IterMap([&](const char* name,Reader& entry) { + T entry_value; + Reflect(entry, entry_value); + value[name]=(std::move(entry_value)); + }); +} +template<class _Ty > +void Reflect(Writer& visitor, std::map<std::string, _Ty>& value) +{ + REFLECT_MEMBER_START(); + for (auto& it : value) + { + visitor.Key(it.first.c_str()); + Reflect(visitor, it.second); + } + REFLECT_MEMBER_END(); +} + +// std::vector +template <typename T> +void Reflect(Reader& visitor, std::vector<T>& values) { + visitor.IterArray([&](Reader& entry) { + T entry_value; + Reflect(entry, entry_value); + values.push_back(std::move(entry_value)); + }); +} + + +template <typename T> +void Reflect(Writer& visitor, std::vector<T>& 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 <typename T> +bool ReflectMemberStart(Reader& visitor, T& value) { + return false; +} +template <typename T> +bool ReflectMemberStart(Writer& visitor, T& value) { + visitor.StartObject(); + return true; +} + +template <typename T> +void ReflectMemberEnd(Reader& visitor, T& value) {} +template <typename T> +void ReflectMemberEnd(Writer& visitor, T& value) { + visitor.EndObject(); +} + +template <typename T> +void ReflectMember(Reader& visitor, const char* name, T& value) { + visitor.DoMember(name, [&](Reader& child) { Reflect(child, value); }); +} +template <typename T> +void ReflectMember(Writer& visitor, const char* name, T& value) { + visitor.Key(name); + Reflect(visitor, value); +} + +template<class _Ty1, class _Ty2> +void Reflect(Writer& visitor, std::pair< boost::optional<_Ty1>, boost::optional<_Ty2> >& value) +{ + if (value.first) + { + Reflect(visitor, value.first); + } + else + { + Reflect(visitor, value.second); + } +} +template<class _Ty2> +void Reflect(Reader& visitor, std::pair< boost::optional<bool>, boost::optional<_Ty2> >& value) +{ + if(visitor.IsBool()) + { + Reflect(visitor, value.first); + return; + } + + Reflect(visitor, value.second); +} +template<class _Ty2> +void Reflect(Reader& visitor, std::pair< boost::optional<std::string>, boost::optional<_Ty2> >& value) +{ + if (visitor.IsString()) + { + Reflect(visitor, value.first); + return; + } + + Reflect(visitor, value.second); +} + + +template<class _Ty1, class _Ty2> +void Reflect(Reader& visitor, std::pair< boost::optional<_Ty1>, boost::optional<_Ty2> >& value) +{ + try + { + Reflect(visitor, value.second); + } + catch (...) + { + Reflect(visitor, value.first); + } +} |