# Autogenerated - do not edit
import calendar
import datetime
import struct

from . import table


PREAMBLE = 'AMQP\x00\x00\x09\x01'

METHOD_CONNECTION_START         = 0x000A000A 	# 10,10 655370
METHOD_CONNECTION_START_OK      = 0x000A000B 	# 10,11 655371
METHOD_CONNECTION_SECURE        = 0x000A0014 	# 10,20 655380
METHOD_CONNECTION_SECURE_OK     = 0x000A0015 	# 10,21 655381
METHOD_CONNECTION_TUNE          = 0x000A001E 	# 10,30 655390
METHOD_CONNECTION_TUNE_OK       = 0x000A001F 	# 10,31 655391
METHOD_CONNECTION_OPEN          = 0x000A0028 	# 10,40 655400
METHOD_CONNECTION_OPEN_OK       = 0x000A0029 	# 10,41 655401
METHOD_CONNECTION_CLOSE         = 0x000A0032 	# 10,50 655410
METHOD_CONNECTION_CLOSE_OK      = 0x000A0033 	# 10,51 655411
METHOD_CHANNEL_OPEN             = 0x0014000A 	# 20,10 1310730
METHOD_CHANNEL_OPEN_OK          = 0x0014000B 	# 20,11 1310731
METHOD_CHANNEL_FLOW             = 0x00140014 	# 20,20 1310740
METHOD_CHANNEL_FLOW_OK          = 0x00140015 	# 20,21 1310741
METHOD_CHANNEL_CLOSE            = 0x00140028 	# 20,40 1310760
METHOD_CHANNEL_CLOSE_OK         = 0x00140029 	# 20,41 1310761
METHOD_EXCHANGE_DECLARE         = 0x0028000A 	# 40,10 2621450
METHOD_EXCHANGE_DECLARE_OK      = 0x0028000B 	# 40,11 2621451
METHOD_EXCHANGE_DELETE          = 0x00280014 	# 40,20 2621460
METHOD_EXCHANGE_DELETE_OK       = 0x00280015 	# 40,21 2621461
METHOD_EXCHANGE_BIND            = 0x0028001E 	# 40,30 2621470
METHOD_EXCHANGE_BIND_OK         = 0x0028001F 	# 40,31 2621471
METHOD_EXCHANGE_UNBIND          = 0x00280028 	# 40,40 2621480
METHOD_EXCHANGE_UNBIND_OK       = 0x00280033 	# 40,51 2621491
METHOD_QUEUE_DECLARE            = 0x0032000A 	# 50,10 3276810
METHOD_QUEUE_DECLARE_OK         = 0x0032000B 	# 50,11 3276811
METHOD_QUEUE_BIND               = 0x00320014 	# 50,20 3276820
METHOD_QUEUE_BIND_OK            = 0x00320015 	# 50,21 3276821
METHOD_QUEUE_PURGE              = 0x0032001E 	# 50,30 3276830
METHOD_QUEUE_PURGE_OK           = 0x0032001F 	# 50,31 3276831
METHOD_QUEUE_DELETE             = 0x00320028 	# 50,40 3276840
METHOD_QUEUE_DELETE_OK          = 0x00320029 	# 50,41 3276841
METHOD_QUEUE_UNBIND             = 0x00320032 	# 50,50 3276850
METHOD_QUEUE_UNBIND_OK          = 0x00320033 	# 50,51 3276851
METHOD_BASIC_QOS                = 0x003C000A 	# 60,10 3932170
METHOD_BASIC_QOS_OK             = 0x003C000B 	# 60,11 3932171
METHOD_BASIC_CONSUME            = 0x003C0014 	# 60,20 3932180
METHOD_BASIC_CONSUME_OK         = 0x003C0015 	# 60,21 3932181
METHOD_BASIC_CANCEL             = 0x003C001E 	# 60,30 3932190
METHOD_BASIC_CANCEL_OK          = 0x003C001F 	# 60,31 3932191
METHOD_BASIC_PUBLISH            = 0x003C0028 	# 60,40 3932200
METHOD_BASIC_RETURN             = 0x003C0032 	# 60,50 3932210
METHOD_BASIC_DELIVER            = 0x003C003C 	# 60,60 3932220
METHOD_BASIC_GET                = 0x003C0046 	# 60,70 3932230
METHOD_BASIC_GET_OK             = 0x003C0047 	# 60,71 3932231
METHOD_BASIC_GET_EMPTY          = 0x003C0048 	# 60,72 3932232
METHOD_BASIC_ACK                = 0x003C0050 	# 60,80 3932240
METHOD_BASIC_REJECT             = 0x003C005A 	# 60,90 3932250
METHOD_BASIC_RECOVER_ASYNC      = 0x003C0064 	# 60,100 3932260
METHOD_BASIC_RECOVER            = 0x003C006E 	# 60,110 3932270
METHOD_BASIC_RECOVER_OK         = 0x003C006F 	# 60,111 3932271
METHOD_BASIC_NACK               = 0x003C0078 	# 60,120 3932280
METHOD_CONFIRM_SELECT           = 0x0055000A 	# 85,10 5570570
METHOD_CONFIRM_SELECT_OK        = 0x0055000B 	# 85,11 5570571

CLASS_BASIC             = 0x003C




class Frame(dict):
    has_content = False
    is_error = False


class FrameConnectionStart(Frame):
    name = 'connection.start'
    method_id = METHOD_CONNECTION_START

def decode_connection_start(data, offset):
    frame = FrameConnectionStart()
    (frame['version_major'],
     frame['version_minor']) = struct.unpack_from('!BB', data, offset)
    offset += 1+1
    frame['server_properties'], offset = table.decode(data, offset)
    (str_len,) = struct.unpack_from('!I', data, offset)
    offset += 4
    frame['mechanisms'] = data[offset : offset+str_len]
    offset += str_len
    (str_len,) = struct.unpack_from('!I', data, offset)
    offset += 4
    frame['locales'] = data[offset : offset+str_len]
    offset += str_len
    return frame, offset


class FrameConnectionSecure(Frame):
    name = 'connection.secure'
    method_id = METHOD_CONNECTION_SECURE

def decode_connection_secure(data, offset):
    frame = FrameConnectionSecure()
    (str_len,) = struct.unpack_from('!I', data, offset)
    offset += 4
    frame['challenge'] = data[offset : offset+str_len]
    offset += str_len
    return frame, offset


class FrameConnectionTune(Frame):
    name = 'connection.tune'
    method_id = METHOD_CONNECTION_TUNE

def decode_connection_tune(data, offset):
    frame = FrameConnectionTune()
    (frame['channel_max'],
     frame['frame_max'],
     frame['heartbeat']) = struct.unpack_from('!HIH', data, offset)
    offset += 2+4+2
    return frame, offset


class FrameConnectionOpenOk(Frame):
    name = 'connection.open_ok'
    method_id = METHOD_CONNECTION_OPEN_OK

def decode_connection_open_ok(data, offset):
    frame = FrameConnectionOpenOk()
    (str_len,) = struct.unpack_from('!B', data, offset)
    offset += 1
    frame['known_hosts'] = data[offset : offset+str_len]
    offset += str_len
    return frame, offset


class FrameConnectionClose(Frame):
    name = 'connection.close'
    method_id = METHOD_CONNECTION_CLOSE

def decode_connection_close(data, offset):
    frame = FrameConnectionClose()
    (frame['reply_code'],
     str_len) = struct.unpack_from('!HB', data, offset)
    offset += 2+1
    frame['reply_text'] = data[offset : offset+str_len]
    offset += str_len
    (frame['class_id'],
     frame['method_id']) = struct.unpack_from('!HH', data, offset)
    offset += 2+2
    return frame, offset


class FrameConnectionCloseOk(Frame):
    name = 'connection.close_ok'
    method_id = METHOD_CONNECTION_CLOSE_OK

def decode_connection_close_ok(data, offset):
    frame = FrameConnectionCloseOk()
    return frame, offset


class FrameChannelOpenOk(Frame):
    name = 'channel.open_ok'
    method_id = METHOD_CHANNEL_OPEN_OK

def decode_channel_open_ok(data, offset):
    frame = FrameChannelOpenOk()
    (str_len,) = struct.unpack_from('!I', data, offset)
    offset += 4
    frame['channel_id'] = data[offset : offset+str_len]
    offset += str_len
    return frame, offset


class FrameChannelFlow(Frame):
    name = 'channel.flow'
    method_id = METHOD_CHANNEL_FLOW

def decode_channel_flow(data, offset):
    frame = FrameChannelFlow()
    (bits,) = struct.unpack_from('!B', data, offset)
    frame['active'] = bool(bits & 0x1)
    offset += 1
    return frame, offset


class FrameChannelFlowOk(Frame):
    name = 'channel.flow_ok'
    method_id = METHOD_CHANNEL_FLOW_OK

def decode_channel_flow_ok(data, offset):
    frame = FrameChannelFlowOk()
    (bits,) = struct.unpack_from('!B', data, offset)
    frame['active'] = bool(bits & 0x1)
    offset += 1
    return frame, offset


class FrameChannelClose(Frame):
    name = 'channel.close'
    method_id = METHOD_CHANNEL_CLOSE

def decode_channel_close(data, offset):
    frame = FrameChannelClose()
    (frame['reply_code'],
     str_len) = struct.unpack_from('!HB', data, offset)
    offset += 2+1
    frame['reply_text'] = data[offset : offset+str_len]
    offset += str_len
    (frame['class_id'],
     frame['method_id']) = struct.unpack_from('!HH', data, offset)
    offset += 2+2
    return frame, offset


class FrameChannelCloseOk(Frame):
    name = 'channel.close_ok'
    method_id = METHOD_CHANNEL_CLOSE_OK

def decode_channel_close_ok(data, offset):
    frame = FrameChannelCloseOk()
    return frame, offset


class FrameExchangeDeclareOk(Frame):
    name = 'exchange.declare_ok'
    method_id = METHOD_EXCHANGE_DECLARE_OK

def decode_exchange_declare_ok(data, offset):
    frame = FrameExchangeDeclareOk()
    return frame, offset


class FrameExchangeDeleteOk(Frame):
    name = 'exchange.delete_ok'
    method_id = METHOD_EXCHANGE_DELETE_OK

def decode_exchange_delete_ok(data, offset):
    frame = FrameExchangeDeleteOk()
    return frame, offset


class FrameExchangeBindOk(Frame):
    name = 'exchange.bind_ok'
    method_id = METHOD_EXCHANGE_BIND_OK

def decode_exchange_bind_ok(data, offset):
    frame = FrameExchangeBindOk()
    return frame, offset


class FrameExchangeUnbindOk(Frame):
    name = 'exchange.unbind_ok'
    method_id = METHOD_EXCHANGE_UNBIND_OK

def decode_exchange_unbind_ok(data, offset):
    frame = FrameExchangeUnbindOk()
    return frame, offset


class FrameQueueDeclareOk(Frame):
    name = 'queue.declare_ok'
    method_id = METHOD_QUEUE_DECLARE_OK

def decode_queue_declare_ok(data, offset):
    frame = FrameQueueDeclareOk()
    (str_len,) = struct.unpack_from('!B', data, offset)
    offset += 1
    frame['queue'] = data[offset : offset+str_len]
    offset += str_len
    (frame['message_count'],
     frame['consumer_count']) = struct.unpack_from('!II', data, offset)
    offset += 4+4
    return frame, offset


class FrameQueueBindOk(Frame):
    name = 'queue.bind_ok'
    method_id = METHOD_QUEUE_BIND_OK

def decode_queue_bind_ok(data, offset):
    frame = FrameQueueBindOk()
    return frame, offset


class FrameQueuePurgeOk(Frame):
    name = 'queue.purge_ok'
    method_id = METHOD_QUEUE_PURGE_OK

def decode_queue_purge_ok(data, offset):
    frame = FrameQueuePurgeOk()
    (frame['message_count'],) = struct.unpack_from('!I', data, offset)
    offset += 4
    return frame, offset


class FrameQueueDeleteOk(Frame):
    name = 'queue.delete_ok'
    method_id = METHOD_QUEUE_DELETE_OK

def decode_queue_delete_ok(data, offset):
    frame = FrameQueueDeleteOk()
    (frame['message_count'],) = struct.unpack_from('!I', data, offset)
    offset += 4
    return frame, offset


class FrameQueueUnbindOk(Frame):
    name = 'queue.unbind_ok'
    method_id = METHOD_QUEUE_UNBIND_OK

def decode_queue_unbind_ok(data, offset):
    frame = FrameQueueUnbindOk()
    return frame, offset


class FrameBasicQosOk(Frame):
    name = 'basic.qos_ok'
    method_id = METHOD_BASIC_QOS_OK

def decode_basic_qos_ok(data, offset):
    frame = FrameBasicQosOk()
    return frame, offset


class FrameBasicConsumeOk(Frame):
    name = 'basic.consume_ok'
    method_id = METHOD_BASIC_CONSUME_OK

def decode_basic_consume_ok(data, offset):
    frame = FrameBasicConsumeOk()
    (str_len,) = struct.unpack_from('!B', data, offset)
    offset += 1
    frame['consumer_tag'] = data[offset : offset+str_len]
    offset += str_len
    return frame, offset


class FrameBasicCancelOk(Frame):
    name = 'basic.cancel_ok'
    method_id = METHOD_BASIC_CANCEL_OK

def decode_basic_cancel_ok(data, offset):
    frame = FrameBasicCancelOk()
    (str_len,) = struct.unpack_from('!B', data, offset)
    offset += 1
    frame['consumer_tag'] = data[offset : offset+str_len]
    offset += str_len
    return frame, offset


class FrameBasicReturn(Frame):
    name = 'basic.return'
    method_id = METHOD_BASIC_RETURN
    has_content = True
    class_id = CLASS_BASIC

def decode_basic_return(data, offset):
    frame = FrameBasicReturn()
    (frame['reply_code'],
     str_len) = struct.unpack_from('!HB', data, offset)
    offset += 2+1
    frame['reply_text'] = data[offset : offset+str_len]
    offset += str_len
    (str_len,) = struct.unpack_from('!B', data, offset)
    offset += 1
    frame['exchange'] = data[offset : offset+str_len]
    offset += str_len
    (str_len,) = struct.unpack_from('!B', data, offset)
    offset += 1
    frame['routing_key'] = data[offset : offset+str_len]
    offset += str_len
    return frame, offset


class FrameBasicDeliver(Frame):
    name = 'basic.deliver'
    method_id = METHOD_BASIC_DELIVER
    has_content = True
    class_id = CLASS_BASIC

def decode_basic_deliver(data, offset):
    frame = FrameBasicDeliver()
    (str_len,) = struct.unpack_from('!B', data, offset)
    offset += 1
    frame['consumer_tag'] = data[offset : offset+str_len]
    offset += str_len
    (frame['delivery_tag'],
     bits,
     str_len) = struct.unpack_from('!QBB', data, offset)
    frame['redelivered'] = bool(bits & 0x1)
    offset += 8+1+1
    frame['exchange'] = data[offset : offset+str_len]
    offset += str_len
    (str_len,) = struct.unpack_from('!B', data, offset)
    offset += 1
    frame['routing_key'] = data[offset : offset+str_len]
    offset += str_len
    return frame, offset


class FrameBasicGetOk(Frame):
    name = 'basic.get_ok'
    method_id = METHOD_BASIC_GET_OK
    has_content = True
    class_id = CLASS_BASIC

def decode_basic_get_ok(data, offset):
    frame = FrameBasicGetOk()
    (frame['delivery_tag'],
     bits,
     str_len) = struct.unpack_from('!QBB', data, offset)
    frame['redelivered'] = bool(bits & 0x1)
    offset += 8+1+1
    frame['exchange'] = data[offset : offset+str_len]
    offset += str_len
    (str_len,) = struct.unpack_from('!B', data, offset)
    offset += 1
    frame['routing_key'] = data[offset : offset+str_len]
    offset += str_len
    (frame['message_count'],) = struct.unpack_from('!I', data, offset)
    offset += 4
    return frame, offset


class FrameBasicGetEmpty(Frame):
    name = 'basic.get_empty'
    method_id = METHOD_BASIC_GET_EMPTY

def decode_basic_get_empty(data, offset):
    frame = FrameBasicGetEmpty()
    (str_len,) = struct.unpack_from('!B', data, offset)
    offset += 1
    frame['cluster_id'] = data[offset : offset+str_len]
    offset += str_len
    return frame, offset


class FrameBasicAck(Frame):
    name = 'basic.ack'
    method_id = METHOD_BASIC_ACK

def decode_basic_ack(data, offset):
    frame = FrameBasicAck()
    (frame['delivery_tag'],
     bits) = struct.unpack_from('!QB', data, offset)
    frame['multiple'] = bool(bits & 0x1)
    offset += 8+1
    return frame, offset


class FrameBasicRecoverOk(Frame):
    name = 'basic.recover_ok'
    method_id = METHOD_BASIC_RECOVER_OK

def decode_basic_recover_ok(data, offset):
    frame = FrameBasicRecoverOk()
    return frame, offset


class FrameConfirmSelectOk(Frame):
    name = 'confirm.select_ok'
    method_id = METHOD_CONFIRM_SELECT_OK

def decode_confirm_select_ok(data, offset):
    frame = FrameConfirmSelectOk()
    return frame, offset



METHODS = {
    METHOD_CONNECTION_START:        decode_connection_start,
    METHOD_CONNECTION_SECURE:       decode_connection_secure,
    METHOD_CONNECTION_TUNE:         decode_connection_tune,
    METHOD_CONNECTION_OPEN_OK:      decode_connection_open_ok,
    METHOD_CONNECTION_CLOSE:        decode_connection_close,
    METHOD_CONNECTION_CLOSE_OK:     decode_connection_close_ok,
    METHOD_CHANNEL_OPEN_OK:         decode_channel_open_ok,
    METHOD_CHANNEL_FLOW:            decode_channel_flow,
    METHOD_CHANNEL_FLOW_OK:         decode_channel_flow_ok,
    METHOD_CHANNEL_CLOSE:           decode_channel_close,
    METHOD_CHANNEL_CLOSE_OK:        decode_channel_close_ok,
    METHOD_EXCHANGE_DECLARE_OK:     decode_exchange_declare_ok,
    METHOD_EXCHANGE_DELETE_OK:      decode_exchange_delete_ok,
    METHOD_EXCHANGE_BIND_OK:        decode_exchange_bind_ok,
    METHOD_EXCHANGE_UNBIND_OK:      decode_exchange_unbind_ok,
    METHOD_QUEUE_DECLARE_OK:        decode_queue_declare_ok,
    METHOD_QUEUE_BIND_OK:           decode_queue_bind_ok,
    METHOD_QUEUE_PURGE_OK:          decode_queue_purge_ok,
    METHOD_QUEUE_DELETE_OK:         decode_queue_delete_ok,
    METHOD_QUEUE_UNBIND_OK:         decode_queue_unbind_ok,
    METHOD_BASIC_QOS_OK:            decode_basic_qos_ok,
    METHOD_BASIC_CONSUME_OK:        decode_basic_consume_ok,
    METHOD_BASIC_CANCEL_OK:         decode_basic_cancel_ok,
    METHOD_BASIC_RETURN:            decode_basic_return,
    METHOD_BASIC_DELIVER:           decode_basic_deliver,
    METHOD_BASIC_GET_OK:            decode_basic_get_ok,
    METHOD_BASIC_GET_EMPTY:         decode_basic_get_empty,
    METHOD_BASIC_ACK:               decode_basic_ack,
    METHOD_BASIC_RECOVER_OK:        decode_basic_recover_ok,
    METHOD_CONFIRM_SELECT_OK:       decode_confirm_select_ok,
}


def decode_basic_properties(data, offset):
    props = {}
    flags, = struct.unpack_from('!H', data, offset)
    offset += 2
    assert (flags & 0x01) == 0
    if (flags & 0x8000): # 1 << 15
        (str_len,) = struct.unpack_from('!B', data, offset)
        offset += 1
        props['content_type'] = data[offset : offset+str_len]
        offset += str_len
    if (flags & 0x4000): # 1 << 14
        (str_len,) = struct.unpack_from('!B', data, offset)
        offset += 1
        props['content_encoding'] = data[offset : offset+str_len]
        offset += str_len
    if (flags & 0x2000): # 1 << 13
        props['headers'], offset = table.decode(data, offset)
    if (flags & 0x1000): # 1 << 12
        (props['delivery_mode'],) = struct.unpack_from('!B', data, offset)
        offset += 1
    if (flags & 0x0800): # 1 << 11
        (props['priority'],) = struct.unpack_from('!B', data, offset)
        offset += 1
    if (flags & 0x0400): # 1 << 10
        (str_len,) = struct.unpack_from('!B', data, offset)
        offset += 1
        props['correlation_id'] = data[offset : offset+str_len]
        offset += str_len
    if (flags & 0x0200): # 1 << 9
        (str_len,) = struct.unpack_from('!B', data, offset)
        offset += 1
        props['reply_to'] = data[offset : offset+str_len]
        offset += str_len
    if (flags & 0x0100): # 1 << 8
        (str_len,) = struct.unpack_from('!B', data, offset)
        offset += 1
        props['expiration'] = data[offset : offset+str_len]
        offset += str_len
    if (flags & 0x0080): # 1 << 7
        (str_len,) = struct.unpack_from('!B', data, offset)
        offset += 1
        props['message_id'] = data[offset : offset+str_len]
        offset += str_len
    if (flags & 0x0040): # 1 << 6
        (props['timestamp'],) = struct.unpack_from('!Q', data, offset)
        offset += 8
    if (flags & 0x0020): # 1 << 5
        (str_len,) = struct.unpack_from('!B', data, offset)
        offset += 1
        props['type_'] = data[offset : offset+str_len]
        offset += str_len
    if (flags & 0x0010): # 1 << 4
        (str_len,) = struct.unpack_from('!B', data, offset)
        offset += 1
        props['user_id'] = data[offset : offset+str_len]
        offset += str_len
    if (flags & 0x0008): # 1 << 3
        (str_len,) = struct.unpack_from('!B', data, offset)
        offset += 1
        props['app_id'] = data[offset : offset+str_len]
        offset += str_len
    if (flags & 0x0004): # 1 << 2
        (str_len,) = struct.unpack_from('!B', data, offset)
        offset += 1
        props['cluster_id'] = data[offset : offset+str_len]
        offset += str_len
    return props, offset


PROPS = {
    CLASS_BASIC: decode_basic_properties, 	# 60
}


# client_properties=None mechanism='PLAIN' response=None locale='en_US'
def encode_connection_start_ok(client_properties, mechanism, response, locale):
    client_properties_raw = table.encode(client_properties)
    return ( (0x01,
              ''.join((
                struct.pack('!I', METHOD_CONNECTION_START_OK),
                client_properties_raw,
                struct.pack('!B', len(mechanism)),
                mechanism,
                struct.pack('!I', len(response)),
                response,
                struct.pack('!B', len(locale)),
                locale,
              ))
           ), )

# response=None
def encode_connection_secure_ok(response):
    return ( (0x01,
              ''.join((
                struct.pack('!II', METHOD_CONNECTION_SECURE_OK, len(response)),
                response,
              ))
           ), )

# channel_max=0 frame_max=0 heartbeat=0
def encode_connection_tune_ok(channel_max, frame_max, heartbeat):
    return ( (0x01,
                struct.pack('!IHIH', METHOD_CONNECTION_TUNE_OK, channel_max, frame_max, heartbeat),
           ), )

# virtual_host='/' capabilities='' insist=False
def encode_connection_open(virtual_host):
    return ( (0x01,
              ''.join((
                struct.pack('!IB', METHOD_CONNECTION_OPEN, len(virtual_host)),
                virtual_host,
                "\x00\x00",
              ))
           ), )

# reply_code=None reply_text='' class_id=None method_id=None
def encode_connection_close(reply_code, reply_text, class_id, method_id):
    return ( (0x01,
              ''.join((
                struct.pack('!IHB', METHOD_CONNECTION_CLOSE, reply_code, len(reply_text)),
                reply_text,
                struct.pack('!HH', class_id, method_id),
              ))
           ), )

# 
def encode_connection_close_ok():
    return ( (0x01,
                struct.pack('!I', METHOD_CONNECTION_CLOSE_OK),
           ), )

# out_of_band=''
def encode_channel_open(out_of_band):
    return ( (0x01,
                struct.pack('!IB', METHOD_CHANNEL_OPEN, 0),
           ), )

# active=None
def encode_channel_flow(active):
    return ( (0x01,
                struct.pack('!IB', METHOD_CHANNEL_FLOW, (active and 0x1 or 0)),
           ), )

# active=None
def encode_channel_flow_ok(active):
    return ( (0x01,
                struct.pack('!IB', METHOD_CHANNEL_FLOW_OK, (active and 0x1 or 0)),
           ), )

# reply_code=None reply_text='' class_id=None method_id=None
def encode_channel_close(reply_code, reply_text, class_id, method_id):
    return ( (0x01,
              ''.join((
                struct.pack('!IHB', METHOD_CHANNEL_CLOSE, reply_code, len(reply_text)),
                reply_text,
                struct.pack('!HH', class_id, method_id),
              ))
           ), )

# 
def encode_channel_close_ok():
    return ( (0x01,
                struct.pack('!I', METHOD_CHANNEL_CLOSE_OK),
           ), )

# ticket=0 exchange=None type_='direct' passive=False durable=False auto_delete=False internal=False nowait=False arguments={}
def encode_exchange_declare(exchange, type_, passive, durable, auto_delete, internal, arguments):
    arguments_raw = table.encode(arguments)
    return ( (0x01,
              ''.join((
                struct.pack('!IHB', METHOD_EXCHANGE_DECLARE, 0, len(exchange)),
                exchange,
                struct.pack('!B', len(type_)),
                type_,
                struct.pack('!B', (passive and 0x1 or 0) | (durable and 0x2 or 0) | (auto_delete and 0x4 or 0) | (internal and 0x8 or 0)),
                arguments_raw,
              ))
           ), )

# ticket=0 exchange=None if_unused=False nowait=False
def encode_exchange_delete(exchange, if_unused):
    return ( (0x01,
              ''.join((
                struct.pack('!IHB', METHOD_EXCHANGE_DELETE, 0, len(exchange)),
                exchange,
                struct.pack('!B', (if_unused and 0x1 or 0)),
              ))
           ), )

# ticket=0 destination=None source=None routing_key='' nowait=False arguments={}
def encode_exchange_bind(destination, source, routing_key, arguments):
    arguments_raw = table.encode(arguments)
    return ( (0x01,
              ''.join((
                struct.pack('!IHB', METHOD_EXCHANGE_BIND, 0, len(destination)),
                destination,
                struct.pack('!B', len(source)),
                source,
                struct.pack('!B', len(routing_key)),
                routing_key,
                "\x00",
                arguments_raw,
              ))
           ), )

# ticket=0 destination=None source=None routing_key='' nowait=False arguments={}
def encode_exchange_unbind(destination, source, routing_key, arguments):
    arguments_raw = table.encode(arguments)
    return ( (0x01,
              ''.join((
                struct.pack('!IHB', METHOD_EXCHANGE_UNBIND, 0, len(destination)),
                destination,
                struct.pack('!B', len(source)),
                source,
                struct.pack('!B', len(routing_key)),
                routing_key,
                "\x00",
                arguments_raw,
              ))
           ), )

# ticket=0 queue='' passive=False durable=False exclusive=False auto_delete=False nowait=False arguments={}
def encode_queue_declare(queue, passive, durable, exclusive, auto_delete, arguments):
    arguments_raw = table.encode(arguments)
    return ( (0x01,
              ''.join((
                struct.pack('!IHB', METHOD_QUEUE_DECLARE, 0, len(queue)),
                queue,
                struct.pack('!B', (passive and 0x1 or 0) | (durable and 0x2 or 0) | (exclusive and 0x4 or 0) | (auto_delete and 0x8 or 0)),
                arguments_raw,
              ))
           ), )

# ticket=0 queue='' exchange=None routing_key='' nowait=False arguments={}
def encode_queue_bind(queue, exchange, routing_key, arguments):
    arguments_raw = table.encode(arguments)
    return ( (0x01,
              ''.join((
                struct.pack('!IHB', METHOD_QUEUE_BIND, 0, len(queue)),
                queue,
                struct.pack('!B', len(exchange)),
                exchange,
                struct.pack('!B', len(routing_key)),
                routing_key,
                "\x00",
                arguments_raw,
              ))
           ), )

# ticket=0 queue='' nowait=False
def encode_queue_purge(queue):
    return ( (0x01,
              ''.join((
                struct.pack('!IHB', METHOD_QUEUE_PURGE, 0, len(queue)),
                queue,
                "\x00",
              ))
           ), )

# ticket=0 queue='' if_unused=False if_empty=False nowait=False
def encode_queue_delete(queue, if_unused, if_empty):
    return ( (0x01,
              ''.join((
                struct.pack('!IHB', METHOD_QUEUE_DELETE, 0, len(queue)),
                queue,
                struct.pack('!B', (if_unused and 0x1 or 0) | (if_empty and 0x2 or 0)),
              ))
           ), )

# ticket=0 queue='' exchange=None routing_key='' arguments={}
def encode_queue_unbind(queue, exchange, routing_key, arguments):
    arguments_raw = table.encode(arguments)
    return ( (0x01,
              ''.join((
                struct.pack('!IHB', METHOD_QUEUE_UNBIND, 0, len(queue)),
                queue,
                struct.pack('!B', len(exchange)),
                exchange,
                struct.pack('!B', len(routing_key)),
                routing_key,
                arguments_raw,
              ))
           ), )

# prefetch_size=0 prefetch_count=0 global_=False
def encode_basic_qos(prefetch_size, prefetch_count, global_):
    return ( (0x01,
                struct.pack('!IIHB', METHOD_BASIC_QOS, prefetch_size, prefetch_count, (global_ and 0x1 or 0)),
           ), )

# ticket=0 queue='' consumer_tag='' no_local=False no_ack=False exclusive=False nowait=False arguments={}
def encode_basic_consume(queue, consumer_tag, no_local, no_ack, exclusive, arguments):
    arguments_raw = table.encode(arguments)
    return ( (0x01,
              ''.join((
                struct.pack('!IHB', METHOD_BASIC_CONSUME, 0, len(queue)),
                queue,
                struct.pack('!B', len(consumer_tag)),
                consumer_tag,
                struct.pack('!B', (no_local and 0x1 or 0) | (no_ack and 0x2 or 0) | (exclusive and 0x4 or 0)),
                arguments_raw,
              ))
           ), )

# consumer_tag=None nowait=False
def encode_basic_cancel(consumer_tag):
    return ( (0x01,
              ''.join((
                struct.pack('!IB', METHOD_BASIC_CANCEL, len(consumer_tag)),
                consumer_tag,
                "\x00",
              ))
           ), )

# ticket=0 exchange='' routing_key='' mandatory=False immediate=False user_headers={} payload='' frame_size=None
def encode_basic_publish(exchange, routing_key, mandatory, immediate, user_headers, body, frame_size):
    props, headers = split_headers(user_headers, BASIC_PROPS_SET)
    if headers:
        props['headers'] = headers
    return [ (0x01,
              ''.join((
                struct.pack('!IHB', METHOD_BASIC_PUBLISH, 0, len(exchange)),
                exchange,
                struct.pack('!B', len(routing_key)),
                routing_key,
                struct.pack('!B', (mandatory and 0x1 or 0) | (immediate and 0x2 or 0)),
              ))
           ),
           encode_basic_properties(len(body), props),
        ] + encode_body(body, frame_size)

# ticket=0 queue='' no_ack=False
def encode_basic_get(queue, no_ack):
    return ( (0x01,
              ''.join((
                struct.pack('!IHB', METHOD_BASIC_GET, 0, len(queue)),
                queue,
                struct.pack('!B', (no_ack and 0x1 or 0)),
              ))
           ), )

# delivery_tag=0 multiple=False
def encode_basic_ack(delivery_tag, multiple):
    return ( (0x01,
                struct.pack('!IQB', METHOD_BASIC_ACK, delivery_tag, (multiple and 0x1 or 0)),
           ), )

# delivery_tag=None requeue=True
def encode_basic_reject(delivery_tag, requeue):
    return ( (0x01,
                struct.pack('!IQB', METHOD_BASIC_REJECT, delivery_tag, (requeue and 0x1 or 0)),
           ), )

# requeue=False
def encode_basic_recover_async(requeue):
    return ( (0x01,
                struct.pack('!IB', METHOD_BASIC_RECOVER_ASYNC, (requeue and 0x1 or 0)),
           ), )

# requeue=False
def encode_basic_recover(requeue):
    return ( (0x01,
                struct.pack('!IB', METHOD_BASIC_RECOVER, (requeue and 0x1 or 0)),
           ), )

# delivery_tag=0 multiple=False requeue=True
def encode_basic_nack(delivery_tag, multiple, requeue):
    return ( (0x01,
                struct.pack('!IQB', METHOD_BASIC_NACK, delivery_tag, (multiple and 0x1 or 0) | (requeue and 0x2 or 0)),
           ), )

# nowait=False
def encode_confirm_select():
    return ( (0x01,
                struct.pack('!IB', METHOD_CONFIRM_SELECT, 0),
           ), )

BASIC_PROPS_SET = set((
    "content_type",      # shortstr
    "content_encoding",  # shortstr
    "headers",           # table
    "delivery_mode",     # octet
    "priority",          # octet
    "correlation_id",    # shortstr
    "reply_to",          # shortstr
    "expiration",        # shortstr
    "message_id",        # shortstr
    "timestamp",         # timestamp
    "type_",             # shortstr
    "user_id",           # shortstr
    "app_id",            # shortstr
    "cluster_id",        # shortstr
    ))

ENCODE_PROPS_BASIC = {
    'content_type': (
        0,
        0x8000, # (1 << 15)
        lambda val: ''.join((
                struct.pack('!B', len(val)),
                val,
        )) ),
    'content_encoding': (
        1,
        0x4000, # (1 << 14)
        lambda val: ''.join((
                struct.pack('!B', len(val)),
                val,
        )) ),
    'headers': (
        2,
        0x2000, # (1 << 13)
        lambda val: table.encode(val)
        ),
    'delivery_mode': (
        3,
        0x1000, # (1 << 12)
        lambda val: struct.pack('!B', val)
        ),
    'priority': (
        4,
        0x0800, # (1 << 11)
        lambda val: struct.pack('!B', val)
        ),
    'correlation_id': (
        5,
        0x0400, # (1 << 10)
        lambda val: ''.join((
                struct.pack('!B', len(val)),
                val,
        )) ),
    'reply_to': (
        6,
        0x0200, # (1 << 9)
        lambda val: ''.join((
                struct.pack('!B', len(val)),
                val,
        )) ),
    'expiration': (
        7,
        0x0100, # (1 << 8)
        lambda val: ''.join((
                struct.pack('!B', len(val)),
                val,
        )) ),
    'message_id': (
        8,
        0x0080, # (1 << 7)
        lambda val: ''.join((
                struct.pack('!B', len(val)),
                val,
        )) ),
    'timestamp': (
        9,
        0x0040, # (1 << 6)
        lambda val: struct.pack('!Q', val)
        ),
    'type_': (
        10,
        0x0020, # (1 << 5)
        lambda val: ''.join((
                struct.pack('!B', len(val)),
                val,
        )) ),
    'user_id': (
        11,
        0x0010, # (1 << 4)
        lambda val: ''.join((
                struct.pack('!B', len(val)),
                val,
        )) ),
    'app_id': (
        12,
        0x0008, # (1 << 3)
        lambda val: ''.join((
                struct.pack('!B', len(val)),
                val,
        )) ),
    'cluster_id': (
        13,
        0x0004, # (1 << 2)
        lambda val: ''.join((
                struct.pack('!B', len(val)),
                val,
        )) ),
}

def encode_basic_properties(body_size, props):
    pieces = ['']*14
    flags = 0
    enc = ENCODE_PROPS_BASIC

    for key in BASIC_PROPS_SET & set(props.iterkeys()):
        i, f, fun = enc[key]
        flags |= f
        pieces[i] = fun(props[key])

    return (0x02, ''.join((
        struct.pack('!HHQH',
                    CLASS_BASIC, 0, body_size, flags),
        ''.join(pieces),
        ))
        )


def split_headers(user_headers, properties_set):
    props = {}
    headers = {}
    for key, value in user_headers.iteritems():
        if key in properties_set:
            props[key] = value
        else:
            headers[key] = value
    return props, headers

def encode_body(body, frame_size):
    limit = frame_size - 7 - 1   # spec is broken...
    r = []
    while body:
        payload, body = body[:limit], body[limit:]
        r.append( (0x03, payload) )
    return r

