diff options
-rw-r--r-- | TODO.rst | 3 | ||||
-rw-r--r-- | pyasn1/codec/ber/encoder.py | 44 | ||||
-rw-r--r-- | pyasn1/codec/cer/encoder.py | 6 | ||||
-rw-r--r-- | pyasn1/codec/der/encoder.py | 2 | ||||
-rw-r--r-- | tests/codec/ber/test_decoder.py | 12 | ||||
-rw-r--r-- | tests/codec/ber/test_encoder.py | 28 |
6 files changed, 70 insertions, 25 deletions
@@ -73,6 +73,7 @@ Minor, housekeeping things * Asn1Item.clone() / shallowcopy issue * large length encoder? + * lookup type by tag first to allow custom codecs for non-base types * type.useful: @@ -87,3 +88,5 @@ Minor, housekeeping things * type vs tagset name convention * how untagged TagSet should be initialized? + +* type and codecs for Real needs refactoring diff --git a/pyasn1/codec/ber/encoder.py b/pyasn1/codec/ber/encoder.py index 306a053..a08a693 100644 --- a/pyasn1/codec/ber/encoder.py +++ b/pyasn1/codec/ber/encoder.py @@ -405,14 +405,39 @@ tagMap = { useful.UTCTime.tagSet: OctetStringEncoder() } -# Type-to-codec map for ambiguous ASN.1 types +# Put in ambiguous & non-ambiguous types for faster codec lookup typeMap = { + univ.Boolean.typeId: BooleanEncoder(), + univ.Integer.typeId: IntegerEncoder(), + univ.BitString.typeId: BitStringEncoder(), + univ.OctetString.typeId: OctetStringEncoder(), + univ.Null.typeId: NullEncoder(), + univ.ObjectIdentifier.typeId: ObjectIdentifierEncoder(), + univ.Enumerated.typeId: IntegerEncoder(), + univ.Real.typeId: RealEncoder(), + # Sequence & Set have same tags as SequenceOf & SetOf univ.Set.typeId: SequenceEncoder(), univ.SetOf.typeId: SequenceOfEncoder(), univ.Sequence.typeId: SequenceEncoder(), univ.SequenceOf.typeId: SequenceOfEncoder(), univ.Choice.typeId: ChoiceEncoder(), - univ.Any.typeId: AnyEncoder() + univ.Any.typeId: AnyEncoder(), + # character string types + char.UTF8String.typeId: OctetStringEncoder(), + char.NumericString.typeId: OctetStringEncoder(), + char.PrintableString.typeId: OctetStringEncoder(), + char.TeletexString.typeId: OctetStringEncoder(), + char.VideotexString.typeId: OctetStringEncoder(), + char.IA5String.typeId: OctetStringEncoder(), + char.GraphicString.typeId: OctetStringEncoder(), + char.VisibleString.typeId: OctetStringEncoder(), + char.GeneralString.typeId: OctetStringEncoder(), + char.UniversalString.typeId: OctetStringEncoder(), + char.BMPString.typeId: OctetStringEncoder(), + # useful types + useful.ObjectDescriptor.typeId: OctetStringEncoder(), + useful.GeneralizedTime.typeId: OctetStringEncoder(), + useful.UTCTime.typeId: OctetStringEncoder() } @@ -434,16 +459,13 @@ class Encoder(object): if len(tagSet) > 1: concreteEncoder = explicitlyTaggedItemEncoder else: - if value.typeId is None: - concreteEncoder = None - else: - concreteEncoder = self.__typeMap.get(value.typeId, None) - if concreteEncoder is None: - concreteEncoder = self.__tagMap.get(tagSet, None) - if concreteEncoder is None: - tagSet = value.baseTagSet + try: + concreteEncoder = self.__typeMap[value.typeId] + except KeyError: + # use base type for codec lookup to recover untagged types + baseTagSet = tag.TagSet(value.tagSet.baseTag, value.tagSet.baseTag) try: - concreteEncoder = self.__tagMap[tagSet] + concreteEncoder = self.__tagMap[baseTagSet] except KeyError: raise error.PyAsn1Error('No encoder for %s' % (value,)) debug.logger & debug.flagEncoder and debug.logger( diff --git a/pyasn1/codec/cer/encoder.py b/pyasn1/codec/cer/encoder.py index 9428fd0..e241e43 100644 --- a/pyasn1/codec/cer/encoder.py +++ b/pyasn1/codec/cer/encoder.py @@ -133,6 +133,12 @@ tagMap.update({ typeMap = encoder.typeMap.copy() typeMap.update({ + univ.Boolean.typeId: BooleanEncoder(), + univ.BitString.typeId: BitStringEncoder(), + univ.OctetString.typeId: OctetStringEncoder(), + univ.Real.typeId: RealEncoder(), + useful.GeneralizedTime.typeId: GeneralizedTimeEncoder(), + useful.UTCTime.typeId: UTCTimeEncoder(), univ.Set.typeId: SetOfEncoder(), univ.SetOf.typeId: SetOfEncoder() }) diff --git a/pyasn1/codec/der/encoder.py b/pyasn1/codec/der/encoder.py index 7d6403c..2d615e3 100644 --- a/pyasn1/codec/der/encoder.py +++ b/pyasn1/codec/der/encoder.py @@ -28,7 +28,7 @@ tagMap.update({ univ.SetOf().tagSet: SetOfEncoder() }) -typeMap = encoder.typeMap +typeMap = encoder.typeMap.copy() class Encoder(encoder.Encoder): diff --git a/tests/codec/ber/test_decoder.py b/tests/codec/ber/test_decoder.py index 9f07425..f3b6c7d 100644 --- a/tests/codec/ber/test_decoder.py +++ b/tests/codec/ber/test_decoder.py @@ -422,6 +422,18 @@ class RealDecoderTestCase(unittest.TestCase): ints2octs((9, 4, 161, 255, 1, 3)) ) == (univ.Real((3, 2, -1020)), null) +# TODO: this requires Real type comparison fix + +# def testBin6(self): +# assert decoder.decode( +# ints2octs((9, 5, 162, 0, 255, 255, 1)) +# ) == (univ.Real((1, 2, 262140)), null) + +# def testBin7(self): +# assert decoder.decode( +# ints2octs((9, 7, 227, 4, 1, 35, 69, 103, 1)) +# ) == (univ.Real((-1, 2, 76354972)), null) + def testPlusInf(self): assert decoder.decode( ints2octs((9, 1, 64)) diff --git a/tests/codec/ber/test_encoder.py b/tests/codec/ber/test_encoder.py index bf0cfcb..d0b91c9 100644 --- a/tests/codec/ber/test_encoder.py +++ b/tests/codec/ber/test_encoder.py @@ -267,7 +267,7 @@ class RealEncoderTestCase(unittest.TestCase): def testBin1(self): assert encoder.encode( # default binEncBase = 2 - univ.Real((0.5, 2, 0)) # check encbase = 2 and exponenta = -1 + univ.Real((0.5, 2, 0)) # check encbase = 2 and exponent = -1 ) == ints2octs((9, 3, 128, 255, 1)) def testBin2(self): @@ -278,38 +278,40 @@ class RealEncoderTestCase(unittest.TestCase): ) == ints2octs((9, 3, 148, 255, 13)) def testBin3(self): - # change binEncBase in the RealEncoder instance => for all further Reals - encoder.tagMap[univ.Real.tagSet].binEncBase = 16 + # change binEncBase in the RealEncoder instance => for all further Real + binEncBase, encoder.typeMap[univ.Real.typeId].binEncBase = encoder.typeMap[univ.Real.typeId].binEncBase, 16 assert encoder.encode( univ.Real((0.00390625, 2, 0)) # check encbase = 16 ) == ints2octs((9, 3, 160, 254, 1)) + encoder.typeMap[univ.Real.typeId].binEncBase = binEncBase def testBin4(self): - # choose binEncBase automatically for all further Reals (testBin[4-7]) - encoder.tagMap[univ.Real.tagSet].binEncBase = None + # choose binEncBase automatically for all further Real (testBin[4-7]) + binEncBase, encoder.typeMap[univ.Real.typeId].binEncBase = encoder.typeMap[univ.Real.typeId].binEncBase, None assert encoder.encode( univ.Real((1, 2, 0)) # check exponenta = 0 ) == ints2octs((9, 3, 128, 0, 1)) + encoder.typeMap[univ.Real.typeId].binEncBase = binEncBase def testBin5(self): assert encoder.encode( - univ.Real((3, 2, -1020)) # case of 2 octs for exponenta and - # negative exponenta and abs(exponenta) is + univ.Real((3, 2, -1020)) # case of 2 octs for exponent and + # negative exponenta and abs(exponent) is # all 1's and fills the whole octet(s) - ) == ints2octs((9, 4, 161, 255, 1, 3)) + ) == ints2octs((9, 4, 129, 252, 4, 3)) def testBin6(self): assert encoder.encode( - univ.Real((1, 2, 262140)) # case of 3 octs for exponenta and - # check that first 9 bits for exponenta + univ.Real((1, 2, 262140)) # case of 3 octs for exponent and + # check that first 9 bits for exponent # are not all 1's - ) == ints2octs((9, 5, 162, 0, 255, 255, 1)) + ) == ints2octs((9, 5, 130, 3, 255, 252, 1)) def testBin7(self): assert encoder.encode( - univ.Real((-1, 2, 76354972)) # case of >3 octs for exponenta and + univ.Real((-1, 2, 76354972)) # case of >3 octs for exponent and # mantissa < 0 - ) == ints2octs((9, 7, 227, 4, 1, 35, 69, 103, 1)) + ) == ints2octs((9, 7, 195, 4, 4, 141, 21, 156, 1)) def testPlusInf(self): assert encoder.encode(univ.Real('inf')) == ints2octs((9, 1, 64)) |