#pragma once #include #include #include namespace clice::json { using namespace llvm::json; template constexpr inline bool is_array_v = false; template constexpr inline bool is_array_v> = true; template constexpr inline bool is_array_v> = true; template constexpr inline bool is_string_v = false; template <> constexpr inline bool is_string_v = true; template <> constexpr inline bool is_string_v = true; template <> constexpr inline bool is_string_v = true; template constexpr inline bool is_integral_v = std::is_same_v || std::is_same_v || std::is_same_v || std::is_same_v; template json::Value serialize(const Value& value) { if constexpr(std::is_same_v) { return value; } else if constexpr(is_integral_v || std::is_enum_v) { return static_cast(value); } else if constexpr(std::is_floating_point_v) { return static_cast(value); } else if constexpr(is_string_v) { return llvm::StringRef(value); } else if constexpr(is_array_v) { json::Array array; for(const auto& element: value) { array.push_back(serialize(element)); } return array; } else { json::Object object; for_each(value, [&](llvm::StringRef name, const auto& field) { object.try_emplace(name, serialize(field)); }); return object; } } template Value deserialize(const json::Value& object) { if constexpr(std::is_same_v) { return Value{object.getAsBoolean().value()}; } else if constexpr(is_integral_v || std::is_enum_v) { return object.getAsInteger().value(); } else if constexpr(std::is_floating_point_v) { return object.getAsNumber().value(); } else if constexpr(is_string_v) { return Value{object.getAsString().value()}; } else if constexpr(is_array_v) { Value array; for(const auto& element: *object.getAsArray()) { array.push_back(deserialize(element)); } return array; } else { Value value; for_each(value, [&](llvm::StringRef name, auto& field) { if(auto element = object.getAsObject()->get(name)) { field = deserialize>(*element); } }); return value; } } } // namespace clice::json