mmdeploy/csrc/core/serialization.h

338 lines
12 KiB
C++

// Copyright (c) OpenMMLab. All rights reserved.
#ifndef MMDEPLOY_SRC_CORE_SERIALIZATION_H_
#define MMDEPLOY_SRC_CORE_SERIALIZATION_H_
#include <iostream>
#include <tuple>
#include <type_traits>
#include <utility>
#include "core/status_code.h"
#include "mpl/detected.h"
#include "mpl/type_traits.h"
namespace mmdeploy {
#define _MMDEPLOY_NTH_ARG(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, \
N, ...) \
N
#define _MMDEPLOY_ARCHIVE_1(x) MMDEPLOY_NVP(x)
#define _MMDEPLOY_ARCHIVE_2(x, ...) MMDEPLOY_NVP(x), _MMDEPLOY_ARCHIVE_1(__VA_ARGS__)
#define _MMDEPLOY_ARCHIVE_3(x, ...) MMDEPLOY_NVP(x), _MMDEPLOY_ARCHIVE_2(__VA_ARGS__)
#define _MMDEPLOY_ARCHIVE_4(x, ...) MMDEPLOY_NVP(x), _MMDEPLOY_ARCHIVE_3(__VA_ARGS__)
#define _MMDEPLOY_ARCHIVE_5(x, ...) MMDEPLOY_NVP(x), _MMDEPLOY_ARCHIVE_4(__VA_ARGS__)
#define _MMDEPLOY_ARCHIVE_6(x, ...) MMDEPLOY_NVP(x), _MMDEPLOY_ARCHIVE_5(__VA_ARGS__)
#define _MMDEPLOY_ARCHIVE_7(x, ...) MMDEPLOY_NVP(x), _MMDEPLOY_ARCHIVE_6(__VA_ARGS__)
#define _MMDEPLOY_ARCHIVE_8(x, ...) MMDEPLOY_NVP(x), _MMDEPLOY_ARCHIVE_7(__VA_ARGS__)
#define _MMDEPLOY_ARCHIVE_9(x, ...) MMDEPLOY_NVP(x), _MMDEPLOY_ARCHIVE_8(__VA_ARGS__)
#define _MMDEPLOY_ARCHIVE_10(x, ...) MMDEPLOY_NVP(x), _MMDEPLOY_ARCHIVE_9(__VA_ARGS__)
#define _MMDEPLOY_ARCHIVE_11(x, ...) MMDEPLOY_NVP(x), _MMDEPLOY_ARCHIVE_10(__VA_ARGS__)
#define _MMDEPLOY_ARCHIVE_12(x, ...) MMDEPLOY_NVP(x), _MMDEPLOY_ARCHIVE_11(__VA_ARGS__)
#define _MMDEPLOY_ARCHIVE_13(x, ...) MMDEPLOY_NVP(x), _MMDEPLOY_ARCHIVE_12(__VA_ARGS__)
#define _MMDEPLOY_ARCHIVE_14(x, ...) MMDEPLOY_NVP(x), _MMDEPLOY_ARCHIVE_13(__VA_ARGS__)
#define _MMDEPLOY_ARCHIVE_15(x, ...) MMDEPLOY_NVP(x), _MMDEPLOY_ARCHIVE_14(__VA_ARGS__)
#define _MMDEPLOY_ARCHIVE_16(x, ...) MMDEPLOY_NVP(x), _MMDEPLOY_ARCHIVE_15(__VA_ARGS__)
#define _MMDEPLOY_ARCHIVE_DISPATCH(...) \
_MMDEPLOY_NTH_ARG(__VA_ARGS__, _MMDEPLOY_ARCHIVE_16(__VA_ARGS__), \
_MMDEPLOY_ARCHIVE_15(__VA_ARGS__), _MMDEPLOY_ARCHIVE_14(__VA_ARGS__), \
_MMDEPLOY_ARCHIVE_13(__VA_ARGS__), _MMDEPLOY_ARCHIVE_12(__VA_ARGS__), \
_MMDEPLOY_ARCHIVE_11(__VA_ARGS__), _MMDEPLOY_ARCHIVE_10(__VA_ARGS__), \
_MMDEPLOY_ARCHIVE_9(__VA_ARGS__), _MMDEPLOY_ARCHIVE_8(__VA_ARGS__), \
_MMDEPLOY_ARCHIVE_7(__VA_ARGS__), _MMDEPLOY_ARCHIVE_6(__VA_ARGS__), \
_MMDEPLOY_ARCHIVE_5(__VA_ARGS__), _MMDEPLOY_ARCHIVE_4(__VA_ARGS__), \
_MMDEPLOY_ARCHIVE_3(__VA_ARGS__), _MMDEPLOY_ARCHIVE_2(__VA_ARGS__), \
_MMDEPLOY_ARCHIVE_1(__VA_ARGS__))
#define MMDEPLOY_ARCHIVE_NVP(archive, ...) archive(_MMDEPLOY_ARCHIVE_DISPATCH(__VA_ARGS__))
#define MMDEPLOY_ARCHIVE(archive, ...) archive(__VA_ARGS__)
#define MMDEPLOY_ARCHIVE_MEMBERS(...) \
template <typename Archive> \
void serialize(Archive &archive) { \
MMDEPLOY_ARCHIVE_NVP(archive, __VA_ARGS__); \
}
#define MMDEPLOY_NVP(var) \
::mmdeploy::NamedValue { std::forward_as_tuple(#var, var) }
template <typename NameT, typename ValueT>
class NamedValue {
public:
explicit NamedValue(std::tuple<NameT, ValueT> &&data) : data_(std::move(data)) {}
template <typename Archive>
void serialize(Archive &archive) {
archive.named_value(std::forward<NameT>(std::get<0>(data_)),
std::forward<ValueT>(std::get<1>(data_)));
}
std::tuple<NameT, ValueT> &data() { return data_; }
private:
std::tuple<NameT, ValueT> data_;
};
template <typename T>
struct array_tag {
explicit array_tag(std::size_t size) : size_(size) {}
std::size_t size() const { return size_; }
std::size_t size_;
};
template <typename T>
struct object_tag {};
template <typename T>
using mapped_type_t = typename T::mapped_type;
template <typename T>
using has_mapped_type = detail::is_detected<mapped_type_t, T>;
template <typename T>
using get_size_t = decltype(std::declval<T>().size());
template <typename T>
using has_size = detail::is_detected<get_size_t, T>;
template <typename T>
using reserve_t = decltype(std::declval<T>().reserve(std::size_t{0}));
template <typename T>
using has_reserve = detail::is_detected<reserve_t, T>;
namespace detail {
template <typename Archive, typename T, typename U = uncvref_t<T>,
typename ValueType = typename U::value_type,
std::enable_if_t<!std::is_same_v<U, std::string>, int> = 0>
auto save(Archive &archive, T &&iterable)
-> std::void_t<decltype(iterable.begin(), iterable.end())> {
if constexpr (has_size<T>::value) {
archive.init(array_tag<ValueType>(iterable.size()));
}
for (auto &&x : iterable) {
archive.item(std::forward<decltype(x)>(x));
}
}
template <typename T0, typename T1>
class KeyValue {
public:
explicit KeyValue(std::tuple<T0, T1> &&data) : data_(std::move(data)) {}
template <typename Archive>
void serialize(Archive &archive) {
archive.named_value("key", std::forward<T0>(std::get<0>(data_)));
archive.named_value("value", std::forward<T1>(std::get<1>(data_)));
}
std::tuple<T0, T1> &data() { return data_; }
private:
std::tuple<T0, T1> data_;
};
template <typename Archive, typename T, typename U = uncvref_t<T>,
typename KeyType = typename U::key_type, typename MappedType = typename U::mapped_type,
std::enable_if_t<!std::is_constructible_v<std::string, KeyType>, int> = 0>
auto save(Archive &archive, T &object) -> std::void_t<decltype(object.begin(), object.end())> {
if constexpr (has_size<T>::value) {
// TODO: provide meaningful type info
archive.init(array_tag<void>(object.size()));
}
for (auto &&[k, v] : object) {
archive.item(KeyValue{
std::forward_as_tuple(std::forward<decltype(k)>(k), std::forward<decltype(v)>(v))});
}
}
template <typename Archive, typename T, typename U = uncvref_t<T>,
typename KeyType = typename U::key_type, typename MappedType = typename U::mapped_type,
std::enable_if_t<std::is_constructible_v<std::string, KeyType>, int> = 0>
auto save(Archive &archive, T &object) -> std::void_t<decltype(object.begin(), object.end())> {
if constexpr (has_size<T>::value) {
archive.init(object_tag<MappedType>());
}
for (auto &&[k, v] : object) {
archive.named_value(std::forward<decltype(k)>(k), std::forward<decltype(v)>(v));
}
}
template <typename Archive, typename T, std::size_t... Is>
void save_tuple_impl(Archive &archive, T &&tuple, std::index_sequence<Is...>) {
(archive.item(std::get<Is>(std::forward<T>(tuple))), ...);
}
template <typename Archive, typename... Ts>
void save(Archive &archive, const std::tuple<Ts...> &tuple) {
save_tuple_impl(archive, tuple, std::index_sequence_for<Ts...>{});
}
template <typename Archive, typename T, size_t... Is>
void load_tuple_impl(Archive &archive, T &tuple, std::index_sequence<Is...>) {
(archive.item(std::get<Is>(tuple)), ...);
}
template <typename Archive, typename T, std::size_t N>
void save(Archive &archive, T (&v)[N]) {
archive.init(array_tag<T>(N));
for (std::size_t i = 0; i < N; ++i) {
archive.item(v[i]);
}
}
template <typename Archive, typename... Ts>
void load(Archive &archive, std::tuple<Ts...> &tuple) {
std::size_t size{};
archive.init(size);
if (size != sizeof...(Ts)) {
throw_exception(eShapeMismatch);
}
load_tuple_impl(archive, tuple, std::index_sequence_for<Ts...>{});
}
template <typename Archive, typename T, typename U = uncvref_t<T>,
typename ValueType = typename U::value_type,
std::enable_if_t<!std::is_same_v<U, std::string>, int> = 0>
auto load(Archive &&archive, T &&vec) -> std::void_t<decltype(vec.push_back(ValueType{}))> {
std::size_t size{};
archive.init(size);
vec.clear();
for (std::size_t i = 0; i < size; ++i) {
ValueType v{};
archive.item(v);
vec.push_back(std::move(v));
}
}
template <typename Archive, typename T, std::size_t N>
void load(Archive &archive, std::array<T, N> &v) {
std::size_t size{};
archive.init(size);
for (std::size_t i = 0; i < size; ++i) {
archive.item(v[i]);
}
}
template <typename Archive, typename T, std::size_t N>
void load(Archive &archive, T (&v)[N]) {
std::size_t size{};
archive.init(size);
for (std::size_t i = 0; i < size; ++i) {
archive.item(v[i]);
}
}
template <typename Archive, typename T, typename U = uncvref_t<T>,
typename ValueType = typename U::value_type,
std::enable_if_t<std::conjunction_v<std::is_default_constructible<ValueType>,
std::negation<has_mapped_type<U>>>,
int> = 0>
auto load(Archive &&archive, T &&set)
-> std::void_t<decltype(set.insert(std::declval<ValueType>()))> {
std::size_t size{};
archive.init(size);
for (std::size_t i = 0; i < size; ++i) {
ValueType v{};
archive.item(v);
set.insert(std::move(v));
}
}
template <
typename Archive, typename T, typename U = uncvref_t<T>,
typename KeyType = typename U::key_type, typename MappedType = typename U::mapped_type,
std::enable_if_t<std::conjunction_v<std::negation<std::is_constructible<KeyType, std::string>>,
std::is_default_constructible<KeyType>,
std::is_default_constructible<MappedType>>,
int> = 0>
void load(Archive &&archive, T &&object) {
std::size_t size{};
archive.init(size);
for (std::size_t i = 0; i < size; ++i) {
KeyType key;
MappedType mapped;
archive.item(KeyValue{std::tie(key, mapped)});
object.insert({std::move(key), std::move(mapped)});
};
}
template <typename Archive, typename T, typename U = uncvref_t<T>,
typename KeyType = typename U::key_type, typename MappedType = typename U::mapped_type,
std::enable_if_t<std::conjunction_v<std::is_constructible<KeyType, std::string>,
std::is_default_constructible<MappedType>>,
int> = 0>
void load(Archive &&archive, T &&object) {
std::size_t size{};
archive.init(size);
for (std::size_t i = 0; i < size; ++i) {
std::string name;
MappedType value{};
archive.named_value(name, value);
object.insert({std::move(name), std::move(value)});
}
}
template <typename Archive, typename T>
using save_t = decltype(save(std::declval<Archive>(), std::declval<T>()));
struct save_fn {
template <typename Archive, typename T>
auto operator()(Archive &&a, T &&v) const -> save_t<Archive, T> {
return save(std::forward<Archive>(a), std::forward<T>(v));
}
};
template <typename Archive, typename T>
using load_t = decltype(load(std::declval<Archive>(), std::declval<T>()));
struct load_fn {
template <typename Archive, typename T>
auto operator()(Archive &&a, T &&v) const -> load_t<Archive, T> {
return load(std::forward<Archive>(a), std::forward<T>(v));
}
};
template <typename Archive, typename T>
using serialize_t = decltype(serialize(std::declval<Archive>(), std::declval<T>()));
struct serialize_fn {
template <typename Archive, typename T>
auto operator()(Archive &&a, T &&v) const -> serialize_t<Archive, T> {
return serialize(std::forward<Archive>(a), std::forward<T>(v));
}
};
} // namespace detail
namespace {
constexpr inline detail::save_fn save{};
constexpr inline detail::load_fn load{};
constexpr inline detail::serialize_fn serialize{};
} // namespace
template <typename T = void, typename SFINAE = void>
struct adl_serializer;
template <typename, typename>
struct adl_serializer {
template <typename Archive, typename T>
static auto save(Archive &&a, T &&v) -> detail::save_t<Archive, T> {
::mmdeploy::save(std::forward<Archive>(a), std::forward<T>(v));
}
template <typename Archive, typename T>
static auto load(Archive &&a, T &&v) -> detail::load_t<Archive, T> {
::mmdeploy::load(std::forward<Archive>(a), std::forward<T>(v));
}
template <typename Archive, typename T>
static auto serialize(Archive &&a, T &&v) -> detail::serialize_t<Archive, T> {
::mmdeploy::serialize(std::forward<Archive>(a), std::forward<T>(v));
}
};
}; // namespace mmdeploy
#endif // MMDEPLOY_SRC_CORE_SERIALIZATION_H_