Skip to content

Commit 32dd9c7

Browse files
authored
Merge pull request #3 from ozkriff/option
Add 'Option' type support
2 parents 2727e3c + 88a5b12 commit 32dd9c7

File tree

2 files changed

+79
-0
lines changed

2 files changed

+79
-0
lines changed

exonum/datatypes.py

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -380,6 +380,70 @@ def Vec(T):
380380
raise NotSupported()
381381

382382

383+
@six.python_2_unicode_compatible
384+
class Opt(ExonumSegment):
385+
def __init__(self, *val):
386+
if len(val) == 0:
387+
self._set_order()
388+
return
389+
390+
val = val[0]
391+
if val:
392+
if isinstance(val, self.T):
393+
self.val = val
394+
else:
395+
self.val = self.T(val)
396+
else:
397+
self.val = None
398+
399+
def count(self):
400+
return 1 if self.val else 0
401+
402+
def __str__(self):
403+
v = self.val
404+
repr = "{}".format(v) if v else "None"
405+
return "{} [{}]".format(self.__class__.__name__, ", ".join(repr))
406+
407+
@classmethod
408+
def read_buffer(cls, buf, offset=0, cnt=0):
409+
dbg("reading Opt of sz {}".format(cnt))
410+
if cnt == 1:
411+
t = cls.T.read(buf, offset=offset)
412+
dbg("read {} at offset {}".format(t, offset))
413+
return cls(t)
414+
else:
415+
assert cnt == 0, "One argument expected"
416+
return cls(None)
417+
418+
def write(self, buf, offset):
419+
dbg(
420+
"writing Opt ({}) of sz {} at offset {}".format(
421+
self.T.__name__, self.count(), offset
422+
)
423+
)
424+
buf[offset : offset + self.sz] = struct.pack(self.fmt, len(buf), self.count())
425+
self.extend_buffer(buf)
426+
427+
def extend_buffer(self, buf):
428+
offset = len(buf)
429+
buf += bytearray(self.count() * self.T.sz)
430+
if self.val:
431+
self.val.write(buf, offset)
432+
offset += self.T.sz
433+
434+
def plain(self):
435+
if self.val:
436+
return self.val.plain()
437+
else:
438+
return None
439+
440+
441+
def Option(T):
442+
if issubclass(T, ExonumField):
443+
return type("Option<{}>".format(T.__name__), (Opt,), {"T": T})()
444+
raise NotSupported()
445+
446+
383447
class ExonumBase(ExonumSegment):
384448
def count(self):
385449
return self.cnt

tests/test_serde.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
Str,
99
Uuid,
1010
Vec,
11+
Option,
1112
i64,
1213
u8,
1314
u16,
@@ -149,3 +150,17 @@ class D(with_metaclass(EncodingStruct)):
149150
b = d.to_bytes()
150151
d2 = D.read_buffer(b)
151152
assert d.d == d2.d
153+
154+
155+
def test_option():
156+
class O(with_metaclass(EncodingStruct)):
157+
a = Option(Str)
158+
b = Option(Str)
159+
c = Option(i64)
160+
d = Option(u8)
161+
162+
o = O(a=None, b="abc", c=1, d=None)
163+
164+
b = o.to_bytes()
165+
o2 = O.read_buffer(b)
166+
assert o == o2

0 commit comments

Comments
 (0)