void luamp_convert_key(struct lua_State *L, struct luaL_serializer *cfg, struct mpstream *stream, int index) { /* Performs keyfy() logic */ struct tuple *tuple = luaT_istuple(L, index); if (tuple != NULL) return tuple_to_mpstream(tuple, stream); struct luaL_field field; if (luaL_tofield(L, cfg, index, &field) < 0) luaT_error(L); if (field.type == MP_ARRAY) { lua_pushvalue(L, index); luamp_encode_r(L, cfg, stream, &field, 0); lua_pop(L, 1); } else if (field.type == MP_NIL) { mpstream_encode_array(stream, 0); } else { mpstream_encode_array(stream, 1); lua_pushvalue(L, index); luamp_encode_r(L, cfg, stream, &field, 0); lua_pop(L, 1); } }
/* * Encode CALL result. * Please read gh-291 carefully before "fixing" this code. */ static inline uint32_t luamp_encode_call(lua_State *L, struct luaL_serializer *cfg, struct mpstream *stream) { int nrets = lua_gettop(L); if (nrets == 0) { return 0; } else if (nrets > 1) { /* * Multireturn: * `return 1, box.tuple.new(...), array, 3, ...` */ for (int i = 1; i <= nrets; ++i) { struct luaL_field field; luaL_tofield(L, cfg, i, &field); struct tuple *tuple; if (field.type == MP_EXT && (tuple = lua_istuple(L, i)) != NULL) { /* `return ..., box.tuple.new(...), ...` */ tuple_to_mpstream(tuple, stream); } else if (field.type != MP_ARRAY) { /* * `return ..., scalar, ... => * ..., { scalar }, ...` */ lua_pushvalue(L, i); luamp_encode_array(cfg, stream, 1); luamp_encode_r(L, cfg, stream, &field, 0); lua_pop(L, 1); } else { /* `return ..., array, ...` */ luamp_encode(L, cfg, stream, i); } } return nrets; } assert(nrets == 1); /* * Inspect the first result */ struct luaL_field root; luaL_tofield(L, cfg, 1, &root); struct tuple *tuple; if (root.type == MP_EXT && (tuple = lua_istuple(L, 1)) != NULL) { /* `return box.tuple()` */ tuple_to_mpstream(tuple, stream); return 1; } else if (root.type != MP_ARRAY) { /* * `return scalar` * `return map` */ luamp_encode_array(cfg, stream, 1); assert(lua_gettop(L) == 1); luamp_encode_r(L, cfg, stream, &root, 0); return 1; } assert(root.type == MP_ARRAY); if (root.size == 0) { /* `return {}` => `{ box.tuple() }` */ luamp_encode_array(cfg, stream, 0); return 1; } /* `return { tuple, scalar, tuple }` */ assert(root.type == MP_ARRAY && root.size > 0); for (uint32_t t = 1; t <= root.size; t++) { lua_rawgeti(L, 1, t); struct luaL_field field; luaL_tofield(L, cfg, -1, &field); if (field.type == MP_EXT && (tuple = lua_istuple(L, -1))) { tuple_to_mpstream(tuple, stream); } else if (field.type != MP_ARRAY) { /* The first member of root table is not tuple/array */ if (t == 1) { /* * `return { scalar, ... } => * box.tuple.new(scalar, ...)` */ luamp_encode_array(cfg, stream, root.size); /* * Encode the first field of tuple using * existing information from luaL_tofield */ luamp_encode_r(L, cfg, stream, &field, 0); lua_pop(L, 1); assert(lua_gettop(L) == 1); /* Encode remaining fields as usual */ for (uint32_t f = 2; f <= root.size; f++) { lua_rawgeti(L, 1, f); luamp_encode(L, cfg, stream, -1); lua_pop(L, 1); } return 1; } /* * `return { tuple/array, ..., scalar, ... } => * { tuple/array, ..., { scalar }, ... }` */ luamp_encode_array(cfg, stream, 1); luamp_encode_r(L, cfg, stream, &field, 0); } else { /* `return { tuple/array, ..., tuple/array, ... }` */ luamp_encode_r(L, cfg, stream, &field, 0); } lua_pop(L, 1); assert(lua_gettop(L) == 1); } return root.size; }