1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one
3  * or more contributor license agreements. See the NOTICE file
4  * distributed with this work for additional information
5  * regarding copyright ownership. The ASF licenses this file
6  * to you under the Apache License, Version 2.0 (the
7  * "License"); you may not use this file except in compliance
8  * with the License. You may obtain a copy of the License at
9  *
10  *   http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing,
13  * software distributed under the License is distributed on an
14  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15  * KIND, either express or implied. See the License for the
16  * specific language governing permissions and limitations
17  * under the License.
18  */
19 
20 #ifndef THRIFT_PY_BINARY_H
21 #define THRIFT_PY_BINARY_H
22 
23 #include <Python.h>
24 #include "ext/protocol.h"
25 #include "ext/endian.h"
26 #include <stdint.h>
27 
28 namespace apache {
29 namespace thrift {
30 namespace py {
31 
32 class BinaryProtocol : public ProtocolBase<BinaryProtocol> {
33 public:
~BinaryProtocol()34   virtual ~BinaryProtocol() {}
35 
writeI8(int8_t val)36   void writeI8(int8_t val) { writeBuffer(reinterpret_cast<char*>(&val), sizeof(int8_t)); }
37 
writeI16(int16_t val)38   void writeI16(int16_t val) {
39     int16_t net = static_cast<int16_t>(htons(val));
40     writeBuffer(reinterpret_cast<char*>(&net), sizeof(int16_t));
41   }
42 
writeI32(int32_t val)43   void writeI32(int32_t val) {
44     int32_t net = static_cast<int32_t>(htonl(val));
45     writeBuffer(reinterpret_cast<char*>(&net), sizeof(int32_t));
46   }
47 
writeI64(int64_t val)48   void writeI64(int64_t val) {
49     int64_t net = static_cast<int64_t>(htonll(val));
50     writeBuffer(reinterpret_cast<char*>(&net), sizeof(int64_t));
51   }
52 
writeDouble(double dub)53   void writeDouble(double dub) {
54     // Unfortunately, bitwise_cast doesn't work in C.  Bad C!
55     union {
56       double f;
57       int64_t t;
58     } transfer;
59     transfer.f = dub;
60     writeI64(transfer.t);
61   }
62 
writeBool(int v)63   void writeBool(int v) { writeByte(static_cast<uint8_t>(v)); }
64 
writeString(PyObject * value,int32_t len)65   void writeString(PyObject* value, int32_t len) {
66     writeI32(len);
67     writeBuffer(PyBytes_AS_STRING(value), len);
68   }
69 
writeListBegin(PyObject * value,const SetListTypeArgs & parsedargs,int32_t len)70   bool writeListBegin(PyObject* value, const SetListTypeArgs& parsedargs, int32_t len) {
71     writeByte(parsedargs.element_type);
72     writeI32(len);
73     return true;
74   }
75 
writeMapBegin(PyObject * value,const MapTypeArgs & parsedargs,int32_t len)76   bool writeMapBegin(PyObject* value, const MapTypeArgs& parsedargs, int32_t len) {
77     writeByte(parsedargs.ktag);
78     writeByte(parsedargs.vtag);
79     writeI32(len);
80     return true;
81   }
82 
writeStructBegin()83   bool writeStructBegin() { return true; }
writeStructEnd()84   bool writeStructEnd() { return true; }
writeField(PyObject * value,const StructItemSpec & parsedspec)85   bool writeField(PyObject* value, const StructItemSpec& parsedspec) {
86     writeByte(static_cast<uint8_t>(parsedspec.type));
87     writeI16(parsedspec.tag);
88     return encodeValue(value, parsedspec.type, parsedspec.typeargs);
89   }
90 
writeFieldStop()91   void writeFieldStop() { writeByte(static_cast<uint8_t>(T_STOP)); }
92 
readBool(bool & val)93   bool readBool(bool& val) {
94     char* buf;
95     if (!readBytes(&buf, 1)) {
96       return false;
97     }
98     val = buf[0] == 1;
99     return true;
100   }
101 
readI8(int8_t & val)102   bool readI8(int8_t& val) {
103     char* buf;
104     if (!readBytes(&buf, 1)) {
105       return false;
106     }
107     val = buf[0];
108     return true;
109   }
110 
readI16(int16_t & val)111   bool readI16(int16_t& val) {
112     char* buf;
113     if (!readBytes(&buf, sizeof(int16_t))) {
114       return false;
115     }
116     memcpy(&val, buf, sizeof(int16_t));
117     val = ntohs(val);
118     return true;
119   }
120 
readI32(int32_t & val)121   bool readI32(int32_t& val) {
122     char* buf;
123     if (!readBytes(&buf, sizeof(int32_t))) {
124       return false;
125     }
126     memcpy(&val, buf, sizeof(int32_t));
127     val = ntohl(val);
128     return true;
129   }
130 
readI64(int64_t & val)131   bool readI64(int64_t& val) {
132     char* buf;
133     if (!readBytes(&buf, sizeof(int64_t))) {
134       return false;
135     }
136     memcpy(&val, buf, sizeof(int64_t));
137     val = ntohll(val);
138     return true;
139   }
140 
readDouble(double & val)141   bool readDouble(double& val) {
142     union {
143       int64_t f;
144       double t;
145     } transfer;
146 
147     if (!readI64(transfer.f)) {
148       return false;
149     }
150     val = transfer.t;
151     return true;
152   }
153 
readString(char ** buf)154   int32_t readString(char** buf) {
155     int32_t len = 0;
156     if (!readI32(len) || !checkLengthLimit(len, stringLimit()) || !readBytes(buf, len)) {
157       return -1;
158     }
159     return len;
160   }
161 
readListBegin(TType & etype)162   int32_t readListBegin(TType& etype) {
163     int32_t len;
164     uint8_t b = 0;
165     if (!readByte(b) || !readI32(len) || !checkLengthLimit(len, containerLimit())) {
166       return -1;
167     }
168     etype = static_cast<TType>(b);
169     return len;
170   }
171 
readMapBegin(TType & ktype,TType & vtype)172   int32_t readMapBegin(TType& ktype, TType& vtype) {
173     int32_t len;
174     uint8_t k, v;
175     if (!readByte(k) || !readByte(v) || !readI32(len) || !checkLengthLimit(len, containerLimit())) {
176       return -1;
177     }
178     ktype = static_cast<TType>(k);
179     vtype = static_cast<TType>(v);
180     return len;
181   }
182 
readStructBegin()183   bool readStructBegin() { return true; }
readStructEnd()184   bool readStructEnd() { return true; }
185 
186   bool readFieldBegin(TType& type, int16_t& tag);
187 
188 #define SKIPBYTES(n)                                                                               \
189   do {                                                                                             \
190     if (!readBytes(&dummy_buf_, (n))) {                                                            \
191       return false;                                                                                \
192     }                                                                                              \
193     return true;                                                                                   \
194   } while (0)
195 
skipBool()196   bool skipBool() { SKIPBYTES(1); }
skipByte()197   bool skipByte() { SKIPBYTES(1); }
skipI16()198   bool skipI16() { SKIPBYTES(2); }
skipI32()199   bool skipI32() { SKIPBYTES(4); }
skipI64()200   bool skipI64() { SKIPBYTES(8); }
skipDouble()201   bool skipDouble() { SKIPBYTES(8); }
skipString()202   bool skipString() {
203     int32_t len;
204     if (!readI32(len)) {
205       return false;
206     }
207     SKIPBYTES(len);
208   }
209 #undef SKIPBYTES
210 
211 private:
212   char* dummy_buf_;
213 };
214 }
215 }
216 }
217 #endif // THRIFT_PY_BINARY_H
218