pack-d 1.0.1

This page describes pack and unpack family of functions. These functions work on format strings that describe types of values to read/write. For example this snippet:

auto writer = BinaryWriter(ByteOrder.LittleEndian); 
writer.write!ushort(15); 
writer.byteOrder = ByteOrder.BigEndian;
writer.write!ushort(615); 
writer.padFill(4); 
writer.writeString("test");

could be replaced with:

ubyte[] data = pack!`<H>H4xs`(15, 615, "test");

Available modifier characters

Modifier characters change byte order in place. Once set, it remains until the end of function call or until another one is set.

Character Effect
= Use native endian byte order
< Use little endian byte order
> Use big endian byte order
@ Use network byte order(big endian)

Example: pack!"<i>ii"(500, 500, 900) encodes first number in little endian and remaining two in big endian.

Available type specifiers

TIP: Common rule for (almost) all type specifiers is that all lowercase letters represent signed types and uppercase letters represent unsigned types.

Character Type Size
c char 1
b byte 1
B ubyte 1
h short 2
H ushort 2
i int 4
I uint 4
p ptrdiff_t 4/8
P size_t 4/8
l long 8
L ulong 8
f float 4
d double 8
s string string length + nul
S string string length
x - 1 (null/skip byte)

Types with size 4/8 (p and P) depend on local machine architecture. On 32 bit architectures they occupy 4 bytes, on 64 bit architectures they occupy 8 bytes.

Arrays

Type specifiers can be prefixed with * to denote dynamic array. If omitted, array elements will be written with no length indicator or null terminator, which means that reading arrays encoded this way requires you to manually store array length.

ubyte[] bytes = pack!`*i`([1,2,3]);
bytes.unpack!`*i` == tuple([1,2,3]); // tuple(int[])

In pack functions type specifier can prefixed with number, meaning exactly number of elements will be written. If array is too small RangeError is thrown. In unpack functions prefixing type specifier with number denotes static array.

ubyte[] bytes = pack!`i`([1,2,3]); // all elements written without length or terminator
bytes.unpack!`3i` == tuple([1,2,3]); // tuple(int[3])

Character x have slighty different meaning depending if used in pack or unpack functions. When passed to pack, null byte is added to output. When passed to unpack, one byte is skipped from input data.

Examples:

Packing

pack function family has two variants:

In-Memory packing

File packing

These function take File instance as first argument followed by data to pack.

Unpacking

Similar to pack functions, unpacking functions have two variants, one taking InputRange of ubytes and second taking std.stdio.File.