#include "LuaValueDeserializer.h" #include "LuaValueSerializer.h" namespace scripting { namespace util { LuaValueDeserializer::LuaValueDeserializer(lua_State* L) : m_L(L) {} luacpp::LuaValue LuaValueDeserializer::deserialize(const SCP_vector& serialized) const { if (serialized.empty()) { throw std::runtime_error("Not enough data"); } const auto type = static_cast(serialized.front()); switch (type) { case SerializationType::PlainJson: return deserializePlainJson(serialized.data() + 1, serialized.size() - 1); default: throw std::runtime_error("Unknown serialization type."); } } luacpp::LuaValue LuaValueDeserializer::deserializePlainJson(const uint8_t* data, size_t size) const { json_error_t error; std::unique_ptr json(json_loadb(reinterpret_cast(data), size, JSON_DECODE_ANY | JSON_DECODE_INT_AS_REAL | JSON_ALLOW_NUL, &error)); if (!json) { throw json_exception(error); } return jsonToValue(json.get()); } luacpp::LuaValue LuaValueDeserializer::jsonToValue(json_t* json) const { switch (json_typeof(json)) { case JSON_OBJECT: { auto objectTbl = luacpp::LuaTable::create(m_L); for(const auto& pair : json::object_range(json)) { objectTbl.addValue(std::get<0>(pair), jsonToValue(std::get<1>(pair))); } return objectTbl; } case JSON_ARRAY: { auto arrayTbl = luacpp::LuaTable::create(m_L); size_t i = 1; for (const auto& value : json::array_range(json)) { arrayTbl.addValue(i, jsonToValue(value)); ++i; } return arrayTbl; } case JSON_STRING: { const auto val = json_string_value(json); const auto len = json_string_length(json); return luacpp::LuaValue::createValue(m_L, SCP_string(val, val + len)); } case JSON_REAL: return luacpp::LuaValue::createValue(m_L, json_real_value(json)); case JSON_TRUE: return luacpp::LuaValue::createValue(m_L, true); case JSON_FALSE: return luacpp::LuaValue::createValue(m_L, false); case JSON_NULL: return luacpp::LuaValue::createNil(m_L); default: return luacpp::LuaValue(); } } } // namespace util } // namespace scripting