add oneof field for actually written fields

This commit is contained in:
Xavier Wang
2022-03-08 21:05:03 +08:00
parent d0021b570b
commit 9122a3aa72
3 changed files with 34 additions and 19 deletions
+6 -1
View File
@@ -1685,7 +1685,7 @@ static void lpb_usedechooks(lua_State *L, lpb_State *LS, const pb_Type *t) {
static void lpb_pushtypetable(lua_State *L, lpb_State *LS, const pb_Type *t) {
const pb_Field *f = NULL;
int mode = LS->default_mode;
lua_createtable(L, 0, t->field_count - t->oneof_count);
lua_createtable(L, 0, t->field_count - t->oneof_field + t->oneof_count*2);
switch (t->is_proto3 && mode == LPB_DEFDEF ? LPB_COPYDEF : mode) {
case LPB_COPYDEF:
while (pb_nextfield(t, &f))
@@ -1827,6 +1827,11 @@ static int lpbD_message(lpb_Env *e, const pb_Type *t) {
lpbD_repeated(e, f, tag);
else {
lua_pushstring(L, (const char*)f->name);
if (f->oneof_idx) {
lua_pushstring(L, (const char*)pb_oneofname(t, f->oneof_idx));
lua_pushvalue(L, -2);
lua_rawset(L, -4);
}
lpbD_field(e, f, tag);
lua_rawset(L, -3);
}
+4 -3
View File
@@ -338,6 +338,7 @@ struct pb_Type {
pb_Table field_names;
pb_Table oneof_index;
unsigned oneof_count; /* extra field count from oneof entries */
unsigned oneof_field; /* extra field in oneof declarations */
unsigned field_count : 28;
unsigned is_enum : 1;
unsigned is_map : 1;
@@ -1245,7 +1246,7 @@ PB_API void pb_deltype(pb_State *S, pb_Type *t) {
pb_freetable(&t->field_tags);
pb_freetable(&t->field_names);
pb_freetable(&t->oneof_index);
t->oneof_count = 0, t->field_count = 0;
t->oneof_field = 0, t->field_count = 0;
t->is_dead = 1;
/*pb_delname(S, t->name); */
/*pb_poolfree(&S->typepool, t); */
@@ -1630,7 +1631,7 @@ static int pbL_loadField(pb_State *S, pbL_FieldInfo *info, pb_Loader *L, pb_Type
pbCE(f = pb_newfield(S, t, pb_newname(S, info->name, NULL), info->number));
f->default_value = pb_newname(S, info->default_value, NULL);
f->type = ft;
if ((f->oneof_idx = info->oneof_index)) ++t->oneof_count;
if ((f->oneof_idx = info->oneof_index)) ++t->oneof_field;
f->type_id = info->type;
f->repeated = info->label == 3; /* repeated */
f->packed = info->packed >= 0 ? info->packed : L->is_proto3 && f->repeated;
@@ -1659,7 +1660,7 @@ static int pbL_loadType(pb_State *S, pbL_TypeInfo *info, pb_Loader *L) {
pbC(pbL_loadEnum(S, &info->enum_type[i], L));
for (i = 0, count = pbL_count(info->nested_type); i < count; ++i)
pbC(pbL_loadType(S, &info->nested_type[i], L));
t->oneof_count -= pbL_count(info->oneof_decl);
t->oneof_count = pbL_count(info->oneof_decl);
L->b.size = (unsigned)curr;
return PB_OK;
}
+24 -15
View File
@@ -11,6 +11,7 @@ local protoc = require "protoc"
local eq = lu.assertEquals
local table_eq = lu.assertItemsEquals
local fail = lu.assertErrorMsgContains
local is_true = lu.assertIsTrue
local types = 0
for _ in pb.types() do
@@ -543,6 +544,9 @@ function _G.test_packed()
fail("table expected at field 'packs', got boolean",
function() pb.encode("TestPacked", { packs = true }) end)
local data = {packs = {}}
check_msg(".TestPacked", data, {})
local hasEmpty
for _, name in pb.types() do
if name == "Empty" then
@@ -684,10 +688,10 @@ function _G.test_oneof()
}
} ]]
check_msg("TestOneof", {})
check_msg("TestOneof", { m1 = {} })
check_msg("TestOneof", { m2 = {} })
check_msg("TestOneof", { m3 = { value = 0 } })
check_msg("TestOneof", { m3 = { value = 10 } })
check_msg("TestOneof", { m1 = {}, body_oneof = "m1" })
check_msg("TestOneof", { m2 = {}, body_oneof = "m2" })
check_msg("TestOneof", { m3 = { value = 0 }, body_oneof = "m3" })
check_msg("TestOneof", { m3 = { value = 10 }, body_oneof = "m3" })
pb.clear "TestOneof"
check_load [[
@@ -702,12 +706,17 @@ function _G.test_oneof()
TestOneof msg = 1;
}
]]
check_msg("TestOneof", { foo = 0 })
check_msg("TestOneof", { bar = "" })
check_msg("TestOneof", { foo = 0, bar = "" })
check_msg("Outter", { msg = { foo = 0 }})
check_msg("Outter", { msg = { bar = "" }})
check_msg("Outter", { msg = { foo = 0, bar = "" }})
check_msg("TestOneof", { foo = 0, body = "foo" })
check_msg("TestOneof", { bar = "", body = "bar" })
local chunk = pb.encode("TestOneof", { foo = 0, bar = "" })
local data = pb.decode("TestOneof", chunk)
is_true(data.body == "foo" or data.body == "bar")
check_msg("Outter", { msg = { foo = 0, body = "foo" }})
check_msg("Outter", { msg = { bar = "", body = "bar" }})
local chunk = pb.encode("Outter", {msg = { foo = 0, bar = "" }})
local data = pb.decode("Outter", chunk)
is_true(data.msg.body == "foo" or data.msg.body == "bar")
pb.clear "TestOneof"
pb.clear "Outter"
@@ -720,12 +729,12 @@ function _G.test_oneof()
}
} ]]
check_msg("TestOneof", { name = "foo" })
check_msg("TestOneof", { value = 0 })
check_msg("TestOneof", { name = "foo", value = 0 })
check_msg("TestOneof", { name = "foo", test_oneof = "name" })
check_msg("TestOneof", { value = 0, test_oneof = "value" })
local chunk = pb.encode("TestOneof", { name = "foo", value = 0 })
local data = pb.decode("TestOneof", chunk)
is_true(data.test_oneof == "name" or data.test_oneof == "value")
local data = { name = "foo", value = 5 }
check_msg("TestOneof", data)
eq(pb.field("TestOneof", "name"), "name")
pb.clear("TestOneof", "name")
eq(pb.field("TestOneof", "name"), nil)