Stub out PGPPacket.to_bytes with header serialization
authorW. Trevor King <wking@tremily.us>
Sat, 21 Dec 2013 01:44:00 +0000 (17:44 -0800)
committerW. Trevor King <wking@tremily.us>
Mon, 23 Dec 2013 02:32:14 +0000 (18:32 -0800)
Also setup a body serialization framework along the lines of the
existing packet-parsing framework in PGPPacket.from_bytes.

The header serialization in _serialize_header is just the inverse of
the parsing in _parse_header.  See the _parse_header commit for
references to RFC 4880.

gpg-migrate.py

index 9453494a9dafbcb0f03ab5f401d4fbf19aac71ac..5a3c8f0ef16a96ca0c4ac3ea8790ed2383485fb4 100755 (executable)
@@ -653,7 +653,36 @@ class PGPPacket (dict):
         self['user'] = str(data, 'utf-8')
 
     def to_bytes(self):
-        pass
+        method_name = '_serialize_{}'.format(self._clean_type())
+        method = getattr(self, method_name, None)
+        if not method:
+            raise NotImplementedError(
+                'cannot serialize packet type {!r}'.format(self['type']))
+        body = method()
+        self['length'] = len(body)
+        return b''.join([
+            self._serialize_header(),
+            body,
+            ])
+
+    def _serialize_header(self):
+        always_one = 1
+        new_format = 0
+        type_code = self._reverse(self._packet_types, self['type'])
+        packet_tag = (
+            always_one * (1 << 7) |
+            new_format * (1 << 6) |
+            type_code * (1 << 2) |
+            self['length-type']
+            )
+        length_bytes, length_type = self._old_format_packet_length_type[
+            self['length-type']]
+        length_format = '>{}'.format(length_type)
+        length_data = _struct.pack(length_format, self['length'])
+        return b''.join([
+            bytes([packet_tag]),
+            length_data,
+            ])
 
 
 def packets_from_bytes(data):