[svn] commit: r58 - in /experiments/graff-ccapi/python: ISC/CC/message.py test.py

BIND 10 source code commits bind10-changes at lists.isc.org
Mon Oct 5 18:57:58 UTC 2009


Author: mgraff
Date: Mon Oct  5 18:57:57 2009
New Revision: 58

Log:
decoding works

Modified:
    experiments/graff-ccapi/python/ISC/CC/message.py
    experiments/graff-ccapi/python/test.py

Modified: experiments/graff-ccapi/python/ISC/CC/message.py
==============================================================================
--- experiments/graff-ccapi/python/ISC/CC/message.py (original)
+++ experiments/graff-ccapi/python/ISC/CC/message.py Mon Oct  5 18:57:57 2009
@@ -33,19 +33,24 @@
     _ITEM_LENGTH_MASK = 0x30
 
     def to_wire(self, items):
-        """Encode a dict into wire format"""
-
+        """Encode a dict into wire format.
+        >>> cc = Message()
+        ... wire = to_wire({"a": "b"})
+        """
         ret = []
         ret.append(struct.pack(">I", self.PROTOCOL_VERSION))
         ret.append(self._encode_hash(items))
         return (''.join(ret))
 
     def _encode_tag(self, tag):
-        """Encode a single tag.  Private."""
-
-        return(struct.pack(">B", len(tag)) + tag)
+        """Encode a single UTF-8 tag.
+        >>> cc = Message()
+        ... wire_partial = cc._encode_tag('this')
+        """
+        return(struct.pack(">B", len(str(tag))) + str(tag))
 
     def _encode_length_and_type(self, data, datatype):
+        """Helper method to handle the length encoding in one place."""
         if data == None:
             return(struct.pack(">B", self._ITEM_NULL))
         length = len(data)
@@ -59,45 +64,133 @@
             return(struct.pack(">B I", datatype, length) + data)
 
     def _pack_string(self, item):
+        """Pack a string (data) and its type/length prefix."""
         return (self._encode_length_and_type(item, self._ITEM_DATA))
 
     def _pack_array(self, item):
+        """Pack a list (array) and its type/length prefix."""
         return (self._encode_length_and_type(self._encode_array(item),
                                              self._ITEM_LIST))
 
     def _pack_hash(self, item):
+        """Pack a dict (hash) and its type/length prefix."""
         data = self._encode_hash(item)
         return (self._encode_length_and_type(data, self._ITEM_HASH))
 
     def _encode_string(self, item):
+        """Encode a string.  More or less identity."""
         return (item)
 
     def _pack_nil(self):
+        """Encode a nil (NULL, None) item."""
         return self._encode_length_and_type(None, None)
 
     def _encode_item(self, item):
+        """Encode each item depending on its type"""
         if item == None:
             return (self._pack_nil())
-        elif item.__class__ == dict:
+        elif type(item) == dict:
             return (self._pack_hash(item))
-        elif item.__class__ == list:
+        elif type(item) == list:
             return (self._pack_array(item))
         else:
             return (self._pack_string(str(item)))
 
     def _encode_array(self, item):
+        """Encode an array, where each value is encoded recursively"""
         ret = []
         for i in item:
             ret.append(self._encode_item(i))
         return (''.join(ret))
 
     def _encode_hash(self, item):
+        """Encode a hash, where each value is encoded recursively"""
+
         ret = []
         for key, value in item.items():
             ret.append(self._encode_tag(key))
             ret.append(self._encode_item(value))
         return (''.join(ret))
 
+    #
+    # decode methods
+    #
+
+    def from_wire(self, data):
+        if len(data) < 5:
+            raise DecodeError("Data is too short to decode")
+        wire_version, data = data[0:4], data[4:]
+        wire_version = struct.unpack(">I", wire_version)[0]
+        if wire_version != self.PROTOCOL_VERSION:
+            raise DecodeError("Incorrect protocol version")
+        return self._decode_hash(data)
+
+    def _decode_tag(self, data):
+        if len(data) < 1:
+            raise DecodeError("Data underrun while decoding")
+        length = struct.unpack(">B", data[0])[0]
+        if len(data) - 1 < length:
+            raise DecodeError("Data underrun while decoding")
+        return [data[1:length + 1], data[length + 1:]]
+
+    def _decode_item(self, data):
+        if len(data) < 1:
+            raise DecodeError("Data underrun while decoding")
+        type_and_length_format = struct.unpack(">B", data[0])[0]
+        item_type = type_and_length_format & self._ITEM_MASK
+        length_format = type_and_length_format & self._ITEM_LENGTH_MASK
+
+        if item_type == self._ITEM_NULL:
+            data = data[1:]
+        else:
+            if length_format == self._ITEM_LENGTH_8:
+                if len(data) - 1 < 1:
+                    raise DecodeError("Data underrun while decoding")
+                length = struct.unpack(">B", data[1])[0]
+                data = data[2:]
+            elif length_format == self._ITEM_LENGTH_16:
+                if len(data) - 1 < 2:
+                    raise DecodeError("Data underrun while decoding")
+                length = struct.unpack(">H", data[1:3])[0]
+                data = data[3:]
+            elif length_format == self._ITEM_LENGTH_32:
+                if len(data) - 1 < 4:
+                    raise DecodeError("Data underrun while decoding")
+                length = struct.unpack(">I", data[1:5])[0]
+                data = data[5:]
+            if len(data) < length:
+                raise DecodeError("Data underrun while decoding")
+            item = data[0:length]
+            data = data[length:]
+
+        if item_type == self._ITEM_DATA:
+            value = item
+        elif item_type == self._ITEM_HASH:
+            value = self._decode_hash(item)
+        elif item_type == self._ITEM_LIST:
+            value = self._decode_array(item)
+        elif item_type == self._ITEM_NULL:
+            value = None
+        else:
+            raise DecodeError("Unknown item type in decode: %02x" % item_type)
+
+        return [value, data]
+
+    def _decode_hash(self, data):
+        ret = {}
+        while len(data) > 0:
+            tag, data = self._decode_tag(data)
+            value, data = self._decode_item(data)
+            ret[tag] = value
+        return ret
+
+    def _decode_array(self, data):
+        ret = []
+        while len(data) > 0:
+            value, data = self._decode_item(data)
+            ret.append(value)
+        return ret
+
 if __name__ == "__main__":
     import doctest
     doctest.testmod()

Modified: experiments/graff-ccapi/python/test.py
==============================================================================
--- experiments/graff-ccapi/python/test.py (original)
+++ experiments/graff-ccapi/python/test.py Mon Oct  5 18:57:57 2009
@@ -8,3 +8,6 @@
        "string": "samplestring" }
 s = cc.to_wire(ss)
 ISC.Util.hexdump(s)
+
+print(ss)
+print cc.from_wire(s)




More information about the bind10-changes mailing list