From 27ddce4cd66002f23b1103d112e957646fd620ee Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Wed, 10 Jan 2018 23:16:33 -0800 Subject: [PATCH] Reader reflection of std::variant --- src/language_server_api.cc | 23 ----------------- src/language_server_api.h | 2 -- src/query_utils.cc | 2 +- src/serializer.h | 52 ++++++++++++++++++++++++++++++++------ src/serializers/json.h | 2 +- src/serializers/msgpack.h | 1 + 6 files changed, 47 insertions(+), 35 deletions(-) diff --git a/src/language_server_api.cc b/src/language_server_api.cc index 1398ff62..f2416dbd 100644 --- a/src/language_server_api.cc +++ b/src/language_server_api.cc @@ -7,29 +7,6 @@ #include -void Reflect(Reader& visitor, std::variant& version) { - if (visitor.IsNull()) { - visitor.GetNull(); - version = std::monostate(); - } else - version = visitor.GetInt(); -} - -void Reflect(Reader& visitor, lsRequestId& id) { - if (visitor.IsNull()) { - visitor.GetNull(); - id = std::monostate(); - } else if (visitor.IsString()) { - std::string v; - Reflect(visitor, v); - id = v; - } else { - int64_t v; - Reflect(visitor, v); - id = v; - } -} - MessageRegistry* MessageRegistry::instance_ = nullptr; lsTextDocumentIdentifier diff --git a/src/language_server_api.h b/src/language_server_api.h index 06d0c6d7..a3870142 100644 --- a/src/language_server_api.h +++ b/src/language_server_api.h @@ -24,7 +24,6 @@ ///////////////////////////////////////////////////////////////////////////// using lsRequestId = std::variant; -void Reflect(Reader& visitor, lsRequestId& id); ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// @@ -253,7 +252,6 @@ struct lsTextDocumentIdentifier { }; MAKE_REFLECT_STRUCT(lsTextDocumentIdentifier, uri); -void Reflect(Reader& visitor, std::variant& version); struct lsVersionedTextDocumentIdentifier { lsDocumentUri uri; // The version number of this document. number | null diff --git a/src/query_utils.cc b/src/query_utils.cc index 00888958..eff1f271 100644 --- a/src/query_utils.cc +++ b/src/query_utils.cc @@ -532,4 +532,4 @@ void EmitDiagnostics(WorkingFiles* working_files, if (working_file) working_file->diagnostics_ = diagnostics; }); -} \ No newline at end of file +} diff --git a/src/serializer.h b/src/serializer.h index 893225f3..fffbffa7 100644 --- a/src/serializer.h +++ b/src/serializer.h @@ -4,8 +4,10 @@ #include #include +#include #include #include +#include #include enum class SerializeFormat { Json, MessagePack }; @@ -19,7 +21,7 @@ class Reader { virtual bool IsNull() = 0; virtual bool IsArray() = 0; virtual bool IsInt() = 0; - // virtual bool IsInt64() = 0; + virtual bool IsInt64() = 0; // virtual bool IsUint64() = 0; virtual bool IsString() = 0; @@ -187,8 +189,44 @@ void Reflect(Writer& visitor, optional& value) { visitor.Null(); } +namespace { +template +struct disjunction + : std::conditional>::type {}; +template +struct disjunction : B0 {}; +} + template struct ReflectVariant { + template + typename std::enable_if...>::value, + void>::type + ReflectTag(Reader& visitor, std::variant& value) { + T a; + Reflect(visitor, a); + value = a; + } + template + typename std::enable_if...>::value, + void>::type + ReflectTag(Reader&, std::variant&) {} + + void operator()(Reader& visitor, std::variant& value) { + if (visitor.IsNull()) + ReflectTag(visitor, value); + // It is possible that IsInt64() && IsInt(). We don't call ReflectTag if + // int is not in Ts... + else if (disjunction...>::value && visitor.IsInt()) + ReflectTag(visitor, value); + else if (visitor.IsInt64()) + ReflectTag(visitor, value); + else if (visitor.IsString()) + ReflectTag(visitor, value); + else + assert(0); + } + void operator()(Writer& visitor, std::variant& value) { if (value.index() == N - 1) Reflect(visitor, std::get(value)); @@ -198,15 +236,13 @@ struct ReflectVariant { }; template -struct ReflectVariant<1, Ts...> { - void operator()(Writer& visitor, std::variant& value) { - Reflect(visitor, std::get<0>(value)); - } +struct ReflectVariant<0, Ts...> { + void operator()(Writer& visitor, std::variant& value) {} }; -// std::variant (Writer only) -template -void Reflect(Writer& visitor, std::variant& value) { +// std::variant +template +void Reflect(TVisitor& visitor, std::variant& value) { ReflectVariant()(visitor, value); } diff --git a/src/serializers/json.h b/src/serializers/json.h index 1ec51f05..297e188f 100644 --- a/src/serializers/json.h +++ b/src/serializers/json.h @@ -16,7 +16,7 @@ class JsonReader : public Reader { bool IsNull() override { return m_->IsNull(); } bool IsArray() override { return m_->IsArray(); } bool IsInt() override { return m_->IsInt(); } - // bool IsInt64() override { return m_->IsInt64(); } + bool IsInt64() override { return m_->IsInt64(); } // bool IsUint64() override { return m_->IsUint64(); } bool IsString() override { return m_->IsString(); } diff --git a/src/serializers/msgpack.h b/src/serializers/msgpack.h index f9704508..df55a9da 100644 --- a/src/serializers/msgpack.h +++ b/src/serializers/msgpack.h @@ -27,6 +27,7 @@ class MessagePackReader : public Reader { return oh_.get().type == msgpack::type::POSITIVE_INTEGER || oh_.get().type == msgpack::type::NEGATIVE_INTEGER; } + bool IsInt64() override { return IsInt(); } bool IsString() override { return oh_.get().type == msgpack::type::STR; } void GetNull() override { pk_->next(oh_); }