♻️ 重构优化LSPAny相关代码
This commit is contained in:
parent
c690b76fcf
commit
a81d9de71d
|
|
@ -1,8 +1,10 @@
|
|||
#pragma once
|
||||
#include <cstdint>
|
||||
#include <limits>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <type_traits>
|
||||
#include <variant>
|
||||
#include <vector>
|
||||
|
||||
|
|
@ -16,6 +18,7 @@ namespace lsp::protocol
|
|||
using string = std::string;
|
||||
|
||||
// LSPAny 这样设计是为了glaz序列化
|
||||
// export type LSPAny = LSPObject | LSPArray | string | integer | uinteger | decimal | boolean | null;
|
||||
struct LSPAny;
|
||||
using LSPObject = std::map<string, LSPAny>;
|
||||
using LSPArray = std::vector<LSPAny>;
|
||||
|
|
@ -26,7 +29,9 @@ namespace lsp::protocol
|
|||
LSPObject,
|
||||
LSPArray,
|
||||
string,
|
||||
decimal, // 放在前面,优先匹配数字
|
||||
integer,
|
||||
uinteger,
|
||||
decimal,
|
||||
boolean,
|
||||
std::nullptr_t>;
|
||||
|
||||
|
|
@ -34,69 +39,74 @@ namespace lsp::protocol
|
|||
|
||||
// 默认构造函数
|
||||
LSPAny();
|
||||
|
||||
// 拷贝和移动构造函数
|
||||
LSPAny(const LSPAny& other);
|
||||
LSPAny(LSPAny&& other) noexcept;
|
||||
// 针对每种支持的类型的构造函数
|
||||
LSPAny(const std::map<string, LSPAny>& val);
|
||||
LSPAny(std::map<string, LSPAny>&& val);
|
||||
LSPAny(const std::vector<LSPAny>& val);
|
||||
LSPAny(std::vector<LSPAny>&& val);
|
||||
|
||||
// 容器类型的构造函数
|
||||
LSPAny(const LSPObject& val);
|
||||
LSPAny(LSPObject&& val);
|
||||
LSPAny(const LSPArray& val);
|
||||
LSPAny(LSPArray&& val);
|
||||
|
||||
// 字符串类型的构造函数
|
||||
LSPAny(const string& val);
|
||||
LSPAny(string&& val);
|
||||
LSPAny(const char* val);
|
||||
|
||||
// 所有数字类型都转换为 decimal
|
||||
LSPAny(int val);
|
||||
LSPAny(long val);
|
||||
LSPAny(long long val);
|
||||
LSPAny(unsigned int val);
|
||||
LSPAny(unsigned long val);
|
||||
LSPAny(unsigned long long val);
|
||||
// 浮点类型的构造函数 -- decimal
|
||||
LSPAny(float val);
|
||||
LSPAny(double val);
|
||||
LSPAny(long double val);
|
||||
|
||||
// 布尔和空值
|
||||
LSPAny(boolean val);
|
||||
LSPAny(std::nullptr_t);
|
||||
|
||||
// 单个模板处理所有整数类型
|
||||
template<typename T, typename = std::enable_if_t<std::is_integral_v<T> && !std::is_same_v<T, bool> && !std::is_same_v<std::decay_t<T>, char>>>
|
||||
LSPAny(T val);
|
||||
|
||||
// 赋值操作符
|
||||
LSPAny& operator=(const LSPAny& other);
|
||||
LSPAny& operator=(LSPAny&& other) noexcept;
|
||||
LSPAny& operator=(const std::map<string, LSPAny>& val);
|
||||
LSPAny& operator=(std::map<string, LSPAny>&& val);
|
||||
LSPAny& operator=(const std::vector<LSPAny>& val);
|
||||
LSPAny& operator=(std::vector<LSPAny>&& val);
|
||||
LSPAny& operator=(const LSPObject& val);
|
||||
LSPAny& operator=(LSPObject&& val);
|
||||
LSPAny& operator=(const LSPArray& val);
|
||||
LSPAny& operator=(LSPArray&& val);
|
||||
|
||||
LSPAny& operator=(const string& val);
|
||||
LSPAny& operator=(string&& val);
|
||||
LSPAny& operator=(const char* val);
|
||||
LSPAny& operator=(int val);
|
||||
LSPAny& operator=(long val);
|
||||
LSPAny& operator=(long long val);
|
||||
LSPAny& operator=(unsigned int val);
|
||||
LSPAny& operator=(unsigned long val);
|
||||
LSPAny& operator=(unsigned long long val);
|
||||
|
||||
LSPAny& operator=(float val);
|
||||
LSPAny& operator=(double val);
|
||||
LSPAny& operator=(long double val);
|
||||
|
||||
LSPAny& operator=(boolean val);
|
||||
LSPAny& operator=(std::nullptr_t);
|
||||
|
||||
// 整数类型赋值 - 使用模板避免类型冲突
|
||||
template<typename T, typename = std::enable_if_t<std::is_integral_v<T> && !std::is_same_v<T, bool> && !std::is_same_v<std::decay_t<T>, char>>>
|
||||
LSPAny& operator=(T val);
|
||||
|
||||
// 类型检查辅助函数
|
||||
template<typename T>
|
||||
bool is() const;
|
||||
bool Is() const;
|
||||
|
||||
template<typename T>
|
||||
T& get();
|
||||
T& Get();
|
||||
|
||||
template<typename T>
|
||||
const T& get() const;
|
||||
const T& Get() const;
|
||||
|
||||
// 访问操作符
|
||||
template<typename Visitor>
|
||||
auto visit(Visitor&& visitor) const;
|
||||
auto Visit(Visitor&& visitor) const;
|
||||
|
||||
template<typename Visitor>
|
||||
auto visit(Visitor&& visitor);
|
||||
auto Visit(Visitor&& visitor);
|
||||
};
|
||||
|
||||
using ProgressToken = std::variant<integer, string>;
|
||||
|
|
@ -227,33 +237,75 @@ namespace lsp::protocol
|
|||
};
|
||||
|
||||
// LSP模板方法
|
||||
template<typename T, typename>
|
||||
LSPAny::LSPAny(T val)
|
||||
{
|
||||
if constexpr (std::is_signed_v<T>)
|
||||
{
|
||||
// 有符号整数
|
||||
if (val >= std::numeric_limits<integer>::min() && val <= std::numeric_limits<integer>::max())
|
||||
value = static_cast<integer>(val);
|
||||
else
|
||||
value = static_cast<decimal>(val); // 超出 int32 范围,转为 decimal(可能丢失精度)
|
||||
}
|
||||
else
|
||||
{
|
||||
// 无符号整数
|
||||
if (val <= std::numeric_limits<uinteger>::max())
|
||||
value = static_cast<uinteger>(val);
|
||||
else
|
||||
value = static_cast<decimal>(val); // 超出 uint32 范围,转为 decimal(可能丢失精度)
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T, typename>
|
||||
LSPAny& LSPAny::operator=(T val)
|
||||
{
|
||||
if constexpr (std::is_signed_v<T>)
|
||||
{
|
||||
// 有符号整数
|
||||
if (val >= std::numeric_limits<integer>::min() && val <= std::numeric_limits<integer>::max())
|
||||
value = static_cast<integer>(val);
|
||||
else
|
||||
value = static_cast<decimal>(val);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (val <= std::numeric_limits<uinteger>::max())
|
||||
value = static_cast<uinteger>(val);
|
||||
else
|
||||
value = static_cast<decimal>(val);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool LSPAny::is() const
|
||||
bool LSPAny::Is() const
|
||||
{
|
||||
return std::holds_alternative<T>(value);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T& LSPAny::get()
|
||||
T& LSPAny::Get()
|
||||
{
|
||||
return std::get<T>(value);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
const T& LSPAny::get() const
|
||||
const T& LSPAny::Get() const
|
||||
{
|
||||
return std::get<T>(value);
|
||||
}
|
||||
|
||||
// 访问操作符
|
||||
template<typename Visitor>
|
||||
auto LSPAny::visit(Visitor&& visitor) const
|
||||
auto LSPAny::Visit(Visitor&& visitor) const
|
||||
{
|
||||
return std::visit(std::forward<Visitor>(visitor), value);
|
||||
}
|
||||
|
||||
template<typename Visitor>
|
||||
auto LSPAny::visit(Visitor&& visitor)
|
||||
auto LSPAny::Visit(Visitor&& visitor)
|
||||
{
|
||||
return std::visit(std::forward<Visitor>(visitor), value);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
#pragma once
|
||||
#include "./basic_types.hpp"
|
||||
// #include "./basic_types.hpp"
|
||||
|
||||
namespace lsp::protocol
|
||||
{
|
||||
|
|
@ -13,16 +13,16 @@ namespace lsp::protocol
|
|||
inline LSPAny::LSPAny(LSPAny&& other) noexcept :
|
||||
value(std::move(other.value)) {}
|
||||
|
||||
inline LSPAny::LSPAny(const std::map<string, LSPAny>& val) :
|
||||
inline LSPAny::LSPAny(const LSPObject& val) :
|
||||
value(val) {}
|
||||
|
||||
inline LSPAny::LSPAny(std::map<string, LSPAny>&& val) :
|
||||
inline LSPAny::LSPAny(LSPObject&& val) :
|
||||
value(std::move(val)) {}
|
||||
|
||||
inline LSPAny::LSPAny(const std::vector<LSPAny>& val) :
|
||||
inline LSPAny::LSPAny(const LSPArray& val) :
|
||||
value(val) {}
|
||||
|
||||
inline LSPAny::LSPAny(std::vector<LSPAny>&& val) :
|
||||
inline LSPAny::LSPAny(LSPArray&& val) :
|
||||
value(std::move(val)) {}
|
||||
|
||||
inline LSPAny::LSPAny(const string& val) :
|
||||
|
|
@ -34,24 +34,6 @@ namespace lsp::protocol
|
|||
inline LSPAny::LSPAny(const char* val) :
|
||||
value(string(val)) {}
|
||||
|
||||
inline LSPAny::LSPAny(int val) :
|
||||
value(static_cast<decimal>(val)) {}
|
||||
|
||||
inline LSPAny::LSPAny(long val) :
|
||||
value(static_cast<decimal>(val)) {}
|
||||
|
||||
inline LSPAny::LSPAny(long long val) :
|
||||
value(static_cast<decimal>(val)) {}
|
||||
|
||||
inline LSPAny::LSPAny(unsigned int val) :
|
||||
value(static_cast<decimal>(val)) {}
|
||||
|
||||
inline LSPAny::LSPAny(unsigned long val) :
|
||||
value(static_cast<decimal>(val)) {}
|
||||
|
||||
inline LSPAny::LSPAny(unsigned long long val) :
|
||||
value(static_cast<decimal>(val)) {}
|
||||
|
||||
inline LSPAny::LSPAny(float val) :
|
||||
value(static_cast<decimal>(val)) {}
|
||||
|
||||
|
|
@ -80,26 +62,25 @@ namespace lsp::protocol
|
|||
return *this;
|
||||
}
|
||||
|
||||
// 针对每种支持的类型的赋值操作符
|
||||
inline LSPAny& LSPAny::operator=(const std::map<string, LSPAny>& val)
|
||||
inline LSPAny& LSPAny::operator=(const LSPObject& val)
|
||||
{
|
||||
value = val;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline LSPAny& LSPAny::operator=(std::map<string, LSPAny>&& val)
|
||||
inline LSPAny& LSPAny::operator=(LSPObject&& val)
|
||||
{
|
||||
value = std::move(val);
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline LSPAny& LSPAny::operator=(const std::vector<LSPAny>& val)
|
||||
inline LSPAny& LSPAny::operator=(const LSPArray& val)
|
||||
{
|
||||
value = val;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline LSPAny& LSPAny::operator=(std::vector<LSPAny>&& val)
|
||||
inline LSPAny& LSPAny::operator=(LSPArray&& val)
|
||||
{
|
||||
value = std::move(val);
|
||||
return *this;
|
||||
|
|
@ -123,43 +104,6 @@ namespace lsp::protocol
|
|||
return *this;
|
||||
}
|
||||
|
||||
// 所有数字类型都转换为 decimal
|
||||
inline LSPAny& LSPAny::operator=(int val)
|
||||
{
|
||||
value = static_cast<decimal>(val);
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline LSPAny& LSPAny::operator=(long val)
|
||||
{
|
||||
value = static_cast<decimal>(val);
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline LSPAny& LSPAny::operator=(long long val)
|
||||
{
|
||||
value = static_cast<decimal>(val);
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline LSPAny& LSPAny::operator=(unsigned int val)
|
||||
{
|
||||
value = static_cast<decimal>(val);
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline LSPAny& LSPAny::operator=(unsigned long val)
|
||||
{
|
||||
value = static_cast<decimal>(val);
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline LSPAny& LSPAny::operator=(unsigned long long val)
|
||||
{
|
||||
value = static_cast<decimal>(val);
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline LSPAny& LSPAny::operator=(float val)
|
||||
{
|
||||
value = static_cast<decimal>(val);
|
||||
|
|
|
|||
|
|
@ -1,40 +1,105 @@
|
|||
#pragma once
|
||||
#include <type_traits>
|
||||
#include <stdexcept>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <optional>
|
||||
#include <variant>
|
||||
#include "../detail/basic_types.hpp"
|
||||
|
||||
namespace lsp::transform
|
||||
{
|
||||
// 通用错误类
|
||||
/// 转换错误异常类
|
||||
class ConversionError : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
explicit ConversionError(const std::string& message)
|
||||
: std::runtime_error("LSP Conversion Error: " + message) {}
|
||||
explicit ConversionError(const std::string& message) : std::runtime_error("LSP Conversion Error: " + message) {}
|
||||
};
|
||||
|
||||
/// 类型特征:LSP 基本类型判断
|
||||
template<typename T>
|
||||
inline constexpr bool is_lsp_basic_type_v =
|
||||
std::is_same_v<T, protocol::integer> ||
|
||||
std::is_same_v<T, protocol::uinteger> ||
|
||||
std::is_same_v<T, protocol::decimal> ||
|
||||
std::is_same_v<T, protocol::boolean> ||
|
||||
std::is_same_v<T, protocol::string> ||
|
||||
std::is_same_v<T, std::nullptr_t>;
|
||||
|
||||
/// 类型特征:LSP 容器类型判断
|
||||
template<typename T>
|
||||
inline constexpr bool is_lsp_container_type_v =
|
||||
std::is_same_v<T, protocol::LSPObject> ||
|
||||
std::is_same_v<T, protocol::LSPArray> ||
|
||||
std::is_same_v<T, protocol::LSPAny>;
|
||||
|
||||
/// 类型特征:检测 vector
|
||||
template<typename T>
|
||||
struct is_vector : std::false_type
|
||||
{
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct is_lsp_basic_type: std::false_type {};
|
||||
|
||||
template<> struct is_lsp_basic_type<protocol::boolean> : std::true_type {};
|
||||
template<> struct is_lsp_basic_type<protocol::string> : std::true_type {};
|
||||
template<> struct is_lsp_basic_type<protocol::decimal> : std::true_type {};
|
||||
template<> struct is_lsp_basic_type<std::nullptr_t> : std::true_type {};
|
||||
struct is_vector<std::vector<T>> : std::true_type
|
||||
{
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct is_lsp_container_type : std::false_type {};
|
||||
inline constexpr bool is_vector_v = is_vector<T>::value;
|
||||
|
||||
template<> struct is_lsp_container_type<protocol::LSPObject> : std::true_type {};
|
||||
template<> struct is_lsp_container_type<protocol::LSPArray> : std::true_type {};
|
||||
template<> struct is_lsp_container_type<protocol::LSPAny> : std::true_type {};
|
||||
|
||||
// struct类型判断
|
||||
/// 类型特征:检测 map
|
||||
template<typename T>
|
||||
struct is_user_struct : std::integral_constant<bool,
|
||||
!std::is_arithmetic<T>::value &&
|
||||
!std::is_same<T, protocol::string>::value &&
|
||||
!std::is_same<T, const char*>::value &&
|
||||
!std::is_same<T, std::nullptr_t>::value &&
|
||||
!is_lsp_basic_type<T>::value &&
|
||||
!is_lsp_container_type<T>::value> {};
|
||||
struct is_map : std::false_type
|
||||
{
|
||||
};
|
||||
|
||||
template<typename K, typename V>
|
||||
struct is_map<std::map<K, V>> : std::true_type
|
||||
{
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
inline constexpr bool is_map_v = is_map<T>::value;
|
||||
|
||||
/// 类型特征:检测 optional
|
||||
template<typename T>
|
||||
struct is_optional : std::false_type
|
||||
{
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct is_optional<std::optional<T>> : std::true_type
|
||||
{
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
inline constexpr bool is_optional_v = is_optional<T>::value;
|
||||
|
||||
/// 类型特征:检测 variant
|
||||
template<typename T>
|
||||
struct is_variant : std::false_type
|
||||
{
|
||||
};
|
||||
|
||||
template<typename... Ts>
|
||||
struct is_variant<std::variant<Ts...>> : std::true_type
|
||||
{
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
inline constexpr bool is_variant_v = is_variant<T>::value;
|
||||
|
||||
/// 类型特征:用户自定义 struct 判断
|
||||
template<typename T>
|
||||
inline constexpr bool is_user_struct_v =
|
||||
std::is_class_v<T> &&
|
||||
!std::is_pointer_v<T> &&
|
||||
!std::is_same_v<T, protocol::string> &&
|
||||
!std::is_same_v<T, std::string> &&
|
||||
!is_lsp_basic_type_v<T> &&
|
||||
!is_lsp_container_type_v<T> &&
|
||||
!is_vector_v<T> &&
|
||||
!is_map_v<T> &&
|
||||
!is_optional_v<T> &&
|
||||
!is_variant_v<T>;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,106 +3,68 @@
|
|||
|
||||
namespace lsp::transform
|
||||
{
|
||||
// ==================== JSON 序列化/反序列化 ====================
|
||||
|
||||
// ===== 全局便利函数 =====
|
||||
template<typename T>
|
||||
std::optional<T> Deserialize(const std::string& json);
|
||||
|
||||
template<typename T>
|
||||
std::optional<std::string> Serialize(const T& obj);
|
||||
|
||||
// 基本类型
|
||||
template<typename T>
|
||||
protocol::LSPAny LSPAny(const T& obj);
|
||||
// ==================== 转换为 LSPAny ====================
|
||||
|
||||
// // struct 类型
|
||||
// template<typename T>
|
||||
// typename std::enable_if<is_user_struct<T>::value, protocol::LSPAny>::type LSPAny(const T& value);
|
||||
/// 任意类型转换为 LSPAny
|
||||
///
|
||||
/// 支持的类型:
|
||||
/// - 基本类型:bool, int, double, string, nullptr
|
||||
/// - 容器类型:vector, map, optional
|
||||
/// - LSP 类型:LSPObject, LSPArray, LSPAny
|
||||
/// - 用户结构体(需要 glaze 支持)
|
||||
inline constexpr auto ToLSPAny = [](const auto& value) {
|
||||
return LSPAnyConverter::ToLSPAny(value);
|
||||
};
|
||||
|
||||
// 容器类型
|
||||
template<typename T>
|
||||
protocol::LSPAny LSPAny(const std::vector<T>& vec);
|
||||
/// LSPAny 转换为指定类型
|
||||
///
|
||||
/// 支持的类型:
|
||||
/// - 基本类型:bool, int, double, string
|
||||
/// - 容器类型:vector<T>, optional<T>
|
||||
/// - LSP 类型:LSPObject, LSPArray
|
||||
/// - 用户结构体(需要 glaze 支持)
|
||||
inline constexpr auto FromLSPAny = []<typename T>(const protocol::LSPAny& any) -> T {
|
||||
return LSPAnyConverter::FromLSPAny<T>(any);
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
protocol::LSPAny LSPAny(const std::map<protocol::string, T>& map);
|
||||
|
||||
template<typename T>
|
||||
protocol::LSPAny LSPAny(const std::optional<T>& opt);
|
||||
|
||||
template<typename T>
|
||||
T As(const protocol::LSPAny& any);
|
||||
|
||||
template<typename T, typename From>
|
||||
std::optional<T> As(const std::optional<From>& opt);
|
||||
|
||||
template<typename T, typename... Ts>
|
||||
T As(const std::variant<Ts...>& var);
|
||||
|
||||
template<typename T>
|
||||
T As(const protocol::LSPObject& obj);
|
||||
|
||||
template<typename T>
|
||||
T As(const protocol::LSPArray& arr);
|
||||
|
||||
template<typename T>
|
||||
T Number(const protocol::LSPAny& any);
|
||||
|
||||
template<typename T>
|
||||
std::vector<T> Vector(const protocol::LSPAny& any);
|
||||
|
||||
template<typename T>
|
||||
std::optional<T> Optional(const protocol::LSPAny& any);
|
||||
|
||||
template<typename T>
|
||||
protocol::LSPObject LSPObject(const T& obj);
|
||||
|
||||
template<typename T>
|
||||
protocol::LSPArray LSPArray(const T& vec);
|
||||
|
||||
protocol::string String(const protocol::LSPAny& any);
|
||||
protocol::boolean Bool(const protocol::LSPAny& any);
|
||||
|
||||
// === 外观接口:类型检查 ===
|
||||
namespace check
|
||||
{
|
||||
inline bool IsObject(const protocol::LSPAny& any) { return any.is<protocol::LSPObject>(); }
|
||||
inline bool IsArray(const protocol::LSPAny& any) { return any.is<protocol::LSPArray>(); }
|
||||
inline bool IsString(const protocol::LSPAny& any) { return any.is<protocol::string>(); }
|
||||
inline bool IsNumber(const protocol::LSPAny& any) { return any.is<protocol::decimal>(); }
|
||||
inline bool IsBool(const protocol::LSPAny& any) { return any.is<protocol::boolean>(); }
|
||||
inline bool IsNull(const protocol::LSPAny& any) { return any.is<std::nullptr_t>(); }
|
||||
/// 检查是否为 LSPObject
|
||||
bool IsObject(const protocol::LSPAny& any);
|
||||
|
||||
/// 检查是否为 LSPArray
|
||||
bool IsArray(const protocol::LSPAny& any);
|
||||
|
||||
/// 检查是否为字符串
|
||||
bool IsString(const protocol::LSPAny& any);
|
||||
|
||||
/// 检查是否为数字(integer/uinteger/decimal)
|
||||
bool IsNumber(const protocol::LSPAny& any);
|
||||
|
||||
/// 检查是否为布尔值
|
||||
bool IsBool(const protocol::LSPAny& any);
|
||||
|
||||
/// 检查是否为 null
|
||||
bool IsNull(const protocol::LSPAny& any);
|
||||
}
|
||||
|
||||
// === 外观接口:调试功能 ===
|
||||
// ==================== 调试工具 ====================
|
||||
|
||||
namespace debug
|
||||
{
|
||||
inline std::string GetTypeName(const protocol::LSPAny& any)
|
||||
{
|
||||
if (any.is<protocol::LSPObject>())
|
||||
return "LSPObject";
|
||||
if (any.is<protocol::LSPArray>())
|
||||
return "LSPArray";
|
||||
if (any.is<protocol::string>())
|
||||
return "string";
|
||||
if (any.is<protocol::decimal>())
|
||||
return "decimal";
|
||||
if (any.is<protocol::boolean>())
|
||||
return "boolean";
|
||||
if (any.is<std::nullptr_t>())
|
||||
return "null";
|
||||
return "unknown";
|
||||
}
|
||||
/// 获取 LSPAny 的类型名称字符串
|
||||
std::string GetTypeName(const protocol::LSPAny& any);
|
||||
|
||||
inline std::string GetIdString(const std::variant<int, std::string>& id)
|
||||
{
|
||||
return std::visit([](const auto& value) -> std::string {
|
||||
if constexpr (std::is_same_v<std::decay_t<decltype(value)>, int>)
|
||||
return std::to_string(value);
|
||||
else
|
||||
return value;
|
||||
}, id);
|
||||
}
|
||||
/// 将 variant<int, string> 转换为字符串(用于 ID)
|
||||
std::string GetIdString(const std::variant<int, std::string>& id);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
#pragma once
|
||||
#include "./facade.hpp"
|
||||
// #include "./facade.hpp"
|
||||
|
||||
namespace lsp::transform
|
||||
{
|
||||
// ==================== JSON 序列化/反序列化 ====================
|
||||
|
||||
template<typename T>
|
||||
inline std::optional<T> Deserialize(const std::string& json)
|
||||
{
|
||||
|
|
@ -25,118 +27,77 @@ namespace lsp::transform
|
|||
return json;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline protocol::LSPAny LSPAny(const T& obj)
|
||||
{
|
||||
return LSPAnyConverter::ToLSPAny(obj);
|
||||
}
|
||||
// ==================== 类型检查 ====================
|
||||
|
||||
template<typename T>
|
||||
inline protocol::LSPAny LSPAny(const std::vector<T>& vec)
|
||||
namespace check
|
||||
{
|
||||
return LSPAnyConverter::ToLSPAny(vec);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline protocol::LSPAny LSPAny(const std::map<protocol::string, T>& map)
|
||||
{
|
||||
return LSPAnyConverter::ToLSPAny(map);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline protocol::LSPAny LSPAny(const std::optional<T>& opt)
|
||||
{
|
||||
return LSPAnyConverter::ToLSPAny(opt);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline T As(const protocol::LSPAny& any)
|
||||
{
|
||||
return LSPAnyConverter::FromLSPAny<T>(any);
|
||||
}
|
||||
|
||||
template<typename T, typename From>
|
||||
inline std::optional<T> As(const std::optional<From>& opt)
|
||||
{
|
||||
return LSPAnyConverter::As<T>(opt);
|
||||
}
|
||||
|
||||
template<typename T, typename... Ts>
|
||||
inline T As(const std::variant<Ts...>& var)
|
||||
{
|
||||
return LSPAnyConverter::As<T>(var);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline T As(const protocol::LSPObject& obj)
|
||||
{
|
||||
return LSPAnyConverter::As<T>(obj);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline T As(const protocol::LSPArray& arr)
|
||||
{
|
||||
return LSPAnyConverter::As<T>(arr);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline T Number(const protocol::LSPAny& any)
|
||||
{
|
||||
return LSPAnyConverter::ToNumber<T>(any);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline std::vector<T> Vector(const protocol::LSPAny& any)
|
||||
{
|
||||
return LSPAnyConverter::ToVector<T>(any);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline std::optional<T> Optional(const protocol::LSPAny& any)
|
||||
{
|
||||
return LSPAnyConverter::ToOptional<T>(any);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline protocol::LSPObject LSPObject(const T& obj)
|
||||
{
|
||||
// 如果已经是 LSPAny,直接获取其中的 LSPObject
|
||||
if constexpr (std::is_same_v<T, protocol::LSPAny>)
|
||||
inline bool IsObject(const protocol::LSPAny& any)
|
||||
{
|
||||
return LSPAnyConverter::ToLSPObject(obj);
|
||||
return any.Is<protocol::LSPObject>();
|
||||
}
|
||||
else
|
||||
|
||||
inline bool IsArray(const protocol::LSPAny& any)
|
||||
{
|
||||
// 否则先转换为 LSPAny,再获取 LSPObject
|
||||
protocol::LSPAny any = LSPAnyConverter::ToLSPAny(obj);
|
||||
return LSPAnyConverter::ToLSPObject(any);
|
||||
return any.Is<protocol::LSPArray>();
|
||||
}
|
||||
|
||||
inline bool IsString(const protocol::LSPAny& any)
|
||||
{
|
||||
return any.Is<protocol::string>();
|
||||
}
|
||||
|
||||
inline bool IsNumber(const protocol::LSPAny& any)
|
||||
{
|
||||
return any.Is<protocol::integer>() ||
|
||||
any.Is<protocol::uinteger>() ||
|
||||
any.Is<protocol::decimal>();
|
||||
}
|
||||
|
||||
inline bool IsBool(const protocol::LSPAny& any)
|
||||
{
|
||||
return any.Is<protocol::boolean>();
|
||||
}
|
||||
|
||||
inline bool IsNull(const protocol::LSPAny& any)
|
||||
{
|
||||
return any.Is<std::nullptr_t>();
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline protocol::LSPArray LSPArray(const T& container)
|
||||
// ==================== 调试工具 ====================
|
||||
|
||||
namespace debug
|
||||
{
|
||||
// 如果已经是 LSPAny,直接获取其中的 LSPArray
|
||||
if constexpr (std::is_same_v<T, protocol::LSPAny>)
|
||||
inline std::string GetTypeName(const protocol::LSPAny& any)
|
||||
{
|
||||
return LSPAnyConverter::ToLSPArray(container);
|
||||
if (any.Is<protocol::LSPObject>())
|
||||
return "LSPObject";
|
||||
if (any.Is<protocol::LSPArray>())
|
||||
return "LSPArray";
|
||||
if (any.Is<protocol::string>())
|
||||
return "string";
|
||||
if (any.Is<protocol::integer>())
|
||||
return "integer";
|
||||
if (any.Is<protocol::uinteger>())
|
||||
return "uinteger";
|
||||
if (any.Is<protocol::decimal>())
|
||||
return "decimal";
|
||||
if (any.Is<protocol::boolean>())
|
||||
return "boolean";
|
||||
if (any.Is<std::nullptr_t>())
|
||||
return "null";
|
||||
return "unknown";
|
||||
}
|
||||
else
|
||||
|
||||
inline std::string GetIdString(const std::variant<int, std::string>& id)
|
||||
{
|
||||
// 否则转换为 LSPAny
|
||||
protocol::LSPAny any = LSPAnyConverter::ToLSPAny(container);
|
||||
return LSPAnyConverter::ToLSPArray(any);
|
||||
return std::visit([](const auto& value) -> std::string {
|
||||
if constexpr (std::is_same_v<std::decay_t<decltype(value)>, int>)
|
||||
return std::to_string(value);
|
||||
else
|
||||
return value;
|
||||
},
|
||||
id);
|
||||
}
|
||||
}
|
||||
|
||||
inline protocol::string String(const protocol::LSPAny& any)
|
||||
{
|
||||
return LSPAnyConverter::ToString(any);
|
||||
}
|
||||
|
||||
inline protocol::boolean Bool(const protocol::LSPAny& any)
|
||||
{
|
||||
return LSPAnyConverter::ToBool(any);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,82 +4,40 @@
|
|||
|
||||
namespace lsp::transform
|
||||
{
|
||||
// LSPAny 序列化/反序列化工具类
|
||||
/// LSPAny 转换核心类
|
||||
/// 提供所有类型的双向转换
|
||||
class LSPAnyConverter
|
||||
{
|
||||
public:
|
||||
// === 基本类型的转换 ===
|
||||
static protocol::LSPAny ToLSPAny(protocol::boolean value);
|
||||
static protocol::LSPAny ToLSPAny(int value);
|
||||
static protocol::LSPAny ToLSPAny(long value);
|
||||
static protocol::LSPAny ToLSPAny(long long value);
|
||||
static protocol::LSPAny ToLSPAny(unsigned int value);
|
||||
static protocol::LSPAny ToLSPAny(unsigned long value);
|
||||
static protocol::LSPAny ToLSPAny(unsigned long long value);
|
||||
static protocol::LSPAny ToLSPAny(float value);
|
||||
static protocol::LSPAny ToLSPAny(double value);
|
||||
static protocol::LSPAny ToLSPAny(long double value);
|
||||
static protocol::LSPAny ToLSPAny(const protocol::string& str);
|
||||
static protocol::LSPAny ToLSPAny(const char* str);
|
||||
static protocol::LSPAny ToLSPAny(std::nullptr_t);
|
||||
static protocol::LSPAny ToLSPAny(const protocol::LSPAny& any);
|
||||
|
||||
// === LSPAny 到基本类型的转换 ===
|
||||
static protocol::boolean ToBool(const protocol::LSPAny& any);
|
||||
static protocol::string ToString(const protocol::LSPAny& any);
|
||||
|
||||
// 其他转换
|
||||
static protocol::LSPObject ToLSPObject(const protocol::LSPAny& any);
|
||||
static protocol::LSPArray ToLSPArray(const protocol::LSPAny& any);
|
||||
|
||||
// === 容器类型的转换 ===
|
||||
// ==================== 任意类型 → LSPAny ====================
|
||||
|
||||
/// 通用转换入口:任意类型 → LSPAny
|
||||
/// 根据类型特征自动分派到具体实现
|
||||
template<typename T>
|
||||
static protocol::LSPAny ToLSPAny(const std::vector<T>& vec);
|
||||
static protocol::LSPAny ToLSPAny(const T& value);
|
||||
|
||||
// ==================== LSPAny → 任意类型 ====================
|
||||
|
||||
/// 通用转换入口:LSPAny → 任意类型
|
||||
/// 根据类型特征自动分派到具体实现
|
||||
template<typename T>
|
||||
static protocol::LSPAny ToLSPAny(const std::map<protocol::string, T>& map);
|
||||
|
||||
template<typename T>
|
||||
static protocol::LSPAny ToLSPAny(const std::optional<T>& opt);
|
||||
|
||||
// === Struct 到 LSPAny 的转换 ===
|
||||
template<typename T>
|
||||
static typename std::enable_if<is_user_struct<T>::value, protocol::LSPAny>::type ToLSPAny(const T& obj);
|
||||
|
||||
template<typename T>
|
||||
static typename std::enable_if<std::is_arithmetic<T>::value && !std::is_same<T, protocol::boolean>::value, T>::type ToNumber(const protocol::LSPAny& any);
|
||||
|
||||
// === LSPAny 到容器类型的转换 ===
|
||||
template<typename T>
|
||||
static std::vector<T> ToVector(const protocol::LSPAny& any);
|
||||
|
||||
template<typename T>
|
||||
static std::optional<T> ToOptional(const protocol::LSPAny& any);
|
||||
|
||||
template<typename T>
|
||||
static typename std::enable_if<is_user_struct<T>::value, T>::type FromLSPAny(const protocol::LSPAny& any);
|
||||
|
||||
// 处理 std::optional<T>
|
||||
template<typename T, typename From>
|
||||
static std::optional<T> As(const std::optional<From>& opt);
|
||||
|
||||
// 处理 std::variant<Ts...>
|
||||
template<typename T, typename... Ts>
|
||||
static T As(const std::variant<Ts...>& var);
|
||||
|
||||
// 处理 LSPObject 和 LSPArray
|
||||
template<typename T>
|
||||
static T As(const protocol::LSPObject& obj);
|
||||
|
||||
template<typename T>
|
||||
static T As(const protocol::LSPArray& arr);
|
||||
|
||||
static T FromLSPAny(const protocol::LSPAny& any);
|
||||
|
||||
private:
|
||||
// ==================== 辅助工具 ====================
|
||||
|
||||
/// 提取数字(支持三种数字类型)
|
||||
template<typename T>
|
||||
static T FromLSPAnyImpl(const protocol::LSPAny& any);
|
||||
};
|
||||
static T ExtractNumber(const protocol::LSPAny& any);
|
||||
|
||||
/// 通过 JSON 转换用户结构体
|
||||
template<typename T>
|
||||
static T ConvertViaJson(const protocol::LSPAny& any);
|
||||
|
||||
/// 将用户结构体序列化为 LSPAny
|
||||
template<typename T>
|
||||
static protocol::LSPAny SerializeViaJson(const T& obj);
|
||||
};
|
||||
}
|
||||
|
||||
#include "./transformer.inl"
|
||||
|
|
|
|||
|
|
@ -1,249 +1,210 @@
|
|||
#pragma once
|
||||
#include "./transformer.hpp"
|
||||
|
||||
namespace lsp::transform
|
||||
{
|
||||
inline protocol::LSPAny LSPAnyConverter::ToLSPAny(protocol::boolean value)
|
||||
{
|
||||
return protocol::LSPAny(value);
|
||||
}
|
||||
|
||||
inline protocol::LSPAny LSPAnyConverter::ToLSPAny(int value)
|
||||
{
|
||||
return protocol::LSPAny(value);
|
||||
}
|
||||
|
||||
inline protocol::LSPAny LSPAnyConverter::ToLSPAny(long value)
|
||||
{
|
||||
return protocol::LSPAny(value);
|
||||
}
|
||||
|
||||
inline protocol::LSPAny LSPAnyConverter::ToLSPAny(long long value)
|
||||
{
|
||||
return protocol::LSPAny(value);
|
||||
}
|
||||
|
||||
inline protocol::LSPAny LSPAnyConverter::ToLSPAny(unsigned int value)
|
||||
{
|
||||
return protocol::LSPAny(value);
|
||||
}
|
||||
|
||||
inline protocol::LSPAny LSPAnyConverter::ToLSPAny(unsigned long value)
|
||||
{
|
||||
return protocol::LSPAny(value);
|
||||
}
|
||||
|
||||
inline protocol::LSPAny LSPAnyConverter::ToLSPAny(unsigned long long value)
|
||||
{
|
||||
return protocol::LSPAny(value);
|
||||
}
|
||||
|
||||
inline protocol::LSPAny LSPAnyConverter::ToLSPAny(float value)
|
||||
{
|
||||
return protocol::LSPAny(value);
|
||||
}
|
||||
|
||||
inline protocol::LSPAny LSPAnyConverter::ToLSPAny(double value)
|
||||
{
|
||||
return protocol::LSPAny(value);
|
||||
}
|
||||
|
||||
inline protocol::LSPAny LSPAnyConverter::ToLSPAny(long double value)
|
||||
{
|
||||
return protocol::LSPAny(value);
|
||||
}
|
||||
|
||||
inline protocol::LSPAny LSPAnyConverter::ToLSPAny(const protocol::string& str)
|
||||
{
|
||||
return protocol::LSPAny(str);
|
||||
}
|
||||
|
||||
inline protocol::LSPAny LSPAnyConverter::ToLSPAny(const char* str)
|
||||
{
|
||||
return protocol::LSPAny(str);
|
||||
}
|
||||
|
||||
inline protocol::LSPAny LSPAnyConverter::ToLSPAny(std::nullptr_t)
|
||||
{
|
||||
return protocol::LSPAny(nullptr);
|
||||
}
|
||||
|
||||
inline protocol::LSPAny LSPAnyConverter::ToLSPAny(const protocol::LSPAny& any)
|
||||
{
|
||||
return any;
|
||||
}
|
||||
|
||||
inline protocol::boolean LSPAnyConverter::ToBool(const protocol::LSPAny& any)
|
||||
{
|
||||
if (!any.is<protocol::boolean>())
|
||||
throw ConversionError("LSPAny does not contain a boolean");
|
||||
return any.get<protocol::boolean>();
|
||||
}
|
||||
|
||||
inline protocol::string LSPAnyConverter::ToString(const protocol::LSPAny& any)
|
||||
{
|
||||
if (!any.is<protocol::string>())
|
||||
throw ConversionError("LSPAny does not contain a string");
|
||||
return any.get<protocol::string>();
|
||||
}
|
||||
|
||||
inline protocol::LSPObject LSPAnyConverter::ToLSPObject(const protocol::LSPAny& any)
|
||||
{
|
||||
if (!any.is<protocol::LSPObject>())
|
||||
throw ConversionError("LSPAny does not contain LSPObject");
|
||||
return any.get<protocol::LSPObject>();
|
||||
}
|
||||
|
||||
inline protocol::LSPArray LSPAnyConverter::ToLSPArray(const protocol::LSPAny& any)
|
||||
{
|
||||
if (!any.is<protocol::LSPArray>())
|
||||
throw ConversionError("LSPAny does not contain LSPArray");
|
||||
return any.get<protocol::LSPArray>();
|
||||
}
|
||||
|
||||
// 模板实现
|
||||
template<typename T>
|
||||
inline protocol::LSPAny LSPAnyConverter::ToLSPAny(const std::vector<T>& vec)
|
||||
{
|
||||
protocol::LSPArray arr;
|
||||
arr.reserve(vec.size());
|
||||
for (const auto& item : vec)
|
||||
arr.push_back(ToLSPAny(item));
|
||||
return protocol::LSPAny(std::move(arr));
|
||||
}
|
||||
// ==================== ToLSPAny 实现 ====================
|
||||
|
||||
template<typename T>
|
||||
inline protocol::LSPAny LSPAnyConverter::ToLSPAny(const std::map<protocol::string, T>& map)
|
||||
inline protocol::LSPAny LSPAnyConverter::ToLSPAny(const T& value)
|
||||
{
|
||||
protocol::LSPObject obj;
|
||||
for (const auto& [key, value] : map)
|
||||
obj[key] = ToLSPAny(value);
|
||||
return protocol::LSPAny(std::move(obj));
|
||||
}
|
||||
using Type = std::decay_t<T>;
|
||||
|
||||
template<typename T>
|
||||
inline protocol::LSPAny LSPAnyConverter::ToLSPAny(const std::optional<T>& opt)
|
||||
{
|
||||
if (opt.has_value())
|
||||
return ToLSPAny(*opt);
|
||||
return protocol::LSPAny(nullptr);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline typename std::enable_if<is_user_struct<T>::value, protocol::LSPAny>::type
|
||||
LSPAnyConverter::ToLSPAny(const T& obj)
|
||||
{
|
||||
try
|
||||
// LSPAny 直接返回
|
||||
if constexpr (std::is_same_v<Type, protocol::LSPAny>)
|
||||
{
|
||||
// 使用glaze序列化为JSON字符串
|
||||
std::string json;
|
||||
auto ec = glz::write_json(obj, json);
|
||||
if (ec)
|
||||
{
|
||||
throw ConversionError("Failed to serialize struct to JSON: " + std::string(glz::format_error(ec, json)));
|
||||
}
|
||||
return value;
|
||||
}
|
||||
// LSPObject 直接返回
|
||||
else if constexpr (std::is_same_v<Type, protocol::LSPObject>)
|
||||
{
|
||||
return protocol::LSPAny(value);
|
||||
}
|
||||
// LSPArray 直接返回
|
||||
else if constexpr (std::is_same_v<Type, protocol::LSPArray>)
|
||||
{
|
||||
return protocol::LSPAny(value);
|
||||
}
|
||||
else if constexpr (std::is_same_v<Type, const char*> ||
|
||||
std::is_same_v<Type, char*>)
|
||||
{
|
||||
return protocol::LSPAny(protocol::string(value));
|
||||
}
|
||||
// LSP 基本类型(boolean, string, decimal, nullptr)
|
||||
else if constexpr (is_lsp_basic_type_v<Type>)
|
||||
{
|
||||
return protocol::LSPAny(value);
|
||||
}
|
||||
// 整数类型(依赖 LSPAny 模板构造函数)
|
||||
else if constexpr (std::is_integral_v<Type> &&
|
||||
!std::is_same_v<Type, bool>)
|
||||
{
|
||||
return protocol::LSPAny(value);
|
||||
}
|
||||
// 浮点类型
|
||||
else if constexpr (std::is_floating_point_v<Type>)
|
||||
{
|
||||
return protocol::LSPAny(value);
|
||||
}
|
||||
// vector → LSPArray
|
||||
else if constexpr (is_vector_v<Type>)
|
||||
{
|
||||
protocol::LSPArray arr;
|
||||
arr.reserve(value.size());
|
||||
for (const auto& item : value)
|
||||
arr.push_back(ToLSPAny(item));
|
||||
return protocol::LSPAny(std::move(arr));
|
||||
}
|
||||
// map → LSPObject
|
||||
else if constexpr (is_map_v<Type>)
|
||||
{
|
||||
protocol::LSPObject obj;
|
||||
for (const auto& [key, val] : value)
|
||||
obj[key] = ToLSPAny(val);
|
||||
return protocol::LSPAny(std::move(obj));
|
||||
}
|
||||
// optional → LSPAny or null
|
||||
else if constexpr (is_optional_v<Type>)
|
||||
{
|
||||
if (value.has_value())
|
||||
return ToLSPAny(*value);
|
||||
return protocol::LSPAny(nullptr);
|
||||
}
|
||||
// 用户结构体 → LSPAny (通过 JSON)
|
||||
else if constexpr (is_user_struct_v<Type>)
|
||||
{
|
||||
return SerializeViaJson(value);
|
||||
}
|
||||
else
|
||||
{
|
||||
static_assert(!sizeof(Type), "Unsupported type for ToLSPAny");
|
||||
}
|
||||
}
|
||||
|
||||
// 直接解析为LSPAny
|
||||
protocol::LSPAny result;
|
||||
ec = glz::read_json(result, json);
|
||||
if (ec)
|
||||
{
|
||||
throw ConversionError("Failed to parse JSON to LSPAny: " + std::string(glz::format_error(ec, json)));
|
||||
}
|
||||
// ==================== FromLSPAny 实现 ====================
|
||||
|
||||
template<typename T>
|
||||
inline T LSPAnyConverter::FromLSPAny(const protocol::LSPAny& any)
|
||||
{
|
||||
using Type = std::decay_t<T>;
|
||||
|
||||
// LSPAny 直接返回
|
||||
if constexpr (std::is_same_v<Type, protocol::LSPAny>)
|
||||
{
|
||||
return any;
|
||||
}
|
||||
// LSPObject 提取
|
||||
else if constexpr (std::is_same_v<Type, protocol::LSPObject>)
|
||||
{
|
||||
if (!any.Is<protocol::LSPObject>())
|
||||
throw ConversionError("LSPAny does not contain LSPObject");
|
||||
return any.Get<protocol::LSPObject>();
|
||||
}
|
||||
// LSPArray 提取
|
||||
else if constexpr (std::is_same_v<Type, protocol::LSPArray>)
|
||||
{
|
||||
if (!any.Is<protocol::LSPArray>())
|
||||
throw ConversionError("LSPAny does not contain LSPArray");
|
||||
return any.Get<protocol::LSPArray>();
|
||||
}
|
||||
// boolean 提取
|
||||
else if constexpr (std::is_same_v<Type, bool>)
|
||||
{
|
||||
if (!any.Is<protocol::boolean>())
|
||||
throw ConversionError("LSPAny does not contain a boolean");
|
||||
return any.Get<protocol::boolean>();
|
||||
}
|
||||
// string 提取
|
||||
else if constexpr (std::is_same_v<Type, protocol::string> ||
|
||||
std::is_same_v<Type, std::string>)
|
||||
{
|
||||
if (!any.Is<protocol::string>())
|
||||
throw ConversionError("LSPAny does not contain a string");
|
||||
return any.Get<protocol::string>();
|
||||
}
|
||||
// 数字类型提取
|
||||
else if constexpr (std::is_arithmetic_v<Type> &&
|
||||
!std::is_same_v<Type, bool>)
|
||||
{
|
||||
return ExtractNumber<Type>(any);
|
||||
}
|
||||
// vector 提取
|
||||
else if constexpr (is_vector_v<Type>)
|
||||
{
|
||||
if (!any.Is<protocol::LSPArray>())
|
||||
throw ConversionError("LSPAny does not contain an array");
|
||||
|
||||
const auto& arr = any.Get<protocol::LSPArray>();
|
||||
Type result;
|
||||
result.reserve(arr.size());
|
||||
for (const auto& item : arr)
|
||||
result.push_back(FromLSPAny<typename Type::value_type>(item));
|
||||
return result;
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
// map 提取
|
||||
else if constexpr (is_map_v<Type>)
|
||||
{
|
||||
throw ConversionError("struct to LSPAny conversion failed: " + std::string(e.what()));
|
||||
if (!any.Is<protocol::LSPObject>())
|
||||
throw ConversionError("LSPAny does not contain an object");
|
||||
|
||||
const auto& obj = any.Get<protocol::LSPObject>();
|
||||
Type result;
|
||||
for (const auto& [key, val] : obj)
|
||||
result[key] = FromLSPAny<typename Type::mapped_type>(val);
|
||||
return result;
|
||||
}
|
||||
// optional 提取
|
||||
else if constexpr (is_optional_v<Type>)
|
||||
{
|
||||
if (any.Is<std::nullptr_t>())
|
||||
return std::nullopt;
|
||||
return FromLSPAny<typename Type::value_type>(any);
|
||||
}
|
||||
// 用户结构体提取(通过 JSON)
|
||||
else if constexpr (is_user_struct_v<Type>)
|
||||
{
|
||||
return ConvertViaJson<Type>(any);
|
||||
}
|
||||
else
|
||||
{
|
||||
static_assert(!sizeof(Type), "Unsupported type for FromLSPAny");
|
||||
}
|
||||
}
|
||||
|
||||
// Fromprotocol::LSPAny 实现
|
||||
// ==================== 辅助工具实现 ====================
|
||||
|
||||
template<typename T>
|
||||
inline typename std::enable_if<std::is_arithmetic<T>::value && !std::is_same<T, protocol::boolean>::value, T>::type LSPAnyConverter::ToNumber(const protocol::LSPAny& any)
|
||||
inline T LSPAnyConverter::ExtractNumber(const protocol::LSPAny& any)
|
||||
{
|
||||
if (!any.is<protocol::decimal>())
|
||||
throw ConversionError("LSPAny does not contain a number");
|
||||
return static_cast<T>(any.get<protocol::decimal>());
|
||||
if (any.Is<protocol::integer>())
|
||||
{
|
||||
return static_cast<T>(any.Get<protocol::integer>());
|
||||
}
|
||||
else if (any.Is<protocol::uinteger>())
|
||||
{
|
||||
return static_cast<T>(any.Get<protocol::uinteger>());
|
||||
}
|
||||
else if (any.Is<protocol::decimal>())
|
||||
{
|
||||
return static_cast<T>(any.Get<protocol::decimal>());
|
||||
}
|
||||
else
|
||||
{
|
||||
throw ConversionError("LSPAny does not contain a number (integer/uinteger/decimal)");
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline std::vector<T> LSPAnyConverter::ToVector(const protocol::LSPAny& any)
|
||||
{
|
||||
if (!any.is<protocol::LSPArray>())
|
||||
throw ConversionError("LSPAny does not contain an array");
|
||||
|
||||
const auto& arr = any.get<protocol::LSPArray>();
|
||||
std::vector<T> result;
|
||||
result.reserve(arr.size());
|
||||
for (const auto& item : arr)
|
||||
result.push_back(FromLSPAny<T>(item));
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline std::optional<T> LSPAnyConverter::ToOptional(const protocol::LSPAny& any)
|
||||
{
|
||||
if (any.is<std::nullptr_t>())
|
||||
return std::nullopt;
|
||||
return FromLSPAny<T>(any);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline typename std::enable_if<is_user_struct<T>::value, T>::type
|
||||
LSPAnyConverter::FromLSPAny(const protocol::LSPAny& any)
|
||||
{
|
||||
return FromLSPAnyImpl<T>(any);
|
||||
}
|
||||
|
||||
// 处理 std::optional<T>
|
||||
template<typename T, typename From>
|
||||
inline std::optional<T> LSPAnyConverter::As(const std::optional<From>& opt)
|
||||
{
|
||||
if (opt.has_value())
|
||||
return As<T>(*opt);
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
// 处理 std::variant<Ts...>
|
||||
template<typename T, typename... Ts>
|
||||
inline T LSPAnyConverter::As(const std::variant<Ts...>& var)
|
||||
{
|
||||
return std::visit([](const auto& val) -> T {
|
||||
return As<T>(val);
|
||||
}, var);
|
||||
}
|
||||
|
||||
// 处理 LSPObject
|
||||
template<typename T>
|
||||
inline T LSPAnyConverter::As(const protocol::LSPObject& obj)
|
||||
{
|
||||
protocol::LSPAny any(obj);
|
||||
return FromLSPAny<T>(any);
|
||||
}
|
||||
|
||||
// 处理 LSPArray
|
||||
template<typename T>
|
||||
inline T LSPAnyConverter::As(const protocol::LSPArray& arr)
|
||||
{
|
||||
protocol::LSPAny any(arr);
|
||||
return FromLSPAny<T>(any);
|
||||
}
|
||||
|
||||
// FromLSPAnyImpl 实现
|
||||
template<typename T>
|
||||
inline T LSPAnyConverter::FromLSPAnyImpl(const protocol::LSPAny& any)
|
||||
inline T LSPAnyConverter::ConvertViaJson(const protocol::LSPAny& any)
|
||||
{
|
||||
try
|
||||
{
|
||||
// 序列化LSPAny为JSON
|
||||
// 序列化 LSPAny 为 JSON
|
||||
std::string json;
|
||||
auto ec = glz::write_json(any.value, json);
|
||||
if (ec)
|
||||
throw ConversionError("Failed to serialize LSPAny to JSON: " + std::string(glz::format_error(ec, json)));
|
||||
|
||||
// 解析JSON到目标类型
|
||||
// 解析 JSON 到目标类型
|
||||
T result;
|
||||
ec = glz::read_json(result, json);
|
||||
if (ec)
|
||||
|
|
@ -256,4 +217,28 @@ namespace lsp::transform
|
|||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline protocol::LSPAny LSPAnyConverter::SerializeViaJson(const T& obj)
|
||||
{
|
||||
try
|
||||
{
|
||||
// 使用 glaze 序列化为 JSON 字符串
|
||||
std::string json;
|
||||
auto ec = glz::write_json(obj, json);
|
||||
if (ec)
|
||||
throw ConversionError("Failed to serialize struct to JSON: " + std::string(glz::format_error(ec, json)));
|
||||
|
||||
// 直接解析为 LSPAny
|
||||
protocol::LSPAny result;
|
||||
ec = glz::read_json(result, json);
|
||||
if (ec)
|
||||
throw ConversionError("Failed to parse JSON to LSPAny: " + std::string(glz::format_error(ec, json)));
|
||||
|
||||
return result;
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
throw ConversionError("struct to LSPAny conversion failed: " + std::string(e.what()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue