Browse Source

break out the non-standard support into it's own class.

The default still supports dict, but a pure standard encoder/decoder
is now available.
python2
John-Mark Gurney 8 years ago
parent
commit
ea1dad8ebd
1 changed files with 46 additions and 29 deletions
  1. +46
    -29
      pasn1.py

+ 46
- 29
pasn1.py View File

@@ -3,10 +3,12 @@
'''A Pure Python ASN.1 encoder/decoder w/ a calling interface in the spirit '''A Pure Python ASN.1 encoder/decoder w/ a calling interface in the spirit
of pickle. of pickle.


It uses a profile of ASN.1.
The default dumps/loads uses a profile of ASN.1 that supports serialization
of key/value pairs. This is non-standard. Instantiate the class ASN1Coder
to get a pure ASN.1 serializer/deserializer.


All lengths must be specified. That is that End-of-contents octets All lengths must be specified. That is that End-of-contents octets
MUST not be used. The shorted form of length encoding MUST be used.
MUST NOT be used. The shorted form of length encoding MUST be used.
A longer length encoding MUST be rejected.''' A longer length encoding MUST be rejected.'''


__author__ = 'John-Mark Gurney' __author__ = 'John-Mark Gurney'
@@ -120,7 +122,6 @@ class ASN1Coder(object):
with the obj. It is expected to return a tuple of a string with the obj. It is expected to return a tuple of a string
and an object that has the method w/ the string as defined: and an object that has the method w/ the string as defined:
'bool': __nonzero__ 'bool': __nonzero__
'dict': iteritems
'float': compatible w/ float 'float': compatible w/ float
'int': compatible w/ int 'int': compatible w/ int
'list': __iter__ 'list': __iter__
@@ -135,7 +136,6 @@ class ASN1Coder(object):


_typemap = { _typemap = {
bool: 'bool', bool: 'bool',
dict: 'dict',
float: 'float', float: 'float',
int: 'int', int: 'int',
list: 'list', list: 'list',
@@ -158,7 +158,6 @@ class ASN1Coder(object):
'\x18': 'datetime', '\x18': 'datetime',
'\x30': 'list', '\x30': 'list',
'\x31': 'set', '\x31': 'set',
'\xe0': 'dict',
} }


_typetag = dict((v, k) for k, v in _tagmap.iteritems()) _typetag = dict((v, k) for k, v in _tagmap.iteritems())
@@ -211,29 +210,6 @@ class ASN1Coder(object):
def dec_null(d, pos, end): def dec_null(d, pos, end):
return None, end return None, end


def enc_dict(self, obj):
#it = list(obj.iteritems())
#it.sort()
r = ''.join(self.dumps(k) + self.dumps(v) for k, v in
obj.iteritems())
return _encodelen(len(r)) + r

def dec_dict(self, d, pos, end):
r = {}
vend = pos
while pos < end:
k, kend = self._loads(d, pos, end)
#if kend > end:
# raise ValueError('key past end')
v, vend = self._loads(d, kend, end)
if vend > end:
raise ValueError('value past end')

r[k] = v
pos = vend

return r, vend

def enc_list(self, obj): def enc_list(self, obj):
r = ''.join(self.dumps(x) for x in obj) r = ''.join(self.dumps(x) for x in obj)
return _encodelen(len(r)) + r return _encodelen(len(r)) + r
@@ -415,7 +391,43 @@ class ASN1Coder(object):


return r return r


_coder = ASN1Coder()
class ASN1DictCoder(ASN1Coder):
'''This adds support for the non-standard dict serialization.

The coerce method also supports the following type:
'dict': iteritems
'''

_typemap = ASN1Coder._typemap.copy()
_typemap[dict] = 'dict'
_tagmap = ASN1Coder._tagmap.copy()
_tagmap['\xe0'] = 'dict'
_typetag = dict((v, k) for k, v in _tagmap.iteritems())

def enc_dict(self, obj):
#it = list(obj.iteritems())
#it.sort()
r = ''.join(self.dumps(k) + self.dumps(v) for k, v in
obj.iteritems())
return _encodelen(len(r)) + r

def dec_dict(self, d, pos, end):
r = {}
vend = pos
while pos < end:
k, kend = self._loads(d, pos, end)
#if kend > end:
# raise ValueError('key past end')
v, vend = self._loads(d, kend, end)
if vend > end:
raise ValueError('value past end')

r[k] = v
pos = vend

return r, vend

_coder = ASN1DictCoder()
dumps = _coder.dumps dumps = _coder.dumps
loads = _coder.loads loads = _coder.loads


@@ -629,3 +641,8 @@ class TestCode(unittest.TestCase):


def test_loads(self): def test_loads(self):
self.assertRaises(ValueError, loads, '\x00\x02\x00') self.assertRaises(ValueError, loads, '\x00\x02\x00')

def test_nodict(self):
'''Verify that ASN1Coder does not support dict.'''

self.assertRaises(KeyError, ASN1Coder().loads, dumps({}))

Loading…
Cancel
Save