248 lines
5.7 KiB
C++
248 lines
5.7 KiB
C++
#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<const bool*>(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<const std::byte*>(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<const std::string*>(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<bool*>(data) = node.as<bool>();
|
|
}
|
|
|
|
void operator()(const IntType& type)
|
|
{
|
|
visitIntValue([&](auto& value)
|
|
{
|
|
using type_t = std::decay_t<decltype(value)>;
|
|
value = node.as<type_t>();
|
|
}, data, type);
|
|
}
|
|
|
|
void operator()(const FloatType& type)
|
|
{
|
|
visitFloatValue([&](auto& value)
|
|
{
|
|
using type_t = std::decay_t<decltype(value)>;
|
|
value = node.as<type_t>();
|
|
}, data, type);
|
|
}
|
|
|
|
void operator()(const CharType& type)
|
|
{
|
|
MIJIN_ERROR("Not implemented.");
|
|
(void) type;
|
|
// visitCharValue([&](auto& value)
|
|
// {
|
|
// using type_t = std::decay_t<decltype(value)>;
|
|
// value = node.as<type_t>();
|
|
// }, 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<std::byte*>(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<std::string*>(data) = node.as<std::string>();
|
|
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<const std::byte*>(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<std::byte*>(data) + property.offset, property.type, propNode);
|
|
}
|
|
}
|
|
}
|