From f48824793cfce315971fe2e699ece198c7a79407 Mon Sep 17 00:00:00 2001 From: Gary Talent Date: Sat, 11 May 2024 02:09:10 -0500 Subject: [PATCH] Squashed 'deps/nostalgia/' changes from 17f28d43..7233da75 7233da75 [ox/std] Remove dedicated keys array from SmallMap 30797c71 [ox/std] Add small sz option to SmallMap e8041121 [ox/std] Add missing oxExpect to timeMapStrToUuid d054528e [ox/std] Remove empty if from SmallMap 09d840cf [ox/std] Add some functions for comparing HashMap and SmallMap aeb1ef3b [ox/std] Cleanup SmallMap, make it easier to make potential changes b66f61c2 [ox/std] Add hash function for UUID b089bf46 [ox/std] Optimize Array compare cd60c4ab [ox/std] Fix bugs in HashMap and SmallMap d1845448 [ox/std] Add == and != operators to UUID c4f6ee00 [nostalgia,olympic] Make performPackTransforms update type id when needed git-subtree-dir: deps/nostalgia git-subtree-split: 7233da75eaaea055ed0486895fc85606db86d0f4 --- deps/ox/src/ox/std/array.hpp | 12 +- deps/ox/src/ox/std/hashmap.hpp | 17 +- deps/ox/src/ox/std/smallmap.hpp | 197 +++++++++--------- deps/ox/src/ox/std/test/CMakeLists.txt | 4 +- deps/ox/src/ox/std/test/tests.cpp | 157 +++++++++++++- deps/ox/src/ox/std/uuid.hpp | 34 ++- .../modules/core/src/keel/keelmodule.cpp | 18 +- src/olympic/keel/include/keel/context.hpp | 2 +- src/olympic/keel/include/keel/typeconv.hpp | 5 +- src/olympic/keel/src/media.cpp | 8 +- 10 files changed, 328 insertions(+), 126 deletions(-) diff --git a/deps/ox/src/ox/std/array.hpp b/deps/ox/src/ox/std/array.hpp index d20a618..242010f 100644 --- a/deps/ox/src/ox/std/array.hpp +++ b/deps/ox/src/ox/std/array.hpp @@ -137,12 +137,16 @@ constexpr Array::Array(Array &&other) noexcept { template constexpr bool Array::operator==(const Array &other) const { - for (std::size_t i = 0; i < ArraySize; i++) { - if (!(m_items[i] == other.m_items[i])) { - return false; + if (std::is_constant_evaluated()) { + for (std::size_t i = 0; i < ArraySize; i++) { + if (!(m_items[i] == other.m_items[i])) { + return false; + } } + return true; + } else { + return memcmp(this, &other, sizeof(*this)) == 0; } - return true; } template diff --git a/deps/ox/src/ox/std/hashmap.hpp b/deps/ox/src/ox/std/hashmap.hpp index 2475359..d38e2c8 100644 --- a/deps/ox/src/ox/std/hashmap.hpp +++ b/deps/ox/src/ox/std/hashmap.hpp @@ -133,17 +133,18 @@ constexpr HashMap &HashMap::operator=(HashMap &&other) noexcep template constexpr T &HashMap::operator[](MaybeView_t const&k) { - auto &p = access(m_pairs, k); - if (p == nullptr) { + auto p = &access(m_pairs, k); + if (*p == nullptr) { if (static_cast(m_pairs.size()) * 0.7 < static_cast(m_keys.size())) { expand(); + p = &access(m_pairs, k); } - p = new Pair; - p->key = k; + *p = new Pair; + (*p)->key = k; m_keys.emplace_back(k); } - return p->value; + return (*p)->value; } template @@ -208,7 +209,7 @@ constexpr void HashMap::clear() { template constexpr void HashMap::expand() { - Vector r; + Vector r(m_pairs.size() * 2); for (std::size_t i = 0; i < m_keys.size(); ++i) { auto const&k = m_keys[i]; access(r, k) = std::move(access(m_pairs, k)); @@ -221,7 +222,7 @@ template constexpr typename HashMap::Pair *const&HashMap::access(Vector const&pairs, KK const&k) const { auto h = static_cast(ox::hash{}(k) % pairs.size()); while (true) { - const auto &p = pairs[h]; + auto const&p = *pairs.at(h).unwrap(); if (p == nullptr || p->key == k) { return p; } else { @@ -235,7 +236,7 @@ template constexpr typename HashMap::Pair *&HashMap::access(Vector &pairs, KK const&k) { auto h = static_cast(ox::hash{}(k) % pairs.size()); while (true) { - auto &p = pairs[h]; + auto &p = *pairs.at(h).unwrap(); if (p == nullptr || p->key == k) { return p; } else { diff --git a/deps/ox/src/ox/std/smallmap.hpp b/deps/ox/src/ox/std/smallmap.hpp index 76ad937..28f2d43 100644 --- a/deps/ox/src/ox/std/smallmap.hpp +++ b/deps/ox/src/ox/std/smallmap.hpp @@ -17,23 +17,23 @@ namespace ox { -template +template class SmallMap { public: using key_t = K; using value_t = T; - - private: struct Pair { K key = {}; T value{}; }; - Vector m_keys; - Vector m_pairs; + + private: + using PairVector = Vector; + PairVector m_pairs; public: - explicit constexpr SmallMap(std::size_t size = 127); + constexpr SmallMap() = default; constexpr SmallMap(SmallMap const&other); @@ -62,92 +62,84 @@ class SmallMap { constexpr std::size_t size() const noexcept; [[nodiscard]] - constexpr Vector const&keys() const noexcept; + constexpr Vector keys() const noexcept; + + [[nodiscard]] + constexpr K const&key(size_t i) const noexcept; + + [[nodiscard]] + constexpr T const&value(size_t i) const noexcept; + + [[nodiscard]] + constexpr T &value(size_t i) noexcept; + + [[nodiscard]] + constexpr Pair const&get(size_t i) const noexcept; + + [[nodiscard]] + constexpr Pair &get(size_t i) noexcept; constexpr void clear(); private: - constexpr void expand(); + template + constexpr Pair const&access(PairVector const&pairs, KK const&key, bool &isNew) const; template - constexpr Pair *const&access(Vector const&pairs, KK const&key) const; - - template - constexpr Pair *&access(Vector &pairs, KK const&key); + constexpr Pair &access(PairVector &pairs, KK const&key, bool &isNew); }; -template -constexpr SmallMap::SmallMap(std::size_t size): m_pairs(size) { -} - -template -constexpr SmallMap::SmallMap(SmallMap const&other) { +template +constexpr SmallMap::SmallMap(SmallMap const&other) { m_pairs = other.m_pairs; } -template -constexpr SmallMap::SmallMap(SmallMap &&other) noexcept { - m_keys = std::move(other.m_keys); +template +constexpr SmallMap::SmallMap(SmallMap &&other) noexcept { m_pairs = std::move(other.m_pairs); } -template -constexpr SmallMap::~SmallMap() { +template +constexpr SmallMap::~SmallMap() { clear(); } -template -constexpr bool SmallMap::operator==(SmallMap const&other) const { - if (m_keys != other.m_keys) { - return false; - } - for (int i = 0; i < m_keys.size(); ++i) { - auto &k = m_keys[i]; - if (at(k) != other.at(k)) { - return false; - } - } - return true; +template +constexpr bool SmallMap::operator==(SmallMap const&other) const { + return m_pairs == other.m_pairs; } -template -constexpr SmallMap &SmallMap::operator=(SmallMap const&other) { +template +constexpr SmallMap &SmallMap::operator=(SmallMap const&other) { if (this != &other) { clear(); - m_keys = other.m_keys; m_pairs = other.m_pairs; } return *this; } -template -constexpr SmallMap &SmallMap::operator=(SmallMap &&other) noexcept { +template +constexpr SmallMap &SmallMap::operator=(SmallMap &&other) noexcept { if (this != &other) { clear(); - m_keys = std::move(other.m_keys); m_pairs = std::move(other.m_pairs); } return *this; } -template -constexpr T &SmallMap::operator[](MaybeView_t const&k) { - auto &p = access(m_pairs, k); - if (p == nullptr) { - if (static_cast(m_pairs.size()) * 0.7 < - static_cast(m_keys.size())) { - expand(); - } - p = new Pair; +template +constexpr T &SmallMap::operator[](MaybeView_t const&k) { + bool isNew{}; + auto p = &access(m_pairs, k, isNew); + if (isNew) { p->key = k; - m_keys.emplace_back(k); } return p->value; } -template -constexpr Result SmallMap::at(MaybeView_t const&k) noexcept { +template +constexpr Result SmallMap::at(MaybeView_t const&k) noexcept { auto p = access(m_pairs, k); if (!p) { return {nullptr, OxError(1, "value not found for given key")}; @@ -155,8 +147,8 @@ constexpr Result SmallMap::at(MaybeView_t const&k) noexcept { return &p->value; } -template -constexpr Result SmallMap::at(MaybeView_t const&k) const noexcept { +template +constexpr Result SmallMap::at(MaybeView_t const&k) const noexcept { auto p = access(m_pairs, k); if (!p) { return {nullptr, OxError(1, "value not found for given key")}; @@ -164,8 +156,8 @@ constexpr Result SmallMap::at(MaybeView_t const&k) const noex return &p->value; } -template -constexpr void SmallMap::erase(MaybeView_t const&k) { +template +constexpr void SmallMap::erase(MaybeView_t const&k) { size_t i{}; for (auto const&p : m_pairs) { if (k == p.key) { @@ -174,65 +166,84 @@ constexpr void SmallMap::erase(MaybeView_t const&k) { ++i; } std::ignore = m_pairs.erase(i); - std::ignore = m_keys.erase(i); } -template -constexpr bool SmallMap::contains(MaybeView_t const&k) const noexcept { +template +constexpr bool SmallMap::contains(MaybeView_t const&k) const noexcept { return access(m_pairs, k) != nullptr; } -template -constexpr std::size_t SmallMap::size() const noexcept { - return m_keys.size(); +template +constexpr std::size_t SmallMap::size() const noexcept { + return m_pairs.size(); } -template -constexpr Vector const&SmallMap::keys() const noexcept { - return m_keys; -} - -template -constexpr void SmallMap::clear() { - for (std::size_t i = 0; i < m_pairs.size(); i++) { - delete m_pairs[i]; +template +constexpr Vector SmallMap::keys() const noexcept { + ox::Vector keys; + keys.reserve(m_pairs.size()); + for (auto const&p : m_pairs) { + keys.emplace_back(p.key); } + return keys; +} + +template +constexpr K const&SmallMap::key(size_t i) const noexcept { + return m_pairs[i].key; +} + +template +constexpr T const&SmallMap::value(size_t i) const noexcept { + return m_pairs[i].value; +} + +template +constexpr T &SmallMap::value(size_t i) noexcept { + return m_pairs[i].value; +} + +template +constexpr SmallMap::Pair const&SmallMap::get(size_t i) const noexcept { + return m_pairs[i]; +} + +template +constexpr SmallMap::Pair &SmallMap::get(size_t i) noexcept { + return m_pairs[i]; +} + +template +constexpr void SmallMap::clear() { m_pairs.clear(); - m_pairs.resize(127); } -template -constexpr void SmallMap::expand() { - Vector r; - for (std::size_t i = 0; i < m_keys.size(); ++i) { - auto const&k = m_keys[i]; - access(r, k) = std::move(access(m_pairs, k)); - } - m_pairs = std::move(r); -} - -template +template template -constexpr typename SmallMap::Pair *const&SmallMap::access( - Vector const&pairs, KK const&k) const { +constexpr typename SmallMap::Pair const&SmallMap::access( + PairVector const&pairs, KK const&k, bool &isNew) const { for (auto const&p : pairs) { if (p.key == k) { - return &p; + isNew = false; + return p; } } - return nullptr; + isNew = true; + return pairs.emplace_back(); } -template +template template -constexpr typename SmallMap::Pair *&SmallMap::access( - Vector &pairs, KK const&k) { +constexpr typename SmallMap::Pair &SmallMap::access( + PairVector &pairs, KK const&k, bool &isNew) { for (auto &p : pairs) { if (p.key == k) { - return &p; + isNew = false; + return p; } } - return nullptr; + isNew = true; + return pairs.emplace_back(); } } diff --git a/deps/ox/src/ox/std/test/CMakeLists.txt b/deps/ox/src/ox/std/test/CMakeLists.txt index d0c7da2..9c395b9 100644 --- a/deps/ox/src/ox/std/test/CMakeLists.txt +++ b/deps/ox/src/ox/std/test/CMakeLists.txt @@ -12,8 +12,10 @@ add_test("[ox/std] ox_memcmp HIJKLMN != ABCDEFG" ${CMAKE_RUNTIME_OUTPUT_DIRECTOR add_test("[ox/std] ox_memcmp ABCDEFG == ABCDEFG" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/StdTest "ABCDEFG == ABCDEFG") add_test("[ox/std] ox_memcmp ABCDEFGHI == ABCDEFG" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/StdTest "ABCDEFGHI == ABCDEFG") add_test("[ox/std] itoa" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/StdTest "itoa") -add_test("[ox/std] BString" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/StdTest "BString") +add_test("[ox/std] IString" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/StdTest "IString") add_test("[ox/std] String" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/StdTest "String") +add_test("[ox/std] SmallMap" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/StdTest "SmallMap") +add_test("[ox/std] SmallMap2" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/StdTest "SmallMap2") add_test("[ox/std] Vector" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/StdTest "Vector") add_test("[ox/std] HashMap" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/StdTest "HashMap") add_test("[ox/std] HeapMgr" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/StdTest malloc) diff --git a/deps/ox/src/ox/std/test/tests.cpp b/deps/ox/src/ox/std/test/tests.cpp index 8345409..e0ad716 100644 --- a/deps/ox/src/ox/std/test/tests.cpp +++ b/deps/ox/src/ox/std/test/tests.cpp @@ -6,13 +6,112 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ -#include "ox/std/def.hpp" +#if __has_include() +#include +#endif + +#include #undef NDEBUG #include #include #include +[[nodiscard]] +static uint64_t nowMs() { +#if __has_include() + using namespace std::chrono; + return static_cast( + duration_cast( + system_clock::now().time_since_epoch()).count()); +#else + return 0; +#endif +} + +template> +uint64_t timeMapStrToUuid(int elemCnt, int lookups, uint64_t seed = 4321) noexcept { + ox::UUID::seedGenerator({1234, seed}); + Map map; + // setup test map + for (int i = 0; i < elemCnt; ++i) { + auto const uuid = ox::UUID::generate().unwrap(); + map[uuid.toString()] = uuid; + } + auto const keys = map.keys(); + ox::Random rand; + // start + auto const startTime = nowMs(); + for (int i = 0; i < lookups; ++i) { + auto const&k = keys[rand.gen() % keys.size()]; + map[k]; + oxExpect(map[k], ox::UUID::fromString(k).unwrap()); + } + return nowMs() - startTime; +} + +template> +uint64_t timeMapUuidToStr(int elemCnt, int lookups, uint64_t seed = 4321) noexcept { + ox::UUID::seedGenerator({1234, seed}); + Map map; + // setup test map + for (int i = 0; i < elemCnt; ++i) { + auto const uuid = ox::UUID::generate().unwrap(); + map[uuid] = uuid.toString(); + } + auto const keys = map.keys(); + ox::Random rand; + // start + auto const startTime = nowMs(); + for (int i = 0; i < lookups; ++i) { + auto const&k = keys[rand.gen() % keys.size()]; + oxExpect(map[k], k.toString()); + } + return nowMs() - startTime; +} + +static ox::Error compareMaps(int lookupCnt = 1'000'000) { + auto const seed = nowMs(); + uint64_t hashTime{}; + uint64_t smallTime{}; + int elemCnt = 1; + oxOut("UUIDStr to UUID:\n\n"); + while (hashTime >= smallTime) { + smallTime = timeMapStrToUuid>(elemCnt, lookupCnt, seed); + hashTime = timeMapStrToUuid>(elemCnt, lookupCnt, seed); + oxOutf( + "UUIDStr to UUID: elemCnt: {}, lookupCnt: {} - hash map time: {}ms, small map time: {}ms\n", + elemCnt, lookupCnt, hashTime, smallTime); + ++elemCnt; + } + oxOut("\n\nString to UUID:\n\n"); + hashTime = 0; + smallTime = 0; + elemCnt = 1; + while (hashTime >= smallTime) { + smallTime = timeMapStrToUuid>(elemCnt, lookupCnt, seed); + hashTime = timeMapStrToUuid>(elemCnt, lookupCnt, seed); + oxOutf( + "String to UUID: elemCnt: {}, lookupCnt: {} - hash map time: {}ms, small map time: {}ms\n", + elemCnt, lookupCnt, hashTime, smallTime); + ++elemCnt; + } + oxOut("\n\nUUID to UUIDStr:\n\n"); + hashTime = 0; + smallTime = 0; + elemCnt = 1; + while (hashTime >= smallTime) { + smallTime = timeMapUuidToStr>(elemCnt, lookupCnt, seed); + hashTime = timeMapUuidToStr>(elemCnt, lookupCnt, seed); + oxOutf( + "UUID to UUIDStr: elemCnt: {}, lookupCnt: {} - hash map time: {}ms, small map time: {}ms\n", + elemCnt, lookupCnt, hashTime, smallTime); + ++elemCnt; + } + oxOut("\n"); + return {}; +} + static std::map tests = { { "malloc", @@ -23,6 +122,8 @@ static std::map tests = { auto a2 = static_cast(ox::heapmgr::malloc(5)); oxAssert(a1 >= buff.front().unwrap() && a1 < buff.back().unwrap(), "malloc is broken"); oxAssert(a2 >= buff.front().unwrap() && a2 < buff.back().unwrap() && a2 > a1 + 5, "malloc is broken"); + ox::heapmgr::free(a1); + ox::heapmgr::free(a2); return OxError(0); } }, @@ -67,14 +168,14 @@ static std::map tests = { } }, { - "BString", + "IString", []() { ox::IString<5> s; oxReturnError(s.append("A")); oxReturnError(s.append("B")); oxReturnError(s.append("9")); oxReturnError(s.append("C")); - oxAssert(s == "AB9C", "BString append broken"); + oxAssert(s == "AB9C", "IString append broken"); s = "asdf"; oxAssert(s == "asdf", "String assign broken"); oxAssert(s != "aoeu", "String assign broken"); @@ -134,10 +235,38 @@ static std::map tests = { return OxError(0); } }, + { + "SmallMap", + [] { + ox::SmallMap map; + map["asdf"] = "aoeu"; + oxExpect(map["asdf"], "aoeu"); + oxExpect(map.size(), 1u); + oxExpect(map["aoeu"], ""); + oxExpect(map.size(), 2u); + return OxError(0); + } + }, + { + "SmallMap2", + [] { + ox::SmallMap si; + si["asdf"] = 42; + si["aoeu"] = 100; + oxAssert(si["asdf"] == 42, "asdf != 42"); + oxAssert(si["aoeu"] == 100, "aoeu != 100"); + ox::SmallMap ii; + ii[4] = 42; + ii[5] = 100; + oxAssert(ii[4] == 42, "4 != 42"); + oxAssert(ii[5] == 100, "5 != 100"); + return OxError(0); + } + }, { "HashMap", [] { - ox::HashMap si; + ox::HashMap si; si["asdf"] = 42; si["aoeu"] = 100; oxAssert(si["asdf"] == 42, "asdf != 42"); @@ -150,6 +279,26 @@ static std::map tests = { return OxError(0); } }, + { + "TimeSmallMapMillion", + [] { + timeMapStrToUuid>(1'000, 1'000'000); + return ox::Error{}; + } + }, + { + "TimeHashMapMillion", + [] { + timeMapStrToUuid>(1'000, 1'000'000); + return ox::Error{}; + } + }, + { + "CompareMaps", + [] { + return compareMaps(); + } + }, { "Serialize-Int", [] { diff --git a/deps/ox/src/ox/std/uuid.hpp b/deps/ox/src/ox/std/uuid.hpp index d2d783b..80b66f1 100644 --- a/deps/ox/src/ox/std/uuid.hpp +++ b/deps/ox/src/ox/std/uuid.hpp @@ -8,9 +8,11 @@ #pragma once +#include "bit.hpp" #include "ignore.hpp" #include "istring.hpp" #include "buffer.hpp" +#include "hash.hpp" #include "random.hpp" #include "ranges.hpp" #include "stringview.hpp" @@ -105,7 +107,7 @@ class UUID { static ox::Result generate() noexcept; [[nodiscard]] - constexpr auto value() const noexcept { + constexpr auto const&value() const noexcept { return m_value; } @@ -118,8 +120,8 @@ class UUID { return false; } else { constexpr uint64_t zero = 0; - return ox::memcmp(&zero, m_value.data() + 0, 8) == 0 - && ox::memcmp(&zero, m_value.data() + 8, 8) == 0; + return memcmp(&zero, m_value.data() + 0, 8) == 0 + && memcmp(&zero, m_value.data() + 8, 8) == 0; } } @@ -146,6 +148,14 @@ class UUID { return out; } + constexpr bool operator==(UUID const&o) const noexcept { + return m_value == o.m_value; + } + + constexpr bool operator!=(UUID const&o) const noexcept { + return !operator==(o); + } + [[nodiscard]] constexpr ox::Error toString(Writer_c auto &writer) const noexcept { auto valueI = 0u; @@ -184,6 +194,24 @@ class UUID { } }; + +template<> +struct hash { + [[nodiscard]] + constexpr size_t operator()(ox::UUID v) const noexcept { + size_t out{}; + if (std::is_constant_evaluated()) { + for (auto i = 0u; i < sizeof(out); ++i) { + out |= static_cast(v.value()[i]) << (i * 8); + } + } else { + memcpy(&out, &v, sizeof(out)); + } + return out; + } +}; + + template constexpr Error model(T *io, ox::CommonPtrWith auto *obj) noexcept { oxReturnError(io->template setTypeInfo()); diff --git a/src/nostalgia/modules/core/src/keel/keelmodule.cpp b/src/nostalgia/modules/core/src/keel/keelmodule.cpp index 4322194..140dfa7 100644 --- a/src/nostalgia/modules/core/src/keel/keelmodule.cpp +++ b/src/nostalgia/modules/core/src/keel/keelmodule.cpp @@ -58,23 +58,25 @@ static class: public keel::Module { ox::Vector packTransforms() const noexcept final { return { // convert tilesheets to CompactTileSheets - [](keel::Context &ctx, ox::Buffer &buff, ox::StringView typeId) -> ox::Error { + [](keel::Context &ctx, ox::Buffer &buff, ox::StringView typeId) -> ox::Result { if (typeId == ox::ModelTypeId_v || typeId == ox::ModelTypeId_v || typeId == ox::ModelTypeId_v || typeId == ox::ModelTypeId_v) { - return keel::convertBuffToBuff( - ctx, buff, ox::ClawFormat::Metal).moveTo(buff); + oxReturnError(keel::convertBuffToBuff( + ctx, buff, ox::ClawFormat::Metal).moveTo(buff)); + return true; } - return {}; + return false; }, - [](keel::Context &ctx, ox::Buffer &buff, ox::StringView typeId) -> ox::Error { + [](keel::Context &ctx, ox::Buffer &buff, ox::StringView typeId) -> ox::Result { if (typeId == ox::ModelTypeId_v || typeId == ox::ModelTypeId_v) { - return keel::convertBuffToBuff( - ctx, buff, ox::ClawFormat::Metal).moveTo(buff); + oxReturnError(keel::convertBuffToBuff( + ctx, buff, ox::ClawFormat::Metal).moveTo(buff)); + return true; } - return {}; + return false; }, }; } diff --git a/src/olympic/keel/include/keel/context.hpp b/src/olympic/keel/include/keel/context.hpp index 30847cb..a34d8a1 100644 --- a/src/olympic/keel/include/keel/context.hpp +++ b/src/olympic/keel/include/keel/context.hpp @@ -12,7 +12,7 @@ namespace keel { class Context; -using PackTransform = ox::Error(*)(Context&, ox::Buffer &clawData, ox::StringView); +using PackTransform = ox::Result(*)(Context&, ox::Buffer &clawData, ox::StringView); class Context { public: diff --git a/src/olympic/keel/include/keel/typeconv.hpp b/src/olympic/keel/include/keel/typeconv.hpp index 2ece88c..b2c51a6 100644 --- a/src/olympic/keel/include/keel/typeconv.hpp +++ b/src/olympic/keel/include/keel/typeconv.hpp @@ -162,11 +162,12 @@ ox::Result convertBuffToBuff( } template -auto transformRule(keel::Context &ctx, ox::Buffer &buff, ox::StringView typeId) noexcept -> ox::Error { +ox::Result transformRule(keel::Context &ctx, ox::Buffer &buff, ox::StringView typeId) noexcept { if (typeId == ox::ModelTypeId_v) { oxReturnError(keel::convertBuffToBuff(ctx, buff, fmt).moveTo(buff)); + return true; } - return {}; + return false; }; diff --git a/src/olympic/keel/src/media.cpp b/src/olympic/keel/src/media.cpp index 682f34a..29572f1 100644 --- a/src/olympic/keel/src/media.cpp +++ b/src/olympic/keel/src/media.cpp @@ -102,9 +102,13 @@ ox::Result uuidToPath(Context &ctx, ox::UUID const&uuid) noexcept { } ox::Error performPackTransforms(Context &ctx, ox::Buffer &clawData) noexcept { - oxRequire(typeId, readAssetTypeId(clawData).to()); + oxRequireM(typeId, readAssetTypeId(clawData)); for (auto const tr : packTransforms(ctx)) { - oxReturnError(tr(ctx, clawData, typeId)); + bool changed{}; + oxReturnError(tr(ctx, clawData, typeId).moveTo(changed)); + if (changed) { + oxReturnError(readAssetTypeId(clawData).moveTo(typeId)); + } } return {}; }