/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you 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. */ #ifndef _THRIFT_PROTOCOL_TBINARYPROTOCOL_TCC_ #define _THRIFT_PROTOCOL_TBINARYPROTOCOL_TCC_ 1 #include #include #include namespace apache { namespace thrift { namespace protocol { template uint32_t TBinaryProtocolT::writeMessageBegin(const std::string& name, const TMessageType messageType, const int32_t seqid) { if (this->strict_write_) { int32_t version = (VERSION_1) | ((int32_t)messageType); uint32_t wsize = 0; wsize += writeI32(version); wsize += writeString(name); wsize += writeI32(seqid); return wsize; } else { uint32_t wsize = 0; wsize += writeString(name); wsize += writeByte((int8_t)messageType); wsize += writeI32(seqid); return wsize; } } template uint32_t TBinaryProtocolT::writeMessageEnd() { return 0; } template uint32_t TBinaryProtocolT::writeStructBegin(const char* name) { (void)name; return 0; } template uint32_t TBinaryProtocolT::writeStructEnd() { return 0; } template uint32_t TBinaryProtocolT::writeFieldBegin(const char* name, const TType fieldType, const int16_t fieldId) { (void)name; uint32_t wsize = 0; wsize += writeByte((int8_t)fieldType); wsize += writeI16(fieldId); return wsize; } template uint32_t TBinaryProtocolT::writeFieldEnd() { return 0; } template uint32_t TBinaryProtocolT::writeFieldStop() { return writeByte((int8_t)T_STOP); } template uint32_t TBinaryProtocolT::writeMapBegin(const TType keyType, const TType valType, const uint32_t size) { uint32_t wsize = 0; wsize += writeByte((int8_t)keyType); wsize += writeByte((int8_t)valType); wsize += writeI32((int32_t)size); return wsize; } template uint32_t TBinaryProtocolT::writeMapEnd() { return 0; } template uint32_t TBinaryProtocolT::writeListBegin(const TType elemType, const uint32_t size) { uint32_t wsize = 0; wsize += writeByte((int8_t)elemType); wsize += writeI32((int32_t)size); return wsize; } template uint32_t TBinaryProtocolT::writeListEnd() { return 0; } template uint32_t TBinaryProtocolT::writeSetBegin(const TType elemType, const uint32_t size) { uint32_t wsize = 0; wsize += writeByte((int8_t)elemType); wsize += writeI32((int32_t)size); return wsize; } template uint32_t TBinaryProtocolT::writeSetEnd() { return 0; } template uint32_t TBinaryProtocolT::writeBool(const bool value) { uint8_t tmp = value ? 1 : 0; this->trans_->write(&tmp, 1); return 1; } template uint32_t TBinaryProtocolT::writeByte(const int8_t byte) { this->trans_->write((uint8_t*)&byte, 1); return 1; } template uint32_t TBinaryProtocolT::writeI16(const int16_t i16) { auto net = (int16_t)ByteOrder_::toWire16(i16); this->trans_->write((uint8_t*)&net, 2); return 2; } template uint32_t TBinaryProtocolT::writeI32(const int32_t i32) { auto net = (int32_t)ByteOrder_::toWire32(i32); this->trans_->write((uint8_t*)&net, 4); return 4; } template uint32_t TBinaryProtocolT::writeI64(const int64_t i64) { auto net = (int64_t)ByteOrder_::toWire64(i64); this->trans_->write((uint8_t*)&net, 8); return 8; } template uint32_t TBinaryProtocolT::writeDouble(const double dub) { static_assert(sizeof(double) == sizeof(uint64_t), "sizeof(double) == sizeof(uint64_t)"); static_assert(std::numeric_limits::is_iec559, "std::numeric_limits::is_iec559"); auto bits = bitwise_cast(dub); bits = ByteOrder_::toWire64(bits); this->trans_->write((uint8_t*)&bits, 8); return 8; } template template uint32_t TBinaryProtocolT::writeString(const StrType& str) { if (str.size() > static_cast((std::numeric_limits::max)())) throw TProtocolException(TProtocolException::SIZE_LIMIT); auto size = static_cast(str.size()); uint32_t result = writeI32((int32_t)size); if (size > 0) { this->trans_->write((uint8_t*)str.data(), size); } return result + size; } template uint32_t TBinaryProtocolT::writeBinary(const std::string& str) { return TBinaryProtocolT::writeString(str); } /** * Reading functions */ template uint32_t TBinaryProtocolT::readMessageBegin(std::string& name, TMessageType& messageType, int32_t& seqid) { uint32_t result = 0; int32_t sz; result += readI32(sz); if (sz < 0) { // Check for correct version number int32_t version = sz & VERSION_MASK; if (version != VERSION_1) { throw TProtocolException(TProtocolException::BAD_VERSION, "Bad version identifier"); } messageType = (TMessageType)(sz & 0x000000ff); result += readString(name); result += readI32(seqid); } else { if (this->strict_read_) { throw TProtocolException(TProtocolException::BAD_VERSION, "No version identifier... old protocol client in strict mode?"); } else { // Handle pre-versioned input int8_t type; result += readStringBody(name, sz); result += readByte(type); messageType = (TMessageType)type; result += readI32(seqid); } } return result; } template uint32_t TBinaryProtocolT::readMessageEnd() { return 0; } template uint32_t TBinaryProtocolT::readStructBegin(std::string& name) { name = ""; return 0; } template uint32_t TBinaryProtocolT::readStructEnd() { return 0; } template uint32_t TBinaryProtocolT::readFieldBegin(std::string& name, TType& fieldType, int16_t& fieldId) { (void)name; uint32_t result = 0; int8_t type; result += readByte(type); fieldType = (TType)type; if (fieldType == T_STOP) { fieldId = 0; return result; } result += readI16(fieldId); return result; } template uint32_t TBinaryProtocolT::readFieldEnd() { return 0; } template uint32_t TBinaryProtocolT::readMapBegin(TType& keyType, TType& valType, uint32_t& size) { int8_t k, v; uint32_t result = 0; int32_t sizei; result += readByte(k); keyType = (TType)k; result += readByte(v); valType = (TType)v; result += readI32(sizei); if (sizei < 0) { throw TProtocolException(TProtocolException::NEGATIVE_SIZE); } else if (this->container_limit_ && sizei > this->container_limit_) { throw TProtocolException(TProtocolException::SIZE_LIMIT); } size = (uint32_t)sizei; TMap map(keyType, valType, size); checkReadBytesAvailable(map); return result; } template uint32_t TBinaryProtocolT::readMapEnd() { return 0; } template uint32_t TBinaryProtocolT::readListBegin(TType& elemType, uint32_t& size) { int8_t e; uint32_t result = 0; int32_t sizei; result += readByte(e); elemType = (TType)e; result += readI32(sizei); if (sizei < 0) { throw TProtocolException(TProtocolException::NEGATIVE_SIZE); } else if (this->container_limit_ && sizei > this->container_limit_) { throw TProtocolException(TProtocolException::SIZE_LIMIT); } size = (uint32_t)sizei; TList list(elemType, size); checkReadBytesAvailable(list); return result; } template uint32_t TBinaryProtocolT::readListEnd() { return 0; } template uint32_t TBinaryProtocolT::readSetBegin(TType& elemType, uint32_t& size) { int8_t e; uint32_t result = 0; int32_t sizei; result += readByte(e); elemType = (TType)e; result += readI32(sizei); if (sizei < 0) { throw TProtocolException(TProtocolException::NEGATIVE_SIZE); } else if (this->container_limit_ && sizei > this->container_limit_) { throw TProtocolException(TProtocolException::SIZE_LIMIT); } size = (uint32_t)sizei; TSet set(elemType, size); checkReadBytesAvailable(set); return result; } template uint32_t TBinaryProtocolT::readSetEnd() { return 0; } template uint32_t TBinaryProtocolT::readBool(bool& value) { uint8_t b[1]; this->trans_->readAll(b, 1); value = *(int8_t*)b != 0; return 1; } template uint32_t TBinaryProtocolT::readByte(int8_t& byte) { uint8_t b[1]; this->trans_->readAll(b, 1); byte = *(int8_t*)b; return 1; } template uint32_t TBinaryProtocolT::readI16(int16_t& i16) { union bytes { uint8_t b[2]; int16_t all; } theBytes; this->trans_->readAll(theBytes.b, 2); i16 = (int16_t)ByteOrder_::fromWire16(theBytes.all); return 2; } template uint32_t TBinaryProtocolT::readI32(int32_t& i32) { union bytes { uint8_t b[4]; int32_t all; } theBytes; this->trans_->readAll(theBytes.b, 4); i32 = (int32_t)ByteOrder_::fromWire32(theBytes.all); return 4; } template uint32_t TBinaryProtocolT::readI64(int64_t& i64) { union bytes { uint8_t b[8]; int64_t all; } theBytes; this->trans_->readAll(theBytes.b, 8); i64 = (int64_t)ByteOrder_::fromWire64(theBytes.all); return 8; } template uint32_t TBinaryProtocolT::readDouble(double& dub) { static_assert(sizeof(double) == sizeof(uint64_t), "sizeof(double) == sizeof(uint64_t)"); static_assert(std::numeric_limits::is_iec559, "std::numeric_limits::is_iec559"); union bytes { uint8_t b[8]; uint64_t all; } theBytes; this->trans_->readAll(theBytes.b, 8); theBytes.all = ByteOrder_::fromWire64(theBytes.all); dub = bitwise_cast(theBytes.all); return 8; } template template uint32_t TBinaryProtocolT::readString(StrType& str) { uint32_t result; int32_t size; result = readI32(size); return result + readStringBody(str, size); } template uint32_t TBinaryProtocolT::readBinary(std::string& str) { return TBinaryProtocolT::readString(str); } template template uint32_t TBinaryProtocolT::readStringBody(StrType& str, int32_t size) { uint32_t result = 0; // Catch error cases if (size < 0) { throw TProtocolException(TProtocolException::NEGATIVE_SIZE); } if (this->string_limit_ > 0 && size > this->string_limit_) { throw TProtocolException(TProtocolException::SIZE_LIMIT); } // Catch empty string case if (size == 0) { str.clear(); return result; } // Try to borrow first const uint8_t* borrow_buf; uint32_t got = size; if ((borrow_buf = this->trans_->borrow(nullptr, &got))) { str.assign((const char*)borrow_buf, size); this->trans_->consume(size); return size; } str.resize(size); this->trans_->readAll(reinterpret_cast(&str[0]), size); return (uint32_t)size; } // Return the minimum number of bytes a type will consume on the wire template int TBinaryProtocolT::getMinSerializedSize(TType type) { switch (type) { case T_STOP: return 0; case T_VOID: return 0; case T_BOOL: return sizeof(int8_t); case T_BYTE: return sizeof(int8_t); case T_DOUBLE: return sizeof(double); case T_I16: return sizeof(short); case T_I32: return sizeof(int); case T_I64: return sizeof(long); case T_STRING: return sizeof(int); // string length case T_STRUCT: return 0; // empty struct case T_MAP: return sizeof(int); // element count case T_SET: return sizeof(int); // element count case T_LIST: return sizeof(int); // element count default: throw TProtocolException(TProtocolException::UNKNOWN, "unrecognized type code"); } } } } } // apache::thrift::protocol #endif // #ifndef _THRIFT_PROTOCOL_TBINARYPROTOCOL_TCC_