From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: From: "v.shpilevoy@tarantool.org" Message-Id: Content-Type: multipart/alternative; boundary="Apple-Mail=_D0B44ADD-7E84-451B-A951-A7489B508424" Mime-Version: 1.0 (Mac OS X Mail 11.2 \(3445.5.20\)) Subject: Re: [PATCH 2/5] lua: port console yaml formatting to C Date: Tue, 20 Mar 2018 21:04:09 +0300 In-Reply-To: <20180320175113.bnocgitvdf5eh2dn@esperanza> References: <881a3705ddfd6c3885171fe3a748b0e2baaded92.1521466428.git.v.shpilevoy@tarantool.org> <20180320175113.bnocgitvdf5eh2dn@esperanza> To: Vladimir Davydov Cc: tarantool-patches@freelists.org List-ID: --Apple-Mail=_D0B44ADD-7E84-451B-A951-A7489B508424 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset=utf-8 > 20 =D0=BC=D0=B0=D1=80=D1=82=D0=B0 2018 =D0=B3., =D0=B2 20:51, Vladimir = Davydov =D0=BD=D0=B0=D0=BF=D0=B8=D1=81=D0=B0=D0=BB= (=D0=B0): >=20 > On Mon, Mar 19, 2018 at 04:34:49PM +0300, Vladislav Shpilevoy wrote: >> Box.session.push() will be implemented in C lbox_session_push() >> function, which will use port to encapsulate different session >> types (binary, text) push() logic. And push() must be able to >> either encode an argument into message pack, or format it as a >> string using yaml. This formatting can not be done in Lua before >> push() call, since it breaks push() virtualization. >>=20 >> Needed for #2677 >>=20 >> Signed-off-by: Vladislav Shpilevoy >> --- >> src/box/lua/console.c | 42 = ++++++++++++++++++++++++++++++++++++++++++ >> src/box/lua/console.lua | 34 ++++++++-------------------------- >> third_party/lua-yaml/lyaml.cc | 9 +++------ >> third_party/lua-yaml/lyaml.h | 3 +++ >> 4 files changed, 56 insertions(+), 32 deletions(-) >>=20 >> diff --git a/src/box/lua/console.c b/src/box/lua/console.c >=20 >> @@ -328,6 +329,32 @@ lbox_console_add_history(struct lua_State *L) >> return 0; >> } >>=20 >> +static int >> +lbox_console_format(struct lua_State *L) >> +{ >> + int arg_count =3D lua_gettop(L); >> + if (arg_count =3D=3D 0) { >> + lua_pushstring(L, "---\n...\n"); >> + return 1; >> + } >> + lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED"); >> + lua_getfield(L, -1, "console"); >> + lua_getfield(L, -1, "formatter"); >> + lua_getfield(L, -1, "encode"); >> + lua_createtable(L, arg_count, 0); >> + for (int i =3D 0; i < arg_count; ++i) { >> + if (lua_isnil(L, i + 1)) >> + lua_getfield(L, -3, "NULL"); >> + else >> + lua_pushvalue(L, i + 1); >> + lua_rawseti(L, -2, i + 1); >> + } >> + lua_call(L, 1, 1); >> + lua_insert(L, -4); >> + lua_pop(L, 3); >> + return 1; >> +} >> + >> void >> tarantool_lua_console_init(struct lua_State *L) >> { >=20 >> @@ -344,6 +372,20 @@ tarantool_lua_console_init(struct lua_State *L) >> lua_getfield(L, -1, "completion_handler"); >> lua_pushcclosure(L, lbox_console_readline, 1); >> lua_setfield(L, -2, "readline"); >> + >> + lua_yaml_new_formatter(L); >> + lua_getfield(L, -1, "cfg"); >> + lua_createtable(L, 0, 4); >> + lua_pushboolean(L, true); >> + lua_setfield(L, -2, "encode_invalid_numbers"); >> + lua_pushboolean(L, true); >> + lua_setfield(L, -2, "encode_load_metatables"); >> + lua_pushboolean(L, true); >> + lua_setfield(L, -2, "encode_use_tostring"); >> + lua_pushboolean(L, true); >> + lua_setfield(L, -2, "encode_invalid_as_nil"); >> + lua_call(L, 1, 0); >> + lua_setfield(L, -2, "formatter"); >=20 >> diff --git a/src/box/lua/console.lua b/src/box/lua/console.lua >> @@ -395,4 +375,6 @@ package.loaded['console'] =3D { >> on_start =3D on_start; >> on_client_disconnect =3D on_client_disconnect; >> completion_handler =3D internal.completion_handler; >> + formatter =3D internal.formatter; >=20 > I don't like that we export the serializer to Lua, but never use it in > Lua code, only in C. Can't we create a serializer in C and pass it to > the encoder function explicitly? The problem of Lua formatter is that it is Lua table, not cdata. And to = fully port it on C it is necessary to rewrite luaL_serializer and l_dump = in lyaml.cc , that seems to be too complicated for a = single propose - format push message. But if you insist, I can do full = port. --Apple-Mail=_D0B44ADD-7E84-451B-A951-A7489B508424 Content-Transfer-Encoding: quoted-printable Content-Type: text/html; charset=utf-8

20 =D0=BC=D0=B0=D1=80=D1=82=D0=B0 2018 =D0=B3., =D0=B2 20:51, = Vladimir Davydov <vdavydov.dev@gmail.com> =D0=BD=D0=B0=D0=BF=D0=B8=D1=81=D0= =B0=D0=BB(=D0=B0):

On Mon, Mar 19, 2018 at 04:34:49PM +0300, = Vladislav Shpilevoy wrote:
Box.session.push() will be = implemented in C lbox_session_push()
function, which will = use port to encapsulate different session
types (binary, = text) push() logic. And push() must be able to
either = encode an argument into message pack, or format it as a
string using yaml. This formatting can not be done in Lua = before
push() call, since it breaks push() = virtualization.

Needed for #2677

Signed-off-by: Vladislav Shpilevoy <v.shpilevoy@tarantool.org>
---
src/box/lua/console.c =         | 42 = ++++++++++++++++++++++++++++++++++++++++++
src/box/lua/console.lua       | = 34 ++++++++--------------------------
third_party/lua-yaml/lyaml.cc |  9 +++------
third_party/lua-yaml/lyaml.h  |  3 +++
4 files changed, 56 insertions(+), 32 deletions(-)

diff --git a/src/box/lua/console.c = b/src/box/lua/console.c

@@ -328,6 +329,32 @@ = lbox_console_add_history(struct lua_State *L)
return = 0;
}

+static int
+lbox_console_format(struct lua_State *L)
+{
+ = int arg_count =3D lua_gettop(L);
+ if = (arg_count =3D=3D 0) {
+ lua_pushstring(L, = "---\n...\n");
+ return 1;
+ }
+ = lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED");
+ = lua_getfield(L, -1, "console");
+ = lua_getfield(L, -1, "formatter");
+ = lua_getfield(L, -1, "encode");
+ = lua_createtable(L, arg_count, 0);
+ for (int = i =3D 0; i < arg_count; ++i) {
+ if = (lua_isnil(L, i + 1))
+ lua_getfield(L, -3, "NULL");
+ = = else
+ lua_pushvalue(L, i + 1);
+ = = lua_rawseti(L, -2, i + 1);
+ }
+ = lua_call(L, 1, 1);
+ lua_insert(L, -4);
+ = lua_pop(L, 3);
+ return 1;
+}
+
void
tarantool_lua_console_init(struct lua_State *L)
{

@@ -344,6 +372,20 @@ = tarantool_lua_console_init(struct lua_State *L)
= lua_getfield(L, -1, "completion_handler");
= lua_pushcclosure(L, lbox_console_readline, 1);
= lua_setfield(L, -2, "readline");
+
+ = lua_yaml_new_formatter(L);
+ = lua_getfield(L, -1, "cfg");
+ = lua_createtable(L, 0, 4);
+ = lua_pushboolean(L, true);
+ = lua_setfield(L, -2, "encode_invalid_numbers");
+ = lua_pushboolean(L, true);
+ = lua_setfield(L, -2, "encode_load_metatables");
+ = lua_pushboolean(L, true);
+ = lua_setfield(L, -2, "encode_use_tostring");
+ = lua_pushboolean(L, true);
+ = lua_setfield(L, -2, "encode_invalid_as_nil");
+ = lua_call(L, 1, 0);
+ lua_setfield(L, -2, = "formatter");

diff --git = a/src/box/lua/console.lua b/src/box/lua/console.lua
@@ = -395,4 +375,6 @@ package.loaded['console'] =3D {
    on_start =3D on_start;
    on_client_disconnect =3D = on_client_disconnect;
    completion_handler =3D = internal.completion_handler;
+    formatter = =3D internal.formatter;

I don't like that we export the serializer to = Lua, but never use it in
Lua code, only in = C. Can't we create a serializer in C and pass it to
the encoder function = explicitly?

The = problem of Lua formatter is that it is Lua table, not cdata. And to = fully port it on C it is necessary to rewrite luaL_serializer = and l_dump in lyaml.cc, = that seems to be too complicated for a single propose - format push = message. But if you insist, I can do full port.


= --Apple-Mail=_D0B44ADD-7E84-451B-A951-A7489B508424--