[ox/mc] Cleanup
All checks were successful
Build / build (push) Successful in 1m10s

This commit is contained in:
2026-01-26 00:12:40 -06:00
parent 2ed469f2dd
commit c6ecadf9a8
2 changed files with 137 additions and 140 deletions

View File

@@ -18,25 +18,25 @@
namespace ox::mc { namespace ox::mc {
template<typename T> template<Integer_c T>
static constexpr auto Bits = sizeof(T) << 3; static constexpr auto Bits = sizeof(T) << 3;
/** /**
* Returns highest bit other than possible signed bit. * Returns highest bit other than possible signed bit.
* Bit numbering starts at 0. * Bit numbering starts at 0.
*/ */
template<typename I> template<Integer_c I>
[[nodiscard]] [[nodiscard]]
constexpr std::size_t highestBit(I val) noexcept { constexpr size_t highestBit(I const val) noexcept {
unsigned shiftStart = sizeof(I) * 8 - 1; unsigned shiftStart = sizeof(I) * 8 - 1;
// find most significant non-sign indicator bit // find the most significant non-sign indicator bit
std::size_t highestBit = 0; size_t highestBit = 0;
// start at one bit lower if signed // start at one bit lower if signed
if constexpr(is_signed_v<I>) { if constexpr(is_signed_v<I>) {
--shiftStart; --shiftStart;
} }
for (auto i = shiftStart; i > 0; --i) { for (auto i = shiftStart; i > 0; --i) {
const auto bitValue = (val >> i) & 1; auto const bitValue = (val >> i) & 1;
if (bitValue) { if (bitValue) {
highestBit = i; highestBit = i;
break; break;
@@ -45,7 +45,7 @@ constexpr std::size_t highestBit(I val) noexcept {
return highestBit; return highestBit;
} }
static_assert(highestBit(int8_t(0b10000000)) == 0); static_assert(highestBit(static_cast<int8_t>(0b10000000)) == 0);
static_assert(highestBit(~static_cast<int8_t>(-1)) == 0); static_assert(highestBit(~static_cast<int8_t>(-1)) == 0);
static_assert(highestBit(~static_cast<int8_t>(-2)) == 0); static_assert(highestBit(~static_cast<int8_t>(-2)) == 0);
static_assert(highestBit(~static_cast<int8_t>(-3)) == 1); static_assert(highestBit(~static_cast<int8_t>(-3)) == 1);
@@ -53,42 +53,39 @@ static_assert(highestBit(1) == 0);
static_assert(highestBit(2) == 1); static_assert(highestBit(2) == 1);
static_assert(highestBit(4) == 2); static_assert(highestBit(4) == 2);
static_assert(highestBit(8) == 3); static_assert(highestBit(8) == 3);
static_assert(highestBit(uint64_t(1) << 31) == 31); static_assert(highestBit(static_cast<uint64_t>(1) << 31) == 31);
static_assert(highestBit(uint64_t(1) << 63) == 63); static_assert(highestBit(static_cast<uint64_t>(1) << 63) == 63);
struct McInt { struct McInt {
ox::Array<uint8_t, 9> data{}; Array<uint8_t, 9> data{};
// length of integer in bytes // length of integer in bytes
std::size_t length = 0; size_t length = 0;
}; };
template<typename I> template<Integer_c I>
[[nodiscard]] [[nodiscard]]
constexpr McInt encodeInteger(I pInput) noexcept { constexpr McInt encodeInteger(I const pInput) noexcept {
auto const input = ox::ResizedInt_t<I, 64>{pInput}; auto const input = ResizedInt_t<I, 64>{pInput};
McInt out; McInt out;
const auto inputNegative = is_signed_v<I> && input < 0; auto const inputNegative = is_signed_v<I> && input < 0;
// move input to uint64_t to allow consistent bit manipulation, and to avoid // move input to uint64_t to allow consistent bit manipulation and to avoid
// overflow concerns // overflow concerns
uint64_t val = 0; auto const val = std::bit_cast<uint64_t>(input);
OX_ALLOW_UNSAFE_BUFFERS_BEGIN
ox::memcpy(&val, &input, sizeof(input));
OX_ALLOW_UNSAFE_BUFFERS_END
if (val) { if (val) {
// bits needed to represent number factoring in space possibly // bits needed to represent number factoring in space possibly
// needed for signed bit // needed for signed bit
const auto highBit = inputNegative ? highestBit(~val) : highestBit(val); auto const highBit = inputNegative ? highestBit(~val) : highestBit(val);
const auto bits = highBit + 1 + (is_signed_v<I> ? 1 : 0); auto const bits = highBit + 1 + (is_signed_v<I> ? 1 : 0);
// bytes needed to store value // bytes needed to store value
std::size_t bytes = bits / 8 + (bits % 8 != 0); size_t bytes = bits / 8 + (bits % 8 != 0);
const auto bitsAvailable = bytes * 8; // bits available to integer value auto const bitsAvailable = bytes * 8; // bits available to integer value
const auto bitsNeeded = bits + bytes; auto const bitsNeeded = bits + bytes;
// factor in bits needed for bytesIndicator (does not affect bytesIndicator) // factor in bits needed for bytesIndicator (does not affect bytesIndicator)
// bits for integer + bits needed to represent bytes > bits available // bits for integer + bits needed to represent bytes > bits available
if (bitsNeeded > bitsAvailable && bytes != 9) { if (bitsNeeded > bitsAvailable && bytes != 9) {
++bytes; ++bytes;
} }
const auto bytesIndicator = onMask<uint8_t>(bytes - 1); auto const bytesIndicator = onMask<uint8_t>(bytes - 1);
// ensure we are copying from little endian representation // ensure we are copying from little endian representation
LittleEndian<uint64_t> leVal = val; LittleEndian<uint64_t> leVal = val;
if (inputNegative) { if (inputNegative) {
@@ -103,9 +100,9 @@ constexpr McInt encodeInteger(I pInput) noexcept {
out.data[1] |= 0b1000'0000; out.data[1] |= 0b1000'0000;
} }
} else { } else {
const auto valBits = bytes * 8; auto const valBits = bytes * 8;
uint64_t negBit = inputNegative ? 1 : 0; uint64_t const negBit = inputNegative ? 1 : 0;
auto intermediate = auto const intermediate =
static_cast<uint64_t>(leVal.raw() | (negBit << (valBits - 1))) << bytes | static_cast<uint64_t>(leVal.raw() | (negBit << (valBits - 1))) << bytes |
static_cast<uint64_t>(bytesIndicator); static_cast<uint64_t>(bytesIndicator);
OX_ALLOW_UNSAFE_BUFFERS_BEGIN OX_ALLOW_UNSAFE_BUFFERS_BEGIN
@@ -122,8 +119,8 @@ constexpr McInt encodeInteger(I pInput) noexcept {
* length integer. * length integer.
*/ */
[[nodiscard]] [[nodiscard]]
constexpr std::size_t countBytes(unsigned b) noexcept { constexpr size_t countBytes(unsigned const b) noexcept {
std::size_t i = 0; size_t i = 0;
while ((b >> i) & 1) ++i; while ((b >> i) & 1) ++i;
return i + 1; return i + 1;
} }
@@ -138,12 +135,12 @@ static_assert(countBytes(0b0011'1111) == 7);
static_assert(countBytes(0b0111'1111) == 8); static_assert(countBytes(0b0111'1111) == 8);
static_assert(countBytes(0b1111'1111) == 9); static_assert(countBytes(0b1111'1111) == 9);
template<typename I> template<Integer_c I>
constexpr Result<I> decodeInteger(Reader_c auto&rdr, std::size_t &bytesRead) noexcept { constexpr Result<I> decodeInteger(Reader_c auto &rdr, size_t &bytesRead) noexcept {
uint8_t firstByte = 0; uint8_t firstByte = 0;
OX_RETURN_ERROR(rdr.read(&firstByte, 1)); OX_RETURN_ERROR(rdr.read(&firstByte, 1));
OX_RETURN_ERROR(rdr.seekg(-1, ox::ios_base::cur)); OX_RETURN_ERROR(rdr.seekg(-1, ox::ios_base::cur));
const auto bytes = countBytes(firstByte); auto const bytes = countBytes(firstByte);
if (bytes == 9) { if (bytes == 9) {
bytesRead = bytes; bytesRead = bytes;
I out = 0; I out = 0;
@@ -157,20 +154,20 @@ constexpr Result<I> decodeInteger(Reader_c auto&rdr, std::size_t &bytesRead) noe
decoded >>= bytes; decoded >>= bytes;
// move sign bit // move sign bit
if constexpr(is_signed_v<I>) { if constexpr(is_signed_v<I>) {
const auto negBit = bytes * 8 - bytes - 1; auto const negBit = bytes * 8 - bytes - 1;
// move sign // move sign
const auto negative = (decoded >> negBit) == 1; auto const negative = (decoded >> negBit) == 1;
if (negative) { if (negative) {
// fill in all bits between encoded sign and real sign with 1s // fill in all bits between encoded sign and real sign with 1s
// split it up because the 32-bit ARM can't shift more than 32 bits // split it up because the 32-bit ARM can't shift more than 32 bits
ox::Array<uint32_t, 2> d = {}; Array<uint32_t, 2> d = {};
//d[0] = decoded & 0xffff'ffff; //d[0] = decoded & 0xffff'ffff;
//d[1] = decoded >> 32; //d[1] = decoded >> 32;
OX_ALLOW_UNSAFE_BUFFERS_BEGIN OX_ALLOW_UNSAFE_BUFFERS_BEGIN
ox::memcpy(&d[0], &decoded, sizeof(decoded)); ox::memcpy(&d[0], &decoded, sizeof(decoded));
OX_ALLOW_UNSAFE_BUFFERS_END OX_ALLOW_UNSAFE_BUFFERS_END
auto bit = negBit; auto bit = negBit;
for (; bit < ox::min<std::size_t>(Bits<I>, 32); ++bit) { for (; bit < ox::min<size_t>(Bits<I>, 32); ++bit) {
d[0] |= 1 << bit; d[0] |= 1 << bit;
} }
bit -= 32; bit -= 32;
@@ -179,7 +176,7 @@ constexpr Result<I> decodeInteger(Reader_c auto&rdr, std::size_t &bytesRead) noe
} }
I out = 0; I out = 0;
if constexpr(ox::defines::BigEndian) { if constexpr(ox::defines::BigEndian) {
const auto d0Tmp = d[0]; auto const d0Tmp = d[0];
d[0] = d[1]; d[0] = d[1];
d[1] = d0Tmp; d[1] = d0Tmp;
} }
@@ -192,9 +189,9 @@ constexpr Result<I> decodeInteger(Reader_c auto&rdr, std::size_t &bytesRead) noe
return static_cast<I>(decoded); return static_cast<I>(decoded);
} }
template<typename I> template<Integer_c I>
Result<I> decodeInteger(McInt m) noexcept { Result<I> decodeInteger(McInt const &m) noexcept {
std::size_t bytesRead{}; size_t bytesRead{};
BufferReader br({reinterpret_cast<const char*>(m.data.data()), 9}); BufferReader br({reinterpret_cast<const char*>(m.data.data()), 9});
return decodeInteger<I>(br, bytesRead); return decodeInteger<I>(br, bytesRead);
} }

View File

@@ -32,68 +32,68 @@ template<Writer_c Writer>
class MetalClawWriter { class MetalClawWriter {
private: private:
ox::Vector<uint8_t, 16> m_presenceMapBuff{}; Vector<uint8_t, 16> m_presenceMapBuff{};
FieldBitmap m_fieldPresence; FieldBitmap m_fieldPresence;
int m_field = 0; int m_field = 0;
ox::Optional<int> m_unionIdx; Optional<int> m_unionIdx;
std::size_t m_writerBeginP{}; size_t m_writerBeginP{};
Writer &m_writer; Writer &m_writer;
public: public:
constexpr explicit MetalClawWriter(Writer &writer, ox::Optional<int> const&unionIdx = {}) noexcept; constexpr explicit MetalClawWriter(Writer &writer, Optional<int> const &unionIdx = {}) noexcept;
constexpr ~MetalClawWriter() noexcept = default; constexpr ~MetalClawWriter() noexcept = default;
constexpr Error field(const char*, const int8_t *val) noexcept; constexpr Error field(CString, int8_t const *val) noexcept;
constexpr Error field(const char*, const int16_t *val) noexcept; constexpr Error field(CString, int16_t const *val) noexcept;
constexpr Error field(const char*, const int32_t *val) noexcept; constexpr Error field(CString, int32_t const *val) noexcept;
constexpr Error field(const char*, const int64_t *val) noexcept; constexpr Error field(CString, int64_t const *val) noexcept;
constexpr Error field(const char*, const uint8_t *val) noexcept; constexpr Error field(CString, uint8_t const *val) noexcept;
constexpr Error field(const char*, const uint16_t *val) noexcept; constexpr Error field(CString, uint16_t const *val) noexcept;
constexpr Error field(const char*, const uint32_t *val) noexcept; constexpr Error field(CString, uint32_t const *val) noexcept;
constexpr Error field(const char*, const uint64_t *val) noexcept; constexpr Error field(CString, uint64_t const *val) noexcept;
constexpr Error field(const char*, const bool *val) noexcept; constexpr Error field(CString, bool const *val) noexcept;
template<typename T> template<typename T>
constexpr Error field(const char*, const T *val, std::size_t len) noexcept; constexpr Error field(CString, T const *val, size_t len) noexcept;
template<typename T> template<typename T>
constexpr Error field(const char *name, const HashMap<String, T> *val) noexcept; constexpr Error field(CString name, HashMap<String, T> const *val) noexcept;
template<std::size_t SmallStringSize> template<size_t SmallStringSize>
constexpr Error field(const char*, const BasicString<SmallStringSize> *val) noexcept; constexpr Error field(CString, BasicString<SmallStringSize> const *val) noexcept;
template<std::size_t L> template<size_t L>
constexpr Error field(const char*, const IString<L> *val) noexcept; constexpr Error field(CString, IString<L> const *val) noexcept;
constexpr Error fieldCString(const char *name, const char *const*val, std::size_t buffLen) noexcept; constexpr Error fieldCString(CString name, CString const*val, size_t buffLen) noexcept;
constexpr Error fieldCString(const char *name, const char **val) noexcept; constexpr Error fieldCString(CString name, CString *val) noexcept;
constexpr Error fieldCString(const char *name, const char *const*val) noexcept; constexpr Error fieldCString(CString name, CString const*val) noexcept;
constexpr Error fieldCString(const char *name, const char *val, std::size_t len) noexcept; constexpr Error fieldCString(CString name, CString val, size_t strLen) noexcept;
template<typename T> template<typename T>
constexpr Error field(const char*, const T *val) noexcept; constexpr Error field(CString, T const *val) noexcept;
template<typename U, bool force = false> template<typename U, bool force = false>
constexpr Error field(const char*, UnionView<U, force> val) noexcept; constexpr Error field(CString, UnionView<U, force> val) noexcept;
template<typename T = std::nullptr_t> template<typename T = std::nullptr_t>
constexpr ox::Error setTypeInfo( constexpr Error setTypeInfo(
const char *name = T::TypeName, CString name = T::TypeName,
int version = T::TypeVersion, int version = T::TypeVersion,
const Vector<String>& = {}, Vector<String> const& = {},
std::size_t fields = ModelFieldCount_v<T>) noexcept; size_t fields = ModelFieldCount_v<T>) noexcept;
/** /**
* stringLength is not implemented in MetalClawWriter * stringLength is not implemented in MetalClawWriter
*/ */
[[nodiscard]] [[nodiscard]]
constexpr auto stringLength(const char*) noexcept { constexpr auto stringLength(CString) noexcept {
return 0; return 0;
} }
@@ -101,7 +101,7 @@ class MetalClawWriter {
* stringLength is not implemented in MetalClawWriter * stringLength is not implemented in MetalClawWriter
*/ */
[[nodiscard]] [[nodiscard]]
constexpr auto arrayLength(const char*, bool = true) noexcept { constexpr auto arrayLength(CString, bool = true) noexcept {
return 0; return 0;
} }
@@ -110,17 +110,17 @@ class MetalClawWriter {
return OpType::Write; return OpType::Write;
} }
ox::Error finalize() noexcept; 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.has_value() || *m_unionIdx == m_field)) { if (val && (!m_unionIdx.has_value() || *m_unionIdx == m_field)) {
auto mi = mc::encodeInteger(val); auto mi = mc::encodeInteger(val);
OX_RETURN_ERROR(m_writer.write(reinterpret_cast<const char*>(mi.data.data()), mi.length)); OX_RETURN_ERROR(m_writer.write(reinterpret_cast<CString>(mi.data.data()), mi.length));
fieldSet = true; fieldSet = true;
} }
OX_RETURN_ERROR(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet)); OX_RETURN_ERROR(m_fieldPresence.set(static_cast<size_t>(m_field), fieldSet));
++m_field; ++m_field;
return {}; return {};
} }
@@ -131,7 +131,7 @@ extern template class ModelHandlerInterface<MetalClawWriter<BufferWriter>>;
extern template class ModelHandlerInterface<MetalClawWriter<CharBuffWriter>>; extern template class ModelHandlerInterface<MetalClawWriter<CharBuffWriter>>;
template<Writer_c Writer> template<Writer_c Writer>
constexpr MetalClawWriter<Writer>::MetalClawWriter(Writer &writer, ox::Optional<int> const&unionIdx) noexcept: constexpr MetalClawWriter<Writer>::MetalClawWriter(Writer &writer, Optional<int> const &unionIdx) noexcept:
m_fieldPresence(m_presenceMapBuff.data(), m_presenceMapBuff.size()), m_fieldPresence(m_presenceMapBuff.data(), m_presenceMapBuff.size()),
m_unionIdx(unionIdx), m_unionIdx(unionIdx),
m_writerBeginP(writer.tellp()), m_writerBeginP(writer.tellp()),
@@ -139,128 +139,128 @@ constexpr MetalClawWriter<Writer>::MetalClawWriter(Writer &writer, ox::Optional<
} }
template<Writer_c Writer> template<Writer_c Writer>
constexpr Error MetalClawWriter<Writer>::field(const char*, const int8_t *val) noexcept { constexpr Error MetalClawWriter<Writer>::field(CString, int8_t const *val) noexcept {
return appendInteger(*val); return appendInteger(*val);
} }
template<Writer_c Writer> template<Writer_c Writer>
constexpr Error MetalClawWriter<Writer>::field(const char*, const int16_t *val) noexcept { constexpr Error MetalClawWriter<Writer>::field(CString, int16_t const *val) noexcept {
return appendInteger(*val); return appendInteger(*val);
} }
template<Writer_c Writer> template<Writer_c Writer>
constexpr Error MetalClawWriter<Writer>::field(const char*, const int32_t *val) noexcept { constexpr Error MetalClawWriter<Writer>::field(CString, int32_t const *val) noexcept {
return appendInteger(*val); return appendInteger(*val);
} }
template<Writer_c Writer> template<Writer_c Writer>
constexpr Error MetalClawWriter<Writer>::field(const char*, const int64_t *val) noexcept { constexpr Error MetalClawWriter<Writer>::field(CString, int64_t const *val) noexcept {
return appendInteger(*val); return appendInteger(*val);
} }
template<Writer_c Writer> template<Writer_c Writer>
constexpr Error MetalClawWriter<Writer>::field(const char*, const uint8_t *val) noexcept { constexpr Error MetalClawWriter<Writer>::field(CString, uint8_t const *val) noexcept {
return appendInteger(*val); return appendInteger(*val);
} }
template<Writer_c Writer> template<Writer_c Writer>
constexpr Error MetalClawWriter<Writer>::field(const char*, const uint16_t *val) noexcept { constexpr Error MetalClawWriter<Writer>::field(CString, uint16_t const *val) noexcept {
return appendInteger(*val); return appendInteger(*val);
} }
template<Writer_c Writer> template<Writer_c Writer>
constexpr Error MetalClawWriter<Writer>::field(const char*, const uint32_t *val) noexcept { constexpr Error MetalClawWriter<Writer>::field(CString, uint32_t const *val) noexcept {
return appendInteger(*val); return appendInteger(*val);
} }
template<Writer_c Writer> template<Writer_c Writer>
constexpr Error MetalClawWriter<Writer>::field(const char*, const uint64_t *val) noexcept { constexpr Error MetalClawWriter<Writer>::field(CString, uint64_t const *val) noexcept {
return appendInteger(*val); return appendInteger(*val);
} }
template<Writer_c Writer> template<Writer_c Writer>
constexpr Error MetalClawWriter<Writer>::field(const char*, const bool *val) noexcept { constexpr Error MetalClawWriter<Writer>::field(CString, bool const *val) noexcept {
if (!m_unionIdx.has_value() || *m_unionIdx == m_field) { if (!m_unionIdx.has_value() || *m_unionIdx == m_field) {
OX_RETURN_ERROR(m_fieldPresence.set(static_cast<std::size_t>(m_field), *val)); OX_RETURN_ERROR(m_fieldPresence.set(static_cast<size_t>(m_field), *val));
} }
++m_field; ++m_field;
return {}; return {};
} }
template<Writer_c Writer> template<Writer_c Writer>
template<std::size_t SmallStringSize> template<size_t SmallStringSize>
constexpr Error MetalClawWriter<Writer>::field(const char*, const BasicString<SmallStringSize> *val) noexcept { constexpr Error MetalClawWriter<Writer>::field(CString, BasicString<SmallStringSize> const *val) noexcept {
bool fieldSet = false; bool fieldSet = false;
if (val->size() && (!m_unionIdx.has_value() || *m_unionIdx == m_field)) { if (val->size() && (!m_unionIdx.has_value() || *m_unionIdx == m_field)) {
// write the length // write the length
const auto strLen = mc::encodeInteger(val->size()); auto const strLen = mc::encodeInteger(val->size());
OX_RETURN_ERROR(m_writer.write(reinterpret_cast<const char*>(strLen.data.data()), strLen.length)); OX_RETURN_ERROR(m_writer.write(reinterpret_cast<CString>(strLen.data.data()), strLen.length));
// write the string // write the string
OX_RETURN_ERROR(m_writer.write(val->c_str(), static_cast<std::size_t>(val->size()))); OX_RETURN_ERROR(m_writer.write(val->c_str(), static_cast<size_t>(val->size())));
fieldSet = true; fieldSet = true;
} }
OX_RETURN_ERROR(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet)); OX_RETURN_ERROR(m_fieldPresence.set(static_cast<size_t>(m_field), fieldSet));
++m_field; ++m_field;
return {}; return {};
} }
template<Writer_c Writer> template<Writer_c Writer>
template<std::size_t L> template<size_t L>
constexpr Error MetalClawWriter<Writer>::field(const char *name, const IString<L> *val) noexcept { constexpr Error MetalClawWriter<Writer>::field(CString name, IString<L> const *val) noexcept {
return fieldCString(name, val->data(), val->size()); return fieldCString(name, val->data(), val->size());
} }
template<Writer_c Writer> template<Writer_c Writer>
constexpr Error MetalClawWriter<Writer>::fieldCString(const char*, const char *const*val, std::size_t) noexcept { constexpr Error MetalClawWriter<Writer>::fieldCString(CString, CString const *val, size_t) noexcept {
bool fieldSet = false; bool fieldSet = false;
if (!m_unionIdx.has_value() || *m_unionIdx == m_field) { if (!m_unionIdx.has_value() || *m_unionIdx == m_field) {
OX_ALLOW_UNSAFE_BUFFERS_BEGIN OX_ALLOW_UNSAFE_BUFFERS_BEGIN
// this strlen is tolerated because sometimes 0 gets passed to // this strlen is tolerated because sometimes 0 gets passed to
// the size param, which is a lie // the size param, which is a lie
// this code should be cleaned up at some point... // this code should be cleaned up at some point...
const auto strLen = *val ? ox::strlen(*val) : 0; auto const strLen = *val ? ox::strlen(*val) : 0;
OX_ALLOW_UNSAFE_BUFFERS_END OX_ALLOW_UNSAFE_BUFFERS_END
// write the length // write the length
const auto strLenBuff = mc::encodeInteger(strLen); auto const strLenBuff = mc::encodeInteger(strLen);
OX_RETURN_ERROR(m_writer.write(reinterpret_cast<const char*>(strLenBuff.data.data()), strLenBuff.length)); OX_RETURN_ERROR(m_writer.write(reinterpret_cast<CString>(strLenBuff.data.data()), strLenBuff.length));
// write the string // write the string
OX_RETURN_ERROR(m_writer.write(*val, static_cast<std::size_t>(strLen))); OX_RETURN_ERROR(m_writer.write(*val, static_cast<size_t>(strLen)));
fieldSet = true; fieldSet = true;
} }
OX_RETURN_ERROR(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet)); OX_RETURN_ERROR(m_fieldPresence.set(static_cast<size_t>(m_field), fieldSet));
++m_field; ++m_field;
return {}; return {};
} }
template<Writer_c Writer> template<Writer_c Writer>
constexpr Error MetalClawWriter<Writer>::fieldCString(const char *name, const char **val) noexcept { constexpr Error MetalClawWriter<Writer>::fieldCString(CString const name, CString *val) noexcept {
return fieldCString(name, val, {}); return fieldCString(name, val, {});
} }
template<Writer_c Writer> template<Writer_c Writer>
constexpr Error MetalClawWriter<Writer>::fieldCString(const char *name, const char *const*val) noexcept { constexpr Error MetalClawWriter<Writer>::fieldCString(CString const name, CString const *val) noexcept {
return fieldCString(name, val, {}); return fieldCString(name, val, {});
} }
template<Writer_c Writer> template<Writer_c Writer>
constexpr Error MetalClawWriter<Writer>::fieldCString(const char*, const char *val, std::size_t strLen) noexcept { constexpr Error MetalClawWriter<Writer>::fieldCString(CString, CString const val, size_t const strLen) noexcept {
bool fieldSet = false; bool fieldSet = false;
if (strLen && (!m_unionIdx.has_value() || *m_unionIdx == m_field)) { if (strLen && (!m_unionIdx.has_value() || *m_unionIdx == m_field)) {
// write the length // write the length
const auto strLenBuff = mc::encodeInteger(strLen); auto const strLenBuff = mc::encodeInteger(strLen);
OX_RETURN_ERROR(m_writer.write(reinterpret_cast<const char*>(strLenBuff.data.data()), strLenBuff.length)); OX_RETURN_ERROR(m_writer.write(reinterpret_cast<CString>(strLenBuff.data.data()), strLenBuff.length));
// write the string // write the string
OX_RETURN_ERROR(m_writer.write(val, static_cast<std::size_t>(strLen))); OX_RETURN_ERROR(m_writer.write(val, static_cast<size_t>(strLen)));
fieldSet = true; fieldSet = true;
} }
OX_RETURN_ERROR(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet)); OX_RETURN_ERROR(m_fieldPresence.set(static_cast<size_t>(m_field), fieldSet));
++m_field; ++m_field;
return {}; return {};
} }
template<Writer_c Writer> template<Writer_c Writer>
template<typename T> template<typename T>
constexpr Error MetalClawWriter<Writer>::field(const char*, const T *val) noexcept { constexpr Error MetalClawWriter<Writer>::field(CString, T const *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 {
@@ -273,7 +273,7 @@ constexpr Error MetalClawWriter<Writer>::field(const char*, const T *val) noexce
OX_RETURN_ERROR(writer.finalize()); OX_RETURN_ERROR(writer.finalize());
fieldSet = writeIdx != m_writer.tellp(); fieldSet = writeIdx != m_writer.tellp();
} }
OX_RETURN_ERROR(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet)); OX_RETURN_ERROR(m_fieldPresence.set(static_cast<size_t>(m_field), fieldSet));
++m_field; ++m_field;
return {}; return {};
} }
@@ -281,35 +281,35 @@ constexpr Error MetalClawWriter<Writer>::field(const char*, const T *val) noexce
template<Writer_c Writer> template<Writer_c Writer>
template<typename U, bool force> template<typename U, bool force>
constexpr Error MetalClawWriter<Writer>::field(const char*, UnionView<U, force> val) noexcept { constexpr Error MetalClawWriter<Writer>::field(CString, UnionView<U, force> val) noexcept {
bool fieldSet = false; bool fieldSet = false;
if (val.get() && (!m_unionIdx.has_value() || *m_unionIdx == m_field)) { if (val.get() && (!m_unionIdx.has_value() || *m_unionIdx == m_field)) {
auto const writeIdx = m_writer.tellp(); auto const writeIdx = m_writer.tellp();
MetalClawWriter<Writer> writer(m_writer, ox::Optional<int>(ox::in_place, val.idx())); MetalClawWriter<Writer> writer(m_writer, Optional<int>(in_place, val.idx()));
ModelHandlerInterface handler{writer}; ModelHandlerInterface handler{writer};
OX_RETURN_ERROR(model(&handler, val.get())); OX_RETURN_ERROR(model(&handler, val.get()));
OX_RETURN_ERROR(writer.finalize()); OX_RETURN_ERROR(writer.finalize());
fieldSet = writeIdx != m_writer.tellp(); fieldSet = writeIdx != m_writer.tellp();
} }
OX_RETURN_ERROR(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet)); OX_RETURN_ERROR(m_fieldPresence.set(static_cast<size_t>(m_field), fieldSet));
++m_field; ++m_field;
return {}; return {};
} }
template<Writer_c Writer> template<Writer_c Writer>
template<typename T> template<typename T>
constexpr Error MetalClawWriter<Writer>::field(const char*, const T *val, std::size_t len) noexcept { constexpr Error MetalClawWriter<Writer>::field(CString, T const *val, size_t const len) noexcept {
bool fieldSet = false; bool fieldSet = false;
if (len && (!m_unionIdx.has_value() || *m_unionIdx == m_field)) { if (len && (!m_unionIdx.has_value() || *m_unionIdx == m_field)) {
// write the length // write the length
const auto arrLen = mc::encodeInteger(len); auto const arrLen = mc::encodeInteger(len);
OX_RETURN_ERROR(m_writer.write(reinterpret_cast<const char*>(arrLen.data.data()), arrLen.length)); OX_RETURN_ERROR(m_writer.write(reinterpret_cast<CString>(arrLen.data.data()), arrLen.length));
auto const writeIdx = m_writer.tellp(); auto const writeIdx = m_writer.tellp();
MetalClawWriter<Writer> writer(m_writer); MetalClawWriter<Writer> writer(m_writer);
ModelHandlerInterface handler{writer}; ModelHandlerInterface handler{writer};
OX_RETURN_ERROR(handler.template setTypeInfo<T>("List", 0, {}, static_cast<std::size_t>(len))); OX_RETURN_ERROR(handler.template setTypeInfo<T>("List", 0, {}, static_cast<size_t>(len)));
// write the array // write the array
for (std::size_t i = 0; i < len; ++i) { for (size_t i{}; i < len; ++i) {
OX_ALLOW_UNSAFE_BUFFERS_BEGIN OX_ALLOW_UNSAFE_BUFFERS_BEGIN
OX_RETURN_ERROR(handler.field("", &val[i])); OX_RETURN_ERROR(handler.field("", &val[i]));
OX_ALLOW_UNSAFE_BUFFERS_END OX_ALLOW_UNSAFE_BUFFERS_END
@@ -317,29 +317,29 @@ OX_ALLOW_UNSAFE_BUFFERS_END
OX_RETURN_ERROR(writer.finalize()); OX_RETURN_ERROR(writer.finalize());
fieldSet = writeIdx != m_writer.tellp(); fieldSet = writeIdx != m_writer.tellp();
} }
OX_RETURN_ERROR(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet)); OX_RETURN_ERROR(m_fieldPresence.set(static_cast<size_t>(m_field), fieldSet));
++m_field; ++m_field;
return {}; return {};
} }
template<Writer_c Writer> template<Writer_c Writer>
template<typename T> template<typename T>
constexpr Error MetalClawWriter<Writer>::field(const char*, const HashMap<String, T> *val) noexcept { constexpr Error MetalClawWriter<Writer>::field(CString, HashMap<String, T> const *val) noexcept {
const auto &keys = val->keys(); auto const &keys = val->keys();
const auto len = keys.size(); auto const len = keys.size();
bool fieldSet = false; bool fieldSet = false;
if (len && (!m_unionIdx.has_value() || *m_unionIdx == m_field)) { if (len && (!m_unionIdx.has_value() || *m_unionIdx == m_field)) {
// write the length // write the length
const auto arrLen = mc::encodeInteger(len); auto const arrLen = mc::encodeInteger(len);
OX_RETURN_ERROR(m_writer.write(reinterpret_cast<const char*>(arrLen.data.data()), arrLen.length)); OX_RETURN_ERROR(m_writer.write(reinterpret_cast<CString>(arrLen.data.data()), arrLen.length));
// write map // write map
MetalClawWriter<Writer> writer(m_writer); MetalClawWriter<Writer> writer(m_writer);
ModelHandlerInterface handler{writer}; ModelHandlerInterface handler{writer};
// double len for both key and value // double len for both key and value
OX_RETURN_ERROR(handler.setTypeInfo("Map", 0, {}, len * 2)); OX_RETURN_ERROR(handler.setTypeInfo("Map", 0, {}, len * 2));
// this loop body needs to be in a lambda because of the potential alloca call // this loop body needs to be in a lambda because of the potential alloca call
constexpr auto loopBody = [](auto &handler, auto const&key, auto const&val) -> ox::Error { constexpr auto loopBody = [](auto &handler, auto const &key, auto const &val) -> Error {
const auto keyLen = key.size(); auto const keyLen = key.size();
auto wkey = ox_malloca(keyLen + 1, char, 0); auto wkey = ox_malloca(keyLen + 1, char, 0);
memcpy(wkey.get(), key.c_str(), keyLen + 1); memcpy(wkey.get(), key.c_str(), keyLen + 1);
OX_RETURN_ERROR(handler.fieldCString("", wkey.get(), keyLen)); OX_RETURN_ERROR(handler.fieldCString("", wkey.get(), keyLen));
@@ -347,26 +347,26 @@ constexpr Error MetalClawWriter<Writer>::field(const char*, const HashMap<String
return handler.field("", value); return handler.field("", value);
}; };
// write the array // write the array
for (std::size_t i = 0; i < len; ++i) { for (size_t i{}; i < len; ++i) {
auto const &key = keys[i]; auto const &key = keys[i];
OX_RETURN_ERROR(loopBody(handler, key, *val)); OX_RETURN_ERROR(loopBody(handler, key, *val));
} }
OX_RETURN_ERROR(writer.finalize()); OX_RETURN_ERROR(writer.finalize());
fieldSet = true; fieldSet = true;
} }
OX_RETURN_ERROR(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet)); OX_RETURN_ERROR(m_fieldPresence.set(static_cast<size_t>(m_field), fieldSet));
++m_field; ++m_field;
return {}; return {};
} }
template<Writer_c Writer> template<Writer_c Writer>
template<typename T> template<typename T>
constexpr ox::Error MetalClawWriter<Writer>::setTypeInfo( constexpr Error MetalClawWriter<Writer>::setTypeInfo(
const char*, CString,
int, int,
const Vector<String>&, Vector<String> const&,
std::size_t fields) noexcept { size_t const fields) noexcept {
const auto fieldPresenceLen = (fields - 1) / 8 + 1; auto const fieldPresenceLen = (fields - 1) / 8 + 1;
OX_RETURN_ERROR(m_writer.write(nullptr, fieldPresenceLen)); OX_RETURN_ERROR(m_writer.write(nullptr, fieldPresenceLen));
m_presenceMapBuff.resize(fieldPresenceLen); m_presenceMapBuff.resize(fieldPresenceLen);
m_fieldPresence.setBuffer(m_presenceMapBuff.data(), m_presenceMapBuff.size()); m_fieldPresence.setBuffer(m_presenceMapBuff.data(), m_presenceMapBuff.size());
@@ -375,17 +375,17 @@ constexpr ox::Error MetalClawWriter<Writer>::setTypeInfo(
} }
template<Writer_c Writer> template<Writer_c Writer>
ox::Error MetalClawWriter<Writer>::finalize() noexcept { Error MetalClawWriter<Writer>::finalize() noexcept {
const auto end = m_writer.tellp(); auto const end = m_writer.tellp();
OX_RETURN_ERROR(m_writer.seekp(m_writerBeginP)); OX_RETURN_ERROR(m_writer.seekp(m_writerBeginP));
OX_RETURN_ERROR(m_writer.write( OX_RETURN_ERROR(m_writer.write(
reinterpret_cast<const char*>(m_presenceMapBuff.data()), reinterpret_cast<CString>(m_presenceMapBuff.data()),
m_presenceMapBuff.size())); m_presenceMapBuff.size()));
OX_RETURN_ERROR(m_writer.seekp(end)); OX_RETURN_ERROR(m_writer.seekp(end));
return {}; return {};
} }
Result<Buffer> writeMC(Writer_c auto &writer, const auto &val) noexcept { Result<Buffer> writeMC(Writer_c auto &writer, auto const &val) noexcept {
MetalClawWriter mcWriter(writer); MetalClawWriter mcWriter(writer);
ModelHandlerInterface handler{mcWriter}; ModelHandlerInterface handler{mcWriter};
OX_RETURN_ERROR(model(&handler, &val)); OX_RETURN_ERROR(model(&handler, &val));
@@ -393,7 +393,7 @@ Result<Buffer> writeMC(Writer_c auto &writer, const auto &val) noexcept {
return {}; return {};
} }
Result<Buffer> writeMC(auto const&val, std::size_t buffReserveSz = 2 * units::KB) noexcept { Result<Buffer> writeMC(auto const &val, size_t const buffReserveSz = 2 * units::KB) noexcept {
Buffer buff(buffReserveSz); Buffer buff(buffReserveSz);
BufferWriter bw(&buff, 0); BufferWriter bw(&buff, 0);
OX_RETURN_ERROR(writeMC(bw, val)); OX_RETURN_ERROR(writeMC(bw, val));
@@ -401,7 +401,7 @@ Result<Buffer> writeMC(auto const&val, std::size_t buffReserveSz = 2 * units::KB
return buff; return buff;
} }
Error writeMC(char *buff, std::size_t buffLen, auto const&val, std::size_t *sizeOut = nullptr) noexcept { Error writeMC(char *buff, size_t const buffLen, auto const &val, size_t *sizeOut = nullptr) noexcept {
CharBuffWriter bw{{buff, buffLen}}; CharBuffWriter bw{{buff, buffLen}};
OX_RETURN_ERROR(writeMC(bw, val)); OX_RETURN_ERROR(writeMC(bw, val));
if (sizeOut) { if (sizeOut) {