Skip to content
On this page

struct_pack Tips

This document introcude some tips about struct_pack

requirements

struct_pack need compiler at least support C++17. We have test it on GCC/Clang/MSVC.

compilertested min version
GCC9.1
Clang/Apple Clang6.0
MSVCVisual Studio 2019 (MSVC19.20)

struct_pack is cross-platform. struct_pack can work in both big-endian and little-endian. struct_pack support 32bit arch or 64bit arch.

When C++20 standard was enabled, struct_pack has better performance by support memcpy user-defined trivial continuous container. In C++17, struct_pack only support memcpy container std::array<T>, std::vector<T>, std::basic_string<T> and std::basic_string_view<T>.

endian

struct_pack will save the data as little-endian even if the arch is big-endian. The trivial-copy optimize and zero-copy optimize will be disable when the object is width than 1 byte. so struct_pack performance in little-endian is better than big-endian.

macro

macrodescription
STRUCT_PACK_OPTIMIZEAllow more extremed loop unrolling to get better performance, but it cost more compile time.
STRUCT_PACK_ENABLE_UNPORTABLE_TYPEEnable serialize unportable type, such as wchar_t/std::wstring/std::bitset. Deserialize them in other platform maybe an undefined bevaior.
STRUCT_PACK_ENABLE_INT128Enable serialize __int128 and __uint128. Not all compiler support it.

How to speed up serialization/deserialization

  1. use string_view instead of string, use span instead of vector/array.
  2. move trivial field to a standlone struct, so that struct_pack could copy it faster.
  3. use std::vector instead of std::list.
  4. define macro STRUCT_PACK_OPTIMIZE.

Type Check

struct_pack will generate a name for the serialized type during compilation, and get a 32-bit MD5 based on the string, then take its upper 31 bits for type check. When deserializing, it will check whether the hash code stored is the same as the type to be deserialized. In order to alleviate possible hash collisions, in debug mode, struct_pack will store the complete type name instead of hash code. Therefore, the binary size in debug mode is slightly larger than release.

serialization config

struct_pack allows user to configure the content of the metadata via struct_pack::sp_config, which currently has the following settings:

enum valuedescription
DEFAULTdefault value
DISABLE_TYPE_INFOProhibit storing full type information in serialized data, even in DEBUG mode
ENABLE_TYPE_INFOProhibit storing full type information in serialized data, even in DEBUG mode
DISABLE_META_INFOForce full type information to be stored in serialized data, even if not in DEBUG mode
ENCODING_WITH_VARINTencode integer(int32_t,int64_t,uint32_t,uint64_t) as variable length coding
USE_FAST_VARINTencode integer(int32_t,int64_t,uint32_t,uint64_t) as fast variable length coding

Note that when serialization is configured with the DISABLE_META_INFO option, it must be ensured that deserialization also uses this option, otherwise the behavior is undefined and the probability is that deserialization will fail.

Also, note that if structure A nests structure B, the configuration for A will not take effect for B.

For example:

cpp
struct rect {
  int a, b, c, d;
};

global config

sp_config::default is default global config, you can also use other config value by following codes:

cpp
namespace struct_pack {
  //default global config
  constexpr sp_config set_default(sp_config*){ return sp_config::DISABLE_ALL_META_INFO; }
}
static_assert(struct_pack::get_needed_size(rect{}).size()==16);

You can have different config value in different code unit(*.cpp file).

config by class static member

This config takes precedence over global config.

Just add a constexpr static member named struct_pack_config to the class

cpp
struct rect {
  int a, b, c, d;
  constexpr static auto struct_pack_config = struct_pack::DISABLE_ALL_META_INFO;
};

config by ADL

ADL configuration takes precedence over class static member.

we can declare a function set_sp_config in the same namespace of type rect:

cpp
inline constexpr struct_pack::sp_config set_sp_config(rect*) {
  return struct_pack::DISABLE_ALL_META_INFO;
}

config by template parameters

This method has the highest priority and requires the configuration to be passed in as a template parameter each time it is serialised.

Note that the USE_FAST_VARINT and ENCODING_WITH_VARINT configurations are ineffective here.

cpp
auto buffer = struct_pack::serialize<struct_pack::DISABLE_ALL_META_INFO>(rect{});
auto result = struct_pack::deserialize<struct_pack::DISABLE_ALL_META_INFO,rect>(buffer);

Currently we do not allow the DISABLE_ALL_META_INFO configuration to be enabled with a compatible field.

Type requires

  1. The type to serialize should be legal struct_pack type.。See document:struct_pack type system
  2. struct_pack support update protocol by add struct_pack::compatible field, which is forward backward compatibility. User should make sure the version number is increment for each update. It's not allow to delete/modify exist field. See : document

This website is released under the MIT License.