From 907c6013d694ebf7343a06c40dfd57a34d3d1c2e Mon Sep 17 00:00:00 2001 From: Julien Castiaux Date: Sat, 21 Dec 2024 17:58:45 +0100 Subject: [PATCH] Use Enum with Tag for pretty repr --- src/asn1.py | 28 +++++++++++++++++++++++++--- tests/test_asn1.py | 16 ++++++++++++++++ 2 files changed, 41 insertions(+), 3 deletions(-) diff --git a/src/asn1.py b/src/asn1.py index 772697b..d03a747 100644 --- a/src/asn1.py +++ b/src/asn1.py @@ -29,7 +29,16 @@ __version__ = "2.7.1" -class Numbers(IntEnum): +class HexEnum(IntEnum): + def __repr__(self): + return '<{cls}.{name}: 0x{value:02x}>'.format( + cls=type(self).__name__, + name=self.name, + value=self.value + ) + + +class Numbers(HexEnum): Boolean = 0x01 Integer = 0x02 BitString = 0x03 @@ -47,12 +56,12 @@ class Numbers(IntEnum): UnicodeString = 0x1e -class Types(IntEnum): +class Types(HexEnum): Constructed = 0x20 Primitive = 0x00 -class Classes(IntEnum): +class Classes(HexEnum): Universal = 0x00 Application = 0x40 Context = 0x80 @@ -551,6 +560,19 @@ def _read_tag(self): # type: () -> Tag nr = (nr << 7) | (byte & 0x7f) if not byte & 0x80: break + try: + typ = Types(typ) + except ValueError: + pass + try: + cls = Classes(cls) + except ValueError: + pass + if cls == Classes.Universal: + try: + nr = Numbers(nr) + except ValueError: + pass return Tag(nr=nr, typ=typ, cls=cls) def _read_length(self): # type: () -> int diff --git a/tests/test_asn1.py b/tests/test_asn1.py index c0134a6..2f2a82b 100644 --- a/tests/test_asn1.py +++ b/tests/test_asn1.py @@ -392,6 +392,7 @@ def test_boolean(self): dec.start(buf) tag = dec.peek() assert tag == (asn1.Numbers.Boolean, asn1.Types.Primitive, asn1.Classes.Universal) + assert str(tag) == "Tag(nr=, typ=, cls=)" tag, val = dec.read() assert isinstance(val, int) assert val @@ -412,6 +413,7 @@ def test_integer(self): dec.start(buf) tag = dec.peek() assert tag == (asn1.Numbers.Integer, asn1.Types.Primitive, asn1.Classes.Universal) + assert str(tag) == "Tag(nr=, typ=, cls=)" tag, val = dec.read() assert isinstance(val, int) assert val == 1 @@ -462,6 +464,7 @@ def test_octet_string(self): dec.start(buf) tag = dec.peek() assert tag == (asn1.Numbers.OctetString, asn1.Types.Primitive, asn1.Classes.Universal) + assert str(tag) == "Tag(nr=, typ=, cls=)" tag, val = dec.read() assert val == b'foo' @@ -471,6 +474,7 @@ def test_printable_string(self): dec.start(buf) tag = dec.peek() assert tag == (asn1.Numbers.PrintableString, asn1.Types.Primitive, asn1.Classes.Universal) + assert str(tag) == "Tag(nr=, typ=, cls=)" tag, val = dec.read() assert val == u'foo' @@ -480,6 +484,7 @@ def test_bitstring(self): dec.start(buf) tag = dec.peek() assert tag == (asn1.Numbers.BitString, asn1.Types.Primitive, asn1.Classes.Universal) + assert str(tag) == "Tag(nr=, typ=, cls=)" tag, val = dec.read() assert val == b'\x12\x34\x56' @@ -489,6 +494,7 @@ def test_bitstring_unused_bits(self): dec.start(buf) tag = dec.peek() assert tag == (asn1.Numbers.BitString, asn1.Types.Primitive, asn1.Classes.Universal) + assert str(tag) == "Tag(nr=, typ=, cls=)" tag, val = dec.read() assert val == b'\x01\x23\x45' @@ -498,6 +504,7 @@ def test_unicode_printable_string(self): dec.start(buf) tag = dec.peek() assert tag == (asn1.Numbers.PrintableString, asn1.Types.Primitive, asn1.Classes.Universal) + assert str(tag) == "Tag(nr=, typ=, cls=)" tag, val = dec.read() assert val == u'fooƩ' @@ -507,6 +514,7 @@ def test_null(self): dec.start(buf) tag = dec.peek() assert tag == (asn1.Numbers.Null, asn1.Types.Primitive, asn1.Classes.Universal) + assert str(tag) == "Tag(nr=, typ=, cls=)" tag, val = dec.read() assert val is None @@ -552,6 +560,7 @@ def test_enumerated(self): dec.start(buf) tag = dec.peek() assert tag == (asn1.Numbers.Enumerated, asn1.Types.Primitive, asn1.Classes.Universal) + assert str(tag) == "Tag(nr=, typ=, cls=)" tag, val = dec.read() assert isinstance(val, int) assert val == 1 @@ -562,6 +571,7 @@ def test_sequence(self): dec.start(buf) tag = dec.peek() assert tag == (asn1.Numbers.Sequence, asn1.Types.Constructed, asn1.Classes.Universal) + assert str(tag) == "Tag(nr=, typ=, cls=)" dec.enter() tag, val = dec.read() assert val == 1 @@ -574,6 +584,7 @@ def test_sequence_of(self): dec.start(buf) tag = dec.peek() assert tag == (asn1.Numbers.Sequence, asn1.Types.Constructed, asn1.Classes.Universal) + assert str(tag) == "Tag(nr=, typ=, cls=)" dec.enter() tag, val = dec.read() assert val == 1 @@ -586,6 +597,7 @@ def test_set(self): dec.start(buf) tag = dec.peek() assert tag == (asn1.Numbers.Set, asn1.Types.Constructed, asn1.Classes.Universal) + assert str(tag) == "Tag(nr=, typ=, cls=)" dec.enter() tag, val = dec.read() assert val == 1 @@ -598,6 +610,7 @@ def test_set_of(self): dec.start(buf) tag = dec.peek() assert tag == (asn1.Numbers.Set, asn1.Types.Constructed, asn1.Classes.Universal) + assert str(tag) == "Tag(nr=, typ=, cls=)" dec.enter() tag, val = dec.read() assert val == 1 @@ -610,6 +623,7 @@ def test_context(self): dec.start(buf) tag = dec.peek() assert tag == (1, asn1.Types.Constructed, asn1.Classes.Context) + assert str(tag) == "Tag(nr=1, typ=, cls=)" dec.enter() tag, val = dec.read() assert val == 1 @@ -620,6 +634,7 @@ def test_application(self): dec.start(buf) tag = dec.peek() assert tag == (1, asn1.Types.Constructed, asn1.Classes.Application) + assert str(tag) == "Tag(nr=1, typ=, cls=)" dec.enter() tag, val = dec.read() assert val == 1 @@ -630,6 +645,7 @@ def test_private(self): dec.start(buf) tag = dec.peek() assert tag == (1, asn1.Types.Constructed, asn1.Classes.Private) + assert str(tag) == "Tag(nr=1, typ=, cls=)" dec.enter() tag, val = dec.read() assert val == 1