| Home | Trees | Indices | Help |
|---|
|
|
1
2 # The contents of this file are subject to the Mozilla Public License
3 # (MPL) Version 1.1 (the "License"); you may not use this file except
4 # in compliance with the License. You may obtain a copy of the License
5 # at http://www.mozilla.org/MPL/
6 #
7 # Software distributed under the License is distributed on an "AS IS"
8 # basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
9 # the License for the specific language governing rights and
10 # limitations under the License.
11 #
12 # The Original Code is LEPL (http://www.acooke.org/lepl)
13 # The Initial Developer of the Original Code is Andrew Cooke.
14 # Portions created by the Initial Developer are Copyright (C) 2009-2010
15 # Andrew Cooke (andrew@acooke.org). All Rights Reserved.
16 #
17 # Alternatively, the contents of this file may be used under the terms
18 # of the LGPL license (the GNU Lesser General Public License,
19 # http://www.gnu.org/licenses/lgpl.html), in which case the provisions
20 # of the LGPL License are applicable instead of those above.
21 #
22 # If you wish to allow use of your version of this file only under the
23 # terms of the LGPL License and not to allow others to use your version
24 # of this file under the MPL, indicate your decision by deleting the
25 # provisions above and replace them with the notice and other provisions
26 # required by the LGPL License. If you do not delete the provisions
27 # above, a recipient may use your version of this file under either the
28 # MPL or the LGPL License.
29
30 '''
31 Convert structured Python data to a binary stream.
32
33 Writing a good API for binary encoding of arbitrary objects does not seem to
34 be easy. In addition, this is my first attempt. My apologies in advance.
35 This is a very basic library - the hope is that something like ASN.1 can
36 then be built on this (if someone buys me a copy of the spec...!)
37
38 The most obvious solution might be to require everything that must be encoded
39 implement some method. Given Python's dynamic nature, ABCs, etc, this might
40 be possible, but it does seem that it could require some rather ugly hacks in
41 some cases, when using existing types.
42
43 The next simplest approach seems to be to use some kind of separate dispatch
44 (rather than the classes themselves) to convert things to a standard
45 intermediate fmt. That is what I do here. The intermediate fmt
46 is the pair (type, BitString), where "type" can be any value (but will be the
47 type of the value in all implementations here - value could be used, but we're
48 trying to give some impression of a layered approach).
49
50 Encoding a structure then requires three steps:
51
52 1. Defining a serialisation of composite structures. Only acyclic structures
53 are considered (I am more interested in network protocols than pickling,
54 which already has a Python solution)
55
56 2. Converting individual values in the serial stream to the intermediate
57 representation.
58
59 3. Encoding the intermediate representation into a final BitString.
60
61 Support for each of these steps is provided by LEPL. Stage 1 comes from the
62 graph and node modules; 2 is provided below (leveraging BitString's class
63 methods); 3 is only supported in a simple way below, with the expectation
64 that future modules might extend both encoding and matching to, for example,
65 ASN.1.
66 '''
67
68 if bytes is str:
69 print('Binary parsing unsupported in this Python version')
70 else:
71
72 from functools import reduce as reduce_
73 from operator import add
74
75 from lepl.bin.bits import BitString, STRICT
76 from lepl.support.graph import leaves
77 from lepl.support.node import Node
78
79
81 '''
82 Convert types appropriately.
83 '''
84 # pylint: disable-msg=W0108
85 # consistency
86 return {int: lambda n: BitString.from_int(n, ordered=big_endian),
87 str: lambda s: BitString.from_str(s, encoding, errors),
88 bytes: lambda b: BitString.from_bytearray(b),
89 bytearray: lambda b: BitString.from_bytearray(b),
90 BitString: lambda x: x}
91
92
94 '''
95 Given a table, create the converter.
96 '''
97 def converter(value):
98 '''
99 The converter.
100 '''
101 type_ = type(value)
102 if type_ in table:
103 return (type_, table[type_](value))
104 for key in table:
105 if isinstance(value, key):
106 return (type_, table[key](value))
107 raise TypeError('Cannot convert {0!r}:{1!r}'.format(value, type_))
108 return converter
109
110
118
| Home | Trees | Indices | Help |
|---|
| Generated by Epydoc 3.0.1 on Sat Jun 9 21:51:02 2012 | http://epydoc.sourceforge.net |