blob: 960b0d003a450c045c78a10b6078571554e1c07e [file] [log] [blame]
/*
* 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_PY_BINARY_H
#define THRIFT_PY_BINARY_H
#include <Python.h>
#include "ext/protocol.h"
#include "ext/endian.h"
#include <stdint.h>
namespace apache {
namespace thrift {
namespace py {
class BinaryProtocol : public ProtocolBase<BinaryProtocol> {
public:
virtual ~BinaryProtocol() {}
void writeI8(int8_t val) { writeBuffer(reinterpret_cast<char*>(&val), sizeof(int8_t)); }
void writeI16(int16_t val) {
int16_t net = static_cast<int16_t>(htons(val));
writeBuffer(reinterpret_cast<char*>(&net), sizeof(int16_t));
}
void writeI32(int32_t val) {
int32_t net = static_cast<int32_t>(htonl(val));
writeBuffer(reinterpret_cast<char*>(&net), sizeof(int32_t));
}
void writeI64(int64_t val) {
int64_t net = static_cast<int64_t>(htonll(val));
writeBuffer(reinterpret_cast<char*>(&net), sizeof(int64_t));
}
void writeDouble(double dub) {
// Unfortunately, bitwise_cast doesn't work in C. Bad C!
union {
double f;
int64_t t;
} transfer;
transfer.f = dub;
writeI64(transfer.t);
}
void writeBool(int v) { writeByte(static_cast<uint8_t>(v)); }
void writeString(PyObject* value, int32_t len) {
writeI32(len);
writeBuffer(PyBytes_AS_STRING(value), len);
}
bool writeListBegin(PyObject* value, const SetListTypeArgs& parsedargs, int32_t len) {
writeByte(parsedargs.element_type);
writeI32(len);
return true;
}
bool writeMapBegin(PyObject* value, const MapTypeArgs& parsedargs, int32_t len) {
writeByte(parsedargs.ktag);
writeByte(parsedargs.vtag);
writeI32(len);
return true;
}
bool writeStructBegin() { return true; }
bool writeStructEnd() { return true; }
bool writeField(PyObject* value, const StructItemSpec& parsedspec) {
writeByte(static_cast<uint8_t>(parsedspec.type));
writeI16(parsedspec.tag);
return encodeValue(value, parsedspec.type, parsedspec.typeargs);
}
void writeFieldStop() { writeByte(static_cast<uint8_t>(T_STOP)); }
bool readBool(bool& val) {
char* buf;
if (!readBytes(&buf, 1)) {
return false;
}
val = buf[0] == 1;
return true;
}
bool readI8(int8_t& val) {
char* buf;
if (!readBytes(&buf, 1)) {
return false;
}
val = buf[0];
return true;
}
bool readI16(int16_t& val) {
char* buf;
if (!readBytes(&buf, sizeof(int16_t))) {
return false;
}
memcpy(&val, buf, sizeof(int16_t));
val = ntohs(val);
return true;
}
bool readI32(int32_t& val) {
char* buf;
if (!readBytes(&buf, sizeof(int32_t))) {
return false;
}
memcpy(&val, buf, sizeof(int32_t));
val = ntohl(val);
return true;
}
bool readI64(int64_t& val) {
char* buf;
if (!readBytes(&buf, sizeof(int64_t))) {
return false;
}
memcpy(&val, buf, sizeof(int64_t));
val = ntohll(val);
return true;
}
bool readDouble(double& val) {
union {
int64_t f;
double t;
} transfer;
if (!readI64(transfer.f)) {
return false;
}
val = transfer.t;
return true;
}
int32_t readString(char** buf) {
int32_t len = 0;
if (!readI32(len) || !checkLengthLimit(len, stringLimit()) || !readBytes(buf, len)) {
return -1;
}
return len;
}
int32_t readListBegin(TType& etype) {
int32_t len;
uint8_t b = 0;
if (!readByte(b) || !readI32(len) || !checkLengthLimit(len, containerLimit())) {
return -1;
}
etype = static_cast<TType>(b);
return len;
}
int32_t readMapBegin(TType& ktype, TType& vtype) {
int32_t len;
uint8_t k, v;
if (!readByte(k) || !readByte(v) || !readI32(len) || !checkLengthLimit(len, containerLimit())) {
return -1;
}
ktype = static_cast<TType>(k);
vtype = static_cast<TType>(v);
return len;
}
bool readStructBegin() { return true; }
bool readStructEnd() { return true; }
bool readFieldBegin(TType& type, int16_t& tag);
#define SKIPBYTES(n) \
do { \
if (!readBytes(&dummy_buf_, (n))) { \
return false; \
} \
return true; \
} while (0)
bool skipBool() { SKIPBYTES(1); }
bool skipByte() { SKIPBYTES(1); }
bool skipI16() { SKIPBYTES(2); }
bool skipI32() { SKIPBYTES(4); }
bool skipI64() { SKIPBYTES(8); }
bool skipDouble() { SKIPBYTES(8); }
bool skipString() {
int32_t len;
if (!readI32(len)) {
return false;
}
SKIPBYTES(len);
}
#undef SKIPBYTES
private:
char* dummy_buf_;
};
}
}
}
#endif // THRIFT_PY_BINARY_H