Bond
 
Loading...
Searching...
No Matches
compact_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 "detail/simple_array.h"
9#include "encoding.h"
10
11#include <bond/core/bond_version.h>
12#include <bond/core/detail/checked.h>
13#include <bond/core/traits.h>
14#include <bond/stream/output_counter.h>
15
16#include <boost/call_traits.hpp>
17#include <boost/noncopyable.hpp>
18#include <boost/static_assert.hpp>
19
20#include <cstring>
21
22/*
23
24 .----------.--------------. .----------.---------.
25 struct (v1) | fields | BT_STOP_BASE |...| fields | BT_STOP |
26 '----------'--------------' '----------'---------'
27
28 .----------.----------.--------------. .----------.---------.
29 struct (v2) | length | fields | BT_STOP_BASE |...| fields | BT_STOP |
30 '----------'----------'--------------' '----------'---------'
31
32 length variable int encoded uint32 length of following fields, up to and
33 including BT_STOP but excluding length itself.
34
35 .----------.----------. .----------.
36 fields | field | field |...| field |
37 '----------'----------' '----------'
38
39 .----------.----------.
40 field | id+type | value |
41 '----------'----------'
42
43 .---.---.---.---.---.---.---.---. i - id bits (BE unsigned int)
44 id+type 0 <= id <= 5 | i | i | i | t | t | t | t | t | t - type bits
45 '---'---'---'---'---'---'---'---' v - value bits
46 2 0 4 0
47
48 .---.---.---.---.---.---.---.---.---. .---.
49 5 < id <= 0xff | 1 | 1 | 0 | t | t | t | t | t | i |...| i |
50 '---'---'---'---'---'---'---'---'---' '---'
51 4 0 7 0
52
53 .---.---.---.---.---.---.---.---.---. .---.---. .---.
54 0xff < id <= 0xffff | 1 | 1 | 1 | t | t | t | t | t | i |...| i | i |...| i |
55 '---'---'---'---'---'---'---'---'---' '---'---' '---'
56 4 0 7 0 15 8
57
58
59 .---.---.---.---.---.---.---.---.
60 value bool | | | | | | | | v |
61 '---'---'---'---'---'---'---'---'
62 0
63
64 .---.---.---.---.---.---.---.---.
65 int8, uint8 | v | v | v | v | v | v | v | v |
66 '---'---'---'---'---'---'---'---'
67 7 0
68
69 signed uses two's complement
70
71 .---.---. .---.---.---. .---.
72 uint16, uint32, | 1 | v |...| v | 0 | v |...| v | [...]
73 uint64 '---'---' '---'---'---' '---'
74 6 0 13 7
75
76 LEB128 variable encoding, high bit of every byte
77 indicates if there is another byte
78
79
80 int16, int32, zig zag encoded to unsigned integer:
81 int64
82 0 -> 0
83 -1 -> 1
84 1 -> 2
85 -2 -> 3
86 ...
87
88 and then encoded as unsigned integer
89
90
91 float, double 32-bit or 64-bit little endian IEEE 764
92
93
94 enum enum constants are encoded using int32
95
96 .-------.------------.
97 string, wstring | count | characters |
98 '-------'------------'
99
100 count variable encoded uint32 count of 1-byte (for
101 string) or 2-byte (for wstring) Unicode code
102 units
103
104 characters 1-byte UTF-8 code units (for string) or 2-byte
105 UTF-16LE code units (for wstring)
106
107
108 .-------.-------.-------.
109 blob, list, set, | type | count | items |
110 vector, nullable '-------'-------'-------'
111
112 .---.---.---.---.---.---.---.---.
113 type (v1) | | | | t | t | t | t | t |
114 '---'---'---'---'---'---'---'---'
115 4 0
116
117 .---.---.---.---.---.---.---.---.
118 type (v2) | c | c | c | t | t | t | t | t |
119 '---'---'---'---'---'---'---'---'
120 2 0 4 0
121
122 if count of items is < 7, 'c' are bit of (count + 1),
123 otherwise 'c' bits are 0.
124
125 count variable encoded uint32 count of items
126 omitted in v2 if 'c' bits within type byte are not 0
127
128 items each item encoded according to its type
129
130
131 .----------.------------.-------.-----.-------.
132 map | key type | value type | count | key | value |
133 '----------'------------'-------'-----'-------'
134
135 .---.---.---.---.---.---.---.---.
136 key type, | | | | t | t | t | t | t |
137 value type '---'---'---'---'---'---'---'---'
138 4 0
139
140 count variable encoded uint32 count of {key,mapped} pairs
141
142 key, mapped each item encoded according to its type
143
144*/
145
146namespace bond
147{
148
149
150template <typename BufferT>
151class CompactBinaryWriter;
152
154template <typename BufferT>
156{
157public:
158 typedef BufferT Buffer;
159 typedef DynamicParser<CompactBinaryReader&> Parser;
161
162 BOND_STATIC_CONSTEXPR uint16_t magic = COMPACT_PROTOCOL;
163 BOND_STATIC_CONSTEXPR uint16_t version = v2;
164
166 CompactBinaryReader(typename boost::call_traits<Buffer>::param_type input,
167 uint16_t version_value = default_version<CompactBinaryReader>::value)
168 : _input(input),
169 _version(version_value)
170 {
171 BOOST_ASSERT(protocol_has_multiple_versions<CompactBinaryReader>::value
172 ? _version <= CompactBinaryReader::version
173 : _version == default_version<CompactBinaryReader>::value);
174 }
175
176
177 // This identical to compiler generated ctor except for noexcept declaration.
178 // Copy ctor that is explicitly declared throw() is needed for boost::variant
179 // to use optimized code path.
181 CompactBinaryReader(const CompactBinaryReader& that) BOND_NOEXCEPT
182 : _input(that._input),
183 _version(that._version)
184 {}
185
186
188 bool operator==(const CompactBinaryReader& rhs) const
189 {
190 return _input == rhs._input;
191 }
192
193
195 typename boost::call_traits<Buffer>::const_reference
196 GetBuffer() const
197 {
198 return _input;
199 }
200
201
203 typename boost::call_traits<Buffer>::reference
205 {
206 return _input;
207 }
208
209
210 bool ReadVersion()
211 {
212 uint16_t magic_value;
213
214 _input.Read(magic_value);
215 _input.Read(_version);
216
217 return magic_value == CompactBinaryReader::magic
218 && (protocol_has_multiple_versions<CompactBinaryReader>::value
219 ? _version <= CompactBinaryReader::version
220 : _version == default_version<CompactBinaryReader>::value);
221 }
222
223
224 // ReadStructBegin
225 void ReadStructBegin(bool base = false)
226 {
227 if (!base && v2 == _version)
228 {
229 uint32_t length;
230 Read(length);
231 }
232 }
233
234 // ReadStructEnd
235 void ReadStructEnd(bool = false)
236 {}
237
238 // ReadFieldBegin
239 void ReadFieldBegin(BondDataType& type, uint16_t& id)
240 {
241 uint8_t raw;
242
243 _input.Read(raw);
244
245 type = static_cast<BondDataType>(raw & 0x1f);
246 id = static_cast<uint16_t>(raw & (0x07 << 5));
247
248 if (id == (0x07 << 5))
249 {
250 // ID is in (0xff, 0xffff] and is in the next two bytes
251 _input.Read(id);
252 }
253 else if (id == (0x06 << 5))
254 {
255 // ID is in (5, 0xff] and is in the next one byte
256 _input.Read(raw);
257 id = static_cast<uint16_t>(raw);
258 }
259 else
260 {
261 // ID is in [0, 5] and was in the byte we already read
262 id >>= 5;
263 }
264 }
265
266 // ReadFieldEnd
267 void ReadFieldEnd()
268 {}
269
270
271 // ReadContainerBegin
272 void ReadContainerBegin(uint32_t& size, BondDataType& type)
273 {
274 uint8_t raw;
275
276 _input.Read(raw);
277 type = static_cast<BondDataType>(raw & 0x1f);
278
279 if (v2 == _version && (raw & (0x07 << 5)))
280 size = (raw >> 5) - 1;
281 else
282 Read(size);
283 }
284
285
286 // container of 2-tuple (e.g. map)
287 void ReadContainerBegin(uint32_t& size, std::pair<BondDataType, BondDataType>& type)
288 {
289 uint8_t raw;
290
291 _input.Read(raw);
292 type.first = static_cast<BondDataType>(raw);
293
294 _input.Read(raw);
295 type.second = static_cast<BondDataType>(raw);
296
297 Read(size);
298 }
299
300
301 // ReadContainerEnd
302 void ReadContainerEnd()
303 {}
304
305
306 // Read for floating point
307 template <typename T>
308 typename boost::enable_if<std::is_floating_point<T> >::type
309 Read(T& value)
310 {
311 _input.Read(value);
312 }
313
314 // Read for unsigned integers
315 template <typename T>
316 typename boost::enable_if<std::is_unsigned<T> >::type
317 Read(T& value)
318 {
319 ReadVariableUnsigned(_input, value);
320 }
321
322 // Read for signed integers
323 template <typename T>
324 typename boost::enable_if<is_signed_int<T> >::type
325 Read(T& value)
326 {
327 typename std::make_unsigned<T>::type unsigned_value;
328
329 ReadVariableUnsigned(_input, unsigned_value);
330 value = DecodeZigZag(unsigned_value);
331 }
332
333
334 // Read for enums
335 template <typename T>
336 typename boost::enable_if<std::is_enum<T> >::type
337 Read(T& value)
338 {
339 BOOST_STATIC_ASSERT(sizeof(value) == sizeof(int32_t));
340 int32_t raw;
341 Read(raw);
342 std::memcpy(&value, &raw, sizeof(raw));
343 }
344
345
346 // Read for int8_t
347 void Read(int8_t& value)
348 {
349 _input.Read(value);
350 }
351
352
353 // Read for uint8_t
354 void Read(uint8_t& value)
355 {
356 _input.Read(value);
357 }
358
359
360 // Read for bool
361 void Read(bool& value)
362 {
363 _input.Read(value);
364 }
365
366
367 // Read for strings
368 template <typename T>
369 typename boost::enable_if<is_string_type<T> >::type
370 Read(T& value)
371 {
372 uint32_t length = 0;
373
374 Read(length);
375 detail::ReadStringData(_input, value, length);
376 }
377
378
379 // Read for blob
380 void Read(blob& value, uint32_t size)
381 {
382 _input.Read(value, size);
383 }
384
385
386 template <typename T>
387 void Skip()
388 {
389 SkipType<get_type_id<T>::value>();
390 }
391
392 template <typename T>
393 void Skip(const bonded<T, CompactBinaryReader&>&)
394 {
395 SkipType<bond::BT_STRUCT>();
396 }
397
398 void Skip(BondDataType type)
399 {
400 SkipType(type);
401 }
402
403protected:
404 using BT = BondDataType;
405
406 template <BT T>
407 typename boost::enable_if_c<(T == BT_BOOL || T == BT_UINT8 || T == BT_INT8)>::type
408 SkipType(uint32_t size = 1)
409 {
410 _input.Skip(detail::checked_multiply(size, sizeof(uint8_t)));
411 }
412
413 template <BT T>
414 typename boost::enable_if_c<(T == BT_UINT16 || T == BT_UINT32 || T == BT_UINT64
415 || T == BT_INT16 || T == BT_INT32 || T == BT_INT64)>::type
416 SkipType()
417 {
418 uint64_t value;
419 Read(value);
420 }
421
422 template <BT T>
423 typename boost::enable_if_c<(T == BT_FLOAT)>::type
424 SkipType(uint32_t size = 1)
425 {
426 _input.Skip(detail::checked_multiply(size, sizeof(float)));
427 }
428
429 template <BT T>
430 typename boost::enable_if_c<(T == BT_DOUBLE)>::type
431 SkipType(uint32_t size = 1)
432 {
433 _input.Skip(detail::checked_multiply(size, sizeof(double)));
434 }
435
436 template <BT T>
437 typename boost::enable_if_c<(T == BT_STRING)>::type
438 SkipType()
439 {
440 uint32_t length;
441
442 Read(length);
443 _input.Skip(length);
444 }
445
446 template <BT T>
447 typename boost::enable_if_c<(T == BT_WSTRING)>::type
448 SkipType()
449 {
450 uint32_t length;
451
452 Read(length);
453 _input.Skip(detail::checked_multiply(length, sizeof(uint16_t)));
454 }
455
456 template <BT T>
457 typename boost::enable_if_c<(T == BT_SET || T == BT_LIST)>::type
458 SkipType()
459 {
460 BondDataType element_type;
461 uint32_t size;
462
463 ReadContainerBegin(size, element_type);
464 SkipType(element_type, size);
465 ReadContainerEnd();
466 }
467
468 template <BT T>
469 typename boost::enable_if_c<(T == BT_MAP)>::type
470 SkipType()
471 {
472 std::pair<BondDataType, BondDataType> element_type;
473 uint32_t size;
474
475 ReadContainerBegin(size, element_type);
476 for (int64_t i = 0; i < size; ++i)
477 {
478 SkipType(element_type.first);
479 SkipType(element_type.second);
480 }
481 ReadContainerEnd();
482 }
483
484 void SkipStructV1()
485 {
486 BOOST_ASSERT(v1 == _version);
487
488 for (;;)
489 {
490 ReadStructBegin();
491
492 uint16_t id;
493 BondDataType field_type;
494
495 for (ReadFieldBegin(field_type, id);
496 field_type != bond::BT_STOP && field_type != bond::BT_STOP_BASE;
497 ReadFieldEnd(), ReadFieldBegin(field_type, id))
498 {
499 SkipType(field_type);
500 }
501
502 ReadStructEnd();
503
504 if (field_type == bond::BT_STOP)
505 break;
506 }
507 }
508
509 void SkipStructV2()
510 {
511 BOOST_ASSERT(v2 == _version);
512
513 uint32_t length;
514 Read(length);
515 _input.Skip(length);
516 }
517
518 template <BT T>
519 typename boost::enable_if_c<(T == BT_STRUCT)>::type
520 SkipType()
521 {
522 if (v2 == _version)
523 {
524 SkipStructV2();
525 }
526 else
527 {
528 SkipStructV1();
529 }
530 }
531
532 template <BT T>
533 typename boost::enable_if_c<(T == BT_STRUCT)>::type
534 SkipType(uint32_t size)
535 {
536 if (v2 == _version)
537 {
538 for (int64_t i = 0; i < size; ++i)
539 {
540 SkipStructV2();
541 }
542 }
543 else
544 {
545 for (int64_t i = 0; i < size; ++i)
546 {
547 SkipStructV1();
548 }
549 }
550 }
551
552 template <BT T>
553 typename boost::enable_if_c<(T == BT_UINT16 || T == BT_UINT32 || T == BT_UINT64
554 || T == BT_INT16 || T == BT_INT32 || T == BT_INT64
555 || T == BT_STRING || T == BT_WSTRING
556 || T == BT_SET || T == BT_LIST || T == BT_MAP)>::type
557 SkipType(uint32_t size)
558 {
559 for (int64_t i = 0; i < size; ++i)
560 {
561 SkipType<T>();
562 }
563 }
564
565 template <typename... Args>
566 void SkipType(BondDataType type, Args&&... args)
567 {
568 switch (type)
569 {
570 case BT_BOOL:
571 case BT_UINT8:
572 case BT_INT8:
573 SkipType<BT_BOOL>(std::forward<Args>(args)...);
574 break;
575
576 case BT_UINT64:
577 case BT_UINT32:
578 case BT_UINT16:
579 case BT_INT64:
580 case BT_INT32:
581 case BT_INT16:
582 SkipType<BT_UINT64>(std::forward<Args>(args)...);
583 break;
584
585 case BT_FLOAT:
586 SkipType<BT_FLOAT>(std::forward<Args>(args)...);
587 break;
588
589 case BT_DOUBLE:
590 SkipType<BT_DOUBLE>(std::forward<Args>(args)...);
591 break;
592
593 case BT_STRING:
594 SkipType<BT_STRING>(std::forward<Args>(args)...);
595 break;
596
597 case BT_WSTRING:
598 SkipType<BT_WSTRING>(std::forward<Args>(args)...);
599 break;
600
601 case BT_SET:
602 case BT_LIST:
603 SkipType<BT_SET>(std::forward<Args>(args)...);
604 break;
605
606 case BT_MAP:
607 SkipType<BT_MAP>(std::forward<Args>(args)...);
608 break;
609
610 case BT_STRUCT:
611 SkipType<BT_STRUCT>(std::forward<Args>(args)...);
612 break;
613
614 default:
615 break;
616 }
617 }
618
619 Buffer _input;
620 uint16_t _version;
621
622 template <typename Input, typename Output>
623 friend
624 bool is_protocol_version_same(const CompactBinaryReader<Input>&,
625 const CompactBinaryWriter<Output>&);
626};
627
628template <typename BufferT>
629BOND_CONSTEXPR_OR_CONST uint16_t CompactBinaryReader<BufferT>::magic;
630
631
632class CompactBinaryCounter
633{
634 template <typename Buffer>
635 friend class CompactBinaryWriter;
636
637private:
638 struct type : OutputCounter // Must be a new type and not an alias.
639 {};
640};
641
642
644template <typename BufferT>
646 : boost::noncopyable
647{
648 struct Pass1
649 {
650 Pass1(CompactBinaryWriter* writer)
651 : writer(writer)
652 {}
653
654 ~Pass1()
655 {
656 writer->_it = NULL;
657 }
658
659 CompactBinaryWriter* writer;
660 };
661
662 using Counter = CompactBinaryCounter::type;
663
664public:
665 typedef BufferT Buffer;
668
669
671 CompactBinaryWriter(Buffer& output,
672 uint16_t version = default_version<Reader>::value)
673 : _output(output),
674 _it(NULL),
675 _version(version)
676 {
677 BOOST_ASSERT(protocol_has_multiple_versions<Reader>::value
678 ? _version <= Reader::version
679 : _version == default_version<Reader>::value);
680 }
681
682 template<typename T>
683 CompactBinaryWriter(Counter& output,
684 const CompactBinaryWriter<T>& pass1)
685 : _output(output),
686 _version(pass1._version)
687 {}
688
689
691 typename boost::call_traits<Buffer>::reference
693 {
694 return _output;
695 }
696
697
698 bool NeedPass0()
699 {
700 return v2 == _version && !_it;
701 }
702
703
704 Pass1 WithPass0(Pass0& pass0)
705 {
706 _it = pass0._lengths.begin();
707 return this;
708 }
709
710 void WriteVersion()
711 {
712 _output.Write(Reader::magic);
713 _output.Write(_version);
714 }
715
716
717 void WriteStructBegin(const Metadata& /*metadata*/, bool base)
718 {
719 if (!base)
720 {
721 LengthBegin(_output);
722 }
723 }
724
725 void WriteStructEnd(bool base = false)
726 {
727 if (base)
728 {
729 _output.Write(static_cast<uint8_t>(BT_STOP_BASE));
730 }
731 else
732 {
733 _output.Write(static_cast<uint8_t>(BT_STOP));
734 LengthEnd(_output);
735 }
736 }
737
738 // WriteField for basic types
739 template <typename T>
740 void WriteField(uint16_t id, const bond::Metadata& /*metadata*/, const T& value)
741 {
742 WriteFieldBegin(get_type_id<T>::value, id);
743 Write(value);
744 WriteFieldEnd();
745 }
746
747 // WriteFieldBegin
748 void WriteFieldBegin(BondDataType type, uint16_t id, const ::bond::Metadata& /*metadata*/)
749 {
750 WriteFieldBegin(type, id);
751 }
752
753 void WriteFieldBegin(BondDataType type, uint16_t id)
754 {
755 BOOST_ASSERT((type & 0x1f) == type);
756
757 if (id <= 5)
758 {
759 _output.Write(static_cast<uint8_t>(type | ((id) << 5)));
760 }
761 else if (id <= 0xff)
762 {
763 _output.Write(static_cast<uint8_t>(type | (0x06 << 5)));
764 _output.Write(static_cast<uint8_t>(id));
765 }
766 else
767 {
768 _output.Write(static_cast<uint8_t>(type | (0x07 << 5)));
769 _output.Write(id);
770 }
771 }
772
773 // WriteFieldEnd
774 void WriteFieldEnd()
775 {}
776
777 // WriteContainerBegin
778 void WriteContainerBegin(uint32_t size, BondDataType type)
779 {
780 BOOST_ASSERT((type & 0x1f) == type);
781
782 if (v2 == _version && size < 7)
783 {
784 Write(static_cast<uint8_t>(type | ((size + 1) << 5)));
785 }
786 else
787 {
788 Write(static_cast<uint8_t>(type));
789 Write(size);
790 }
791 }
792
793 // container of 2-tuples (e.g. map)
794 void WriteContainerBegin(uint32_t size, std::pair<BondDataType, BondDataType> type)
795 {
796 Write(static_cast<uint8_t>(type.first));
797 Write(static_cast<uint8_t>(type.second));
798 WriteVariableUnsigned(_output, size);
799 }
800
801 // WriteContainerEnd
802 void WriteContainerEnd()
803 {}
804
805 // Write for floating point
806 template <typename T>
807 typename boost::enable_if<std::is_floating_point<T> >::type
808 Write(const T& value)
809 {
810 _output.Write(value);
811 }
812
813 // Write for unsigned integers
814 template <typename T>
815 typename boost::enable_if<std::is_unsigned<T> >::type
816 Write(const T& value)
817 {
818 WriteVariableUnsigned(_output, value);
819 }
820
821 // Write for signed integers
822 template <typename T>
823 typename boost::enable_if<is_signed_int<T> >::type
824 Write(const T& value)
825 {
826 WriteVariableUnsigned(_output, EncodeZigZag(value));
827 }
828
829 // Write for enums
830 template <typename T>
831 typename boost::enable_if<std::is_enum<T> >::type
832 Write(const T& value)
833 {
834 BOOST_STATIC_ASSERT(sizeof(value) == sizeof(int32_t));
835 Write(static_cast<int32_t>(value));
836 }
837
838 // Write for int8_t
839 void Write(const int8_t& value)
840 {
841 _output.Write(value);
842 }
843
844 // Write for uint8_t
845 void Write(const uint8_t& value)
846 {
847 _output.Write(value);
848 }
849
850 // Write for bool
851 void Write(const bool& value)
852 {
853 _output.Write(value);
854 }
855
856 // Write for strings
857 template <typename T>
858 typename boost::enable_if<is_string_type<T> >::type
859 Write(const T& value)
860 {
861 uint32_t length = string_length(value);
862
863 Write(length);
864 detail::WriteStringData(_output, value, length);
865 }
866
867 // Write for blob
868 void Write(const blob& value)
869 {
870 _output.Write(value);
871 }
872
873protected:
874 template <typename Buffer>
875 friend class CompactBinaryWriter;
876
877 void LengthBegin(Counter& counter)
878 {
879 _stack.push(_lengths.size());
880 _lengths.push(counter.GetCount());
881 }
882
883 void LengthEnd(Counter& counter)
884 {
885 uint32_t& length = _lengths[_stack.pop()];
886
887 length = counter.GetCount() - length;
888 counter.WriteVariableUnsigned(length);
889 }
890
891 template<typename T>
892 void LengthBegin(T&)
893 {
894 if (v2 == _version)
895 {
896 Write(*_it++);
897 }
898 }
899
900 template<typename T>
901 void LengthEnd(T&)
902 {}
903
904protected:
905 Buffer& _output;
906 const uint32_t* _it;
907 uint16_t _version;
908 detail::SimpleArray<uint32_t> _stack;
909 detail::SimpleArray<uint32_t> _lengths;
910
911 template <typename Input, typename Output>
912 friend
913 bool is_protocol_version_same(const CompactBinaryReader<Input>&,
914 const CompactBinaryWriter<Output>&);
915};
916
917template <typename Input> struct
918protocol_has_multiple_versions<CompactBinaryReader<Input> >
919 : enable_protocol_versions<CompactBinaryReader<Input> > {};
920
921template <typename Input, typename Output>
922inline
923bool is_protocol_version_same(const CompactBinaryReader<Input>& reader,
924 const CompactBinaryWriter<Output>& writer)
925{
926 return reader._version == writer._version;
927}
928
929} // namespace bond
Reader for Compact Binary Protocol.
Definition: compact_binary.h:156
CompactBinaryReader(typename boost::call_traits< Buffer >::param_type input, uint16_t version_value=default_version< CompactBinaryReader >::value)
Construct from input buffer/stream containing serialized data.
Definition: compact_binary.h:166
boost::call_traits< Buffer >::reference GetBuffer()
Access to underlying buffer.
Definition: compact_binary.h:204
bool operator==(const CompactBinaryReader &rhs) const
Comparison operator.
Definition: compact_binary.h:188
CompactBinaryReader(const CompactBinaryReader &that) BOND_NOEXCEPT
Copy constructor.
Definition: compact_binary.h:181
boost::call_traits< Buffer >::const_reference GetBuffer() const
Access to underlying buffer.
Definition: compact_binary.h:196
Writer for Compact Binary Protocol.
Definition: compact_binary.h:647
boost::call_traits< Buffer >::reference GetBuffer()
Access to underlying buffer.
Definition: compact_binary.h:692
CompactBinaryWriter(Buffer &output, uint16_t version=default_version< Reader >::value)
Construct from output buffer/stream.
Definition: compact_binary.h:671
namespace bond
Definition: apply.h:17