/* * Copyright 2015 - 2025 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 https://mozilla.org/MPL/2.0/. */ #pragma once #include #ifdef OX_USE_STDLIB #include #endif #include #include #include #include "format.hpp" namespace ox { namespace detail { struct TypeInfoCatcher { const char *name = nullptr; int version = 0; template constexpr ox::Error setTypeInfo( const char *pName = T::TypeName, int pVersion = T::TypeVersion, const Vector& = {}, std::size_t = 0) noexcept { this->name = pName; this->version = pVersion; return {}; } constexpr Error field(...) noexcept { return {}; } static constexpr auto opType() { return OpType::Write; } }; template struct type_version { static constexpr auto value = -1; }; template struct type_version { static constexpr auto value = T::TypeVersion; }; template constexpr const char *getTypeName(const T *t) noexcept { TypeInfoCatcher tnc; std::ignore = model(&tnc, t); return tnc.name; } template constexpr int getTypeVersion(const T *t) noexcept { TypeInfoCatcher tnc; std::ignore = model(&tnc, t); return tnc.version; } template ox::Error writeClawHeader(Writer_c auto &writer, const T *t, ClawFormat fmt) noexcept { switch (fmt) { case ClawFormat::Metal: OX_RETURN_ERROR(write(writer, "M2;")); break; case ClawFormat::Organic: OX_RETURN_ERROR(write(writer, "O1;")); break; default: return ox::Error(1); } OX_RETURN_ERROR(write(writer, detail::getTypeName(t))); OX_RETURN_ERROR(writer.put(';')); const auto tn = detail::getTypeVersion(t); if (tn > -1) { OX_RETURN_ERROR(ox::writeItoa(tn, writer)); } OX_RETURN_ERROR(writer.put(';')); return {}; } } Result writeClaw( const auto &t, ClawFormat fmt = ClawFormat::Metal, std::size_t buffReserveSz = 2 * units::KB) noexcept { Buffer out(buffReserveSz); BufferWriter bw(&out, 0); OX_RETURN_ERROR(detail::writeClawHeader(bw, &t, fmt)); #ifdef OX_USE_STDLIB if (fmt == ClawFormat::Metal) { OX_RETURN_ERROR(writeMC(bw, t)); } else if (fmt == ClawFormat::Organic) { OX_REQUIRE(data, writeOC(t)); OX_RETURN_ERROR(bw.write(data.data(), data.size())); } #else if (fmt != ClawFormat::Metal) { return ox::Error(1, "OC is not supported in this build"); } OX_RETURN_ERROR(writeMC(bw, t)); #endif out.resize(bw.tellp()); return out; } }