[ox] Rename Serialization package to Model

This commit is contained in:
2019-03-17 13:04:18 -05:00
parent cf7ba595aa
commit bf6469b4a3
17 changed files with 14 additions and 14 deletions

35
deps/ox/src/ox/model/CMakeLists.txt vendored Normal file
View File

@@ -0,0 +1,35 @@
add_library(
OxModel
desctypes.cpp
descwrite.cpp
)
target_link_libraries(
OxModel PUBLIC
OxStd
)
set_property(
TARGET
OxModel
PROPERTY
POSITION_INDEPENDENT_CODE ON
)
install(
FILES
descread.hpp
desctypes.hpp
descwrite.hpp
optype.hpp
model.hpp
types.hpp
walk.hpp
DESTINATION
include/ox/model
)
install(TARGETS OxModel
LIBRARY DESTINATION lib/ox
ARCHIVE DESTINATION lib/ox
)

View File

@@ -0,0 +1,7 @@
<Type> : <TypeName><FieldList>
<FieldList> : <FieldList> | <FieldList><Field>
<Field> : <FieldType><TypeID><FieldName>
<TypeID> : <TypeName> | <TypeName><Type>
<TypeName> : <string>
<FieldType> : <0: single> | <1: list>
<FieldName> : <string>

42
deps/ox/src/ox/model/descread.hpp vendored Normal file
View File

@@ -0,0 +1,42 @@
/*
* Copyright 2015 - 2018 gtalent2@gmail.com
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#pragma once
#include "desctypes.hpp"
namespace ox {
template<typename ReaderBase>
class TypeDescReader: public ReaderBase {
private:
TypeStore m_typeStore;
public:
TypeDescReader(uint8_t *buff, std::size_t buffLen);
const TypeStore &typeStore() const;
};
template<typename ReaderBase>
TypeDescReader<ReaderBase>::TypeDescReader(uint8_t *buff, std::size_t buffLen): ReaderBase(buff, buffLen) {
}
template<typename ReaderBase>
const TypeStore &TypeDescReader<ReaderBase>::typeStore() const {
return m_typeStore;
}
template<typename ReaderBase, typename T>
int readMCDef(uint8_t *buff, std::size_t buffLen, T *val) {
TypeDescReader<ReaderBase> reader(buff, buffLen);
return ioOp(&reader, val);
}
}

19
deps/ox/src/ox/model/desctypes.cpp vendored Normal file
View File

@@ -0,0 +1,19 @@
/*
* Copyright 2015 - 2018 gtalent2@gmail.com
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#include "desctypes.hpp"
namespace ox {
DescriptorField::~DescriptorField() {
if (ownsType) {
delete type;
}
}
}

175
deps/ox/src/ox/model/desctypes.hpp vendored Normal file
View File

@@ -0,0 +1,175 @@
/*
* Copyright 2015 - 2018 gtalent2@gmail.com
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#pragma once
#include <ox/std/error.hpp>
#include <ox/std/hashmap.hpp>
#include <ox/std/string.hpp>
#include <ox/std/vector.hpp>
namespace ox {
using String = BString<100>;
using FieldName = String;
using TypeName = String;
enum class PrimitiveType: uint8_t {
UnsignedInteger = 0,
SignedInteger = 1,
Bool = 2,
// Float = 3, reserved, but not implemented
String = 4,
Struct = 5,
};
struct DescriptorField {
// order of fields matters
// only serialize type name if type has already been serialized
const struct DescriptorType *type = nullptr;
FieldName fieldName;
int subscriptLevels = 0;
// do not serialize the following
TypeName typeName; // gives reference to type for lookup if type is null
bool ownsType = false;
constexpr DescriptorField() noexcept = default;
/**
* Allow for explicit copying.
*/
constexpr explicit DescriptorField(const DescriptorField &other) noexcept {
type = other.type;
fieldName = other.fieldName;
subscriptLevels = other.subscriptLevels;
typeName = other.typeName;
ownsType = false; // is copy, only owns type if move
}
constexpr DescriptorField(const DescriptorType *type, const FieldName &fieldName, int subscriptLevels, const TypeName &typeName, bool ownsType) noexcept {
this->type = type;
this->fieldName = fieldName;
this->subscriptLevels = subscriptLevels;
this->typeName = typeName;
this->ownsType = ownsType;
}
constexpr DescriptorField(DescriptorField &&other) noexcept {
type = other.type;
fieldName = other.fieldName;
subscriptLevels = other.subscriptLevels;
typeName = other.typeName;
ownsType = other.ownsType;
other.type = {};
other.fieldName = "";
other.subscriptLevels = {};
other.typeName = "";
other.ownsType = {};
}
~DescriptorField();
constexpr const DescriptorField &operator=(DescriptorField &&other) noexcept {
type = other.type;
fieldName = other.fieldName;
subscriptLevels = other.subscriptLevels;
typeName = other.typeName;
ownsType = other.ownsType;
other.type = {};
other.fieldName = "";
other.subscriptLevels = {};
other.typeName = "";
other.ownsType = {};
return *this;
}
};
using FieldList = Vector<DescriptorField>;
struct DescriptorType {
TypeName typeName;
PrimitiveType primitiveType;
// fieldList only applies to structs
FieldList fieldList;
// - number of bytes for integer and float types
// - number of fields for structs and lists
int64_t length = 0;
DescriptorType() = default;
DescriptorType(TypeName tn, PrimitiveType t, int b): typeName(tn), primitiveType(t), length(b) {
}
DescriptorType(TypeName tn, PrimitiveType t, FieldList fl): typeName(tn), primitiveType(t), fieldList(fl) {
}
};
template<typename T>
Error ioOp(T *io, DescriptorType *type) {
Error err = 0;
io->setTypeInfo("ox::DescriptorType", 4);
err |= io->op("typeName", &type->typeName);
err |= io->op("primitiveType", &type->primitiveType);
err |= io->op("fieldList", &type->fieldList);
err |= io->op("length", &type->length);
return err;
}
template<typename T>
Error ioOpWrite(T *io, DescriptorField *field) {
Error err = 0;
io->setTypeInfo("ox::DescriptorField", 4);
if (field->ownsType) {
err |= io->op("typeName", "");
err |= io->op("type", field->type);
} else {
err |= io->op("typeName", &field->type->typeName);
err |= io->op("type", static_cast<decltype(field->type)>(nullptr));
}
err |= io->op("fieldName", &field->fieldName);
// defaultValue is unused now, but leave placeholder for backwards compatibility
const int DefaultValue = 0;
err |= io->op("defaultValue", &DefaultValue);
return err;
}
template<typename T>
Error ioOpRead(T *io, DescriptorField *field) {
Error err = 0;
auto &typeStore = io->typeStore();
io->setTypeInfo("ox::DescriptorField", 4);
err |= io->op("typeName", &field->typeName);
if (field->typeName == "") {
field->ownsType = true;
if (field->type == nullptr) {
field->type = new DescriptorType;
}
err |= io->op("type", field->type);
typeStore[field->type->typeName] = field->type;
} else {
// should be empty, so discard
DescriptorType t;
err |= io->op("type", &t);
field->type = typeStore[field->typeName];
}
err |= io->op("fieldName", &field->fieldName);
// defaultValue is unused now, but placeholder for backwards compatibility
err |= io->op("defaultValue", nullptr);
return err;
}
using TypeStore = ox::HashMap<String, DescriptorType*>;
}

153
deps/ox/src/ox/model/descwrite.cpp vendored Normal file
View File

@@ -0,0 +1,153 @@
/*
* Copyright 2015 - 2019 gtalent2@gmail.com
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#include <ox/std/typeinfo.hpp>
#include "descwrite.hpp"
namespace ox {
static_assert([] {
int i = 0;
return indirectionLevels(i) == 0;
}(), "indirectionLevels broken: indirectionLevels(int)");
static_assert([] {
int i = 0;
return indirectionLevels(&i) == 1;
}(), "indirectionLevels broken: indirectionLevels(int*)");
static_assert([] {
int i[2] = {};
return indirectionLevels(i) == 1;
}(), "indirectionLevels broken: indirectionLevels(int[])");
static_assert([] {
int i[2][2] = {{}};
return indirectionLevels(i) == 2;
}(), "indirectionLevels broken: indirectionLevels(int[][])");
TypeDescWriter::TypeDescWriter(TypeStore *typeStore) {
if (!typeStore) {
m_typeStoreOwnerRef = new TypeStore;
typeStore = m_typeStoreOwnerRef;
}
m_typeStore = typeStore;
}
TypeDescWriter::~TypeDescWriter() {
// does not own it's elements
delete m_typeStoreOwnerRef;
}
DescriptorType *TypeDescWriter::type(int8_t*, bool *alreadyExisted) {
constexpr auto TypeName = "B:int8_t";
constexpr auto PT = PrimitiveType::SignedInteger;
constexpr auto Bytes = 1;
return getType(TypeName, PT, Bytes, alreadyExisted);
}
DescriptorType *TypeDescWriter::type(int16_t*, bool *alreadyExisted) {
constexpr auto TypeName = "B:int16_t";
constexpr auto PT = PrimitiveType::SignedInteger;
constexpr auto Bytes = 2;
return getType(TypeName, PT, Bytes, alreadyExisted);
}
DescriptorType *TypeDescWriter::type(int32_t*, bool *alreadyExisted) {
constexpr auto TypeName = "B:int32_t";
constexpr auto PT = PrimitiveType::SignedInteger;
constexpr auto Bytes = 4;
return getType(TypeName, PT, Bytes, alreadyExisted);
}
DescriptorType *TypeDescWriter::type(int64_t*, bool *alreadyExisted) {
constexpr auto TypeName = "B:int64_t";
constexpr auto PT = PrimitiveType::SignedInteger;
constexpr auto Bytes = 8;
return getType(TypeName, PT, Bytes, alreadyExisted);
}
DescriptorType *TypeDescWriter::type(uint8_t*, bool *alreadyExisted) {
constexpr auto TypeName = "B:uint8_t";
constexpr auto PT = PrimitiveType::UnsignedInteger;
constexpr auto Bytes = 1;
return getType(TypeName, PT, Bytes, alreadyExisted);
}
DescriptorType *TypeDescWriter::type(uint16_t*, bool *alreadyExisted) {
constexpr auto TypeName = "B:uint16_t";
constexpr auto PT = PrimitiveType::UnsignedInteger;
constexpr auto Bytes = 2;
return getType(TypeName, PT, Bytes, alreadyExisted);
}
DescriptorType *TypeDescWriter::type(uint32_t*, bool *alreadyExisted) {
constexpr auto TypeName = "B:uint32_t";
constexpr auto PT = PrimitiveType::UnsignedInteger;
constexpr auto Bytes = 4;
return getType(TypeName, PT, Bytes, alreadyExisted);
}
DescriptorType *TypeDescWriter::type(uint64_t*, bool *alreadyExisted) {
constexpr auto TypeName = "B:uint64_t";
constexpr auto PT = PrimitiveType::UnsignedInteger;
constexpr auto Bytes = 8;
return getType(TypeName, PT, Bytes, alreadyExisted);
}
DescriptorType *TypeDescWriter::type(const char*, bool *alreadyExisted) {
constexpr auto TypeName = "B:string";
constexpr auto PT = PrimitiveType::String;
return getType(TypeName, PT, 0, alreadyExisted);
}
DescriptorType *TypeDescWriter::type(SerStr, bool *alreadyExisted) {
constexpr auto TypeName = "B:string";
constexpr auto PT = PrimitiveType::String;
return getType(TypeName, PT, 0, alreadyExisted);
}
DescriptorType *TypeDescWriter::type(bool*, bool *alreadyExisted) {
constexpr auto TypeName = "B:bool";
constexpr auto PT = PrimitiveType::Bool;
constexpr auto Bytes = 0;
return getType(TypeName, PT, Bytes, alreadyExisted);
}
void TypeDescWriter::setTypeInfo(const char *name, int) {
auto &t = m_typeStore->at(name);
if (!t) {
t = new DescriptorType;
}
m_type = t;
m_type->typeName = name;
m_type->primitiveType = PrimitiveType::Struct;
}
DescriptorType *TypeDescWriter::getType(TypeName tn, PrimitiveType pt, int b, bool *alreadyExisted) {
if (m_typeStore->contains(tn)) {
*alreadyExisted = true;
auto type = m_typeStore->at(tn);
oxAssert(type != nullptr, "TypeDescWriter::getType returning null DescriptorType");
return type;
} else {
*alreadyExisted = false;
auto &t = m_typeStore->at(tn);
if (!t) {
t = new DescriptorType;
}
t->typeName = tn;
t->primitiveType = pt;
t->length = b;
return t;
}
}
}

183
deps/ox/src/ox/model/descwrite.hpp vendored Normal file
View File

@@ -0,0 +1,183 @@
/*
* Copyright 2015 - 2019 gtalent2@gmail.com
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#pragma once
#include <ox/std/byteswap.hpp>
#include <ox/std/hashmap.hpp>
#include <ox/std/string.hpp>
#include <ox/std/trace.hpp>
#include <ox/std/types.hpp>
#include <ox/std/vector.hpp>
#include "desctypes.hpp"
#include "optype.hpp"
#include "types.hpp"
namespace ox {
template<typename T>
static constexpr int indirectionLevels(T) {
return 0;
}
template<typename T>
static constexpr int indirectionLevels(T *t) {
return 1 + indirectionLevels(*t);
}
class TypeDescWriter {
private:
struct NameCatcher {
TypeName name;
constexpr void setTypeInfo(const char *name, int) noexcept {
this->name = name;
}
template<typename T>
constexpr ox::Error op(const char*, T*, std::size_t) noexcept {
return OxError(0);
}
template<typename T>
constexpr ox::Error op(const char*, T*) noexcept {
return OxError(0);
}
};
TypeStore *m_typeStoreOwnerRef = nullptr;
TypeStore *m_typeStore = nullptr;
DescriptorType *m_type = nullptr;
public:
explicit TypeDescWriter(TypeStore *typeStore = nullptr);
~TypeDescWriter();
template<typename T>
ox::Error op(const char *name, T *val, std::size_t valLen);
template<typename T>
ox::Error op(const char *name, ox::Vector<T> *val);
template<typename T>
ox::Error op(const char *name, T *val);
void setTypeInfo(const char *name, int fields);
[[nodiscard]] DescriptorType *definition() noexcept {
return m_type;
}
static constexpr OpType opType() {
return OpType::WriteDefinition;
}
private:
DescriptorType *type(int8_t *val, bool *alreadyExisted);
DescriptorType *type(int16_t *val, bool *alreadyExisted);
DescriptorType *type(int32_t *val, bool *alreadyExisted);
DescriptorType *type(int64_t *val, bool *alreadyExisted);
DescriptorType *type(uint8_t *val, bool *alreadyExisted);
DescriptorType *type(uint16_t *val, bool *alreadyExisted);
DescriptorType *type(uint32_t *val, bool *alreadyExisted);
DescriptorType *type(uint64_t *val, bool *alreadyExisted);
DescriptorType *type(bool *val, bool *alreadyExisted);
DescriptorType *type(const char *val, bool *alreadyExisted);
DescriptorType *type(SerStr val, bool *alreadyExisted);
template<std::size_t sz>
DescriptorType *type(BString<sz> *val, bool *alreadyExisted);
template<typename T>
DescriptorType *type(T *val, bool *alreadyExisted);
DescriptorType *getType(TypeName tn, PrimitiveType t, int b, bool *alreadyExisted);
};
// array handler
template<typename T>
ox::Error TypeDescWriter::op(const char *name, T *val, std::size_t) {
if (m_type) {
constexpr typename ox::remove_pointer<decltype(val)>::type *p = nullptr;
bool alreadyExisted = false;
const auto t = type(p, &alreadyExisted);
oxAssert(t != nullptr, "op(const char *name, T *val, std::size_t): Type not found or generated");
if (t == nullptr) {
type(p, &alreadyExisted);
}
m_type->fieldList.emplace_back(t, name, indirectionLevels(val), alreadyExisted ? t->typeName : "", !alreadyExisted);
return OxError(0);
}
return OxError(1);
}
template<typename T>
ox::Error TypeDescWriter::op(const char *name, ox::Vector<T> *val) {
return op(name, val->data(), val->size());
}
template<typename T>
ox::Error TypeDescWriter::op(const char *name, T *val) {
if (m_type) {
bool alreadyExisted = false;
const auto t = type(val, &alreadyExisted);
oxAssert(t != nullptr, "op(const char *name, T *val): Type not found or generated");
m_type->fieldList.emplace_back(t, name, 0, alreadyExisted ? t->typeName : "", !alreadyExisted);
return OxError(0);
}
return OxError(1);
}
template<std::size_t sz>
DescriptorType *TypeDescWriter::type(BString<sz> *val, bool *alreadyExisted) {
return type(SerStr(val), alreadyExisted);
}
template<typename T>
DescriptorType *TypeDescWriter::type(T *val, bool *alreadyExisted) {
NameCatcher nc;
ioOp(&nc, val);
if (m_typeStore->contains(nc.name)) {
*alreadyExisted = true;
return m_typeStore->at(nc.name);
} else {
TypeDescWriter dw(m_typeStore);
oxLogError(ioOp(&dw, val));
*alreadyExisted = false;
return dw.m_type;
}
}
template<typename T>
[[nodiscard]] ValErr<DescriptorType*> buildMCDef(T *val) {
TypeDescWriter writer;
Error err = ioOp(&writer, val);
return {writer.definition(), err};
}
template<typename T>
Error writeMCDef(uint8_t *buff, std::size_t buffLen, T *val, std::size_t *sizeOut = nullptr) {
auto def = buildMCDef(val);
auto err = def.error;
if (!err) {
err |= writeMC(buff, buffLen, def.value, sizeOut);
}
delete def.value;
return err;
}
}

15
deps/ox/src/ox/model/model.hpp vendored Normal file
View File

@@ -0,0 +1,15 @@
/*
* Copyright 2015 - 2019 gtalent2@gmail.com
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#pragma once
#include "descread.hpp"
#include "desctypes.hpp"
#include "descwrite.hpp"
#include "types.hpp"
#include "walk.hpp"

50
deps/ox/src/ox/model/optype.hpp vendored Normal file
View File

@@ -0,0 +1,50 @@
/*
* Copyright 2015 - 2018 gtalent2@gmail.com
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#pragma once
#include <ox/std/error.hpp>
namespace ox {
enum class OpType {
Read = 1,
Write = 2,
WriteDefinition = 3,
};
// empty default implementations of ioOp functions
template<typename T, typename O>
ox::Error ioOpRead(T*, O*) {
return OxError(1);
}
template<typename T, typename O>
ox::Error ioOpWrite(T*, O*) {
return OxError(1);
}
template<typename T, typename O>
ox::Error ioOpWriteDefinition(T*, O*) {
return OxError(1);
}
template<typename T, typename O>
ox::Error ioOp(T *io, O *obj) {
if constexpr(T::opType() == ox::OpType::Read) {
return ioOpRead(io, obj);
} else if constexpr(T::opType() == ox::OpType::Write) {
return ioOpWrite(io, obj);
} else if constexpr(T::opType() == ox::OpType::WriteDefinition) {
return ioOpWriteDefinition(io, obj);
}
return OxError(1);
}
}

58
deps/ox/src/ox/model/types.hpp vendored Normal file
View File

@@ -0,0 +1,58 @@
/*
* Copyright 2015 - 2018 gtalent2@gmail.com
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#pragma once
#include <ox/std/string.hpp>
#include <ox/std/strops.hpp>
#include <ox/std/types.hpp>
namespace ox {
class SerStr {
protected:
int m_cap = 0;
char *m_str = nullptr;
public:
template<std::size_t sz>
constexpr SerStr(BString<sz> *str) noexcept {
m_str = str->data();
m_cap = str->cap();
}
constexpr SerStr(char *str, int cap) noexcept {
m_str = str;
m_cap = cap;
}
constexpr const char *c_str() noexcept {
return m_str;
}
constexpr char *data() noexcept {
// do not return a non-const pointer to the const_casted m_str
return m_str;
}
constexpr int len() noexcept {
return ox_strlen(m_str);
}
constexpr int bytes() noexcept {
return ox_strlen(m_str) + 1; // adds 1 for \0
}
constexpr int cap() noexcept {
return m_cap;
}
};
}

146
deps/ox/src/ox/model/walk.hpp vendored Normal file
View File

@@ -0,0 +1,146 @@
/*
* Copyright 2015 - 2018 gtalent2@gmail.com
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#pragma once
#include <ox/std/error.hpp>
#include "desctypes.hpp"
namespace ox {
template<typename Reader, typename T>
class DataWalker {
template<typename ReaderBase, typename FH>
friend ox::Error parseField(const DescriptorField &field, ReaderBase *rdr, DataWalker<ReaderBase, FH> *walker);
private:
Vector<const DescriptorType*> m_typeStack;
T m_fieldHandler;
Vector<FieldName> m_path;
Vector<TypeName> m_typePath;
public:
DataWalker(DescriptorType *type, T fieldHandler);
[[nodiscard]] const DescriptorType *type() const noexcept;
ox::Error read(const DescriptorField&, Reader *rdr);
protected:
void pushNamePath(FieldName fn);
void popNamePath();
void pushType(const DescriptorType *type);
void popType();
};
template<typename Reader, typename T>
DataWalker<Reader, T>::DataWalker(DescriptorType *type, T fieldHandler): m_fieldHandler(fieldHandler) {
m_typeStack.push_back(type);
}
template<typename Reader, typename T>
const DescriptorType *DataWalker<Reader, T>::type() const noexcept {
return m_typeStack.back();
}
template<typename Reader, typename T>
ox::Error DataWalker<Reader, T>::read(const DescriptorField &f, Reader *rdr) {
// get const ref of paths
const auto &pathCr = m_path;
const auto &typePathCr = m_typePath;
return m_fieldHandler(pathCr, typePathCr, f, rdr);
}
template<typename Reader, typename T>
void DataWalker<Reader, T>::pushNamePath(FieldName fn) {
m_path.push_back(fn);
}
template<typename Reader, typename T>
void DataWalker<Reader, T>::popNamePath() {
m_path.pop_back();
}
template<typename Reader, typename T>
void DataWalker<Reader, T>::pushType(const DescriptorType *type) {
m_typeStack.push_back(type);
}
template<typename Reader, typename T>
void DataWalker<Reader, T>::popType() {
m_typeStack.pop_back();
}
template<typename Reader, typename FH>
static ox::Error parseField(const DescriptorField &field, Reader *rdr, DataWalker<Reader, FH> *walker) {
walker->pushNamePath(field.fieldName);
if (field.subscriptLevels) {
// add array handling
const auto arrayLen = rdr->arrayLength(true);
auto child = rdr->child();
child.setTypeInfo(field.fieldName.c_str(), arrayLen);
DescriptorField f(field); // create mutable copy
--f.subscriptLevels;
BString<100> subscript;
for (ArrayLength i = 0; i < arrayLen; i++) {
subscript = "[";
subscript += i;
subscript += "]";
walker->pushNamePath(subscript);
oxReturnError(parseField(f, &child, walker));
walker->popNamePath();
}
rdr->nextField();
} else {
switch (field.type->primitiveType) {
case PrimitiveType::UnsignedInteger:
case PrimitiveType::SignedInteger:
case PrimitiveType::Bool:
case PrimitiveType::String:
oxReturnError(walker->read(field, rdr));
break;
case PrimitiveType::Struct:
if (rdr->fieldPresent()) {
auto child = rdr->child();
walker->pushType(field.type);
oxReturnError(ioOp(&child, walker));
walker->popType();
rdr->nextField();
} else {
// skip and discard absent field
int discard;
oxReturnError(rdr->op("", &discard));
}
break;
}
}
walker->popNamePath();
return OxError(0);
}
template<typename Reader, typename FH>
ox::Error ioOp(Reader *rdr, DataWalker<Reader, FH> *walker) {
auto type = walker->type();
if (!type) {
return OxError(1);
}
auto typeName = type->typeName.c_str();
auto &fields = type->fieldList;
rdr->setTypeInfo(typeName, fields.size());
for (std::size_t i = 0; i < fields.size(); i++) {
oxReturnError(parseField(fields[i], rdr, walker));
}
return OxError(0);
}
}