Skip to content

Commit 5692fb5

Browse files
committed
fields, structure: Allow conditional SubstructureFields.
TODO: Write unit tests to completely verify fix. Fixes #25
1 parent acdfb85 commit 5692fb5

File tree

2 files changed

+16
-6
lines changed

2 files changed

+16
-6
lines changed

suitcase/fields.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -612,9 +612,9 @@ def pack(self, stream):
612612
if self.condition(self._parent):
613613
self.field.pack(stream)
614614

615-
def unpack(self, data):
615+
def unpack(self, data, **kwargs):
616616
if self.condition(self._parent):
617-
self.field.unpack(data)
617+
return self.field.unpack(data, **kwargs)
618618

619619
def getval(self):
620620
return self.field.getval()

suitcase/structure.py

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@
88
import six
99
from suitcase.exceptions import SuitcaseException, \
1010
SuitcasePackException, SuitcaseParseError
11-
from suitcase.fields import FieldPlaceholder, CRCField, SubstructureField
11+
from suitcase.fields import FieldPlaceholder, CRCField, SubstructureField, \
12+
ConditionalField
1213
from six import BytesIO
1314

1415

@@ -85,6 +86,11 @@ def unpack_stream(self, stream):
8586
logic present for dealing with checksum fields.
8687
8788
"""
89+
def is_substructure(field):
90+
return isinstance(field, SubstructureField) or \
91+
isinstance(field, ConditionalField) and \
92+
isinstance(field.field, SubstructureField)
93+
8894
crc_fields = []
8995
greedy_field = None
9096
# go through the fields from first to last. If we hit a greedy
@@ -93,11 +99,15 @@ def unpack_stream(self, stream):
9399
if isinstance(field, CRCField):
94100
crc_fields.append((field, stream.tell()))
95101
length = field.bytes_required
96-
if isinstance(field, SubstructureField):
102+
if is_substructure(field):
97103
remaining_data = stream.getvalue()[stream.tell():]
98104
returned_stream = field.unpack(remaining_data, trailing=True)
105+
if returned_stream is not None:
106+
consumed = returned_stream.tell()
107+
else:
108+
consumed = 0
99109
# We need to fast forward by as much as was consumed by the structure
100-
stream.seek(stream.tell() + returned_stream.tell())
110+
stream.seek(stream.tell() + consumed)
101111
continue
102112
elif length is None:
103113
greedy_field = field
@@ -135,7 +145,7 @@ def unpack_stream(self, stream):
135145
raise SuitcaseParseError("While attempting to parse field "
136146
"%r we tried to read %s bytes but "
137147
"we were only able to read %s." %
138-
(name, length, len(data)))
148+
(_name, length, len(data)))
139149
try:
140150
field.unpack(data)
141151
except SuitcaseException:

0 commit comments

Comments
 (0)