summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--tests/test_parse.py5
-rw-r--r--viewstate/parse.py246
2 files changed, 125 insertions, 126 deletions
diff --git a/tests/test_parse.py b/tests/test_parse.py
index 570ab96..62f0f23 100644
--- a/tests/test_parse.py
+++ b/tests/test_parse.py
@@ -6,7 +6,7 @@ from os.path import join
from viewstate import *
-class TestNewParse(object):
+class TestParse(object):
def test_const_value(self):
vs = ViewState(raw=b'\xff\x01\x67')
assert vs.decode() is True
@@ -20,9 +20,6 @@ class TestNewParse(object):
vs = ViewState(raw=b'\xff\x01\x05' + bytes([len(s)]) + s.encode())
assert vs.decode() == s
-
-@pytest.mark.skip()
-class TestParse(object):
def test_simple_dict(self):
vs = ViewState(raw=b'\xff\x01\x18\x02\x05\x01a\x05\x01b\x05\x01c\x05\x01d')
assert vs.decode() == {'a': 'b', 'c': 'd'}
diff --git a/viewstate/parse.py b/viewstate/parse.py
index 99fe677..75b82a5 100644
--- a/viewstate/parse.py
+++ b/viewstate/parse.py
@@ -81,6 +81,7 @@ class String(Parser):
s = remain[:n]
return s.decode(), remain[n:]
+
class Enum(Parser):
marker = 0x0b
@@ -93,6 +94,7 @@ class Enum(Parser):
final = 'Enum: {}, val: {}'.format(enum, val)
return final, remain
+
class Color(Parser):
marker = 0x0a
@@ -102,145 +104,145 @@ class Color(Parser):
# Originally reported in https://github.com/yuvadm/viewstate/issues/2
return 'Color: unknown', b[2:]
+
class Pair(Parser):
marker = 0x0f
def parse(self, b):
- first, remain = parse(b)
- second, remain = parse(remain)
+ first, remain = Parser().parse(b)
+ second, remain = Parser().parse(remain)
return (first, second), remain
-def parse_triplet(b):
- first, remain = parse(b)
- second, remain = parse(remain)
- third, remain = parse(remain)
- return (first, second, third), remain
-def parse_datetime(b):
- print([x for x in b[:8]])
- return datetime(2000, 1, 1), b[8:]
+class Triplet(Parser):
+ marker = 0x10
-def parse_unit(b):
- print([x for x in b[:12]])
- return 'Unit: ', b[12:]
+ def parse(self, b):
+ first, remain = Parser().parse(b)
+ second, remain = Parser().parse(remain)
+ third, remain = Parser().parse(remain)
+ return (first, second, third), remain
-def parse_rgba(b):
- return 'RGBA({},{},{},{})'.format(*b[:4]), b[4:]
-def parse_str_array(b):
- n, remain = parse_int(b)
- l = []
- for _ in range(n):
- if not remain[0]:
- val, remain = '', remain[1:]
- else:
- val, remain = parse_string(remain)
- l.append(val)
- return l, remain
+class Datetime(Parser):
+ marker = 0x06
+
+ def parse(self, b):
+ #print([x for x in b[:8]])
+ return datetime(2000, 1, 1), b[8:]
+
+
+class Unit(Parser):
+ marker = 0x1b
+
+ def parse(self, b):
+ #print([x for x in b[:12]])
+ return 'Unit: ', b[12:]
+
+
+class RGBA(Parser):
+ marker = 0x09
+
+ def parse(self, b):
+ return 'RGBA({},{},{},{})'.format(*b[:4]), b[4:]
+
+
+class StringArray(Parser):
+ marker = 0x15
+
+ def parse(self, b):
+ n, remain = Integer().parse(b)
+ l = []
+ for _ in range(n):
+ if not remain[0]:
+ val, remain = '', remain[1:]
+ else:
+ val, remain = String().parse(remain)
+ l.append(val)
+ return l, remain
+
-def parse_array(b):
- n, remain = parse_int(b)
- l = []
- for _ in range(n):
- val, remain = parse(remain)
- l.append(val)
- return l, remain
+class Array(Parser):
+ marker = 0x16
+
+ def parse(self, b):
+ n, remain = Integer().parse(b)
+ l = []
+ for _ in range(n):
+ val, remain = Parser().parse(remain)
+ l.append(val)
+ return l, remain
-def parse_stringref(b):
- val, remain = parse_int(b)
- return 'Stringref #{}'.format(val), remain
-def parse_formatted_string(b):
- if b[0] == 0x29:
- s1, remain = parse_string(b[1:])
- s2, remain = parse_string(remain)
- return 'Formatted string: {} {}'.format(s2, s1), remain
- elif b[0] == 0x2b:
- i, remain = parse_int(b[1:])
- s, remain = parse_string(remain)
- return 'Formatted string: {} type ref {}'.format(s, i), remain
- else:
- raise ViewStateException('Unknown formatted string type marker {}'.format(b[:20]))
+class StringRef(Parser):
+ marker = 0x1f
-def parse_sparse_array(b):
- type, remain = parse_type(b)
- length, remain = parse_int(remain)
- n, remain = parse_int(remain)
- l = [None] * length
- for _ in range(n):
- idx, remain = parse_int(remain)
- val, remain = parse(remain)
- l[idx] = val
- return l, remain
+ def parse(self, b):
+ val, remain = Integer().parse(b)
+ return 'Stringref #{}'.format(val), remain
-def parse_dict(b):
- n = b[0]
- d = {}
- remain = b[1:]
- for _ in range(n):
- k, remain = parse(remain)
- v, remain = parse(remain)
- d[k] = v
- return d, remain
-def parse_type(b):
- if b[0] in (0x29, 0x2a):
- return parse_string(b[1:])
- elif b[0] == 0x2b:
- return parse_int(b[1:])
- else:
- raise ViewStateException('Unknown type flag at {} bytes {}'.format(len(b), b[:20]))
+class FormattedString(Parser):
+ marker = 0x28
-def parse_typed_array(b):
- typeval, remain = parse_type(b)
- n, remain = parse_int(remain)
- l = []
- for _ in range(n):
- val, remain = parse(remain)
- l.append(val)
- return l, remain
+ def parse(self, b):
+ if b[0] == 0x29:
+ s1, remain = String().parse(b[1:])
+ s2, remain = String().parse(remain)
+ return 'Formatted string: {} {}'.format(s2, s1), remain
+ elif b[0] == 0x2b:
+ i, remain = Integer().parse(b[1:])
+ s, remain = String().parse(remain)
+ return 'Formatted string: {} type ref {}'.format(s, i), remain
+ else:
+ raise ViewStateException('Unknown formatted string type marker {}'.format(b[:20]))
+
+
+class SparseArray(Parser):
+ marker = 0x3c
+
+ def parse(self, b):
+ type, remain = Type().parse(b)
+ length, remain = Integer().parse(remain)
+ n, remain = Integer().parse(remain)
+ l = [None] * length
+ for _ in range(n):
+ idx, remain = Integer().parse(remain)
+ val, remain = Parser().parse(remain)
+ l[idx] = val
+ return l, remain
-def parse(b):
- if not b:
- return None
- else:
- assert type(b) == bytes().__class__
- if 100 <= b[0] <= 104:
- return parse_const(b[0]), b[1:]
- elif b[0] == 0x02:
- return parse_int(b[1:])
- elif b[0] in (0x05, 0x1e):
- return parse_string(b[1:])
- elif b[0] == 0x06:
- return parse_datetime(b[1:])
- elif b[0] == 0x09:
- return parse_rgba(b[1:])
- elif b[0] == 0x10:
- return parse_triplet(b[1:])
- elif b[0] == 0x0a:
- return parse_color(b[1:])
- elif b[0] == 0x0b:
- return parse_enum(b[1:])
- elif b[0] == 0x0f:
- return parse_pair(b[1:])
- elif b[0] == 0x14:
- return parse_typed_array(b[1:])
- elif b[0] == 0x15:
- return parse_str_array(b[1:])
- elif b[0] == 0x16:
- return parse_array(b[1:])
- elif b[0] == 0x18:
- return parse_dict(b[1:])
- elif b[0] == 0x1b:
- return parse_unit(b[1:])
- elif b[0] == 0x1f:
- return parse_stringref(b[1:])
- elif b[0] == 0x28:
- return parse_formatted_string(b[1:])
- elif b[0] == 0x3c:
- return parse_sparse_array(b[1:])
- else:
- raise ViewStateException('Unable to parse remainder of {} bytes {}'.format(len(b), b[:20]))
- return b, bytes()
+class Dict(Parser):
+ marker = 0x18
+ def parse(self, b):
+ n = b[0]
+ d = {}
+ remain = b[1:]
+ for _ in range(n):
+ k, remain = Parser().parse(remain)
+ v, remain = Parser().parse(remain)
+ d[k] = v
+ return d, remain
+
+class Type(Parser):
+ def parse(self, b):
+ if b[0] in (0x29, 0x2a):
+ return String().parse(b[1:])
+ elif b[0] == 0x2b:
+ return Integer().parse(b[1:])
+ else:
+ raise ViewStateException('Unknown type flag at {} bytes {}'.format(len(b), b[:20]))
+
+class TypedArray(Parser):
+ marker = 0x14
+
+ def parse(self, b):
+ typeval, remain = Type().parse(b)
+ n, remain = Integer().parse(remain)
+ l = []
+ for _ in range(n):
+ val, remain = Parser().parse(remain)
+ l.append(val)
+ return l, remain