module Tarantool::UnpackTuples

Constants

UTF8

Public Instance Methods

_unpack_field(p1, p2, p3, p4, p5) click to toggle source
static VALUE
unpack_field(VALUE self, VALUE data, VALUE field, VALUE i_o, VALUE realfield_o, VALUE serializers)
{
    int i = NUM2INT(i_o);
    const char *str = RSTRING_PTR(data);
    size_t len = RSTRING_LEN(data);
    size_t fieldsize = slice_ber((const uint8_t**)&str, &len);
    VALUE value;
    size_t offset = RSTRING_LEN(data) - len;

    if (fieldsize == 0) {
        return Qnil;
    }
    if (fieldsize > len) {
        rb_raise(rb_eValueError, "Response mailformed at field #%u fieldsize: %zu tail len: %zu", i, fieldsize, len);
    }

    if (field == sym_int || field == sym_integer) {
        if (fieldsize != 4) {
            rb_raise(rb_eValueError, "Bad field size %zd for integer field #%u", fieldsize, i);
        }
        value = UINT2NUM(get_uint32(str));
    } else if (field == sym_str || field == sym_string) {
        if (*str == 0 && fieldsize > 0) {
            value = rb_enc_str_new(str+1, fieldsize-1, rb_utf8_encoding());
        } else {
            value = rb_enc_str_new(str, fieldsize, rb_utf8_encoding());
        }
    } else if (field == sym_int64) {
        if (fieldsize != 8) {
            rb_raise(rb_eValueError, "Bad field size %zd for 64bit integer field #%u", fieldsize, i);
        }
        value = U642NUM(get_uint64(str));
    } else if (field == sym_bytes) {
        value = rb_enc_str_new(str, fieldsize, rb_ascii8bit_encoding());
    } else if (field == sym_int16) {
        if (fieldsize != 2) {
            rb_raise(rb_eValueError, "Bad field size %zd for 16bit integer field #%u", fieldsize, i);
        }
        value = UINT2NUM(get_uint16(str));
    } else if (field == sym_int8) {
        if (fieldsize != 1) {
            rb_raise(rb_eValueError, "Bad field size %zd for 8bit integer field #%u", fieldsize, i);
        }
        value = UINT2NUM(*(uint8_t*)str);
    } else if (field == sym_sint) {
        if (fieldsize != 4) {
            rb_raise(rb_eValueError, "Bad field size %zd for integer field #%u", fieldsize, i);
        }
        value = INT2NUM((int32_t)get_uint32(str));
    } else if (field == sym_sint64) {
        if (fieldsize != 8) {
            rb_raise(rb_eValueError, "Bad field size %zd for 64bit integer field #%u", fieldsize, i);
        }
        value = I642NUM((int64_t)get_uint64(str));
    } else if (field == sym_sint16) {
        if (fieldsize != 2) {
            rb_raise(rb_eValueError, "Bad field size %zd for 16bit integer field #%u", fieldsize, i);
        }
        value = INT2NUM((int16_t)get_uint16(str));
    } else if (field == sym_sint8) {
        if (fieldsize != 1) {
            rb_raise(rb_eValueError, "Bad field size %zd for 8bit integer field #%u", fieldsize, i);
        }
        value = INT2NUM(*(int8_t*)str);
    } else if (field == sym_varint) {
        if (fieldsize == 4) {
            value = UINT2NUM(get_uint32(str));
        } else if (fieldsize == 8) {
            value = U642NUM(get_uint64(str));
        } else if (fieldsize == 2) {
            value = UINT2NUM(get_uint16(str));
        } else {
            rb_raise(rb_eValueError, "Bad field size %zd for integer field %d", fieldsize, i);
        }
    } else if (field == sym_auto) {
        value = rb_enc_str_new(str, fieldsize, rb_utf8_encoding());
        if (fieldsize == 2 || fieldsize == 4 || fieldsize == 8) {
            value = rb_class_new_instance(1, &value, rb_cAutoType);
        }
    } else {
        int realfield = NUM2INT(realfield_o);
        VALUE serializer = rb_ary_entry(serializers, realfield);
        VALUE substr = rb_enc_str_new(str, fieldsize, rb_ascii8bit_encoding());
        if (!RTEST(serializer)) {
            serializer = rb_funcall2(self, id_get_serializer, 1, &field);
            rb_ary_store(serializers, realfield, serializer);
        }
        value = rb_funcall2(serializer, id_decode, 1, &substr);
    }
    rb_str_drop_bytes(data, offset + fieldsize);
    return value;
}

Private Instance Methods

get_tail_no(p1, p2, p3) click to toggle source
static VALUE
get_tail_no(VALUE self, VALUE array, VALUE index_o, VALUE tail_o)
{
    int size = RARRAY_LEN(array);
    int index = NUM2INT(index_o);
    int tail = NUM2INT(tail_o);
    int pos = index < size ? index : (size - tail + (index - size) % tail);
    return INT2NUM(pos);
}