|
|
|
@ -12,11 +12,12 @@ |
|
|
|
|
|
|
|
|
|
#include "lauxlib.h" |
|
|
|
|
#include "upb/bindings/lua/upb.h" |
|
|
|
|
#include "upb/json_decode.h" |
|
|
|
|
#include "upb/json_encode.h" |
|
|
|
|
#include "upb/port_def.inc" |
|
|
|
|
#include "upb/reflection.h" |
|
|
|
|
#include "upb/text_encode.h" |
|
|
|
|
|
|
|
|
|
#include "upb/port_def.inc" |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Message/Map/Array objects. These objects form a directed graph: a message |
|
|
|
|
* can contain submessages, arrays, and maps, which can then point to other |
|
|
|
@ -637,6 +638,20 @@ static const upb_fielddef *lupb_msg_checkfield(lua_State *L, int msg, |
|
|
|
|
return f; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
upb_msg *lupb_msg_pushnew(lua_State *L, int narg) { |
|
|
|
|
const upb_msgdef *m = lupb_msgdef_check(L, narg); |
|
|
|
|
lupb_msg *lmsg = lupb_newuserdata(L, sizeof(lupb_msg), 2, LUPB_MSG); |
|
|
|
|
upb_arena *arena = lupb_arena_pushnew(L); |
|
|
|
|
|
|
|
|
|
lua_setiuservalue(L, -2, LUPB_ARENA_INDEX); |
|
|
|
|
lua_pushvalue(L, 1); |
|
|
|
|
lua_setiuservalue(L, -2, LUPB_MSGDEF_INDEX); |
|
|
|
|
|
|
|
|
|
lmsg->msg = upb_msg_new(m, arena); |
|
|
|
|
lupb_cacheset(L, lmsg->msg); |
|
|
|
|
return lmsg->msg; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* lupb_msg_newmsgwrapper() |
|
|
|
|
* |
|
|
|
@ -726,28 +741,19 @@ static void lupb_msg_typechecksubmsg(lua_State *L, int narg, int msgarg, |
|
|
|
|
/* lupb_msg Public API */ |
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* lupb_msg_pushnew |
|
|
|
|
* lupb_msgdef_call |
|
|
|
|
* |
|
|
|
|
* Handles: |
|
|
|
|
* new_msg = MessageClass() |
|
|
|
|
* new_msg = MessageClass{foo = "bar", baz = 3, quux = {foo = 3}} |
|
|
|
|
*/ |
|
|
|
|
int lupb_msg_pushnew(lua_State *L) { |
|
|
|
|
int argcount = lua_gettop(L); |
|
|
|
|
const upb_msgdef *m = lupb_msgdef_check(L, 1); |
|
|
|
|
lupb_msg *lmsg = lupb_newuserdata(L, sizeof(lupb_msg), 2, LUPB_MSG); |
|
|
|
|
upb_arena *arena = lupb_arena_pushnew(L); |
|
|
|
|
|
|
|
|
|
lua_setiuservalue(L, -2, LUPB_ARENA_INDEX); |
|
|
|
|
lua_pushvalue(L, 1); |
|
|
|
|
lua_setiuservalue(L, -2, LUPB_MSGDEF_INDEX); |
|
|
|
|
|
|
|
|
|
lmsg->msg = upb_msg_new(m, arena); |
|
|
|
|
lupb_cacheset(L, lmsg->msg); |
|
|
|
|
int lupb_msgdef_call(lua_State *L) { |
|
|
|
|
int arg_count = lua_gettop(L); |
|
|
|
|
lupb_msg_pushnew(L, 1); |
|
|
|
|
|
|
|
|
|
if (argcount > 1) { |
|
|
|
|
if (arg_count > 1) { |
|
|
|
|
/* Set initial fields from table. */ |
|
|
|
|
int msg = lua_gettop(L); |
|
|
|
|
int msg = arg_count + 1; |
|
|
|
|
lua_pushnil(L); |
|
|
|
|
while (lua_next(L, 2) != 0) { |
|
|
|
|
lua_pushvalue(L, -2); /* now stack is key, val, key */ |
|
|
|
@ -883,6 +889,19 @@ static const struct luaL_Reg lupb_msg_mm[] = { |
|
|
|
|
|
|
|
|
|
/* lupb_msg toplevel **********************************************************/ |
|
|
|
|
|
|
|
|
|
static int lupb_getoptions(lua_State *L, int narg) { |
|
|
|
|
int options = 0; |
|
|
|
|
if (lua_gettop(L) >= narg) { |
|
|
|
|
size_t len = lua_rawlen(L, narg); |
|
|
|
|
for (size_t i = 1; i <= len; i++) { |
|
|
|
|
lua_rawgeti(L, narg, i); |
|
|
|
|
options |= lupb_checkuint32(L, -1); |
|
|
|
|
lua_pop(L, 1); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
return options; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* lupb_decode() |
|
|
|
|
* |
|
|
|
@ -894,26 +913,16 @@ static int lupb_decode(lua_State *L) { |
|
|
|
|
const upb_msgdef *m = lupb_msgdef_check(L, 1); |
|
|
|
|
const char *pb = lua_tolstring(L, 2, &len); |
|
|
|
|
const upb_msglayout *layout = upb_msgdef_layout(m); |
|
|
|
|
upb_msg *msg = lupb_msg_pushnew(L, 1); |
|
|
|
|
upb_arena *arena = lupb_arenaget(L, -1); |
|
|
|
|
char *buf; |
|
|
|
|
upb_msg *msg; |
|
|
|
|
upb_arena *arena; |
|
|
|
|
bool ok; |
|
|
|
|
|
|
|
|
|
/* Create message. */ |
|
|
|
|
lua_pushcfunction(L, &lupb_msg_pushnew); |
|
|
|
|
lua_pushvalue(L, 1); |
|
|
|
|
lua_call(L, 1, 1); |
|
|
|
|
msg = lupb_msg_check(L, -1); |
|
|
|
|
|
|
|
|
|
lua_getiuservalue(L, -1, LUPB_ARENA_INDEX); |
|
|
|
|
arena = lupb_arena_check(L, -1); |
|
|
|
|
lua_pop(L, 1); |
|
|
|
|
|
|
|
|
|
/* Copy input data to arena, message will reference it. */ |
|
|
|
|
buf = upb_arena_malloc(arena, len); |
|
|
|
|
memcpy(buf, pb, len); |
|
|
|
|
|
|
|
|
|
ok = upb_decode(buf, len, msg, layout, arena); |
|
|
|
|
ok = _upb_decode(buf, len, msg, layout, arena, UPB_DECODE_ALIAS); |
|
|
|
|
|
|
|
|
|
if (!ok) { |
|
|
|
|
lua_pushstring(L, "Error decoding protobuf."); |
|
|
|
@ -924,38 +933,81 @@ static int lupb_decode(lua_State *L) { |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* lupb_msg_textencode() |
|
|
|
|
* lupb_encode() |
|
|
|
|
* |
|
|
|
|
* Handles: |
|
|
|
|
* text_string = upb.text_encode(msg, {upb.TXTENC_SINGLELINE}) |
|
|
|
|
* bin_string = upb.encode(msg) |
|
|
|
|
*/ |
|
|
|
|
static int lupb_textencode(lua_State *L) { |
|
|
|
|
int argcount = lua_gettop(L); |
|
|
|
|
upb_msg *msg = lupb_msg_check(L, 1); |
|
|
|
|
const upb_msgdef *m; |
|
|
|
|
char buf[1024]; |
|
|
|
|
static int lupb_encode(lua_State *L) { |
|
|
|
|
const upb_msg *msg = lupb_msg_check(L, 1); |
|
|
|
|
const upb_msgdef *m = lupb_msg_getmsgdef(L, 1); |
|
|
|
|
const upb_msglayout *layout = upb_msgdef_layout(m); |
|
|
|
|
int options = lupb_getoptions(L, 2); |
|
|
|
|
upb_arena *arena; |
|
|
|
|
size_t size; |
|
|
|
|
int options = 0; |
|
|
|
|
char *result; |
|
|
|
|
|
|
|
|
|
lua_getiuservalue(L, 1, LUPB_MSGDEF_INDEX); |
|
|
|
|
m = lupb_msgdef_check(L, -1); |
|
|
|
|
arena = lupb_arena_pushnew(L); |
|
|
|
|
result = upb_encode_ex(msg, (const void*)layout, options, arena, &size); |
|
|
|
|
|
|
|
|
|
if (argcount > 1) { |
|
|
|
|
size_t len = lua_rawlen(L, 2); |
|
|
|
|
for (size_t i = 1; i <= len; i++) { |
|
|
|
|
lua_rawgeti(L, 2, i); |
|
|
|
|
options |= lupb_checkuint32(L, -1); |
|
|
|
|
lua_pop(L, 1); |
|
|
|
|
} |
|
|
|
|
if (!result) { |
|
|
|
|
lua_pushstring(L, "Error encoding protobuf."); |
|
|
|
|
return lua_error(L); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
size = upb_text_encode(msg, m, NULL, options, buf, sizeof(buf)); |
|
|
|
|
lua_pushlstring(L, result, size); |
|
|
|
|
|
|
|
|
|
return 1; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* lupb_jsondecode() |
|
|
|
|
* |
|
|
|
|
* Handles: |
|
|
|
|
* text_string = upb.json_decode(MessageClass, json_str, {upb.JSONDEC_IGNOREUNKNOWN}) |
|
|
|
|
*/ |
|
|
|
|
static int lupb_jsondecode(lua_State *L) { |
|
|
|
|
size_t len; |
|
|
|
|
const upb_msgdef *m = lupb_msgdef_check(L, 1); |
|
|
|
|
const char *json = lua_tolstring(L, 2, &len); |
|
|
|
|
int options = lupb_getoptions(L, 3); |
|
|
|
|
upb_msg *msg; |
|
|
|
|
upb_arena *arena; |
|
|
|
|
upb_status status; |
|
|
|
|
|
|
|
|
|
msg = lupb_msg_pushnew(L, 1); |
|
|
|
|
arena = lupb_arenaget(L, -1); |
|
|
|
|
upb_status_clear(&status); |
|
|
|
|
upb_json_decode(json, len, msg, m, NULL, options, arena, &status); |
|
|
|
|
lupb_checkstatus(L, &status); |
|
|
|
|
|
|
|
|
|
return 1; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* lupb_jsonencode() |
|
|
|
|
* |
|
|
|
|
* Handles: |
|
|
|
|
* text_string = upb.json_encode(msg, {upb.JSONENC_EMITDEFAULTS}) |
|
|
|
|
*/ |
|
|
|
|
static int lupb_jsonencode(lua_State *L) { |
|
|
|
|
upb_msg *msg = lupb_msg_check(L, 1); |
|
|
|
|
const upb_msgdef *m = lupb_msg_getmsgdef(L, 1); |
|
|
|
|
int options = lupb_getoptions(L, 2); |
|
|
|
|
char buf[1024]; |
|
|
|
|
size_t size; |
|
|
|
|
upb_status status; |
|
|
|
|
|
|
|
|
|
upb_status_clear(&status); |
|
|
|
|
size = upb_json_encode(msg, m, NULL, options, buf, sizeof(buf), &status); |
|
|
|
|
lupb_checkstatus(L, &status); |
|
|
|
|
|
|
|
|
|
if (size < sizeof(buf)) { |
|
|
|
|
lua_pushlstring(L, buf, size); |
|
|
|
|
} else { |
|
|
|
|
char *ptr = malloc(size + 1); |
|
|
|
|
upb_text_encode(msg, m, NULL, options, ptr, size + 1); |
|
|
|
|
upb_json_encode(msg, m, NULL, options, ptr, size + 1, &status); |
|
|
|
|
lupb_checkstatus(L, &status); |
|
|
|
|
lua_pushlstring(L, ptr, size); |
|
|
|
|
free(ptr); |
|
|
|
|
} |
|
|
|
@ -964,42 +1016,29 @@ static int lupb_textencode(lua_State *L) { |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* lupb_encode() |
|
|
|
|
* lupb_textencode() |
|
|
|
|
* |
|
|
|
|
* Handles: |
|
|
|
|
* bin_string = upb.encode(msg) |
|
|
|
|
* text_string = upb.text_encode(msg, {upb.TXTENC_SINGLELINE}) |
|
|
|
|
*/ |
|
|
|
|
static int lupb_encode(lua_State *L) { |
|
|
|
|
int argcount = lua_gettop(L); |
|
|
|
|
const upb_msg *msg = lupb_msg_check(L, 1); |
|
|
|
|
const upb_msglayout *layout; |
|
|
|
|
upb_arena *arena = lupb_arena_pushnew(L); |
|
|
|
|
static int lupb_textencode(lua_State *L) { |
|
|
|
|
upb_msg *msg = lupb_msg_check(L, 1); |
|
|
|
|
const upb_msgdef *m = lupb_msg_getmsgdef(L, 1); |
|
|
|
|
int options = lupb_getoptions(L, 2); |
|
|
|
|
char buf[1024]; |
|
|
|
|
size_t size; |
|
|
|
|
char *result; |
|
|
|
|
int options = 0; |
|
|
|
|
|
|
|
|
|
if (argcount > 1) { |
|
|
|
|
size_t len = lua_rawlen(L, 2); |
|
|
|
|
for (size_t i = 1; i <= len; i++) { |
|
|
|
|
lua_rawgeti(L, 2, i); |
|
|
|
|
options |= lupb_checkuint32(L, -1); |
|
|
|
|
lua_pop(L, 1); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
lua_getiuservalue(L, 1, LUPB_MSGDEF_INDEX); |
|
|
|
|
layout = upb_msgdef_layout(lupb_msgdef_check(L, -1)); |
|
|
|
|
lua_pop(L, 1); |
|
|
|
|
|
|
|
|
|
result = upb_encode_ex(msg, (const void*)layout, options, arena, &size); |
|
|
|
|
size = upb_text_encode(msg, m, NULL, options, buf, sizeof(buf)); |
|
|
|
|
|
|
|
|
|
if (!result) { |
|
|
|
|
lua_pushstring(L, "Error encoding protobuf."); |
|
|
|
|
return lua_error(L); |
|
|
|
|
if (size < sizeof(buf)) { |
|
|
|
|
lua_pushlstring(L, buf, size); |
|
|
|
|
} else { |
|
|
|
|
char *ptr = malloc(size + 1); |
|
|
|
|
upb_text_encode(msg, m, NULL, options, ptr, size + 1); |
|
|
|
|
lua_pushlstring(L, ptr, size); |
|
|
|
|
free(ptr); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
lua_pushlstring(L, result, size); |
|
|
|
|
|
|
|
|
|
return 1; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -1013,6 +1052,8 @@ static const struct luaL_Reg lupb_msg_toplevel_m[] = { |
|
|
|
|
{"Map", lupb_map_new}, |
|
|
|
|
{"decode", lupb_decode}, |
|
|
|
|
{"encode", lupb_encode}, |
|
|
|
|
{"json_decode", lupb_jsondecode}, |
|
|
|
|
{"json_encode", lupb_jsonencode}, |
|
|
|
|
{"text_encode", lupb_textencode}, |
|
|
|
|
{NULL, NULL} |
|
|
|
|
}; |
|
|
|
@ -1032,5 +1073,10 @@ void lupb_msg_registertypes(lua_State *L) { |
|
|
|
|
lupb_setfieldi(L, "ENCODE_DETERMINISTIC", UPB_ENCODE_DETERMINISTIC); |
|
|
|
|
lupb_setfieldi(L, "ENCODE_SKIPUNKNOWN", UPB_ENCODE_SKIPUNKNOWN); |
|
|
|
|
|
|
|
|
|
lupb_setfieldi(L, "JSONENC_EMITDEFAULTS", UPB_JSONENC_EMITDEFAULTS); |
|
|
|
|
lupb_setfieldi(L, "JSONENC_PROTONAMES", UPB_JSONENC_PROTONAMES); |
|
|
|
|
|
|
|
|
|
lupb_setfieldi(L, "JSONDEC_IGNOREUNKNOWN", UPB_JSONDEC_IGNOREUNKNOWN); |
|
|
|
|
|
|
|
|
|
lupb_cacheinit(L); |
|
|
|
|
} |
|
|
|
|