blob: dd7750b49a819c3e41e01be081c949720019522f [file] [log] [blame]
Nobuaki Sukegawa6525f6a2016-02-11 13:58:39 +09001/*
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
28namespace apache {
29namespace thrift {
30namespace py {
31
32class BinaryProtocol : public ProtocolBase<BinaryProtocol> {
33public:
34 virtual ~BinaryProtocol() {}
35
36 void writeI8(int8_t val) { writeBuffer(reinterpret_cast<char*>(&val), sizeof(int8_t)); }
37
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
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
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
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
63 void writeBool(int v) { writeByte(static_cast<uint8_t>(v)); }
64
65 void writeString(PyObject* value, int32_t len) {
66 writeI32(len);
67 writeBuffer(PyBytes_AS_STRING(value), len);
68 }
69
70 bool writeListBegin(PyObject* value, const SetListTypeArgs& parsedargs, int32_t len) {
71 writeByte(parsedargs.element_type);
72 writeI32(len);
73 return true;
74 }
75
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
83 bool writeStructBegin() { return true; }
84 bool writeStructEnd() { return true; }
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
Carel Combrinka715bdf2025-10-30 07:44:21 +010091 void writeUuid(char* value) {
92 writeBuffer(value, 16);
93 }
94
Nobuaki Sukegawa6525f6a2016-02-11 13:58:39 +090095 void writeFieldStop() { writeByte(static_cast<uint8_t>(T_STOP)); }
96
97 bool readBool(bool& val) {
98 char* buf;
99 if (!readBytes(&buf, 1)) {
100 return false;
101 }
102 val = buf[0] == 1;
103 return true;
104 }
105
106 bool readI8(int8_t& val) {
107 char* buf;
108 if (!readBytes(&buf, 1)) {
109 return false;
110 }
111 val = buf[0];
112 return true;
113 }
114
115 bool readI16(int16_t& val) {
116 char* buf;
117 if (!readBytes(&buf, sizeof(int16_t))) {
118 return false;
119 }
James E. King, III0ad20bd2017-09-30 15:44:16 -0700120 memcpy(&val, buf, sizeof(int16_t));
121 val = ntohs(val);
Nobuaki Sukegawa6525f6a2016-02-11 13:58:39 +0900122 return true;
123 }
124
125 bool readI32(int32_t& val) {
126 char* buf;
127 if (!readBytes(&buf, sizeof(int32_t))) {
128 return false;
129 }
James E. King, III0ad20bd2017-09-30 15:44:16 -0700130 memcpy(&val, buf, sizeof(int32_t));
131 val = ntohl(val);
Nobuaki Sukegawa6525f6a2016-02-11 13:58:39 +0900132 return true;
133 }
134
135 bool readI64(int64_t& val) {
136 char* buf;
137 if (!readBytes(&buf, sizeof(int64_t))) {
138 return false;
139 }
James E. King, III0ad20bd2017-09-30 15:44:16 -0700140 memcpy(&val, buf, sizeof(int64_t));
141 val = ntohll(val);
Nobuaki Sukegawa6525f6a2016-02-11 13:58:39 +0900142 return true;
143 }
144
145 bool readDouble(double& val) {
146 union {
147 int64_t f;
148 double t;
149 } transfer;
150
151 if (!readI64(transfer.f)) {
152 return false;
153 }
154 val = transfer.t;
155 return true;
156 }
157
158 int32_t readString(char** buf) {
159 int32_t len = 0;
160 if (!readI32(len) || !checkLengthLimit(len, stringLimit()) || !readBytes(buf, len)) {
161 return -1;
162 }
163 return len;
164 }
165
Carel Combrinka715bdf2025-10-30 07:44:21 +0100166 int32_t readUuid(char** buf) {
167 if (!readBytes(buf, 16)) {
168 return -1;
169 }
170 return 16;
171 }
172
Nobuaki Sukegawa6525f6a2016-02-11 13:58:39 +0900173 int32_t readListBegin(TType& etype) {
174 int32_t len;
175 uint8_t b = 0;
176 if (!readByte(b) || !readI32(len) || !checkLengthLimit(len, containerLimit())) {
177 return -1;
178 }
179 etype = static_cast<TType>(b);
180 return len;
181 }
182
183 int32_t readMapBegin(TType& ktype, TType& vtype) {
184 int32_t len;
185 uint8_t k, v;
186 if (!readByte(k) || !readByte(v) || !readI32(len) || !checkLengthLimit(len, containerLimit())) {
187 return -1;
188 }
189 ktype = static_cast<TType>(k);
190 vtype = static_cast<TType>(v);
191 return len;
192 }
193
194 bool readStructBegin() { return true; }
195 bool readStructEnd() { return true; }
196
197 bool readFieldBegin(TType& type, int16_t& tag);
198
199#define SKIPBYTES(n) \
200 do { \
201 if (!readBytes(&dummy_buf_, (n))) { \
202 return false; \
203 } \
204 return true; \
205 } while (0)
206
207 bool skipBool() { SKIPBYTES(1); }
208 bool skipByte() { SKIPBYTES(1); }
209 bool skipI16() { SKIPBYTES(2); }
210 bool skipI32() { SKIPBYTES(4); }
211 bool skipI64() { SKIPBYTES(8); }
212 bool skipDouble() { SKIPBYTES(8); }
213 bool skipString() {
214 int32_t len;
215 if (!readI32(len)) {
216 return false;
217 }
218 SKIPBYTES(len);
219 }
Carel Combrinka715bdf2025-10-30 07:44:21 +0100220 bool skipUuid() { SKIPBYTES(16); }
Nobuaki Sukegawa6525f6a2016-02-11 13:58:39 +0900221#undef SKIPBYTES
222
223private:
224 char* dummy_buf_;
225};
226}
227}
228}
229#endif // THRIFT_PY_BINARY_H