static bool s_add_native_header()

in source/event_stream_headers.c [10:157]


static bool s_add_native_header(struct aws_array_list *native_headers, PyObject *src_tuple_py) {
    bool success = false;

    /* For reading bytes-like values. Needs to be released at end of function */
    Py_buffer value_buf_py = {.obj = NULL};

    const char *name;
    size_t name_len;
    PyObject *value_py; /* Borrowed reference, don't need to decref */
    int type;
    if (!PyArg_ParseTuple(src_tuple_py, "s#Oi", &name, (Py_ssize_t *)&name_len, &value_py, &type)) {
        goto done;
    }

    const size_t name_len_max = sizeof(((struct aws_event_stream_header_value_pair *)0)->header_name) - 1;
    if (name_len > name_len_max) {
        PyErr_SetString(PyExc_ValueError, "Header.name exceeds max length");
        goto done;
    }

    switch (type) {
        case AWS_EVENT_STREAM_HEADER_BOOL_TRUE: {
            if (aws_event_stream_add_bool_header(native_headers, name, name_len, true)) {
                PyErr_SetAwsLastError();
                goto done;
            }
        } break;

        case AWS_EVENT_STREAM_HEADER_BOOL_FALSE: {
            if (aws_event_stream_add_bool_header(native_headers, name, name_len, false)) {
                PyErr_SetAwsLastError();
                goto done;
            }
        } break;

        case AWS_EVENT_STREAM_HEADER_BYTE: {
            int32_t value = PyLong_AsLong(value_py);
            if (PyErr_Occurred()) {
                goto done;
            }
            /* simply casting to 8 bits, we already checked bounds when setting value in python */
            if (aws_event_stream_add_byte_header(native_headers, name, name_len, (int8_t)value)) {
                PyErr_SetAwsLastError();
                goto done;
            }
        } break;

        case AWS_EVENT_STREAM_HEADER_INT16: {
            int32_t value = PyLong_AsLong(value_py);
            if (PyErr_Occurred()) {
                goto done;
            }
            /* simply casting to 16 bits, we already checked bounds when setting value in python */
            if (aws_event_stream_add_int16_header(native_headers, name, name_len, (int16_t)value)) {
                PyErr_SetAwsLastError();
                goto done;
            }
        } break;

        case AWS_EVENT_STREAM_HEADER_INT32: {
            int32_t value = PyLong_AsLong(value_py);
            if (PyErr_Occurred()) {
                goto done;
            }
            if (aws_event_stream_add_int32_header(native_headers, name, name_len, value)) {
                PyErr_SetAwsLastError();
                goto done;
            }
        } break;

        case AWS_EVENT_STREAM_HEADER_INT64: {
            int64_t value = PyLong_AsLongLong(value_py);
            if (PyErr_Occurred()) {
                goto done;
            }
            if (aws_event_stream_add_int64_header(native_headers, name, name_len, value)) {
                PyErr_SetAwsLastError();
                goto done;
            }
        } break;

        case AWS_EVENT_STREAM_HEADER_BYTE_BUF: {
            if (PyObject_GetBuffer(value_py, &value_buf_py, PyBUF_SIMPLE) == -1) { /* New reference */
                goto done;
            }
            if (aws_event_stream_add_bytebuf_header(
                    native_headers, name, name_len, value_buf_py.buf, value_buf_py.len, true /*copy*/)) {
                PyErr_SetAwsLastError();
                goto done;
            }
        } break;

        case AWS_EVENT_STREAM_HEADER_STRING: {
            size_t value_len;
            const char *value = PyUnicode_AsUTF8AndSize(value_py, (Py_ssize_t *)&value_len);
            if (!value) {
                goto done;
            }
            if (value_len > UINT16_MAX) {
                PyErr_SetString(PyExc_ValueError, "Header STRING value exceeds max length");
                goto done;
            }
            if (aws_event_stream_add_string_header(
                    native_headers, name, name_len, value, (uint16_t)value_len, true /*copy*/)) {
                PyErr_SetAwsLastError();
                goto done;
            }
        } break;

        case AWS_EVENT_STREAM_HEADER_TIMESTAMP: {
            int64_t value = PyLong_AsLongLong(value_py);
            if (PyErr_Occurred()) {
                goto done;
            }
            if (aws_event_stream_add_timestamp_header(native_headers, name, name_len, value)) {
                PyErr_SetAwsLastError();
                goto done;
            }
        } break;

        case AWS_EVENT_STREAM_HEADER_UUID: {
            /* UUID.bytes was passed in */
            if (PyObject_GetBuffer(value_py, &value_buf_py, PyBUF_SIMPLE) == -1) { /* New reference */
                goto done;
            }
            if (value_buf_py.len != 16) {
                PyErr_SetString(PyExc_ValueError, "UUID.bytes must be length 16");
                goto done;
            }
            if (aws_event_stream_add_uuid_header(native_headers, name, name_len, (const uint8_t *)value_buf_py.buf)) {
                PyErr_SetAwsLastError();
                goto done;
            }
        } break;

        default: {
            PyErr_SetString(PyExc_ValueError, "Header.type has invalid value");
            goto done;
        } break;
    }

    success = true;
done:
    if (value_buf_py.obj) {
        PyBuffer_Release(&value_buf_py);
    }
    return success;
}