libikarus/src/ikarus/values/data.cpp
folling 954b8a11a3
finalize schema/data setup
Signed-off-by: Folling <mail@folling.io>
2025-04-15 12:11:25 +02:00

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
);
}