From c4a1655a8f03e5481ea25dcbf1a99c160fe29f67 Mon Sep 17 00:00:00 2001 From: Gary Talent Date: Sun, 29 May 2022 22:21:05 -0500 Subject: [PATCH] [ox] Make model type version mandatory --- deps/ox/src/ox/fs/filesystem/filelocation.hpp | 26 ++++++++++--- deps/ox/src/ox/mc/read.hpp | 16 +++----- deps/ox/src/ox/mc/test/tests.cpp | 3 ++ deps/ox/src/ox/mc/write.hpp | 8 ++-- deps/ox/src/ox/model/desctypes.hpp | 4 +- deps/ox/src/ox/model/descwrite.hpp | 2 +- deps/ox/src/ox/model/fieldcounter.hpp | 35 ++++++++--------- deps/ox/src/ox/model/modelops.hpp | 8 ++-- deps/ox/src/ox/model/optype.hpp | 8 ---- deps/ox/src/ox/model/typenamecatcher.hpp | 7 +++- deps/ox/src/ox/model/walk.hpp | 39 ++++++++++--------- deps/ox/src/ox/oc/read.hpp | 4 ++ deps/ox/src/ox/oc/test/tests.cpp | 3 ++ deps/ox/src/ox/oc/write.hpp | 2 +- 14 files changed, 89 insertions(+), 76 deletions(-) diff --git a/deps/ox/src/ox/fs/filesystem/filelocation.hpp b/deps/ox/src/ox/fs/filesystem/filelocation.hpp index 20441f64..6eb76d5d 100644 --- a/deps/ox/src/ox/fs/filesystem/filelocation.hpp +++ b/deps/ox/src/ox/fs/filesystem/filelocation.hpp @@ -28,9 +28,11 @@ class FileAddress { public: static constexpr auto TypeName = "net.drinkingtea.ox.FileAddress"; + static constexpr auto TypeVersion = 1; union Data { static constexpr auto TypeName = "net.drinkingtea.ox.FileAddress.Data"; + static constexpr auto TypeVersion = 1; char *path = nullptr; const char *constPath; uint64_t inode; @@ -129,8 +131,14 @@ constexpr const char *getModelTypeName() noexcept { template constexpr Error model(T *io, FileAddress::Data *obj) noexcept { io->template setTypeInfo(); - oxReturnError(io->field("path", SerStr(&obj->path))); - oxReturnError(io->field("constPath", SerStr(&obj->path))); + if constexpr(ox_strcmp(T::opType(), OpType::Reflect) == 0) { + String dummy; + oxReturnError(io->field("path", &dummy)); + oxReturnError(io->field("constPath", &dummy)); + } else { + oxReturnError(io->field("path", SerStr(&obj->path))); + oxReturnError(io->field("constPath", SerStr(&obj->path))); + } oxReturnError(io->field("inode", &obj->inode)); return OxError(0); } @@ -138,10 +146,16 @@ constexpr Error model(T *io, FileAddress::Data *obj) noexcept { template constexpr Error model(T *io, FileAddress *fa) noexcept { io->template setTypeInfo(); - auto type = static_cast(fa->m_type); - oxReturnError(io->field("type", &type)); - fa->m_type = static_cast(type); - oxReturnError(io->field("data", UnionView(&fa->m_data, static_cast(fa->m_type)))); + if constexpr(ox_strcmp(T::opType(), OpType::Reflect) == 0) { + int8_t type = 0; + oxReturnError(io->field("type", &type)); + oxReturnError(io->field("data", UnionView(&fa->m_data, 0))); + } else { + auto type = static_cast(fa->m_type); + oxReturnError(io->field("type", &type)); + fa->m_type = static_cast(type); + oxReturnError(io->field("data", UnionView(&fa->m_data, static_cast(fa->m_type)))); + } return OxError(0); } diff --git a/deps/ox/src/ox/mc/read.hpp b/deps/ox/src/ox/mc/read.hpp index 8be2b6b0..b986f9b3 100644 --- a/deps/ox/src/ox/mc/read.hpp +++ b/deps/ox/src/ox/mc/read.hpp @@ -95,9 +95,7 @@ class MetalClawReader { StringLength stringLength(const char *name) noexcept; template - constexpr void setTypeInfo() noexcept; - - constexpr void setTypeInfo(const char *name, int fields) noexcept; + constexpr void setTypeInfo(const char *name = T::TypeName, int version = T::TypeVersion, int fields = ModelFieldCount_v) noexcept; /** * Returns a MetalClawReader to parse a child object. @@ -237,7 +235,7 @@ Error MetalClawReader::field(const char *name, T *val, std::size_t valLen) noexc // read the list if (valLen >= len) { auto reader = child(""); - reader.setTypeInfo("List", static_cast(len)); + reader.setTypeInfo("List", 0, static_cast(len)); for (std::size_t i = 0; i < len; ++i) { oxReturnError(reader.field("", &val[i])); } @@ -264,7 +262,7 @@ Error MetalClawReader::field(const char*, HashMap *val) noexcept { m_buffIt += bytesRead; // read the list auto reader = child(""); - reader.setTypeInfo("List", static_cast(len)); + reader.setTypeInfo("List", 0, static_cast(len)); for (std::size_t i = 0; i < len; ++i) { const auto keyLen = reader.stringLength(nullptr); auto wkey = ox_malloca(keyLen + 1, char, 0); @@ -292,7 +290,7 @@ Error MetalClawReader::field(const char*, Handler handler) noexcept { // read the list auto reader = child(""); - reader.setTypeInfo("List", static_cast(len)); + reader.setTypeInfo("List", 0, static_cast(len)); for (std::size_t i = 0; i < len; ++i) { T val; oxReturnError(reader.field("", &val)); @@ -305,11 +303,7 @@ Error MetalClawReader::field(const char*, Handler handler) noexcept { } template -constexpr void MetalClawReader::setTypeInfo() noexcept { - setTypeInfo(ModelTypeName_v, countFields()); -} - -constexpr void MetalClawReader::setTypeInfo(const char*, int fields) noexcept { +constexpr void MetalClawReader::setTypeInfo(const char*, int, int fields) noexcept { m_fields = fields; m_buffIt = static_cast((fields / 8 + 1) - (fields % 8 == 0)); m_fieldPresence.setFields(fields); diff --git a/deps/ox/src/ox/mc/test/tests.cpp b/deps/ox/src/ox/mc/test/tests.cpp index 299d080b..2a22df29 100644 --- a/deps/ox/src/ox/mc/test/tests.cpp +++ b/deps/ox/src/ox/mc/test/tests.cpp @@ -16,6 +16,7 @@ union TestUnion { static constexpr auto TypeName = "TestUnion"; + static constexpr auto TypeVersion = 1; bool Bool; uint32_t Int = 5; char CString[32]; @@ -23,6 +24,7 @@ union TestUnion { struct TestStructNest { static constexpr auto TypeName = "TestStructNest"; + static constexpr auto TypeVersion = 1; bool Bool = false; uint32_t Int = 0; ox::BString<32> BString = ""; @@ -30,6 +32,7 @@ struct TestStructNest { struct TestStruct { static constexpr auto TypeName = "TestStruct"; + static constexpr auto TypeVersion = 1; bool Bool = false; int32_t Int = 0; int32_t Int1 = 0; diff --git a/deps/ox/src/ox/mc/write.hpp b/deps/ox/src/ox/mc/write.hpp index 620abb43..893c8d6b 100644 --- a/deps/ox/src/ox/mc/write.hpp +++ b/deps/ox/src/ox/mc/write.hpp @@ -77,7 +77,7 @@ class MetalClawWriter { Error field(const char*, UnionView val) noexcept; template - void setTypeInfo(const char *name = T::TypeName, int fields = countFields()) noexcept; + void setTypeInfo(const char *name = T::TypeName, int version = T::TypeVersion, int fields = ModelFieldCount_v) noexcept; [[nodiscard]] std::size_t size() const noexcept; @@ -171,7 +171,7 @@ Error MetalClawWriter::field(const char*, T *val, std::size_t len) noexcept { } MetalClawWriter writer(m_buff + m_buffIt, m_buffLen - m_buffIt); - writer.setTypeInfo("List", len); + writer.setTypeInfo("List", 0, len); // write the array for (std::size_t i = 0; i < len; i++) { @@ -205,7 +205,7 @@ Error MetalClawWriter::field(const char*, HashMap *val) noexcept { MetalClawWriter writer(m_buff + m_buffIt, m_buffLen - m_buffIt); // double len for both key and value - writer.setTypeInfo("Map", len * 2); + writer.setTypeInfo("Map", 0, len * 2); // write the array for (std::size_t i = 0; i < len; i++) { @@ -245,7 +245,7 @@ Error MetalClawWriter::appendInteger(I val) noexcept { } template -void MetalClawWriter::setTypeInfo(const char*, int fields) noexcept { +void MetalClawWriter::setTypeInfo(const char*, int, int fields) noexcept { m_fields = fields; m_fieldPresence.setFields(fields); m_buffIt = static_cast(m_fieldPresence.getMaxLen()); diff --git a/deps/ox/src/ox/model/desctypes.hpp b/deps/ox/src/ox/model/desctypes.hpp index a924aee8..ec6d150a 100644 --- a/deps/ox/src/ox/model/desctypes.hpp +++ b/deps/ox/src/ox/model/desctypes.hpp @@ -85,6 +85,7 @@ struct DescriptorType { static constexpr auto TypeVersion = 2; String typeName; + int typeVersion = 0; PrimitiveType primitiveType = PrimitiveType::UnsignedInteger; // fieldList only applies to structs FieldList fieldList; @@ -117,6 +118,7 @@ template constexpr Error model(T *io, DescriptorType *type) noexcept { io->template setTypeInfo(); oxReturnError(io->field("typeName", &type->typeName)); + oxReturnError(io->field("typeVersion", &type->typeVersion)); if constexpr(ox_strcmp(T::opType(), "Reflect") == 0) { uint8_t pt = 0; oxReturnError(io->field("primitiveType", &pt)); @@ -148,7 +150,7 @@ class TypeDescReader; template constexpr Error model(TypeDescReader *io, DescriptorField *field) noexcept { - io->template setTypeInfo(DescriptorField::TypeName, 4); + io->template setTypeInfo(DescriptorField::TypeName, DescriptorField::TypeVersion, 4); oxReturnError(io->field("typeName", &field->typeName)); auto &typeStore = io->typeStore(); auto &[type, err] = typeStore->at(field->typeName).value; diff --git a/deps/ox/src/ox/model/descwrite.hpp b/deps/ox/src/ox/model/descwrite.hpp index 26eef4a9..58545052 100644 --- a/deps/ox/src/ox/model/descwrite.hpp +++ b/deps/ox/src/ox/model/descwrite.hpp @@ -59,7 +59,7 @@ class TypeDescWriter { constexpr Error field(const char *name, T *val) noexcept; template - constexpr void setTypeInfo(const char *name = T::TypeName, int fields = countFields()) noexcept; + constexpr void setTypeInfo(const char *name = T::TypeName, int fields = ModelFieldCount_v) noexcept; [[nodiscard]] constexpr DescriptorType *definition() noexcept { diff --git a/deps/ox/src/ox/model/fieldcounter.hpp b/deps/ox/src/ox/model/fieldcounter.hpp index 724bbf84..9f302b1c 100644 --- a/deps/ox/src/ox/model/fieldcounter.hpp +++ b/deps/ox/src/ox/model/fieldcounter.hpp @@ -15,29 +15,31 @@ namespace ox { +namespace detail { + template class FieldCounter { public: int fields = 0; template - constexpr void setTypeInfo(const char* = "", int = 0) { + constexpr void setTypeInfo(const char * = "", int = 0, int = 0) { } template - constexpr ox::Error field(const char*, U) noexcept { + constexpr ox::Error field(const char *, U) noexcept { ++fields; return OxError(0); } template - constexpr ox::Error field(const char*, U, std::size_t) noexcept { + constexpr ox::Error field(const char *, U, std::size_t) noexcept { ++fields; return OxError(0); } template - constexpr Error field(const char*, Handler) { + constexpr Error field(const char *, Handler) { ++fields; return OxError(0); } @@ -47,21 +49,16 @@ class FieldCounter { } }; -template -constexpr int countFields() noexcept { - if (std::is_constant_evaluated()) { - auto a = std::allocator(); - auto t = a.allocate(1); - FieldCounter c; - oxIgnoreError(model(&c, t)); - a.deallocate(t, 1); - return c.fields; - } else { - T t; - FieldCounter c; - oxIgnoreError(model(&c, &t)); - return c.fields; - } } +template +constexpr auto ModelFieldCount_v = [] { + auto a = std::allocator(); + auto t = a.allocate(1); + detail::FieldCounter c; + oxAssert(model(&c, t), "Count failed"); + a.deallocate(t, 1); + return c.fields; +}(); + } diff --git a/deps/ox/src/ox/model/modelops.hpp b/deps/ox/src/ox/model/modelops.hpp index 8d2a420c..98bbb5a0 100644 --- a/deps/ox/src/ox/model/modelops.hpp +++ b/deps/ox/src/ox/model/modelops.hpp @@ -52,7 +52,7 @@ class MemberList { } template - constexpr void setTypeInfo(const char* = T::TypeName, int = countFields()) noexcept { + constexpr void setTypeInfo(const char* = T::TypeName, int = ModelFieldCount_v) noexcept { } [[nodiscard]] @@ -172,7 +172,7 @@ class Mover { } template - constexpr void setTypeInfo(const char* = T::TypeName, int = countFields()) noexcept { + constexpr void setTypeInfo(const char* = T::TypeName, int = T::TypeVersion, int = ModelFieldCount_v) noexcept { } [[nodiscard]] @@ -262,7 +262,7 @@ class Equals { template constexpr void moveModel(T *dst, T *src) noexcept { - constexpr auto size = countFields(); + constexpr auto size = ModelFieldCount_v; detail::MemberList dstFields; detail::Mover mover(&dstFields); oxIgnoreError(model(&dstFields, dst)); @@ -271,7 +271,7 @@ constexpr void moveModel(T *dst, T *src) noexcept { template constexpr void copyModel(T *dst, const T *src) noexcept { - constexpr auto size = countFields(); + constexpr auto size = ModelFieldCount_v; detail::MemberList dstFields; detail::Copier copier(&dstFields); oxIgnoreError(model(&dstFields, dst)); diff --git a/deps/ox/src/ox/model/optype.hpp b/deps/ox/src/ox/model/optype.hpp index 5927b68e..e06409ab 100644 --- a/deps/ox/src/ox/model/optype.hpp +++ b/deps/ox/src/ox/model/optype.hpp @@ -17,7 +17,6 @@ namespace ox { namespace OpType { constexpr auto Read = "Read"; constexpr auto Write = "Write"; - constexpr auto WriteDefinition = "WriteDefinition"; constexpr auto Reflect = "Reflect"; } @@ -35,11 +34,6 @@ constexpr Error modelWrite(T*, O*) noexcept { return OxError(1, "Model: modelWrite not implemented"); } -template -constexpr Error modelWriteDefinition(T*, O*) noexcept { - return OxError(1, "Model: modelWriteDefinition not implemented"); -} - template constexpr Error modelReflect(T*, O*) noexcept { return OxError(1, "Model: modelReflect not implemented"); @@ -51,8 +45,6 @@ constexpr Error model(T *io, O *obj) noexcept { return modelRead(io, obj); } else if constexpr(ox_strcmp(T::opType(), OpType::Write) == 0) { return modelWrite(io, obj); - } else if constexpr(ox_strcmp(T::opType(), OpType::WriteDefinition) == 0) { - return modelWriteDefinition(io, obj); } else if constexpr(ox_strcmp(T::opType(), OpType::Reflect) == 0) { return modelReflect(io, obj); } else { diff --git a/deps/ox/src/ox/model/typenamecatcher.hpp b/deps/ox/src/ox/model/typenamecatcher.hpp index 46bdb4c9..10a693d1 100644 --- a/deps/ox/src/ox/model/typenamecatcher.hpp +++ b/deps/ox/src/ox/model/typenamecatcher.hpp @@ -59,7 +59,7 @@ struct TypeInfoCatcher { constexpr TypeInfoCatcher() noexcept = default; template - constexpr void setTypeInfo(const char *n = T::TypeName, int v = T::TypeVersion) noexcept { + constexpr void setTypeInfo(const char *n = T::TypeName, int v = T::TypeVersion, int = 0) noexcept { this->name = n; this->version = v; } @@ -80,7 +80,7 @@ struct TypeInfoCatcher { } static constexpr auto opType() noexcept { - return OpType::WriteDefinition; + return OpType::Reflect; } }; @@ -135,4 +135,7 @@ consteval auto requireModelTypeName() noexcept { template constexpr auto ModelTypeName_v = getModelTypeName(); +template +constexpr auto ModelTypeVersion_v = requireModelTypeVersion(); + } diff --git a/deps/ox/src/ox/model/walk.hpp b/deps/ox/src/ox/model/walk.hpp index 42ecc95b..21dcaaaa 100644 --- a/deps/ox/src/ox/model/walk.hpp +++ b/deps/ox/src/ox/model/walk.hpp @@ -17,7 +17,7 @@ namespace ox { template class DataWalker { template - friend Error parseField(const DescriptorField &field, ReaderBase *rdr, DataWalker *walker) noexcept; + friend constexpr Error parseField(const DescriptorField &field, ReaderBase *rdr, DataWalker *walker) noexcept; private: Vector m_typeStack; @@ -26,36 +26,36 @@ class DataWalker { Vector m_typePath; public: - DataWalker(DescriptorType *type, T fieldHandler) noexcept; + constexpr DataWalker(DescriptorType *type, T fieldHandler) noexcept; - Result type() const noexcept; + constexpr Result type() const noexcept; - Error read(const DescriptorField&, Reader *rdr) noexcept; + constexpr Error read(const DescriptorField&, Reader *rdr) noexcept; protected: - void pushNamePath(const FieldName &fn) noexcept; + constexpr void pushNamePath(const FieldName &fn) noexcept; - void popNamePath() noexcept; + constexpr void popNamePath() noexcept; - void pushType(const DescriptorType *type) noexcept; + constexpr void pushType(const DescriptorType *type) noexcept; - void popType() noexcept; + constexpr void popType() noexcept; }; template -DataWalker::DataWalker(DescriptorType *type, T fieldHandler) noexcept: m_fieldHandler(fieldHandler) { +constexpr DataWalker::DataWalker(DescriptorType *type, T fieldHandler) noexcept: m_fieldHandler(fieldHandler) { m_typeStack.push_back(type); } template -Result DataWalker::type() const noexcept { +constexpr Result DataWalker::type() const noexcept { oxRequire(out, m_typeStack.back()); return out; } template -Error DataWalker::read(const DescriptorField &f, Reader *rdr) noexcept { +constexpr Error DataWalker::read(const DescriptorField &f, Reader *rdr) noexcept { // get const ref of paths const auto &pathCr = m_path; const auto &typePathCr = m_typePath; @@ -63,33 +63,33 @@ Error DataWalker::read(const DescriptorField &f, Reader *rdr) noexcep } template -void DataWalker::pushNamePath(const FieldName &fn) noexcept { +constexpr void DataWalker::pushNamePath(const FieldName &fn) noexcept { m_path.push_back(fn); } template -void DataWalker::popNamePath() noexcept { +constexpr void DataWalker::popNamePath() noexcept { m_path.pop_back(); } template -void DataWalker::pushType(const DescriptorType *type) noexcept { +constexpr void DataWalker::pushType(const DescriptorType *type) noexcept { m_typeStack.push_back(type); } template -void DataWalker::popType() noexcept { +constexpr void DataWalker::popType() noexcept { m_typeStack.pop_back(); } template -static Error parseField(const DescriptorField &field, Reader *rdr, DataWalker *walker) noexcept { +static constexpr Error parseField(const DescriptorField &field, Reader *rdr, DataWalker *walker) noexcept { walker->pushNamePath(field.fieldName); if (field.subscriptLevels) { // add array handling oxRequire(arrayLen, rdr->arrayLength(field.fieldName.c_str(), true)); auto child = rdr->child(field.fieldName.c_str()); - child.setTypeInfo(field.fieldName.c_str(), arrayLen); + child.setTypeInfo(field.type->typeName.c_str(), field.type->typeVersion, arrayLen); DescriptorField f(field); // create mutable copy --f.subscriptLevels; String subscript; @@ -134,8 +134,9 @@ template constexpr Error model(Reader *rdr, DataWalker *walker) noexcept { oxRequire(type, walker->type()); auto typeName = type->typeName.c_str(); + auto typeVersion = type->typeVersion; auto &fields = type->fieldList; - rdr->setTypeInfo(typeName, fields.size()); + rdr->setTypeInfo(typeName, typeVersion, fields.size()); for (const auto &field : fields) { oxReturnError(parseField(field, rdr, walker)); } @@ -143,7 +144,7 @@ constexpr Error model(Reader *rdr, DataWalker *walker) noexcept { } template -Error walkModel(DescriptorType *type, const char *data, std::size_t dataLen, Handler handler) noexcept { +constexpr Error walkModel(DescriptorType *type, const char *data, std::size_t dataLen, Handler handler) noexcept { DataWalker walker(type, handler); Reader rdr(reinterpret_cast(data), dataLen); return model(&rdr, &walker); diff --git a/deps/ox/src/ox/oc/read.hpp b/deps/ox/src/ox/oc/read.hpp index 1da862f3..a491420b 100644 --- a/deps/ox/src/ox/oc/read.hpp +++ b/deps/ox/src/ox/oc/read.hpp @@ -96,6 +96,10 @@ class OrganicClawReader { constexpr void setTypeInfo(const char*, int) noexcept { } + template + constexpr void setTypeInfo(const char*, int, int) noexcept { + } + /** * Returns a OrganicClawReader to parse a child object. */ diff --git a/deps/ox/src/ox/oc/test/tests.cpp b/deps/ox/src/ox/oc/test/tests.cpp index 70b75c3c..540b9059 100644 --- a/deps/ox/src/ox/oc/test/tests.cpp +++ b/deps/ox/src/ox/oc/test/tests.cpp @@ -16,6 +16,7 @@ union TestUnion { static constexpr auto TypeName = "TestUnion"; + static constexpr auto TypeVersion = 1; bool Bool; uint32_t Int = 5; char String[32]; @@ -23,6 +24,7 @@ union TestUnion { struct TestStructNest { static constexpr auto TypeName = "TestStructNest"; + static constexpr auto TypeVersion = 1; bool Bool = false; uint32_t Int = 0; ox::BString<32> String = ""; @@ -30,6 +32,7 @@ struct TestStructNest { struct TestStruct { static constexpr auto TypeName = "TestStruct"; + static constexpr auto TypeVersion = 1; bool Bool = false; int32_t Int = 0; int32_t Int1 = 0; diff --git a/deps/ox/src/ox/oc/write.hpp b/deps/ox/src/ox/oc/write.hpp index 79713591..6a26c40f 100644 --- a/deps/ox/src/ox/oc/write.hpp +++ b/deps/ox/src/ox/oc/write.hpp @@ -69,7 +69,7 @@ class OrganicClawWriter { Error field(const char*, T *val) noexcept; template - constexpr void setTypeInfo(const char* = T::TypeName, int = countFields()) noexcept { + constexpr void setTypeInfo(const char* = T::TypeName, int = T::TypeVersion, int = ModelFieldCount_v) noexcept { } static constexpr auto opType() noexcept {