Tarantool development patches archive
 help / color / mirror / Atom feed
From: Vladislav Shpilevoy <v.shpilevoy@tarantool.org>
To: Mergen Imeev <imeevma@tarantool.org>
Cc: tarantool-patches@freelists.org
Subject: [tarantool-patches] Re: [PATCH v9 4/7] lua: remove exceptions from function luaL_tofield()
Date: Thu, 28 Mar 2019 21:40:00 +0300	[thread overview]
Message-ID: <58e2a19a-e6ce-bfaf-d926-c216ae83f197@tarantool.org> (raw)
In-Reply-To: <20190328175410.GC4864@tarantool.org>

Thanks for the fixes! I've pushed my review fixes on the
branch, and dropped at the end of the email. But I've not
tested them, so I propose you to do that, if you agree
with the concept.

=========================================================

diff --git a/src/lua/utils.c b/src/lua/utils.c
index 6150e84ff..38245a979 100644
--- a/src/lua/utils.c
+++ b/src/lua/utils.c
@@ -399,47 +399,58 @@ lua_field_inspect_ucdata(struct lua_State *L, struct luaL_serializer *cfg,
 }
 
 /**
- * Check that the field LUAL_SERIALIZE of the metatable is
- * available. If so, create field using it.
- *
- * This function returns two values on stack. On top of the stack
- * is boolean that shows if error happened. On the next position
- * can be boolean or result of execution of function from the
- * metatable. If it is boolean, that if its value is false than
- * there were no metatables.It its value is true than there was
- * string in that field of metatable.
- *
- * @param L Lua State.
+ * A helper structure to simplify safe call of __serialize method.
+ * It passes some arguments into the serializer called via pcall,
+ * and carries out some results.
+ */
+struct lua_serialize_status {
+	/**
+	 * True if an attempt to call __serialize has failed. A
+	 * diag message is set.
+	 */
+	bool is_error;
+	/**
+	 * True, if __serialize exists. Otherwise an ordinary
+	 * default serialization is used.
+	 */
+	bool is_serialize_used;
+	/** Parameters, passed originally to luaL_tofield. */
+	struct luaL_serializer *cfg;
+	struct luaL_field *field;
+};
+
+/**
+ * Call __serialize method of a table object if the former exists.
+ * The function expects 2 values pushed onto the Lua stack: a
+ * value to serialize, and a pointer at a struct
+ * lua_serialize_status object. If __serialize exists and is
+ * correct, then one value is pushed as a result of serialization.
+ * Otherwise is_error and is_serialize_used attributes of status
+ * should be checked.
  */
 static int
-get_metafield_serialize(struct lua_State *L)
+lua_field_try_serialize(struct lua_State *L)
 {
-	if (luaL_getmetafield(L, 1, LUAL_SERIALIZE) == 0) {
-		lua_pushboolean(L, false);
-		lua_pushboolean(L, false);
-		return 2;
-	}
-	bool is_error = false;
-	struct luaL_serializer *cfg =
-		(struct luaL_serializer *)lua_touserdata(L, 2);
-	struct luaL_field *field =
-		(struct luaL_field *)lua_touserdata(L, 3);
-
+	struct lua_serialize_status *s =
+		(struct lua_serialize_status *) lua_touserdata(L, 2);
+	s->is_serialize_used = (luaL_getmetafield(L, 1, LUAL_SERIALIZE) != 0);
+	s->is_error = false;
+	if (! s->is_serialize_used)
+		return 0;
+	struct luaL_serializer *cfg = s->cfg;
+	struct luaL_field *field = s->field;
 	if (lua_isfunction(L, -1)) {
 		/* copy object itself */
 		lua_pushvalue(L, 1);
 		lua_call(L, 1, 1);
-		is_error = (luaL_tofield(L, cfg, -1, field) != 0);
-		lua_pushboolean(L, is_error);
-		return 2;
+		s->is_error = (luaL_tofield(L, cfg, -1, field) != 0);
+		return s->is_error ? 0 : 1;
 	}
-
 	if (!lua_isstring(L, -1)) {
 		diag_set(LuajitError, "invalid " LUAL_SERIALIZE " value");
-		lua_pushboolean(L, true);
-		return 2;
+		s->is_error = true;
+		return 0;
 	}
-
 	const char *type = lua_tostring(L, -1);
 	if (strcmp(type, "array") == 0 || strcmp(type, "seq") == 0 ||
 	    strcmp(type, "sequence") == 0) {
@@ -449,9 +460,7 @@ get_metafield_serialize(struct lua_State *L)
 		if (cfg->has_compact && type[3] == '\0')
 			field->compact = true;
 		lua_pop(L, 1); /* type */
-		lua_pushboolean(L, true);
-		lua_pushboolean(L, false);
-		return 2;
+		return 1;
 	} else if (strcmp(type, "map") == 0 || strcmp(type, "mapping") == 0) {
 		field->type = MP_MAP;   /* Override type */
 		field->size = luaL_maplen(L, 1);
@@ -459,13 +468,11 @@ get_metafield_serialize(struct lua_State *L)
 		if (cfg->has_compact && type[3] == '\0')
 			field->compact = true;
 		lua_pop(L, 1); /* type */
-		lua_pushboolean(L, true);
-		lua_pushboolean(L, false);
-		return 2;
+		return 1;
 	} else {
 		diag_set(LuajitError, "invalid " LUAL_SERIALIZE " value");
-		lua_pushboolean(L, true);
-		return 2;
+		s->is_error = true;
+		return 0;
 	}
 }
 
@@ -478,27 +485,19 @@ lua_field_inspect_table(struct lua_State *L, struct luaL_serializer *cfg,
 	uint32_t max = 0;
 
 	if (cfg->encode_load_metatables) {
-		lua_pushcfunction(L, get_metafield_serialize);
+		struct lua_serialize_status s;
+		s.cfg = cfg;
+		s.field = field;
+		lua_pushcfunction(L, lua_field_try_serialize);
 		lua_pushvalue(L, idx);
-		lua_pushlightuserdata(L, cfg);
-		lua_pushlightuserdata(L, field);
-		if (lua_pcall(L, 3, 2, 0) != 0) {
+		lua_pushlightuserdata(L, &s);
+		if (lua_pcall(L, 2, 1, 0) != 0) {
 			diag_set(LuajitError, lua_tostring(L, -1));
 			return -1;
 		}
-		bool is_error = lua_toboolean(L, -1);
-		bool is_bool = lua_isboolean(L, -2);
-		if (is_error) {
-			lua_pop(L, 2);
+		if (s.is_error)
 			return -1;
-		}
-		if (is_bool) {
-			bool is_metatable_available = lua_toboolean(L, -2);
-			lua_pop(L, 2);
-			if (is_metatable_available)
-				return 0;
-		} else {
-			lua_pop(L, 1);
+		if (s.is_serialize_used) {
 			lua_replace(L, idx);
 			return 0;
 		}

  reply	other threads:[~2019-03-28 18:40 UTC|newest]

Thread overview: 36+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-03-22 10:50 [tarantool-patches] [PATCH v9 0/7] sql: remove box.sql.execute imeevma
2019-03-22 10:50 ` [tarantool-patches] [PATCH v9 1/7] sql: add column name to SQL change counter imeevma
2019-03-22 15:42   ` [tarantool-patches] " Konstantin Osipov
2019-03-25 19:34     ` Mergen Imeev
2019-03-29 12:00   ` Kirill Yukhin
2019-03-22 10:50 ` [tarantool-patches] [PATCH v9 2/7] sql: fix error code for SQL errors in execute.c imeevma
2019-03-22 15:45   ` [tarantool-patches] " Konstantin Osipov
2019-03-26 21:48   ` Vladislav Shpilevoy
2019-03-27 11:43     ` Konstantin Osipov
2019-03-28 17:46     ` Mergen Imeev
2019-03-29 12:01   ` Kirill Yukhin
2019-03-22 10:50 ` [tarantool-patches] [PATCH v9 3/7] sql: remove box.sql.debug() imeevma
2019-03-22 15:46   ` [tarantool-patches] " Konstantin Osipov
2019-03-25 19:39     ` Mergen Imeev
2019-03-26 21:48       ` Vladislav Shpilevoy
2019-03-28 17:48         ` Mergen Imeev
2019-03-28 18:01           ` Vladislav Shpilevoy
2019-03-29 12:02   ` Kirill Yukhin
2019-03-22 10:50 ` [tarantool-patches] [PATCH v9 4/7] lua: remove exceptions from function luaL_tofield() imeevma
2019-03-22 15:53   ` [tarantool-patches] " Konstantin Osipov
2019-03-29 19:26     ` Vladislav Shpilevoy
2019-03-26 21:48   ` Vladislav Shpilevoy
2019-03-28 17:54     ` Mergen Imeev
2019-03-28 18:40       ` Vladislav Shpilevoy [this message]
2019-03-28 19:56         ` Mergen Imeev
2019-03-28 21:41           ` Mergen Imeev
2019-03-29 21:06           ` Vladislav Shpilevoy
2019-03-22 10:50 ` [tarantool-patches] [PATCH v9 5/7] iproto: create port_sql imeevma
2019-03-22 15:55   ` [tarantool-patches] " Konstantin Osipov
2019-03-22 10:50 ` [tarantool-patches] [PATCH v9 6/7] sql: create box.execute() imeevma
2019-03-22 15:57   ` [tarantool-patches] " Konstantin Osipov
2019-03-22 10:50 ` [tarantool-patches] [PATCH v9 7/7] sql: remove box.sql.execute() imeevma
2019-03-26 21:48   ` [tarantool-patches] " Vladislav Shpilevoy
2019-03-28 20:13     ` Mergen Imeev
2019-03-29 21:06       ` Vladislav Shpilevoy
2019-03-29 21:07 ` [tarantool-patches] Re: [PATCH v9 0/7] sql: remove box.sql.execute Vladislav Shpilevoy

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=58e2a19a-e6ce-bfaf-d926-c216ae83f197@tarantool.org \
    --to=v.shpilevoy@tarantool.org \
    --cc=imeevma@tarantool.org \
    --cc=tarantool-patches@freelists.org \
    --subject='[tarantool-patches] Re: [PATCH v9 4/7] lua: remove exceptions from function luaL_tofield()' \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox