@@ -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+
383447class ExonumBase (ExonumSegment ):
384448 def count (self ):
385449 return self .cnt
0 commit comments