1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
|
# Note this implementation is more strict than necessary to demonstrate
# minimum restrictions on types allowed in dictionaries.
def dump(data):
if type(data) is long or type(data) is int:
out = str(data)
return '%d:%s#' % (len(out), out)
elif type(data) is float:
out = '%f' % data
return '%d:%s^' % (len(out), out)
elif type(data) is str:
return '%d:' % len(data) + data + ','
elif type(data) is dict:
return dump_dict(data)
elif type(data) is list:
return dump_list(data)
elif data == None:
return '0:~'
elif type(data) is bool:
out = repr(data).lower()
return '%d:%s!' % (len(out), out)
else:
assert False, "Can't serialize stuff that's %s." % type(data)
def parse(data):
payload, payload_type, remain = parse_payload(data)
if payload_type == '#':
value = int(payload)
elif payload_type == '}':
value = parse_dict(payload)
elif payload_type == ']':
value = parse_list(payload)
elif payload_type == '!':
value = payload == 'true'
elif payload_type == '^':
value = float(payload)
elif payload_type == '~':
assert len(payload) == 0, "Payload must be 0 length for null."
value = None
elif payload_type == ',':
value = payload
else:
assert False, "Invalid payload type: %r" % payload_type
return value, remain
def parse_payload(data):
assert data, "Invalid data to parse, it's empty."
length, extra = data.split(':', 1)
length = int(length)
payload, extra = extra[:length], extra[length:]
assert extra, "No payload type: %r, %r" % (payload, extra)
payload_type, remain = extra[0], extra[1:]
assert len(payload) == length, "Data is wrong length %d vs %d" % (length, len(payload))
return payload, payload_type, remain
def parse_list(data):
if len(data) == 0: return []
result = []
value, extra = parse(data)
result.append(value)
while extra:
value, extra = parse(extra)
result.append(value)
return result
def parse_pair(data):
key, extra = parse(data)
assert extra, "Unbalanced dictionary store."
value, extra = parse(extra)
return key, value, extra
def parse_dict(data):
if len(data) == 0: return {}
key, value, extra = parse_pair(data)
assert type(key) is str, "Keys can only be strings."
result = {key: value}
while extra:
key, value, extra = parse_pair(extra)
result[key] = value
return result
def dump_dict(data):
result = []
for k,v in data.items():
result.append(dump(str(k)))
result.append(dump(v))
payload = ''.join(result)
return '%d:' % len(payload) + payload + '}'
def dump_list(data):
result = []
for i in data:
result.append(dump(i))
payload = ''.join(result)
return '%d:' % len(payload) + payload + ']'
|