diff --git a/include/lua/init.h b/include/lua/init.h
index e6109c1fe0168d16408d5d555927ac692b285a98..b4dae65ef3deb0fed5afea7185057ffa1506ec58 100644
--- a/include/lua/init.h
+++ b/include/lua/init.h
@@ -110,4 +110,5 @@ tarantool_lua(struct lua_State *L,
  *
  */
 int luaL_pushnumber64(struct lua_State *L, uint64_t val);
+
 #endif /* INCLUDES_TARANTOOL_LUA_H */
diff --git a/src/box/box_lua.m b/src/box/box_lua.m
index 9c41930f7e002344669f469614b296cd7ad81ad9..8df04988fc2f21899491d013b8ce4f7146a548e9 100644
--- a/src/box/box_lua.m
+++ b/src/box/box_lua.m
@@ -1186,12 +1186,6 @@ lbox_raise(lua_State *L)
 	return 0;
 }
 
-static const struct luaL_reg boxlib[] = {
-	{"process", lbox_process},
-	{"raise", lbox_raise},
-	{NULL, NULL}
-};
-
 /**
  * A helper to find a Lua function by name and put it
  * on top of the stack.
@@ -1279,6 +1273,328 @@ box_index_init_iterator_types(struct lua_State *L, int idx)
 	}
 }
 
+/**
+ * Pack our BER integer into luaL_Buffer
+ */
+static void
+luaL_addvarint32(luaL_Buffer *b, u32 u32)
+{
+	char varint_buf[sizeof(u32)+1];
+	struct tbuf tbuf = { .size = 0, .capacity = sizeof(varint_buf),
+		.data = varint_buf };
+	write_varint32(&tbuf, u32);
+	luaL_addlstring(b, tbuf.data, tbuf.size);
+}
+
+/**
+ * Convert box.pack() format specifier to Tarantool
+ * binary protocol UPDATE opcode
+ */
+static char format_to_opcode(char format)
+{
+	switch (format) {
+	case '=': return 0;
+	case '+': return 1;
+	case '&': return 2;
+	case '^': return 3;
+	case '|': return 4;
+	case ':': return 5;
+	case '#': return 6;
+	case '!': return 7;
+	case '-': return 8;
+	default: return format;
+	}
+}
+
+/**
+ * Counterpart to @a format_to_opcode
+ */
+static char opcode_to_format(char opcode)
+{
+	switch (opcode) {
+	case 0: return '=';
+	case 1: return '+';
+	case 2: return '&';
+	case 3: return '^';
+	case 4: return '|';
+	case 5: return ':';
+	case 6: return '#';
+	case 7: return '!';
+	case 8: return '-';
+	default: return opcode;
+	}
+}
+
+/**
+ * To use Tarantool/Box binary protocol primitives from Lua, we
+ * need a way to pack Lua variables into a binary representation.
+ * We do it by exporting a helper function
+ *
+ * box.pack(format, args...)
+ *
+ * which takes the format, which is very similar to Perl 'pack'
+ * format, and a list of arguments, and returns a binary string
+ * which has the arguments packed according to the format.
+ *
+ * For example, a typical SELECT packet packs in Lua like this:
+ *
+ * pkt = box.pack("iiiiiip", -- pack format
+ *                         0, -- space id
+ *                         0, -- index id
+ *                         0, -- offset
+ *                         2^32, -- limit
+ *                         1, -- number of SELECT arguments
+ *                         1, -- tuple cardinality
+ *                         key); -- the key to use for SELECT
+ *
+ * @sa doc/box-protocol.txt, binary protocol description
+ * @todo: implement box.unpack(format, str), for testing purposes
+ */
+static int
+lbox_pack(struct lua_State *L)
+{
+	luaL_Buffer b;
+	const char *format = luaL_checkstring(L, 1);
+	/* first arg comes second */
+	int i = 2;
+	int nargs = lua_gettop(L);
+	u16 u16buf;
+	u32 u32buf;
+	u64 u64buf;
+	size_t size;
+	const char *str;
+
+	luaL_buffinit(L, &b);
+
+	while (*format) {
+		if (i > nargs)
+			luaL_error(L, "box.pack: argument count does not match "
+				   "the format");
+		switch (*format) {
+		case 'B':
+		case 'b':
+			/* signed and unsigned 8-bit integers */
+			u32buf = lua_tointeger(L, i);
+			if (u32buf > 0xff)
+				luaL_error(L, "box.pack: argument too big for "
+					   "8-bit integer");
+			luaL_addchar(&b, (char) u32buf);
+			break;
+		case 'S':
+		case 's':
+			/* signed and unsigned 8-bit integers */
+			u32buf = lua_tointeger(L, i);
+			if (u32buf > 0xffff)
+				luaL_error(L, "box.pack: argument too big for "
+					   "16-bit integer");
+			u16buf = (u16) u32buf;
+			luaL_addlstring(&b, (char *) &u16buf, sizeof(u16));
+			break;
+		case 'I':
+		case 'i':
+			/* signed and unsigned 32-bit integers */
+			u32buf = lua_tointeger(L, i);
+			luaL_addlstring(&b, (char *) &u32buf, sizeof(u32));
+			break;
+		case 'L':
+		case 'l':
+			/* signed and unsigned 64-bit integers */
+			u64buf = tarantool_lua_tointeger64(L, i);
+			luaL_addlstring(&b, (char *) &u64buf, sizeof(u64));
+			break;
+		case 'w':
+			/* Perl 'pack' BER-encoded integer */
+			luaL_addvarint32(&b, lua_tointeger(L, i));
+			break;
+		case 'A':
+		case 'a':
+			/* A sequence of bytes */
+			str = luaL_checklstring(L, i, &size);
+			luaL_addlstring(&b, str, size);
+			break;
+		case 'P':
+		case 'p':
+			if (lua_type(L, i) == LUA_TNUMBER) {
+				u64buf = lua_tonumber(L, i);
+				if (u64buf > UINT32_MAX) {
+					str = (char *) &u64buf;
+					size = sizeof(u64);
+				} else {
+					u32buf = (u32) u64buf;
+					str = (char *) &u32buf;
+					size = sizeof(u32);
+				}
+			} else if (lua_type(L, i) == LUA_TCDATA) {
+				u64buf = tarantool_lua_tointeger64(L, i);
+				str = (char *) &u64buf;
+				size = sizeof(u64);
+			} else {
+				str = luaL_checklstring(L, i, &size);
+			}
+			luaL_addvarint32(&b, size);
+			luaL_addlstring(&b, str, size);
+			break;
+		case '=':
+			/* update tuple set foo = bar */
+		case '+':
+			/* set field += val */
+		case '-':
+			/* set field -= val */
+		case '&':
+			/* set field & =val */
+		case '|':
+			/* set field |= val */
+		case '^':
+			/* set field ^= val */
+		case ':':
+			/* splice */
+		case '#':
+			/* delete field */
+		case '!':
+			/* insert field */
+			/* field no */
+			u32buf = (u32) lua_tointeger(L, i);
+			luaL_addlstring(&b, (char *) &u32buf, sizeof(u32));
+			luaL_addchar(&b, format_to_opcode(*format));
+			break;
+		default:
+			luaL_error(L, "box.pack: unsupported pack "
+				   "format specifier '%c'", *format);
+		}
+		i++;
+		format++;
+	}
+	luaL_pushresult(&b);
+	return 1;
+}
+
+static int
+lbox_unpack(struct lua_State *L)
+{
+	size_t format_size = 0;
+	const char *format = luaL_checklstring(L, 1, &format_size);
+	const char *f = format;
+
+	size_t str_size = 0;
+	const u8 *str = (const u8 *) luaL_checklstring(L, 2, &str_size);
+	const u8 *end = str + str_size;
+	const u8 *s = str;
+
+	int i = 0;
+
+	char charbuf;
+	u8  u8buf;
+	u16 u16buf;
+	u32 u32buf;
+
+#define CHECK_SIZE(cur) if (unlikely((cur) >= end)) {	                \
+	luaL_error(L, "box.unpack('%c'): got %d bytes (expected: %d+)",	\
+		   *f, (int) (end - str), (int) 1 + ((cur) - str));	\
+}
+	while (*f) {
+		switch (*f) {
+		case 'b':
+			CHECK_SIZE(s);
+			u8buf = *(u8 *) s;
+			lua_pushnumber(L, u8buf);
+			s++;
+			break;
+		case 's':
+			CHECK_SIZE(s + 1);
+			u16buf = *(u16 *) s;
+			lua_pushnumber(L, u16buf);
+			s += 2;
+			break;
+		case 'i':
+			CHECK_SIZE(s + 3);
+			u32buf = *(u32 *) s;
+			lua_pushnumber(L, u32buf);
+			s += 4;
+			break;
+		case 'l':
+			CHECK_SIZE(s + 7);
+			luaL_pushnumber64(L, *(uint64_t*) s);
+			s += 8;
+			break;
+		case 'w':
+			/* load_varint32_s throws exception on error. */
+			u32buf = load_varint32_s((void *)&s, end - s);
+			lua_pushnumber(L, u32buf);
+			break;
+		case 'P':
+		case 'p':
+			/* load_varint32_s throws exception on error. */
+			u32buf = load_varint32_s((void *)&s, end - s);
+			CHECK_SIZE(s + u32buf - 1);
+			lua_pushlstring(L, (const char *) s, u32buf);
+			s += u32buf;
+			break;
+		case '=':
+			/* update tuple set foo = bar */
+		case '+':
+			/* set field += val */
+		case '-':
+			/* set field -= val */
+		case '&':
+			/* set field & =val */
+		case '|':
+			/* set field |= val */
+		case '^':
+			/* set field ^= val */
+		case ':':
+			/* splice */
+		case '#':
+			/* delete field */
+		case '!':
+			/* insert field */
+			CHECK_SIZE(s + 4);
+
+			/* field no */
+			u32buf = *(u32 *) s;
+
+			/* opcode */
+			charbuf = *(char *) (s + 4);
+			charbuf = opcode_to_format(charbuf);
+			if (charbuf != *f) {
+				luaL_error(L, "box.unpack('%s'): "
+					   "unexpected opcode: "
+					   "offset %d, expected '%c',"
+					   "found '%c'",
+					   format, s - str, *f, charbuf);
+			}
+
+			lua_pushnumber(L, u32buf);
+			s += 5;
+			break;
+		default:
+			luaL_error(L, "box.unpack: unsupported "
+				   "format specifier '%c'", *f);
+		}
+		i++;
+		f++;
+	}
+
+	assert(s <= end);
+
+	if (s != end) {
+		luaL_error(L, "box.unpack('%s'): too many bytes: "
+			   "unpacked %d, total %d",
+			   format, s - str, str_size);
+	}
+
+	return i;
+
+#undef CHECK_SIZE
+}
+
+static const struct luaL_reg boxlib[] = {
+	{"process", lbox_process},
+	{"raise", lbox_raise},
+	{"pack", lbox_pack},
+	{"unpack", lbox_unpack},
+	{NULL, NULL}
+};
+
 void
 mod_lua_init(struct lua_State *L)
 {
diff --git a/src/lua/init.m b/src/lua/init.m
index 5a101cf4ef41be731ab764a4649aa4bd8b6c8ed4..ef9f3bd804ea58f7250ebfcad5cf085525ba80b7 100644
--- a/src/lua/init.m
+++ b/src/lua/init.m
@@ -101,19 +101,6 @@ tarantool_lua_dup_out(struct lua_State *L, struct lua_State *child_L)
 
 const char *boxlib_name = "box";
 
-/**
- * Pack our BER integer into luaL_Buffer
- */
-static void
-luaL_addvarint32(luaL_Buffer *b, u32 u32)
-{
-	char varint_buf[sizeof(u32)+1];
-	struct tbuf tbuf = { .size = 0, .capacity = sizeof(varint_buf),
-		.data = varint_buf };
-	write_varint32(&tbuf, u32);
-	luaL_addlstring(b, tbuf.data, tbuf.size);
-}
-
 uint64_t
 tarantool_lua_tointeger64(struct lua_State *L, int idx)
 {
@@ -154,188 +141,6 @@ tarantool_lua_tointeger64(struct lua_State *L, int idx)
 	return result;
 }
 
-/**
- * Convert box.pack() format specifier to Tarantool
- * binary protocol UPDATE opcode
- */
-static char format_to_opcode(char format)
-{
-	switch (format) {
-	case '=': return 0;
-	case '+': return 1;
-	case '&': return 2;
-	case '^': return 3;
-	case '|': return 4;
-	case ':': return 5;
-	case '#': return 6;
-	case '!': return 7;
-	case '-': return 8;
-	default: return format;
-	}
-}
-
-/**
- * Counterpart to @a format_to_opcode
- */
-static char opcode_to_format(char opcode)
-{
-	switch (opcode) {
-	case 0: return '=';
-	case 1: return '+';
-	case 2: return '&';
-	case 3: return '^';
-	case 4: return '|';
-	case 5: return ':';
-	case 6: return '#';
-	case 7: return '!';
-	case 8: return '-';
-	default: return opcode;
-	}
-}
-
-/**
- * To use Tarantool/Box binary protocol primitives from Lua, we
- * need a way to pack Lua variables into a binary representation.
- * We do it by exporting a helper function
- *
- * box.pack(format, args...)
- *
- * which takes the format, which is very similar to Perl 'pack'
- * format, and a list of arguments, and returns a binary string
- * which has the arguments packed according to the format.
- *
- * For example, a typical SELECT packet packs in Lua like this:
- *
- * pkt = box.pack("iiiiiip", -- pack format
- *                         0, -- space id
- *                         0, -- index id
- *                         0, -- offset
- *                         2^32, -- limit
- *                         1, -- number of SELECT arguments
- *                         1, -- tuple cardinality
- *                         key); -- the key to use for SELECT
- *
- * @sa doc/box-protocol.txt, binary protocol description
- * @todo: implement box.unpack(format, str), for testing purposes
- */
-static int
-lbox_pack(struct lua_State *L)
-{
-	luaL_Buffer b;
-	const char *format = luaL_checkstring(L, 1);
-	/* first arg comes second */
-	int i = 2;
-	int nargs = lua_gettop(L);
-	u16 u16buf;
-	u32 u32buf;
-	u64 u64buf;
-	size_t size;
-	const char *str;
-
-	luaL_buffinit(L, &b);
-
-	while (*format) {
-		if (i > nargs)
-			luaL_error(L, "box.pack: argument count does not match "
-				   "the format");
-		switch (*format) {
-		case 'B':
-		case 'b':
-			/* signed and unsigned 8-bit integers */
-			u32buf = lua_tointeger(L, i);
-			if (u32buf > 0xff)
-				luaL_error(L, "box.pack: argument too big for "
-					   "8-bit integer");
-			luaL_addchar(&b, (char) u32buf);
-			break;
-		case 'S':
-		case 's':
-			/* signed and unsigned 8-bit integers */
-			u32buf = lua_tointeger(L, i);
-			if (u32buf > 0xffff)
-				luaL_error(L, "box.pack: argument too big for "
-					   "16-bit integer");
-			u16buf = (u16) u32buf;
-			luaL_addlstring(&b, (char *) &u16buf, sizeof(u16));
-			break;
-		case 'I':
-		case 'i':
-			/* signed and unsigned 32-bit integers */
-			u32buf = lua_tointeger(L, i);
-			luaL_addlstring(&b, (char *) &u32buf, sizeof(u32));
-			break;
-		case 'L':
-		case 'l':
-			/* signed and unsigned 64-bit integers */
-			u64buf = tarantool_lua_tointeger64(L, i);
-			luaL_addlstring(&b, (char *) &u64buf, sizeof(u64));
-			break;
-		case 'w':
-			/* Perl 'pack' BER-encoded integer */
-			luaL_addvarint32(&b, lua_tointeger(L, i));
-			break;
-		case 'A':
-		case 'a':
-			/* A sequence of bytes */
-			str = luaL_checklstring(L, i, &size);
-			luaL_addlstring(&b, str, size);
-			break;
-		case 'P':
-		case 'p':
-			if (lua_type(L, i) == LUA_TNUMBER) {
-				u64buf = lua_tonumber(L, i);
-				if (u64buf > UINT32_MAX) {
-					str = (char *) &u64buf;
-					size = sizeof(u64);
-				} else {
-					u32buf = (u32) u64buf;
-					str = (char *) &u32buf;
-					size = sizeof(u32);
-				}
-			} else if (lua_type(L, i) == LUA_TCDATA) {
-				u64buf = tarantool_lua_tointeger64(L, i);
-				str = (char *) &u64buf;
-				size = sizeof(u64);
-			} else {
-				str = luaL_checklstring(L, i, &size);
-			}
-			luaL_addvarint32(&b, size);
-			luaL_addlstring(&b, str, size);
-			break;
-		case '=':
-			/* update tuple set foo = bar */
-		case '+':
-			/* set field += val */
-		case '-':
-			/* set field -= val */
-		case '&':
-			/* set field & =val */
-		case '|':
-			/* set field |= val */
-		case '^':
-			/* set field ^= val */
-		case ':':
-			/* splice */
-		case '#':
-			/* delete field */
-		case '!':
-			/* insert field */
-			/* field no */
-			u32buf = (u32) lua_tointeger(L, i);
-			luaL_addlstring(&b, (char *) &u32buf, sizeof(u32));
-			luaL_addchar(&b, format_to_opcode(*format));
-			break;
-		default:
-			luaL_error(L, "box.pack: unsupported pack "
-				   "format specifier '%c'", *format);
-		}
-		i++;
-		format++;
-	}
-	luaL_pushresult(&b);
-	return 1;
-}
-
 static GCcdata*
 luaL_pushcdata(struct lua_State *L, CTypeID id, int bits)
 {
@@ -359,127 +164,6 @@ luaL_pushnumber64(struct lua_State *L, uint64_t val)
 	return 1;
 }
 
-
-static int
-lbox_unpack(struct lua_State *L)
-{
-	size_t format_size = 0;
-	const char *format = luaL_checklstring(L, 1, &format_size);
-	const char *f = format;
-
-	size_t str_size = 0;
-	const u8 *str = (const u8 *) luaL_checklstring(L, 2, &str_size);
-	const u8 *end = str + str_size;
-	const u8 *s = str;
-
-	int i = 0;
-
-	char charbuf;
-	u8  u8buf;
-	u16 u16buf;
-	u32 u32buf;
-
-#define CHECK_SIZE(cur) if (unlikely((cur) >= end)) {	                \
-	luaL_error(L, "box.unpack('%c'): got %d bytes (expected: %d+)",	\
-		   *f, (int) (end - str), (int) 1 + ((cur) - str));	\
-}
-	while (*f) {
-		switch (*f) {
-		case 'b':
-			CHECK_SIZE(s);
-			u8buf = *(u8 *) s;
-			lua_pushnumber(L, u8buf);
-			s++;
-			break;
-		case 's':
-			CHECK_SIZE(s + 1);
-			u16buf = *(u16 *) s;
-			lua_pushnumber(L, u16buf);
-			s += 2;
-			break;
-		case 'i':
-			CHECK_SIZE(s + 3);
-			u32buf = *(u32 *) s;
-			lua_pushnumber(L, u32buf);
-			s += 4;
-			break;
-		case 'l':
-			CHECK_SIZE(s + 7);
-			GCcdata *cd = luaL_pushcdata(L, CTID_UINT64, 8);
-			*(uint64_t*)cdataptr(cd) = *(uint64_t*) s;
-			s += 8;
-			break;
-		case 'w':
-			/* load_varint32_s throws exception on error. */
-			u32buf = load_varint32_s((void *)&s, end - s);
-			lua_pushnumber(L, u32buf);
-			break;
-		case 'P':
-		case 'p':
-			/* load_varint32_s throws exception on error. */
-			u32buf = load_varint32_s((void *)&s, end - s);
-			CHECK_SIZE(s + u32buf - 1);
-			lua_pushlstring(L, (const char *) s, u32buf);
-			s += u32buf;
-			break;
-		case '=':
-			/* update tuple set foo = bar */
-		case '+':
-			/* set field += val */
-		case '-':
-			/* set field -= val */
-		case '&':
-			/* set field & =val */
-		case '|':
-			/* set field |= val */
-		case '^':
-			/* set field ^= val */
-		case ':':
-			/* splice */
-		case '#':
-			/* delete field */
-		case '!':
-			/* insert field */
-			CHECK_SIZE(s + 4);
-
-			/* field no */
-			u32buf = *(u32 *) s;
-
-			/* opcode */
-			charbuf = *(char *) (s + 4);
-			charbuf = opcode_to_format(charbuf);
-			if (charbuf != *f) {
-				luaL_error(L, "box.unpack('%s'): "
-					   "unexpected opcode: "
-					   "offset %d, expected '%c',"
-					   "found '%c'",
-					   format, s - str, *f, charbuf);
-			}
-
-			lua_pushnumber(L, u32buf);
-			s += 5;
-			break;
-		default:
-			luaL_error(L, "box.unpack: unsupported "
-				   "format specifier '%c'", *f);
-		}
-		i++;
-		f++;
-	}
-
-	assert(s <= end);
-
-	if (s != end) {
-		luaL_error(L, "box.unpack('%s'): too many bytes: "
-			   "unpacked %d, total %d",
-			   format, s - str, str_size);
-	}
-
-	return i;
-
-#undef CHECK_SIZE
-}
-
 /** Report libev time (cheap). */
 static int
 lbox_time(struct lua_State *L)
@@ -496,14 +180,10 @@ lbox_time64(struct lua_State *L)
 	return 1;
 }
 
-
-
 /**
  * descriptor for box methods
  */
 static const struct luaL_reg boxlib[] = {
-	{"pack", lbox_pack},
-	{"unpack", lbox_unpack},
 	{"time", lbox_time},
 	{"time64", lbox_time64},
 	{NULL, NULL}
diff --git a/test/box/lua.result b/test/box/lua.result
index 482a4370f7effd3ee8e4b5ea741a0c13325a234d..5a4d05d5bccd2a6d230d7d15bae000d39cc4036f 100644
--- a/test/box/lua.result
+++ b/test/box/lua.result
@@ -32,14 +32,14 @@ lua for n in pairs(box) do print('  - box.', n) end
   - box.space
   - box.insert
   - box.cfg
-  - box.uuid
-  - box.session
   - box.tuple
+  - box.session
   - box.select_limit
+  - box.index
   - box.dostring
   - box.process
-  - box.index
   - box.stat
+  - box.uuid
   - box.select
   - box.flags
   - box.unpack