blob: f14ddaeb60aeae95d36fffdd499e598e0ba0f23f [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#include <Python.h>
21#include "types.h"
22#include "binary.h"
23#include "compact.h"
Nobuaki Sukegawaf7a8d942016-03-01 01:41:47 +090024#include <limits>
Nobuaki Sukegawa6525f6a2016-02-11 13:58:39 +090025#include <stdint.h>
Nobuaki Sukegawa6525f6a2016-02-11 13:58:39 +090026
27// TODO(dreiss): defval appears to be unused. Look into removing it.
28// TODO(dreiss): Make parse_spec_args recursive, and cache the output
29// permanently in the object. (Malloc and orphan.)
30// TODO(dreiss): Why do we need cStringIO for reading, why not just char*?
31// Can cStringIO let us work with a BufferedTransport?
32// TODO(dreiss): Don't ignore the rv from cwrite (maybe).
33
34// Doing a benchmark shows that interning actually makes a difference, amazingly.
35
36/** Pointer to interned string to speed up attribute lookup. */
37PyObject* INTERN_STRING(TFrozenDict);
38PyObject* INTERN_STRING(cstringio_buf);
39PyObject* INTERN_STRING(cstringio_refill);
40static PyObject* INTERN_STRING(string_length_limit);
41static PyObject* INTERN_STRING(container_length_limit);
42static PyObject* INTERN_STRING(trans);
43
44namespace apache {
45namespace thrift {
46namespace py {
47
48template <typename T>
49static PyObject* encode_impl(PyObject* args) {
50 if (!args)
zeshuai00726681fb2020-06-03 17:24:38 +080051 return nullptr;
Nobuaki Sukegawa6525f6a2016-02-11 13:58:39 +090052
zeshuai00726681fb2020-06-03 17:24:38 +080053 PyObject* enc_obj = nullptr;
54 PyObject* type_args = nullptr;
Nobuaki Sukegawa6525f6a2016-02-11 13:58:39 +090055 if (!PyArg_ParseTuple(args, "OO", &enc_obj, &type_args)) {
zeshuai00726681fb2020-06-03 17:24:38 +080056 return nullptr;
Nobuaki Sukegawa6525f6a2016-02-11 13:58:39 +090057 }
58 if (!enc_obj || !type_args) {
zeshuai00726681fb2020-06-03 17:24:38 +080059 return nullptr;
Nobuaki Sukegawa6525f6a2016-02-11 13:58:39 +090060 }
61
62 T protocol;
63 if (!protocol.prepareEncodeBuffer() || !protocol.encodeValue(enc_obj, T_STRUCT, type_args)) {
zeshuai00726681fb2020-06-03 17:24:38 +080064 return nullptr;
Nobuaki Sukegawa6525f6a2016-02-11 13:58:39 +090065 }
66
67 return protocol.getEncodedValue();
68}
69
70static inline long as_long_then_delete(PyObject* value, long default_value) {
71 ScopedPyObject scope(value);
72 long v = PyInt_AsLong(value);
73 if (INT_CONV_ERROR_OCCURRED(v)) {
74 PyErr_Clear();
75 return default_value;
76 }
77 return v;
78}
79
80template <typename T>
81static PyObject* decode_impl(PyObject* args) {
zeshuai00726681fb2020-06-03 17:24:38 +080082 PyObject* output_obj = nullptr;
83 PyObject* oprot = nullptr;
84 PyObject* typeargs = nullptr;
Nobuaki Sukegawa6525f6a2016-02-11 13:58:39 +090085 if (!PyArg_ParseTuple(args, "OOO", &output_obj, &oprot, &typeargs)) {
zeshuai00726681fb2020-06-03 17:24:38 +080086 return nullptr;
Nobuaki Sukegawa6525f6a2016-02-11 13:58:39 +090087 }
88
89 T protocol;
James E. King, III07f59972017-03-10 06:18:33 -050090 int32_t default_limit = (std::numeric_limits<int32_t>::max)();
Nobuaki Sukegawa6525f6a2016-02-11 13:58:39 +090091 protocol.setStringLengthLimit(
Nobuaki Sukegawaf7a8d942016-03-01 01:41:47 +090092 as_long_then_delete(PyObject_GetAttr(oprot, INTERN_STRING(string_length_limit)),
93 default_limit));
Nobuaki Sukegawa6525f6a2016-02-11 13:58:39 +090094 protocol.setContainerLengthLimit(
95 as_long_then_delete(PyObject_GetAttr(oprot, INTERN_STRING(container_length_limit)),
Nobuaki Sukegawaf7a8d942016-03-01 01:41:47 +090096 default_limit));
Nobuaki Sukegawa6525f6a2016-02-11 13:58:39 +090097 ScopedPyObject transport(PyObject_GetAttr(oprot, INTERN_STRING(trans)));
98 if (!transport) {
zeshuai00726681fb2020-06-03 17:24:38 +080099 return nullptr;
Nobuaki Sukegawa6525f6a2016-02-11 13:58:39 +0900100 }
101
102 StructTypeArgs parsedargs;
103 if (!parse_struct_args(&parsedargs, typeargs)) {
zeshuai00726681fb2020-06-03 17:24:38 +0800104 return nullptr;
Nobuaki Sukegawa6525f6a2016-02-11 13:58:39 +0900105 }
106
107 if (!protocol.prepareDecodeBufferFromTransport(transport.get())) {
zeshuai00726681fb2020-06-03 17:24:38 +0800108 return nullptr;
Nobuaki Sukegawa6525f6a2016-02-11 13:58:39 +0900109 }
110
111 return protocol.readStruct(output_obj, parsedargs.klass, parsedargs.spec);
112}
113}
114}
115}
116
117using namespace apache::thrift::py;
118
119/* -- PYTHON MODULE SETUP STUFF --- */
120
121extern "C" {
122
123static PyObject* encode_binary(PyObject*, PyObject* args) {
124 return encode_impl<BinaryProtocol>(args);
125}
126
127static PyObject* decode_binary(PyObject*, PyObject* args) {
128 return decode_impl<BinaryProtocol>(args);
129}
130
131static PyObject* encode_compact(PyObject*, PyObject* args) {
132 return encode_impl<CompactProtocol>(args);
133}
134
135static PyObject* decode_compact(PyObject*, PyObject* args) {
136 return decode_impl<CompactProtocol>(args);
137}
138
139static PyMethodDef ThriftFastBinaryMethods[] = {
140 {"encode_binary", encode_binary, METH_VARARGS, ""},
141 {"decode_binary", decode_binary, METH_VARARGS, ""},
142 {"encode_compact", encode_compact, METH_VARARGS, ""},
143 {"decode_compact", decode_compact, METH_VARARGS, ""},
zeshuai00726681fb2020-06-03 17:24:38 +0800144 {nullptr, nullptr, 0, nullptr} /* Sentinel */
Nobuaki Sukegawa6525f6a2016-02-11 13:58:39 +0900145};
146
Nobuaki Sukegawa7af189a2016-02-11 16:21:01 +0900147#if PY_MAJOR_VERSION >= 3
148
149static struct PyModuleDef ThriftFastBinaryDef = {PyModuleDef_HEAD_INIT,
150 "thrift.protocol.fastbinary",
zeshuai00726681fb2020-06-03 17:24:38 +0800151 nullptr,
Nobuaki Sukegawa7af189a2016-02-11 16:21:01 +0900152 0,
153 ThriftFastBinaryMethods,
zeshuai00726681fb2020-06-03 17:24:38 +0800154 nullptr,
155 nullptr,
156 nullptr,
157 nullptr};
Nobuaki Sukegawa7af189a2016-02-11 16:21:01 +0900158
zeshuai00726681fb2020-06-03 17:24:38 +0800159#define INITERROR return nullptr;
Nobuaki Sukegawa7af189a2016-02-11 16:21:01 +0900160
161PyObject* PyInit_fastbinary() {
162
163#else
164
Nobuaki Sukegawa6525f6a2016-02-11 13:58:39 +0900165#define INITERROR return;
166
167void initfastbinary() {
168
169 PycString_IMPORT;
zeshuai00726681fb2020-06-03 17:24:38 +0800170 if (PycStringIO == nullptr)
Nobuaki Sukegawa6525f6a2016-02-11 13:58:39 +0900171 INITERROR
172
Nobuaki Sukegawa7af189a2016-02-11 16:21:01 +0900173#endif
174
Nobuaki Sukegawa6525f6a2016-02-11 13:58:39 +0900175#define INIT_INTERN_STRING(value) \
176 do { \
177 INTERN_STRING(value) = PyString_InternFromString(#value); \
178 if (!INTERN_STRING(value)) \
179 INITERROR \
180 } while (0)
181
182 INIT_INTERN_STRING(TFrozenDict);
183 INIT_INTERN_STRING(cstringio_buf);
184 INIT_INTERN_STRING(cstringio_refill);
185 INIT_INTERN_STRING(string_length_limit);
186 INIT_INTERN_STRING(container_length_limit);
187 INIT_INTERN_STRING(trans);
188#undef INIT_INTERN_STRING
189
190 PyObject* module =
Nobuaki Sukegawa7af189a2016-02-11 16:21:01 +0900191#if PY_MAJOR_VERSION >= 3
192 PyModule_Create(&ThriftFastBinaryDef);
193#else
Nobuaki Sukegawa6525f6a2016-02-11 13:58:39 +0900194 Py_InitModule("thrift.protocol.fastbinary", ThriftFastBinaryMethods);
Nobuaki Sukegawa7af189a2016-02-11 16:21:01 +0900195#endif
zeshuai00726681fb2020-06-03 17:24:38 +0800196 if (module == nullptr)
Nobuaki Sukegawa6525f6a2016-02-11 13:58:39 +0900197 INITERROR;
198
Nobuaki Sukegawa7af189a2016-02-11 16:21:01 +0900199#if PY_MAJOR_VERSION >= 3
200 return module;
201#endif
Nobuaki Sukegawa6525f6a2016-02-11 13:58:39 +0900202}
203}