Binary Type Support - liuli-neko/NekoProtoTools GitHub Wiki

This page details the C++ types supported by the NekoProto::BinarySerializer and describes how they are represented in the resulting binary byte stream.

Related Concepts:

Prerequisites

To use the BinarySerializer, ensure you include the core header <nekoproto/proto/binary_serializer.hpp>.

Additionally, remember to include the necessary type support headers (<nekoproto/proto/types/...>) for the standard library types you wish to serialize/deserialize (e.g., <nekoproto/proto/types/string.hpp>, <nekoproto/proto/types/vector.hpp>), or include the general <nekoproto/proto/types/types.hpp>. Fundamental types and std::optional are typically covered by including <nekoproto/proto/binary_serializer.hpp>.

Format Characteristics

  • Compact: Generally produces smaller output compared to text-based formats like JSON or XML.
  • Not Human-Readable: The output is a sequence of bytes intended for machine processing.
  • Network Byte Order: Multi-byte numeric types (int16_t, uint16_t, int32_t, uint32_t, int64_t, uint64_t, float, double, and size/length prefixes) are stored in Big Endian format (most significant byte first). This ensures consistency when sending data between systems with different native byte orders (endianness).
  • Fixed/Variable Length: Basic types have fixed sizes. Strings and containers have a variable size, prefixed by their length/element count.

Supported Types and Binary Mapping

The following table outlines the mapping between C++ types and their binary representation:

C++ Type Supported Size (Bytes) Required Type Header (nekoproto/proto/types/...) Notes
bool 1 (builtin) 0x00 for false, 0x01 for true.
int8_t, uint8_t 1 (builtin) Stored directly.
int16_t, uint16_t 2 (builtin) Network Byte Order (Big Endian).
int32_t, uint32_t 4 (builtin) Network Byte Order (Big Endian).
int64_t, uint64_t 8 (builtin) Network Byte Order (Big Endian).
float 4 (builtin) IEEE 754 format, Network Byte Order (Big Endian).
double 8 (builtin) IEEE 754 format, Network Byte Order (Big Endian).
std::string 4 (length) + N (content) string.hpp uint32_t length prefix (Big Endian), then raw bytes.
std::u8string (C++20) 4 (length) + N (content) u8string.hpp uint32_t length prefix (Big Endian), then raw bytes.
enum class/enum Size of underlying type enum.hpp Serialized as its underlying integer value (Big Endian if >1 byte).
std::optional<T> 1 (flag) [+ Size of T] (builtin) 1-byte flag (0=null, 1=present), followed by T if present.
std::vector<T> 4 (count) + N * Size of T vector.hpp uint32_t count prefix (Big Endian), then elements.
std::list<T> 4 (count) + N * Size of T list.hpp uint32_t count prefix (Big Endian), then elements.
std::deque<T> 4 (count) + N * Size of T deque.hpp uint32_t count prefix (Big Endian), then elements.
std::array<T, N> N * Size of T array.hpp Elements stored consecutively. No size prefix needed.
std::set<T> 4 (count) + N * Size of T set.hpp uint32_t count prefix (Big Endian), then elements.
std::multiset<T> 4 (count) + N * Size of T multiset.hpp uint32_t count prefix (Big Endian), then elements.
std::unordered_set<T> 4 (count) + N * Size of T unordered_set.hpp uint32_t count prefix (Big Endian), then elements.
std::unordered_multiset<T> 4 (count) + N * Size of T unordered_multiset.hpp uint32_t count prefix (Big Endian), then elements.
std::map<K, V> 4 (count) + N * (Size K + Size V) map.hpp uint32_t count prefix (Big Endian), then K, V pairs.
std::multimap<K, V> 4 (count) + N * (Size K + Size V) multimap.hpp uint32_t count prefix (Big Endian), then K, V pairs.
std::unordered_map<K, V> 4 (count) + N * (Size K + Size V) unordered_map.hpp uint32_t count prefix (Big Endian), then K, V pairs.
std::unordered_multimap<K, V> 4 (count) + N * (Size K + Size V) unordered_multimap.hpp uint32_t count prefix (Big Endian), then K, V pairs.
std::pair<T1, T2> Size T1 + Size T2 pair.hpp T1 followed immediately by T2.
std::tuple<T...> Sum of Sizes of T... tuple.hpp Elements stored consecutively in order.
std::variant<T...> 4 (index) + Size of Active T variant.hpp uint32_t index prefix (Big Endian), then active value.
std::bitset<N> 4 (size N) + ceil(N/8) bitset.hpp Size prefix (Big Endian), then packed bytes.
std::shared_ptr<T> 1 (flag) [+ Size of T] shared_ptr.hpp Same as std::optional<T>.
std::unique_ptr<T> 1 (flag) [+ Size of T] unique_ptr.hpp Same as std::optional<T>.
std::atomic<T> Size of T atomic.hpp Serializes the contained value T.
Custom struct/class (using macro) Sum of Sizes of Members (user-defined) Members serialized consecutively in order listed in macro.
Protocol class (using macros) Sum of Sizes of Members (user-defined) Members serialized consecutively in order listed in macro.
NamePairValue<std::string, T> 4+len(name) + len(T) (builtin) Used internally/special cases; name + value.
std::any - - Not supported.

(builtin): Support provided directly by <nekoproto/proto/types/types.hpp>.

Notes on Specific Types

  • Containers & Strings: All variable-length containers (except std::array) and strings are prefixed with a 4-byte count/length field (uint32_t in Network Byte Order) indicating the number of elements or bytes that follow.
  • Custom Structs/Classes: Members declared using NEKO_SERIALIZER are serialized sequentially in the exact order they are listed in the macro. The total size is the sum of the sizes of the individual members.
  • Pointers: Raw pointers are not directly supported. Use smart pointers or manage serialization explicitly.

The BinarySerializer provides a compact representation suitable for network transmission or storage where human readability is not a requirement. Careful attention to the defined order and sizes is necessary when attempting to interoperate with other systems or manually parse the binary data.

⚠️ **GitHub.com Fallback** ⚠️