static PyObject*
determine_format(PyObject *self, PyObject *args)
{
    int rv;
    PyObject *orig;

    rv = PyArg_ParseTuple(args, "O", &orig);
    if (!rv) {
        return NULL;
    }

    (void)self;
    return pycbc_tc_determine_format(orig);
}
int
pycbc_tc_encode_value(pycbc_Bucket *conn,
                       PyObject **value,
                       PyObject *flag_v,
                       void **buf,
                       size_t *nbuf,
                       lcb_uint32_t *flags)
{
    PyObject *flags_obj;
    PyObject *orig_value;
    PyObject *new_value = NULL;
    PyObject *result_tuple = NULL;
    lcb_uint32_t flags_stackval;
    int rv;
    Py_ssize_t plen;

    orig_value = *value;

    if (!flag_v) {
        flag_v = conn->dfl_fmt;
    }

    if (!conn->tc) {

        if (flag_v == pycbc_helpers.fmt_auto) {
            flag_v = pycbc_tc_determine_format(*value);
        }

        rv = pycbc_get_u32(flag_v, &flags_stackval);
        if (rv < 0) {
            PYCBC_EXC_WRAP_OBJ(PYCBC_EXC_ARGUMENTS, 0,
                               "Bad value for flags",
                               flag_v);
            return -1;
        }

        *flags = flags_stackval;
        return encode_common(value, buf, nbuf, flags_stackval);
    }

    /**
     * Calling into Transcoder
     */

    rv = do_call_tc(conn, orig_value, flag_v, &result_tuple, ENCODE_VALUE);
    if (rv < 0) {
        return -1;
    }

    if (!PyTuple_Check(result_tuple) || PyTuple_GET_SIZE(result_tuple) != 2) {
        PYCBC_EXC_WRAP_EX(PYCBC_EXC_ENCODING, 0,
                          "Expected return of (bytes, flags)",
                          orig_value,
                          result_tuple);

        Py_XDECREF(result_tuple);
        return -1;

    }

    new_value = PyTuple_GET_ITEM(result_tuple, 0);
    flags_obj = PyTuple_GET_ITEM(result_tuple, 1);

    if (new_value == NULL || flags_obj == NULL) {
        PYCBC_EXC_WRAP_OBJ(PYCBC_EXC_INTERNAL, 0, "Tuple GET_ITEM had NULL",
                           result_tuple);

        Py_XDECREF(result_tuple);
        return -1;
    }

    rv = pycbc_get_u32(flags_obj, &flags_stackval);
    if (rv < 0) {
        Py_XDECREF(result_tuple);
        PYCBC_EXC_WRAP_VALUE(PYCBC_EXC_ENCODING, 0,
                             "Transcoder.encode_value() returned a bad "
                             "value for flags", orig_value);
        return -1;
    }

    *flags = flags_stackval;
    rv = PyBytes_AsStringAndSize(new_value, (char**)buf, &plen);
    if (rv == -1) {
        Py_XDECREF(result_tuple);

        PYCBC_EXC_WRAP_VALUE(PYCBC_EXC_ENCODING, 0,
                             "Value returned by Transcoder.encode_value() "
                             "could not be converted to bytes",
                orig_value);
        return -1;
    }

    *value = new_value;
    *nbuf = plen;

    Py_INCREF(new_value);
    Py_XDECREF(result_tuple);

    return 0;
}
int
pycbc_tc_encode_value(pycbc_Bucket *conn, PyObject *srcbuf, PyObject *srcflags,
                      pycbc_pybuffer *dstbuf, lcb_U32 *dstflags)
{
    PyObject *flags_obj;
    PyObject *new_value = NULL;
    PyObject *result_tuple = NULL;
    lcb_U32 flags_stackval;
    int rv;
    Py_ssize_t plen;

    if (!srcflags) {
        srcflags = conn->dfl_fmt;
    }

    if (!conn->tc) {
        if (srcflags == pycbc_helpers.fmt_auto) {
            srcflags = pycbc_tc_determine_format(srcbuf);
        }

        rv = pycbc_get_u32(srcflags, &flags_stackval);
        if (rv < 0) {
            PYCBC_EXC_WRAP_OBJ(PYCBC_EXC_ARGUMENTS, 0,
                               "Bad value for flags", srcflags);
            return -1;
        }

        *dstflags = flags_stackval;
        return encode_common(srcbuf, dstbuf, flags_stackval);
    }

    /**
     * Calling into Transcoder
     */
    rv = do_call_tc(conn, srcbuf, srcflags, &result_tuple, ENCODE_VALUE);
    if (rv < 0) {
        return -1;
    }

    if (!PyTuple_Check(result_tuple) || PyTuple_GET_SIZE(result_tuple) != 2) {
        PYCBC_EXC_WRAP_EX(PYCBC_EXC_ENCODING, 0,
                          "Expected return of (bytes, flags)",
                          srcbuf, result_tuple);

        Py_XDECREF(result_tuple);
        return -1;

    }

    new_value = PyTuple_GET_ITEM(result_tuple, 0);
    flags_obj = PyTuple_GET_ITEM(result_tuple, 1);

    if (new_value == NULL || flags_obj == NULL) {
        PYCBC_EXC_WRAP_OBJ(PYCBC_EXC_INTERNAL, 0, "Tuple GET_ITEM had NULL",
                           result_tuple);

        Py_XDECREF(result_tuple);
        return -1;
    }

    rv = pycbc_get_u32(flags_obj, &flags_stackval);
    if (rv < 0) {
        Py_XDECREF(result_tuple);
        PYCBC_EXC_WRAP_VALUE(PYCBC_EXC_ENCODING, 0,
                             "Transcoder.encode_value() returned a bad "
                             "value for flags", srcbuf);
        return -1;
    }

    *dstflags = flags_stackval;
    rv = PyBytes_AsStringAndSize(new_value, (char**)&dstbuf->buffer, &plen);
    if (rv == -1) {
        Py_XDECREF(result_tuple);
        PYCBC_EXC_WRAP_VALUE(PYCBC_EXC_ENCODING, 0,
                             "Value returned by Transcoder.encode_value() "
                             "could not be converted to bytes", srcbuf);
        return -1;
    }

    dstbuf->pyobj = new_value;
    dstbuf->length = plen;

    Py_INCREF(new_value);
    Py_XDECREF(result_tuple);

    return 0;
}