hessian2/basic_codec/object_codec.cc (195 lines of code) (raw):
#include "hessian2/basic_codec/object_codec.hpp"
namespace Hessian2 {
template <>
std::unique_ptr<NullObject> Decoder::decode() {
auto ret = reader_->read<uint8_t>();
if (!ret.first) {
return nullptr;
}
ABSL_ASSERT(ret.second == 'N');
return std::make_unique<NullObject>();
}
template <>
bool Encoder::encode(const NullObject&) {
writer_->writeByte('N');
return true;
}
/*
x00 - x1f # utf-8 string length 0-32
x20 - x2f # binary data length 0-16
x30 - x33 # utf-8 string length 0-1023
x34 - x37 # binary data length 0-1023
x38 - x3f # three-octet compact long (-x40000 to x3ffff)
x40 # reserved (expansion/escape)
x41 # 8-bit binary data non-final chunk ('A')
x42 # 8-bit binary data final chunk ('B')
x43 # object type definition ('C')
x44 # 64-bit IEEE encoded double ('D')
x45 # reserved
x46 # boolean false ('F')
x47 # reserved
x48 # untyped map ('H')
x49 # 32-bit signed integer ('I')
x4a # 64-bit UTC millisecond date
x4b # 32-bit UTC minute date
x4c # 64-bit signed long integer ('L')
x4d # map with type ('M')
x4e # null ('N')
x4f # object instance ('O')
x50 # reserved
x51 # reference to map/list/object - integer ('Q')
x52 # utf-8 string non-final chunk ('R')
x53 # utf-8 string final chunk ('S')
x54 # boolean true ('T')
x55 # variable-length list/vector ('U')
x56 # fixed-length list/vector ('V')
x57 # variable-length untyped list/vector ('W')
x58 # fixed-length untyped list/vector ('X')
x59 # long encoded as 32-bit int ('Y')
x5a # list/map terminator ('Z')
x5b # double 0.0
x5c # double 1.0
x5d # double represented as byte (-128.0 to 127.0)
x5e # double represented as short (-32768.0 to 327676.0)
x5f # double represented as float
x60 - x6f # object with direct type
x70 - x77 # fixed list with direct length
x78 - x7f # fixed untyped list with direct length
x80 - xbf # one-octet compact int (-x10 to x3f, x90 is 0)
xc0 - xcf # two-octet compact int (-x800 to x7ff)
xd0 - xd7 # three-octet compact int (-x40000 to x3ffff)
xd8 - xef # one-octet compact long (-x8 to xf, xe0 is 0)
xf0 - xff # two-octet compact long (-x800 to x7ff, xf8 is 0)
*/
template <>
std::unique_ptr<Object> Decoder::decode() {
auto ret = reader_->peek<uint8_t>();
if (!ret.first) {
return nullptr;
}
auto code = ret.second;
switch (code) {
// Null Object
case 'N': {
auto ret = decode<NullObject>();
return ret == nullptr ? nullptr : std::make_unique<NullObject>();
}
// Bool
case 0x46:
case 0x54: {
auto ret = decode<bool>();
return ret == nullptr ? nullptr : std::make_unique<BooleanObject>(*ret);
}
// Date
case 0x4a:
case 0x4b: {
auto ret = decode<std::chrono::milliseconds>();
return ret == nullptr ? nullptr : std::make_unique<DateObject>(*ret);
}
// Double
case 0x5b:
case 0x5c:
case 0x5d:
case 0x5e:
case 0x5f:
case 'D': {
auto ret = decode<double>();
return ret == nullptr ? nullptr : std::make_unique<DoubleObject>(*ret);
}
// Typed list
case 'V':
case 0x55:
case 0x70:
case 0x71:
case 0x72:
case 0x73:
case 0x74:
case 0x75:
case 0x76:
case 0x77: {
auto ret = decode<TypedListObject>();
return ret;
}
// Untyped list
case 0x57:
case 0x58:
case 0x78:
case 0x79:
case 0x7a:
case 0x7b:
case 0x7c:
case 0x7d:
case 0x7e:
case 0x7f: {
auto ret = decode<UntypedListObject>();
return ret;
}
// Typed map
case 'M': {
auto ret = decode<TypedMapObject>();
return ret;
}
case 'H': {
auto ret = decode<UntypedMapObject>();
return ret;
}
case 'C': {
auto ret = decode<Object::Definition>();
if (!ret) {
return nullptr;
}
return decode<Object>();
}
case 'O':
case 0x60:
case 0x61:
case 0x62:
case 0x63:
case 0x64:
case 0x65:
case 0x66:
case 0x67:
case 0x68:
case 0x69:
case 0x6a:
case 0x6b:
case 0x6c:
case 0x6d:
case 0x6e:
case 0x6f: {
auto ret = decode<ClassInstanceObject>();
return ret;
}
case 0x51: {
auto ret = decode<RefObject>();
return ret;
}
default:
break;
}
// String
if (code <= 0x1f || (code >= 0x30 && code <= 0x33) || code == 0x52 ||
code == 0x53) {
auto ret = decode<std::string>();
return ret == nullptr ? nullptr
: std::make_unique<StringObject>(std::move(ret));
}
// Binary
if ((code >= 0x20 && code <= 0x2f) || (code >= 0x34 && code <= 0x37) ||
code == 0x41 || code == 0x42) {
auto ret = decode<std::vector<uint8_t>>();
return ret == nullptr ? nullptr
: std::make_unique<BinaryObject>(std::move(ret));
}
// Long
if ((code >= 0x38 && code <= 0x3f) || (code >= 0xd8 && code <= 0xef) ||
code >= 0xf0 || code == 0x59 || code == 0x4c) {
auto ret = decode<int64_t>();
return ret == nullptr ? nullptr : std::make_unique<LongObject>(*ret);
}
// int
if (code == 0x49 || (code >= 0x80 && code <= 0xbf) ||
(code >= 0xc0 && code <= 0xcf) || (code >= 0xd0 && code <= 0xd7)) {
auto ret = decode<int32_t>();
return ret == nullptr ? nullptr : std::make_unique<IntegerObject>(*ret);
}
return nullptr;
}
template <>
bool Encoder::encode(const Object& value) {
switch (value.type()) {
case Object::Type::Binary: {
return encode<std::vector<uint8_t>>(value.toBinary().value().get());
}
case Object::Type::Boolean: {
return encode<bool>(value.toBoolean().value().get());
}
case Object::Type::Date: {
return encode<std::chrono::milliseconds>(value.toDate().value().get());
}
case Object::Type::Double: {
return encode<double>(value.toDouble().value().get());
}
case Object::Type::Integer: {
return encode<int32_t>(value.toInteger().value().get());
}
case Object::Type::Long: {
return encode<int64_t>(value.toLong().value().get());
}
case Object::Type::Null: {
NullObject o;
return encode<NullObject>(o);
}
case Object::Type::Ref: {
return encode<RefObject>(*dynamic_cast<const RefObject*>(&value));
}
case Object::Type::String: {
return encode<std::string>(value.toString().value().get());
}
case Object::Type::TypedList: {
return encode<TypedListObject>(
*dynamic_cast<const TypedListObject*>(&value));
}
case Object::Type::UntypedList: {
return encode<UntypedListObject>(
*dynamic_cast<const UntypedListObject*>(&value));
}
case Object::Type::TypedMap: {
return encode<TypedMapObject>(
*dynamic_cast<const TypedMapObject*>(&value));
}
case Object::Type::UntypedMap: {
return encode<UntypedMapObject>(
*dynamic_cast<const UntypedMapObject*>(&value));
}
case Object::Type::Class: {
return encode<ClassInstanceObject>(
*dynamic_cast<const ClassInstanceObject*>(&value));
}
default:
return false;
}
}
} // namespace Hessian2