yalantinglibs/include/ylt/struct_pack/user_helper.hpp

85 lines
3.1 KiB
C++

#pragma once
#include <cstdint>
#include <span>
#include "ylt/struct_pack/calculate_size.hpp"
#include "ylt/struct_pack/packer.hpp"
#include "ylt/struct_pack/reflection.hpp"
#include "ylt/struct_pack/unpacker.hpp"
namespace struct_pack {
template <std::size_t size_width = sizeof(uint64_t), typename Writer,
typename T>
STRUCT_PACK_INLINE void write(Writer& writer, const T& t) {
struct_pack::detail::packer<Writer, T, true> packer{writer};
packer.template serialize_one<size_width, UINT64_MAX, 0>(t);
};
template <std::size_t size_width = sizeof(uint64_t), typename Writer,
typename T>
STRUCT_PACK_INLINE void write(Writer& writer, const T* t, std::size_t len) {
if constexpr (detail::is_trivial_serializable<T>::value &&
detail::is_little_endian_copyable<sizeof(T)>) {
write_bytes_array(writer, (char*)t, sizeof(T) * len);
}
else {
struct_pack::detail::packer<Writer, T, true> packer{writer};
for (std::size_t i = 0; i < len; ++i) {
packer.template serialize_one<size_width, UINT64_MAX, 0>(t[i]);
}
}
};
template <std::size_t size_width = sizeof(uint64_t), bool ifSkip = false,
typename Reader, typename T>
STRUCT_PACK_INLINE struct_pack::err_code read(Reader& reader, T& t) {
struct_pack::detail::unpacker<Reader, sp_config::DEFAULT, true> unpacker{
reader};
return unpacker.template deserialize_one<size_width, UINT64_MAX, !ifSkip>(t);
};
template <std::size_t size_width = sizeof(uint64_t), bool ifSkip = false,
typename Reader, typename T>
STRUCT_PACK_INLINE struct_pack::err_code read(Reader& reader, T* t,
std::size_t len) {
if constexpr (detail::is_trivial_serializable<T>::value &&
detail::is_little_endian_copyable<sizeof(T)>) {
if constexpr (!ifSkip) {
if SP_UNLIKELY (!read_bytes_array(reader, (char*)t, sizeof(T) * len)) {
return struct_pack::errc::no_buffer_space;
}
}
else {
return reader.ignore(sizeof(T) * len) ? errc{} : errc::no_buffer_space;
}
}
else {
struct_pack::detail::unpacker<Reader, sp_config::DEFAULT, true> unpacker{
reader};
for (std::size_t i = 0; i < len; ++i) {
auto code =
unpacker.template deserialize_one<size_width, UINT64_MAX, !ifSkip>(
t[i]);
if SP_UNLIKELY (code) {
return code;
}
}
}
return {};
};
template <std::size_t size_width = sizeof(uint64_t), typename T>
STRUCT_PACK_INLINE constexpr std::size_t get_write_size(const T& t) {
auto sz = struct_pack::detail::calculate_one_size(t);
return sz.size_cnt * size_width + sz.total;
};
template <std::size_t size_width = sizeof(uint64_t), typename T>
STRUCT_PACK_INLINE constexpr std::size_t get_write_size(const T* t,
std::size_t len) {
if constexpr (detail::is_trivial_serializable<T>::value) {
return sizeof(T) * len;
}
else {
detail::size_info sz{};
for (std::size_t i = 0; i < len; ++i) {
sz += struct_pack::detail::calculate_one_size(t[i]);
}
return sz.size_cnt * size_width + sz.total;
}
};
}; // namespace struct_pack