#include "iwa/serialization.hpp" namespace iwa { namespace { void propertyToYAML(const void* data, const iwa::Type& type, YAML::Emitter& emitter); void propertyFromYAML(void* data, const iwa::Type& type, const YAML::Node& node); struct PropertyEmitVisitor { const void* data; YAML::Emitter& emitter; void operator()(const VoidType&) { emitter << YAML::Null; } void operator()(const BoolType&) { emitter << *static_cast(data); } void operator()(const IntType& type) { visitIntValue([&](auto&& value) { emitter << value; }, data, type); } void operator()(const FloatType& type) { visitFloatValue([&](auto&& value) { emitter << value; }, data, type); } void operator()(const CharType& type) { visitCharValue([&](auto&& value) { emitter << value; }, data, type); } void operator()(const ArrayType& type) { emitter << YAML::BeginSeq; for (std::size_t idx = 0; idx < type.arraySize; ++idx) { const std::byte* ele = static_cast(data) + (idx * type.arrayStride); propertyToYAML(ele, *type.baseType, emitter); } emitter << YAML::EndSeq; } void operator()(const ClassType&) { MIJIN_ERROR("Not implemented."); emitter << YAML::Null; } void operator()(const StructType& type) { structToYAML(data, *type.struct_, emitter); } void operator()(const PointerType&) { MIJIN_ERROR("Not implemented."); emitter << YAML::Null; } void operator()(const ReferenceType&) { MIJIN_ERROR("Not implemented."); emitter << YAML::Null; } void operator()(const ConstType& type) { propertyToYAML(data, *type.baseType, emitter); } void operator()(const VolatileType& type) { propertyToYAML(data, *type.baseType, emitter); } void operator()(const STDType& type) { switch (type) { case STDType::STRING: emitter << *static_cast(data); break; } } void operator()(const BitFlagsType&) { MIJIN_ERROR("Not implemented."); emitter << YAML::Null; } }; struct PropertyParseVisitor { void* data; const YAML::Node& node; void operator()(const VoidType&) { /* ??? */ } void operator()(const BoolType&) { *static_cast(data) = node.as(); } void operator()(const IntType& type) { visitIntValue([&](auto& value) { using type_t = std::decay_t; value = node.as(); }, data, type); } void operator()(const FloatType& type) { visitFloatValue([&](auto& value) { using type_t = std::decay_t; value = node.as(); }, data, type); } void operator()(const CharType& type) { MIJIN_ERROR("Not implemented."); (void) type; // visitCharValue([&](auto& value) // { // using type_t = std::decay_t; // value = node.as(); // }, data, type); } void operator()(const ArrayType& type) { if (!node.IsSequence() || node.size() != type.arraySize) { throw std::runtime_error("Node not an array or size doesn't fit."); } for (std::size_t idx = 0; idx < type.arraySize; ++idx) { std::byte* ele = static_cast(data) + (idx * type.arrayStride); propertyFromYAML(ele, *type.baseType, node[idx]); } } void operator()(const ClassType&) { MIJIN_ERROR("Not implemented."); } void operator()(const StructType& type) { structFromYAML(data, *type.struct_, node); } void operator()(const PointerType&) { MIJIN_ERROR("Not implemented."); } void operator()(const ReferenceType&) { MIJIN_ERROR("Not implemented."); } void operator()(const ConstType&) { MIJIN_ERROR("Can't read const values."); } void operator()(const VolatileType& type) { propertyFromYAML(data, *type.baseType, node); } void operator()(const STDType& type) { switch (type) { case STDType::STRING: *static_cast(data) = node.as(); break; } } void operator()(const BitFlagsType&) { MIJIN_ERROR("Not implemented."); } }; void propertyToYAML(const void* data, const iwa::Type& type, YAML::Emitter& emitter) { std::visit(PropertyEmitVisitor{data, emitter}, type); } void propertyFromYAML(void* data, const iwa::Type& type, const YAML::Node& node) { std::visit(PropertyParseVisitor{data, node}, type); } } void structToYAML(const void* data, const Struct& type, YAML::Emitter& emitter) { emitter << YAML::BeginMap; for (const Property& property : type.getProperties()) { emitter << YAML::Key << property.name; propertyToYAML(static_cast(data) + property.offset, property.type, emitter); } emitter << YAML::EndMap; } void structFromYAML(void* data, const Struct& type, const YAML::Node& node) { if (!node.IsMap()) { throw std::runtime_error("Expected map."); } for (const Property& property : type.getProperties()) { const YAML::Node& propNode = node[property.name]; if (propNode.IsNull()) { continue; } propertyFromYAML(static_cast(data) + property.offset, property.type, propNode); } } }