Report a bug
If you spot a problem with this page, click here to create a GitHub issue.
Improve this page
Quickly fork, edit online, and submit a pull request for this page. Requires a signed-in GitHub account. This works well for small changes. If you'd like to make larger changes you may want to consider using a local clone.

mir.ser.msgpack

High level Msgpack serialization API

enum MessagePackFmt: ubyte;
MessagePack support
fixint
Integers
7-bit positive integer
fixnint
5-bit negative integer (???)
uint8
8-bit unsigned integer
uint16
16-bit unsigned integer
uint32
32-bit unsigned integer
uint64
64-bit unsigned integer
int8
8-bit signed integer
int16
16-bit signed integer
int32
32-bit signed integer
int64
64-bit signed integer
fixmap
Maps
Map with a maximum length of 15 key-value pairs
map16
Map with a maximum length of 65535 key-value pairs
map32
Map with a maximum length of 4294967295 key-value pairs
fixarray
Arrays
Array with a maximum length of 15 elements
array16
Array with a maximum length of 65535 elements
array32
Array with a maximum length of 4294967295 elements
fixstr
Strings
String with a maximum length of 31 bytes
str8
String with a maximum length of 255 (1 << 8 - 1) bytes
str16
String with a maximum length of 65535 (1 << 16 - 1) bytes
str32
String with a maximum length of 4294967295 (1 << 32 - 1) bytes
nil
Nil
false_
Boolean values
bin8
Binary (byte array)
Byte array with a maximum length of 255 bytes
bin16
Byte array with a maximum length of 65535 bytes
bin32
Byte array with a maximum length of 4294967295 bytes
fixext1
Implementation-specific extensions
Integer & byte array whose length is 1 byte
fixext2
Integer & byte array whose length is 2 bytes
fixext4
Integer & byte array whose length is 4 bytes
fixext8
Integer & byte array whose length is 8 bytes
fixext16
Integer & byte array whose length is 16 bytes
ext8
Integer & byte array whose maximum length is 255 bytes
ext16
Integer & byte array whose maximum length is 65535 bytes
ext32
Integer & byte array whose maximum length is 4294967295 bytes
float32
Floats
Single-precision IEEE 754 floating point number
float64
Double-precision IEEE 754 floating point number
struct MsgpackSerializer(Appender);
Msgpack serialization back-end
int serdeTarget;
Mutable value used to choose format specidied or user-defined serialization specializations
alias structBegin = aggrBegin!"beginMap";
alias structEnd = aggrEnd!"beginMap";
alias listBegin = aggrBegin!"beginArray";
alias listEnd = aggrEnd!"beginArray";
alias sexpBegin = listBegin;
alias sexpEnd = listEnd;
size_t stringBegin();
void putStringPart(scope const(char)[] str);
Puts string part. The implementation allows to split string unicode points.
@trusted void stringEnd(size_t state);
auto annotationsBegin();
void annotationsEnd(size_t state);
size_t annotationWrapperBegin();
alias annotationWrapperEnd = structEnd;
void putKey(scope const char[] key);
void putAnnotation(scope const(char)[] annotation);
void putSymbol(scope const char[] symbol);
void putValue(W, WordEndian endian)(BigIntView!(W, endian) view);
void putValue(size_t size)(auto const ref BigInt!size num);
void putValue(size_t size)(auto const ref Decimal!size num);
void putValue(typeof(null));
void putNull(IonTypeCode code);
void putValue(bool b);
void putValue(scope const(char)[] value);
void putValue(Clob value);
void putValue(Blob value);
void putValue(Timestamp value);
void elemBegin();
alias sexpElemBegin = elemBegin;
void nextTopLevelValue();
void serializeMsgpack(Appender, T)(Appender* appender, auto ref T value, int serdeTarget = SerdeTarget.ion);
immutable(ubyte)[] serializeMsgpack(T)(auto ref T value, int serdeTarget = SerdeTarget.ion);
Examples:
Test serializing booleans
assert(serializeMsgpack(true) == [0xc3]);
assert(serializeMsgpack(false) == [0xc2]);
Examples:
Test serializing nulls
assert(serializeMsgpack(null) == [0xc0]);
Examples:
Test serializing signed integral types
// Bytes
assert(serializeMsgpack(byte.min) == [0xd0, 0x80]);
assert(serializeMsgpack(byte.max) == [0x7f]);

// Shorts
assert(serializeMsgpack(short(byte.max)) == [0x7f]);
assert(serializeMsgpack(short(byte.max) + 1) == [0xd1, 0x00, 0x80]);
assert(serializeMsgpack(short.min) == [0xd1, 0x80, 0x00]);
assert(serializeMsgpack(short.max) == [0xd1, 0x7f, 0xff]);

// Integers
assert(serializeMsgpack(int(-32)) == [0xe0]);
assert(serializeMsgpack(int(byte.max)) == [0x7f]);
assert(serializeMsgpack(int(short.max)) == [0xd1, 0x7f, 0xff]);
assert(serializeMsgpack(int(short.max) + 1) == [0xd2, 0x00, 0x00, 0x80, 0x00]);
assert(serializeMsgpack(int.min) == [0xd2, 0x80, 0x00, 0x00, 0x00]);
assert(serializeMsgpack(int.max) == [0xd2, 0x7f, 0xff, 0xff, 0xff]);

// Long integers
assert(serializeMsgpack(long(int.max)) == [0xd2, 0x7f, 0xff, 0xff, 0xff]);
assert(serializeMsgpack(long(int.max) + 1) == [0xd3, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00]);
assert(serializeMsgpack(long.max) == [0xd3, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff]);
assert(serializeMsgpack(long.min) == [0xd3, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
Examples:
Test serializing unsigned integral types
// Unsigned bytes
assert(serializeMsgpack(ubyte.min) == [0x00]);
assert(serializeMsgpack(ubyte((1 << 7) - 1)) == [0x7f]);
assert(serializeMsgpack(ubyte((1 << 7))) == [0xcc, 0x80]);
assert(serializeMsgpack(ubyte.max) == [0xcc, 0xff]);

// Unsigned shorts
assert(serializeMsgpack(ushort(ubyte.max)) == [0xcc, 0xff]);
assert(serializeMsgpack(ushort(ubyte.max + 1)) == [0xcd, 0x01, 0x00]);
assert(serializeMsgpack(ushort.min) == [0x00]);
assert(serializeMsgpack(ushort.max) == [0xcd, 0xff, 0xff]); 

// Unsigned integers
assert(serializeMsgpack(uint(ubyte.max)) == [0xcc, 0xff]);
assert(serializeMsgpack(uint(ushort.max)) == [0xcd, 0xff, 0xff]);
assert(serializeMsgpack(uint(ushort.max + 1)) == [0xce, 0x00, 0x01, 0x00, 0x00]);
assert(serializeMsgpack(uint.min) == [0x00]);
assert(serializeMsgpack(uint.max) == [0xce, 0xff, 0xff, 0xff, 0xff]);

// Long unsigned integers
assert(serializeMsgpack(ulong(ubyte.max)) == [0xcc, 0xff]);
assert(serializeMsgpack(ulong(ushort.max)) == [0xcd, 0xff, 0xff]);
assert(serializeMsgpack(ulong(uint.max)) == [0xce, 0xff, 0xff, 0xff, 0xff]);
assert(serializeMsgpack(ulong(uint.max) + 1) == [0xcf, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00]);
assert(serializeMsgpack(ulong.min) == [0x00]);
assert(serializeMsgpack(ulong.max) == [0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff]);

// Mir's BigIntView
import mir.bignum.integer : BigInt;
assert(serializeMsgpack(BigInt!2(0xDEADBEEF)) == [0xd3, 0x00, 0x00, 0x00, 0x00, 0xde, 0xad, 0xbe, 0xef]);
Examples:
Test serializing floats / doubles / reals
assert(serializeMsgpack(float.min_normal) == [0xca, 0x00, 0x80, 0x00, 0x00]);
assert(serializeMsgpack(float.max) == [0xca, 0x7f, 0x7f, 0xff, 0xff]);
assert(serializeMsgpack(double.min_normal) == [0xcb, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
assert(serializeMsgpack(double.max) == [0xcb, 0x7f, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff]);
static if (real.mant_dig == 64)
{
    assert(serializeMsgpack(real.min_normal) == [0xcb,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00]);
    assert(serializeMsgpack(real.max) == [0xcb,0x7f,0xf0,0x00,0x00,0x00,0x00,0x00,0x00]);
}

// Mir's Decimal
import mir.bignum.decimal : Decimal;
assert(serializeMsgpack(Decimal!2("777.777")) == [0xcb,0x40,0x88,0x4e,0x37,0x4b,0xc6,0xa7,0xf0]);
assert(serializeMsgpack(Decimal!2("-777.7")) == [0xcb,0xc0,0x88,0x4d,0x99,0x99,0x99,0x99,0x9a]);
Examples:
Test serializing timestamps
import mir.timestamp : Timestamp;
assert(serializeMsgpack(Timestamp(1970, 1, 1, 0, 0, 0)) == [0xd6, 0xff, 0x00, 0x00, 0x00, 0x00]);
assert(serializeMsgpack(Timestamp(2038, 1, 19, 3, 14, 7)) == [0xd6, 0xff, 0x7f, 0xff, 0xff, 0xff]);
assert(serializeMsgpack(Timestamp(2299, 12, 31, 23, 59, 59)) == [0xd7, 0xff, 0x00, 0x00, 0x00, 0x02, 0x6c, 0xb5, 0xda, 0xff]);
assert(serializeMsgpack(Timestamp(3000, 12, 31, 23, 59, 59)) == [0xc7, 0x0c, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x93, 0x3f, 0xff, 0x7f]);
Examples:
Test serializing strings
import std.array : replicate;
assert(serializeMsgpack("a") == [0xa1, 0x61]);

// These need to be trusted because we cast const(char)[] to ubyte[] (which is fine here!)
() @trusted {
    auto a = "a".replicate(32);
    assert(serializeMsgpack(a) == 
        cast(ubyte[])[0xd9, 0x20] ~ cast(ubyte[])a);
} ();

() @trusted {
    auto a = "a".replicate(ushort.max);
    assert(serializeMsgpack(a) == 
        cast(ubyte[])[0xda, 0xff, 0xff] ~ cast(ubyte[])a);
} ();

() @trusted {
    auto a = "a".replicate(ushort.max + 1);
    assert(serializeMsgpack(a) == 
        cast(ubyte[])[0xdb, 0x00, 0x01, 0x00, 0x00] ~ cast(ubyte[])a);
} ();
Examples:
Test serializing blobs / clobs
import mir.lob : Blob, Clob;
import std.array : replicate;

// Blobs
// These need to be trusted because we cast const(char)[] to ubyte[] (which is fine here!)
() @trusted {
    auto de = "\xde".replicate(32);
    assert(serializeMsgpack(Blob(cast(ubyte[])de)) ==
        cast(ubyte[])[0xc4, 0x20] ~ cast(ubyte[])de);
} ();

() @trusted {
    auto de = "\xde".replicate(ushort.max);
    assert(serializeMsgpack(Blob(cast(ubyte[])de)) ==
        cast(ubyte[])[0xc5, 0xff, 0xff] ~ cast(ubyte[])de);
} ();

() @trusted {
    auto de = "\xde".replicate(ushort.max + 1);
    assert(serializeMsgpack(Blob(cast(ubyte[])de)) ==
        cast(ubyte[])[0xc6, 0x00, 0x01, 0x00, 0x00] ~ cast(ubyte[])de);
} ();

// Clobs (serialized just as regular strings here)
() @trusted {
    auto de = "\xde".replicate(32);
    assert(serializeMsgpack(Clob(de)) == 
        cast(ubyte[])[0xd9, 0x20] ~ cast(ubyte[])de);
} ();
Examples:
Test serializing arrays
// nested arrays
assert(serializeMsgpack([["foo"], ["bar"], ["baz"]]) == [0x93, 0x91, 0xa3, 0x66, 0x6f, 0x6f, 0x91, 0xa3, 0x62, 0x61, 0x72, 0x91, 0xa3, 0x62, 0x61, 0x7a]);
assert(serializeMsgpack([0xDEADBEEF, 0xCAFEBABE, 0xAAAA_AAAA]) == [0x93, 0xce, 0xde, 0xad, 0xbe, 0xef, 0xce, 0xca, 0xfe, 0xba, 0xbe, 0xce, 0xaa, 0xaa, 0xaa, 0xaa]);
assert(serializeMsgpack(["foo", "bar", "baz"]) == [0x93, 0xa3, 0x66, 0x6f, 0x6f, 0xa3, 0x62, 0x61, 0x72, 0xa3, 0x62, 0x61, 0x7a]);
assert(serializeMsgpack([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17]) == [0xdc,0x00,0x11,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11]);
Examples:
Test serializing enums
enum Foo
{
    Bar,
    Baz
}

assert(serializeMsgpack(Foo.Bar) == [0xa3,0x42,0x61,0x72]);
assert(serializeMsgpack(Foo.Baz) == [0xa3,0x42,0x61,0x7a]);
Examples:
Test serializing maps (structs)
static struct Book
{
    string title;
    bool wouldRecommend;
    string description;
    uint numberOfNovellas;
    double price;
    float weight;
    string[] tags;
}

Book book = Book("A Hero of Our Time", true, "", 5, 7.99, 6.88, ["russian", "novel", "19th century"]);

// This will probably break if you modify how any of the data types
// are serialized.
assert(serializeMsgpack(book) == [0x87,0xa5,0x74,0x69,0x74,0x6c,0x65,0xb2,0x41,0x20,0x48,0x65,0x72,0x6f,0x20,0x6f,0x66,0x20,0x4f,0x75,0x72,0x20,0x54,0x69,0x6d,0x65,0xae,0x77,0x6f,0x75,0x6c,0x64,0x52,0x65,0x63,0x6f,0x6d,0x6d,0x65,0x6e,0x64,0xc3,0xab,0x64,0x65,0x73,0x63,0x72,0x69,0x70,0x74,0x69,0x6f,0x6e,0xa0,0xb0,0x6e,0x75,0x6d,0x62,0x65,0x72,0x4f,0x66,0x4e,0x6f,0x76,0x65,0x6c,0x6c,0x61,0x73,0x05,0xa5,0x70,0x72,0x69,0x63,0x65,0xcb,0x40,0x1f,0xf5,0xc2,0x8f,0x5c,0x28,0xf6,0xa6,0x77,0x65,0x69,0x67,0x68,0x74,0xca,0x40,0xdc,0x28,0xf6,0xa4,0x74,0x61,0x67,0x73,0x93,0xa7,0x72,0x75,0x73,0x73,0x69,0x61,0x6e,0xa5,0x6e,0x6f,0x76,0x65,0x6c,0xac,0x31,0x39,0x74,0x68,0x20,0x63,0x65,0x6e,0x74,0x75,0x72,0x79]);
Examples:
Test serializing a large map (struct)
static struct HugeStruct
{
    bool a;
    bool b;
    bool c;
    bool d;
    bool e;
    string f;
    string g;
    string h;
    string i;
    string j;
    int k;
    int l;
    int m;
    int n;
    int o;
    long p;
}

HugeStruct s = HugeStruct(true, true, true, true, true, "", "", "", "", "", 123, 456, 789, 123, 456, 0xDEADBEEF);
assert(serializeMsgpack(s) == [0xde,0x00,0x10,0xa1,0x61,0xc3,0xa1,0x62,0xc3,0xa1,0x63,0xc3,0xa1,0x64,0xc3,0xa1,0x65,0xc3,0xa1,0x66,0xa0,0xa1,0x67,0xa0,0xa1,0x68,0xa0,0xa1,0x69,0xa0,0xa1,0x6a,0xa0,0xa1,0x6b,0x7b,0xa1,0x6c,0xd1,0x01,0xc8,0xa1,0x6d,0xd1,0x03,0x15,0xa1,0x6e,0x7b,0xa1,0x6f,0xd1,0x01,0xc8,0xa1,0x70,0xd3,0x00,0x00,0x00,0x00,0xde,0xad,0xbe,0xef]);
Examples:
Test serializing annotated structs
import mir.algebraic;
import mir.serde : serdeAlgebraicAnnotation;

@serdeAlgebraicAnnotation("Foo")
static struct Foo
{
    string bar;
}

@serdeAlgebraicAnnotation("Fooz")
static struct Fooz
{
    long bar;
}

alias V = Variant!(Foo, Fooz);
auto foo = V(Foo("baz"));

assert(serializeMsgpack(foo) == [0x81,0xa3,0x46,0x6f,0x6f,0x81,0xa3,0x62,0x61,0x72,0xa3,0x62,0x61,0x7a]);
Examples:
Test custom serialize function with MessagePack
static class MyExampleClass
{
    string text;

    this(string text)
    {
        this.text = text;
    }

    void serialize(S)(ref S serializer) const
    {
        auto state = serializer.stringBegin;
        serializer.putStringPart("Hello! ");
        serializer.putStringPart("String passed: ");
        serializer.putStringPart(this.text);
        serializer.stringEnd(state);

        import mir.ion.type_code : IonTypeCode;
        serializer.putNull(IonTypeCode.string);
    }
}

assert(serializeMsgpack(new MyExampleClass("foo bar baz")) == [0xd9,0x21,0x48,0x65,0x6c,0x6c,0x6f,0x21,0x20,0x53,0x74,0x72,0x69,0x6e,0x67,0x20,0x70,0x61,0x73,0x73,0x65,0x64,0x3a,0x20,0x66,0x6f,0x6f,0x20,0x62,0x61,0x72,0x20,0x62,0x61,0x7a,0xc0]);
Examples:
Test excessively large struct
import mir.ion.exception : IonException;

static class HugeStruct
{
    void serialize(S)(ref S serializer) const
    {
        auto state = serializer.structBegin(size_t(uint.max) + 1);
    }
}

bool caught = false;
try
{
    serializeMsgpack(new HugeStruct());
}
catch (IonException e)
{
    caught = true;
}

assert(caught);
Examples:
Test excessively large array
import mir.ion.exception : IonException;

static class HugeArray
{
    void serialize(S)(ref S serializer) const
    {
        auto state = serializer.listBegin(size_t(uint.max) + 1); 
    }
}

bool caught = false;
try 
{
    serializeMsgpack(new HugeArray());
}
catch (IonException e)
{
    caught = true;
}

assert(caught);
Examples:
Test invalidly large BigInt
import mir.ion.exception : IonException;
import mir.bignum.integer : BigInt;

bool caught = false;
try
{
    serializeMsgpack(BigInt!4.fromHexString("c39b18a9f06fd8e962d99935cea0707f79a222050aaeaaaed17feb7aa76999d7"));
}
catch (IonException e)
{
    caught = true;
}
assert(caught);