hessian2/basic_codec/map_codec.cc (104 lines of code) (raw):
#include "hessian2/basic_codec/map_codec.hpp"
namespace Hessian2 {
//# map/object
// ::= 'M' type (value value)* 'Z' # key, value map pairs
template <>
std::unique_ptr<TypedMapObject> Decoder::decode() {
std::string type;
Object::TypedMap obj_map;
auto result = std::make_unique<TypedMapObject>();
values_ref_.push_back(result.get());
auto ret = reader_->read<uint8_t>();
ABSL_ASSERT(ret.first);
auto code = ret.second;
ABSL_ASSERT(code == 'M');
// Read Type
auto type_str = decode<Object::TypeRef>();
if (!type_str) {
return nullptr;
}
obj_map.type_name_ = std::move(type_str->type_);
ret = reader_->peek<uint8_t>();
if (!ret.first) {
return nullptr;
}
while (ret.second != 'Z') {
auto key = decode<Object>();
if (!key) {
return nullptr;
}
auto value = decode<Object>();
if (!value) {
return nullptr;
}
obj_map.field_name_and_value_.emplace(std::move(key), std::move(value));
ret = reader_->peek<uint8_t>();
if (!ret.first) {
return nullptr;
}
}
// Skip last 'Z'
reader_->read<uint8_t>();
result->setTypedMap(std::move(obj_map));
return result;
}
// ::= 'H' (value value)* 'Z' # untyped key, value
template <>
std::unique_ptr<UntypedMapObject> Decoder::decode() {
std::string type;
Object::UntypedMap obj_map;
auto result = std::make_unique<UntypedMapObject>();
values_ref_.push_back(result.get());
auto ret = reader_->read<uint8_t>();
ABSL_ASSERT(ret.first);
auto code = ret.second;
ABSL_ASSERT(code == 'H');
ret = reader_->peek<uint8_t>();
if (!ret.first) {
return nullptr;
}
while (ret.second != 'Z') {
auto key = decode<Object>();
if (!key) {
return nullptr;
}
auto value = decode<Object>();
if (!value) {
return nullptr;
}
obj_map.emplace(std::move(key), std::move(value));
ret = reader_->peek<uint8_t>();
if (!ret.first) {
return nullptr;
}
}
// Skip last 'Z'
reader_->read<uint8_t>();
result->setUntypedMap(std::move(obj_map));
return result;
}
template <>
bool Encoder::encode(const TypedMapObject& value) {
values_ref_.emplace(&value, values_ref_.size());
auto typed_map = value.toTypedMap();
ABSL_ASSERT(typed_map.has_value());
auto& typed_map_value = typed_map.value().get();
writer_->writeByte('M');
Object::TypeRef type_ref(typed_map_value.type_name_);
encode<Object::TypeRef>(type_ref);
for (const auto& elem : typed_map_value.field_name_and_value_) {
encode<Object>(*elem.first);
encode<Object>(*elem.second);
}
writer_->writeByte('Z');
return true;
}
template <>
bool Encoder::encode(const UntypedMapObject& value) {
values_ref_.emplace(&value, values_ref_.size());
auto untyped_map = value.toUntypedMap();
ABSL_ASSERT(untyped_map.has_value());
auto& untyped_map_value = untyped_map.value().get();
writer_->writeByte('H');
for (const auto& elem : untyped_map_value) {
encode<Object>(*elem.first);
encode<Object>(*elem.second);
}
writer_->writeByte('Z');
return true;
}
} // namespace Hessian2