Program Listing for File serialization.h#

↰ Return to documentation for file (include/nodes-graph/serialization.h)

#pragma once


#include <array>
#include <cstdint>
#include <map>
#include <set>
#include <string>
#include <vector>
#include "nodes-graph/types.h"
#include "nodes-graph/graph.h"


namespace ng::serialization {

    using len_t = uint64_t;
    using buffer_t = std::vector<char>;
    using bound_t = uint8_t;

    constexpr std::size_t LEN = sizeof(len_t);

    enum Bounds: bound_t {
        graph     = 21,
        whitelist = 19,
        callbacks = 17,
        sockets   = 15,
        nodes     = 13,
        links     = 11,
        interface = 9
    };

    using version_t = std::array<char, 3>;

    inline std::string app_name() { return "nodes-graph"; }

    inline version_t parser_version() {
        return version_t{
            static_cast<char>(0),
            static_cast<char>(1),
            static_cast<char>(0)
        };
    }

    bool is_sup_or_equal(const version_t& a, const version_t& b);

    void add_length_prefix(buffer_t& buffer);

    // --- Base types

    void serialize(buffer_t& buffer, len_t l);
    void serialize(buffer_t& buffer, bound_t b);
    void serialize(buffer_t& buffer, bool s);
    void serialize(buffer_t& buffer, socket_t type);

    // --- Strings and identifiers

    void serialize_bytes(buffer_t& buffer, const char* s, len_t l);
    void serialize(buffer_t& buffer, const std::string& s);

    template <std::size_t N>
    void serialize(buffer_t& buffer, const std::array<char, N>& identifier);

    void serialize(buffer_t& buffer, const qualifier_t& qualifier);
    void serialize(buffer_t& buffer, const socket_uuid_t& socket_uuid);
    void serialize(buffer_t& buffer, const link_t& link);

    // --- Graph components

    void serialize_socket_base(buffer_t& buffer, const Socket& socket);
    void serialize(buffer_t& buffer, const InputSocket& socket);
    void serialize(buffer_t& buffer, const OutputSocket& socket);
    void serialize(buffer_t& buffer, const Node& node);
    void serialize(buffer_t& buffer, const Graph::InterfaceProperties& interface_ppts);

    // --- Collections

    template <typename T>
    void serialize(buffer_t& buffer, const std::set<T>& collection, bound_t bound);

    template <typename U, typename V>
    void serialize(buffer_t& buffer, const std::map<U, V>& collection, bound_t bound);

    // ---

    class Serializer {
        const Graph& graph_;
        buffer_t buffer_;

    public:
        Serializer(const Graph& graph);

        void serialize_graph();

        inline version_t get_parser_version() const { return parser_version(); }
        inline std::string get_app_name() const { return app_name(); }
        inline const buffer_t& get_buffer() const { return buffer_; }
    };


    // -------------------------------------------------------------------------


    template <std::size_t N>
    void serialize(buffer_t& buffer, const std::array<char, N>& identifier) {
        serialize_bytes(buffer, identifier.data(), N);
    }


    template <typename T>
    void serialize(buffer_t& buffer, const std::set<T>& collection, bound_t bound) {
        buffer_t b;

        serialize(b, bound);
        serialize(b, static_cast<len_t>(collection.size()));

        for (const auto& item : collection) {
            serialize(b, item);
        }

        serialize(b, bound);
        add_length_prefix(b);

        buffer.insert(buffer.end(), b.begin(), b.end());
    }


    template <typename U, typename V>
    void serialize(buffer_t& buffer, const std::map<U, V>& collection, bound_t bound) {
        buffer_t b;

        serialize(b, bound);
        serialize(b, static_cast<len_t>(collection.size()));

        for (const auto& [key, value] : collection) {
            serialize(b, key);
            serialize(b, value);
        }

        serialize(b, bound);
        add_length_prefix(b);

        buffer.insert(buffer.end(), b.begin(), b.end());
    }

} // namespace ng::serialization