laforge has uploaded this change for review. ( https://gerrit.osmocom.org/c/pysim/+/35380?usp=email )
Change subject: construct/tlv: Pass optional 'context' into construct decoder ......................................................................
construct/tlv: Pass optional 'context' into construct decoder
The context is some opaque dictionary that can be used by the constructs; let's allow the caller of parse_construct, from_bytes, from_tlv to specify it.
Also, when decoding a TLV_IE_Collection, pass the decode results of existing siblings via the construct.
Change-Id: I021016aaa09cddf9d36521c1a54b468ec49ff54d --- M pySim/construct.py M pySim/tlv.py 2 files changed, 32 insertions(+), 15 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/pysim refs/changes/80/35380/1
diff --git a/pySim/construct.py b/pySim/construct.py index af96b49..3872c2c 100644 --- a/pySim/construct.py +++ b/pySim/construct.py @@ -173,11 +173,11 @@ return r
-def parse_construct(c, raw_bin_data: bytes, length: typing.Optional[int] = None, exclude_prefix: str = '_'): +def parse_construct(c, raw_bin_data: bytes, length: typing.Optional[int] = None, exclude_prefix: str = '_', context: dict = {}): """Helper function to wrap around normalize_construct() and filter_dict().""" if not length: length = len(raw_bin_data) - parsed = c.parse(raw_bin_data, total_len=length) + parsed = c.parse(raw_bin_data, total_len=length, **context) return normalize_construct(parsed)
diff --git a/pySim/tlv.py b/pySim/tlv.py index c85d92b..f1dc268 100644 --- a/pySim/tlv.py +++ b/pySim/tlv.py @@ -102,16 +102,16 @@ def _to_bytes(self): raise NotImplementedError('%s._to_bytes' % type(self).__name__)
- def from_bytes(self, do: bytes): + def from_bytes(self, do: bytes, context: dict = {}): """Convert from binary bytes to internal representation. Store the decoded result in the internal state and return it.""" self.encoded = do if self.encoded == b'': self.decoded = None elif self._construct: - self.decoded = parse_construct(self._construct, do) + self.decoded = parse_construct(self._construct, do, context=context) elif self.__class__._construct: - self.decoded = parse_construct(self.__class__._construct, do) + self.decoded = parse_construct(self.__class__._construct, do, context=context) else: self.decoded = self._from_bytes(do) return self.decoded @@ -188,13 +188,13 @@ else: return super().to_bytes()
- def from_bytes(self, do: bytes): + def from_bytes(self, do: bytes, context: dict = {}): """Parse *the value part* from binary bytes to internal representation.""" if self.nested_collection: - self.children = self.nested_collection.from_bytes(do) + self.children = self.nested_collection.from_bytes(do, context=context) else: self.children = [] - return super().from_bytes(do) + return super().from_bytes(do, context=context)
class TLV_IE(IE): @@ -234,7 +234,7 @@ val = self.to_bytes() return self._encode_tag() + self._encode_len(val) + val
- def from_tlv(self, do: bytes): + def from_tlv(self, do: bytes, context: dict = {}): if len(do) == 0: return {}, b'' (rawtag, remainder) = self.__class__._parse_tag_raw(do) @@ -248,7 +248,7 @@ else: value = do remainder = b'' - dec = self.from_bytes(value) + dec = self.from_bytes(value, context=context) return dec, remainder
@@ -343,7 +343,7 @@ else: raise TypeError
- def from_bytes(self, binary: bytes) -> List[TLV_IE]: + def from_bytes(self, binary: bytes, context: dict = {}) -> List[TLV_IE]: """Create a list of TLV_IEs from the collection based on binary input data. Args: binary : binary bytes of encoded data @@ -357,6 +357,7 @@ first = next(iter(self.members_by_tag.values())) # iterate until no binary trailer is left while len(remainder): + context['siblings'] = res # obtain the tag at the start of the remainder tag, r = first._parse_tag_raw(remainder) if tag == None: @@ -365,7 +366,7 @@ cls = self.members_by_tag[tag] # create an instance and parse accordingly inst = cls() - dec, remainder = inst.from_tlv(remainder) + dec, remainder = inst.from_tlv(remainder, context=context) res.append(inst) else: # unknown tag; create the related class on-the-fly using the same base class @@ -376,7 +377,7 @@ cls._to_bytes = lambda s: bytes.fromhex(s.decoded['raw']) # create an instance and parse accordingly inst = cls() - dec, remainder = inst.from_tlv(remainder) + dec, remainder = inst.from_tlv(remainder, context=context) res.append(inst) self.children = res return res @@ -419,8 +420,8 @@ out += c.to_tlv() return out
- def from_tlv(self, do): - return self.from_bytes(do) + def from_tlv(self, do, context: dict = {}): + return self.from_bytes(do, context=context)
def to_tlv(self): return self.to_bytes()