11template<
typename BaseContainer>
requires AdjacencyContainer<BaseContainer,typename BaseContainer::node_type>
14 using N =
typename BaseContainer::node_type;
25 std::vector<uint8_t>
get() const noexcept {
26 std::vector<uint8_t> result;
28 auto write_bytes = [&](
const void* data,
size_t size) {
29 const uint8_t* bytes =
static_cast<const uint8_t*
>(data);
30 result.insert(result.end(), bytes, bytes + size);
33 auto write_u64 = [&](uint64_t value) {
34 write_bytes(&value,
sizeof(uint64_t));
38 std::unordered_map<N,uint64_t,typename BaseContainer::hash_function,typename BaseContainer::equality_predicate> nodeToIDMap;
41 std::vector<std::pair<uint64_t,std::vector<uint8_t>>> nodeData;
42 for(
const auto & node: this->
nodes()){
43 uint64_t
id = nodeID++;
44 nodeToIDMap[node] = id;
45 std::vector<uint8_t> data = toBinary(node);
46 nodeData.emplace_back(
id, std::move(data));
50 uint64_t numNodes = nodeData.size();
54 for(
const auto & [
id, data] : nodeData){
56 uint64_t dataSize = data.size();
58 write_bytes(data.data(), dataSize);
69 for(
const auto &[from,to]: edges){
70 uint64_t fromID = nodeToIDMap.at(from);
71 uint64_t toID = nodeToIDMap.at(to);
79 void load(
const std::vector<uint8_t> & data) {
85 auto ensure_bytes = [&](
size_t need){
86 if(offset + need > data.size()){
87 throw std::runtime_error(
"Binary data truncated");
91 auto read_u64 = [&]() -> uint64_t {
92 ensure_bytes(
sizeof(uint64_t));
94 for(
size_t i = 0; i <
sizeof(uint64_t); ++i){
95 v |=
static_cast<uint64_t
>(data[offset + i]) << (8 * i);
97 offset +=
sizeof(uint64_t);
102 uint64_t numNodes = read_u64();
104 std::unordered_map<uint64_t,N> idToNodeMap;
105 idToNodeMap.reserve(numNodes);
108 for(uint64_t i = 0; i < numNodes; ++i){
109 uint64_t nodeID = read_u64();
110 uint64_t dataSize = read_u64();
111 if(dataSize > data.size() - offset){
112 throw std::runtime_error(
"Binary data truncated while reading node payload");
114 std::vector<uint8_t> nodeBytes(data.begin() + offset, data.begin() + offset +
static_cast<size_t>(dataSize));
115 offset +=
static_cast<size_t>(dataSize);
117 N node = fromBinary(nodeBytes);
119 idToNodeMap.emplace(nodeID, std::move(node));
123 uint64_t numEdges = read_u64();
126 for(uint64_t i = 0; i < numEdges; ++i){
127 uint64_t fromID = read_u64();
128 uint64_t toID = read_u64();
129 if(not idToNodeMap.contains(fromID) or not idToNodeMap.contains(toID)){
130 throw std::runtime_error(
"Binary data format error: edge references unknown node id");
132 this->
addAdjacency(idToNodeMap.at(fromID), idToNodeMap.at(toID));
A decorator for adjacency containers that adds additional functionality.
Definition AdjacencyContainerDecorator.hpp:16
auto getAdjacencyPairs() const noexcept
Definition AdjacencyContainerDecorator.hpp:86
auto nodes() const noexcept
Definition AdjacencyContainerDecorator.hpp:82
void addAdjacency(const N &from, const N &to)
Definition AdjacencyContainerDecorator.hpp:30
bool addNode(const N &node)
Definition AdjacencyContainerDecorator.hpp:42
Definition BinaryAdjacency.hpp:12
BinaryAdjacency(BaseContainer &&baseContainer, util::UnaryFunction< N, std::vector< uint8_t > > auto toBinary, util::UnaryFunction< std::vector< uint8_t >, N > auto fromBinary)
Definition BinaryAdjacency.hpp:20
void load(const std::vector< uint8_t > &data)
Definition BinaryAdjacency.hpp:79
std::vector< uint8_t > get() const noexcept
Definition BinaryAdjacency.hpp:25
Definition FunctionalConcepts.hpp:9
Definition AdjacencyContainer.hpp:4
constexpr size_t size(std::ranges::range auto &&range) noexcept
Definition CollectionConcepts.hpp:50
std::function< R(const T &)> UnaryFunction_t
Definition FunctionalConcepts.hpp:12