/* * Copyright (c) 2020, Alibaba Group Holding Limited * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * serialization.h is for packing all of integral types data into buffer stream. */ #ifndef XENGINE_INCLUDE_SERIALIZATION_H_ #define XENGINE_INCLUDE_SERIALIZATION_H_ #include #include #include #include #include //#include "autovector.h" #include "template_util.h" #include "xengine/slice.h" #include "xengine/status.h" #ifndef UNUSED #define UNUSED(x) ((void)x) #endif #define ASSERT_BUFFER(length) \ assert(nullptr != buffer && bufsiz - pos >= length) #define ASSERT_FIXED_LENGTH_BUFFER(type) \ assert(nullptr != buffer && bufsiz - pos >= (int64_t)sizeof(type)) #define DECLARE_SERIALIZATION() \ public: \ int serialize(char *buffer, int64_t bufsiz, int64_t &pos) const; \ int deserialize(const char *buffer, int64_t bufsiz, int64_t &pos); \ int64_t get_serialize_size() const; #define DEFINE_SERIALIZATION(clz, ...) \ int clz::serialize(char *buffer, int64_t bufsiz, int64_t &pos) const { \ return util::serialize(buffer, bufsiz, pos, __VA_ARGS__); \ } \ int clz::deserialize(const char *buffer, int64_t bufsiz, int64_t &pos) { \ return util::deserialize(buffer, bufsiz, pos, __VA_ARGS__); \ } \ int64_t clz::get_serialize_size() const { \ return util::get_serialize_size(__VA_ARGS__); \ } /*-----------------macros for compactiple serialize and deserialize---------------------*/ //macros for declare compactiple serialize and deserialize #define DECLARE_COMPACTIPLE_SERIALIZATION(VERSION) \ public: \ DECLARE_COMPACTIPLE_SERIALIZATION_; \ private: \ const static int64_t VERSION_ = VERSION #define DECLARE_COMPACTIPLE_SERIALIZATION_ \ int serialize(char *buf, int64_t buf_len, int64_t &pos) const; \ int serialize_(char *buf, int64_t buf_len, int64_t &pos) const; \ int deserialize(const char *buf, int64_t buf_len, int64_t &pos); \ int deserialize_(const char *buf, int64_t buf_len, int64_t &pos); \ int64_t get_serialize_size() const; \ int64_t get_serialize_size_() const //macros for serialize and deserialize header #define SERIALIZE_HEADER(VERSION, LEN) \ if (common::Status::kOk == ret) { \ ret = util::serialize(buf, buf_len, pos, VERSION); \ } \ if (common::Status::kOk == ret) { \ ret = util::serialize(buf, buf_len, pos, LEN); \ } #define CHECK_HEADER(VERSION, LEN) \ if (common::Status::kOk == ret) { \ if (VERSION_ != VERSION) { \ ret = common::Status::kNotSupported; \ } else if (LEN < 0) { \ ret = common::Status::kCorruption; \ } else if (buf_len < (pos + LEN)) { \ ret = common::Status::kCorruption; \ } \ } #define DESERIALIZE_HEADER(VERSION, LEN) \ if (common::Status::kOk == ret) { \ ret = util::deserialize(buf, buf_len, pos, VERSION); \ } \ if (common::Status::kOk == ret) { \ ret = util::deserialize(buf, buf_len, pos, LEN); \ } #define HEADER_SERIALIZE_SIZE(VERSION, LEN) \ LEN += util::get_serialize_size(LEN); \ LEN += util::get_serialize_size(VERSION) #define DEFINE_COMPACTIPLE_SERIALIZATION(CLZ, ...) \ int CLZ::serialize(char *buf, int64_t buf_len, int64_t &pos) const \ { \ int ret = common::Status::kOk; \ int64_t serialize_size = get_serialize_size_(); \ SERIALIZE_HEADER(VERSION_, serialize_size); \ if (common::Status::kOk == ret) { \ ret = serialize_(buf, buf_len, pos); \ } \ return ret; \ } \ int CLZ::serialize_(char *buf, int64_t buf_len, int64_t &pos) const \ { \ return util::serialize_x(buf, buf_len, pos, ##__VA_ARGS__); \ } \ int CLZ::deserialize(const char *buf, int64_t buf_len, int64_t &pos) \ { \ int ret = common::Status::kOk; \ int64_t version = 0; \ int64_t deserialize_size = 0; \ int64_t orig_pos = 0; \ DESERIALIZE_HEADER(version, deserialize_size);\ CHECK_HEADER(version, deserialize_size); \ if (common::Status::kOk == ret) { \ orig_pos = pos; \ pos = 0; \ ret = deserialize_(buf + orig_pos, deserialize_size, pos); \ pos = orig_pos + deserialize_size; \ } \ return ret; \ } \ int CLZ::deserialize_(const char *buf, int64_t buf_len, int64_t &pos) \ { \ return util::deserialize_x(buf, buf_len, pos, ##__VA_ARGS__); \ } \ int64_t CLZ::get_serialize_size() const \ { \ int64_t serialize_size = get_serialize_size_(); \ HEADER_SERIALIZE_SIZE(VERSION_, serialize_size); \ return serialize_size; \ } \ int64_t CLZ::get_serialize_size_() const \ { \ return util::get_serialize_size_x(__VA_ARGS__); \ } // macros for declare pure virtual serialize and deserialize #define DECLARE_PURE_VIRTUAL_SERIALIZATION() \ virtual int serialize(char *buf, int64_t buf_len, int64_t &pos) const = 0; \ virtual int deserialize(const char *buf, int64_t buf_len, int64_t &pos) = 0; \ virtual int64_t get_serialize_size() const = 0 namespace xengine { namespace common { class Status; class Slice; } // namespace common namespace util { const uint64_t XE_MAX_V1B = (__UINT64_C(1) << 7) - 1; const uint64_t XE_MAX_V2B = (__UINT64_C(1) << 14) - 1; const uint64_t XE_MAX_V3B = (__UINT64_C(1) << 21) - 1; const uint64_t XE_MAX_V4B = (__UINT64_C(1) << 28) - 1; const uint64_t XE_MAX_V5B = (__UINT64_C(1) << 35) - 1; const uint64_t XE_MAX_V6B = (__UINT64_C(1) << 42) - 1; const uint64_t XE_MAX_V7B = (__UINT64_C(1) << 49) - 1; const uint64_t XE_MAX_V8B = (__UINT64_C(1) << 56) - 1; const uint64_t XE_MAX_V9B = (__UINT64_C(1) << 63) - 1; const uint64_t XE_MAX_1B = (__UINT64_C(1) << 8) - 1; const uint64_t XE_MAX_2B = (__UINT64_C(1) << 16) - 1; const uint64_t XE_MAX_3B = (__UINT64_C(1) << 24) - 1; const uint64_t XE_MAX_4B = (__UINT64_C(1) << 32) - 1; const uint64_t XE_MAX_5B = (__UINT64_C(1) << 40) - 1; const uint64_t XE_MAX_6B = (__UINT64_C(1) << 48) - 1; const uint64_t XE_MAX_7B = (__UINT64_C(1) << 56) - 1; const uint64_t XE_MAX_8B = UINT64_MAX; const uint64_t XE_MAX_INT_1B = (__UINT64_C(23)); const uint64_t XE_MAX_INT_2B = (__UINT64_C(1) << 8) - 1; const uint64_t XE_MAX_INT_3B = (__UINT64_C(1) << 16) - 1; const uint64_t XE_MAX_INT_4B = (__UINT64_C(1) << 24) - 1; const uint64_t XE_MAX_INT_5B = (__UINT64_C(1) << 32) - 1; const uint64_t XE_MAX_INT_7B = (__UINT64_C(1) << 48) - 1; const uint64_t XE_MAX_INT_9B = UINT64_MAX; const int64_t XE_MAX_1B_STR_LEN = (__INT64_C(55)); const int64_t XE_MAX_2B_STR_LEN = (__INT64_C(1) << 8) - 1; const int64_t XE_MAX_3B_STR_LEN = (__INT64_C(1) << 16) - 1; const int64_t XE_MAX_4B_STR_LEN = (__INT64_C(1) << 24) - 1; const int64_t XE_MAX_5B_STR_LEN = (__INT64_C(1) << 32) - 1; const int8_t XE_INT_TYPE_BIT_POS = 7; const int8_t XE_INT_OPERATION_BIT_POS = 6; const int8_t XE_INT_SIGN_BIT_POS = 5; const int8_t XE_DATETIME_OPERATION_BIT = 3; const int8_t XE_DATETIME_SIGN_BIT = 2; const int8_t XE_FLOAT_OPERATION_BIT_POS = 0; const int8_t XE_DECIMAL_OPERATION_BIT_POS = 7; const int8_t XE_INT_VALUE_MASK = 0x1f; const int8_t XE_VARCHAR_LEN_MASK = 0x3f; const int8_t XE_DATETIME_LEN_MASK = 0x3; const int8_t XE_VARCHAR_TYPE = static_cast((0x1 << 7)); const int8_t XE_SEQ_TYPE = static_cast(0xc0); const int8_t XE_DATETIME_TYPE = static_cast(0xd0); const int8_t XE_PRECISE_DATETIME_TYPE = static_cast(0xe0); const int8_t XE_MODIFYTIME_TYPE = static_cast(0xf0); const int8_t XE_CREATETIME_TYPE = static_cast(0xf4); const int8_t XE_FLOAT_TYPE = static_cast(0xf8); const int8_t XE_DOUBLE_TYPE = static_cast(0xfa); const int8_t XE_nullptr_TYPE = static_cast(0xfc); const int8_t XE_BOOL_TYPE = static_cast(0xfd); const int8_t XE_EXTEND_TYPE = static_cast(0xfe); const int8_t XE_DECIMAL_TYPE = static_cast(0xff); const int8_t XE_NUMBER_TYPE = XE_DECIMAL_TYPE; // 2014number /** * @brief Encode a byte into given buffer. * * @param buffer address of destination buffer * @param value the byte * */ inline int encode_fixed_int8(char *buffer, const int64_t bufsiz, int64_t &pos, int8_t value) { ASSERT_FIXED_LENGTH_BUFFER(int8_t); *(buffer + pos++) = value; return common::Status::kOk; } inline int decode_fixed_int8(const char *buffer, const int64_t bufsiz, int64_t &pos, int8_t &value) { ASSERT_FIXED_LENGTH_BUFFER(int8_t); value = *(buffer + pos++); return common::Status::kOk; } /** * @brief Enocde a 16-bit integer in big-endian order * * @param buffer address of destination buffer * @param value value to encode */ inline int encode_fixed_int16(char *buffer, const int64_t bufsiz, int64_t &pos, int16_t value) { ASSERT_FIXED_LENGTH_BUFFER(int16_t); *(buffer + pos++) = static_cast((((value) >> 8)) & 0xff); *(buffer + pos++) = static_cast((value)&0xff); return common::Status::kOk; } inline int decode_fixed_int16(const char *buffer, const int64_t bufsiz, int64_t &pos, int16_t &value) { ASSERT_FIXED_LENGTH_BUFFER(int16_t); value = static_cast(((*(buffer + pos++)) & 0xff) << 8); value = static_cast(value | (*(buffer + pos++) & 0xff)); return common::Status::kOk; } inline int encode_fixed_int32(char *buffer, const int64_t bufsiz, int64_t &pos, int32_t value) { ASSERT_FIXED_LENGTH_BUFFER(int32_t); *(buffer + pos++) = static_cast(((value) >> 24) & 0xff); *(buffer + pos++) = static_cast(((value) >> 16) & 0xff); *(buffer + pos++) = static_cast(((value) >> 8) & 0xff); *(buffer + pos++) = static_cast((value)&0xff); return common::Status::kOk; } inline int decode_fixed_int32(const char *buffer, const int64_t bufsiz, int64_t &pos, int32_t &value) { ASSERT_FIXED_LENGTH_BUFFER(int32_t); value = ((static_cast(*(buffer + pos++))) & 0xff) << 24; value |= ((static_cast(*(buffer + pos++))) & 0xff) << 16; value |= ((static_cast(*(buffer + pos++))) & 0xff) << 8; value |= ((static_cast(*(buffer + pos++))) & 0xff); return common::Status::kOk; } inline int encode_fixed_int64(char *buffer, const int64_t bufsiz, int64_t &pos, int64_t value) { ASSERT_FIXED_LENGTH_BUFFER(int64_t); *(buffer + pos++) = static_cast(((value) >> 56) & 0xff); *(buffer + pos++) = static_cast(((value) >> 48) & 0xff); *(buffer + pos++) = static_cast(((value) >> 40) & 0xff); *(buffer + pos++) = static_cast(((value) >> 32) & 0xff); *(buffer + pos++) = static_cast(((value) >> 24) & 0xff); *(buffer + pos++) = static_cast(((value) >> 16) & 0xff); *(buffer + pos++) = static_cast(((value) >> 8) & 0xff); *(buffer + pos++) = static_cast((value)&0xff); return common::Status::kOk; } inline int decode_fixed_int64(const char *buffer, const int64_t bufsiz, int64_t &pos, int64_t &value) { ASSERT_FIXED_LENGTH_BUFFER(int64_t); value = ((static_cast((*(buffer + pos++))) & 0xff)) << 56; value |= ((static_cast((*(buffer + pos++))) & 0xff)) << 48; value |= ((static_cast((*(buffer + pos++))) & 0xff)) << 40; value |= ((static_cast((*(buffer + pos++))) & 0xff)) << 32; value |= ((static_cast((*(buffer + pos++))) & 0xff)) << 24; value |= ((static_cast((*(buffer + pos++))) & 0xff)) << 16; value |= ((static_cast((*(buffer + pos++))) & 0xff)) << 8; value |= ((static_cast((*(buffer + pos++))) & 0xff)); return common::Status::kOk; } inline int encode_boolean(char *buffer, const int64_t bufsiz, int64_t &pos, bool value) { ASSERT_FIXED_LENGTH_BUFFER(int8_t); *(buffer + pos++) = (value) ? 1 : 0; return common::Status::kOk; } inline int decode_boolean(const char *buffer, const int64_t bufsiz, int64_t &pos, bool &value) { ASSERT_FIXED_LENGTH_BUFFER(char); int8_t v = 0; int ret = 0; if ((ret = decode_fixed_int8(buffer, bufsiz, pos, v)) == common::Status::kOk) { value = (v != 0); } return ret; } inline int64_t encoded_length_var_int64(int64_t value) { uint64_t uv = static_cast(value); int64_t need_bytes = 0; if (uv <= XE_MAX_V1B) need_bytes = 1; else if (uv <= XE_MAX_V2B) need_bytes = 2; else if (uv <= XE_MAX_V3B) need_bytes = 3; else if (uv <= XE_MAX_V4B) need_bytes = 4; else if (uv <= XE_MAX_V5B) need_bytes = 5; else if (uv <= XE_MAX_V6B) need_bytes = 6; else if (uv <= XE_MAX_V7B) need_bytes = 7; else if (uv <= XE_MAX_V8B) need_bytes = 8; else if (uv <= XE_MAX_V9B) need_bytes = 9; else need_bytes = 10; return need_bytes; } /** * @brief Encode a integer (up to 64bit) in variable length encoding * * @param buffer pointer to the destination buffer * @param end the end pointer to the destination buffer * @param value value to encode * * @return true - success, false - failed */ inline int encode_var_int64(char *buffer, const int64_t bufsiz, int64_t &pos, int64_t value) { uint64_t uv = static_cast(value); ASSERT_BUFFER(encoded_length_var_int64(uv)); while (uv > XE_MAX_V1B) { *(buffer + pos++) = static_cast((uv) | 0x80); uv >>= 7; } if (uv <= XE_MAX_V1B) { *(buffer + pos++) = static_cast((uv)&0x7f); } return common::Status::kOk; } inline int decode_var_int64(const char *buffer, const int64_t bufsiz, int64_t &pos, int64_t &value) { uint64_t uv = 0; uint32_t shift = 0; int64_t tmp_pos = pos; int ret = common::Status::kOk; while ((*(buffer + tmp_pos)) & 0x80) { if (bufsiz - tmp_pos < 1) { ret = common::Status::kNoSpace; break; } uv |= (static_cast(*(buffer + tmp_pos++)) & 0x7f) << shift; shift += 7; } if (common::Status::kOk == ret) { if (bufsiz - tmp_pos < 1) { ret = common::Status::kNoSpace; } else { uv |= ((static_cast(*(buffer + tmp_pos++)) & 0x7f) << shift); value = static_cast(uv); pos = tmp_pos; } } return ret; } inline int64_t encoded_length_var_int32(int32_t value) { uint32_t uv = static_cast(value); int64_t need_bytes = 0; if (uv <= XE_MAX_V1B) need_bytes = 1; else if (uv <= XE_MAX_V2B) need_bytes = 2; else if (uv <= XE_MAX_V3B) need_bytes = 3; else if (uv <= XE_MAX_V4B) need_bytes = 4; else need_bytes = 5; return need_bytes; } /** * @brief Encode a integer (up to 32bit) in variable length encoding * * @param buffer pointer to the destination buffer * @param end the end pointer to the destination buffer * @param value value to encode * * @return true - success, false - failed */ inline int encode_var_int32(char *buffer, const int64_t bufsiz, int64_t &pos, int32_t value) { uint32_t uv = static_cast(value); ASSERT_BUFFER(encoded_length_var_int32(value)); while (uv > XE_MAX_V1B) { *(buffer + pos++) = static_cast((uv) | 0x80); uv >>= 7; } if (uv <= XE_MAX_V1B) { *(buffer + pos++) = static_cast((uv)&0x7f); } return common::Status::kOk; } inline int decode_var_int32(const char *buffer, const int64_t bufsiz, int64_t &pos, int32_t &value) { uint32_t uv = 0; uint32_t shift = 0; int ret = common::Status::kOk; int64_t tmp_pos = pos; while ((*(buffer + tmp_pos)) & 0x80) { if (bufsiz - tmp_pos < 1) { ret = common::Status::kNoSpace; break; } uv |= (static_cast(*(buffer + tmp_pos++)) & 0x7f) << shift; shift += 7; } if (common::Status::kOk == ret) { if (bufsiz - tmp_pos < 1) ret = common::Status::kNoSpace; else { uv |= (static_cast(*(buffer + tmp_pos++)) & 0x7f) << shift; value = static_cast(uv); pos = tmp_pos; } } return ret; } inline int64_t encoded_length_var_str(int64_t len) { return encoded_length_var_int64(len) + len; } /** * @brief Encode a buffer as vstr(int64,data,null) * * @param buffer pointer to the destination buffer * @param vbuf pointer to the start of the input buffer * @param len length of the input buffer */ inline int encode_var_str(char *buffer, const int64_t bufsiz, int64_t &pos, const void *str, int64_t len) { int ret = 0; ASSERT_BUFFER(encoded_length_var_str(len)); if (common::Status::kOk == ret) { /** * even through it's a null string, we can serialize it with * lenght 0, and following a '\0' */ ret = encode_var_int64(buffer, bufsiz, pos, len); if (common::Status::kOk == ret && len > 0 && nullptr != str) { memcpy(buffer + pos, str, len); pos += len; } } return ret; } inline int encode_var_str(char *buffer, const int64_t bufsiz, int64_t &pos, const common::Slice &slice) { return encode_var_str(buffer, bufsiz, pos, slice.data(), slice.size()); } // return deserialized string pointer to input buffer; // return nullptr if error occurs; inline const char *decode_var_str(const char *buffer, const int64_t bufsiz, int64_t &pos, int64_t &length) { const char *str = 0; int64_t tmp_pos = pos; length = -1; if ((nullptr == buffer) || (bufsiz < 0) || (pos < 0)) { } else if (decode_var_int64(buffer, bufsiz, tmp_pos, length) != common::Status::kOk) { } else if (length >= 0) { if (bufsiz - tmp_pos >= length) { str = buffer + tmp_pos; tmp_pos += length; pos = tmp_pos; } } return str; } // copy deserialized string into @dest[@length] inline int decode_var_str(const char *buffer, const int64_t bufsiz, int64_t &pos, char *dest, int64_t &length) { int ret = 0; int64_t tmp_len = 0; int64_t tmp_pos = pos; if ((nullptr == buffer) || (bufsiz < 0) || (pos < 0) || (nullptr == dest) || length < 0) { ret = common::Status::kNoSpace; } else if (decode_var_int64(buffer, bufsiz, tmp_pos, tmp_len) != 0 || tmp_len > bufsiz || tmp_len > length) { ret = common::Status::kNoSpace; } else if (tmp_len >= 0) { if (bufsiz - tmp_pos >= tmp_len) { length = tmp_len; memcpy(dest, buffer + tmp_pos, tmp_len); tmp_pos += tmp_len; pos = tmp_pos; } } return ret; } // setup @slice's data point to serialized buffer; // WARNING : @slice does not own the buffer, it will be unavialable // when @buffer is no longer live. inline int decode_var_str(const char *buffer, const int64_t bufsiz, int64_t &pos, common::Slice &slice) { int64_t length = 0; slice.data_ = decode_var_str(buffer, bufsiz, pos, length); slice.size_ = static_cast(length); if (nullptr == slice.data_ || length < 0) { return common::Status::kNoSpace; } return common::Status::kOk; } inline int decode_var_str(const char *buffer, const int64_t bufsiz, int64_t &pos, std::string &value) { int64_t length = 0; const char *data = decode_var_str(buffer, bufsiz, pos, length); if (nullptr == data || length < 0) { return common::Status::kNoSpace; } value.assign(data, length); return common::Status::kOk; } // ----------------------------------------------------------------- // serialize & deserialize template functions; // ----------------------------------------------------------------- inline int serialize(char *buffer, const int64_t bufsiz, int64_t &pos, int64_t value) { return encode_var_int64(buffer, bufsiz, pos, value); } inline int serialize(char *buffer, const int64_t bufsiz, int64_t &pos, uint64_t value) { return encode_var_int64(buffer, bufsiz, pos, static_cast(value)); } inline int serialize(char *buffer, const int64_t bufsiz, int64_t &pos, int32_t value) { return encode_var_int32(buffer, bufsiz, pos, value); } inline int serialize(char *buffer, const int64_t bufsiz, int64_t &pos, uint32_t value) { return encode_var_int32(buffer, bufsiz, pos, static_cast(value)); } inline int serialize(char *buffer, const int64_t bufsiz, int64_t &pos, int16_t value) { return encode_fixed_int16(buffer, bufsiz, pos, value); } inline int serialize(char *buffer, const int64_t bufsiz, int64_t &pos, uint16_t value) { return encode_fixed_int16(buffer, bufsiz, pos, static_cast(value)); } inline int serialize(char *buffer, const int64_t bufsiz, int64_t &pos, int8_t value) { return encode_fixed_int8(buffer, bufsiz, pos, value); } inline int serialize(char *buffer, const int64_t bufsiz, int64_t &pos, uint8_t value) { return encode_fixed_int8(buffer, bufsiz, pos, static_cast(value)); } inline int serialize(char *buffer, const int64_t bufsiz, int64_t &pos, const char *value) { return encode_var_str(buffer, bufsiz, pos, value, strlen(value)); } inline int serialize(char *buffer, const int64_t bufsiz, int64_t &pos, const common::Slice &value) { return encode_var_str(buffer, bufsiz, pos, value); } inline int serialize(char *buffer, const int64_t bufsiz, int64_t &pos, const std::string &value) { return encode_var_str(buffer, bufsiz, pos, value.data(), value.size()); } template int serialize(char *buffer, const int64_t bufsiz, int64_t &pos, const T &value) { return value.serialize(buffer, bufsiz, pos); } template int serialize_x(char *buf, const int64_t buf_len, int64_t &pos, const T &value); template int serialize_x(char *buf, const int64_t buf_len, int64_t &pos, const T &head, const Args &... rest); template int deserialize_x(const char *buf, int64_t buf_len, int64_t &pos, T &value); template int deserialize_x(const char *buf, int64_t buf_len, int64_t &pos, T &head, Args &... rest); template int get_serialize_size_x(const T &value); template int get_serialize_size_x(const T &head, const Args &... rest); template int serialize_v(char *buffer, const int64_t bufsiz, int64_t &pos, const autovector &values) { int ret = 0; if (common::Status::kOk != (ret = encode_var_int64(buffer, bufsiz, pos, values.size()))) { } else { for (auto &value : values) { if (common::Status::kOk != (ret = serialize(buffer, bufsiz, pos, value))) { break; } } } return ret; } template int serialize_v(char *buf, const int64_t buf_len, int64_t &pos, const std::vector &values) { int ret = common::Status::kOk; if (common::Status::kOk != (ret = encode_var_int64(buf, buf_len, pos, values.size()))) { } else { for (auto &value : values) { if (common::Status::kOk != (ret = serialize_x(buf, buf_len, pos, value))) { break; } } } return ret; } template int serialize_v(char *buf, const int64_t buf_len, int64_t &pos, const std::unordered_set &values) { int ret = common::Status::kOk; if (common::Status::kOk != (ret = encode_var_int64(buf, buf_len, pos, values.size()))) { } else { for (auto &value : values) { if (common::Status::kOk != (ret = serialize(buf, buf_len, pos, value))) { break; } } } return ret; } template int serialize_x(char *buf, const int64_t buf_len, int64_t &pos, const T &value); template int serialize_v(char *buf, const int64_t buf_len, int64_t &pos, const std::unordered_map &values) { int ret = common::Status::kOk; if (common::Status::kOk != (ret = encode_var_int64(buf, buf_len, pos, values.size()))) { } else { for (auto &value : values) { if (common::Status::kOk != (ret = serialize_x(buf, buf_len, pos, value.first))) { break; } if(common::Status::kOk != (ret = serialize_x(buf, buf_len, pos, value.second)) ) { break; } } } return ret; } template class Container, typename... Args> int serialize_v(char *buffer, const int64_t bufsiz, int64_t &pos, const Container &values) { int ret = 0; if (common::Status::kOk != (ret = encode_var_int64(buffer, bufsiz, pos, values.size()))) { } else { for (auto &value : values) { if (common::Status::kOk != (ret = serialize(buffer, bufsiz, pos, value))) { break; } } } return ret; } inline int deserialize(const char *buffer, const int64_t bufsiz, int64_t &pos, int64_t &value) { return decode_var_int64(buffer, bufsiz, pos, value); } inline int deserialize(const char *buffer, const int64_t bufsiz, int64_t &pos, uint64_t &value) { return decode_var_int64(buffer, bufsiz, pos, reinterpret_cast(value)); } inline int deserialize(const char *buffer, const int64_t bufsiz, int64_t &pos, int32_t &value) { return decode_var_int32(buffer, bufsiz, pos, value); } inline int deserialize(const char *buffer, const int64_t bufsiz, int64_t &pos, uint32_t &value) { return decode_var_int32(buffer, bufsiz, pos, reinterpret_cast(value)); } inline int deserialize(const char *buffer, const int64_t bufsiz, int64_t &pos, int16_t &value) { return decode_fixed_int16(buffer, bufsiz, pos, value); } inline int deserialize(const char *buffer, const int64_t bufsiz, int64_t &pos, uint16_t &value) { return decode_fixed_int16(buffer, bufsiz, pos, reinterpret_cast(value)); } inline int deserialize(const char *buffer, const int64_t bufsiz, int64_t &pos, int8_t &value) { return decode_fixed_int8(buffer, bufsiz, pos, value); } inline int deserialize(const char *buffer, const int64_t bufsiz, int64_t &pos, uint8_t &value) { return decode_fixed_int8(buffer, bufsiz, pos, reinterpret_cast(value)); } // make sure @value has enough space, otherwise it will be segment fault. inline int deserialize(const char *buffer, const int64_t bufsiz, int64_t &pos, char *value) { int64_t length = bufsiz; int ret = decode_var_str(buffer, bufsiz, pos, value, length); if (common::Status::kOk == ret) { value[length] = 0; } return ret; } inline int deserialize(const char *buffer, const int64_t bufsiz, int64_t &pos, common::Slice &value) { return decode_var_str(buffer, bufsiz, pos, value); } inline int deserialize(const char *buffer, const int64_t bufsiz, int64_t &pos, std::string &value) { return decode_var_str(buffer, bufsiz, pos, value); } template int deserialize(const char *buffer, const int64_t bufsiz, int64_t &pos, T &value) { return value.deserialize(buffer, bufsiz, pos); } template class Container, typename... Args> int deserialize_v(const char *buffer, const int64_t bufsiz, int64_t &pos, Container &values) { int ret = 0; int64_t size = 0; if (common::Status::kOk != (ret = decode_var_int64(buffer, bufsiz, pos, size))) { } else { E value; for (int64_t i = 0; i < size; ++i) { if (common::Status::kOk != (ret = deserialize(buffer, bufsiz, pos, value))) { break; } else { values.push_back(value); } } } return ret; } template int deserialize_v(const char *buffer, const int64_t bufsiz, int64_t &pos, autovector &values) { int ret = 0; int64_t size = 0; if (common::Status::kOk != (ret = decode_var_int64(buffer, bufsiz, pos, size))) { } else { E value; for (int64_t i = 0; i < size; ++i) { if (common::Status::kOk != (ret = deserialize(buffer, bufsiz, pos, value))) { break; } else { values.emplace_back(value); } } } return ret; } template int deserialize_v(const char *buf, const int64_t buf_len, int64_t &pos, std::vector &values) { int ret = common::Status::kOk; int64_t size = 0; if (common::Status::kOk != (ret = decode_var_int64(buf, buf_len, pos, size))) { } else { T value; for (int64_t i = 0; i < size; ++i) { if (common::Status::kOk != (ret = deserialize_x(buf, buf_len, pos, value))) { break; } else { values.emplace_back(value); } } } return ret; } template int deserialize_v(const char *buf, const int64_t buf_len, int64_t &pos, std::unordered_set &values) { int ret = common::Status::kOk; int64_t size = 0; T value; if (common::Status::kOk != (ret = decode_var_int64(buf, buf_len, pos, size))) { } else { for (int64_t i = 0; i < size; ++i) { if (common::Status::kOk != (ret = deserialize(buf, buf_len, pos, value))) { break; } else { values.emplace(value); } } } return ret; } template int deserialize_x(const char *buf, int64_t buf_len, int64_t &pos, T &value); template int deserialize_v(const char *buf, const int64_t buf_len, int64_t &pos, std::unordered_map &values) { int ret = common::Status::kOk; int64_t size = 0; if (common::Status::kOk != (ret = decode_var_int64(buf, buf_len, pos, size))) { } else { for (int64_t i = 0; i < size; ++i) { T first; E second; if (common::Status::kOk != (ret = deserialize_x(buf, buf_len, pos, first))) { break; } else if (common::Status::kOk != (ret = deserialize_x(buf, buf_len, pos, second))) { break; } else { values[first] = second; } } } return ret; } inline int64_t get_serialize_size(int64_t value) { return encoded_length_var_int64(value); } inline int64_t get_serialize_size(uint64_t value) { return encoded_length_var_int64(static_cast(value)); } inline int64_t get_serialize_size(int32_t value) { return encoded_length_var_int32(value); } inline int64_t get_serialize_size(uint32_t value) { return encoded_length_var_int32(static_cast(value)); } inline int64_t get_serialize_size(int16_t value) { return sizeof(value); } inline int64_t get_serialize_size(uint16_t value) { return sizeof(value); } inline int64_t get_serialize_size(int8_t value) { return sizeof(value); } inline int64_t get_serialize_size(uint8_t value) { return sizeof(value); } inline int64_t get_serialize_size(const char *value) { return encoded_length_var_str(nullptr == value ? 0 : strlen(value)); } inline int64_t get_serialize_size(const common::Slice &value) { return encoded_length_var_str(value.size()); } inline int64_t get_serialize_size(const std::string &value) { return encoded_length_var_str(value.size()); } template int64_t get_serialize_size(const T &value) { return value.get_serialize_size(); } template int get_serialize_v_size(const autovector &values) { int64_t ret = get_serialize_size(values.size()); for (auto &value : values) { ret += get_serialize_size(value); } return ret; } template int get_serialize_v_size(const std::vector &values) { int64_t value_size = values.size(); int64_t ret_size = get_serialize_size(value_size); for (auto &value : values) { ret_size += get_serialize_size_x(value); } return ret_size; } template int get_serialize_v_size(const std::unordered_set &values) { int64_t size = get_serialize_size(values.size()); for (auto &value : values) { size += get_serialize_size(value); } return size; } template int get_serialize_size_x(const T &value); template int get_serialize_v_size(const std::unordered_map &values) { int64_t size = get_serialize_size(values.size()); for (auto &value : values) { size += get_serialize_size_x(value.first); size += get_serialize_size_x(value.second); } return size; } template class Container, typename... Args> int get_serialize_v_size(const Container &values) { int64_t ret = get_serialize_size(values.size()); for (auto &value : values) { ret += get_serialize_size(value); } return ret; } // generic template (variant arguments) template int serialize(char *buffer, const int64_t bufsiz, int64_t &pos, const T &head, const Args &... rest) { int ret = 0; if (common::Status::kOk != (ret = serialize(buffer, bufsiz, pos, head))) { } else if (common::Status::kOk != (ret = serialize(buffer, bufsiz, pos, rest...))) { } return ret; } template int deserialize(const char *buffer, const int64_t bufsiz, int64_t &pos, T &head, Args &... rest) { int ret = 0; if (common::Status::kOk != (ret = deserialize(buffer, bufsiz, pos, head))) { } else if (common::Status::kOk != (ret = deserialize(buffer, bufsiz, pos, rest...))) { } return ret; } template int64_t get_serialize_size(const T &head, const Args &... rest) { return get_serialize_size(head) + get_serialize_size(rest...); } // generic template (variant arguments), for compactiple serialize and deserialize template struct ContainerSerializeWrap; template <> struct ContainerSerializeWrap { template int operator()(char *buf, int64_t buf_len, int64_t &pos, const T &t) { return util::serialize_v(buf, buf_len, pos, t); } }; template <> struct ContainerSerializeWrap { template int operator()(char *buf, int64_t buf_len, int64_t &pos, const T &t) { return util::serialize(buf, buf_len, pos, t); } }; template struct ContainerDeserializeWrap; template <> struct ContainerDeserializeWrap { template int operator()(const char *buf, int64_t buf_len, int64_t &pos, T &t) { return util::deserialize_v(buf, buf_len, pos, t); } }; template <> struct ContainerDeserializeWrap { template int operator()(const char *buf, int64_t buf_len, int64_t &pos, T &t) { return util::deserialize(buf, buf_len, pos, t); } }; template struct ContainerGetSerializeSizeWrap; template <> struct ContainerGetSerializeSizeWrap { template int operator()(const T &t) { return util::get_serialize_v_size(t); } }; template <> struct ContainerGetSerializeSizeWrap { template int operator()(const T &t) { return util::get_serialize_size(t); } }; template struct SerializeWrap; template <> struct SerializeWrap { template int operator()(char *buf, int64_t buf_len, int64_t &pos, const T &t) { return t.serialize(buf, buf_len, pos); } }; template <> struct SerializeWrap { template int operator()(char *buf, int64_t buf_len, int64_t &pos, const T &t) { typedef ContainerSerializeWrap Wrap; return Wrap()(buf, buf_len, pos, t); } }; template struct DeserializeWrap; template <> struct DeserializeWrap { template int operator()(const char *buf, int64_t buf_len, int64_t &pos, T &t) { return t.deserialize(buf, buf_len, pos); } }; template <> struct DeserializeWrap { template int operator()(const char *buf, int64_t buf_len, int64_t &pos, T &t) { typedef ContainerDeserializeWrap Wrap; return Wrap()(buf, buf_len, pos, t); } }; template struct GetSerializeSizeWrap; template <> struct GetSerializeSizeWrap { template int64_t operator()(const T &t) { return t.get_serialize_size(); } }; template <> struct GetSerializeSizeWrap { template int64_t operator()(const T &t) { typedef ContainerGetSerializeSizeWrap Wrap; return Wrap()(t); //return util::get_serialize_size(t); } }; template int serialize_x(char *buf, const int64_t buf_len, int64_t &pos, const T &value) { typedef SerializeWrap Wrap; return Wrap()(buf, buf_len, pos, value); } template int serialize_x(char *buf, const int64_t buf_len, int64_t &pos, const T &head, const Args &... rest) { int ret = common::Status::kOk; typedef SerializeWrap Wrap; if (common::Status::kOk != (ret = Wrap()(buf, buf_len, pos, head))) { } else if (common::Status::kOk != (ret = serialize_x(buf, buf_len, pos, rest...))) { } return ret; } template int deserialize_x(const char *buf, int64_t buf_len, int64_t &pos, T &value) { typedef DeserializeWrap Wrap; return Wrap()(buf, buf_len, pos, value); } template int deserialize_x(const char *buf, int64_t buf_len, int64_t &pos, T &head, Args &... rest) { int ret = common::Status::kOk; typedef DeserializeWrap Wrap; if ((pos < buf_len) && common::Status::kOk != (ret = Wrap()(buf, buf_len, pos, head))) { } else if ((pos < buf_len) && common::Status::kOk != (ret = deserialize_x(buf, buf_len, pos, rest...))) { } return ret; } template int get_serialize_size_x(const T &value) { typedef GetSerializeSizeWrap Wrap; return Wrap()(value); } template int get_serialize_size_x(const T &head, const Args &... rest) { typedef GetSerializeSizeWrap Wrap; return Wrap()(head) + get_serialize_size_x(rest...); } } /* util */ } /* xengine*/ #endif // XENGINE_SERIALIZATION_H_