diff --git a/src/box/lua/tuple.cc b/src/box/lua/tuple.cc index d8522df9340539eb2230992622951fa31b0706ae..a725236e26c9e6aba2b5177a2f183fc8fe6cde33 100644 --- a/src/box/lua/tuple.cc +++ b/src/box/lua/tuple.cc @@ -111,14 +111,6 @@ lbox_tuple_gc(struct lua_State *L) return 0; } -static int -lbox_tuple_len(struct lua_State *L) -{ - struct tuple *tuple = lua_checktuple(L, 1); - lua_pushnumber(L, tuple_arity(tuple)); - return 1; -} - static int lbox_tuple_slice(struct lua_State *L) { @@ -425,37 +417,6 @@ lbox_tuple_totable(struct lua_State *L) return 1; } -/** - * Implementation of tuple __index metamethod. - * - * Provides operator [] access to individual fields for integer - * indexes, as well as searches and invokes metatable methods - * for strings. - */ -static int -lbox_tuple_index(struct lua_State *L) -{ - struct tuple *tuple = lua_checktuple(L, 1); - /* For integer indexes, implement [] operator */ - if (lua_isnumber(L, 2)) { - int i = luaL_checkint(L, 2); - const char *field = tuple_field(tuple, i); - if (field == NULL) { - const char *data = tuple->data; - luaL_error(L, "%s: index %d is out of bounds (0..%d)", - tuplelib_name, i, mp_decode_array(&data)); - } - luamp_decode(L, &field); - return 1; - } - - /* If we got a string, try to find a method for it. */ - const char *sz = luaL_checkstring(L, 2); - lua_getmetatable(L, 1); - lua_getfield(L, -1, sz); - return 1; -} - void lbox_pushtuple(struct lua_State *L, struct tuple *tuple) { @@ -524,8 +485,6 @@ lbox_tuple_pairs(struct lua_State *L) static const struct luaL_reg lbox_tuple_meta[] = { {"__gc", lbox_tuple_gc}, - {"__len", lbox_tuple_len}, - {"__index", lbox_tuple_index}, {"next", lbox_tuple_next}, {"pairs", lbox_tuple_pairs}, {"slice", lbox_tuple_slice}, diff --git a/src/box/lua/tuple.lua b/src/box/lua/tuple.lua index c2989d2897f30f87076755eb5865330f158b7ae1..f53f17a21eef84672c36a06662ef37be7cf9ef03 100644 --- a/src/box/lua/tuple.lua +++ b/src/box/lua/tuple.lua @@ -2,6 +2,7 @@ local ffi = require('ffi') local yaml = require('yaml') +local msgpackffi = require('msgpackffi') ffi.cdef([[ struct tuple @@ -12,6 +13,11 @@ struct tuple uint32_t _bsize; char data[0]; } __attribute__((packed)); + +uint32_t +tuple_arity(const struct tuple *tuple); +const char * +tuple_field(const struct tuple *tuple, uint32_t i); ]]) local builtin = ffi.C @@ -33,10 +39,19 @@ local methods = { local tuple_gc = cfuncs.__gc; -local tuple_field = cfuncs.__index +local tuple_field = function(tuple, field_n) + local field = builtin.tuple_field(tuple, field_n) + if field == nil then + return nil + end + return msgpackffi.decode_unchecked(field) +end + ffi.metatype('struct tuple', { __gc = tuple_gc; - __len = cfuncs.__len; + __len = function(tuple) + return builtin.tuple_arity(tuple) + end; __tostring = function(tuple) -- Unpack tuple, call yaml.encode, remove yaml header and footer -- 5 = '---\n\n' (header), -6 = '\n...\n' (footer) diff --git a/src/box/tuple.h b/src/box/tuple.h index 5f1f62e01e8d70eaf34c16d3b753b7dc65133a9f..58a0a649311fdf7a516e8231ba3cb999b7a49385 100644 --- a/src/box/tuple.h +++ b/src/box/tuple.h @@ -206,7 +206,7 @@ tuple_format(const struct tuple *tuple) * @param tuple * @return the number of fields in tuple */ -static inline uint32_t +extern "C" inline uint32_t tuple_arity(const struct tuple *tuple) { const char *data = tuple->data; @@ -220,7 +220,7 @@ tuple_arity(const struct tuple *tuple) * @pre field < tuple->field_count. * @returns field data if field exists or NULL */ -static inline const char * +inline const char * tuple_field_old(const struct tuple_format *format, const struct tuple *tuple, uint32_t i) { @@ -261,7 +261,7 @@ tuple_field_old(const struct tuple_format *format, * or NULL if field is out of range * @param len pointer where the len of the field will be stored */ -inline const char * +extern "C" inline const char * tuple_field(const struct tuple *tuple, uint32_t i) { return tuple_field_old(tuple_format(tuple), tuple, i); diff --git a/src/ffisyms.cc b/src/ffisyms.cc index f7346dce0eb49c67ea1a03b7c053625ad93e81a8..523b9a9284732573033ba81a1cfadc0498700712 100644 --- a/src/ffisyms.cc +++ b/src/ffisyms.cc @@ -1,5 +1,6 @@ #include <bit/bit.h> #include <lib/msgpuck/msgpuck.h> +#include <box/tuple.h> /* * A special hack to cc/ld to keep symbols in an optimized binary. @@ -9,5 +10,7 @@ void *ffi_symbols[] = { (void *) bswap_u32, (void *) bswap_u64, (void *) mp_bswap_float, - (void *) mp_bswap_double + (void *) mp_bswap_double, + (void *) tuple_arity, + (void *) tuple_field };