diff options
author | Josh Haberman <jhaberman@gmail.com> | 2016-09-09 14:03:25 -0700 |
---|---|---|
committer | Josh Haberman <jhaberman@gmail.com> | 2016-11-29 17:56:13 +0000 |
commit | 4b0c4ca7fb0aa9207af3398e04534b23fbb88f27 (patch) | |
tree | 045750c6262e74f366ae2ec29797d3816005c21a /upb/bindings/lua/upb/pb.c | |
parent | 77c97fd3f29caa5c243294b5f4e6763b3ed3c36f (diff) |
New upb_msg code and Lua bindings around it.
There are still some things that are unfinished,
but we are at parity with what Lua had before.
Diffstat (limited to 'upb/bindings/lua/upb/pb.c')
-rw-r--r-- | upb/bindings/lua/upb/pb.c | 94 |
1 files changed, 41 insertions, 53 deletions
diff --git a/upb/bindings/lua/upb/pb.c b/upb/bindings/lua/upb/pb.c index f095a61..d6f13d9 100644 --- a/upb/bindings/lua/upb/pb.c +++ b/upb/bindings/lua/upb/pb.c @@ -10,59 +10,24 @@ #define LUPB_PBDECODERMETHOD "lupb.pb.decodermethod" -#define MSGDEF_INDEX 1 - -static upb_pbdecodermethod *lupb_pbdecodermethod_check(lua_State *L, int narg) { - return lupb_refcounted_check(L, narg, LUPB_PBDECODERMETHOD); -} - -static int lupb_pbdecodermethod_new(lua_State *L) { - const upb_handlers *handlers = lupb_msg_newwritehandlers(L, 1, &handlers); - const upb_pbdecodermethod *m; - - upb_pbdecodermethodopts opts; - upb_pbdecodermethodopts_init(&opts, handlers); - - m = upb_pbdecodermethod_new(&opts, &m); - upb_handlers_unref(handlers, &handlers); - lupb_refcounted_pushnewrapper( - L, upb_pbdecodermethod_upcast(m), LUPB_PBDECODERMETHOD, &m); - - /* We need to keep a pointer to the MessageDef (in Lua space) so we can - * construct new messages in parse(). */ - lua_newtable(L); - lua_pushvalue(L, 1); - lua_rawseti(L, -2, MSGDEF_INDEX); - lua_setuservalue(L, -2); - - return 1; /* The DecoderMethod wrapper. */ -} - -/* Unlike most of our exposed Lua functions, this does not correspond to an - * actual method on the underlying DecoderMethod. But it's convenient, and - * important to implement in C because we can do stack allocation and - * initialization of our runtime structures like the Decoder and Sink. */ -static int lupb_pbdecodermethod_parse(lua_State *L) { +static int lupb_pb_strtomessage(lua_State *L) { size_t len; - const upb_pbdecodermethod *method = lupb_pbdecodermethod_check(L, 1); - const char *pb = lua_tolstring(L, 2, &len); - void *msg; upb_status status = UPB_STATUS_INIT; + const char *pb = lua_tolstring(L, 1, &len); + const upb_msglayout *layout = lua_touserdata(L, lua_upvalueindex(1)); + const upb_pbdecodermethod *method = lua_touserdata(L, lua_upvalueindex(2)); + const upb_handlers *handlers = upb_pbdecodermethod_desthandlers(method); + + upb_arena *msg_arena; upb_env env; upb_sink sink; upb_pbdecoder *decoder; + void *msg; - const upb_handlers *handlers = upb_pbdecodermethod_desthandlers(method); - - lua_getuservalue(L, 1); - lua_rawgeti(L, -1, MSGDEF_INDEX); - lupb_assert(L, !lua_isnil(L, -1)); - lupb_msg_pushnew(L, -1); /* Push new message. */ - msg = lua_touserdata(L, -1); - - /* Handlers need this. */ - lua_getuservalue(L, -1); + lupb_arena_new(L); + msg_arena = lupb_arena_check(L, -1); + msg = upb_msg_new(layout, upb_arena_alloc(msg_arena)); upb_env_init(&env); upb_env_reporterrorsto(&env, &status); upb_sink_reset(&sink, handlers, msg); @@ -76,18 +41,42 @@ static int lupb_pbdecodermethod_parse(lua_State *L) { lupb_checkstatus(L, &status); - lua_pop(L, 1); /* Uservalue. */ - + /* References the arena at the top of the stack. */ + lupb_msg_pushref(L, lua_upvalueindex(3), msg); return 1; } -static const struct luaL_Reg lupb_pbdecodermethod_m[] = { - {"parse", lupb_pbdecodermethod_parse}, +static int lupb_pb_makestrtomsgdecoder(lua_State *L) { + const upb_msglayout *layout = lupb_msgclass_getlayout(L, 1); + const upb_handlers *handlers = lupb_msgclass_getmergehandlers(L, 1); + const upb_pbdecodermethod *m; + + upb_pbdecodermethodopts opts; + upb_pbdecodermethodopts_init(&opts, handlers); + + m = upb_pbdecodermethod_new(&opts, &m); + + /* Push upvalues for the closure. */ + lua_pushlightuserdata(L, (void*)layout); + lua_pushlightuserdata(L, (void*)m); + lua_pushvalue(L, 1); + + /* Upvalue for the closure, only to keep the decodermethod alive. */ + lupb_refcounted_pushnewrapper( + L, upb_pbdecodermethod_upcast(m), LUPB_PBDECODERMETHOD, &m); + + lua_pushcclosure(L, &lupb_pb_strtomessage, 4); + + return 1; /* The decoder closure. */ +} + +static const struct luaL_Reg decodermethod_mm[] = { + {"__gc", lupb_refcounted_gc}, {NULL, NULL} }; static const struct luaL_Reg toplevel_m[] = { - {"DecoderMethod", lupb_pbdecodermethod_new}, + {"MakeStringToMessageDecoder", lupb_pb_makestrtomsgdecoder}, {NULL, NULL} }; @@ -97,8 +86,7 @@ int luaopen_upb_pb_c(lua_State *L) { return 1; } - lupb_register_type(L, LUPB_PBDECODERMETHOD, lupb_pbdecodermethod_m, NULL, - true); + lupb_register_type(L, LUPB_PBDECODERMETHOD, NULL, decodermethod_mm); return 1; } |