Exemple #1
0
static char *test_parser_fixed_scalars(void *context)
{
    int idx = 0;
    static char error[1024];

    while (fs_vectors[idx].data) {
        qd_field_iterator_t *field  = qd_field_iterator_binary(fs_vectors[idx].data,
                                                               fs_vectors[idx].length);
        qd_parsed_field_t *parsed = qd_parse(field);
        if (!qd_parse_ok(parsed)) return "Unexpected Parse Error";
        if (qd_parse_tag(parsed) != fs_vectors[idx].expected_tag) {
            sprintf(error, "(%d) Tag: Expected %02x, Got %02x", idx,
                    fs_vectors[idx].expected_tag, qd_parse_tag(parsed));
            return error;
        }
        if (fs_vectors[idx].check_uint &&
            qd_parse_as_uint(parsed) != fs_vectors[idx].expected_ulong) {
            sprintf(error, "(%d) UINT: Expected %"PRIx64", Got %"PRIx32, idx,
                    fs_vectors[idx].expected_ulong, qd_parse_as_uint(parsed));
            return error;
        }
        if (fs_vectors[idx].check_ulong &&
            qd_parse_as_ulong(parsed) != fs_vectors[idx].expected_ulong) {
            sprintf(error, "(%d) ULONG: Expected %"PRIx64", Got %"PRIx64, idx,
                    fs_vectors[idx].expected_ulong, qd_parse_as_ulong(parsed));
            return error;
        }
        if (fs_vectors[idx].check_int &&
            qd_parse_as_int(parsed) != fs_vectors[idx].expected_long) {
            sprintf(error, "(%d) INT: Expected %"PRIx64", Got %"PRIx32, idx,
                    fs_vectors[idx].expected_long, qd_parse_as_int(parsed));
            return error;
        }
        if (fs_vectors[idx].check_long &&
            qd_parse_as_long(parsed) != fs_vectors[idx].expected_long) {
            sprintf(error, "(%d) LONG: Expected %"PRIx64", Got %"PRIx64, idx,
                    fs_vectors[idx].expected_long, qd_parse_as_long(parsed));
            return error;
        }
        idx++;

        qd_field_iterator_free(field);
        qd_parse_free(parsed);
    }

    return 0;
}
void qdra_config_auto_link_create_CT(qdr_core_t          *core,
                                      qd_field_iterator_t *name,
                                      qdr_query_t         *query,
                                      qd_parsed_field_t   *in_body)
{
    while (true) {
        //
        // Ensure there isn't a duplicate name and that the body is a map
        //
        qdr_auto_link_t *al = DEQ_HEAD(core->auto_links);
        while (al) {
            if (name && al->name && qd_field_iterator_equal(name, (const unsigned char*) al->name))
                break;
            al = DEQ_NEXT(al);
        }

        if (!!al) {
            query->status = QD_AMQP_BAD_REQUEST;
            query->status.description = "Name conflicts with an existing entity";
            qd_log(core->agent_log, QD_LOG_ERROR, "Error performing CREATE of %s: %s", CONFIG_AUTOLINK_TYPE, query->status.description);
            break;
        }

        if (!qd_parse_is_map(in_body)) {
            query->status = QD_AMQP_BAD_REQUEST;
            query->status.description = "Body of request must be a map";
            qd_log(core->agent_log, QD_LOG_ERROR, "Error performing CREATE of %s: %s", CONFIG_AUTOLINK_TYPE, query->status.description);
            break;
        }

        //
        // Extract the fields from the request
        //
        qd_parsed_field_t *addr_field       = qd_parse_value_by_key(in_body, qdr_config_auto_link_columns[QDR_CONFIG_AUTO_LINK_ADDR]);
        qd_parsed_field_t *dir_field        = qd_parse_value_by_key(in_body, qdr_config_auto_link_columns[QDR_CONFIG_AUTO_LINK_DIR]);
        qd_parsed_field_t *phase_field      = qd_parse_value_by_key(in_body, qdr_config_auto_link_columns[QDR_CONFIG_AUTO_LINK_PHASE]);
        qd_parsed_field_t *connection_field = qd_parse_value_by_key(in_body, qdr_config_auto_link_columns[QDR_CONFIG_AUTO_LINK_CONNECTION]);
        qd_parsed_field_t *container_field  = qd_parse_value_by_key(in_body, qdr_config_auto_link_columns[QDR_CONFIG_AUTO_LINK_CONTAINER_ID]);

        //
        // Addr and dir fields are mandatory.  Fail if they're not both here.
        //
        if (!addr_field || !dir_field) {
            query->status = QD_AMQP_BAD_REQUEST;
            query->status.description = "addr and dir fields are mandatory";
            qd_log(core->agent_log, QD_LOG_ERROR, "Error performing CREATE of %s: %s", CONFIG_AUTOLINK_TYPE, query->status.description);
            break;
        }

        qd_direction_t dir;
        const char *error = qdra_auto_link_direction_CT(dir_field, &dir);
        if (error) {
            query->status = QD_AMQP_BAD_REQUEST;
            query->status.description = error;
            qd_log(core->agent_log, QD_LOG_ERROR, "Error performing CREATE of %s: %s", CONFIG_AUTOLINK_TYPE, query->status.description);
            break;
        }

        //
        // Use the specified phase if present.  Otherwise default based on the direction:
        // Phase 0 for outgoing links and phase 1 for incoming links.
        //
        int phase = phase_field ? qd_parse_as_int(phase_field) : (dir == QD_OUTGOING ? 0 : 1);

        //
        // Validate the phase
        //
        if (phase < 0 || phase > 9) {
            query->status = QD_AMQP_BAD_REQUEST;
            query->status.description = "autoLink phase must be between 0 and 9";
            qd_log(core->agent_log, QD_LOG_ERROR, "Error performing CREATE of %s: %s", CONFIG_AUTOLINK_TYPE, query->status.description);
            break;
        }

        //
        // The request is good.  Create the entity.
        //
        bool               is_container = !!container_field;
        qd_parsed_field_t *in_use_conn  = is_container ? container_field : connection_field;

        al = qdr_route_add_auto_link_CT(core, name, addr_field, dir, phase, in_use_conn, is_container);

        //
        // Compose the result map for the response.
        //
        if (query->body) {
            qd_compose_start_map(query->body);
            for (int col = 0; col < QDR_CONFIG_AUTO_LINK_COLUMN_COUNT; col++)
                qdr_config_auto_link_insert_column_CT(al, col, query->body, true);
            qd_compose_end_map(query->body);
        }

        query->status = QD_AMQP_CREATED;
        break;
    }

    //
    // Enqueue the response if there is a body. If there is no body, this is a management
    // operation created internally by the configuration file parser.
    //
    if (query->body) {
        //
        // If there was an error in processing the create, insert a NULL value into the body.
        //
        if (query->status.status / 100 > 2)
            qd_compose_insert_null(query->body);
        qdr_agent_enqueue_response_CT(core, query);
    } else {
        if (query->status.status / 100 > 2)
            qd_log(core->log, QD_LOG_ERROR, "Error configuring linkRoute: %s", query->status.description);
        qdr_query_free(query);
    }
}
Exemple #3
0
static char *test_parser_fixed_scalars(void *context)
{
    int idx = 0;
    qd_iterator_t *field = NULL;
    qd_parsed_field_t *parsed = NULL;
    static char error[1024];

    error[0] = 0;

    while (fs_vectors[idx].data) {
        field = qd_iterator_binary(fs_vectors[idx].data,
                                   fs_vectors[idx].length, ITER_VIEW_ALL);
        parsed = qd_parse(field);

        qd_iterator_t *typed_iter = qd_parse_typed(parsed);

        int length = qd_iterator_length(typed_iter);

        if (length != fs_vectors[idx].length) {
            strcpy(error, "Length of typed iterator does not match actual length");
            break;
        }

        if (!qd_parse_ok(parsed)) {
            strcpy(error, "Unexpected Parse Error");
            break;
        }
        if (qd_parse_tag(parsed) != fs_vectors[idx].expected_tag) {
            sprintf(error, "(%d) Tag: Expected %02x, Got %02x", idx,
                    fs_vectors[idx].expected_tag, qd_parse_tag(parsed));
            break;
        }
        if (fs_vectors[idx].check_uint &&
            qd_parse_as_uint(parsed) != fs_vectors[idx].expected_ulong) {
            sprintf(error, "(%d) UINT: Expected %"PRIx64", Got %"PRIx32, idx,
                    fs_vectors[idx].expected_ulong, qd_parse_as_uint(parsed));
            break;
        }
        if (fs_vectors[idx].check_ulong &&
            qd_parse_as_ulong(parsed) != fs_vectors[idx].expected_ulong) {
            sprintf(error, "(%d) ULONG: Expected %"PRIx64", Got %"PRIx64, idx,
                    fs_vectors[idx].expected_ulong, qd_parse_as_ulong(parsed));
            break;
        }
        if (fs_vectors[idx].check_int &&
            qd_parse_as_int(parsed) != fs_vectors[idx].expected_long) {
            sprintf(error, "(%d) INT: Expected %"PRIx64", Got %"PRIx32, idx,
                    fs_vectors[idx].expected_long, qd_parse_as_int(parsed));
            break;
        }
        if (fs_vectors[idx].check_long &&
            qd_parse_as_long(parsed) != fs_vectors[idx].expected_long) {
            sprintf(error, "(%d) LONG: Expected %"PRIx64", Got %"PRIx64, idx,
                    fs_vectors[idx].expected_long, qd_parse_as_long(parsed));
            break;
        }
        idx++;
        qd_iterator_free(field);
        field = 0;
        qd_parse_free(parsed);
        parsed = 0;
    }

    qd_iterator_free(field);
    qd_parse_free(parsed);
    return *error ? error : 0;
}
Exemple #4
0
static char *test_integer_conversion(void *context)
{
    const struct fs_vector_t {
        const char *data;
        int         length;
        uint8_t     parse_as;
        bool        expect_fail;
        int64_t     expected_int;
        uint64_t    expected_uint;
    } fs_vectors[] = {
        // can successfully convert 64 bit values that are valid in the 32bit range
        {"\x80\x00\x00\x00\x00\xff\xff\xff\xff", 9, QD_AMQP_UINT, false, 0,         UINT32_MAX},
        {"\x80\x00\x00\x00\x00\x00\x00\x00\x00", 9, QD_AMQP_UINT, false, 0,         0},
        {"\x80\x00\x00\x00\x00\x00\x00\x00\x01", 9, QD_AMQP_UINT, false, 0,         1},
        {"\x81\x00\x00\x00\x00\x7f\xff\xff\xff", 9, QD_AMQP_INT,  false, INT32_MAX, 0},
        {"\x81\xFF\xFF\xFF\xFF\x80\x00\x00\x00", 9, QD_AMQP_INT,  false, INT32_MIN, 0},
        {"\x81\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF", 9, QD_AMQP_INT,  false, -1,        0},

        // signed/unsigned conversions
        {"\x70\x7F\xFF\xFF\xFF",                 5, QD_AMQP_INT,  false, INT32_MAX, 0},
        {"\x71\x7F\xFF\xFF\xFF",                 5, QD_AMQP_UINT, false, 0,         INT32_MAX},
        {"\x80\x7F\xFF\xFF\xFF\xFF\xFF\xFF\xFF", 9, QD_AMQP_LONG, false, INT64_MAX, 0},
        {"\x81\x7F\xFF\xFF\xFF\xFF\xFF\xFF\xFF", 9, QD_AMQP_ULONG, false,0,         INT64_MAX},
        {"\x50\x7F",                             2, QD_AMQP_INT,  false, INT8_MAX,  0},
        {"\x60\x7F\xFF",                         3, QD_AMQP_INT,  false, INT16_MAX,  0},
        {"\x53\x7F",                             2, QD_AMQP_INT,  false, INT8_MAX,  0},
        {"\x55\x7F",                             2, QD_AMQP_UINT, false, 0,         INT8_MAX},
        {"\x51\x7F",                             2, QD_AMQP_UINT, false, 0,         INT8_MAX},
        {"\x61\x7F\xFF",                         3, QD_AMQP_UINT, false, 0,         INT16_MAX},

        // strings
        {"\xa1\x02 1",                           4, QD_AMQP_UINT, false, 0,         1},
        {"\xa1\x02-1",                           4, QD_AMQP_INT,  false, -1,        0},

        {"\xa1\x14" "18446744073709551615",     22, QD_AMQP_ULONG,false, 0,         UINT64_MAX},
        {"\xa1\x14" "-9223372036854775808",     22, QD_AMQP_LONG, false, INT64_MIN, 0},
        {"\xa1\x13" "9223372036854775807",      21, QD_AMQP_LONG, false, INT64_MAX, 0},
        {"\xa3\x13" "9223372036854775807",      21, QD_AMQP_LONG, false, INT64_MAX, 0},

        // cannot convert 64 bit values that are outside the 32bit range as int32
        {"\x80\x00\x00\x00\x01\x00\x00\x00\x00", 9, QD_AMQP_UINT, true,  0, 0},
        {"\x81\x00\x00\x00\x00\x80\x00\x00\x00", 9, QD_AMQP_INT,  true,  0, 0},
        {"\x81\xFF\xFF\xFF\xFF\x7F\xFF\xFF\xFF", 9, QD_AMQP_INT,  true,  0, 0},

        // bad signed/unsigned conversions
        {"\x80\x80\x00\x00\x00\x00\x00\x00\x00", 9, QD_AMQP_LONG,  true, 0, 0},
        {"\x81\x80\x00\x00\x00\x00\x00\x00\x00", 9, QD_AMQP_ULONG, true, 0, 0},
        {"\x70\x80\x00\x00\x00",                 5, QD_AMQP_LONG,  true, 0, 0},
        {"\x71\x80\x00\x00\x00",                 5, QD_AMQP_ULONG, true, 0, 0},
        {"\x55\x80",                             2, QD_AMQP_UINT,  true, 0, 0},
        {"\x51\x80",                             2, QD_AMQP_UINT,  true, 0, 0},
        {"\x54\x80",                             2, QD_AMQP_UINT,  true, 0, 0},
        {"\x61\x80\x00",                         3, QD_AMQP_UINT,  true, 0, 0},
        {"\x53\x80",                             2, QD_AMQP_INT,   true, 0, 0},
        {"\x52\x80",                             2, QD_AMQP_INT,   true, 0, 0},
        {"\x50\x80",                             2, QD_AMQP_LONG,  true, 0, 0},
        {"\x60\x80",                             2, QD_AMQP_LONG,  true, 0, 0},
        {NULL},
    };

    char *error = NULL;
    for (int i = 0; fs_vectors[i].data && !error; ++i) {
        qd_iterator_t     *data_iter = qd_iterator_binary(fs_vectors[i].data, fs_vectors[i].length, ITER_VIEW_ALL);
        qd_parsed_field_t *field = qd_parse(data_iter);

        if (!qd_parse_ok(field)) {
            error = "unexpected parse error";
            qd_iterator_free(data_iter);
            qd_parse_free(field);
            break;
        }

        bool equal = false;
        switch (fs_vectors[i].parse_as) {
        case QD_AMQP_UINT:
        {
            uint32_t tmp = qd_parse_as_uint(field);
            equal = (tmp == fs_vectors[i].expected_uint);
            break;
        }
        case QD_AMQP_ULONG:
        {
            uint64_t tmp = qd_parse_as_ulong(field);
            equal = (tmp == fs_vectors[i].expected_uint);
            break;
        }
        case QD_AMQP_INT:
        {

            int32_t tmp = qd_parse_as_int(field);
            equal = (tmp == fs_vectors[i].expected_int);
            break;
        }
        case QD_AMQP_LONG:
        {
            int64_t tmp = qd_parse_as_long(field);
            equal = (tmp == fs_vectors[i].expected_int);
            break;
        }
        }

        if (!qd_parse_ok(field)) {
            if (!fs_vectors[i].expect_fail) {
                error = "unexpected conversion/parse error";
            }
        } else if (fs_vectors[i].expect_fail) {
            error = "Conversion did not fail as expected";
        } else if (!equal) {
            error = "unexpected converted value";
        }

        qd_iterator_free(data_iter);
        qd_parse_free(field);
    }

    return error;
}
/**
 * Checks the content of the message to see if this can be handled by the C-management agent. If this agent cannot handle it, it will be
 * forwarded to the Python agent.
 */
static bool qd_can_handle_request(qd_parsed_field_t           *properties_fld,
                                  qd_router_entity_type_t     *entity_type,
                                  qd_router_operation_type_t  *operation_type,
                                  qd_field_iterator_t        **identity_iter,
                                  qd_field_iterator_t        **name_iter,
                                  int                         *count,
                                  int                         *offset)
{
    // The must be a property field and that property field should be a AMQP map. This is true for QUERY but I need
    // to check if it true for CREATE, UPDATE and DELETE
    if (properties_fld == 0 || !qd_parse_is_map(properties_fld))
        return false;

    //
    // Only certain entity types can be handled by this agent.
    // 'entityType': 'org.apache.qpid.dispatch.router.address
    // 'entityType': 'org.apache.qpid.dispatch.router.link'
    // TODO - Add more entity types here. The above is not a complete list.

    qd_parsed_field_t *parsed_field = qd_parse_value_by_key(properties_fld, IDENTITY);
    if (parsed_field!=0) {
        *identity_iter = qd_parse_raw(parsed_field);
    }
    parsed_field = qd_parse_value_by_key(properties_fld, NAME);
    if (parsed_field!=0) {
        *name_iter = qd_parse_raw(parsed_field);
    }

    parsed_field = qd_parse_value_by_key(properties_fld, ENTITY);

    if (parsed_field == 0) { // Sometimes there is no 'entityType' but 'type' might be available.
        parsed_field = qd_parse_value_by_key(properties_fld, TYPE);
        if (parsed_field == 0)
            return false;
    }

    if (qd_field_iterator_equal(qd_parse_raw(parsed_field), address_entity_type))
        *entity_type = QD_ROUTER_ADDRESS;
    else if (qd_field_iterator_equal(qd_parse_raw(parsed_field), link_entity_type))
        *entity_type = QD_ROUTER_LINK;
    else if (qd_field_iterator_equal(qd_parse_raw(parsed_field), config_address_entity_type))
        *entity_type = QD_ROUTER_CONFIG_ADDRESS;
    else if (qd_field_iterator_equal(qd_parse_raw(parsed_field), link_route_entity_type))
        *entity_type = QD_ROUTER_CONFIG_LINK_ROUTE;
    else if (qd_field_iterator_equal(qd_parse_raw(parsed_field), auto_link_entity_type))
        *entity_type = QD_ROUTER_CONFIG_AUTO_LINK;
    else if (qd_field_iterator_equal(qd_parse_raw(parsed_field), console_entity_type))
        *entity_type = QD_ROUTER_FORBIDDEN;
    else
        return false;


    parsed_field = qd_parse_value_by_key(properties_fld, OPERATION);

    if (parsed_field == 0)
        return false;

    if (qd_field_iterator_equal(qd_parse_raw(parsed_field), MANAGEMENT_QUERY))
        (*operation_type) = QD_ROUTER_OPERATION_QUERY;
    else if (qd_field_iterator_equal(qd_parse_raw(parsed_field), MANAGEMENT_CREATE))
        (*operation_type) = QD_ROUTER_OPERATION_CREATE;
    else if (qd_field_iterator_equal(qd_parse_raw(parsed_field), MANAGEMENT_READ))
        (*operation_type) = QD_ROUTER_OPERATION_READ;
    else if (qd_field_iterator_equal(qd_parse_raw(parsed_field), MANAGEMENT_UPDATE))
        (*operation_type) = QD_ROUTER_OPERATION_UPDATE;
    else if (qd_field_iterator_equal(qd_parse_raw(parsed_field), MANAGEMENT_DELETE))
        (*operation_type) = QD_ROUTER_OPERATION_DELETE;
    else
        // This is an unknown operation type. cannot be handled, return false.
        return false;

    // Obtain the count and offset.
    parsed_field = qd_parse_value_by_key(properties_fld, COUNT);
    if (parsed_field)
        (*count) = qd_parse_as_int(parsed_field);
    else
        (*count) = -1;

    parsed_field = qd_parse_value_by_key(properties_fld, OFFSET);
    if (parsed_field)
        (*offset) = qd_parse_as_int(parsed_field);
    else
        (*offset) = 0;

    return true;
}
static qd_iterator_t *router_annotate_message(qd_router_t       *router,
                                              qd_parsed_field_t *in_ma,
                                              qd_message_t      *msg,
                                              qd_bitmask_t     **link_exclusions,
                                              bool               strip_inbound_annotations)
{
    qd_iterator_t *ingress_iter = 0;

    qd_parsed_field_t *trace   = 0;
    qd_parsed_field_t *ingress = 0;
    qd_parsed_field_t *to      = 0;
    qd_parsed_field_t *phase   = 0;

    *link_exclusions = 0;

    if (in_ma && !strip_inbound_annotations) {
        uint32_t count = qd_parse_sub_count(in_ma);
        bool done = false;

        for (uint32_t idx = 0; idx < count && !done; idx++) {
            qd_parsed_field_t *sub  = qd_parse_sub_key(in_ma, idx);
            if (!sub)
                continue;
            qd_iterator_t *iter = qd_parse_raw(sub);
            if (!iter)
                continue;

            if        (qd_iterator_equal(iter, (unsigned char*) QD_MA_TRACE)) {
                trace = qd_parse_sub_value(in_ma, idx);
            } else if (qd_iterator_equal(iter, (unsigned char*) QD_MA_INGRESS)) {
                ingress = qd_parse_sub_value(in_ma, idx);
            } else if (qd_iterator_equal(iter, (unsigned char*) QD_MA_TO)) {
                to = qd_parse_sub_value(in_ma, idx);
            } else if (qd_iterator_equal(iter, (unsigned char*) QD_MA_PHASE)) {
                phase = qd_parse_sub_value(in_ma, idx);
            }
            done = trace && ingress && to && phase;
        }
    }

    //
    // QD_MA_TRACE:
    // If there is a trace field, append this router's ID to the trace.
    // If the router ID is already in the trace the msg has looped.
    //
    qd_composed_field_t *trace_field = qd_compose_subfield(0);
    qd_compose_start_list(trace_field);
    if (trace) {
        if (qd_parse_is_list(trace)) {
            //
            // Create a link-exclusion map for the items in the trace.  This map will
            // contain a one-bit for each link that leads to a neighbor router that
            // the message has already passed through.
            //
            *link_exclusions = qd_tracemask_create(router->tracemask, trace);

            //
            // Append this router's ID to the trace.
            //
            uint32_t idx = 0;
            qd_parsed_field_t *trace_item = qd_parse_sub_value(trace, idx);
            while (trace_item) {
                qd_iterator_t *iter = qd_parse_raw(trace_item);
                qd_iterator_reset_view(iter, ITER_VIEW_ALL);
                qd_compose_insert_string_iterator(trace_field, iter);
                idx++;
                trace_item = qd_parse_sub_value(trace, idx);
            }
        }
    }

    qd_compose_insert_string(trace_field, node_id);
    qd_compose_end_list(trace_field);
    qd_message_set_trace_annotation(msg, trace_field);

    //
    // QD_MA_TO:
    // Preserve the existing value.
    //
    if (to) {
        qd_composed_field_t *to_field = qd_compose_subfield(0);
        qd_compose_insert_string_iterator(to_field, qd_parse_raw(to));
        qd_message_set_to_override_annotation(msg, to_field);
    }

    //
    // QD_MA_PHASE:
    // Preserve the existing value.
    //
    if (phase) {
        int phase_val = qd_parse_as_int(phase);
        qd_message_set_phase_annotation(msg, phase_val);
    }

    //
    // QD_MA_INGRESS:
    // If there is no ingress field, annotate the ingress as
    // this router else keep the original field.
    //
    qd_composed_field_t *ingress_field = qd_compose_subfield(0);
    if (ingress && qd_parse_is_scalar(ingress)) {
        ingress_iter = qd_parse_raw(ingress);
        qd_compose_insert_string_iterator(ingress_field, ingress_iter);
    } else
        qd_compose_insert_string(ingress_field, node_id);
    qd_message_set_ingress_annotation(msg, ingress_field);

    //
    // Return the iterator to the ingress field _if_ it was present.
    // If we added the ingress, return NULL.
    //
    return ingress_iter;
}
PyObject *qd_field_to_py(qd_parsed_field_t *field)
{
    qd_python_check_lock();
    PyObject *result = 0;
    uint8_t   tag    = qd_parse_tag(field);
    switch (tag) {
      case QD_AMQP_NULL:
        Py_INCREF(Py_None);
        result = Py_None;
        break;

      case QD_AMQP_BOOLEAN:
      case QD_AMQP_TRUE:
      case QD_AMQP_FALSE:
        result = qd_parse_as_uint(field) ? Py_True : Py_False;
        break;

      case QD_AMQP_UBYTE:
      case QD_AMQP_USHORT:
      case QD_AMQP_UINT:
      case QD_AMQP_SMALLUINT:
      case QD_AMQP_UINT0:
        result = PyInt_FromLong((long) qd_parse_as_uint(field));
        break;

      case QD_AMQP_ULONG:
      case QD_AMQP_SMALLULONG:
      case QD_AMQP_ULONG0:
      case QD_AMQP_TIMESTAMP:
        result = PyLong_FromUnsignedLongLong((unsigned PY_LONG_LONG) qd_parse_as_ulong(field));
        break;

      case QD_AMQP_BYTE:
      case QD_AMQP_SHORT:
      case QD_AMQP_INT:
      case QD_AMQP_SMALLINT:
        result = PyInt_FromLong((long) qd_parse_as_int(field));
        break;

      case QD_AMQP_LONG:
      case QD_AMQP_SMALLLONG:
        result = PyLong_FromLongLong((PY_LONG_LONG)qd_parse_as_long(field));
        break;

      case QD_AMQP_FLOAT:
      case QD_AMQP_DOUBLE:
      case QD_AMQP_DECIMAL32:
      case QD_AMQP_DECIMAL64:
      case QD_AMQP_DECIMAL128:
      case QD_AMQP_UTF32:
      case QD_AMQP_UUID:
        break;

      case QD_AMQP_VBIN8:
      case QD_AMQP_VBIN32:
      case QD_AMQP_STR8_UTF8:
      case QD_AMQP_STR32_UTF8:
      case QD_AMQP_SYM8:
      case QD_AMQP_SYM32:
        result = parsed_to_py_string(field);
        break;

      case QD_AMQP_LIST0:
      case QD_AMQP_LIST8:
      case QD_AMQP_LIST32: {
          uint32_t count = qd_parse_sub_count(field);
          result = PyList_New(count);
          for (uint32_t idx = 0; idx < count; idx++) {
              qd_parsed_field_t *sub = qd_parse_sub_value(field, idx);
              PyObject *pysub = qd_field_to_py(sub);
              if (pysub == 0)
                  return 0;
              PyList_SetItem(result, idx, pysub);
          }
          break;
      }
      case QD_AMQP_MAP8:
      case QD_AMQP_MAP32: {
          uint32_t count = qd_parse_sub_count(field);
          result = PyDict_New();
          for (uint32_t idx = 0; idx < count; idx++) {
              qd_parsed_field_t *key = qd_parse_sub_key(field, idx);
              qd_parsed_field_t *val = qd_parse_sub_value(field, idx);
              PyObject *pykey = parsed_to_py_string(key);
              PyObject *pyval = qd_field_to_py(val);
              if (pyval == 0)
                  return 0;
              PyDict_SetItem(result, pykey, pyval);
              Py_DECREF(pykey);
              Py_DECREF(pyval);
          }
          break;
      }
      case QD_AMQP_ARRAY8:
      case QD_AMQP_ARRAY32:
        break;
    }
    if (!result)
        Py_RETURN_NONE;
    return result;
}