849 lines
19 KiB
C++
849 lines
19 KiB
C++
#include <glaze/glaze.hpp>
|
||
#include <variant>
|
||
#include <map>
|
||
#include <vector>
|
||
#include <string>
|
||
#include <cstdint>
|
||
#include <optional>
|
||
#include <type_traits>
|
||
|
||
using integer = std::int32_t;
|
||
using uinteger = std::uint32_t;
|
||
using decimal = double;
|
||
using boolean = bool;
|
||
using string = std::string;
|
||
|
||
// 前向声明
|
||
struct LSPAny;
|
||
using LSPObject = std::map<string, LSPAny>;
|
||
using LSPArray = std::vector<LSPAny>;
|
||
|
||
using LSPAnyVariant = std::variant<
|
||
LSPObject,
|
||
LSPArray,
|
||
string,
|
||
decimal, // 放在前面,优先匹配数字
|
||
boolean,
|
||
std::nullptr_t>;
|
||
|
||
struct LSPAny
|
||
{
|
||
LSPAnyVariant value;
|
||
|
||
// 默认构造函数
|
||
LSPAny() :
|
||
value(nullptr) {}
|
||
|
||
// 拷贝和移动构造函数
|
||
LSPAny(const LSPAny& other) :
|
||
value(other.value) {}
|
||
LSPAny(LSPAny&& other) noexcept :
|
||
value(std::move(other.value)) {}
|
||
|
||
// 针对每种支持的类型的构造函数
|
||
LSPAny(const std::map<string, LSPAny>& val) :
|
||
value(val) {}
|
||
LSPAny(std::map<string, LSPAny>&& val) :
|
||
value(std::move(val)) {}
|
||
|
||
LSPAny(const std::vector<LSPAny>& val) :
|
||
value(val) {}
|
||
LSPAny(std::vector<LSPAny>&& val) :
|
||
value(std::move(val)) {}
|
||
|
||
LSPAny(const string& val) :
|
||
value(val) {}
|
||
LSPAny(string&& val) :
|
||
value(std::move(val)) {}
|
||
LSPAny(const char* val) :
|
||
value(string(val)) {}
|
||
|
||
// 所有数字类型都转换为 decimal
|
||
LSPAny(int val) :
|
||
value(static_cast<decimal>(val)) {}
|
||
LSPAny(long val) :
|
||
value(static_cast<decimal>(val)) {}
|
||
LSPAny(long long val) :
|
||
value(static_cast<decimal>(val)) {}
|
||
LSPAny(unsigned int val) :
|
||
value(static_cast<decimal>(val)) {}
|
||
LSPAny(unsigned long val) :
|
||
value(static_cast<decimal>(val)) {}
|
||
LSPAny(unsigned long long val) :
|
||
value(static_cast<decimal>(val)) {}
|
||
LSPAny(float val) :
|
||
value(static_cast<decimal>(val)) {}
|
||
LSPAny(double val) :
|
||
value(val) {}
|
||
LSPAny(long double val) :
|
||
value(static_cast<decimal>(val)) {}
|
||
|
||
LSPAny(boolean val) :
|
||
value(val) {}
|
||
LSPAny(std::nullptr_t) :
|
||
value(nullptr) {}
|
||
|
||
// 赋值操作符
|
||
LSPAny& operator=(const LSPAny& other)
|
||
{
|
||
value = other.value;
|
||
return *this;
|
||
}
|
||
|
||
LSPAny& operator=(LSPAny&& other) noexcept
|
||
{
|
||
value = std::move(other.value);
|
||
return *this;
|
||
}
|
||
|
||
// 针对每种支持的类型的赋值操作符
|
||
LSPAny& operator=(const std::map<string, LSPAny>& val)
|
||
{
|
||
value = val;
|
||
return *this;
|
||
}
|
||
|
||
LSPAny& operator=(std::map<string, LSPAny>&& val)
|
||
{
|
||
value = std::move(val);
|
||
return *this;
|
||
}
|
||
|
||
LSPAny& operator=(const std::vector<LSPAny>& val)
|
||
{
|
||
value = val;
|
||
return *this;
|
||
}
|
||
|
||
LSPAny& operator=(std::vector<LSPAny>&& val)
|
||
{
|
||
value = std::move(val);
|
||
return *this;
|
||
}
|
||
|
||
LSPAny& operator=(const string& val)
|
||
{
|
||
value = val;
|
||
return *this;
|
||
}
|
||
|
||
LSPAny& operator=(string&& val)
|
||
{
|
||
value = std::move(val);
|
||
return *this;
|
||
}
|
||
|
||
LSPAny& operator=(const char* val)
|
||
{
|
||
value = string(val);
|
||
return *this;
|
||
}
|
||
|
||
// 所有数字类型都转换为 decimal
|
||
LSPAny& operator=(int val)
|
||
{
|
||
value = static_cast<decimal>(val);
|
||
return *this;
|
||
}
|
||
|
||
LSPAny& operator=(long val)
|
||
{
|
||
value = static_cast<decimal>(val);
|
||
return *this;
|
||
}
|
||
|
||
LSPAny& operator=(long long val)
|
||
{
|
||
value = static_cast<decimal>(val);
|
||
return *this;
|
||
}
|
||
|
||
LSPAny& operator=(unsigned int val)
|
||
{
|
||
value = static_cast<decimal>(val);
|
||
return *this;
|
||
}
|
||
|
||
LSPAny& operator=(unsigned long val)
|
||
{
|
||
value = static_cast<decimal>(val);
|
||
return *this;
|
||
}
|
||
|
||
LSPAny& operator=(unsigned long long val)
|
||
{
|
||
value = static_cast<decimal>(val);
|
||
return *this;
|
||
}
|
||
|
||
LSPAny& operator=(float val)
|
||
{
|
||
value = static_cast<decimal>(val);
|
||
return *this;
|
||
}
|
||
|
||
LSPAny& operator=(double val)
|
||
{
|
||
value = val;
|
||
return *this;
|
||
}
|
||
|
||
LSPAny& operator=(long double val)
|
||
{
|
||
value = static_cast<decimal>(val);
|
||
return *this;
|
||
}
|
||
|
||
LSPAny& operator=(boolean val)
|
||
{
|
||
value = val;
|
||
return *this;
|
||
}
|
||
|
||
LSPAny& operator=(std::nullptr_t)
|
||
{
|
||
value = nullptr;
|
||
return *this;
|
||
}
|
||
|
||
// 类型检查辅助函数
|
||
template<typename T>
|
||
bool is() const
|
||
{
|
||
return std::holds_alternative<T>(value);
|
||
}
|
||
|
||
template<typename T>
|
||
T& get()
|
||
{
|
||
return std::get<T>(value);
|
||
}
|
||
|
||
template<typename T>
|
||
const T& get() const
|
||
{
|
||
return std::get<T>(value);
|
||
}
|
||
|
||
// 访问操作符
|
||
template<typename Visitor>
|
||
auto visit(Visitor&& visitor) const
|
||
{
|
||
return std::visit(std::forward<Visitor>(visitor), value);
|
||
}
|
||
|
||
template<typename Visitor>
|
||
auto visit(Visitor&& visitor)
|
||
{
|
||
return std::visit(std::forward<Visitor>(visitor), value);
|
||
}
|
||
};
|
||
|
||
// glaze 自动支持 std::variant,无需额外配置
|
||
namespace glz
|
||
{
|
||
template<>
|
||
struct meta<LSPAny>
|
||
{
|
||
using T = LSPAny;
|
||
static constexpr auto value = &T::value;
|
||
};
|
||
}
|
||
|
||
// ===== 简单清晰的转换模板 =====
|
||
|
||
// 转换工具类
|
||
struct LSPConvert
|
||
{
|
||
// === 基本类型的转换(优先级最高) ===
|
||
|
||
// boolean
|
||
static LSPAny ToLSPAny(boolean value)
|
||
{
|
||
return LSPAny(value);
|
||
}
|
||
|
||
// 整数类型
|
||
static LSPAny ToLSPAny(int value)
|
||
{
|
||
return LSPAny(value);
|
||
}
|
||
|
||
static LSPAny ToLSPAny(long value)
|
||
{
|
||
return LSPAny(value);
|
||
}
|
||
|
||
static LSPAny ToLSPAny(long long value)
|
||
{
|
||
return LSPAny(value);
|
||
}
|
||
|
||
static LSPAny ToLSPAny(unsigned int value)
|
||
{
|
||
return LSPAny(value);
|
||
}
|
||
|
||
static LSPAny ToLSPAny(unsigned long value)
|
||
{
|
||
return LSPAny(value);
|
||
}
|
||
|
||
static LSPAny ToLSPAny(unsigned long long value)
|
||
{
|
||
return LSPAny(value);
|
||
}
|
||
|
||
// 浮点类型
|
||
static LSPAny ToLSPAny(float value)
|
||
{
|
||
return LSPAny(value);
|
||
}
|
||
|
||
static LSPAny ToLSPAny(double value)
|
||
{
|
||
return LSPAny(value);
|
||
}
|
||
|
||
static LSPAny ToLSPAny(long double value)
|
||
{
|
||
return LSPAny(value);
|
||
}
|
||
|
||
// string
|
||
static LSPAny ToLSPAny(const string& str)
|
||
{
|
||
return LSPAny(str);
|
||
}
|
||
|
||
static LSPAny ToLSPAny(const char* str)
|
||
{
|
||
return LSPAny(str);
|
||
}
|
||
|
||
// nullptr
|
||
static LSPAny ToLSPAny(std::nullptr_t)
|
||
{
|
||
return LSPAny(nullptr);
|
||
}
|
||
|
||
// LSPAny 自身
|
||
static LSPAny ToLSPAny(const LSPAny& any)
|
||
{
|
||
return any;
|
||
}
|
||
|
||
// === 容器类型的转换 ===
|
||
|
||
// vector
|
||
template<typename T>
|
||
static LSPAny ToLSPAny(const std::vector<T>& vec)
|
||
{
|
||
LSPArray arr;
|
||
arr.reserve(vec.size());
|
||
for (const auto& item : vec)
|
||
{
|
||
arr.push_back(ToLSPAny(item));
|
||
}
|
||
return LSPAny(std::move(arr));
|
||
}
|
||
|
||
// map
|
||
template<typename T>
|
||
static LSPAny ToLSPAny(const std::map<string, T>& map)
|
||
{
|
||
LSPObject obj;
|
||
for (const auto& [key, value] : map)
|
||
{
|
||
obj[key] = ToLSPAny(value);
|
||
}
|
||
return LSPAny(std::move(obj));
|
||
}
|
||
|
||
// optional
|
||
template<typename T>
|
||
static LSPAny ToLSPAny(const std::optional<T>& opt)
|
||
{
|
||
if (opt.has_value())
|
||
{
|
||
return ToLSPAny(*opt);
|
||
}
|
||
return LSPAny(nullptr);
|
||
}
|
||
|
||
// === Struct 到 LSPAny 的转换(最低优先级) ===
|
||
template<typename T>
|
||
static typename std::enable_if<
|
||
!std::is_arithmetic<T>::value &&
|
||
!std::is_same<T, string>::value &&
|
||
!std::is_same<T, const char*>::value &&
|
||
!std::is_same<T, std::nullptr_t>::value &&
|
||
!std::is_same<T, LSPAny>::value,
|
||
LSPAny>::type
|
||
ToLSPAny(const T& obj)
|
||
{
|
||
// 序列化为 JSON 字符串
|
||
std::string json;
|
||
auto ec = glz::write_json(obj, json);
|
||
if (ec)
|
||
{
|
||
throw std::runtime_error("Failed to serialize to JSON");
|
||
}
|
||
|
||
// 直接解析为 LSPAny
|
||
LSPAny result;
|
||
ec = glz::read_json(result, json);
|
||
if (ec)
|
||
{
|
||
throw std::runtime_error("Failed to parse JSON to LSPAny");
|
||
}
|
||
|
||
return result;
|
||
}
|
||
|
||
// === LSPAny 到基本类型的转换 ===
|
||
|
||
// boolean
|
||
static boolean BoolFromLSPAny(const LSPAny& any)
|
||
{
|
||
if (!any.is<boolean>())
|
||
{
|
||
throw std::runtime_error("LSPAny is not a boolean");
|
||
}
|
||
return any.get<boolean>();
|
||
}
|
||
|
||
// 数字类型
|
||
template<typename T>
|
||
static typename std::enable_if<std::is_arithmetic<T>::value && !std::is_same<T, boolean>::value, T>::type
|
||
NumberFromLSPAny(const LSPAny& any)
|
||
{
|
||
if (!any.is<decimal>())
|
||
{
|
||
throw std::runtime_error("LSPAny is not a number");
|
||
}
|
||
return static_cast<T>(any.get<decimal>());
|
||
}
|
||
|
||
// string
|
||
static string StringFromLSPAny(const LSPAny& any)
|
||
{
|
||
if (!any.is<string>())
|
||
{
|
||
throw std::runtime_error("LSPAny is not a string");
|
||
}
|
||
return any.get<string>();
|
||
}
|
||
|
||
// === LSPAny 到容器类型的转换 ===
|
||
|
||
// vector
|
||
template<typename T>
|
||
static std::vector<T> VectorFromLSPAny(const LSPAny& any)
|
||
{
|
||
if (!any.is<LSPArray>())
|
||
{
|
||
throw std::runtime_error("LSPAny is not an array");
|
||
}
|
||
|
||
const auto& arr = any.get<LSPArray>();
|
||
std::vector<T> result;
|
||
result.reserve(arr.size());
|
||
for (const auto& item : arr)
|
||
{
|
||
result.push_back(FromLSPAny<T>(item));
|
||
}
|
||
return result;
|
||
}
|
||
|
||
// optional
|
||
template<typename T>
|
||
static std::optional<T> OptionalFromLSPAny(const LSPAny& any)
|
||
{
|
||
if (any.is<std::nullptr_t>())
|
||
{
|
||
return std::nullopt;
|
||
}
|
||
return FromLSPAny<T>(any);
|
||
}
|
||
|
||
// === LSPAny 到 Struct 的转换 ===
|
||
template<typename T>
|
||
static T FromLSPAny(const LSPAny& any)
|
||
{
|
||
return FromLSPAnyImpl<T>(any);
|
||
}
|
||
|
||
private:
|
||
// 内部实现,使用重载来处理不同类型
|
||
|
||
// boolean
|
||
static boolean FromLSPAnyImpl(const LSPAny& any, boolean*)
|
||
{
|
||
return BoolFromLSPAny(any);
|
||
}
|
||
|
||
// string
|
||
static string FromLSPAnyImpl(const LSPAny& any, string*)
|
||
{
|
||
return StringFromLSPAny(any);
|
||
}
|
||
|
||
// 数字类型
|
||
template<typename T>
|
||
static typename std::enable_if<std::is_arithmetic<T>::value && !std::is_same<T, boolean>::value, T>::type
|
||
FromLSPAnyImpl(const LSPAny& any, T*)
|
||
{
|
||
return NumberFromLSPAny<T>(any);
|
||
}
|
||
|
||
// LSPAny 自身
|
||
static LSPAny FromLSPAnyImpl(const LSPAny& any, LSPAny*)
|
||
{
|
||
return any;
|
||
}
|
||
|
||
// struct 类型
|
||
template<typename T>
|
||
static typename std::enable_if<
|
||
!std::is_arithmetic<T>::value &&
|
||
!std::is_same<T, string>::value &&
|
||
!std::is_same<T, LSPAny>::value,
|
||
T>::type
|
||
FromLSPAnyImpl(const LSPAny& any, T*)
|
||
{
|
||
// 序列化 LSPAny 为 JSON
|
||
std::string json;
|
||
auto ec = glz::write_json(any.value, json);
|
||
if (ec)
|
||
{
|
||
throw std::runtime_error("Failed to serialize LSPAny to JSON");
|
||
}
|
||
|
||
// 解析 JSON 到目标类型
|
||
T result;
|
||
ec = glz::read_json(result, json);
|
||
if (ec)
|
||
{
|
||
throw std::runtime_error("Failed to parse JSON to target type");
|
||
}
|
||
|
||
return result;
|
||
}
|
||
|
||
// 通过指针类型来分派
|
||
template<typename T>
|
||
static T FromLSPAnyImpl(const LSPAny& any)
|
||
{
|
||
return FromLSPAnyImpl(any, static_cast<T*>(nullptr));
|
||
}
|
||
};
|
||
|
||
// ===== 便利函数(可选) =====
|
||
|
||
// 基本类型的便利函数
|
||
inline LSPAny ToLSPAny(boolean value) { return LSPConvert::ToLSPAny(value); }
|
||
inline LSPAny ToLSPAny(int value) { return LSPConvert::ToLSPAny(value); }
|
||
inline LSPAny ToLSPAny(long value) { return LSPConvert::ToLSPAny(value); }
|
||
inline LSPAny ToLSPAny(long long value) { return LSPConvert::ToLSPAny(value); }
|
||
inline LSPAny ToLSPAny(unsigned int value) { return LSPConvert::ToLSPAny(value); }
|
||
inline LSPAny ToLSPAny(unsigned long value) { return LSPConvert::ToLSPAny(value); }
|
||
inline LSPAny ToLSPAny(unsigned long long value) { return LSPConvert::ToLSPAny(value); }
|
||
inline LSPAny ToLSPAny(float value) { return LSPConvert::ToLSPAny(value); }
|
||
inline LSPAny ToLSPAny(double value) { return LSPConvert::ToLSPAny(value); }
|
||
inline LSPAny ToLSPAny(long double value) { return LSPConvert::ToLSPAny(value); }
|
||
inline LSPAny ToLSPAny(const string& str) { return LSPConvert::ToLSPAny(str); }
|
||
inline LSPAny ToLSPAny(const char* str) { return LSPConvert::ToLSPAny(str); }
|
||
inline LSPAny ToLSPAny(std::nullptr_t) { return LSPConvert::ToLSPAny(nullptr); }
|
||
inline LSPAny ToLSPAny(const LSPAny& any) { return LSPConvert::ToLSPAny(any); }
|
||
|
||
// 容器类型的便利函数
|
||
template<typename T>
|
||
LSPAny ToLSPAny(const std::vector<T>& vec)
|
||
{
|
||
return LSPConvert::ToLSPAny(vec);
|
||
}
|
||
|
||
template<typename T>
|
||
LSPAny ToLSPAny(const std::map<string, T>& map)
|
||
{
|
||
return LSPConvert::ToLSPAny(map);
|
||
}
|
||
|
||
template<typename T>
|
||
LSPAny ToLSPAny(const std::optional<T>& opt)
|
||
{
|
||
return LSPConvert::ToLSPAny(opt);
|
||
}
|
||
|
||
// struct 类型的便利函数
|
||
template<typename T>
|
||
typename std::enable_if<
|
||
!std::is_arithmetic<T>::value &&
|
||
!std::is_same<T, string>::value &&
|
||
!std::is_same<T, const char*>::value &&
|
||
!std::is_same<T, std::nullptr_t>::value &&
|
||
!std::is_same<T, LSPAny>::value,
|
||
LSPAny>::type
|
||
ToLSPAny(const T& value)
|
||
{
|
||
return LSPConvert::ToLSPAny(value);
|
||
}
|
||
|
||
// FromLSPAny 便利函数
|
||
template<typename T>
|
||
T FromLSPAny(const LSPAny& any)
|
||
{
|
||
return LSPConvert::FromLSPAny<T>(any);
|
||
}
|
||
|
||
// ===== 测试代码 =====
|
||
|
||
// 测试用的结构体
|
||
struct Message
|
||
{
|
||
string jsonrpc = "2.0";
|
||
string method;
|
||
int id = 0;
|
||
};
|
||
|
||
struct Position
|
||
{
|
||
int line;
|
||
int character;
|
||
};
|
||
|
||
struct Range
|
||
{
|
||
Position start;
|
||
Position end;
|
||
};
|
||
|
||
struct TextDocumentIdentifier
|
||
{
|
||
string uri;
|
||
};
|
||
|
||
struct TextDocumentPositionParams
|
||
{
|
||
TextDocumentIdentifier textDocument;
|
||
Position position;
|
||
};
|
||
|
||
struct CompletionItem
|
||
{
|
||
string label;
|
||
std::optional<int> kind;
|
||
std::optional<string> detail;
|
||
std::optional<string> documentation;
|
||
std::optional<boolean> deprecated;
|
||
std::optional<boolean> preselect;
|
||
std::optional<string> sortText;
|
||
std::optional<string> filterText;
|
||
std::optional<string> insertText;
|
||
};
|
||
|
||
// 为测试结构体提供 glaze 元数据
|
||
template<>
|
||
struct glz::meta<Message>
|
||
{
|
||
using T = Message;
|
||
static constexpr auto value = object(
|
||
"jsonrpc",
|
||
&T::jsonrpc,
|
||
"method",
|
||
&T::method,
|
||
"id",
|
||
&T::id);
|
||
};
|
||
|
||
template<>
|
||
struct glz::meta<Position>
|
||
{
|
||
using T = Position;
|
||
static constexpr auto value = object(
|
||
"line",
|
||
&T::line,
|
||
"character",
|
||
&T::character);
|
||
};
|
||
|
||
template<>
|
||
struct glz::meta<Range>
|
||
{
|
||
using T = Range;
|
||
static constexpr auto value = object(
|
||
"start",
|
||
&T::start,
|
||
"end",
|
||
&T::end);
|
||
};
|
||
|
||
template<>
|
||
struct glz::meta<TextDocumentIdentifier>
|
||
{
|
||
using T = TextDocumentIdentifier;
|
||
static constexpr auto value = object(
|
||
"uri",
|
||
&T::uri);
|
||
};
|
||
|
||
template<>
|
||
struct glz::meta<TextDocumentPositionParams>
|
||
{
|
||
using T = TextDocumentPositionParams;
|
||
static constexpr auto value = object(
|
||
"textDocument",
|
||
&T::textDocument,
|
||
"position",
|
||
&T::position);
|
||
};
|
||
|
||
template<>
|
||
struct glz::meta<CompletionItem>
|
||
{
|
||
using T = CompletionItem;
|
||
static constexpr auto value = object(
|
||
"label",
|
||
&T::label,
|
||
"kind",
|
||
&T::kind,
|
||
"detail",
|
||
&T::detail,
|
||
"documentation",
|
||
&T::documentation,
|
||
"deprecated",
|
||
&T::deprecated,
|
||
"preselect",
|
||
&T::preselect,
|
||
"sortText",
|
||
&T::sortText,
|
||
"filterText",
|
||
&T::filterText,
|
||
"insertText",
|
||
&T::insertText);
|
||
};
|
||
|
||
// 测试函数
|
||
#include <iostream>
|
||
|
||
void test_basic_conversion()
|
||
{
|
||
std::cout << "=== Testing Basic Conversion ===" << std::endl;
|
||
|
||
// 测试 struct 转换
|
||
Message msg;
|
||
msg.method = "textDocument/completion";
|
||
msg.id = 42;
|
||
|
||
// Struct -> LSPAny
|
||
LSPAny any = ToLSPAny(msg);
|
||
|
||
// 序列化查看
|
||
std::string json;
|
||
glz::write_json(any, json);
|
||
std::cout << "Message as JSON: " << json << std::endl;
|
||
|
||
// LSPAny -> Struct
|
||
Message restored = FromLSPAny<Message>(any);
|
||
std::cout << "Restored method: " << restored.method << std::endl;
|
||
std::cout << "Restored id: " << restored.id << std::endl;
|
||
}
|
||
|
||
void test_vector_conversion()
|
||
{
|
||
std::cout << "\n=== Testing Vector Conversion ===" << std::endl;
|
||
|
||
std::vector<Position> positions = {
|
||
{ 10, 5 },
|
||
{ 20, 15 },
|
||
{ 30, 25 }
|
||
};
|
||
|
||
// Vector -> LSPAny
|
||
LSPAny any = ToLSPAny(positions);
|
||
|
||
std::string json;
|
||
glz::write_json(any, json);
|
||
std::cout << "Vector as JSON: " << json << std::endl;
|
||
|
||
// LSPAny -> Vector
|
||
auto restored = LSPConvert::VectorFromLSPAny<Position>(any);
|
||
std::cout << "Restored " << restored.size() << " positions" << std::endl;
|
||
}
|
||
|
||
void test_optional_conversion()
|
||
{
|
||
std::cout << "\n=== Testing Optional Conversion ===" << std::endl;
|
||
|
||
CompletionItem item;
|
||
item.label = "std::vector";
|
||
item.kind = 1;
|
||
item.detail = "template<typename T> class vector";
|
||
|
||
LSPAny any = ToLSPAny(item);
|
||
|
||
std::string json;
|
||
glz::write_json(any, json);
|
||
std::cout << "CompletionItem as JSON: " << json << std::endl;
|
||
|
||
// 测试 null optional
|
||
std::optional<string> empty_opt;
|
||
LSPAny null_any = ToLSPAny(empty_opt);
|
||
glz::write_json(null_any, json);
|
||
std::cout << "Empty optional as JSON: " << json << std::endl;
|
||
}
|
||
|
||
void test_mixed_usage()
|
||
{
|
||
std::cout << "\n=== Testing Mixed Usage ===" << std::endl;
|
||
|
||
// 创建复杂对象
|
||
LSPObject obj;
|
||
obj["message"] = ToLSPAny(Message{ "2.0", "test/method", 123 });
|
||
obj["position"] = ToLSPAny(Position{ 10, 20 });
|
||
obj["numbers"] = ToLSPAny(std::vector<int>{ 1, 2, 3 });
|
||
obj["flag"] = LSPAny(true);
|
||
obj["value"] = LSPAny(3.14);
|
||
obj["text"] = LSPAny("Hello LSP");
|
||
obj["empty"] = LSPAny(nullptr);
|
||
|
||
LSPAny root(obj);
|
||
|
||
std::string json;
|
||
glz::write_json(root, json);
|
||
std::cout << "Complex object: " << json << std::endl;
|
||
|
||
// 提取值
|
||
if (root.is<LSPObject>())
|
||
{
|
||
auto& root_obj = root.get<LSPObject>();
|
||
|
||
Message msg = FromLSPAny<Message>(root_obj["message"]);
|
||
std::cout << "Extracted message method: " << msg.method << std::endl;
|
||
|
||
Position pos = FromLSPAny<Position>(root_obj["position"]);
|
||
std::cout << "Extracted position: " << pos.line << ", " << pos.character << std::endl;
|
||
}
|
||
}
|
||
|
||
int main()
|
||
{
|
||
try
|
||
{
|
||
test_basic_conversion();
|
||
test_vector_conversion();
|
||
test_optional_conversion();
|
||
test_mixed_usage();
|
||
|
||
std::cout << "\nAll tests completed!" << std::endl;
|
||
}
|
||
catch (const std::exception& e)
|
||
{
|
||
std::cout << "Exception: " << e.what() << std::endl;
|
||
return 1;
|
||
}
|
||
|
||
return 0;
|
||
}
|