1 /**
2  * Модуль сериализатора MessagePack
3  *
4  * Copyright: (c) 2015-2017, Milofon Project.
5  * License: Subject to the terms of the BSD license, as written in the included LICENSE.txt file.
6  * Author: <m.galanin@milofon.org> Maksim Galanin
7  * Date: 2018-01-28
8  */
9 
10 module dango.service.serializer.msgpack;
11 
12 private
13 {
14     import std.algorithm.searching : startsWith;
15 
16     import proped : Properties;
17     import msgpack;
18 
19     import dango.service.serializer.core;
20 }
21 
22 
23 class MsgPackSerializer : Serializer
24 {
25     private bool _withFieldName;
26 
27 
28     this()
29     {
30         _withFieldName = false;
31     }
32 
33 
34     this(bool withFieldName)
35     {
36         _withFieldName = withFieldName;
37     }
38 
39 
40     override void initialize(Properties config)
41     {
42         _withFieldName = config.getOrElse!bool("withFieldName", false);
43     }
44 
45 
46     override UniNode deserialize(ubyte[] bytes)
47     {
48         auto unpacker = StreamingUnpacker(bytes);
49         unpacker.execute();
50         return toUniNode(unpacker.purge);
51     }
52 
53 
54     override ubyte[] serialize(UniNode node)
55     {
56         Value val = fromUniNode(node);
57         auto packer = Packer(_withFieldName);
58         val.toMsgpack(packer);
59         return packer.stream.data;
60     }
61 }
62 
63 
64 private:
65 
66 
67 UniNode toUniNode(Value input)
68 {
69     UniNode convert(Value node)
70     {
71         switch(node.type) with (Value)
72         {
73             case Type.nil:
74                 return UniNode();
75             case Type.boolean:
76                 return UniNode(node.via.boolean);
77             case Type.unsigned:
78                 return UniNode(node.via.uinteger);
79             case Type.signed:
80                 return UniNode(node.via.integer);
81             case Type.floating:
82                 return UniNode(node.via.floating);
83             case Type.raw:
84                 return UniNode(node.via.raw);
85             case Type.array:
86             {
87                 UniNode[] arr = new UniNode[](node.via.array.length);
88                 foreach(i, Value ch; node.via.array)
89                     arr[i] = convert(ch);
90                 return UniNode(arr);
91             }
92             case Type.map:
93             {
94                 UniNode[string] map;
95                 foreach(Value key, Value ch; node.via.map)
96                 {
97                     string k = cast(string)key.via.raw;
98                     map[k] = convert(ch);
99                 }
100                 return UniNode(map);
101             }
102             default:
103                 return UniNode();
104         }
105     }
106 
107     return convert(input);
108 }
109 
110 
111 Value fromUniNode(UniNode input)
112 {
113     Value convert(UniNode node)
114     {
115         switch(node.type) with (UniNode)
116         {
117             case Type.nil:
118                 return Value();
119             case Type.boolean:
120                 return Value(node.get!bool);
121             case Type.signed:
122                 return Value(node.get!long);
123             case Type.unsigned:
124                 return Value(node.get!ulong);
125             case Type.floating:
126                 return Value(node.get!double);
127             case Type.raw:
128                 return Value(node.get!(ubyte[]));
129             case Type.text:
130                 return Value(node.get!(string));
131             case Type.array:
132             {
133                 Value[] arr;
134                 foreach(UniNode ch; node.get!(UniNode[]))
135                     arr ~= convert(ch);
136                 return Value(arr);
137             }
138             case Type.object:
139             {
140                 Value[Value] map;
141                 foreach(string key, UniNode ch; node.get!(UniNode[string]))
142                     map[Value(key)] = convert(ch);
143                 return Value(map);
144             }
145             default:
146                 return Value();
147         }
148     }
149 
150     return convert(input);
151 }