From af8759a9c1d965a3220024d1857aea219d62d898 Mon Sep 17 00:00:00 2001 From: Marcos Magueta Date: Mon, 18 May 2026 12:50:25 -0300 Subject: Branching and object registry rework (#11) --- src/MultigroupCodec.cpp | 78 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 src/MultigroupCodec.cpp (limited to 'src/MultigroupCodec.cpp') diff --git a/src/MultigroupCodec.cpp b/src/MultigroupCodec.cpp new file mode 100644 index 0000000..81d305c --- /dev/null +++ b/src/MultigroupCodec.cpp @@ -0,0 +1,78 @@ +#include "MultigroupCodec.h" + +#include "Merkle.h" + +namespace nt::MultigroupCodec +{ + // A relation with zero tuples reports an empty merkle_root externally. + // The merkle tree's payload type is fixed-width Hash32, so the codec + // maps "" ↔ the all-zero hash. The collision probability with a real + // SHA256 hitting all-zero (2^-256) is treated as unreachable. + static nt::Hash32 encode_payload(const std::string& hex) + { + if (hex.empty()) return nt::Hash32{}; + return nt::hex_to_bin(hex); + } + + static std::string decode_payload(const nt::Hash32& bin) + { + static const nt::Hash32 zero{}; + if (bin == zero) return ""; + return nt::bin_to_hex(bin); + } + + std::string Build(IStorageBackend& store, + const std::vector& relations) + { + std::string root; + for (const auto& [name, root_hex] : relations) + root = nt::Merkle::Insert(store, root, name, + encode_payload(root_hex)); + return root; + } + + std::vector List(IStorageBackend& store, + const std::string& root_hex) + { + std::vector out; + constexpr size_t kPageSize = 1024; + size_t offset = 0; + while (true) + { + auto page = nt::Merkle::Page(store, root_hex, + offset, kPageSize); + if (page.empty()) break; + for (auto& entry : page) + out.emplace_back(std::move(entry.key), + decode_payload(entry.payload)); + if (page.size() < kPageSize) break; + offset += page.size(); + } + return out; + } + + std::string InsertOne(IStorageBackend& store, + const std::string& root_hex, + const std::string& relation_name, + const std::string& relation_root_hex) + { + return nt::Merkle::Insert(store, root_hex, relation_name, + encode_payload(relation_root_hex)); + } + + std::string RemoveOne(IStorageBackend& store, + const std::string& root_hex, + const std::string& relation_name) + { + return nt::Merkle::Remove(store, root_hex, relation_name); + } + + std::string Lookup(IStorageBackend& store, + const std::string& root_hex, + const std::string& relation_name) + { + auto found = nt::Merkle::Get(store, root_hex, relation_name); + if (!found) return ""; + return decode_payload(*found); + } +} -- cgit v1.2.3