diff options
Diffstat (limited to '')
| -rw-r--r-- | src/MultigroupCodec.cpp | 78 |
1 files changed, 78 insertions, 0 deletions
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<RelationEntry>& relations) + { + std::string root; + for (const auto& [name, root_hex] : relations) + root = nt::Merkle<std::string>::Insert(store, root, name, + encode_payload(root_hex)); + return root; + } + + std::vector<RelationEntry> List(IStorageBackend& store, + const std::string& root_hex) + { + std::vector<RelationEntry> out; + constexpr size_t kPageSize = 1024; + size_t offset = 0; + while (true) + { + auto page = nt::Merkle<std::string>::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<std::string>::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<std::string>::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<std::string>::Get(store, root_hex, relation_name); + if (!found) return ""; + return decode_payload(*found); + } +} |
