[ox] Make TypeStore own all type info

This commit is contained in:
Gary Talent 2022-05-28 19:55:46 -05:00
parent 440d9c0a46
commit 9c3a46d144
18 changed files with 312 additions and 258 deletions

View File

@ -72,7 +72,7 @@ template<typename T>
Result<T> readClaw(const char *buff, std::size_t buffLen) { Result<T> readClaw(const char *buff, std::size_t buffLen) {
T val; T val;
oxReturnError(readClaw(buff, buffLen, &val)); oxReturnError(readClaw(buff, buffLen, &val));
return std::move(val); return val;
} }
template<typename T> template<typename T>

View File

@ -16,7 +16,6 @@
union TestUnion { union TestUnion {
static constexpr auto TypeName = "TestUnion"; static constexpr auto TypeName = "TestUnion";
static constexpr auto Fields = 3;
bool Bool; bool Bool;
uint32_t Int = 5; uint32_t Int = 5;
char CString[32]; char CString[32];
@ -24,7 +23,6 @@ union TestUnion {
struct TestStructNest { struct TestStructNest {
static constexpr auto TypeName = "TestStructNest"; static constexpr auto TypeName = "TestStructNest";
static constexpr auto Fields = 3;
bool Bool = false; bool Bool = false;
uint32_t Int = 0; uint32_t Int = 0;
ox::BString<32> BString = ""; ox::BString<32> BString = "";
@ -32,7 +30,6 @@ struct TestStructNest {
struct TestStruct { struct TestStruct {
static constexpr auto TypeName = "TestStruct"; static constexpr auto TypeName = "TestStruct";
static constexpr auto Fields = 16;
bool Bool = false; bool Bool = false;
int32_t Int = 0; int32_t Int = 0;
int32_t Int1 = 0; int32_t Int1 = 0;
@ -272,7 +269,7 @@ std::map<ox::String, ox::Error(*)()> tests = {
[] { [] {
//constexpr size_t descBuffLen = 1024; //constexpr size_t descBuffLen = 1024;
//uint8_t descBuff[descBuffLen]; //uint8_t descBuff[descBuffLen];
static constexpr size_t dataBuffLen = 1024; static constexpr size_t dataBuffLen = ox::units::MB;
char dataBuff[dataBuffLen]; char dataBuff[dataBuffLen];
TestStruct testIn, testOut; TestStruct testIn, testOut;
testIn.Bool = true; testIn.Bool = true;
@ -286,10 +283,11 @@ std::map<ox::String, ox::Error(*)()> tests = {
testIn.Struct.Int = 300; testIn.Struct.Int = 300;
testIn.Struct.BString = "Test String 2"; testIn.Struct.BString = "Test String 2";
oxAssert(ox::writeMC(dataBuff, dataBuffLen, &testIn), "Data generation failed"); oxAssert(ox::writeMC(dataBuff, dataBuffLen, &testIn), "Data generation failed");
auto type = ox::buildTypeDef(&testIn); ox::TypeStore typeStore;
auto type = ox::buildTypeDef(&typeStore, &testIn);
oxAssert(type.error, "Descriptor write failed"); oxAssert(type.error, "Descriptor write failed");
oxReturnError(ox::walkModel<ox::MetalClawReader>(type.value.get(), dataBuff, dataBuffLen, oxReturnError(ox::walkModel<ox::MetalClawReader>(type.value, dataBuff, dataBuffLen,
[](const ox::Vector<ox::FieldName>&, const ox::Vector<ox::TypeName>&, const ox::DescriptorField &f, ox::MetalClawReader *rdr) -> ox::Error { [](const ox::Vector<ox::FieldName>&, const ox::Vector<ox::String>&, const ox::DescriptorField &f, ox::MetalClawReader *rdr) -> ox::Error {
//std::cout << f.fieldName.c_str() << '\n'; //std::cout << f.fieldName.c_str() << '\n';
auto fieldName = f.fieldName.c_str(); auto fieldName = f.fieldName.c_str();
switch (f.type->primitiveType) { switch (f.type->primitiveType) {
@ -360,10 +358,10 @@ std::map<ox::String, ox::Error(*)()> tests = {
break; break;
} }
case ox::PrimitiveType::String: { case ox::PrimitiveType::String: {
ox::Vector<char> v(rdr->stringLength(fieldName) + 1); ox::String s;
//std::cout << rdr->stringLength() << '\n'; //std::cout << rdr->stringLength() << '\n';
oxAssert(rdr->field(fieldName, ox::SerStr(v.data(), v.size())), "Walking model failed."); oxAssert(rdr->field(fieldName, &s), "Walking model failed.");
std::cout << fieldName << ":\t" << "string:\t\t" << v.data() << '\n'; oxOutf("{}:\tstring:\t\t{}\n", fieldName, s);
break; break;
} }
case ox::PrimitiveType::Struct: case ox::PrimitiveType::Struct:

View File

@ -30,6 +30,7 @@ install(
modelops.hpp modelops.hpp
typenamecatcher.hpp typenamecatcher.hpp
types.hpp types.hpp
typestore.hpp
walk.hpp walk.hpp
DESTINATION DESTINATION
include/ox/model include/ox/model

View File

@ -8,6 +8,7 @@
#pragma once #pragma once
#include "typestore.hpp"
#include "desctypes.hpp" #include "desctypes.hpp"
namespace ox { namespace ox {
@ -18,24 +19,25 @@ class TypeDescReader: public ReaderBase {
TypeStore m_typeStore; TypeStore m_typeStore;
public: public:
TypeDescReader(const uint8_t *buff, std::size_t buffLen) noexcept; constexpr TypeDescReader(const uint8_t *buff, std::size_t buffLen) noexcept;
[[nodiscard]] [[nodiscard]]
const TypeStore &typeStore() const noexcept; constexpr const auto &typeStore() const noexcept;
}; };
template<typename ReaderBase> template<typename ReaderBase>
TypeDescReader<ReaderBase>::TypeDescReader(const uint8_t *buff, std::size_t buffLen) noexcept: ReaderBase(buff, buffLen) { constexpr TypeDescReader<ReaderBase>::TypeDescReader(const uint8_t *buff, std::size_t buffLen) noexcept:
ReaderBase(buff, buffLen) {
} }
template<typename ReaderBase> template<typename ReaderBase>
const TypeStore &TypeDescReader<ReaderBase>::typeStore() const noexcept { constexpr const auto &TypeDescReader<ReaderBase>::typeStore() const noexcept {
return m_typeStore; return m_typeStore;
} }
template<typename ReaderBase, typename T> template<typename ReaderBase, typename T>
int readMCDef(const uint8_t *buff, std::size_t buffLen, T *val) noexcept { constexpr int readMCDef(const uint8_t *buff, std::size_t buffLen, T *val) noexcept {
TypeDescReader<ReaderBase> reader(buff, buffLen); TypeDescReader<ReaderBase> reader(buff, buffLen);
return model(&reader, val); return model(&reader, val);
} }

View File

@ -10,10 +10,4 @@
namespace ox { namespace ox {
DescriptorField::~DescriptorField() {
if (ownsType) {
safeDelete(type);
}
}
} }

View File

@ -11,6 +11,7 @@
#include <ox/std/bit.hpp> #include <ox/std/bit.hpp>
#include <ox/std/error.hpp> #include <ox/std/error.hpp>
#include <ox/std/hashmap.hpp> #include <ox/std/hashmap.hpp>
#include <ox/std/memory.hpp>
#include <ox/std/string.hpp> #include <ox/std/string.hpp>
#include <ox/std/vector.hpp> #include <ox/std/vector.hpp>
@ -19,7 +20,6 @@
namespace ox { namespace ox {
using FieldName = String; using FieldName = String;
using TypeName = String;
enum class PrimitiveType: uint8_t { enum class PrimitiveType: uint8_t {
UnsignedInteger = 0, UnsignedInteger = 0,
@ -34,82 +34,57 @@ enum class PrimitiveType: uint8_t {
struct DescriptorField { struct DescriptorField {
// order of fields matters // order of fields matters
static constexpr auto TypeName = "net.drinkingtea.ox.DescriptorField";
static constexpr auto TypeVersion = 1; static constexpr auto TypeVersion = 1;
// only serialize type name if type has already been serialized // do not serialize type
struct DescriptorType *type = nullptr; const struct DescriptorType *type = nullptr;
String fieldName; String fieldName;
int subscriptLevels = 0; int subscriptLevels = 0;
String typeName; // gives reference to type for lookup if type is null
// do not serialize the following
TypeName typeName; // gives reference to type for lookup if type is null
bool ownsType = false;
constexpr DescriptorField() noexcept = default; constexpr DescriptorField() noexcept = default;
/** constexpr DescriptorField(const DescriptorType *pType, String pFieldName,
* Allow for explicit copying. int pSubscriptLevels, String pTypeName) noexcept:
*/ type(pType),
constexpr DescriptorField(const DescriptorField &other) noexcept { fieldName(pFieldName),
type = other.type; subscriptLevels(pSubscriptLevels),
fieldName = other.fieldName; typeName(pTypeName) {
subscriptLevels = other.subscriptLevels;
typeName = other.typeName;
ownsType = false; // is copy, only owns type if move
} }
constexpr DescriptorField(DescriptorType *type, const String &fieldName, int subscriptLevels, const TypeName &typeName, bool ownsType) noexcept { constexpr DescriptorField(const DescriptorField &other) noexcept:
this->type = type; type(other.type),
this->fieldName = fieldName; fieldName(other.fieldName),
this->subscriptLevels = subscriptLevels; subscriptLevels(other.subscriptLevels),
this->typeName = typeName; typeName(other.typeName) {
this->ownsType = ownsType;
} }
constexpr DescriptorField(DescriptorField &&other) noexcept { constexpr DescriptorField(DescriptorField &&other) noexcept:
type = other.type; type(other.type),
fieldName = other.fieldName; fieldName(other.fieldName),
subscriptLevels = other.subscriptLevels; subscriptLevels(other.subscriptLevels),
typeName = other.typeName; typeName(std::move(other.typeName)) {
ownsType = other.ownsType;
other.type = {}; other.type = {};
other.fieldName = "";
other.subscriptLevels = {}; other.subscriptLevels = {};
other.typeName = "";
other.ownsType = {};
} }
~DescriptorField(); constexpr ~DescriptorField() noexcept = default;
const DescriptorField &operator=(const DescriptorField &other) noexcept { constexpr DescriptorField &operator=(const DescriptorField &other) noexcept = delete;
type = other.type;
fieldName = other.fieldName;
subscriptLevels = other.subscriptLevels;
typeName = other.typeName;
ownsType = other.ownsType;
return *this;
}
const DescriptorField &operator=(DescriptorField &&other) noexcept { constexpr DescriptorField &operator=(DescriptorField &&other) noexcept = delete;
type = std::move(other.type);
other.type = {};
fieldName = std::move(other.fieldName);
subscriptLevels = std::move(other.subscriptLevels);
other.subscriptLevels = {};
typeName = std::move(other.typeName);
ownsType = std::move(other.ownsType);
other.ownsType = {};
return *this;
}
}; };
using FieldList = Vector<DescriptorField>; using FieldList = Vector<DescriptorField>;
struct DescriptorType { struct DescriptorType {
static constexpr auto TypeName = "net.drinkingtea.ox.DescriptorType";
static constexpr auto TypeVersion = 1; static constexpr auto TypeVersion = 1;
TypeName typeName = "";
String typeName;
PrimitiveType primitiveType = PrimitiveType::UnsignedInteger; PrimitiveType primitiveType = PrimitiveType::UnsignedInteger;
// fieldList only applies to structs // fieldList only applies to structs
FieldList fieldList; FieldList fieldList;
@ -118,23 +93,33 @@ struct DescriptorType {
int64_t length = 0; int64_t length = 0;
bool preloadable = false; bool preloadable = false;
DescriptorType() = default; constexpr DescriptorType() noexcept = default;
DescriptorType(const TypeName &tn, PrimitiveType t, int b): typeName(tn), primitiveType(t), length(b) { constexpr explicit DescriptorType(String tn) noexcept: typeName(std::move(tn)) {
} }
DescriptorType(const TypeName &tn, PrimitiveType t, const FieldList &fl): typeName(tn), primitiveType(t), fieldList(fl) { constexpr DescriptorType(String tn, PrimitiveType t, int b) noexcept:
typeName(std::move(tn)),
primitiveType(t),
length(b) {
} }
constexpr DescriptorType(String tn, PrimitiveType t, FieldList fl) noexcept:
typeName(std::move(tn)),
primitiveType(t),
fieldList(std::move(fl)) {
}
}; };
template<typename T> template<typename T>
constexpr Error model(T *io, DescriptorType *type) noexcept { constexpr Error model(T *io, DescriptorType *type) noexcept {
io->template setTypeInfo<T>("net.drinkingtea.ox.DescriptorType", 5); io->template setTypeInfo<DescriptorType>();
oxReturnError(io->field("typeName", &type->typeName)); oxReturnError(io->field("typeName", &type->typeName));
auto pt = std::bit_cast<uint8_t>(type->primitiveType); auto pt = static_cast<uint8_t>(type->primitiveType);
oxReturnError(io->field("primitiveType", &pt)); oxReturnError(io->field("primitiveType", &pt));
type->primitiveType = std::bit_cast<PrimitiveType>(pt); type->primitiveType = static_cast<PrimitiveType>(pt);
oxReturnError(io->field("fieldList", &type->fieldList)); oxReturnError(io->field("fieldList", &type->fieldList));
oxReturnError(io->field("length", &type->length)); oxReturnError(io->field("length", &type->length));
oxReturnError(io->field("preloadable", &type->preloadable)); oxReturnError(io->field("preloadable", &type->preloadable));
@ -142,47 +127,34 @@ constexpr Error model(T *io, DescriptorType *type) noexcept {
} }
template<typename T> template<typename T>
Error modelWrite(T *io, DescriptorField *field) noexcept { constexpr Error model(T *io, DescriptorField *field) noexcept {
io->setTypeInfo("ox::DescriptorField", 4); io->template setTypeInfo<DescriptorField>(DescriptorField::TypeName, 4);
if (field->ownsType) { oxReturnError(io->field("typeName", &field->typeName));
String empty = "";
oxReturnError(io->field("typeName", &empty));
oxReturnError(io->field("type", field->type));
} else {
oxReturnError(io->field("typeName", &field->type->typeName));
oxReturnError(io->field("type", static_cast<decltype(field->type)>(nullptr)));
}
oxReturnError(io->field("fieldName", &field->fieldName)); oxReturnError(io->field("fieldName", &field->fieldName));
oxReturnError(io->field("subscriptLevels", &field->subscriptLevels));
// defaultValue is unused now, but leave placeholder for backwards compatibility // defaultValue is unused now, but leave placeholder for backwards compatibility
int DefaultValue = 0; int defaultValue = 0;
oxReturnError(io->field("defaultValue", &DefaultValue)); oxReturnError(io->field("defaultValue", &defaultValue));
return OxError(0); return OxError(0);
} }
template<typename ReaderBase>
class TypeDescReader;
template<typename T> template<typename T>
Error modelRead(T *io, DescriptorField *field) noexcept { constexpr Error model(TypeDescReader<T> *io, DescriptorField *field) noexcept {
auto &typeStore = io->typeStore(); io->template setTypeInfo<DescriptorField>(DescriptorField::TypeName, 4);
io->setTypeInfo("ox::DescriptorField", 4);
oxReturnError(io->field("typeName", &field->typeName)); oxReturnError(io->field("typeName", &field->typeName));
if (field->typeName == "") { auto &typeStore = io->typeStore();
field->ownsType = true; auto &[type, err] = typeStore->at(field->typeName).value;
if (field->type == nullptr) { oxReturnError(err);
field->type = new DescriptorType; field->type = type.get();
}
oxReturnError(io->field("type", field->type));
typeStore[field->type->typeName] = field->type;
} else {
// should be empty, so discard
DescriptorType t;
oxReturnError(io->field("type", &t));
field->type = typeStore[field->typeName];
}
oxReturnError(io->field("fieldName", &field->fieldName)); oxReturnError(io->field("fieldName", &field->fieldName));
oxReturnError(io->field("subscriptLevels", &field->subscriptLevels));
// defaultValue is unused now, but placeholder for backwards compatibility // defaultValue is unused now, but placeholder for backwards compatibility
oxReturnError(io->field("defaultValue", nullptr)); int defaultValue = 0;
oxReturnError(io->field("defaultValue", &defaultValue));
return OxError(0); return OxError(0);
} }
using TypeStore = HashMap<String, DescriptorType*>;
} }

View File

@ -47,116 +47,102 @@ static_assert([] {
return detail::indirectionLevels(i) == 1; return detail::indirectionLevels(i) == 1;
}(), "indirectionLevels broken: indirectionLevels(int[])"); }(), "indirectionLevels broken: indirectionLevels(int[])");
TypeDescWriter::TypeDescWriter(TypeStore *typeStore) noexcept { const DescriptorType *TypeDescWriter::type(int8_t*, bool *alreadyExisted) noexcept {
if (!typeStore) { constexpr auto String = "B:int8_t";
m_typeStoreOwnerRef = new TypeStore;
typeStore = m_typeStoreOwnerRef;
}
m_typeStore = typeStore;
}
TypeDescWriter::~TypeDescWriter() noexcept {
// does not own it's elements
safeDelete(m_typeStoreOwnerRef);
}
DescriptorType *TypeDescWriter::type(int8_t*, bool *alreadyExisted) noexcept {
constexpr auto TypeName = "B:int8_t";
constexpr auto PT = PrimitiveType::SignedInteger; constexpr auto PT = PrimitiveType::SignedInteger;
constexpr auto Bytes = 1; constexpr auto Bytes = 1;
return getType(TypeName, PT, Bytes, alreadyExisted); return getType(String, PT, Bytes, alreadyExisted);
} }
DescriptorType *TypeDescWriter::type(int16_t*, bool *alreadyExisted) noexcept { const DescriptorType *TypeDescWriter::type(int16_t*, bool *alreadyExisted) noexcept {
constexpr auto TypeName = "B:int16_t"; constexpr auto String = "B:int16_t";
constexpr auto PT = PrimitiveType::SignedInteger; constexpr auto PT = PrimitiveType::SignedInteger;
constexpr auto Bytes = 2; constexpr auto Bytes = 2;
return getType(TypeName, PT, Bytes, alreadyExisted); return getType(String, PT, Bytes, alreadyExisted);
} }
DescriptorType *TypeDescWriter::type(int32_t*, bool *alreadyExisted) noexcept { const DescriptorType *TypeDescWriter::type(int32_t*, bool *alreadyExisted) noexcept {
constexpr auto TypeName = "B:int32_t"; constexpr auto String = "B:int32_t";
constexpr auto PT = PrimitiveType::SignedInteger; constexpr auto PT = PrimitiveType::SignedInteger;
constexpr auto Bytes = 4; constexpr auto Bytes = 4;
return getType(TypeName, PT, Bytes, alreadyExisted); return getType(String, PT, Bytes, alreadyExisted);
} }
DescriptorType *TypeDescWriter::type(int64_t*, bool *alreadyExisted) noexcept { const DescriptorType *TypeDescWriter::type(int64_t*, bool *alreadyExisted) noexcept {
constexpr auto TypeName = "B:int64_t"; constexpr auto String = "B:int64_t";
constexpr auto PT = PrimitiveType::SignedInteger; constexpr auto PT = PrimitiveType::SignedInteger;
constexpr auto Bytes = 8; constexpr auto Bytes = 8;
return getType(TypeName, PT, Bytes, alreadyExisted); return getType(String, PT, Bytes, alreadyExisted);
} }
DescriptorType *TypeDescWriter::type(uint8_t*, bool *alreadyExisted) noexcept { const DescriptorType *TypeDescWriter::type(uint8_t*, bool *alreadyExisted) noexcept {
constexpr auto TypeName = "B:uint8_t"; constexpr auto String = "B:uint8_t";
constexpr auto PT = PrimitiveType::UnsignedInteger; constexpr auto PT = PrimitiveType::UnsignedInteger;
constexpr auto Bytes = 1; constexpr auto Bytes = 1;
return getType(TypeName, PT, Bytes, alreadyExisted); return getType(String, PT, Bytes, alreadyExisted);
} }
DescriptorType *TypeDescWriter::type(uint16_t*, bool *alreadyExisted) noexcept { const DescriptorType *TypeDescWriter::type(uint16_t*, bool *alreadyExisted) noexcept {
constexpr auto TypeName = "B:uint16_t"; constexpr auto String = "B:uint16_t";
constexpr auto PT = PrimitiveType::UnsignedInteger; constexpr auto PT = PrimitiveType::UnsignedInteger;
constexpr auto Bytes = 2; constexpr auto Bytes = 2;
return getType(TypeName, PT, Bytes, alreadyExisted); return getType(String, PT, Bytes, alreadyExisted);
} }
DescriptorType *TypeDescWriter::type(uint32_t*, bool *alreadyExisted) noexcept { const DescriptorType *TypeDescWriter::type(uint32_t*, bool *alreadyExisted) noexcept {
constexpr auto TypeName = "B:uint32_t"; constexpr auto String = "B:uint32_t";
constexpr auto PT = PrimitiveType::UnsignedInteger; constexpr auto PT = PrimitiveType::UnsignedInteger;
constexpr auto Bytes = 4; constexpr auto Bytes = 4;
return getType(TypeName, PT, Bytes, alreadyExisted); return getType(String, PT, Bytes, alreadyExisted);
} }
DescriptorType *TypeDescWriter::type(uint64_t*, bool *alreadyExisted) noexcept { const DescriptorType *TypeDescWriter::type(uint64_t*, bool *alreadyExisted) noexcept {
constexpr auto TypeName = "B:uint64_t"; constexpr auto String = "B:uint64_t";
constexpr auto PT = PrimitiveType::UnsignedInteger; constexpr auto PT = PrimitiveType::UnsignedInteger;
constexpr auto Bytes = 8; constexpr auto Bytes = 8;
return getType(TypeName, PT, Bytes, alreadyExisted); return getType(String, PT, Bytes, alreadyExisted);
} }
DescriptorType *TypeDescWriter::type(char*, bool *alreadyExisted) noexcept { const DescriptorType *TypeDescWriter::type(char*, bool *alreadyExisted) noexcept {
constexpr auto TypeName = "B:string"; constexpr auto String = "B:string";
constexpr auto PT = PrimitiveType::String; constexpr auto PT = PrimitiveType::String;
return getType(TypeName, PT, 0, alreadyExisted); return getType(String, PT, 0, alreadyExisted);
} }
DescriptorType *TypeDescWriter::type(SerStr, bool *alreadyExisted) noexcept { const DescriptorType *TypeDescWriter::type(SerStr, bool *alreadyExisted) noexcept {
constexpr auto TypeName = "B:string"; constexpr auto String = "B:string";
constexpr auto PT = PrimitiveType::String; constexpr auto PT = PrimitiveType::String;
return getType(TypeName, PT, 0, alreadyExisted); return getType(String, PT, 0, alreadyExisted);
} }
DescriptorType *TypeDescWriter::type(String*, bool *alreadyExisted) noexcept { const DescriptorType *TypeDescWriter::type(String*, bool *alreadyExisted) noexcept {
constexpr auto TypeName = "B:string"; constexpr auto String = "B:string";
constexpr auto PT = PrimitiveType::String; constexpr auto PT = PrimitiveType::String;
return getType(TypeName, PT, 0, alreadyExisted); return getType(String, PT, 0, alreadyExisted);
} }
DescriptorType *TypeDescWriter::type(bool*, bool *alreadyExisted) noexcept { const DescriptorType *TypeDescWriter::type(bool*, bool *alreadyExisted) noexcept {
constexpr auto TypeName = "B:bool"; constexpr auto String = "B:bool";
constexpr auto PT = PrimitiveType::Bool; constexpr auto PT = PrimitiveType::Bool;
constexpr auto Bytes = 0; constexpr auto Bytes = 0;
return getType(TypeName, PT, Bytes, alreadyExisted); return getType(String, PT, Bytes, alreadyExisted);
} }
DescriptorType *TypeDescWriter::getType(const TypeName &tn, PrimitiveType pt, int b, bool *alreadyExisted) noexcept { const DescriptorType *TypeDescWriter::getType(const String &tn, PrimitiveType pt, int b, bool *alreadyExisted) noexcept {
if (m_typeStore->contains(tn)) { auto t = m_typeStore->get(tn);
if (!t.error) {
*alreadyExisted = true; *alreadyExisted = true;
auto type = m_typeStore->operator[](tn); auto type = t.value;
oxAssert(type != nullptr, "TypeDescWriter::getType returning null DescriptorType"); oxAssert(type != nullptr, "TypeDescWriter::getType returning null DescriptorType");
return type; return type;
} else { } else {
*alreadyExisted = false; *alreadyExisted = false;
auto &t = m_typeStore->operator[](tn); auto dt = ox::make_unique<DescriptorType>(tn);
if (!t) { dt->primitiveType = pt;
t = new DescriptorType; dt->length = b;
} const auto out = dt.get();
t->typeName = tn; m_typeStore->set(tn, std::move(dt));
t->primitiveType = pt; return out;
t->length = b;
return t;
} }
} }

View File

@ -22,6 +22,7 @@
#include "optype.hpp" #include "optype.hpp"
#include "typenamecatcher.hpp" #include "typenamecatcher.hpp"
#include "types.hpp" #include "types.hpp"
#include "typestore.hpp"
namespace ox { namespace ox {
@ -42,28 +43,26 @@ static constexpr int indirectionLevels(T *t) noexcept {
class TypeDescWriter { class TypeDescWriter {
private: private:
TypeStore *m_typeStoreOwnerRef = nullptr;
TypeStore *m_typeStore = nullptr; TypeStore *m_typeStore = nullptr;
DescriptorType *m_type = nullptr; DescriptorType *m_type = nullptr;
public: public:
explicit TypeDescWriter(TypeStore *typeStore = nullptr) noexcept; explicit constexpr TypeDescWriter(TypeStore *typeStore = nullptr) noexcept;
~TypeDescWriter() noexcept;
template<typename T> template<typename T>
Error field(const char *name, T *val, std::size_t valLen) noexcept; constexpr Error field(const char *name, T *val, std::size_t valLen) noexcept;
template<typename T> template<typename T>
Error field(const char *name, T val) noexcept; constexpr Error field(const char *name, T val) noexcept;
template<typename T> template<typename T>
Error field(const char *name, T *val) noexcept; constexpr Error field(const char *name, T *val) noexcept;
template<typename T = std::nullptr_t> template<typename T = std::nullptr_t>
void setTypeInfo(const char *name = T::TypeName, int fields = countFields<T>()) noexcept; constexpr void setTypeInfo(const char *name = T::TypeName, int fields = countFields<T>()) noexcept;
[[nodiscard]] DescriptorType *definition() noexcept { [[nodiscard]]
constexpr DescriptorType *definition() noexcept {
return m_type; return m_type;
} }
@ -72,45 +71,48 @@ class TypeDescWriter {
} }
private: private:
DescriptorType *type(int8_t *val, bool *alreadyExisted) noexcept; const DescriptorType *type(int8_t *val, bool *alreadyExisted) noexcept;
DescriptorType *type(int16_t *val, bool *alreadyExisted) noexcept; const DescriptorType *type(int16_t *val, bool *alreadyExisted) noexcept;
DescriptorType *type(int32_t *val, bool *alreadyExisted) noexcept; const DescriptorType *type(int32_t *val, bool *alreadyExisted) noexcept;
DescriptorType *type(int64_t *val, bool *alreadyExisted) noexcept; const DescriptorType *type(int64_t *val, bool *alreadyExisted) noexcept;
DescriptorType *type(uint8_t *val, bool *alreadyExisted) noexcept; const DescriptorType *type(uint8_t *val, bool *alreadyExisted) noexcept;
DescriptorType *type(uint16_t *val, bool *alreadyExisted) noexcept; const DescriptorType *type(uint16_t *val, bool *alreadyExisted) noexcept;
DescriptorType *type(uint32_t *val, bool *alreadyExisted) noexcept; const DescriptorType *type(uint32_t *val, bool *alreadyExisted) noexcept;
DescriptorType *type(uint64_t *val, bool *alreadyExisted) noexcept; const DescriptorType *type(uint64_t *val, bool *alreadyExisted) noexcept;
DescriptorType *type(bool *val, bool *alreadyExisted) noexcept; const DescriptorType *type(bool *val, bool *alreadyExisted) noexcept;
DescriptorType *type(char *val, bool *alreadyExisted) noexcept; const DescriptorType *type(char *val, bool *alreadyExisted) noexcept;
DescriptorType *type(SerStr val, bool *alreadyExisted) noexcept; const DescriptorType *type(SerStr val, bool *alreadyExisted) noexcept;
DescriptorType *type(String *val, bool *alreadyExisted) noexcept; const DescriptorType *type(String *val, bool *alreadyExisted) noexcept;
template<std::size_t sz> template<std::size_t sz>
DescriptorType *type(BString<sz> *val, bool *alreadyExisted) noexcept; constexpr const DescriptorType *type(BString<sz> *val, bool *alreadyExisted) noexcept;
template<typename T> template<typename T>
DescriptorType *type(T *val, bool *alreadyExisted) noexcept; constexpr const DescriptorType *type(T *val, bool *alreadyExisted) noexcept;
template<typename T> template<typename T>
DescriptorType *type(Vector<T> *val, bool *alreadyExisted) noexcept; constexpr const DescriptorType *type(Vector<T> *val, bool *alreadyExisted) noexcept;
template<typename T> template<typename T>
DescriptorType *type(HashMap<String, T> *val, bool *alreadyExisted) noexcept; constexpr const DescriptorType *type(HashMap<String, T> *val, bool *alreadyExisted) noexcept;
template<typename U> template<typename U>
DescriptorType *type(UnionView<U> val, bool *alreadyExisted) noexcept; constexpr const DescriptorType *type(UnionView<U> val, bool *alreadyExisted) noexcept;
DescriptorType *getType(const TypeName &tn, PrimitiveType t, int b, bool *alreadyExisted) noexcept; const DescriptorType *getType(const String &tn, PrimitiveType t, int b, bool *alreadyExisted) noexcept;
}; };
constexpr TypeDescWriter::TypeDescWriter(TypeStore *typeStore) noexcept: m_typeStore(typeStore) {
}
// array handler // array handler
template<typename T> template<typename T>
Error TypeDescWriter::field(const char *name, T *val, std::size_t) noexcept { constexpr Error TypeDescWriter::field(const char *name, T *val, std::size_t) noexcept {
if (m_type) { if (m_type) {
constexpr typename remove_pointer<decltype(val)>::type *p = nullptr; constexpr typename remove_pointer<decltype(val)>::type *p = nullptr;
bool alreadyExisted = false; bool alreadyExisted = false;
@ -119,47 +121,47 @@ Error TypeDescWriter::field(const char *name, T *val, std::size_t) noexcept {
if (t == nullptr) { if (t == nullptr) {
type(p, &alreadyExisted); type(p, &alreadyExisted);
} }
m_type->fieldList.emplace_back(t, name, detail::indirectionLevels(val), alreadyExisted ? t->typeName : "", !alreadyExisted); m_type->fieldList.emplace_back(t, name, detail::indirectionLevels(val), alreadyExisted ? t->typeName : "");
return OxError(0); return OxError(0);
} }
return OxError(1); return OxError(1);
} }
template<typename T> template<typename T>
Error TypeDescWriter::field(const char *name, T val) noexcept { constexpr Error TypeDescWriter::field(const char *name, T val) noexcept {
if (m_type) { if (m_type) {
bool alreadyExisted = false; bool alreadyExisted = false;
const auto t = type(val, &alreadyExisted); const auto t = type(val, &alreadyExisted);
oxAssert(t != nullptr, "field(const char *name, T val): Type not found or generated"); oxAssert(t != nullptr, "field(const char *name, T val): Type not found or generated");
m_type->fieldList.emplace_back(t, name, 0, alreadyExisted ? t->typeName : "", !alreadyExisted); m_type->fieldList.emplace_back(t, name, 0, alreadyExisted ? t->typeName : "");
return OxError(0); return OxError(0);
} }
return OxError(1); return OxError(1);
} }
template<typename T> template<typename T>
Error TypeDescWriter::field(const char *name, T *val) noexcept { constexpr Error TypeDescWriter::field(const char *name, T *val) noexcept {
if (m_type) { if (m_type) {
bool alreadyExisted = false; bool alreadyExisted = false;
const auto t = type(val, &alreadyExisted); const auto t = type(val, &alreadyExisted);
oxAssert(t != nullptr, "field(const char *name, T *val): Type not found or generated"); oxAssert(t != nullptr, "field(const char *name, T *val): Type not found or generated");
m_type->fieldList.emplace_back(t, name, 0, alreadyExisted ? t->typeName : "", !alreadyExisted); m_type->fieldList.emplace_back(t, name, 0, t->typeName);
return OxError(0); return OxError(0);
} }
return OxError(1); return OxError(1);
} }
template<std::size_t sz> template<std::size_t sz>
DescriptorType *TypeDescWriter::type(BString<sz> *val, bool *alreadyExisted) noexcept { constexpr const DescriptorType *TypeDescWriter::type(BString<sz> *val, bool *alreadyExisted) noexcept {
return type(SerStr(val), alreadyExisted); return type(SerStr(val), alreadyExisted);
} }
template<typename T> template<typename T>
DescriptorType *TypeDescWriter::type(T *val, bool *alreadyExisted) noexcept { constexpr const DescriptorType *TypeDescWriter::type(T *val, bool *alreadyExisted) noexcept {
const auto name = getModelTypeName(val); auto [t, err] = m_typeStore->template get<T>();
if (m_typeStore->contains(name)) { if (!err) {
*alreadyExisted = true; *alreadyExisted = true;
return m_typeStore->operator[](name); return t;
} else { } else {
TypeDescWriter dw(m_typeStore); TypeDescWriter dw(m_typeStore);
oxLogError(model(&dw, val)); oxLogError(model(&dw, val));
@ -169,29 +171,24 @@ DescriptorType *TypeDescWriter::type(T *val, bool *alreadyExisted) noexcept {
} }
template<typename T> template<typename T>
DescriptorType *TypeDescWriter::type(Vector<T> *val, bool *alreadyExisted) noexcept { constexpr const DescriptorType *TypeDescWriter::type(Vector<T> *val, bool *alreadyExisted) noexcept {
return type(val->data(), alreadyExisted); return type(val->data(), alreadyExisted);
} }
template<typename T> template<typename T>
DescriptorType *TypeDescWriter::type(HashMap<String, T>*, bool *alreadyExisted) noexcept { constexpr const DescriptorType *TypeDescWriter::type(HashMap<String, T>*, bool *alreadyExisted) noexcept {
return type(static_cast<T*>(nullptr), alreadyExisted); return type(static_cast<T*>(nullptr), alreadyExisted);
} }
template<typename U> template<typename U>
DescriptorType *TypeDescWriter::type(UnionView<U> val, bool *alreadyExisted) noexcept { constexpr const DescriptorType *TypeDescWriter::type(UnionView<U> val, bool *alreadyExisted) noexcept {
return type(val.get(), alreadyExisted); return type(val.get(), alreadyExisted);
} }
template<typename T> template<typename T>
void TypeDescWriter::setTypeInfo(const char *name, int) noexcept { constexpr void TypeDescWriter::setTypeInfo(const char *name, int) noexcept {
auto &t = m_typeStore->operator[](name); m_type = m_typeStore->getInit(name);
if (!t) { if constexpr(is_union_v<T>) {
t = new DescriptorType;
}
m_type = t;
m_type->typeName = name;
if (is_union_v<T>) {
m_type->primitiveType = PrimitiveType::Union; m_type->primitiveType = PrimitiveType::Union;
} else { } else {
m_type->primitiveType = PrimitiveType::Struct; m_type->primitiveType = PrimitiveType::Struct;
@ -200,21 +197,16 @@ void TypeDescWriter::setTypeInfo(const char *name, int) noexcept {
} }
template<typename T> template<typename T>
Result<UniquePtr<DescriptorType>> buildTypeDef(T *val) noexcept { Result<DescriptorType*> buildTypeDef(TypeStore *typeStore, T *val) noexcept {
TypeDescWriter writer; TypeDescWriter writer(typeStore);
oxReturnError(model(&writer, val)); oxReturnError(model(&writer, val));
return UniquePtr<DescriptorType>{writer.definition()}; return writer.definition();
} }
Error writeTypeDef(uint8_t *buff, std::size_t buffLen, auto *val, std::size_t *sizeOut = nullptr) noexcept { auto writeTypeDefOC(auto *val) noexcept {
oxRequire(def, buildTypeDef(val)); TypeStore typeStore;
return writeType(buff, buffLen, def.get(), sizeOut); oxRequire(def, buildTypeDef(&typeStore, val));
} return writeOC(def.get());
Result<Buffer> writeTypeDef(auto *val) noexcept {
Buffer buff(units::MB);
oxReturnError(writeTypeDef(buff.data(), buff.size(), val));
return std::move(buff);
} }
} }

View File

@ -49,10 +49,19 @@ class FieldCounter {
template<typename T> template<typename T>
constexpr int countFields() noexcept { constexpr int countFields() noexcept {
T t; if (std::is_constant_evaluated()) {
FieldCounter<T> c; auto a = std::allocator<T>();
oxIgnoreError(model(&c, &t)); auto t = a.allocate(1);
return c.fields; FieldCounter<T> c;
oxIgnoreError(model(&c, t));
a.deallocate(t, 1);
return c.fields;
} else {
T t;
FieldCounter<T> c;
oxIgnoreError(model(&c, &t));
return c.fields;
}
} }
} }

View File

@ -16,4 +16,5 @@
#include "modelops.hpp" #include "modelops.hpp"
#include "typenamecatcher.hpp" #include "typenamecatcher.hpp"
#include "types.hpp" #include "types.hpp"
#include "typestore.hpp"
#include "walk.hpp" #include "walk.hpp"

View File

@ -13,6 +13,7 @@
#include <ox/std/types.hpp> #include <ox/std/types.hpp>
#include <ox/std/utility.hpp> #include <ox/std/utility.hpp>
#include "fieldcounter.hpp"
#include "types.hpp" #include "types.hpp"
namespace ox { namespace ox {
@ -51,7 +52,7 @@ class MemberList {
} }
template<typename T = void> template<typename T = void>
constexpr void setTypeInfo(const char* = T::TypeName, int = T::Fields) noexcept { constexpr void setTypeInfo(const char* = T::TypeName, int = countFields<T>()) noexcept {
} }
[[nodiscard]] [[nodiscard]]
@ -171,7 +172,7 @@ class Mover {
} }
template<typename T = void> template<typename T = void>
constexpr void setTypeInfo(const char* = T::TypeName, int = T::Fields) noexcept { constexpr void setTypeInfo(const char* = T::TypeName, int = countFields<T>()) noexcept {
} }
[[nodiscard]] [[nodiscard]]
@ -261,7 +262,7 @@ class Equals {
template<typename T> template<typename T>
constexpr void moveModel(T *dst, T *src) noexcept { constexpr void moveModel(T *dst, T *src) noexcept {
constexpr auto size = T::Fields; constexpr auto size = countFields<T>();
detail::MemberList<size> dstFields; detail::MemberList<size> dstFields;
detail::Mover<size> mover(&dstFields); detail::Mover<size> mover(&dstFields);
oxIgnoreError(model(&dstFields, dst)); oxIgnoreError(model(&dstFields, dst));
@ -270,7 +271,7 @@ constexpr void moveModel(T *dst, T *src) noexcept {
template<typename T> template<typename T>
constexpr void copyModel(T *dst, const T *src) noexcept { constexpr void copyModel(T *dst, const T *src) noexcept {
constexpr auto size = T::Fields; constexpr auto size = countFields<T>();
detail::MemberList<size> dstFields; detail::MemberList<size> dstFields;
detail::Copier<size> copier(&dstFields); detail::Copier<size> copier(&dstFields);
oxIgnoreError(model(&dstFields, dst)); oxIgnoreError(model(&dstFields, dst));

View File

@ -129,7 +129,6 @@ constexpr Str getModelTypeName(T *val) noexcept {
template<typename T> template<typename T>
consteval auto requireModelTypeName() noexcept { consteval auto requireModelTypeName() noexcept {
constexpr auto name = getModelTypeName<T>(); constexpr auto name = getModelTypeName<T>();
static_assert(ox_strcmp(name, "") != 0, "TypeName is required");
return name; return name;
} }

View File

@ -76,6 +76,12 @@ class SerStr {
m_cap = cap; m_cap = cap;
} }
explicit constexpr SerStr(char *str, char **tgt, int cap = -1) noexcept {
m_tgt = tgt;
m_str = str;
m_cap = cap;
}
template<std::size_t cap> template<std::size_t cap>
explicit constexpr SerStr(char (&str)[cap]) noexcept { explicit constexpr SerStr(char (&str)[cap]) noexcept {
m_str = str; m_str = str;

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

@ -0,0 +1,96 @@
/*
* Copyright 2015 - 2022 gary@drinkingtea.net
*
* 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/hashmap.hpp>
#include <ox/std/memory.hpp>
#include <ox/std/string.hpp>
#include "typenamecatcher.hpp"
#include "desctypes.hpp"
namespace ox {
class TypeStore {
private:
HashMap<String, UniquePtr<DescriptorType>> m_cache;
public:
constexpr TypeStore() noexcept = default;
constexpr virtual ~TypeStore() noexcept = default;
constexpr Result<DescriptorType*> get(const auto &name) const noexcept {
oxRequire(out, m_cache.at(name));
return out->get();
}
template<typename T>
constexpr Result<DescriptorType*> get() const noexcept {
constexpr auto name = requireModelTypeName<T>();
oxRequire(out, m_cache.at(name));
return out->get();
}
constexpr DescriptorType *getInit(const auto &name) noexcept {
auto [out, err] = m_cache.at(name);
if (err) {
auto &out = m_cache[name];
out = ox::make_unique<DescriptorType>(name);
return out.get();
}
return out->get();
}
template<typename T>
constexpr DescriptorType *getInit() noexcept {
constexpr auto name = requireModelTypeName<T>();
return getInit(name);
}
template<typename T>
constexpr Result<DescriptorType*> getLoad() noexcept {
constexpr auto nameCstr = requireModelTypeName<T>();
const String name = nameCstr;
auto [val, err] = m_cache.at(name);
if (err) {
oxRequireM(dt, loadDescriptor(name));
auto &out = m_cache[name];
out = std::move(dt);
return out.get();
}
return val->get();
}
constexpr void set(const String &name, UniquePtr<DescriptorType> dt) noexcept {
m_cache[name] = std::move(dt);
}
constexpr void set(const String &name, DescriptorType *dt) noexcept {
m_cache[name] = UniquePtr<DescriptorType>(dt);
}
[[nodiscard]]
constexpr auto typeList() const noexcept {
auto keys = m_cache.keys();
ox::Vector<DescriptorType*> descs;
for (const auto &k : keys) {
descs.emplace_back(m_cache.at(k).value->get());
}
return descs;
}
protected:
constexpr virtual Result<UniquePtr<DescriptorType>> loadDescriptor(const ox::String&) noexcept {
return OxError(1);
}
};
}

View File

@ -23,7 +23,7 @@ class DataWalker {
Vector<const DescriptorType*> m_typeStack; Vector<const DescriptorType*> m_typeStack;
T m_fieldHandler; T m_fieldHandler;
Vector<FieldName> m_path; Vector<FieldName> m_path;
Vector<TypeName> m_typePath; Vector<String> m_typePath;
public: public:
DataWalker(DescriptorType *type, T fieldHandler) noexcept; DataWalker(DescriptorType *type, T fieldHandler) noexcept;

View File

@ -16,7 +16,6 @@
union TestUnion { union TestUnion {
static constexpr auto TypeName = "TestUnion"; static constexpr auto TypeName = "TestUnion";
static constexpr auto Fields = 3;
bool Bool; bool Bool;
uint32_t Int = 5; uint32_t Int = 5;
char String[32]; char String[32];
@ -24,7 +23,6 @@ union TestUnion {
struct TestStructNest { struct TestStructNest {
static constexpr auto TypeName = "TestStructNest"; static constexpr auto TypeName = "TestStructNest";
static constexpr auto Fields = 3;
bool Bool = false; bool Bool = false;
uint32_t Int = 0; uint32_t Int = 0;
ox::BString<32> String = ""; ox::BString<32> String = "";
@ -32,7 +30,6 @@ struct TestStructNest {
struct TestStruct { struct TestStruct {
static constexpr auto TypeName = "TestStruct"; static constexpr auto TypeName = "TestStruct";
static constexpr auto Fields = 17;
bool Bool = false; bool Bool = false;
int32_t Int = 0; int32_t Int = 0;
int32_t Int1 = 0; int32_t Int1 = 0;
@ -44,7 +41,6 @@ struct TestStruct {
int32_t Int7 = 0; int32_t Int7 = 0;
int32_t Int8 = 0; int32_t Int8 = 0;
TestUnion Union; TestUnion Union;
char *CString = nullptr;
ox::BString<32> String = ""; ox::BString<32> String = "";
uint32_t List[4] = {0, 0, 0, 0}; uint32_t List[4] = {0, 0, 0, 0};
ox::HashMap<ox::String, int> Map; ox::HashMap<ox::String, int> Map;
@ -55,8 +51,7 @@ struct TestStruct {
TestStruct(TestStruct &&other) noexcept; TestStruct(TestStruct &&other) noexcept;
~TestStruct() noexcept { constexpr ~TestStruct() noexcept {
delete[] CString;
} }
constexpr TestStruct &operator=(TestStruct&&) noexcept; constexpr TestStruct &operator=(TestStruct&&) noexcept;
@ -95,7 +90,6 @@ constexpr ox::Error model(T *io, TestStruct *obj) noexcept {
oxReturnError(io->field("Int7", &obj->Int7)); oxReturnError(io->field("Int7", &obj->Int7));
oxReturnError(io->field("Int8", &obj->Int8)); oxReturnError(io->field("Int8", &obj->Int8));
oxReturnError(io->field("Union", ox::UnionView{&obj->Union, 1})); oxReturnError(io->field("Union", ox::UnionView{&obj->Union, 1}));
oxReturnError(io->field("CString", ox::SerStr(&obj->CString)));
oxReturnError(io->field("String", &obj->String)); oxReturnError(io->field("String", &obj->String));
oxReturnError(io->field("List", obj->List, 4)); oxReturnError(io->field("List", obj->List, 4));
oxReturnError(io->field("Map", &obj->Map)); oxReturnError(io->field("Map", &obj->Map));
@ -132,8 +126,6 @@ const std::map<std::string_view, ox::Error(*)()> tests = {
testIn.Int = 42; testIn.Int = 42;
testIn.Union.Int = 52; testIn.Union.Int = 52;
testIn.String = "Test String 1"; testIn.String = "Test String 1";
testIn.CString = new char[ox_strlen("c-string") + 1];
ox_strcpy(testIn.CString, "c-string");
testIn.List[0] = 1; testIn.List[0] = 1;
testIn.List[1] = 2; testIn.List[1] = 2;
testIn.List[2] = 3; testIn.List[2] = 3;
@ -160,7 +152,6 @@ const std::map<std::string_view, ox::Error(*)()> tests = {
oxAssert(testIn.Int6 == testOut.Int6, "Int6 value mismatch"); oxAssert(testIn.Int6 == testOut.Int6, "Int6 value mismatch");
oxAssert(testIn.Int7 == testOut.Int7, "Int7 value mismatch"); oxAssert(testIn.Int7 == testOut.Int7, "Int7 value mismatch");
oxAssert(testIn.Int8 == testOut.Int8, "Int8 value mismatch"); oxAssert(testIn.Int8 == testOut.Int8, "Int8 value mismatch");
oxAssert(ox_strcmp(testIn.CString, testOut.CString) == 0, "CString value mismatch");
oxAssert(testIn.Union.Int == testOut.Union.Int, "Union.Int value mismatch"); oxAssert(testIn.Union.Int == testOut.Union.Int, "Union.Int value mismatch");
oxAssert(testIn.String == testOut.String, "String value mismatch"); oxAssert(testIn.String == testOut.String, "String value mismatch");
oxAssert(testIn.List[0] == testOut.List[0], "List[0] value mismatch"); oxAssert(testIn.List[0] == testOut.List[0], "List[0] value mismatch");
@ -197,10 +188,12 @@ const std::map<std::string_view, ox::Error(*)()> tests = {
auto [oc, ocErr] = ox::writeOC(&testIn); auto [oc, ocErr] = ox::writeOC(&testIn);
oxAssert(ocErr, "Data generation failed"); oxAssert(ocErr, "Data generation failed");
auto type = ox::buildTypeDef(&testIn); ox::TypeStore typeStore;
auto type = ox::buildTypeDef(&typeStore, &testIn);
oxAssert(type.error, "Descriptor write failed"); oxAssert(type.error, "Descriptor write failed");
oxReturnError(ox::walkModel<ox::OrganicClawReader>(type.value.get(), oc.data(), oc.size(), oxReturnError(ox::walkModel<ox::OrganicClawReader>(type.value, oc.data(), oc.size(),
[](const ox::Vector<ox::FieldName>&, const ox::Vector<ox::TypeName>&, const ox::DescriptorField &f, ox::OrganicClawReader *rdr) -> ox::Error { [](const ox::Vector<ox::FieldName>&, const ox::Vector<ox::String>&, const ox::DescriptorField &f,
ox::OrganicClawReader *rdr) -> ox::Error {
auto fieldName = f.fieldName.c_str(); auto fieldName = f.fieldName.c_str();
switch (f.type->primitiveType) { switch (f.type->primitiveType) {
case ox::PrimitiveType::UnsignedInteger: case ox::PrimitiveType::UnsignedInteger:

View File

@ -36,7 +36,7 @@ constexpr void assertFunc(const char *file, int line, bool pass, [[maybe_unused]
if (!pass) { if (!pass) {
if (!std::is_constant_evaluated()) { if (!std::is_constant_evaluated()) {
#ifdef OX_USE_STDLIB #ifdef OX_USE_STDLIB
oxErrf("\033[31;1;1mASSERT FAILURE:\033[0m [{}:{}]: {}\n", file, line, msg); oxErrf("\n\033[31;1;1mASSERT FAILURE:\033[0m [{}:{}]: {}\n", file, line, msg);
printStackTrace(2); printStackTrace(2);
oxTracef("assert", "Failed assert: {} ({}) [{}:{}]", msg, assertTxt, file, line); oxTracef("assert", "Failed assert: {} ({}) [{}:{}]", msg, assertTxt, file, line);
std::abort(); std::abort();
@ -53,7 +53,7 @@ constexpr void assertFunc(const char *file, int line, const Error &err, const ch
if (err) { if (err) {
if (!std::is_constant_evaluated()) { if (!std::is_constant_evaluated()) {
#if defined(OX_USE_STDLIB) #if defined(OX_USE_STDLIB)
oxErrf("\033[31;1;1mASSERT FAILURE:\033[0m [{}:{}]: {}\n", file, line, assertMsg); oxErrf("\n\033[31;1;1mASSERT FAILURE:\033[0m [{}:{}]: {}\n", file, line, assertMsg);
if (err.msg) { if (err.msg) {
oxErrf("\tError Message:\t{}\n", err.msg); oxErrf("\tError Message:\t{}\n", err.msg);
} }

View File

@ -135,6 +135,10 @@ struct [[nodiscard]] Result {
constexpr Result(const Result<U> &other) noexcept: value(other.value), error(other.error) { constexpr Result(const Result<U> &other) noexcept: value(other.value), error(other.error) {
} }
template<typename U>
constexpr Result(const Result<U> &&other) noexcept: value(std::move(other.value)), error(std::move(other.error)) {
}
constexpr Result(const Error &error) noexcept: error(error) { constexpr Result(const Error &error) noexcept: error(error) {
} }