libcruft-util/cruft/util/serialise/std.hpp

194 lines
5.0 KiB
C++

/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* Copyright 2022, Danny Robson <danny@nerdcruft.net>
*/
#pragma once
#include "./converter.hpp"
#include "./ops.hpp"
///////////////////////////////////////////////////////////////////////////////
template <typename ElementT>
struct cruft::serialise::converter<std::vector<ElementT>> {
using value_type = std::vector<ElementT>;
static std::size_t
size (value_type const &val)
{
std::size_t accum = sizeof (typename value_type::size_type);
for (auto const &i: val)
accum += converter<ElementT>::size (i);
return accum;
}
static
cruft::view<std::byte*>
to_bytes [[nodiscard]] (
cruft::view<std::byte*> dst,
value_type const &src
) {
dst = ::cruft::serialise::to_bytes (dst, src.size ());
for (auto const &i: src)
dst = ::cruft::serialise::to_bytes (dst, i);
return dst;
}
static
value_type
from_bytes (cruft::view<std::byte*> &src)
{
auto const len = ::cruft::serialise::from_bytes<typename std::vector<ElementT>::size_type> (src);
std::vector<ElementT> res;
res.reserve (len);
for (std::size_t i = 0; i != len; ++i)
res.push_back (::cruft::serialise::from_bytes<ElementT> (src));
return res;
}
};
///////////////////////////////////////////////////////////////////////////////
template <>
struct cruft::serialise::converter<std::string> {
using value_type = std::string;
static std::size_t
size (value_type const &val)
{
return sizeof (value_type::size_type) + sizeof (value_type::value_type) * val.size ();
}
static
cruft::view<std::byte*>
to_bytes [[nodiscard]] (
cruft::view<std::byte*> dst,
value_type const &src
) {
dst = ::cruft::serialise::to_bytes (dst, src.size ());
for (auto const &i: src)
dst = ::cruft::serialise::to_bytes (dst, i);
return dst;
}
static
value_type
from_bytes (cruft::view<std::byte*> &src)
{
std::string res;
res.resize (::cruft::serialise::converter<std::string::size_type>::from_bytes (src));
for (auto &i: res)
i = ::cruft::serialise::converter<std::string::value_type>::from_bytes (src);
return res;
}
};
///////////////////////////////////////////////////////////////////////////////
template <typename A, typename B>
struct cruft::serialise::converter<std::pair<A, B>> {
using value_type = std::pair<A, B>;
static std::size_t
size (value_type const &val)
{
return converter<A>::size (val.first) + converter<B>::size (val.second);
}
static
cruft::view<std::byte*>
to_bytes [[nodiscard]] (
cruft::view<std::byte*> dst,
value_type const &src
) {
dst = ::cruft::serialise::to_bytes (dst, src.first);
dst = ::cruft::serialise::to_bytes (dst, src.second);
return dst;
}
static
value_type
from_bytes (cruft::view<std::byte*> &src)
{
return {
cruft::serialise::converter<A>::from_bytes (src),
cruft::serialise::converter<B>::from_bytes (src),
};
}
};
///////////////////////////////////////////////////////////////////////////////
template <typename ...ElementT>
struct cruft::serialise::converter<std::tuple<ElementT...>> {
using value_type = std::tuple<ElementT...>;
static std::size_t
size (value_type const &val)
{
return size (val, std::make_index_sequence<sizeof ...(ElementT)> {});
}
static
cruft::view<std::byte*>
to_bytes [[nodiscard]] (
cruft::view<std::byte*> dst,
value_type const &src
) {
return to_bytes (dst, src, std::make_index_sequence<sizeof... (ElementT)> {});
}
static
value_type
from_bytes (cruft::view<std::byte*> &src)
{
return from_bytes (src, std::make_index_sequence<sizeof... (ElementT)> {});
}
private:
template <std::size_t ...Index>
static std::size_t
size (value_type const &val, std::index_sequence<Index...> const &)
{
return (
converter<
std::tuple_element_t<Index, value_type>
>::size (
std::get<Index> (val)
) + ... + 0uz
);
}
template <std::size_t ...IndexV>
static
cruft::view<std::byte*>
to_bytes [[nodiscard]] (
cruft::view<std::byte*> dst,
value_type const &src,
std::index_sequence<IndexV...> const&
) {
return ::cruft::serialise::to_bytes (dst, std::get<IndexV> (src)...);
}
template <std::size_t ...IndexV>
static
value_type
from_bytes (cruft::view<std::byte*> &src, std::index_sequence<IndexV...> const&)
{
return std::tuple {
::cruft::serialise::from_bytes<ElementT> (src)...,
};
}
};