summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--TODO.rst3
-rw-r--r--pyasn1/codec/ber/encoder.py44
-rw-r--r--pyasn1/codec/cer/encoder.py6
-rw-r--r--pyasn1/codec/der/encoder.py2
-rw-r--r--tests/codec/ber/test_decoder.py12
-rw-r--r--tests/codec/ber/test_encoder.py28
6 files changed, 70 insertions, 25 deletions
diff --git a/TODO.rst b/TODO.rst
index 21f164e..5c79ee7 100644
--- a/TODO.rst
+++ b/TODO.rst
@@ -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))