Program Listing for File serialization.cc#
↰ Return to documentation for file (src/serialization.cc)
#include "nodes-graph/serialization.h"
namespace ng::serialization {
static_assert(sizeof(bool) == 1, "Booleans are serialized on a single byte");
namespace {
template <typename T>
void append_raw(buffer_t& buffer, const T& value) {
buffer.insert(
buffer.end(),
reinterpret_cast<const char*>(&value),
reinterpret_cast<const char*>(&value) + sizeof(T)
);
}
} // namespace
bool is_sup_or_equal(const version_t& a, const version_t& b) {
for (std::size_t i = 0; i < a.size(); ++i) {
if (a[i] > b[i]) return true;
if (a[i] < b[i]) return false;
}
return true;
}
void add_length_prefix(buffer_t& buffer) {
len_t len = buffer.size() + LEN;
buffer.insert(
buffer.begin(),
reinterpret_cast<char*>(&len),
reinterpret_cast<char*>(&len) + LEN
);
}
// --- Base types are just added to the buffer as such, they are not prefixed by their length in bytes.
void serialize(buffer_t& buffer, len_t l) { append_raw(buffer, l); }
void serialize(buffer_t& buffer, bound_t b) { append_raw(buffer, b); }
void serialize(buffer_t& buffer, bool s) { append_raw(buffer, s); }
void serialize(buffer_t& buffer, socket_t type) { append_raw(buffer, type); }
// --- Strings are serialized as a sequence of characters including the null terminator, prefixed by their length in bytes.
void serialize_bytes(buffer_t& buffer, const char* s, len_t l) {
serialize(buffer, l);
buffer.insert(buffer.end(), s, s + l);
}
void serialize(buffer_t& buffer, const std::string& s) {
serialize_bytes(buffer, s.c_str(), static_cast<len_t>(s.size() + 1));
}
void serialize(buffer_t& buffer, const qualifier_t& qualifier) {
buffer_t b;
for (std::size_t i = 0 ; i < qualifier_t::N_CHUNKS; ++i) {
serialize(b, qualifier.chunks[i]);
}
add_length_prefix(b);
buffer.insert(buffer.end(), b.begin(), b.end());
}
void serialize(buffer_t& buffer, const socket_uuid_t& socket_uuid) {
buffer_t b;
serialize(b, socket_uuid.first);
serialize(b, socket_uuid.second);
add_length_prefix(b);
buffer.insert(buffer.end(), b.begin(), b.end());
}
void serialize(buffer_t& buffer, const link_t& link) {
buffer_t b;
serialize(b, link.first);
serialize(b, link.second);
add_length_prefix(b);
buffer.insert(buffer.end(), b.begin(), b.end());
}
// --- Graph components
void serialize_socket_base(buffer_t& buffer, const Socket& socket) {
serialize(buffer, socket.get_name());
serialize(buffer, socket.get_id());
serialize(buffer, socket.get_type());
serialize(buffer, socket.is_active());
serialize(buffer, socket.get_on_added_link_callbacks(), Bounds::callbacks);
serialize(buffer, socket.get_on_broken_link_callbacks(), Bounds::callbacks);
}
void serialize(buffer_t& buffer, const InputSocket& socket) {
buffer_t b;
serialize_socket_base(b, socket);
serialize(b, socket.get_value());
serialize(b, socket.get_allowed_values(), Bounds::whitelist);
serialize(b, socket.is_linkable());
serialize(b, socket.get_on_value_changed_callbacks(), Bounds::callbacks);
add_length_prefix(b);
buffer.insert(buffer.end(), b.begin(), b.end());
}
void serialize(buffer_t& buffer, const OutputSocket& socket) {
buffer_t b;
serialize_socket_base(b, socket);
add_length_prefix(b);
buffer.insert(buffer.end(), b.begin(), b.end());
}
void serialize(buffer_t& buffer, const Node& node) {
buffer_t b;
serialize(b, node.get_id());
serialize(b, node.get_qualifier());
serialize(b, node.get_name());
serialize(b, node.get_input_sockets(), Bounds::sockets);
serialize(b, node.get_output_sockets(), Bounds::sockets);
serialize(b, node.is_proxy());
add_length_prefix(b);
buffer.insert(buffer.end(), b.begin(), b.end());
}
void serialize(buffer_t& buffer, const Graph::InterfaceProperties& interface_ppts) {
buffer_t b;
serialize(b, interface_ppts.socket_id);
serialize(b, interface_ppts.show_as);
add_length_prefix(b);
buffer.insert(buffer.end(), b.begin(), b.end());
}
// ---
Serializer::Serializer(const Graph& graph) : graph_(graph) {
if (!graph_.get_qualifier().has_value())
throw std::runtime_error("Graph must have a qualifier for serialization.");
}
void Serializer::serialize_graph() {
buffer_.clear();
serialize(buffer_, Bounds::graph);
serialize(buffer_, graph_.get_qualifier().value());
serialize(buffer_, get_parser_version());
serialize(buffer_, get_app_name());
serialize(buffer_, graph_.get_name());
serialize(buffer_, graph_.get_links(), Bounds::links);
serialize(buffer_, graph_.get_nodes(), Bounds::nodes);
serialize(buffer_, graph_.get_input_sockets(), Bounds::sockets);
serialize(buffer_, graph_.get_output_sockets(), Bounds::sockets);
serialize(buffer_, graph_.get_parameters(), Bounds::interface);
serialize(buffer_, graph_.get_results(), Bounds::interface);
serialize(buffer_, Bounds::graph);
add_length_prefix(buffer_);
}
} // namespace ng::serialization