dexter has uploaded this change for review. ( 
https://gerrit.osmocom.org/c/python/pyosmocom/+/39193?usp=email )


Change subject: construct: allow stripping of leading zeros with 
StripTrailerAdapter
......................................................................

construct: allow stripping of leading zeros with StripTrailerAdapter

The class StripTrailerAdapter is currently only able to strip zeros at the end
of an integer. What it can not do is stripping leading zeros. Let's add a
parameter for that and extend the unittests accordingly.

Related: OS#6679

Change-Id: I1a9fff17abbbef0c5f6d45f58198debfa12e78b6
---
M src/osmocom/construct.py
M tests/test_construct.py
2 files changed, 59 insertions(+), 6 deletions(-)



  git pull ssh://gerrit.osmocom.org:29418/python/pyosmocom 
refs/changes/93/39193/1

diff --git a/src/osmocom/construct.py b/src/osmocom/construct.py
index 1f5bd45..dd92165 100644
--- a/src/osmocom/construct.py
+++ b/src/osmocom/construct.py
@@ -420,19 +420,23 @@
     where you have a bit-mask that may have 1, 2 or 3 bytes, depending on 
whether or not any
     of the LSBs are actually set.
     """
-    def __init__(self, subcon, total_length:int, default_value=b'\x00', 
min_len=1, steps:[int]=[]):
+    def __init__(self, subcon, total_length:int, default_value=b'\x00', 
min_len=1, steps:[int]=[], reverse:bool = False):
         super().__init__(subcon)
         assert len(default_value) == 1
         self.total_length = total_length
         self.default_value = default_value
         self.min_len = min_len
         self.steps = steps
+        self.reverse = reverse

     def _decode(self, obj, context, path):
         assert isinstance(obj, bytes)
         # pad with suppressed/missing bytes
         if len(obj) < self.total_length:
-            obj += self.default_value * (self.total_length - len(obj))
+            if self.reverse:
+                obj = self.default_value * (self.total_length - len(obj)) + obj
+            else:
+                obj += self.default_value * (self.total_length - len(obj))
         return int.from_bytes(obj, 'big')

     def _encode(self, obj, context, path):
@@ -441,10 +445,16 @@
         # remove trailing bytes if they are zero

         obj_step_aligned = obj
-        while len(obj) > self.min_len and obj[-1] == self.default_value[0]:
-            obj = obj[:-1]
-            if len(obj) in self.steps:
-                obj_step_aligned = obj
+        if self.reverse:
+            while len(obj) > self.min_len and obj[0] == self.default_value[0]:
+                obj = obj[1:]
+                if len(obj) in self.steps:
+                    obj_step_aligned = obj
+        else:
+            while len(obj) > self.min_len and obj[-1] == self.default_value[0]:
+                obj = obj[:-1]
+                if len(obj) in self.steps:
+                    obj_step_aligned = obj

         if self.steps == []:
             return obj
diff --git a/tests/test_construct.py b/tests/test_construct.py
index e4234db..4fb1a71 100755
--- a/tests/test_construct.py
+++ b/tests/test_construct.py
@@ -101,6 +101,11 @@
                                           final_application=0x0200, 
global_service=0x0100,
                                           receipt_generation=0x80, 
ciphered_load_file_data_block=0x40,
                                           contactless_activation=0x20, 
contactless_self_activation=0x10)
+    IntegerSteps = StripTrailerAdapter(GreedyBytes, 4, steps = [2,4])
+    Integer = StripTrailerAdapter(GreedyBytes, 4)
+    IntegerStepsReverse = StripTrailerAdapter(GreedyBytes, 4, steps = [2,4], 
reverse = True)
+    IntegerReverse = StripTrailerAdapter(GreedyBytes, 4, reverse = True)
+
     examples = ['00', '80', '8040', '400010']
     def test_encdec(self):
         for e in self.examples:
@@ -108,6 +113,44 @@
             reenc = self.Privileges.build(dec)
             self.assertEqual(e, b2h(reenc))

+    def test_encdec_integer(self):
+        enc = self.IntegerSteps.build(0x10000000)
+        self.assertEqual(b2h(enc), '1000')
+        enc = self.IntegerSteps.build(0x10200000)
+        self.assertEqual(b2h(enc), '1020')
+        enc = self.IntegerSteps.build(0x10203000)
+        self.assertEqual(b2h(enc), '10203000')
+        enc = self.IntegerSteps.build(0x10203040)
+        self.assertEqual(b2h(enc), '10203040')
+
+        enc = self.Integer.build(0x10000000)
+        self.assertEqual(b2h(enc), '10')
+        enc = self.Integer.build(0x10200000)
+        self.assertEqual(b2h(enc), '1020')
+        enc = self.Integer.build(0x10203000)
+        self.assertEqual(b2h(enc), '102030')
+        enc = self.Integer.build(0x10203040)
+        self.assertEqual(b2h(enc), '10203040')
+
+    def test_encdec_integer_reverse(self):
+        enc = self.IntegerStepsReverse.build(0x40)
+        self.assertEqual(b2h(enc), '0040')
+        enc = self.IntegerStepsReverse.build(0x3040)
+        self.assertEqual(b2h(enc), '3040')
+        enc = self.IntegerStepsReverse.build(0x203040)
+        self.assertEqual(b2h(enc), '00203040')
+        enc = self.IntegerStepsReverse.build(0x10203040)
+        self.assertEqual(b2h(enc), '10203040')
+
+        enc = self.IntegerReverse.build(0x40)
+        self.assertEqual(b2h(enc), '40')
+        enc = self.IntegerReverse.build(0x3040)
+        self.assertEqual(b2h(enc), '3040')
+        enc = self.IntegerReverse.build(0x203040)
+        self.assertEqual(b2h(enc), '203040')
+        enc = self.IntegerReverse.build(0x10203040)
+        self.assertEqual(b2h(enc), '10203040')
+
     def test_enc(self):
         enc = self.Privileges.build({'dap_verification' : True})
         self.assertEqual(b2h(enc), '40')

--
To view, visit https://gerrit.osmocom.org/c/python/pyosmocom/+/39193?usp=email
To unsubscribe, or for help writing mail filters, visit 
https://gerrit.osmocom.org/settings?usp=email

Gerrit-MessageType: newchange
Gerrit-Project: python/pyosmocom
Gerrit-Branch: master
Gerrit-Change-Id: I1a9fff17abbbef0c5f6d45f58198debfa12e78b6
Gerrit-Change-Number: 39193
Gerrit-PatchSet: 1
Gerrit-Owner: dexter <[email protected]>

Reply via email to