diff --git a/asn1tools/codecs/per.py b/asn1tools/codecs/per.py index 03742e67..bb31d5b3 100644 --- a/asn1tools/codecs/per.py +++ b/asn1tools/codecs/per.py @@ -909,8 +909,10 @@ def encode(self, data, encoder): if self.number_of_bits is None: return self.encode_unbound(data, encoder) elif self.minimum != self.maximum: - encoder.append_non_negative_binary_integer(len(data) - self.minimum, - self.number_of_bits) + encoder.append_constrained_whole_number(len(data), + self.minimum, + self.maximum, + self.number_of_bits) for entry in data: self.element_type.encode(entry, encoder) @@ -936,13 +938,13 @@ def decode(self, decoder): pass elif self.number_of_bits is None: return self.decode_unbound(decoder) + elif self.minimum != self.maximum: + length = decoder.read_constrained_whole_number(self.minimum, + self.maximum, + self.number_of_bits) else: length = self.minimum - if self.minimum != self.maximum: - length += decoder.read_non_negative_binary_integer( - self.number_of_bits) - decoded = [] for _ in range(length): diff --git a/asn1tools/codecs/uper.py b/asn1tools/codecs/uper.py index 72722e23..c179e63e 100644 --- a/asn1tools/codecs/uper.py +++ b/asn1tools/codecs/uper.py @@ -2,8 +2,6 @@ """ -from datetime import date - from . import DecodeError from . import per from . import restricted_utc_time_to_datetime @@ -20,8 +18,6 @@ from .per import ObjectIdentifier from .per import Sequence from .per import Set -from .per import SequenceOf -from .per import SetOf from .per import Choice from .per import UTF8String from .per import GeneralString @@ -113,6 +109,59 @@ def decode(self, decoder): return bytearray(data).decode('ascii') +class ArrayType(per.ArrayType): + + def encode(self, data, encoder): + if self.has_extension_marker: + if self.minimum <= len(data) <= self.maximum: + encoder.append_bit(0) + else: + encoder.append_bit(1) + encoder.append_length_determinant(len(data)) + + for entry in data: + self.element_type.encode(entry, encoder) + + return + + if self.number_of_bits is None: + return self.encode_unbound(data, encoder) + elif self.minimum != self.maximum: + encoder.append_non_negative_binary_integer(len(data) - self.minimum, + self.number_of_bits) + + for entry in data: + self.element_type.encode(entry, encoder) + + def decode(self, decoder): + length = None + + if self.has_extension_marker: + bit = decoder.read_bit() + + if bit: + length = decoder.read_length_determinant() + + if length is not None: + pass + elif self.number_of_bits is None: + return self.decode_unbound(decoder) + else: + length = self.minimum + + if self.minimum != self.maximum: + length += decoder.read_non_negative_binary_integer( + self.number_of_bits) + + decoded = [] + + for _ in range(length): + decoded_element = self.element_type.decode(decoder) + decoded.append(decoded_element) + + return decoded + + class Integer(Type): def __init__(self, name): @@ -239,6 +288,38 @@ def decode(self, decoder): return decoder.read_bytes(length) +class SequenceOf(ArrayType): + + def __init__(self, + name, + element_type, + minimum, + maximum, + has_extension_marker): + super(SequenceOf, self).__init__(name, + element_type, + minimum, + maximum, + has_extension_marker, + 'SEQUENCE OF') + + +class SetOf(ArrayType): + + def __init__(self, + name, + element_type, + minimum, + maximum, + has_extension_marker): + super(SetOf, self).__init__(name, + element_type, + minimum, + maximum, + has_extension_marker, + 'SET OF') + + class NumericString(KnownMultiplierStringType): ALPHABET = bytearray(NUMERIC_STRING.encode('ascii')) diff --git a/tests/test_per.py b/tests/test_per.py index 76128dfb..e8963486 100644 --- a/tests/test_per.py +++ b/tests/test_per.py @@ -681,6 +681,7 @@ def test_sequence_of(self): "} " "G ::= SEQUENCE SIZE (1..2, ..., 6..7) OF INTEGER " "H ::= SEQUENCE SIZE (1..MAX) OF INTEGER " + "I ::= SEQUENCE SIZE (1..10000) OF OCTET STRING " "END", 'per') @@ -709,7 +710,8 @@ def test_sequence_of(self): ('G', 6 * [1], b'\x80\x06\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01'), - ('H', [1], b'\x01\x01\x01') + ('H', [1], b'\x01\x01\x01'), + ('I', 300 * [b'\x56'], b'\x01\x2b' + 300 * b'\x01\x56') ] for type_name, decoded, encoded in datas: diff --git a/tests/test_uper.py b/tests/test_uper.py index 6bdb9631..2e4a0e00 100644 --- a/tests/test_uper.py +++ b/tests/test_uper.py @@ -726,6 +726,7 @@ def test_sequence_of(self): "C ::= SEQUENCE SIZE (1..5) OF INTEGER " "D ::= SEQUENCE SIZE (1..2, ...) OF INTEGER " "E ::= SEQUENCE SIZE (1..2, ..., 6..7) OF INTEGER " + "F ::= SEQUENCE SIZE (1..10000) OF OCTET STRING " "END", 'uper') @@ -742,7 +743,8 @@ def test_sequence_of(self): ('D', [2, 1], b'\x40\x40\x80\x40\x40'), ('E', 6 * [1], - b'\x83\x00\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80') + b'\x83\x00\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80'), + ('F', 300 * [b'\x56'], b'\x04\xac' + 300 * b'\x05\x58') ] for type_name, decoded, encoded in datas: