THRIFT-3612 Add Python C extension for compact protocol
Client: Python
Patch: Nobuaki Sukegawa
This closes #844
diff --git a/lib/py/src/ext/compact.cpp b/lib/py/src/ext/compact.cpp
new file mode 100644
index 0000000..15a99a0
--- /dev/null
+++ b/lib/py/src/ext/compact.cpp
@@ -0,0 +1,107 @@
+/*
+ * 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.
+ */
+
+#include "ext/compact.h"
+
+namespace apache {
+namespace thrift {
+namespace py {
+
+const uint8_t CompactProtocol::TTypeToCType[] = {
+ CT_STOP, // T_STOP
+ 0, // unused
+ CT_BOOLEAN_TRUE, // T_BOOL
+ CT_BYTE, // T_BYTE
+ CT_DOUBLE, // T_DOUBLE
+ 0, // unused
+ CT_I16, // T_I16
+ 0, // unused
+ CT_I32, // T_I32
+ 0, // unused
+ CT_I64, // T_I64
+ CT_BINARY, // T_STRING
+ CT_STRUCT, // T_STRUCT
+ CT_MAP, // T_MAP
+ CT_SET, // T_SET
+ CT_LIST, // T_LIST
+};
+
+bool CompactProtocol::readFieldBegin(TType& type, int16_t& tag) {
+ uint8_t b;
+ if (!readByte(b)) {
+ return false;
+ }
+ uint8_t ctype = b & 0xf;
+ type = getTType(ctype);
+ if (type == -1) {
+ return false;
+ } else if (type == T_STOP) {
+ tag = 0;
+ return true;
+ }
+ uint8_t diff = (b & 0xf0) >> 4;
+ if (diff) {
+ tag = readTags_.top() + diff;
+ } else if (!readI16(tag)) {
+ readTags_.top() = -1;
+ return false;
+ }
+ if (ctype == CT_BOOLEAN_FALSE || ctype == CT_BOOLEAN_TRUE) {
+ readBool_.exists = true;
+ readBool_.value = ctype == CT_BOOLEAN_TRUE;
+ }
+ readTags_.top() = tag;
+ return true;
+}
+
+TType CompactProtocol::getTType(uint8_t type) {
+ switch (type) {
+ case T_STOP:
+ return T_STOP;
+ case CT_BOOLEAN_FALSE:
+ case CT_BOOLEAN_TRUE:
+ return T_BOOL;
+ case CT_BYTE:
+ return T_BYTE;
+ case CT_I16:
+ return T_I16;
+ case CT_I32:
+ return T_I32;
+ case CT_I64:
+ return T_I64;
+ case CT_DOUBLE:
+ return T_DOUBLE;
+ case CT_BINARY:
+ return T_STRING;
+ case CT_LIST:
+ return T_LIST;
+ case CT_SET:
+ return T_SET;
+ case CT_MAP:
+ return T_MAP;
+ case CT_STRUCT:
+ return T_STRUCT;
+ default:
+ PyErr_Format(PyExc_TypeError, "don't know what type: %d", type);
+ return static_cast<TType>(-1);
+ }
+}
+}
+}
+}