[ox/mc] Make MC Write use Writer_c

This commit is contained in:
Gary Talent 2023-06-08 00:56:02 -05:00
parent ae3f0bb5db
commit ce4dcdcd18
6 changed files with 150 additions and 137 deletions

View File

@ -158,12 +158,10 @@ static std::map<std::string_view, ox::Error(*)()> tests = {
testIn.Struct.Bool = false; testIn.Struct.Bool = false;
testIn.Struct.Int = 300; testIn.Struct.Int = 300;
testIn.Struct.String = "Test String 2"; testIn.Struct.String = "Test String 2";
const auto [buff, err] = ox::writeMC(&testIn);
auto [buff, err] = ox::writeClaw(&testIn, ox::ClawFormat::Metal); oxAssert(err, "writeClaw failed");
oxAssert(err, "writeMC failed"); oxAssert(ox::readMC(buff.data(), buff.size(), &testOut), "readClaw failed");
oxAssert(ox::readClaw(buff.data(), buff.size(), &testOut), "readMC failed");
//std::cout << testIn.Union.Int << "|" << testOut.Union.Int << "|\n"; //std::cout << testIn.Union.Int << "|" << testOut.Union.Int << "|\n";
oxAssert(testIn.Bool == testOut.Bool, "Bool value mismatch"); oxAssert(testIn.Bool == testOut.Bool, "Bool value mismatch");
oxAssert(testIn.Int == testOut.Int, "Int value mismatch"); oxAssert(testIn.Int == testOut.Int, "Int value mismatch");
oxAssert(testIn.Int1 == testOut.Int1, "Int1 value mismatch"); oxAssert(testIn.Int1 == testOut.Int1, "Int1 value mismatch");

View File

@ -24,6 +24,8 @@ class FieldBitmapReader {
public: public:
constexpr FieldBitmapReader(T map, std::size_t maxLen) noexcept; constexpr FieldBitmapReader(T map, std::size_t maxLen) noexcept;
constexpr auto setBuffer(T map, std::size_t maxLen) noexcept;
constexpr Result<bool> get(std::size_t i) const noexcept; constexpr Result<bool> get(std::size_t i) const noexcept;
constexpr void setFields(int) noexcept; constexpr void setFields(int) noexcept;
@ -41,6 +43,12 @@ constexpr FieldBitmapReader<T>::FieldBitmapReader(T map, std::size_t maxLen) noe
m_mapLen = maxLen; m_mapLen = maxLen;
} }
template<typename T>
constexpr auto FieldBitmapReader<T>::setBuffer(T map, std::size_t maxLen) noexcept {
m_map = map;
m_mapLen = maxLen;
}
template<typename T> template<typename T>
constexpr Result<bool> FieldBitmapReader<T>::get(std::size_t i) const noexcept { constexpr Result<bool> FieldBitmapReader<T>::get(std::size_t i) const noexcept {
if (i / 8 < m_mapLen) { if (i / 8 < m_mapLen) {

View File

@ -122,8 +122,6 @@ std::map<ox::String, ox::Error(*)()> tests = {
"MetalClawReader", "MetalClawReader",
[] { [] {
// setup for tests // setup for tests
static constexpr size_t buffLen = 1024;
char buff[buffLen];
TestStruct testIn, testOut; TestStruct testIn, testOut;
testIn.Bool = true; testIn.Bool = true;
testIn.Int = 42; testIn.Int = 42;
@ -140,8 +138,9 @@ 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";
// run tests // run tests
oxAssert(ox::writeMC(buff, buffLen, &testIn), "writeMC failed"); const auto [buff, err] = ox::writeMC(&testIn);
oxAssert(ox::readMC(buff, buffLen, &testOut), "readMC failed"); oxAssert(err, "writeMC failed");
oxAssert(ox::readMC(buff.data(), buff.size(), &testOut), "readMC failed");
//std::cout << testIn.Union.Int << "|" << testOut.Union.Int << "|\n"; //std::cout << testIn.Union.Int << "|" << testOut.Union.Int << "|\n";
oxAssert(testIn.Bool == testOut.Bool, "Bool value mismatch"); oxAssert(testIn.Bool == testOut.Bool, "Bool value mismatch");
oxAssert(testIn.Int == testOut.Int, "Int value mismatch"); oxAssert(testIn.Int == testOut.Int, "Int value mismatch");

View File

@ -15,6 +15,7 @@
namespace ox { namespace ox {
template class ModelHandlerInterface<MetalClawWriter>; template class ModelHandlerInterface<MetalClawWriter<BufferWriter>>;
template class ModelHandlerInterface<MetalClawWriter<CharBuffWriter>>;
} }

View File

@ -27,19 +27,19 @@
namespace ox { namespace ox {
template<Writer_c Writer>
class MetalClawWriter { class MetalClawWriter {
private: private:
ox::Vector<uint8_t, 16> m_presenceMapBuff;
FieldBitmap m_fieldPresence; FieldBitmap m_fieldPresence;
int m_fields = 0;
int m_field = 0; int m_field = 0;
int m_unionIdx = -1; int m_unionIdx = -1;
std::size_t m_buffIt = 0; std::size_t m_writerBeginP{};
std::size_t m_buffLen = 0; Writer &m_writer;
uint8_t *m_buff = nullptr;
public: public:
constexpr MetalClawWriter(uint8_t *buff, std::size_t buffLen, int unionIdx = -1) noexcept; constexpr explicit MetalClawWriter(Writer &writer, int unionIdx = -1) noexcept;
constexpr ~MetalClawWriter() noexcept = default; constexpr ~MetalClawWriter() noexcept = default;
@ -122,77 +122,81 @@ class MetalClawWriter {
return 0; return 0;
} }
[[nodiscard]]
constexpr std::size_t size() const noexcept;
[[nodiscard]] [[nodiscard]]
static constexpr auto opType() noexcept { static constexpr auto opType() noexcept {
return OpType::Write; return OpType::Write;
} }
ox::Error finalize() noexcept;
private: private:
constexpr Error appendInteger(Integer_c auto val) noexcept { constexpr Error appendInteger(Integer_c auto val) noexcept {
bool fieldSet = false; bool fieldSet = false;
if (val && (m_unionIdx == -1 || m_unionIdx == m_field)) { if (val && (m_unionIdx == -1 || m_unionIdx == m_field)) {
auto mi = mc::encodeInteger(val); auto mi = mc::encodeInteger(val);
if (mi.length < m_buffLen) { oxReturnError(m_writer.write(reinterpret_cast<const char*>(mi.data), mi.length));
fieldSet = true; fieldSet = true;
ox_memcpy(&m_buff[m_buffIt], mi.data, mi.length);
m_buffIt += mi.length;
} else {
return OxError(MC_BUFFENDED);
}
} }
oxReturnError(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet)); oxReturnError(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet));
m_field++; ++m_field;
return OxError(0); return OxError(0);
} }
}; };
extern template class ModelHandlerInterface<MetalClawWriter>; extern template class ModelHandlerInterface<MetalClawWriter<BufferWriter>>;
extern template class ModelHandlerInterface<MetalClawWriter<CharBuffWriter>>;
constexpr MetalClawWriter::MetalClawWriter(uint8_t *buff, std::size_t buffLen, int unionIdx) noexcept: template<Writer_c Writer>
m_fieldPresence(buff, buffLen), constexpr MetalClawWriter<Writer>::MetalClawWriter(Writer &writer, int unionIdx) noexcept:
m_fieldPresence(m_presenceMapBuff.data(), m_presenceMapBuff.size()),
m_unionIdx(unionIdx), m_unionIdx(unionIdx),
m_buffLen(buffLen), m_writerBeginP(writer.tellp()),
m_buff(buff) { m_writer(writer) {
} }
constexpr Error MetalClawWriter::field(const char*, CommonPtrWith<int8_t> auto *val) noexcept { template<Writer_c Writer>
constexpr Error MetalClawWriter<Writer>::field(const char*, CommonPtrWith<int8_t> auto *val) noexcept {
return appendInteger(*val); return appendInteger(*val);
} }
constexpr Error MetalClawWriter::field(const char*, CommonPtrWith<int16_t> auto *val) noexcept { template<Writer_c Writer>
constexpr Error MetalClawWriter<Writer>::field(const char*, CommonPtrWith<int16_t> auto *val) noexcept {
return appendInteger(*val); return appendInteger(*val);
} }
constexpr Error MetalClawWriter::field(const char*, CommonPtrWith<int32_t> auto *val) noexcept { template<Writer_c Writer>
constexpr Error MetalClawWriter<Writer>::field(const char*, CommonPtrWith<int32_t> auto *val) noexcept {
return appendInteger(*val); return appendInteger(*val);
} }
constexpr Error MetalClawWriter::field(const char*, CommonPtrWith<int64_t> auto *val) noexcept { template<Writer_c Writer>
constexpr Error MetalClawWriter<Writer>::field(const char*, CommonPtrWith<int64_t> auto *val) noexcept {
return appendInteger(*val); return appendInteger(*val);
} }
template<Writer_c Writer>
constexpr Error MetalClawWriter::field(const char*, CommonPtrWith<uint8_t> auto *val) noexcept { constexpr Error MetalClawWriter<Writer>::field(const char*, CommonPtrWith<uint8_t> auto *val) noexcept {
return appendInteger(*val); return appendInteger(*val);
} }
constexpr Error MetalClawWriter::field(const char*, CommonPtrWith<uint16_t> auto *val) noexcept { template<Writer_c Writer>
constexpr Error MetalClawWriter<Writer>::field(const char*, CommonPtrWith<uint16_t> auto *val) noexcept {
return appendInteger(*val); return appendInteger(*val);
} }
constexpr Error MetalClawWriter::field(const char*, CommonPtrWith<uint32_t> auto *val) noexcept { template<Writer_c Writer>
constexpr Error MetalClawWriter<Writer>::field(const char*, CommonPtrWith<uint32_t> auto *val) noexcept {
return appendInteger(*val); return appendInteger(*val);
} }
constexpr Error MetalClawWriter::field(const char*, CommonPtrWith<uint64_t> auto *val) noexcept { template<Writer_c Writer>
constexpr Error MetalClawWriter<Writer>::field(const char*, CommonPtrWith<uint64_t> auto *val) noexcept {
return appendInteger(*val); return appendInteger(*val);
} }
constexpr Error MetalClawWriter::field(const char*, CommonPtrWith<bool> auto *val) noexcept { template<Writer_c Writer>
constexpr Error MetalClawWriter<Writer>::field(const char*, CommonPtrWith<bool> auto *val) noexcept {
if (m_unionIdx == -1 || m_unionIdx == m_field) { if (m_unionIdx == -1 || m_unionIdx == m_field) {
oxReturnError(m_fieldPresence.set(static_cast<std::size_t>(m_field), *val)); oxReturnError(m_fieldPresence.set(static_cast<std::size_t>(m_field), *val));
} }
@ -200,179 +204,155 @@ constexpr Error MetalClawWriter::field(const char*, CommonPtrWith<bool> auto *va
return OxError(0); return OxError(0);
} }
template<Writer_c Writer>
template<std::size_t SmallStringSize> template<std::size_t SmallStringSize>
constexpr Error MetalClawWriter::field(const char*, const BasicString<SmallStringSize> *val) noexcept { constexpr Error MetalClawWriter<Writer>::field(const char*, const BasicString<SmallStringSize> *val) noexcept {
bool fieldSet = false; bool fieldSet = false;
if (val->len() && (m_unionIdx == -1 || m_unionIdx == m_field)) { if (val->len() && (m_unionIdx == -1 || m_unionIdx == m_field)) {
// write the length // write the length
const auto strLen = mc::encodeInteger(val->len()); const auto strLen = mc::encodeInteger(val->len());
if (m_buffIt + strLen.length + static_cast<std::size_t>(val->len()) < m_buffLen) { oxReturnError(m_writer.write(reinterpret_cast<const char*>(strLen.data), strLen.length));
memcpy(&m_buff[m_buffIt], strLen.data, strLen.length);
m_buffIt += strLen.length;
// write the string // write the string
memcpy(&m_buff[m_buffIt], val->c_str(), static_cast<std::size_t>(val->len())); oxReturnError(m_writer.write(val->c_str(), static_cast<std::size_t>(val->len())));
m_buffIt += static_cast<std::size_t>(val->len());
fieldSet = true; fieldSet = true;
} else {
return OxError(MC_BUFFENDED);
}
} }
oxReturnError(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet)); oxReturnError(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet));
++m_field; ++m_field;
return OxError(0); return OxError(0);
} }
template<Writer_c Writer>
template<std::size_t L> template<std::size_t L>
constexpr Error MetalClawWriter::field(const char *name, const BString<L> *val) noexcept { constexpr Error MetalClawWriter<Writer>::field(const char *name, const BString<L> *val) noexcept {
return fieldCString(name, val->data(), val->cap()); return fieldCString(name, val->data(), val->cap());
} }
template<Writer_c Writer>
template<std::size_t SmallStringSize> template<std::size_t SmallStringSize>
constexpr Error MetalClawWriter::field(const char *name, BasicString<SmallStringSize> *val) noexcept { constexpr Error MetalClawWriter<Writer>::field(const char *name, BasicString<SmallStringSize> *val) noexcept {
return field(name, const_cast<const BasicString<SmallStringSize>*>(val)); return field(name, const_cast<const BasicString<SmallStringSize>*>(val));
} }
template<Writer_c Writer>
template<std::size_t L> template<std::size_t L>
constexpr Error MetalClawWriter::field(const char *name, BString<L> *val) noexcept { constexpr Error MetalClawWriter<Writer>::field(const char *name, BString<L> *val) noexcept {
return fieldCString(name, val->data(), val->cap()); return fieldCString(name, val->data(), val->cap());
} }
constexpr Error MetalClawWriter::fieldCString(const char*, const char *const*val, std::size_t) noexcept { template<Writer_c Writer>
constexpr Error MetalClawWriter<Writer>::fieldCString(const char*, const char *const*val, std::size_t) noexcept {
bool fieldSet = false; bool fieldSet = false;
if (m_unionIdx == -1 || m_unionIdx == m_field) { if (m_unionIdx == -1 || m_unionIdx == m_field) {
const auto strLen = *val ? ox_strlen(*val) : 0; const auto strLen = *val ? ox_strlen(*val) : 0;
// write the length // write the length
const auto strLenBuff = mc::encodeInteger(strLen); const auto strLenBuff = mc::encodeInteger(strLen);
if (m_buffIt + strLenBuff.length + static_cast<std::size_t>(strLen) < m_buffLen) { oxReturnError(m_writer.write(reinterpret_cast<const char*>(strLenBuff.data), strLenBuff.length));
ox_memcpy(&m_buff[m_buffIt], strLenBuff.data, strLenBuff.length);
m_buffIt += strLenBuff.length;
// write the string // write the string
ox_memcpy(&m_buff[m_buffIt], *val, static_cast<std::size_t>(strLen)); oxReturnError(m_writer.write(*val, static_cast<std::size_t>(strLen)));
m_buffIt += static_cast<std::size_t>(strLen);
fieldSet = true; fieldSet = true;
} else {
return OxError(MC_BUFFENDED);
}
} }
oxReturnError(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet)); oxReturnError(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet));
++m_field; ++m_field;
return OxError(0); return OxError(0);
} }
constexpr Error MetalClawWriter::fieldCString(const char *name, const char **val) noexcept { template<Writer_c Writer>
constexpr Error MetalClawWriter<Writer>::fieldCString(const char *name, const char **val) noexcept {
return fieldCString(name, val, {}); return fieldCString(name, val, {});
} }
constexpr Error MetalClawWriter::fieldCString(const char *name, const char *const*val) noexcept { template<Writer_c Writer>
constexpr Error MetalClawWriter<Writer>::fieldCString(const char *name, const char *const*val) noexcept {
return fieldCString(name, val, {}); return fieldCString(name, val, {});
} }
constexpr Error MetalClawWriter::fieldCString(const char*, const char *val, std::size_t strLen) noexcept { template<Writer_c Writer>
constexpr Error MetalClawWriter<Writer>::fieldCString(const char*, const char *val, std::size_t strLen) noexcept {
bool fieldSet = false; bool fieldSet = false;
if (strLen && (m_unionIdx == -1 || m_unionIdx == m_field)) { if (strLen && (m_unionIdx == -1 || m_unionIdx == m_field)) {
// write the length // write the length
const auto strLenBuff = mc::encodeInteger(strLen); const auto strLenBuff = mc::encodeInteger(strLen);
if (m_buffIt + strLenBuff.length + static_cast<std::size_t>(strLen) < m_buffLen) { oxReturnError(m_writer.write(reinterpret_cast<const char*>(strLenBuff.data), strLenBuff.length));
ox_memcpy(&m_buff[m_buffIt], strLenBuff.data, strLenBuff.length);
m_buffIt += strLenBuff.length;
// write the string // write the string
ox_memcpy(&m_buff[m_buffIt], val, static_cast<std::size_t>(strLen)); oxReturnError(m_writer.write(val, static_cast<std::size_t>(strLen)));
m_buffIt += static_cast<std::size_t>(strLen);
fieldSet = true; fieldSet = true;
} else {
return OxError(MC_BUFFENDED);
}
} }
oxReturnError(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet)); oxReturnError(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet));
++m_field; ++m_field;
return OxError(0); return OxError(0);
} }
template<Writer_c Writer>
template<typename T> template<typename T>
constexpr Error MetalClawWriter::field(const char*, T *val) noexcept { constexpr Error MetalClawWriter<Writer>::field(const char*, T *val) noexcept {
if constexpr(isVector_v<T> || isArray_v<T>) { if constexpr(isVector_v<T> || isArray_v<T>) {
return field(nullptr, val->data(), val->size()); return field(nullptr, val->data(), val->size());
} else { } else {
bool fieldSet = false; bool fieldSet = false;
if (val && (m_unionIdx == -1 || m_unionIdx == m_field)) { if (val && (m_unionIdx == -1 || m_unionIdx == m_field)) {
MetalClawWriter writer(m_buff + m_buffIt, m_buffLen - m_buffIt); MetalClawWriter<Writer> writer(m_writer);
ModelHandlerInterface<MetalClawWriter> handler{&writer}; ModelHandlerInterface<MetalClawWriter<Writer>> handler{&writer};
oxReturnError(model(&handler, val)); oxReturnError(model(&handler, val));
if (static_cast<std::size_t>(writer.m_fieldPresence.getMaxLen()) < writer.m_buffIt) { oxReturnError(writer.finalize());
m_buffIt += writer.m_buffIt;
fieldSet = true; fieldSet = true;
} }
}
oxReturnError(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet)); oxReturnError(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet));
++m_field; ++m_field;
return OxError(0); return OxError(0);
} }
} }
template<Writer_c Writer>
template<typename U, bool force> template<typename U, bool force>
constexpr Error MetalClawWriter::field(const char*, UnionView<U, force> val) noexcept { constexpr Error MetalClawWriter<Writer>::field(const char*, UnionView<U, force> val) noexcept {
bool fieldSet = false; bool fieldSet = false;
if (val.get() && (m_unionIdx == -1 || m_unionIdx == m_field)) { if (val.get() && (m_unionIdx == -1 || m_unionIdx == m_field)) {
MetalClawWriter writer(m_buff + m_buffIt, m_buffLen - m_buffIt, val.idx()); MetalClawWriter<Writer> writer(m_writer, val.idx());
ModelHandlerInterface handler{&writer}; ModelHandlerInterface handler{&writer};
oxReturnError(model(&handler, val.get())); oxReturnError(model(&handler, val.get()));
if (static_cast<std::size_t>(writer.m_fieldPresence.getMaxLen()) < writer.m_buffIt) { oxReturnError(writer.finalize());
m_buffIt += writer.m_buffIt;
fieldSet = true; fieldSet = true;
} }
}
oxReturnError(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet)); oxReturnError(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet));
m_field++; ++m_field;
return OxError(0); return OxError(0);
} }
template<Writer_c Writer>
template<typename T> template<typename T>
constexpr Error MetalClawWriter::field(const char*, T *val, std::size_t len) noexcept { constexpr Error MetalClawWriter<Writer>::field(const char*, T *val, std::size_t len) noexcept {
bool fieldSet = false; bool fieldSet = false;
if (len && (m_unionIdx == -1 || m_unionIdx == m_field)) { if (len && (m_unionIdx == -1 || m_unionIdx == m_field)) {
// write the length // write the length
const auto arrLen = mc::encodeInteger(len); const auto arrLen = mc::encodeInteger(len);
if (m_buffIt + arrLen.length < m_buffLen) { oxReturnError(m_writer.write(reinterpret_cast<const char*>(arrLen.data), arrLen.length));
ox_memcpy(&m_buff[m_buffIt], arrLen.data, arrLen.length); MetalClawWriter<Writer> writer(m_writer);
m_buffIt += arrLen.length;
} else {
return OxError(MC_BUFFENDED);
}
MetalClawWriter writer(m_buff + m_buffIt, m_buffLen - m_buffIt);
ModelHandlerInterface handler{&writer}; ModelHandlerInterface handler{&writer};
handler.setTypeInfo<T>("List", 0, {}, static_cast<std::size_t>(len)); handler.template setTypeInfo<T>("List", 0, {}, static_cast<std::size_t>(len));
// write the array // write the array
for (std::size_t i = 0; i < len; i++) { for (std::size_t i = 0; i < len; i++) {
oxReturnError(handler.field("", &val[i])); oxReturnError(handler.field("", &val[i]));
} }
oxReturnError(writer.finalize());
m_buffIt += writer.m_buffIt;
fieldSet = true; fieldSet = true;
} }
oxReturnError(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet)); oxReturnError(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet));
m_field++; ++m_field;
return OxError(0); return OxError(0);
} }
template<Writer_c Writer>
template<typename T> template<typename T>
constexpr Error MetalClawWriter::field(const char*, const HashMap<String, T> *val) noexcept { constexpr Error MetalClawWriter<Writer>::field(const char*, const HashMap<String, T> *val) noexcept {
const auto &keys = val->keys(); const auto &keys = val->keys();
const auto len = keys.size(); const auto len = keys.size();
bool fieldSet = false; bool fieldSet = false;
if (len && (m_unionIdx == -1 || m_unionIdx == m_field)) { if (len && (m_unionIdx == -1 || m_unionIdx == m_field)) {
// write the length // write the length
const auto arrLen = mc::encodeInteger(len); const auto arrLen = mc::encodeInteger(len);
if (m_buffIt + arrLen.length < m_buffLen) { oxReturnError(m_writer.write(reinterpret_cast<const char*>(arrLen.data), arrLen.length));
ox_memcpy(&m_buff[m_buffIt], arrLen.data, arrLen.length); // write map
m_buffIt += arrLen.length; MetalClawWriter<Writer> writer(m_writer);
} else {
return OxError(MC_BUFFENDED);
}
MetalClawWriter writer(m_buff + m_buffIt, m_buffLen - m_buffIt);
ModelHandlerInterface handler{&writer}; ModelHandlerInterface handler{&writer};
// double len for both key and value // double len for both key and value
handler.setTypeInfo("Map", 0, {}, len * 2); handler.setTypeInfo("Map", 0, {}, len * 2);
@ -386,48 +366,69 @@ constexpr Error MetalClawWriter::field(const char*, const HashMap<String, T> *va
oxRequireM(value, val->at(key)); oxRequireM(value, val->at(key));
oxReturnError(handler.field("", value)); oxReturnError(handler.field("", value));
} }
m_buffIt += writer.m_buffIt; oxReturnError(writer.finalize());
fieldSet = true; fieldSet = true;
} }
oxReturnError(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet)); oxReturnError(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet));
m_field++; ++m_field;
return OxError(0); return OxError(0);
} }
template<Writer_c Writer>
template<typename T> template<typename T>
constexpr Error MetalClawWriter::field(const char *name, HashMap<String, T> *val) noexcept { constexpr Error MetalClawWriter<Writer>::field(const char *name, HashMap<String, T> *val) noexcept {
return field(name, const_cast<const HashMap<String, T>*>(val)); return field(name, const_cast<const HashMap<String, T>*>(val));
} }
template<Writer_c Writer>
template<typename T> template<typename T>
constexpr void MetalClawWriter::setTypeInfo(const char*, int, const Vector<String>&, std::size_t fields) noexcept { constexpr void MetalClawWriter<Writer>::setTypeInfo(
m_fields = static_cast<int>(fields); const char*,
int,
const Vector<String>&,
std::size_t fields) noexcept {
// TODO: change all setTypeInfo signatures to return Errors
const auto fieldPresenceLen = (fields - 1) / 8 + 1;
oxIgnoreError(m_writer.write(nullptr, fieldPresenceLen));
m_presenceMapBuff.resize(fieldPresenceLen);
m_fieldPresence.setBuffer(m_presenceMapBuff.data(), m_presenceMapBuff.size());
m_fieldPresence.setFields(static_cast<int>(fields)); m_fieldPresence.setFields(static_cast<int>(fields));
m_buffIt = static_cast<std::size_t>(m_fieldPresence.getMaxLen());
ox_memset(m_buff, 0, m_buffIt);
} }
constexpr std::size_t MetalClawWriter::size() const noexcept { template<Writer_c Writer>
return m_buffIt; ox::Error MetalClawWriter<Writer>::finalize() noexcept {
const auto end = m_writer.tellp();
oxReturnError(m_writer.seekp(m_writerBeginP));
oxReturnError(m_writer.write(
reinterpret_cast<const char*>(m_presenceMapBuff.data()),
m_presenceMapBuff.size()));
oxReturnError(m_writer.seekp(end));
return {};
} }
Result<Buffer> writeMC(auto *val) noexcept { Result<Buffer> writeMC(Writer_c auto &writer, auto &val) noexcept {
Buffer buff(10 * units::MB); MetalClawWriter mcWriter(writer);
MetalClawWriter writer(reinterpret_cast<uint8_t*>(buff.data()), buff.size()); ModelHandlerInterface handler{&mcWriter};
ModelHandlerInterface handler{&writer}; oxReturnError(model(&handler, &val));
oxReturnError(model(&handler, val)); oxReturnError(mcWriter.finalize());
buff.resize(writer.size()); return {};
}
Result<Buffer> writeMC(auto *val, std::size_t buffReserveSz = 2 * units::KB) noexcept {
Buffer buff(buffReserveSz);
BufferWriter bw(&buff, 0);
oxReturnError(writeMC(bw, *val));
buff.resize(bw.tellp());
return buff; return buff;
} }
Error writeMC(char *buff, std::size_t buffLen, auto *val, std::size_t *sizeOut = nullptr) noexcept { Error writeMC(char *buff, std::size_t buffLen, auto *val, std::size_t *sizeOut = nullptr) noexcept {
MetalClawWriter writer(reinterpret_cast<uint8_t*>(buff), buffLen); CharBuffWriter bw(buff, buffLen);
ModelHandlerInterface handler(&writer); oxReturnError(writeMC(bw, *val));
auto err = model(&handler, val);
if (sizeOut) { if (sizeOut) {
*sizeOut = writer.size(); *sizeOut = bw.tellp();
} }
return err; return {};
} }
} }

View File

@ -66,6 +66,12 @@ class WriterT: public Writer_v {
} }
}; };
/**
* Allocates the specified amount of data at the end of the current write stream.
* @param writer
* @param sz
* @return
*/
constexpr ox::Result<std::size_t> allocate(Writer_c auto *writer, std::size_t sz) noexcept { constexpr ox::Result<std::size_t> allocate(Writer_c auto *writer, std::size_t sz) noexcept {
const auto p = writer->tellp(); const auto p = writer->tellp();
oxReturnError(writer->seekp(0, ios_base::end)); oxReturnError(writer->seekp(0, ios_base::end));