pyloxi: rewrite deserialization to use OFReader
diff --git a/py_gen/templates/generic_util.py b/py_gen/templates/generic_util.py
index a69cd62..53091ed 100644
--- a/py_gen/templates/generic_util.py
+++ b/py_gen/templates/generic_util.py
@@ -35,36 +35,34 @@
import loxi
import struct
-def unpack_array(deserializer, element_size, buf):
+def unpack_list(reader, deserializer):
"""
- Deserialize an array of fixed length elements.
- The deserializer function should take a buffer and return the new object.
- """
- if len(buf) % element_size != 0: raise loxi.ProtocolError("invalid array length")
- n = len(buf) / element_size
- return [deserializer(buffer(buf, i*element_size, element_size)) for i in range(n)]
-
-def unpack_list(deserializer, length_fmt, buf, extra_len=0):
- """
- Deserialize a list of variable-length entries.
- 'length_fmt' is a struct format string with exactly one non-padding format
- character that returns the length of the given element, minus extra_len.
- The deserializer function should take a buffer and return the new object.
+ The deserializer function should take an OFReader and return the new object.
"""
entries = []
- offset = 0
- length_struct = struct.Struct(length_fmt)
- n = len(buf)
- while offset < n:
- if offset + length_struct.size > len(buf): raise loxi.ProtocolError("entry header overruns list length")
- length, = length_struct.unpack_from(buf, offset)
- length += extra_len
- if length < length_struct.size: raise loxi.ProtocolError("entry length is less than the header length")
- if offset + length > len(buf): raise loxi.ProtocolError("entry length overruns list length")
- entries.append(deserializer(buffer(buf, offset, length)))
- offset += length
+ while not reader.is_empty():
+ entries.append(deserializer(reader))
return entries
+def unpack_list_lv16(reader, deserializer):
+ """
+ The deserializer function should take an OFReader and return the new object.
+ """
+ def wrapper(reader):
+ length, = reader.peek('!H')
+ return deserializer(reader.slice(length))
+ return unpack_list(reader, wrapper)
+
+def unpack_list_tlv16(reader, deserializer):
+ """
+ The deserializer function should take an OFReader and an integer type
+ and return the new object.
+ """
+ def wrapper(reader):
+ typ, length, = reader.peek('!HH')
+ return deserializer(reader.slice(length), typ)
+ return unpack_list(reader, wrapper)
+
class OFReader(object):
"""
Cursor over a read-only buffer