diff --git a/coolamqp/framing/frames/compilation/compile_definitions.py b/coolamqp/framing/frames/compilation/compile_definitions.py
index 8526beec47bc14d04e12723c142d34d5be27858b..430440d115f9e91e635e0c1fab3688a6cb5135ef 100644
--- a/coolamqp/framing/frames/compilation/compile_definitions.py
+++ b/coolamqp/framing/frames/compilation/compile_definitions.py
@@ -10,6 +10,17 @@ from coolamqp.framing.frames.compilation.utilities import get_constants, get_cla
     frepr
 from coolamqp.framing.frames.base import BASIC_TYPES
 
+TYPE_TRANSLATOR = {
+        'shortstr': 'binary type (max length 255)',
+        'longstr': 'binary type',
+        'table': 'table. See coolamqp.framing.frames.field_table',
+        'bit': 'bool',
+        'octet': 'int, 8 bit unsigned',
+        'short': 'int, 16 bit unsigned',
+        'long': 'int, 32 bit unsigned',
+        'longlong': 'int, 64 bit unsigned',
+        'timestamp': '64 bit signed POSIX timestamp (in seconds)',
+}
 
 def compile_definitions(xml_file='resources/amqp0-9-1.xml', out_file='coolamqp/framing/frames/definitions.py'):
     """parse resources/amqp-0-9-1.xml into """
@@ -102,22 +113,296 @@ from coolamqp.framing.frames.field_table import enframe_table, deframe_table, fr
 
            name_class(cls.name), doxify(None, cls.docs), frepr(cls.name), cls.index, name_class(cls.name))
 
+        is_static = all(property.basic_type not in ('table', 'longstr', 'shortstr') for property in cls.content_properties)
+
         for property in cls.content_properties:
             line('        (%s, %s, %s), # %s\n', frepr(property.name), frepr(property.type), frepr(property.basic_type),
                  frepr(property.label))
         line('    ]\n\n')
 
 
-        line('''    def __init__(%s):'
+        line('''    def __init__(%s):
+        """
+        Create the property list.
+
 ''',
-             u', '.join(['self'] + [name_field(property.name) for property in cls.content_properties])
+             u', '.join(['self'] + [name_field(property.name) for property in cls.content_properties if not property.reserved])
              )
 
-        for property in cls.content_properties:
+        for property in (p for p in cls.content_properties if not p.reserved):
+            line('''        :param %s: %s
+        :type %s: %s (%s in AMQP)
+''',
+                 name_field(property.name), property.label, name_field(property.name), TYPE_TRANSLATOR[property.basic_type], property.type)
+        line('''        """
+''')
+
+        for property in (p for p in cls.content_properties if not p.reserved):
+
             line('        self.%s = %s # %s\n', name_field(property.name), name_field(property.name), property.label)
+        line('''\n    def write_arguments(self, buf):
+''')
+
+        def emit_structs(su):
+            if len(su) == 0:
+                return
+            line("        buf.write(struct.pack('!")
+            line(''.join(a for a, b in su))
+            line("', ")
+            line(', '.join(b for a, b in su))
+            line('))\n')
+
+        def emit_bits(bits):
+            bits = [b for b in bits if b != '0']  # reserved values are out :>
+
+            line("        buf.write(struct.pack('!B', %s))\n",
+                 u' | '.join((u'(int(%s) << %s)' % (bit, position)) for position, bit in enumerate(bits))
+                 )
+
+        good_structs = []
+        written = False
+        bits = []
+        for property in cls.content_properties:
+            val = 'self.' + name_field(property.name) if not property.reserved else BASIC_TYPES[property.basic_type][2]
+
+            if (len(bits) == 8) or ((property.basic_type != 'bit') and len(bits) > 0):
+                emit_bits(bits)
+                bits = []
+                written = True
+
+            if property.basic_type == 'bit':
+                bits.append(val)
+            elif property.reserved:
+                line("        buf.write(" + BASIC_TYPES[property.basic_type][2] + ")\n")
+                written = True
+                continue
+            elif BASIC_TYPES[property.basic_type][1] is None:
+                # struct can't do it
+
+                if property.basic_type == 'longstr':
+                    good_structs.append(('L', 'len(%s)' % (val,)))
+
+                elif property.basic_type == 'shortstr':
+                    good_structs.append(('B', 'len(%s)' % (val,)))
+
+                emit_structs(good_structs)
+                good_structs = []
+
+                if property.basic_type == 'table':
+                    line('        enframe_table(buf, %s)\n' % (val,))
+                    written = True
+                else:
+                    # emit ours
+                    line('        buf.write(' + val + ')\n')
+                    written = True
+            else:
+                # special case - empty string
+                if property.basic_type == 'shortstr' and property.reserved:
+                    continue  # just skip :)
+
+                val = ('self.' + name_field(property.name)) if not property.reserved else frepr(
+                    BASIC_TYPES[property.basic_type][2], sop=six.binary_type)
+
+                good_structs.append((BASIC_TYPES[property.basic_type][1], val))
+                written = True
+        written = written or len(good_structs) > 0
+        emit_structs(good_structs)
+        if len(bits) > 0:
+            emit_bits(bits)
+            written = True
+            bits = []
+
+        if not written:
+            line('        pass # this has a frame, but it''s only default shortstrs\n')
+        line('\n')
+
+        line('''    @staticmethod
+    def from_buffer(buf, start_offset):
+''')
+
+        if len([f for f in cls.content_properties if not f.reserved]) == 0:
+            line("        return %sContentPropertyList()\n\n", name_class(cls.name))
+        else:
+            line("""        assert (len(buf) - start_offset) >= %s.MINIMUM_SIZE, 'Content property list too short!'
+        offset = start_offset   # we will use it to count consumed bytes
+""",
+                 full_class_name)
+            # The simple, or the painful way?
+            has_nonstruct_fields = False
+            for property in cls.content_properties:
+                if BASIC_TYPES[property.basic_type][1] is None:
+                    has_nonstruct_fields = True
+
+            if len(cls.content_properties) == 0:
+                line('        return %s(), 0\n', full_class_name)
+            elif is_static:
+                fieldnames = []
+                formats = []
+
+                bits = []
+                bit_id = 0
+                bits_to_sync_later = {}  # bit_0 => [fLSB, fMSB]
+
+                for property in cls.content_properties:
+                    if property.basic_type == 'bit':
+                        bits.append(None if property.reserved else name_field(property.name))
+
+                        if len(bits) == 8:
+                            fieldnames.append('_bit_%s' % (bit_id,))
+                            formats.append('B')
+                            bits_to_sync_later['_bit_%s' % (bit_id,)] = bits
+                            bits = []
+                            bit_id += 1
+
+                    elif property.reserved:
+                        formats.append('%sx' % (BASIC_TYPES[property.basic_type][0],))
+                    else:
+                        fieldnames.append(name_field(property.name))
+                        formats.append(BASIC_TYPES[property.basic_type][1])
+
+                # sync bits
+                if len(bits) > 0:
+                    fieldnames.append('_bit_%s' % (bit_id,))
+                    formats.append('B')
+                    bits_to_sync_later['_bit_%s' % (bit_id,)] = bits
 
+                line("        %s, = struct.unpack_from('!%s', buf, offset)\n",
+                     u', '.join(fieldnames),
+                     u''.join(formats)
+                     )
 
+                # If there were any bits, unpack them now
+                for var_name, bits in bits_to_sync_later.items():
+                    for bitname, multiplier in zip(bits, (1, 2, 4, 8, 16, 32, 64, 128)):
+                        line("        %s = bool(%s & %s)\n", bitname, var_name, multiplier)
 
+                line("        return %s(%s)", full_class_name, u', '.join([
+                                                                              name_field(property.name) for field in
+                                                                              cls.content_properties if not property.reserved
+                                                                              ]))
+
+            else:
+                def emit_bits(bits):
+
+                    if all(n == '_' for n in bits):
+                        # everything is reserved, lol
+                        line("""        offset += 1
+""")
+                        return
+
+                    line("""        _bit, = struct.unpack_from('!B', buf, offset)
+        offset += 1
+""")
+                    for bit, multiplier in zip(bits, (1, 2, 4, 8, 16, 32, 64, 128)):
+                        if bit != '_':
+                            line("""        %s = bool(_bit & %s)
+""",
+                                 bit, multiplier)
+
+                def emit_structures(ss, ln):
+                    line("""        %s, = struct.unpack_from('!%s', buf, offset)
+        offset += %s
+""",
+                         u', '.join([a[0] for a in ss if not (a[0] == '_' and a[1][-1] == 'x')]),
+                         ''.join([a[1] for a in ss]),
+                         ln
+                         )
+
+                # we'll be counting bytes
+                to_struct = []  # accumulate static field, (var name, struct_code)
+                cur_struct_len = 0  # length of current struct
+
+                bits = []
+                bit_id = 0
+
+                for property in cls.content_properties:
+                    fieldname = '_' if property.reserved else name_field(property.name)
+
+                    if (len(bits) > 0) and (property.basic_type != 'bit'):
+                        emit_bits(bits)
+                        bits = []
+
+                    # offset is current start
+                    # length is length to read
+                    if BASIC_TYPES[property.basic_type][0] is not None:
+                        if property.reserved:
+                            to_struct.append(('_', '%sx' % (BASIC_TYPES[property.basic_type][0],)))
+                        else:
+                            to_struct.append((fieldname, BASIC_TYPES[property.basic_type][1]))
+                        cur_struct_len += BASIC_TYPES[property.basic_type][0]
+                    elif property.basic_type == 'bit':
+                        bits.append(fieldname)
+                    else:
+                        if property.basic_type == 'table':  # oh my god
+                            line("""        %s, delta = deframe_table(buf, offset)
+        offset += delta
+""", name_field(property.name))
+                        else:  # longstr or shortstr
+                            f_q, f_l = ('L', 4) if property.basic_type == 'longstr' else ('B', 1)
+                            to_struct.append(('s_len', f_q))
+                            cur_struct_len += f_l
+                            emit_structures(to_struct, cur_struct_len)
+                            to_struct, cur_struct_len = [], 0
+                            if property.reserved:
+                                line("        offset += s_len\n")
+                            else:
+                                line("        %s = buf[offset:offset+s_len]\n        offset += s_len\n",
+                                     fieldname)
+
+                    # check bits for overflow
+                    if len(bits) == 8:
+                        emit_bits(bits)
+                        bits = []
+
+                if len(bits) > 0:
+                    emit_bits(bits)
+                elif len(to_struct) > 0:
+                    emit_structures(to_struct, cur_struct_len)
+
+                line("        return %sContentPropertyList(%s)",
+                     name_class(cls.name),
+                     u', '.join(name_field(property.name) for property in cls.content_properties if not property.reserved))
+
+            line('\n\n')
+
+        line('    def get_size(self):\n        return ')
+        parts = []
+        accumulator = 0
+        bits = 0
+        for property in cls.content_properties:
+            bt = property.basic_type
+
+            if (bits > 0) and (bt != 'bit'):  # sync bits if not
+                accumulator += int(math.ceil(bits / 8))
+                bits = 0
+
+            if property.basic_type == 'bit':
+                bits += 1
+            elif property.reserved:
+                accumulator += BASIC_TYPES[property.basic_type][3]
+            elif BASIC_TYPES[bt][0] is not None:
+                accumulator += BASIC_TYPES[property.basic_type][0]
+            elif bt == 'shortstr':
+                parts.append('len(self.' + name_field(property.name) + ')')
+                accumulator += 1
+            elif bt == 'longstr':
+                parts.append('len(self.' + name_field(property.name) + ')')
+                accumulator += 4
+            elif bt == 'table':
+                parts.append('frame_table_size(self.' + name_field(property.name) + ')')
+                accumulator += 4
+            else:
+                raise Exception()
+
+        if bits > 0:  # sync bits
+            accumulator += int(math.ceil(bits / 8))
+            bits = 0
+
+        parts.append(repr(accumulator))
+        line(u' + '.join(parts))
+        line('\n\n')
+
+        # ============================================ Do methods for this class
         for method in cls.methods:
             full_class_name = '%s%s' % (name_class(cls.name), name_method(method.name))
 
@@ -225,19 +510,9 @@ from coolamqp.framing.frames.field_table import enframe_table, deframe_table, fr
                     line('        :param %s: %s\n', name_field(field.name),
                          doxify(field.label, field.docs, prefix=12, blank=False))
 
-                tp = {
-                    'shortstr': 'binary type (max length 255)',
-                    'longstr': 'binary type',
-                    'table': 'table. See coolamqp.framing.frames.field_table',
-                    'bit': 'bool',
-                    'octet': 'int, 8 bit unsigned',
-                    'short': 'int, 16 bit unsigned',
-                    'long': 'int, 32 bit unsigned',
-                    'longlong': 'int, 64 bit unsigned',
-                    'timestamp': '64 bit signed POSIX timestamp (in seconds)',
-                }
-
-                line('        :type %s: %s (%s in AMQP)\n', name_field(field.name), tp[field.basic_type], field.type)
+
+
+                line('        :type %s: %s (%s in AMQP)\n', name_field(field.name), TYPE_TRANSLATOR[field.basic_type], field.type)
 
             line('        """\n')
 
diff --git a/coolamqp/framing/frames/compilation/utilities.py b/coolamqp/framing/frames/compilation/utilities.py
index 48f59d293cb33eedb9ea4a305e5e0d8220a2b06f..a0bdd86641969e39b981a55b073e09146137c40b 100644
--- a/coolamqp/framing/frames/compilation/utilities.py
+++ b/coolamqp/framing/frames/compilation/utilities.py
@@ -14,7 +14,7 @@ Method = namedtuple('Method', ('name', 'synchronous', 'index', 'label', 'docs',
                                'sent_by_client', 'sent_by_server', 'constant'))
         # synchronous is bool, constant is bool
         # repponse is a list of method.name
-Property = namedtuple('Property', ('name', 'type', 'label', 'basic_type'))
+Property = namedtuple('Property', ('name', 'type', 'label', 'basic_type', 'reserved'))
 Class_ = namedtuple('Class_', ('name', 'index', 'docs', 'methods', 'content_properties'))   # label is int
 Domain = namedtuple('Domain', ('name', 'type', 'elementary'))   # elementary is bool
 
@@ -109,7 +109,8 @@ def for_method_field(elem): # for <field> in <method>
 
 def for_content_property(elem):
     a = elem.attrib
-    return Property(a['name'], a['domain'], a.get('label', ''), None)
+    return Property(a['name'], a['domain'], a.get('label', ''), None, 'reserved' in a['name'])
+
 
 def for_method(elem):       # for <method>
     a = elem.attrib
diff --git a/coolamqp/framing/frames/definitions.py b/coolamqp/framing/frames/definitions.py
index d95813006e5f8d73213489da1cde9103f1f228b7..c9001741a267ca2bf79a8184f91af5205cc3987d 100644
--- a/coolamqp/framing/frames/definitions.py
+++ b/coolamqp/framing/frames/definitions.py
@@ -118,7 +118,22 @@ class ConnectionContentPropertyList(AMQPContentPropertyList):
 
     ]
 
-    def __init__(self):'
+    def __init__(self):
+        """
+        Create the property list.
+
+        """
+
+    def write_arguments(self, buf):
+        pass # this has a frame, but its only default shortstrs
+
+    @staticmethod
+    def from_buffer(buf, start_offset):
+        return ConnectionContentPropertyList()
+
+    def get_size(self):
+        return 0
+
 
 class ConnectionClose(AMQPMethodPayload):
     """
@@ -860,7 +875,22 @@ class ChannelContentPropertyList(AMQPContentPropertyList):
 
     ]
 
-    def __init__(self):'
+    def __init__(self):
+        """
+        Create the property list.
+
+        """
+
+    def write_arguments(self, buf):
+        pass # this has a frame, but its only default shortstrs
+
+    @staticmethod
+    def from_buffer(buf, start_offset):
+        return ChannelContentPropertyList()
+
+    def get_size(self):
+        return 0
+
 
 class ChannelClose(AMQPMethodPayload):
     """
@@ -1226,7 +1256,22 @@ class ExchangeContentPropertyList(AMQPContentPropertyList):
 
     ]
 
-    def __init__(self):'
+    def __init__(self):
+        """
+        Create the property list.
+
+        """
+
+    def write_arguments(self, buf):
+        pass # this has a frame, but its only default shortstrs
+
+    @staticmethod
+    def from_buffer(buf, start_offset):
+        return ExchangeContentPropertyList()
+
+    def get_size(self):
+        return 0
+
 
 class ExchangeDeclare(AMQPMethodPayload):
     """
@@ -1537,7 +1582,22 @@ class QueueContentPropertyList(AMQPContentPropertyList):
 
     ]
 
-    def __init__(self):'
+    def __init__(self):
+        """
+        Create the property list.
+
+        """
+
+    def write_arguments(self, buf):
+        pass # this has a frame, but its only default shortstrs
+
+    @staticmethod
+    def from_buffer(buf, start_offset):
+        return QueueContentPropertyList()
+
+    def get_size(self):
+        return 0
+
 
 class QueueBind(AMQPMethodPayload):
     """
@@ -2326,7 +2386,37 @@ class BasicContentPropertyList(AMQPContentPropertyList):
         (u'reserved', u'shortstr', u'shortstr'), # u'reserved, must be empty'
     ]
 
-    def __init__(self, content_type, content_encoding, headers, delivery_mode, priority, correlation_id, reply_to, expiration, message_id, timestamp, type, user_id, app_id, reserved):'
+    def __init__(self, content_type, content_encoding, headers, delivery_mode, priority, correlation_id, reply_to, expiration, message_id, timestamp, type, user_id, app_id):
+        """
+        Create the property list.
+
+        :param content_type: MIME content type
+        :type content_type: binary type (max length 255) (shortstr in AMQP)
+        :param content_encoding: MIME content encoding
+        :type content_encoding: binary type (max length 255) (shortstr in AMQP)
+        :param headers: message header field table
+        :type headers: table. See coolamqp.framing.frames.field_table (table in AMQP)
+        :param delivery_mode: non-persistent (1) or persistent (2)
+        :type delivery_mode: int, 8 bit unsigned (octet in AMQP)
+        :param priority: message priority, 0 to 9
+        :type priority: int, 8 bit unsigned (octet in AMQP)
+        :param correlation_id: application correlation identifier
+        :type correlation_id: binary type (max length 255) (shortstr in AMQP)
+        :param reply_to: address to reply to
+        :type reply_to: binary type (max length 255) (shortstr in AMQP)
+        :param expiration: message expiration specification
+        :type expiration: binary type (max length 255) (shortstr in AMQP)
+        :param message_id: application message identifier
+        :type message_id: binary type (max length 255) (shortstr in AMQP)
+        :param timestamp: message timestamp
+        :type timestamp: 64 bit signed POSIX timestamp (in seconds) (timestamp in AMQP)
+        :param type: message type name
+        :type type: binary type (max length 255) (shortstr in AMQP)
+        :param user_id: creating user id
+        :type user_id: binary type (max length 255) (shortstr in AMQP)
+        :param app_id: creating application id
+        :type app_id: binary type (max length 255) (shortstr in AMQP)
+        """
         self.content_type = content_type # MIME content type
         self.content_encoding = content_encoding # MIME content encoding
         self.headers = headers # message header field table
@@ -2340,7 +2430,79 @@ class BasicContentPropertyList(AMQPContentPropertyList):
         self.type = type # message type name
         self.user_id = user_id # creating user id
         self.app_id = app_id # creating application id
-        self.reserved = reserved # reserved, must be empty
+
+    def write_arguments(self, buf):
+        buf.write(struct.pack('!B', len(self.content_type)))
+        buf.write(self.content_type)
+        buf.write(struct.pack('!B', len(self.content_encoding)))
+        buf.write(self.content_encoding)
+        enframe_table(buf, self.headers)
+        buf.write(struct.pack('!BBB', self.delivery_mode, self.priority, len(self.correlation_id)))
+        buf.write(self.correlation_id)
+        buf.write(struct.pack('!B', len(self.reply_to)))
+        buf.write(self.reply_to)
+        buf.write(struct.pack('!B', len(self.expiration)))
+        buf.write(self.expiration)
+        buf.write(struct.pack('!B', len(self.message_id)))
+        buf.write(self.message_id)
+        buf.write(struct.pack('!LB', self.timestamp, len(self.type)))
+        buf.write(self.type)
+        buf.write(struct.pack('!B', len(self.user_id)))
+        buf.write(self.user_id)
+        buf.write(struct.pack('!B', len(self.app_id)))
+        buf.write(self.app_id)
+        buf.write(b'\x00')
+
+    @staticmethod
+    def from_buffer(buf, start_offset):
+        assert (len(buf) - start_offset) >= QueueUnbindOk.MINIMUM_SIZE, 'Content property list too short!'
+        offset = start_offset   # we will use it to count consumed bytes
+        s_len, = struct.unpack_from('!B', buf, offset)
+        offset += 1
+        content_type = buf[offset:offset+s_len]
+        offset += s_len
+        s_len, = struct.unpack_from('!B', buf, offset)
+        offset += 1
+        content_encoding = buf[offset:offset+s_len]
+        offset += s_len
+        headers, delta = deframe_table(buf, offset)
+        offset += delta
+        delivery_mode, priority, s_len, = struct.unpack_from('!BBB', buf, offset)
+        offset += 3
+        correlation_id = buf[offset:offset+s_len]
+        offset += s_len
+        s_len, = struct.unpack_from('!B', buf, offset)
+        offset += 1
+        reply_to = buf[offset:offset+s_len]
+        offset += s_len
+        s_len, = struct.unpack_from('!B', buf, offset)
+        offset += 1
+        expiration = buf[offset:offset+s_len]
+        offset += s_len
+        s_len, = struct.unpack_from('!B', buf, offset)
+        offset += 1
+        message_id = buf[offset:offset+s_len]
+        offset += s_len
+        timestamp, s_len, = struct.unpack_from('!LB', buf, offset)
+        offset += 9
+        type = buf[offset:offset+s_len]
+        offset += s_len
+        s_len, = struct.unpack_from('!B', buf, offset)
+        offset += 1
+        user_id = buf[offset:offset+s_len]
+        offset += s_len
+        s_len, = struct.unpack_from('!B', buf, offset)
+        offset += 1
+        app_id = buf[offset:offset+s_len]
+        offset += s_len
+        s_len, = struct.unpack_from('!B', buf, offset)
+        offset += 1
+        offset += s_len
+        return BasicContentPropertyList(content_type, content_encoding, headers, delivery_mode, priority, correlation_id, reply_to, expiration, message_id, timestamp, type, user_id, app_id)
+
+    def get_size(self):
+        return len(self.content_type) + len(self.content_encoding) + frame_table_size(self.headers) + len(self.correlation_id) + len(self.reply_to) + len(self.expiration) + len(self.message_id) + len(self.type) + len(self.user_id) + len(self.app_id) + 24
+
 
 class BasicAck(AMQPMethodPayload):
     """
@@ -3596,7 +3758,22 @@ class TxContentPropertyList(AMQPContentPropertyList):
 
     ]
 
-    def __init__(self):'
+    def __init__(self):
+        """
+        Create the property list.
+
+        """
+
+    def write_arguments(self, buf):
+        pass # this has a frame, but its only default shortstrs
+
+    @staticmethod
+    def from_buffer(buf, start_offset):
+        return TxContentPropertyList()
+
+    def get_size(self):
+        return 0
+
 
 class TxCommit(AMQPMethodPayload):
     """