Program Listing for File deserialization.h#
↰ Return to documentation for file (include/nodes-graph/deserialization.h)
#pragma once
#include <cstring>
#include <map>
#include <set>
#include <string>
#include <vector>
#include "nodes-graph/serialization.h"
namespace ng::deserialization {
namespace sr = ng::serialization;
struct ReadHead {
const sr::buffer_t& buffer;
std::size_t pos = 0;
ReadHead(const sr::buffer_t& buffer) : buffer(buffer) {}
inline std::size_t remaining() const { return (pos < buffer.size()) ? buffer.size() - pos : 0; }
inline void require(std::size_t n) const {
if (n > remaining()) { throw std::runtime_error("Unexpected end of buffer"); }
}
inline const char* c_str() const { return buffer.data() + pos; }
inline void read(void* dst, std::size_t n) {
require(n);
std::memcpy(dst, c_str(), n);
pos += n;
}
};
// --- Base types
sr::len_t deserialize_len(ReadHead& head);
sr::bound_t deserialize_bound(ReadHead& head);
bool deserialize_bool(ReadHead& head);
socket_t deserialize_socket_type(ReadHead& head);
// --- Strings and identifiers
std::string deserialize_string(ReadHead& head);
template <std::size_t N>
std::array<char, N> deserialize_array(ReadHead& head);
qualifier_t deserialize_qualifier(ReadHead& head);
socket_uuid_t deserialize_socket_uuid(ReadHead& head);
link_t deserialize_link(ReadHead& head);
// --- Graph components
struct SocketAttributes {
sr::len_t len;
std::size_t start;
std::string name;
socket_id_t id;
socket_t type;
bool active;
std::set<qualifier_t> on_added_link_callbacks;
std::set<qualifier_t> on_broken_link_callbacks;
};
SocketAttributes deserialize_socket_base(ReadHead& head);
InputSocket deserialize_input_socket(ReadHead& head);
OutputSocket deserialize_output_socket(ReadHead& head);
Node deserialize_node(ReadHead& head);
Graph::InterfaceProperties deserialize_interface_properties(ReadHead& head);
// --- Collections
template <typename T>
std::set<T> deserialize_set(ReadHead& head, T(*deserialize_item)(ReadHead&), sr::bound_t bound);
template <typename U, typename V>
std::map<U, V> deserialize_map(ReadHead& head, U(*deserialize_key)(ReadHead&), V(*deserialize_value)(ReadHead&), sr::bound_t bound);
// ---
class Deserializer {
const sr::buffer_t& buffer_;
Graph graph_;
public:
Deserializer(const sr::buffer_t& buffer) : buffer_(buffer) {}
void deserialize_graph();
inline const Graph& get_graph() const { return graph_; }
};
// -------------------------------------------------------------------------
template <std::size_t N>
std::array<char, N> deserialize_array(ReadHead& head) {
sr::len_t len = deserialize_len(head);
if (len != N)
throw std::runtime_error("Array length does not match the expected size");
std::array<char, N> result;
head.read(result.data(), N);
return result;
}
template <typename T>
std::set<T> deserialize_set(ReadHead& head, T(*deserialize_item)(ReadHead&), sr::bound_t bound) {
std::size_t start = head.pos;
sr::len_t len = deserialize_len(head);
if (deserialize_bound(head) != bound)
throw std::runtime_error("Bound does not match the expected value");
sr::len_t n_items = deserialize_len(head);
std::set<T> result;
for (sr::len_t i = 0; i < n_items; ++i) {
result.insert(deserialize_item(head));
}
if (deserialize_bound(head) != bound)
throw std::runtime_error("Bound does not match the expected value at the end of the set");
if (result.size() != n_items)
throw std::runtime_error("Number of deserialized items does not match the expected count");
if (len != head.pos - start)
throw std::runtime_error("Set length does not match the expected size");
return result;
}
template <typename U, typename V>
std::map<U, V> deserialize_map(ReadHead& head, U(*deserialize_key)(ReadHead&), V(*deserialize_value)(ReadHead&), sr::bound_t bound) {
std::size_t start = head.pos;
sr::len_t len = deserialize_len(head);
if (deserialize_bound(head) != bound)
throw std::runtime_error("Bound does not match the expected value");
sr::len_t n_items = deserialize_len(head);
std::map<U, V> result;
for (sr::len_t i = 0; i < n_items; ++i) {
U key = deserialize_key(head);
V value = deserialize_value(head);
result.emplace(std::move(key), std::move(value));
}
if (deserialize_bound(head) != bound)
throw std::runtime_error("Bound does not match the expected value at the end of the map");
if (result.size() != n_items)
throw std::runtime_error("Number of deserialized items does not match the expected count");
if (len != head.pos - start)
throw std::runtime_error("Map length does not match the expected size");
return result;
}
} // namespace ng::deserialization