Bond
 
Loading...
Searching...
No Matches
simple_binary.h
1// Copyright (c) Microsoft. All rights reserved.
2// Licensed under the MIT license. See LICENSE file in the project root for full license information.
3
4#pragma once
5
6#include <bond/core/config.h>
7
8#include "encoding.h"
9
10#include <bond/core/bond_version.h>
11#include <bond/core/traits.h>
12
13#include <boost/call_traits.hpp>
14#include <boost/noncopyable.hpp>
15
16/*
17 .-------------.----------------.
18 struct | base fields | derived fields |
19 '-------------'----------------'
20
21 .----------.----------. .----------.
22 fields | field | field |...| field |
23 '----------'----------' '----------'
24
25 .----------.
26 field | value |
27 '----------'
28
29 .---.---.---.---.---.---.---.---.
30 value bool | | | | | | | | v |
31 '---'---'---'---'---'---'---'---'
32 0
33
34 all integral types are written binary, native size, uncompressed, little endian
35
36 float, double little endian
37
38
39 .-------.------------.
40 string, wstring | count | characters |
41 '-------'------------'
42
43 count uint32 count of 1-byte (for string)
44 or 2-byte (for wstring) Unicode code
45 units (variable encoded in v2)
46
47 characters 1-byte UTF-8 code units (for string) or 2-byte
48 UTF-16LE code units (for wstring)
49
50
51 .-------. .-------.
52 blob, list, set, | count | | items |...
53 vector, nullable '-------' '-------'
54
55 count uint32 count of items (variable encoded in v2)
56
57 items each item encoded according to its type
58
59 .-------. .-----.--------.
60 map | count | | key | mapped |...
61 '-------' '-----'--------'
62
63 count uint32 count of {key,mapped} pairs (variable encoded in v2)
64
65 key, mapped each item encoded according to its type
66
67 .-------. .-----------.
68 bonded | count | | marshaled |
69 '-------' '-----------'
70 count uint32 count of bytes (always fixed-width, even in v2)
71
72 marshaled a marshaled payload
73*/
74
75namespace bond
76{
77
78
79template <typename BufferT>
80class SimpleBinaryWriter;
81
82
84template <typename BufferT, typename MarshaledBondedProtocolsT>
86{
87public:
88 typedef BufferT Buffer;
89 typedef StaticParser<SimpleBinaryReader&> Parser;
91
92 BOND_STATIC_CONSTEXPR uint16_t magic = SIMPLE_PROTOCOL;
93 BOND_STATIC_CONSTEXPR uint16_t version = v2;
94
95
97 SimpleBinaryReader(typename boost::call_traits<Buffer>::param_type input,
98 uint16_t version_value = default_version<SimpleBinaryReader>::value)
99 : _input(input),
100 _version(version_value)
101 {
102 BOOST_ASSERT(_version <= SimpleBinaryReader::version);
103 }
104
105
106 // This identical to compiler generated ctor except for noexcept declaration.
107 // Copy ctor that is explicitly declared throw() is needed for boost::variant
108 // to use optimized code path.
110 SimpleBinaryReader(const SimpleBinaryReader& that) BOND_NOEXCEPT
111 : _input(that._input),
112 _version(that._version)
113 {}
114
115
117 bool operator==(const SimpleBinaryReader& rhs) const
118 {
119 return _input == rhs._input;
120 }
121
122
124 typename boost::call_traits<Buffer>::const_reference
125 GetBuffer() const
126 {
127 return _input;
128 }
129
130
132 typename boost::call_traits<Buffer>::reference
134 {
135 return _input;
136 }
137
138
139 bool ReadVersion()
140 {
141 uint16_t magic_value;
142
143 _input.Read(magic_value);
144 _input.Read(_version);
145
146 return magic_value == SimpleBinaryReader::magic
147 && _version <= SimpleBinaryReader::version;
148 }
149
150
151 // Read for basic types
152 template <typename T>
153 typename boost::disable_if<is_string_type<T> >::type
154 Read(T& var)
155 {
156 _input.Read(var);
157 }
158
159
160 // Read for strings
161 template <typename T>
162 typename boost::enable_if<is_string_type<T> >::type
163 Read(T& var)
164 {
165 uint32_t length = 0;
166
167 ReadSize(length);
168 detail::ReadStringData(_input, var, length);
169 }
170
171
172 // Read for blob
173 void Read(blob& var, uint32_t size)
174 {
175 _input.Read(var, size);
176 }
177
178
179 // Skip for basic types
180 template <typename T>
181 typename boost::disable_if<is_string_type<T> >::type
182 Skip()
183 {
184 _input.Skip(sizeof(T));
185 }
186
187
188 template <typename T>
189 void Skip(const bonded<T, SimpleBinaryReader&>& bonded);
190
191
192 // Skip for strings
193 template <typename T>
194 typename boost::enable_if<is_string_type<T> >::type
195 Skip()
196 {
197 uint32_t length;
198
199 ReadSize(length);
200 _input.Skip(length * sizeof(typename detail::string_char_int_type<T>::type));
201 }
202
203
204 void Skip(BondDataType type)
205 {
206 switch (type)
207 {
208 case BT_BOOL:
209 case BT_UINT8:
210 case BT_INT8:
211 _input.Skip(sizeof(uint8_t));
212 break;
213
214 case BT_UINT16:
215 case BT_INT16:
216 _input.Skip(sizeof(uint16_t));
217 break;
218
219 case BT_UINT32:
220 case BT_INT32:
221 _input.Skip(sizeof(uint32_t));
222 break;
223
224 case BT_UINT64:
225 case BT_INT64:
226 _input.Skip(sizeof(uint64_t));
227 break;
228
229 case BT_FLOAT:
230 _input.Skip(sizeof(float));
231 break;
232
233 case BT_DOUBLE:
234 _input.Skip(sizeof(double));
235 break;
236
237 case BT_STRING:
238 Skip<std::string>();
239 break;
240
241 case BT_WSTRING:
242 Skip<std::wstring>();
243 break;
244
245 default:
246 break;
247 }
248 }
249
250
251 template <typename T>
252 void ReadContainerBegin(uint32_t& size, T&)
253 {
254 ReadSize(size);
255 }
256
257 void ReadContainerEnd()
258 {}
259
260protected:
261 void ReadSize(uint32_t& size)
262 {
263 if (_version == v1)
264 Read(size);
265 else
266 ReadVariableUnsigned(_input, size);
267 }
268
269
270 template <typename Input, typename MarshaledBondedProtocols, typename Output>
271 friend
272 bool is_protocol_version_same(const SimpleBinaryReader<Input, MarshaledBondedProtocols>&,
273 const SimpleBinaryWriter<Output>&);
274
275 Buffer _input;
276 uint16_t _version;
277};
278
279
280template <typename BufferT, typename MarshaledBondedProtocolsT>
281BOND_CONSTEXPR_OR_CONST uint16_t SimpleBinaryReader<BufferT, MarshaledBondedProtocolsT>::magic;
282
283
285template <typename BufferT>
287 : boost::noncopyable
288{
289public:
290 typedef BufferT Buffer;
292
294 SimpleBinaryWriter(Buffer& output,
295 uint16_t version = default_version<Reader>::value)
296 : _output(output),
297 _version(version)
298 {
299 BOOST_ASSERT(_version <= Reader::version);
300 }
301
303 typename boost::call_traits<Buffer>::reference
305 {
306 return _output;
307 }
308
309 void WriteVersion()
310 {
311 _output.Write(Reader::magic);
312 _output.Write(_version);
313 }
314
315 void WriteStructBegin(const Metadata& /*metadata*/, bool /*base*/)
316 {}
317
318 void WriteStructEnd(bool = false)
319 {}
320
321 void WriteFieldBegin(BondDataType /*type*/, uint16_t /*id*/, const Metadata& /*metadata*/)
322 {}
323
324 void WriteFieldBegin(BondDataType /*type*/, uint16_t /*id*/)
325 {}
326
327 void WriteFieldEnd()
328 {}
329
330
331 // WriteContainerBegin
332 template <typename T>
333 void WriteContainerBegin(uint32_t size, T)
334 {
335 WriteSize(size);
336 }
337
338
339 // WriteContainerEnd
340 void WriteContainerEnd()
341 {}
342
343 template <typename T>
344 void WriteField(uint16_t /*id*/, const bond::Metadata& /*metadata*/, const T& value)
345 {
346 Write(value);
347 }
348
349 void WriteFieldOmitted(BondDataType type, uint16_t /*id*/, const Metadata& metadata);
350
351 // Write for basic types
352 template <typename T>
353 typename boost::disable_if<is_string_type<T> >::type
354 Write(const T& value)
355 {
356 _output.Write(value);
357 }
358
359 // Write for strings
360 template <typename T>
361 typename boost::enable_if<is_string_type<T> >::type
362 Write(const T& value)
363 {
364 uint32_t length = string_length(value);
365
366 WriteSize(length);
367 detail::WriteStringData(_output, value, length);
368 }
369
370 // Write for blob
371 void Write(const blob& value)
372 {
373 _output.Write(value);
374 }
375
376protected:
377 void WriteSize(uint32_t& size)
378 {
379 if (_version == v1)
380 Write(size);
381 else
382 WriteVariableUnsigned(_output, size);
383 }
384
385 template <typename Input, typename MarshaledBondedProtocols, typename Output>
386 friend
387 bool is_protocol_version_same(const SimpleBinaryReader<Input, MarshaledBondedProtocols>&,
388 const SimpleBinaryWriter<Output>&);
389
390 Buffer& _output;
391 uint16_t _version;
392};
393
394
395template <typename Input, typename MarshaledBondedProtocols> struct
396protocol_has_multiple_versions<SimpleBinaryReader<Input, MarshaledBondedProtocols> >
397 : std::true_type {};
398
399
400template <typename Input, typename MarshaledBondedProtocols, typename Output>
401bool is_protocol_version_same(const SimpleBinaryReader<Input, MarshaledBondedProtocols>& reader,
402 const SimpleBinaryWriter<Output>& writer)
403{
404 return reader._version == writer._version;
405}
406
407template <typename Output> struct
408may_omit_fields<SimpleBinaryWriter<Output> >
409 : std::false_type {};
410
411} // namespace bond
Reader for Simple Binary protocol.
Definition: simple_binary.h:86
boost::call_traits< Buffer >::const_reference GetBuffer() const
Access to underlying buffer.
Definition: simple_binary.h:125
SimpleBinaryReader(typename boost::call_traits< Buffer >::param_type input, uint16_t version_value=default_version< SimpleBinaryReader >::value)
Construct from input buffer/stream containing serialized data.
Definition: simple_binary.h:97
bool operator==(const SimpleBinaryReader &rhs) const
Comparison operator.
Definition: simple_binary.h:117
SimpleBinaryReader(const SimpleBinaryReader &that) BOND_NOEXCEPT
Copy constructor.
Definition: simple_binary.h:110
boost::call_traits< Buffer >::reference GetBuffer()
Access to underlying buffer.
Definition: simple_binary.h:133
Writer for Simple Binary protocol.
Definition: simple_binary.h:288
boost::call_traits< Buffer >::reference GetBuffer()
Access to underlying buffer.
Definition: simple_binary.h:304
SimpleBinaryWriter(Buffer &output, uint16_t version=default_version< Reader >::value)
Construct from output buffer/stream.
Definition: simple_binary.h:294
namespace bond
Definition: apply.h:17