217 lines
5.7 KiB
C++
217 lines
5.7 KiB
C++
#include "data.hpp"
|
|
|
|
#include <nlohmann/json.hpp>
|
|
|
|
#include <cppbase/result.hpp>
|
|
#include <cppbase/templates.hpp>
|
|
|
|
#include <ikarus/values/data.h>
|
|
#include <ikarus/values/errors.hpp>
|
|
#include <ikarus/values/schema.h>
|
|
#include <ikarus/values/shared.hpp>
|
|
|
|
auto get_primitive_type(IkarusValueDataPrimitive const & primitive)
|
|
-> IkarusValuePrimitiveType {
|
|
return std::visit(
|
|
cppbase::overloaded{
|
|
[](IkarusValueDataPrimitiveToggle const &) {
|
|
return IkarusValuePrimitiveType_Toggle;
|
|
},
|
|
[](IkarusValueDataPrimitiveNumber const &) {
|
|
return IkarusValuePrimitiveType_Number;
|
|
},
|
|
[](IkarusValueDataPrimitiveString const &) {
|
|
return IkarusValuePrimitiveType_Text;
|
|
}
|
|
},
|
|
primitive
|
|
);
|
|
}
|
|
|
|
auto IkarusValueData::from_json(nlohmann::json const & json)
|
|
-> cppbase::Result<IkarusValueData, IkarusValueDataParseError> {
|
|
if (!json.is_object()) {
|
|
return cppbase::err(IkarusJsonError{IkarusJsonInvalidTypeError{}});
|
|
}
|
|
|
|
IkarusValueData value{};
|
|
|
|
VTRY(
|
|
auto type,
|
|
deserialize_enum<IkarusValueDataType>(
|
|
json,
|
|
"type",
|
|
IkarusValueDataType_Primitive,
|
|
IkarusValueDataType_Tuple
|
|
)
|
|
);
|
|
|
|
switch (type) {
|
|
case IkarusValueDataType_Primitive: {
|
|
VTRY(
|
|
auto primitive,
|
|
deserialize_enum<IkarusValuePrimitiveType>(
|
|
json,
|
|
"primitive",
|
|
IkarusValuePrimitiveType_Toggle,
|
|
IkarusValuePrimitiveType_Text
|
|
)
|
|
);
|
|
|
|
switch (primitive) {
|
|
case IkarusValuePrimitiveType_Toggle: {
|
|
VTRY(auto data, deserialize_any<bool>(json, "data"));
|
|
|
|
value.variant = IkarusValueDataPrimitiveToggle{data};
|
|
break;
|
|
}
|
|
case IkarusValuePrimitiveType_Number: {
|
|
VTRY(auto data, deserialize_any<double>(json, "data"));
|
|
|
|
value.variant = IkarusValueDataPrimitiveNumber{data};
|
|
break;
|
|
}
|
|
case IkarusValuePrimitiveType_Text: {
|
|
VTRY(auto data, deserialize_any<std::string>(json, "data"));
|
|
|
|
value.variant = IkarusValueDataPrimitiveString{data};
|
|
break;
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
case IkarusValueDataType_List: {
|
|
std::vector<cppbase::owning_ptr<IkarusValueData>> values_data{};
|
|
VTRY(
|
|
auto data_json,
|
|
deserialize_any<std::vector<nlohmann::json>>(json, "data")
|
|
);
|
|
|
|
values_data.reserve(data_json.size());
|
|
for (auto const & data_json : data_json) {
|
|
VTRY(auto value_data, IkarusValueData::from_json(data_json));
|
|
values_data.emplace_back(
|
|
cppbase::make_owning<IkarusValueData>(std::move(value_data))
|
|
);
|
|
}
|
|
|
|
value.variant = IkarusValueDataList{values_data};
|
|
break;
|
|
}
|
|
case IkarusValueDataType_Map: {
|
|
std::vector<std::pair<
|
|
cppbase::owning_ptr<IkarusValueData>,
|
|
cppbase::owning_ptr<IkarusValueData>>>
|
|
map_data{};
|
|
|
|
VTRY(
|
|
auto map_data_json,
|
|
deserialize_any<std::vector<nlohmann::json>>(json, "data")
|
|
);
|
|
|
|
map_data.reserve(map_data_json.size());
|
|
|
|
for (auto const & pair_json : map_data_json) {
|
|
VTRY(auto key_json, get_key(pair_json, "key"));
|
|
VTRY(auto value_json, get_key(pair_json, "value"));
|
|
VTRY(auto key, IkarusValueData::from_json(*key_json));
|
|
VTRY(auto value, IkarusValueData::from_json(*value_json));
|
|
|
|
map_data.emplace_back(
|
|
cppbase::make_owning<IkarusValueData>(key),
|
|
cppbase::make_owning<IkarusValueData>(value)
|
|
);
|
|
}
|
|
|
|
value.variant = IkarusValueDataMap{map_data};
|
|
break;
|
|
}
|
|
case IkarusValueDataType_Tuple: {
|
|
std::vector<cppbase::owning_ptr<IkarusValueData>> values_data{};
|
|
|
|
VTRY(
|
|
auto values_json,
|
|
deserialize_any<std::vector<nlohmann::json>>(json, "data")
|
|
);
|
|
|
|
values_data.reserve(values_json.size());
|
|
|
|
for (auto const & value_json : values_json) {
|
|
VTRY(auto value_data, IkarusValueData::from_json(value_json));
|
|
values_data.emplace_back(
|
|
cppbase::make_owning<IkarusValueData>(value_data)
|
|
);
|
|
}
|
|
|
|
value.variant = IkarusValueDataTuple{values_data};
|
|
break;
|
|
}
|
|
}
|
|
|
|
return cppbase::ok(value);
|
|
}
|
|
|
|
auto IkarusValueData::to_json(
|
|
nlohmann::json & json,
|
|
IkarusValueData const & value
|
|
) -> void {
|
|
std::visit(
|
|
cppbase::overloaded{
|
|
[&](IkarusValueDataPrimitive const & primitive) {
|
|
std::visit(
|
|
cppbase::overloaded{
|
|
[&](IkarusValueDataPrimitiveToggle const & toggle) {
|
|
json["type"] = IkarusValueDataType_Primitive;
|
|
json["primitive"] = IkarusValuePrimitiveType_Toggle;
|
|
json["data"] = toggle.value;
|
|
},
|
|
[&](IkarusValueDataPrimitiveNumber const & number) {
|
|
json["type"] = IkarusValueDataType_Primitive;
|
|
json["primitive"] = IkarusValuePrimitiveType_Number;
|
|
json["data"] = number.value;
|
|
},
|
|
[&](IkarusValueDataPrimitiveString const & string) {
|
|
json["type"] = IkarusValueDataType_Primitive;
|
|
json["primitive"] = IkarusValuePrimitiveType_Text;
|
|
json["data"] = string.value;
|
|
}
|
|
},
|
|
primitive
|
|
);
|
|
},
|
|
[&](IkarusValueDataList const & list) {
|
|
json["type"] = IkarusValueDataType_List;
|
|
json["data"] = list.values |
|
|
std::views::transform([](auto const & data) {
|
|
nlohmann::json j;
|
|
IkarusValueData::to_json(j, *data);
|
|
return j;
|
|
}) |
|
|
std::ranges::to<std::vector<nlohmann::json>>();
|
|
},
|
|
[&](IkarusValueDataMap const & map) {
|
|
json["type"] = IkarusValueDataType_Map;
|
|
json["data"] =
|
|
map.values | std::views::transform([](auto const & pair) {
|
|
nlohmann::json j;
|
|
IkarusValueData::to_json(j["key"], *pair.first);
|
|
IkarusValueData::to_json(j["value"], *pair.second);
|
|
return j;
|
|
}) |
|
|
std::ranges::to<std::vector<nlohmann::json>>();
|
|
},
|
|
[&](IkarusValueDataTuple const & tuple) {
|
|
json["type"] = IkarusValueDataType_Tuple;
|
|
json["data"] = tuple.values |
|
|
std::views::transform([](auto const & data) {
|
|
nlohmann::json j;
|
|
IkarusValueData::to_json(j, *data);
|
|
return j;
|
|
}) |
|
|
std::ranges::to<std::vector<nlohmann::json>>();
|
|
}
|
|
},
|
|
value.variant
|
|
);
|
|
}
|