hessian2/codec.hpp (154 lines of code) (raw):

#pragma once #include <chrono> #include <cstddef> #include <memory> #include <string> #include <utility> #include <vector> #include "absl/strings/str_cat.h" #include "absl/strings/str_format.h" #include "absl/strings/string_view.h" #include "hessian2/object.hpp" #include "hessian2/string_reader.hpp" #include "hessian2/string_writer.hpp" namespace Hessian2 { class Decoder; class Encoder; namespace detail { struct FromHessianFn { template <typename CustomType> void operator()(CustomType& j, Decoder& c) const noexcept { return fromHessian(j, c); } }; struct ToHessianFn { template <typename CustomType> bool operator()(const CustomType& j, Encoder& e) const noexcept { return toHessian(j, e); } }; } // namespace detail /// namespace to hold default `fromHessian`/`toHessian` function /// to see why this is required: /// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4381.html namespace { // Global function objects. constexpr const auto& FromHessian = static_const<detail::FromHessianFn>::value; constexpr const auto& ToHessian = static_const<detail::ToHessianFn>::value; } // namespace class Decoder { public: // Error codes during decode. enum class ErrorCode { NO_DECODE_ERROR, NOT_ENOUGH_BUFFER, UNEXPECTED_TYPE, }; // Use default StringReader implement Decoder(absl::string_view input) : reader_(std::make_unique<StringReader>(input)) {} Decoder(ReaderPtr&& read) : reader_(std::move(read)) {} template <typename T> std::unique_ptr<T> decode() { auto t = std::make_unique<T>(); Hessian2::FromHessian(*t, *this); return t; } uint64_t offset() { return reader_->offset(); } uint16_t getTypeRefSize() { return types_ref_.size(); } uint16_t getDefRefSize() { return def_ref_.size(); } ErrorCode errorCode() const { return error_code_; } std::string getErrorMessage() const { if (!error_pos_) { return absl::StrFormat("pos: %d, %s", error_pos_, errorCodeToString()); } return errorCodeToString(); } int errorPos() const { return error_pos_; } const std::vector<Object::RawDefinitionSharedPtr>& getDefRefVec() { return def_ref_; } protected: ReaderPtr reader_; std::vector<std::string> types_ref_; std::vector<Object::RawDefinitionSharedPtr> def_ref_; // decode's objects need to have a lifetime longer than value_ref_ std::vector<Object*> values_ref_; ErrorCode error_code_{ErrorCode::NO_DECODE_ERROR}; int error_pos_{0}; private: std::string errorCodeToString() const { switch (error_code_) { case ErrorCode::NO_DECODE_ERROR: return std::string(); case ErrorCode::NOT_ENOUGH_BUFFER: return std::string("There is not enough buffer"); case ErrorCode::UNEXPECTED_TYPE: return std::string("Unexpected type"); } return std::string(); } }; class Encoder { public: // Error codes during encode. enum class ErrorCode { NO_ENCODE_ERROR, }; // Use default StringWriter implement Encoder(std::string& output) : writer_(std::make_unique<StringWriter>(output)) {} Encoder(WriterPtr&& writer) : writer_(std::move(writer)) {} template <typename T> bool encode(const T& o) { return Hessian2::ToHessian(o, *this); } // References are not currently supported void encodeVarListBegin(const std::string& type); void encodeVarListEnd(); void encodeFixedListBegin(const std::string& type, uint32_t len); void encodeFixedListEnd(); void encodeMapBegin(const std::string& type); void encodeMapEnd(); void encodeClassInstanceBegin(const Object::RawDefinition&); void encodeClassInstanceEnd(); uint16_t getTypeRefSize() { return types_ref_.size(); } uint16_t getDefRefSize() { return def_ref_.size(); } uint16_t getValueRefSize() { return values_ref_.size(); } int16_t getTypeRef(const std::string& search) { auto find = types_ref_.find(search); if (find != types_ref_.end()) { return find->second; } return -1; } int16_t getDefRef(const Object::RawDefinition& def) { for (uint16_t i = 0; i < def_ref_.size(); i++) { if (*def_ref_[i] == def) { return i; } } return -1; } int16_t getValueRef(const Object* o) { auto find = values_ref_.find(o); if (find != values_ref_.end()) { return find->second; } return -1; } ErrorCode errorCode() const { return error_code_; } std::string getErrorMessage() const { return errorCodeToString(); } const std::vector<Object::RawDefinitionSharedPtr>& getDefRefVec() { return def_ref_; } private: std::string errorCodeToString() const { switch (error_code_) { case ErrorCode::NO_ENCODE_ERROR: return std::string(); } return std::string(); } protected: WriterPtr writer_; std::unordered_map<std::string, uint16_t> types_ref_; std::vector<Object::RawDefinitionSharedPtr> def_ref_; // Encode's objects need to have a lifetime longer than values_ref_ // Only two pointers to the same object are considered references std::unordered_map<const Object*, uint16_t> values_ref_; ErrorCode error_code_{ErrorCode::NO_ENCODE_ERROR}; }; // fwd decl template <> std::unique_ptr<Object> Decoder::decode(); template <> bool Encoder::encode(const Object&); } // namespace Hessian2