dexter has uploaded this change for review.

View Change

filesystem: pass total_len to construct of when encoding file contents

In our construct models we frequently use a context parameter "total_len",
we also pass this parameter to construct when we decode files, but we
do not pass it when we generate files. This is a problem, because when
total_len is used in the construct model, this parameter must be known
also when decoding the file.

Let's make sure that the total_len is properly determined and and passed
to construct (via pyosmocom)

Related: OS#5714
Change-Id: I1b7a51594fbc5d9fe01132c39354a2fa88d53f9b
---
M pySim/filesystem.py
M pySim/runtime.py
M requirements.txt
3 files changed, 36 insertions(+), 16 deletions(-)

git pull ssh://gerrit.osmocom.org:29418/pysim refs/changes/95/38195/1
diff --git a/pySim/filesystem.py b/pySim/filesystem.py
index 43a72f2..5258569 100644
--- a/pySim/filesystem.py
+++ b/pySim/filesystem.py
@@ -179,7 +179,7 @@
"""Return a dict of {'identifier': self} tuples.

Args:
- alias : Add an alias with given name to 'self'
+ alias : Add an alias with given name to 'self'
flags : Specify which selectables to return 'FIDS' and/or 'NAMES';
If not specified, all selectables will be returned.
Returns:
@@ -743,7 +743,17 @@
return t.to_dict()
return {'raw': raw_bin_data.hex()}

- def encode_bin(self, abstract_data: dict) -> bytearray:
+ def _get_size(self, total_len : int = None):
+ if total_len is not None:
+ return {"total_len" : total_len}
+ elif self.size[1] is not None:
+ return {"total_len" : self.size[1]}
+ elif self.size[0] is not None:
+ return {"total_len" : self.size[0]}
+ else:
+ return {"total_len" : None}
+
+ def encode_bin(self, abstract_data: dict, total_len : int = None) -> bytearray:
"""Encode abstract representation into raw (binary) data.

A derived class would typically provide an _encode_bin() or _encode_hex() method
@@ -762,7 +772,7 @@
if callable(method):
return h2b(method(abstract_data))
if self._construct:
- return build_construct(self._construct, abstract_data)
+ return build_construct(self._construct, abstract_data, self._get_size(total_len))
if self._tlv:
t = self._tlv() if inspect.isclass(self._tlv) else self._tlv
t.from_dict(abstract_data)
@@ -770,7 +780,7 @@
raise NotImplementedError(
"%s encoder not yet implemented. Patches welcome." % self)

- def encode_hex(self, abstract_data: dict) -> str:
+ def encode_hex(self, abstract_data: dict, total_len : int = None) -> str:
"""Encode abstract representation into raw (hex string) data.

A derived class would typically provide an _encode_bin() or _encode_hex() method
@@ -790,7 +800,7 @@
raw_bin_data = method(abstract_data)
return b2h(raw_bin_data)
if self._construct:
- return b2h(build_construct(self._construct, abstract_data))
+ return b2h(build_construct(self._construct, abstract_data, self._get_size(total_len)))
if self._tlv:
t = self._tlv() if inspect.isclass(self._tlv) else self._tlv
t.from_dict(abstract_data)
@@ -1030,7 +1040,17 @@
return t.to_dict()
return {'raw': raw_hex_data}

- def encode_record_hex(self, abstract_data: dict, record_nr: int) -> str:
+ def __get_rec_len(self, total_len : int = None):
+ if total_len is not None:
+ return {"total_len" : total_len}
+ elif self.rec_len[1] is not None:
+ return {"total_len" : self.rec_len[1]}
+ elif self.rec_len[0] is not None:
+ return {"total_len" : self.rec_len[0]}
+ else:
+ return {"total_len" : None}
+
+ def encode_record_hex(self, abstract_data: dict, record_nr: int, total_len: int = None) -> str:
"""Encode abstract representation into raw (hex string) data.

A derived class would typically provide an _encode_record_bin() or _encode_record_hex()
@@ -1051,7 +1071,7 @@
raw_bin_data = method(abstract_data, record_nr=record_nr)
return b2h(raw_bin_data)
if self._construct:
- return b2h(build_construct(self._construct, abstract_data))
+ return b2h(build_construct(self._construct, abstract_data, self.__get_rec_len(total_len)))
if self._tlv:
t = self._tlv() if inspect.isclass(self._tlv) else self._tlv
t.from_dict(abstract_data)
@@ -1059,7 +1079,7 @@
raise NotImplementedError(
"%s encoder not yet implemented. Patches welcome." % self)

- def encode_record_bin(self, abstract_data: dict, record_nr : int) -> bytearray:
+ def encode_record_bin(self, abstract_data: dict, record_nr : int, total_len : int = None) -> bytearray:
"""Encode abstract representation into raw (binary) data.

A derived class would typically provide an _encode_record_bin() or _encode_record_hex()
@@ -1079,7 +1099,7 @@
if callable(method):
return h2b(method(abstract_data, record_nr=record_nr))
if self._construct:
- return build_construct(self._construct, abstract_data)
+ return build_construct(self._construct, abstract_data, self.__get_rec_len(total_len))
if self._tlv:
t = self._tlv() if inspect.isclass(self._tlv) else self._tlv
t.from_dict(abstract_data)
@@ -1224,7 +1244,7 @@
return t.to_dict()
return {'raw': raw_hex_data}

- def encode_record_hex(self, abstract_data: dict) -> str:
+ def encode_record_hex(self, abstract_data: dict, total_len : int = None) -> str:
"""Encode abstract representation into raw (hex string) data.

A derived class would typically provide an _encode_record_bin() or _encode_record_hex()
@@ -1243,7 +1263,7 @@
if callable(method):
return b2h(method(abstract_data))
if self._construct:
- return b2h(filter_dict(build_construct(self._construct, abstract_data)))
+ return b2h(filter_dict(build_construct(self._construct, abstract_data, self._get_size(total_len))))
if self._tlv:
t = self._tlv() if inspect.isclass(self._tlv) else self._tlv
t.from_dict(abstract_data)
@@ -1251,7 +1271,7 @@
raise NotImplementedError(
"%s encoder not yet implemented. Patches welcome." % self)

- def encode_record_bin(self, abstract_data: dict) -> bytearray:
+ def encode_record_bin(self, abstract_data: dict, total_len : int = None) -> bytearray:
"""Encode abstract representation into raw (binary) data.

A derived class would typically provide an _encode_record_bin() or _encode_record_hex()
@@ -1270,7 +1290,7 @@
if callable(method):
return h2b(method(abstract_data))
if self._construct:
- return filter_dict(build_construct(self._construct, abstract_data))
+ return filter_dict(build_construct(self._construct, abstract_data, self._get_size(total_len)))
if self._tlv:
t = self._tlv() if inspect.isclass(self._tlv) else self._tlv
t.from_dict(abstract_data)
diff --git a/pySim/runtime.py b/pySim/runtime.py
index 898008e..5281857 100644
--- a/pySim/runtime.py
+++ b/pySim/runtime.py
@@ -518,7 +518,7 @@
Args:
data : abstract data which is to be encoded and written
"""
- data_hex = self.selected_file.encode_hex(data)
+ data_hex = self.selected_file.encode_hex(data, self.selected_file_size())
return self.update_binary(data_hex)

def read_record(self, rec_nr: int = 0):
@@ -568,7 +568,7 @@
rec_nr : Record number to read
data_hex : Abstract data to be written
"""
- data_hex = self.selected_file.encode_record_hex(data, rec_nr)
+ data_hex = self.selected_file.encode_record_hex(data, rec_nr, self.selected_file_record_len())
return self.update_record(rec_nr, data_hex)

def retrieve_data(self, tag: int = 0):
diff --git a/requirements.txt b/requirements.txt
index 99fd5f9..25e3654 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -5,7 +5,7 @@
jsonpath-ng
construct>=2.9.51
bidict
-pyosmocom>=0.0.2
+pyosmocom>=0.0.3
pyyaml>=5.1
termcolor
colorlog

To view, visit change 38195. To unsubscribe, or for help writing mail filters, visit settings.

Gerrit-MessageType: newchange
Gerrit-Project: pysim
Gerrit-Branch: master
Gerrit-Change-Id: I1b7a51594fbc5d9fe01132c39354a2fa88d53f9b
Gerrit-Change-Number: 38195
Gerrit-PatchSet: 1
Gerrit-Owner: dexter <pmaier@sysmocom.de>