-
Notifications
You must be signed in to change notification settings - Fork 9
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added parsing request as cython extension
- Loading branch information
1 parent
67ecb58
commit b4f3a96
Showing
15 changed files
with
555 additions
and
23 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
[submodule "third_party/msgpuck"] | ||
path = third_party/msgpuck | ||
url = https://github.com/tarantool/msgpuck.git |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
from libc.stdint cimport uint32_t, uint64_t, int64_t | ||
|
||
cdef extern from "../../third_party/msgpuck/msgpuck.h": | ||
cdef enum mp_type: | ||
MP_NIL = 0 | ||
MP_UINT | ||
MP_INT | ||
MP_STR | ||
MP_BIN | ||
MP_ARRAY | ||
MP_MAP | ||
MP_BOOL | ||
MP_FLOAT | ||
MP_DOUBLE | ||
MP_EXT | ||
|
||
cdef mp_type mp_typeof(const char c); | ||
|
||
cdef uint32_t mp_decode_array(const char **data); | ||
|
||
cdef uint32_t mp_decode_map(const char **data); | ||
|
||
cdef uint64_t mp_decode_uint(const char **data); | ||
|
||
cdef int64_t mp_decode_int(const char **data); | ||
|
||
cdef float mp_decode_float(const char **data); | ||
|
||
cdef double mp_decode_double(const char **data); | ||
|
||
cdef uint32_t mp_decode_strl(const char **data); | ||
cdef const char *mp_decode_str(const char **data, uint32_t *len); | ||
|
||
cdef uint32_t mp_decode_binl(const char **data); | ||
cdef const char *mp_decode_bin(const char **data, uint32_t *len); | ||
|
||
cdef uint32_t mp_decode_strbinl(const char **data); | ||
cdef const char *mp_decode_strbin(const char **data, uint32_t *len); | ||
|
||
cdef void mp_decode_nil(const char **data); | ||
cdef bint mp_decode_bool(const char **data); | ||
|
||
cdef void mp_next(const char **data); | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
cdef enum tnt_header_key: | ||
TP_CODE = 0x00 | ||
TP_SYNC = 0x01 | ||
TP_SERVER_ID = 0x02 | ||
TP_LSN = 0x03 | ||
TP_TIMESTAMP = 0x04 | ||
TP_SCHEMA_ID = 0x05 | ||
|
||
|
||
cdef enum tnt_body_key_t: | ||
TP_SPACE = 0x10 | ||
TP_INDEX = 0x11 | ||
TP_LIMIT = 0x12 | ||
TP_OFFSET = 0x13 | ||
TP_ITERATOR = 0x14 | ||
TP_KEY = 0x20 | ||
TP_TUPLE = 0x21 | ||
TP_FUNCTION = 0x22 | ||
TP_USERNAME = 0x23 | ||
TP_EXPRESSION = 0x27 | ||
TP_OPERATIONS = 0x28 | ||
|
||
|
||
cdef enum tnt_response_key_t: | ||
TP_DATA = 0x30 | ||
TP_ERROR = 0x31 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,183 @@ | ||
from libc.stdint cimport uint32_t, uint64_t, int64_t | ||
|
||
cimport cmsgpuck as mp | ||
cimport const as tnt_const | ||
|
||
from response cimport TntResponse | ||
|
||
|
||
cdef _decode_obj(const char** p): | ||
cdef: | ||
uint32_t i | ||
mp.mp_type obj_type | ||
|
||
const char* s | ||
uint32_t s_len | ||
|
||
uint32_t arr_size | ||
list arr | ||
|
||
uint32_t map_size | ||
dict map | ||
mp.mp_type map_key_type | ||
const char* map_key_str | ||
uint32_t map_key_len | ||
object map_key | ||
|
||
|
||
obj_type = mp.mp_typeof(p[0][0]) | ||
if obj_type == mp.MP_UINT: | ||
return mp.mp_decode_uint(p) | ||
elif obj_type == mp.MP_INT: | ||
return mp.mp_decode_int(p) | ||
elif obj_type == mp.MP_STR: | ||
s = NULL | ||
s_len = 0 | ||
s = mp.mp_decode_str(p, &s_len) | ||
return s[:s_len].decode() | ||
elif obj_type == mp.MP_BIN: | ||
s = NULL | ||
s_len = 0 | ||
s = mp.mp_decode_bin(p, &s_len) | ||
return <bytes>s | ||
elif obj_type == mp.MP_BOOL: | ||
return mp.mp_decode_bool(p) | ||
elif obj_type == mp.MP_FLOAT: | ||
return mp.mp_decode_float(p) | ||
elif obj_type == mp.MP_DOUBLE: | ||
return mp.mp_decode_double(p) | ||
elif obj_type == mp.MP_ARRAY: | ||
arr_size = mp.mp_decode_array(p) | ||
value = [] | ||
for i in range(arr_size): | ||
value.append(_decode_obj(p)) | ||
return value | ||
elif obj_type == mp.MP_MAP: | ||
map = {} | ||
map_size = mp.mp_decode_map(p) | ||
for i in range(map_size): | ||
map_key_type = mp.mp_typeof(p[0][0]) | ||
if map_key_type == mp.MP_STR: | ||
map_key_len = 0 | ||
map_key_str = mp.mp_decode_str(p, &map_key_len) | ||
map_key = <object>(map_key_str[:map_key_len].decode()) | ||
elif map_key_type == mp.MP_UINT: | ||
map_key = <object>mp.mp_decode_uint(p) | ||
elif map_key_type == mp.MP_INT: | ||
map_key = <object>mp.mp_decode_int(p) | ||
else: | ||
mp.mp_next(p) # skip current key | ||
mp.mp_next(p) # skip value | ||
print('Unexpected key type in map: {}'.format(map_key_type)) | ||
|
||
map[map_key] = _decode_obj(p) | ||
|
||
return map | ||
elif obj_type == mp.MP_NIL: | ||
mp.mp_next(p) | ||
return None | ||
else: | ||
print('Unexpected obj type: {}'.format(obj_type)) | ||
mp.mp_next(p) | ||
return None | ||
|
||
|
||
cdef _cresponse_parse_body_data(const char* b): | ||
cdef: | ||
uint32_t size | ||
uint32_t tuple_size | ||
list tuples | ||
uint32_t i, k | ||
|
||
size = mp.mp_decode_array(&b) | ||
tuples = [] | ||
for i in range(size): | ||
tuple_size = mp.mp_decode_array(&b) | ||
t = [] | ||
for k in range(tuple_size): | ||
t.append(_decode_obj(&b)) | ||
tuples.append(t) | ||
|
||
return tuples | ||
|
||
|
||
cdef cresponse_parse(bytes buf): | ||
cdef: | ||
const char* b | ||
uint32_t size | ||
uint32_t key | ||
uint32_t s_len | ||
const char* s | ||
TntResponse resp | ||
|
||
buf_len = len(buf) | ||
begin = <const char*>buf | ||
b = <const char*>buf | ||
# if mp.mp_typeof(b[0]) != mp.MP_MAP: | ||
# raise TypeError('Response header must be a MP_MAP') | ||
|
||
resp = TntResponse() | ||
|
||
# parsing header | ||
size = mp.mp_decode_map(&b) | ||
for _ in range(size): | ||
# if mp.mp_typeof(b[0]) != mp.MP_UINT: | ||
# raise TypeError('Header key must be a MP_UINT') | ||
|
||
key = mp.mp_decode_uint(&b) | ||
if key == tnt_const.TP_CODE: | ||
# if mp.mp_typeof(b[0]) != mp.MP_UINT: | ||
# raise TypeError('code type must be a MP_UINT') | ||
|
||
resp.code = mp.mp_decode_uint(&b) | ||
resp.code &= 0x7FFF | ||
elif key == tnt_const.TP_SYNC: | ||
# if mp.mp_typeof(b[0]) != mp.MP_UINT: | ||
# raise TypeError('sync type must be a MP_UINT') | ||
|
||
resp.sync = mp.mp_decode_uint(&b) | ||
elif key == tnt_const.TP_SCHEMA_ID: | ||
# if mp.mp_typeof(b[0]) != mp.MP_UINT: | ||
# raise TypeError('schema_id type must be a MP_UINT') | ||
|
||
resp.schema_id = mp.mp_decode_uint(&b) | ||
else: | ||
print('Unknown argument in header. Skipping.') | ||
mp.mp_next(&b) | ||
|
||
|
||
# parsing body | ||
if b == &begin[buf_len]: | ||
# buffer exceeded | ||
return resp | ||
|
||
# if mp.mp_typeof(b[0]) != mp.MP_MAP: | ||
# raise TypeError('Response body must be a MP_MAP') | ||
|
||
size = mp.mp_decode_map(&b) | ||
for _ in range(size): | ||
# if mp.mp_typeof(b[0]) != mp.MP_UINT: | ||
# raise TypeError('Header key must be a MP_UINT') | ||
|
||
key = mp.mp_decode_uint(&b) | ||
if key == tnt_const.TP_ERROR: | ||
# if mp.mp_typeof(b[0]) != mp.MP_STR: | ||
# raise TypeError('errstr type must be a MP_STR') | ||
|
||
s = NULL | ||
s_len = 0 | ||
s = mp.mp_decode_str(&b, &s_len) | ||
resp.errmsg = s[:s_len].decode() | ||
elif key == tnt_const.TP_DATA: | ||
if mp.mp_typeof(b[0]) != mp.MP_ARRAY: | ||
raise TypeError('body data type must be a MP_ARRAY') | ||
resp.body = _cresponse_parse_body_data(b) | ||
|
||
return resp | ||
|
||
|
||
|
||
|
||
cpdef response_parse(bytes buf): | ||
res = cresponse_parse(buf) | ||
return res |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
from libc.stdint cimport uint64_t | ||
|
||
cdef class TntResponse: | ||
cdef: | ||
int code | ||
uint64_t sync | ||
int schema_id | ||
str errmsg | ||
list body | ||
|
||
cdef inline has_schema_id(self): | ||
return self.schema_id != -1 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
cdef class TntResponse: | ||
def __cinit__(self): | ||
self.code = 0 | ||
self.sync = 0 | ||
self.schema_id = -1 | ||
self.errmsg = None | ||
self.body = None | ||
|
||
def __repr__(self): | ||
return '<TntResponse: code={}, sync={}>'.format(self.code, self.sync) |
Oops, something went wrong.