Skip to content

Commit

Permalink
Fallback to Python parsing if Cython module unavailable
Browse files Browse the repository at this point in the history
Rename _parser to c_parser
  • Loading branch information
medeor413 committed Apr 25, 2017
1 parent 0bfd5ca commit a1ffe76
Show file tree
Hide file tree
Showing 3 changed files with 109 additions and 76 deletions.
2 changes: 1 addition & 1 deletion build_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@

setup(
name = "StarryPy Packet Parser",
ext_modules = cythonize('_parser.pyx')
ext_modules = cythonize('c_parser.pyx')
)
File renamed without changes.
183 changes: 108 additions & 75 deletions data_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,20 @@
import functools
import io
import struct
import _parser
from collections import OrderedDict
from io import BytesIO
try:
import c_parser
use_c_parser = True
print("Using Cython parser")
except ImportError:
use_c_parser = False
print("Falling back to Python parser")

from utilities import DotDict, WarpType, WarpWorldType



#
## Packet Helpers
#
Expand Down Expand Up @@ -169,20 +176,23 @@ def _build(cls, obj, ctx: OrderedDotDict):


class VLQ(Struct):
@classmethod
# def _parse(cls, stream: BytesIO, ctx: OrderedDict) -> int:
# value = 0
# while True:
# try:
# tmp = ord(stream.read(1))
# value = (value << 7) | (tmp & 0x7f)
# if tmp & 0x80 == 0:
# break
# except TypeError: # If the stream is empty.
# break
# return value
def _parse(cls, stream: BytesIO, ctx: OrderedDict) -> int:
return _parser.parse_vlq(stream)
if use_c_parser:
@classmethod
def _parse(cls, stream: BytesIO, ctx: OrderedDict) -> int:
return c_parser.parse_vlq(stream)
else:
@classmethod
def _parse(cls, stream: BytesIO, ctx: OrderedDict) -> int:
value = 0
while True:
try:
tmp = ord(stream.read(1))
value = (value << 7) | (tmp & 0x7f)
if tmp & 0x80 == 0:
break
except TypeError: # If the stream is empty.
break
return value

@classmethod
def _build(cls, obj, ctx):
Expand All @@ -204,15 +214,18 @@ def _build(cls, obj, ctx):


class SignedVLQ(Struct):
@classmethod
# def _parse(cls, stream: BytesIO, ctx: OrderedDict):
# v = VLQ.parse(stream, ctx)
# if (v & 1) == 0x00:
# return v >> 1
# else:
# return -((v >> 1) + 1)
def _parse(cls, stream: BytesIO, ctx: OrderedDict):
return _parser.parse_svlq(stream)
if use_c_parser:
@classmethod
def _parse(cls, stream: BytesIO, ctx: OrderedDict):
return c_parser.parse_svlq(stream)
else:
@classmethod
def _parse(cls, stream: BytesIO, ctx: OrderedDict):
v = VLQ.parse(stream, ctx)
if (v & 1) == 0x00:
return v >> 1
else:
return -((v >> 1) + 1)

@classmethod
def _build(cls, obj, ctx):
Expand Down Expand Up @@ -292,26 +305,34 @@ def _build(cls, obj, ctx: OrderedDotDict):


class StarByteArray(Struct):
@classmethod
def _parse(cls, stream: BytesIO, ctx: OrderedDict):
# length = VLQ.parse(stream, ctx)
# return stream.read(length)
return _parser.parse_starbytearray(stream)
if use_c_parser:
@classmethod
def _parse(cls, stream: BytesIO, ctx: OrderedDict):
return c_parser.parse_starbytearray(stream)
else:
@classmethod
def _parse(cls, stream: BytesIO, ctx: OrderedDict):
length = VLQ.parse(stream, ctx)
return stream.read(length)

@classmethod
def _build(cls, obj, ctx: OrderedDotDict):
return VLQ.build(len(obj), ctx) + obj


class StarString(Struct):
@classmethod
def _parse(cls, stream: BytesIO, ctx: OrderedDict):
# data = StarByteArray.parse(stream, ctx)
# try:
# return data.decode("utf-8")
# except UnicodeDecodeError:
# return data
return _parser.parse_starstring(stream)
if use_c_parser:
@classmethod
def _parse(cls, stream: BytesIO, ctx: OrderedDict):
return c_parser.parse_starstring(stream)
else:
@classmethod
def _parse(cls, stream: BytesIO, ctx: OrderedDict):
data = StarByteArray.parse(stream, ctx)
try:
return data.decode("utf-8")
except UnicodeDecodeError:
return data

@classmethod
def _build(cls, obj, ctx: OrderedDotDict):
Expand Down Expand Up @@ -361,50 +382,62 @@ def _build(cls, obj, ctx: OrderedDotDict):


class VariantVariant(Struct):
@classmethod
def _parse(cls, stream: BytesIO, ctx: OrderedDict):
# l = VLQ.parse(stream, ctx)
# return [Variant.parse(stream, ctx) for _ in range(l)]
return _parser.parse_variant_variant(stream)
if use_c_parser:
@classmethod
def _parse(cls, stream: BytesIO, ctx: OrderedDict):
return c_parser.parse_variant_variant(stream)
else:
@classmethod
def _parse(cls, stream: BytesIO, ctx: OrderedDict):
l = VLQ.parse(stream, ctx)
return [Variant.parse(stream, ctx) for _ in range(l)]


class DictVariant(Struct):
@classmethod
def _parse(cls, stream: BytesIO, ctx: OrderedDict):
# l = VLQ.parse(stream, ctx)
# c = {}
# for _ in range(l):
# key = StarString.parse(stream, ctx)
# value = Variant.parse(stream, ctx)
# if isinstance(value, bytes):
# try:
# value = value.decode('utf-8')
# except UnicodeDecodeError:
# pass
# c[key] = value
# return c
return _parser.parse_dict_variant(stream)
if use_c_parser:
@classmethod
def _parse(cls, stream: BytesIO, ctx: OrderedDict):
return c_parser.parse_dict_variant(stream)
else:
@classmethod
def _parse(cls, stream: BytesIO, ctx: OrderedDict):
l = VLQ.parse(stream, ctx)
c = {}
for _ in range(l):
key = StarString.parse(stream, ctx)
value = Variant.parse(stream, ctx)
if isinstance(value, bytes):
try:
value = value.decode('utf-8')
except UnicodeDecodeError:
pass
c[key] = value
return c


class Variant(Struct):
@classmethod
def _parse(cls, stream: BytesIO, ctx: OrderedDict):
# x = Byte.parse(stream, ctx)
# if x == 1:
# return None
# elif x == 2:
# return BDouble.parse(stream, ctx)
# elif x == 3:
# return Flag.parse(stream, ctx)
# elif x == 4:
# return SignedVLQ.parse(stream, ctx)
# elif x == 5:
# return StarString.parse(stream, ctx)
# elif x == 6:
# return VariantVariant.parse(stream, ctx)
# elif x == 7:
# return DictVariant.parse(stream, ctx)
return _parser.parse_variant(stream)
if use_c_parser:
@classmethod
def _parse(cls, stream: BytesIO, ctx: OrderedDict):
return c_parser.parse_variant(stream)
else:
@classmethod
def _parse(cls, stream: BytesIO, ctx: OrderedDict):
x = Byte.parse(stream, ctx)
if x == 1:
return None
elif x == 2:
return BDouble.parse(stream, ctx)
elif x == 3:
return Flag.parse(stream, ctx)
elif x == 4:
return SignedVLQ.parse(stream, ctx)
elif x == 5:
return StarString.parse(stream, ctx)
elif x == 6:
return VariantVariant.parse(stream, ctx)
elif x == 7:
return DictVariant.parse(stream, ctx)


class StringSet(Struct):
Expand Down

0 comments on commit a1ffe76

Please sign in to comment.