-
Notifications
You must be signed in to change notification settings - Fork 105
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
57 changed files
with
8,758 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
dub.selections.json | ||
.dub | ||
tests/*/tests | ||
__test__*__ | ||
*.obj | ||
*.[oa] | ||
*.so | ||
*.lib | ||
*.dll | ||
*.sublime-project | ||
*.sublime-workspace | ||
msgpack-d-test-unittest |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
Boost Software License - Version 1.0 - August 17th, 2003 | ||
|
||
Permission is hereby granted, free of charge, to any person or organization | ||
obtaining a copy of the software and accompanying documentation covered by | ||
this license (the "Software") to use, reproduce, display, distribute, | ||
execute, and transmit the Software, and to prepare derivative works of the | ||
Software, and to permit third-parties to whom the Software is furnished to | ||
do so, all subject to the following: | ||
|
||
The copyright notices in the Software and this entire statement, including | ||
the above license grant, this restriction and the following disclaimer, | ||
must be included in all copies of the Software, in whole or in part, and | ||
all derivative works of the Software, unless such copies or derivative | ||
works are solely in the form of machine-executable object code generated by | ||
a source language processor. | ||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT | ||
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE | ||
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, | ||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | ||
DEALINGS IN THE SOFTWARE. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,199 @@ | ||
[![CI](https://github.com/msgpack/msgpack-d/actions/workflows/d.yml/badge.svg)](https://github.com/msgpack/msgpack-d/actions/workflows/d.yml) | ||
|
||
# MessagePack for D | ||
|
||
MessagePack is a binary-based JSON-like serialization library. | ||
|
||
MessagePack for D is a pure D implementation of MessagePack. | ||
|
||
# Features | ||
|
||
* Small size and High performance | ||
* Zero copy serialization / deserialization | ||
* Streaming deserializer for non-contiguous IO situation | ||
* Supports D features (Ranges, Tuples, real type) | ||
|
||
Note: The `real` type is only supported in D. | ||
Don't use the `real` type when communicating with other programming languages. | ||
Note that `Unpacker` will raise an exception if a loss of precision occurs. | ||
|
||
## Current Limitations | ||
|
||
* No circular references support | ||
* If you want to use the LDC compiler, you need at least version 0.15.2 beta2 | ||
|
||
# Install | ||
|
||
Use dub to add it as a dependency: | ||
|
||
```sh | ||
% dub install msgpack-d | ||
``` | ||
|
||
# Usage | ||
|
||
Example code can be found in the `example` directory. | ||
|
||
The documentation can be found [here](http://msgpack.github.io/msgpack-d/) | ||
|
||
## pack / unpack | ||
|
||
msgpack-d is very simple to use. Use `pack` for serialization, and `unpack` for deserialization: | ||
|
||
```D | ||
import std.file; | ||
import msgpack; | ||
struct S { int x; float y; string z; } | ||
void main() | ||
{ | ||
S input = S(10, 25.5, "message"); | ||
// serialize data | ||
ubyte[] inData = pack(input); | ||
// write data to a file | ||
write("file.dat", inData); | ||
// read data from a file | ||
ubyte[] outData = cast(ubyte[])read("file.dat"); | ||
// unserialize the data | ||
S target = outData.unpack!S(); | ||
// verify data is the same | ||
assert(target.x == input.x); | ||
assert(target.y == input.y); | ||
assert(target.z == input.z); | ||
} | ||
``` | ||
|
||
### Feature: Skip serialization/deserialization of a specific field. | ||
|
||
Use the `@nonPacked` attribute: | ||
|
||
```d | ||
struct User | ||
{ | ||
string name; | ||
@nonPacked int level; // pack / unpack will ignore the 'level' field | ||
} | ||
``` | ||
|
||
### Feature: Use your own serialization/deserialization routines for custom class and struct types. | ||
|
||
msgpack-d provides the functions `registerPackHandler` / `registerUnpackHandler` to allow you | ||
to use custom routines during the serialization or deserialization of user-defined class and struct types. | ||
This feature is especially useful when serializing a derived class object when that object is statically | ||
typed as a base class object. | ||
|
||
For example: | ||
|
||
```d | ||
class Document { } | ||
class XmlDocument : Document | ||
{ | ||
this() { } | ||
this(string name) { this.name = name; } | ||
string name; | ||
} | ||
void xmlPackHandler(ref Packer p, ref XmlDocument xml) | ||
{ | ||
p.pack(xml.name); | ||
} | ||
void xmlUnpackHandler(ref Unpacker u, ref XmlDocument xml) | ||
{ | ||
u.unpack(xml.name); | ||
} | ||
void main() | ||
{ | ||
/// Register the 'xmlPackHandler' and 'xmlUnpackHandler' routines for | ||
/// XmlDocument object instances. | ||
registerPackHandler!(XmlDocument, xmlPackHandler); | ||
registerUnpackHandler!(XmlDocument, xmlUnpackHandler); | ||
/// Now we can serialize/deserialize XmlDocument object instances via a | ||
/// base class reference. | ||
Document doc = new XmlDocument("test.xml"); | ||
auto data = pack(doc); | ||
XmlDocument xml = unpack!XmlDocument(data); | ||
assert(xml.name == "test.xml"); // xml.name is "test.xml" | ||
} | ||
``` | ||
|
||
In addition, here is also a method using `@serializedAs` attribute: | ||
|
||
```d | ||
import std.datetime: Clock, SysTime; | ||
static struct SysTimePackProxy | ||
{ | ||
static void serialize(ref Packer p, ref in SysTime tim) | ||
{ | ||
p.pack(tim.toISOExtString()); | ||
} | ||
static void deserialize(ref Unpacker u, ref SysTime tim) | ||
{ | ||
string tmp; | ||
u.unpack(tmp); | ||
tim = SysTime.fromISOExtString(tmp); | ||
} | ||
} | ||
static struct LogData | ||
{ | ||
string msg; | ||
string file; | ||
ulong line; | ||
@serializedAs!SysTimePackProxy SysTime timestamp; | ||
this(string message, string file = __FILE__, ulong line = __LINE__) | ||
{ | ||
this.msg = message; | ||
this.file = file; | ||
this.line = line; | ||
this.timestamp = Clock.currTime(); | ||
} | ||
} | ||
void main() | ||
{ | ||
/// Now we can serialize/deserialize LogData | ||
LogData[] logs; | ||
logs ~= LogData("MessagePack is nice!"); | ||
auto data = pack(logs); | ||
LogData[] datas = unpack!(LogData[])(data); | ||
assert(datas[0].timestamp.toString() == datas[0].timestamp.toString()); | ||
} | ||
``` | ||
|
||
## The PackerImpl / Unpacker / StreamingUnpacker types | ||
|
||
These types are used by the `pack` and `unpack` functions. | ||
|
||
See the documentation of [PackerImpl](http://msgpack.github.io/msgpack-d/#PackerImpl), [Unpacker](http://msgpack.github.io/msgpack-d/#Unpacker) and [StreamingUnpacker](http://msgpack.github.io/msgpack-d/#StreamingUnpacker) for more details. | ||
|
||
# Links | ||
|
||
* [The MessagePack Project](http://msgpack.org/) | ||
|
||
The official MessagePack protocol website. | ||
|
||
* [msgpack-d's issue tracker](https://github.com/msgpack/msgpack-d/issues) | ||
|
||
Use this issue tracker to review and file bugs in msgpack-d. | ||
|
||
* [MessagePack's Github](http://github.com/msgpack/) | ||
|
||
Other language bindings and implementations of the msgpack protocol can be found here. | ||
|
||
# Copyright | ||
|
||
Copyright (c) 2010- Masahiro Nakagawa | ||
|
||
# License | ||
|
||
Distributed under the [Boost Software License, Version 1.0](http://www.boost.org/users/license.html). |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
{ | ||
"name": "msgpack-d", | ||
"description": "MessagePack for D.", | ||
"authors": ["Masahiro Nakagawa"], | ||
"homepage": "https://github.com/msgpack/msgpack-d", | ||
"license": "Boost Software License, Version 1.0", | ||
"copyright": "Copyright (c) 2010- Masahiro Nakagawa", | ||
|
||
"configurations": [ | ||
{ | ||
"name": "default", | ||
"targetType": "library" | ||
}, | ||
{ | ||
"name": "unittest", | ||
"dflags": ["-dip25", "-dip1000"] | ||
} | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
import std.conv; | ||
import std.stdio; | ||
import std.datetime; | ||
import msgpack; | ||
|
||
struct A { | ||
int x; | ||
} | ||
|
||
struct Foo | ||
{ | ||
A[] a; | ||
} | ||
|
||
void main() | ||
{ | ||
Foo foo; | ||
foreach (a; 'a' .. 'z') | ||
foreach (b; 'a' .. 'z') | ||
foreach (c; 'a' .. 'z') | ||
foo.a ~= A(); | ||
|
||
auto sw = StopWatch(AutoStart.yes); | ||
ubyte[] data = msgpack.pack(foo); | ||
writeln(sw.peek.usecs); | ||
|
||
auto sw2 = StopWatch(AutoStart.yes); | ||
Foo foo1 = msgpack.unpack(data).as!(typeof(foo)); | ||
writeln(sw2.peek.usecs); | ||
|
||
assert(foo == foo1); | ||
|
||
Foo foo2; | ||
auto sw3 = StopWatch(AutoStart.yes); | ||
msgpack.unpack(data, foo2); | ||
writeln(sw3.peek.usecs); | ||
|
||
assert(foo == foo2); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
// Written in the D programming language. | ||
|
||
/** | ||
* Attribute usage | ||
*/ | ||
|
||
import msgpack; | ||
|
||
struct Hoge | ||
{ | ||
string f1; | ||
@nonPacked int f2; | ||
} | ||
|
||
void main() | ||
{ | ||
Hoge hoge = Hoge("hoge", 10); | ||
Hoge fuga; | ||
|
||
unpack(pack(hoge), fuga); | ||
assert(hoge.f1 == fuga.f1); | ||
assert(hoge.f2 != fuga.f2); | ||
assert(fuga.f2 == int.init); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
// Written in the D programming language. | ||
|
||
/** | ||
* Compares direct conversion with stream. | ||
*/ | ||
|
||
import std.datetime; | ||
import std.stdio; | ||
import std.typecons; | ||
|
||
import msgpack; | ||
|
||
|
||
void main() | ||
{ | ||
// tuple | ||
auto test1 = tuple(new int[](100), "MessagePack!", [1:2.0, 3:4.0, 5:6.0, 7:8.0]); | ||
auto data1 = pack(test1); | ||
|
||
// stream | ||
void s1() | ||
{ | ||
auto result = unpack(data1).as!(typeof(test1)); | ||
} | ||
|
||
// direct conversion | ||
void d1() | ||
{ | ||
typeof(test1) result; | ||
unpack(data1, result); | ||
} | ||
|
||
// array | ||
auto test2 = new int[](1000); | ||
auto data2 = pack(test2); | ||
|
||
// stream | ||
void s2() | ||
{ | ||
auto result = unpack(data2).as!(typeof(test2)); | ||
} | ||
|
||
// direct conversion | ||
void d2() | ||
{ | ||
typeof(test2) result; | ||
unpack(data2, result); | ||
} | ||
|
||
auto times = benchmark!(s1, d1, s2, d2)(1000); | ||
writeln("Stream(Tuple):", times[0].msecs); | ||
writeln("Direct(Tuple):", times[1].msecs); | ||
writeln("Stream(Array):", times[2].msecs); | ||
writeln("Direct(Array):", times[3].msecs); | ||
} |
Oops, something went wrong.