6#include <bond/core/config.h>
8#include "detail/simple_array.h"
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>
16#include <boost/call_traits.hpp>
17#include <boost/noncopyable.hpp>
18#include <boost/static_assert.hpp>
150template <
typename BufferT>
151class CompactBinaryWriter;
154template <
typename BufferT>
158 typedef BufferT Buffer;
159 typedef DynamicParser<CompactBinaryReader&> Parser;
162 BOND_STATIC_CONSTEXPR uint16_t magic = COMPACT_PROTOCOL;
163 BOND_STATIC_CONSTEXPR uint16_t version = v2;
167 uint16_t version_value = default_version<CompactBinaryReader>::value)
169 _version(version_value)
171 BOOST_ASSERT(protocol_has_multiple_versions<CompactBinaryReader>::value
172 ? _version <= CompactBinaryReader::version
173 : _version == default_version<CompactBinaryReader>::value);
182 : _input(that._input),
183 _version(that._version)
190 return _input == rhs._input;
195 typename boost::call_traits<Buffer>::const_reference
203 typename boost::call_traits<Buffer>::reference
212 uint16_t magic_value;
214 _input.Read(magic_value);
215 _input.Read(_version);
217 return magic_value == CompactBinaryReader::magic
218 && (protocol_has_multiple_versions<CompactBinaryReader>::value
219 ? _version <= CompactBinaryReader::version
220 : _version == default_version<CompactBinaryReader>::value);
225 void ReadStructBegin(
bool base =
false)
227 if (!base && v2 == _version)
235 void ReadStructEnd(
bool =
false)
239 void ReadFieldBegin(BondDataType& type, uint16_t&
id)
245 type =
static_cast<BondDataType
>(raw & 0x1f);
246 id =
static_cast<uint16_t
>(raw & (0x07 << 5));
248 if (
id == (0x07 << 5))
253 else if (
id == (0x06 << 5))
257 id =
static_cast<uint16_t
>(raw);
272 void ReadContainerBegin(uint32_t& size, BondDataType& type)
277 type =
static_cast<BondDataType
>(raw & 0x1f);
279 if (v2 == _version && (raw & (0x07 << 5)))
280 size = (raw >> 5) - 1;
287 void ReadContainerBegin(uint32_t& size, std::pair<BondDataType, BondDataType>& type)
292 type.first =
static_cast<BondDataType
>(raw);
295 type.second =
static_cast<BondDataType
>(raw);
302 void ReadContainerEnd()
307 template <
typename T>
308 typename boost::enable_if<std::is_floating_point<T> >::type
315 template <
typename T>
316 typename boost::enable_if<std::is_unsigned<T> >::type
319 ReadVariableUnsigned(_input, value);
323 template <
typename T>
324 typename boost::enable_if<is_signed_int<T> >::type
327 typename std::make_unsigned<T>::type unsigned_value;
329 ReadVariableUnsigned(_input, unsigned_value);
330 value = DecodeZigZag(unsigned_value);
335 template <
typename T>
336 typename boost::enable_if<std::is_enum<T> >::type
339 BOOST_STATIC_ASSERT(
sizeof(value) ==
sizeof(int32_t));
342 std::memcpy(&value, &raw,
sizeof(raw));
347 void Read(int8_t& value)
354 void Read(uint8_t& value)
361 void Read(
bool& value)
368 template <
typename T>
369 typename boost::enable_if<is_string_type<T> >::type
375 detail::ReadStringData(_input, value, length);
380 void Read(blob& value, uint32_t size)
382 _input.Read(value, size);
386 template <
typename T>
389 SkipType<get_type_id<T>::value>();
392 template <
typename T>
393 void Skip(
const bonded<T, CompactBinaryReader&>&)
395 SkipType<bond::BT_STRUCT>();
398 void Skip(BondDataType type)
404 using BT = BondDataType;
407 typename boost::enable_if_c<(T == BT_BOOL || T == BT_UINT8 || T == BT_INT8)>::type
408 SkipType(uint32_t size = 1)
410 _input.Skip(detail::checked_multiply(size,
sizeof(uint8_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
423 typename boost::enable_if_c<(T == BT_FLOAT)>::type
424 SkipType(uint32_t size = 1)
426 _input.Skip(detail::checked_multiply(size,
sizeof(
float)));
430 typename boost::enable_if_c<(T == BT_DOUBLE)>::type
431 SkipType(uint32_t size = 1)
433 _input.Skip(detail::checked_multiply(size,
sizeof(
double)));
437 typename boost::enable_if_c<(T == BT_STRING)>::type
447 typename boost::enable_if_c<(T == BT_WSTRING)>::type
453 _input.Skip(detail::checked_multiply(length,
sizeof(uint16_t)));
457 typename boost::enable_if_c<(T == BT_SET || T == BT_LIST)>::type
460 BondDataType element_type;
463 ReadContainerBegin(size, element_type);
464 SkipType(element_type, size);
469 typename boost::enable_if_c<(T == BT_MAP)>::type
472 std::pair<BondDataType, BondDataType> element_type;
475 ReadContainerBegin(size, element_type);
476 for (int64_t i = 0; i < size; ++i)
478 SkipType(element_type.first);
479 SkipType(element_type.second);
486 BOOST_ASSERT(v1 == _version);
493 BondDataType field_type;
495 for (ReadFieldBegin(field_type,
id);
496 field_type != bond::BT_STOP && field_type != bond::BT_STOP_BASE;
497 ReadFieldEnd(), ReadFieldBegin(field_type,
id))
499 SkipType(field_type);
504 if (field_type == bond::BT_STOP)
511 BOOST_ASSERT(v2 == _version);
519 typename boost::enable_if_c<(T == BT_STRUCT)>::type
533 typename boost::enable_if_c<(T == BT_STRUCT)>::type
534 SkipType(uint32_t size)
538 for (int64_t i = 0; i < size; ++i)
545 for (int64_t i = 0; i < size; ++i)
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)
559 for (int64_t i = 0; i < size; ++i)
565 template <
typename... Args>
566 void SkipType(BondDataType type, Args&&... args)
573 SkipType<BT_BOOL>(std::forward<Args>(args)...);
582 SkipType<BT_UINT64>(std::forward<Args>(args)...);
586 SkipType<BT_FLOAT>(std::forward<Args>(args)...);
590 SkipType<BT_DOUBLE>(std::forward<Args>(args)...);
594 SkipType<BT_STRING>(std::forward<Args>(args)...);
598 SkipType<BT_WSTRING>(std::forward<Args>(args)...);
603 SkipType<BT_SET>(std::forward<Args>(args)...);
607 SkipType<BT_MAP>(std::forward<Args>(args)...);
611 SkipType<BT_STRUCT>(std::forward<Args>(args)...);
622 template <
typename Input,
typename Output>
624 bool is_protocol_version_same(
const CompactBinaryReader<Input>&,
625 const CompactBinaryWriter<Output>&);
628template <
typename BufferT>
629BOND_CONSTEXPR_OR_CONST uint16_t CompactBinaryReader<BufferT>::magic;
632class CompactBinaryCounter
634 template <
typename Buffer>
635 friend class CompactBinaryWriter;
638 struct type : OutputCounter
644template <
typename BufferT>
662 using Counter = CompactBinaryCounter::type;
665 typedef BufferT Buffer;
672 uint16_t version = default_version<Reader>::value)
677 BOOST_ASSERT(protocol_has_multiple_versions<Reader>::value
678 ? _version <= Reader::version
679 : _version == default_version<Reader>::value);
686 _version(pass1._version)
691 typename boost::call_traits<Buffer>::reference
700 return v2 == _version && !_it;
704 Pass1 WithPass0(Pass0& pass0)
706 _it = pass0._lengths.begin();
712 _output.Write(Reader::magic);
713 _output.Write(_version);
717 void WriteStructBegin(
const Metadata& ,
bool base)
721 LengthBegin(_output);
725 void WriteStructEnd(
bool base =
false)
729 _output.Write(
static_cast<uint8_t
>(BT_STOP_BASE));
733 _output.Write(
static_cast<uint8_t
>(BT_STOP));
739 template <
typename T>
740 void WriteField(uint16_t
id,
const bond::Metadata& ,
const T& value)
742 WriteFieldBegin(get_type_id<T>::value,
id);
748 void WriteFieldBegin(BondDataType type, uint16_t
id, const ::bond::Metadata& )
750 WriteFieldBegin(type,
id);
753 void WriteFieldBegin(BondDataType type, uint16_t
id)
755 BOOST_ASSERT((type & 0x1f) == type);
759 _output.Write(
static_cast<uint8_t
>(type | ((
id) << 5)));
763 _output.Write(
static_cast<uint8_t
>(type | (0x06 << 5)));
764 _output.Write(
static_cast<uint8_t
>(
id));
768 _output.Write(
static_cast<uint8_t
>(type | (0x07 << 5)));
778 void WriteContainerBegin(uint32_t size, BondDataType type)
780 BOOST_ASSERT((type & 0x1f) == type);
782 if (v2 == _version && size < 7)
784 Write(
static_cast<uint8_t
>(type | ((size + 1) << 5)));
788 Write(
static_cast<uint8_t
>(type));
794 void WriteContainerBegin(uint32_t size, std::pair<BondDataType, BondDataType> type)
796 Write(
static_cast<uint8_t
>(type.first));
797 Write(
static_cast<uint8_t
>(type.second));
798 WriteVariableUnsigned(_output, size);
802 void WriteContainerEnd()
806 template <
typename T>
807 typename boost::enable_if<std::is_floating_point<T> >::type
808 Write(
const T& value)
810 _output.Write(value);
814 template <
typename T>
815 typename boost::enable_if<std::is_unsigned<T> >::type
816 Write(
const T& value)
818 WriteVariableUnsigned(_output, value);
822 template <
typename T>
823 typename boost::enable_if<is_signed_int<T> >::type
824 Write(
const T& value)
826 WriteVariableUnsigned(_output, EncodeZigZag(value));
830 template <
typename T>
831 typename boost::enable_if<std::is_enum<T> >::type
832 Write(
const T& value)
834 BOOST_STATIC_ASSERT(
sizeof(value) ==
sizeof(int32_t));
835 Write(
static_cast<int32_t
>(value));
839 void Write(
const int8_t& value)
841 _output.Write(value);
845 void Write(
const uint8_t& value)
847 _output.Write(value);
851 void Write(
const bool& value)
853 _output.Write(value);
857 template <
typename T>
858 typename boost::enable_if<is_string_type<T> >::type
859 Write(
const T& value)
861 uint32_t length = string_length(value);
864 detail::WriteStringData(_output, value, length);
868 void Write(
const blob& value)
870 _output.Write(value);
874 template <
typename Buffer>
875 friend class CompactBinaryWriter;
877 void LengthBegin(Counter& counter)
879 _stack.push(_lengths.size());
880 _lengths.push(counter.GetCount());
883 void LengthEnd(Counter& counter)
885 uint32_t& length = _lengths[_stack.pop()];
887 length = counter.GetCount() - length;
888 counter.WriteVariableUnsigned(length);
908 detail::SimpleArray<uint32_t> _stack;
909 detail::SimpleArray<uint32_t> _lengths;
911 template <
typename Input,
typename Output>
913 bool is_protocol_version_same(
const CompactBinaryReader<Input>&,
914 const CompactBinaryWriter<Output>&);
917template <
typename Input>
struct
918protocol_has_multiple_versions<CompactBinaryReader<Input> >
919 : enable_protocol_versions<CompactBinaryReader<Input> > {};
921template <
typename Input,
typename Output>
923bool is_protocol_version_same(
const CompactBinaryReader<Input>& reader,
924 const CompactBinaryWriter<Output>& writer)
926 return reader._version == writer._version;
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