VOOZH about

URL: https://deepwiki.com/stefanak-michal/php-bolt-driver/7-data-serialization-(packstream)

⇱ Data Serialization (PackStream) | stefanak-michal/php-bolt-driver | DeepWiki


Loading...
Last indexed: 14 February 2026 (a283bd)
Menu

Data Serialization (PackStream)

This document provides an overview of PackStream serialization in the PHP Bolt driver, including the bidirectional conversion between PHP types and binary PackStream format. PackStream is the binary protocol used by Bolt to efficiently encode structured data for transmission between client and server.

For detailed information on specific topics, see:

PackStream Overview

PackStream is a binary serialization format designed for efficient encoding of typed data in the Bolt protocol. It provides:

  • Size-optimized encoding: Different marker bytes based on value size (TINY, 8-bit, 16-bit, 32-bit variants)
  • Type preservation: Explicit type markers for all data types
  • Structure support: Custom structures with signature bytes for graph types, temporal types, and spatial types
  • Streaming capability: Chunked message encoding for large payloads

The serialization layer is version-specific, with PackStream v1 being the primary implementation supporting Bolt protocol versions 1 through 6.

Sources: src/packstream/v1/Packer.php1-250 src/packstream/v1/Unpacker.php1-294

Architecture

The serialization system is organized around two core interfaces and their implementations:


Sources: src/packstream/v1/Packer.php16-17 src/packstream/v1/Unpacker.php17-18 src/protocol/v6/AvailableStructures.php1-64 src/protocol/AProtocol.php

Packer: PHP to Binary Conversion

The Packer class converts PHP values to binary PackStream format. It implements a generator-based architecture that yields chunks for efficient memory usage.

Key Methods

MethodPurposeLine Reference
pack()Main entry point for packing messages with signaturesrc/packstream/v1/Packer.php33-63
packInteger()Variable-length integer encoding (TINY_INT to INT_64)src/packstream/v1/Packer.php140-158
packFloat()64-bit float encoding (FLOAT_64)src/packstream/v1/Packer.php132-135
packString()UTF-8 string encoding with size variantssrc/packstream/v1/Packer.php115-130
packList()List/array encodingsrc/packstream/v1/Packer.php188-207
packDictionary()Map/object encodingsrc/packstream/v1/Packer.php163-183
packStructure()Custom structure encoding with signaturesrc/packstream/v1/Packer.php212-231
packByteArray()Raw bytes encodingsrc/packstream/v1/Packer.php236-248

Type Dispatching

The private p() method implements type dispatching based on PHP's native type system:


Sources: src/packstream/v1/Packer.php68-110

Endianness Handling

The Packer detects system endianness at construction and reverses byte order for integers when running on little-endian systems:


Sources: src/packstream/v1/Packer.php23-31 src/packstream/v1/Packer.php148

Size Constants

PackStream uses different encoding variants based on value size:

ConstantValuePurpose
SMALL16Threshold for TINY variants
MEDIUM256Threshold for 8-bit variants
LARGE65536Threshold for 16-bit variants
HUGE4294967295Maximum for 32-bit variants

Sources: src/packstream/v1/Packer.php18-21

Unpacker: Binary to PHP Conversion

The Unpacker class reverses the packing process, converting binary PackStream data back to PHP types.

Key Methods

MethodPurposeLine Reference
unpack()Main entry point for unpacking messagessrc/packstream/v1/Unpacker.php32-42
getSignature()Retrieve message signature after unpackingsrc/packstream/v1/Unpacker.php47-50
unpackInteger()Variable-length integer decodingsrc/packstream/v1/Unpacker.php210-231
unpackFloat()64-bit float decodingsrc/packstream/v1/Unpacker.php237-245
unpackString()UTF-8 string decodingsrc/packstream/v1/Unpacker.php188-203
unpackList()List/array decodingsrc/packstream/v1/Unpacker.php252-272
unpackDictionary()Map/object decodingsrc/packstream/v1/Unpacker.php163-182
unpackStructure()Custom structure decoding with instantiationsrc/packstream/v1/Unpacker.php123-156
unpackByteArray()Raw bytes decodingsrc/packstream/v1/Unpacker.php278-291

Marker-Based Dispatching

The unpacker reads a marker byte and dispatches to the appropriate handler:


Sources: src/packstream/v1/Unpacker.php68-116

Structure Instantiation

When unpacking structures, the Unpacker uses reflection to instantiate classes registered in $structuresLt:


Sources: src/packstream/v1/Unpacker.php123-156

Structure Registry

Protocol versions define which structures are available through the AvailableStructures trait:


Asymmetric Packing

Note that graph structures (Node, Relationship, Path) appear only in unpackStructuresLt because they are server-to-client only. The client cannot create these structures for sending to the server.

Sources: src/protocol/v6/AvailableStructures.php34-62

Type System Overview

PackStream supports the following type categories:

Primitive Types

PHP TypePackStream EncodingMarker Byte(s)
nullNULL0xC0
bool (true)TRUE0xC3
bool (false)FALSE0xC2
intTINY_INT to INT_64-16 to 127, 0xC8-0xCB
floatFLOAT_640xC1
stringTINY_STRING to STRING_320x80-0x8F, 0xD0-0xD2

Collection Types

PHP TypePackStream EncodingMarker Byte(s)
array (list)TINY_LIST to LIST_320x90-0x9F, 0xD4-0xD6
array (assoc)TINY_MAP to MAP_320xA0-0xAF, 0xD8-0xDA
BytesBYTES_8 to BYTES_320xCC-0xCE

Structure Types

Structures are encoded with a signature byte following the structure header. For details on specific structures, see:

Sources: src/packstream/v1/Packer.php68-110 src/packstream/v1/Unpacker.php68-116

Message Chunking

The Packer implements chunking for large messages, breaking them into 65535-byte chunks:


This allows streaming of arbitrarily large messages without loading the entire payload into memory.

Sources: src/packstream/v1/Packer.php50-63

Memory-Efficient Generators

The library provides generator interfaces for memory-efficient serialization of large collections:


These generators enable processing of large datasets (e.g., 50,000 records) without loading them entirely into memory, as validated by performance tests.

Sources: src/packstream/v1/Packer.php98-101 tests/PerformanceTest.php19-63 tests/packstream/v1/PackerTest.php188-226

Integration with Protocol Layer

The AProtocol class instantiates Packer and Unpacker with the appropriate structure registries:


Protocol versions define their available structures through traits like AvailableStructures, which populate $packStructuresLt and $unpackStructuresLt arrays.

Write Operations


Read Operations


Sources: src/protocol/AProtocol.php src/protocol/v6/AvailableStructures.php32-63

Testing

The PackStream implementation is thoroughly tested through multiple test suites:

Unit Tests

Test ClassPurposeLine Reference
PackerTestValidates packing of all PHP typestests/packstream/v1/PackerTest.php1-229
UnpackerTestValidates unpacking of all PackStream typestests/packstream/v1/UnpackerTest.php1-201
BytesTestTests Bytes object serializationtests/packstream/v1/BytesTest.php1-59

Integration Tests

The PerformanceTest validates memory-efficient serialization with generators:


This ensures that large datasets can be processed without excessive memory consumption.

Sources: tests/packstream/v1/PackerTest.php1-229 tests/packstream/v1/UnpackerTest.php1-201 tests/PerformanceTest.php19-63

Performance Considerations

Memory Efficiency

  • Generator-based packing: The Packer uses yield to stream chunks, avoiding memory buildup
  • Collection generators: IPackListGenerator and IPackDictionaryGenerator enable streaming of large collections
  • Chunked transmission: 65535-byte chunks prevent large message buffer allocation

Endianness Optimization

The library detects system endianness once at construction and caches the result, avoiding repeated detection on every integer pack/unpack operation.

Size Optimization

PackStream's variable-length encoding minimizes wire size:

  • Integers from -16 to 127 use 1 byte (TINY_INT)
  • Small strings (≤15 bytes) use 1 header byte (TINY_STRING)
  • Small collections (≤15 items) use 1 header byte (TINY_LIST, TINY_MAP)

Sources: src/packstream/v1/Packer.php23-31 src/packstream/v1/Packer.php140-158 tests/PerformanceTest.php19-63