-- Unknown-field passthrough: a decoder that meets fields not in its schema -- must capture their raw bytes into result._unknown_fields and a subsequent -- encode must re-emit them verbatim. Mirrors Tarantool's built-in `protobuf` -- module convention. local t = require('luatest') local function hex(s) local out = {} for i = 1, #s do out[i] = string.format('%02x', s:byte(i)) end return table.concat(out) end local MODES = {'full', 'runtime'} -- Wire-tag for (field_id, wire_type). Single-byte for id <= 15; we always -- produce the multi-byte varint here for safety. local function tag_bytes(id, wt) local v = id * 8 + wt local out = {} while v >= 0x80 do out[#out + 1] = string.char(v % 0x80 + 0x80) v = math.floor(v / 0x80) end out[#out + 1] = string.char(v) return table.concat(out) end -- Construct one byte-slice per wire type, using field IDs not declared in -- examples/proto/hello.proto's Address (fields 1..4). These should all be -- treated as unknown by the Address decoder. local UNK_VARINT = tag_bytes(50, 0) .. '\x2a' -- value 42 local UNK_I32 = tag_bytes(51, 5) .. '\x01\x00\x00\x00' -- value 1 local UNK_I64 = tag_bytes(52, 1) .. '\x02\x00\x00\x00\x00\x00\x00\x00' local UNK_LEN = tag_bytes(53, 2) .. '\x03foo' -- 3-byte string local ALL_UNK = UNK_VARINT .. UNK_I32 .. UNK_I64 .. UNK_LEN for _, mode in ipairs(MODES) do local g = t.group('unknown.' .. mode) local hello = require(mode .. '.hello.hello_pb') g.test_no_unknown_means_field_absent = function() local dec = hello.Address_decode(hello.Address_encode({street = 'X'})) t.assert_equals(dec.street, 'X') t.assert_equals(dec._unknown_fields, nil, '_unknown_fields must be absent when input had only known fields') end g.test_varint_unknown_round_trips = function() local known = hello.Address_encode({street = 'X', zip = 7}) local mixed = known .. UNK_VARINT local dec = hello.Address_decode(mixed) t.assert_equals(dec.street, 'X') t.assert_equals(dec.zip, 7) t.assert_equals(hex(dec._unknown_fields), hex(UNK_VARINT)) end g.test_all_wire_types_captured_in_order = function() local known = hello.Address_encode({street = 'X'}) local mixed = known .. ALL_UNK local dec = hello.Address_decode(mixed) t.assert_equals(dec.street, 'X') t.assert_equals(hex(dec._unknown_fields), hex(ALL_UNK), 'all four wire types must be captured verbatim in source order') end g.test_unknowns_interleaved_with_knowns = function() -- Bytes ordering: unknown, known, unknown — capture must preserve the -- two unknown chunks in encounter order (the known field stays out). local known1 = hello.Address_encode({street = 'A'}) local known2 = hello.Address_encode({zip = 99}) local mixed = UNK_VARINT .. known1 .. UNK_I64 .. known2 local dec = hello.Address_decode(mixed) t.assert_equals(dec.street, 'A') t.assert_equals(dec.zip, 99) t.assert_equals(hex(dec._unknown_fields), hex(UNK_VARINT .. UNK_I64)) end g.test_re_encode_preserves_unknown_bytes = function() local mixed = hello.Address_encode({street = 'X'}) .. ALL_UNK local dec = hello.Address_decode(mixed) local re_enc = hello.Address_encode(dec) -- Knowns are re-encoded in field-declaration order; unknowns trail. local expected = hello.Address_encode({street = 'X'}) .. ALL_UNK t.assert_equals(hex(re_enc), hex(expected), 'unknown bytes must be re-emitted verbatim at the tail') end g.test_re_encode_decode_idempotent = function() local mixed = hello.Address_encode({street = 'X', zip = 1}) .. UNK_LEN local dec1 = hello.Address_decode(mixed) local dec2 = hello.Address_decode(hello.Address_encode(dec1)) t.assert_equals(dec2.street, 'X') t.assert_equals(dec2.zip, 1) t.assert_equals(hex(dec2._unknown_fields), hex(UNK_LEN)) end g.test_empty_unknown_string_treated_as_absent = function() -- User explicitly sets _unknown_fields = '' on encode; should be a no-op. local enc = hello.Address_encode({street = 'X', _unknown_fields = ''}) t.assert_equals(hex(enc), hex(hello.Address_encode({street = 'X'}))) end end -- --------------------------------------------------------------------------- -- Cross-mode parity: full and runtime must capture identical unknown bytes. -- --------------------------------------------------------------------------- local g_parity = t.group('unknown.parity') local hello_full = require('full.hello.hello_pb') local hello_runtime = require('runtime.hello.hello_pb') g_parity.test_capture_identical_across_modes = function() local mixed = hello_full.Address_encode({street = 'X'}) .. ALL_UNK local d1 = hello_full.Address_decode(mixed) local d2 = hello_runtime.Address_decode(mixed) t.assert_equals(hex(d1._unknown_fields), hex(d2._unknown_fields)) t.assert_equals(hex(d1._unknown_fields), hex(ALL_UNK)) end g_parity.test_reencode_identical_across_modes = function() local table_with_unknowns = { street = 'X', zip = 9, _unknown_fields = ALL_UNK, } t.assert_equals( hex(hello_full.Address_encode(table_with_unknowns)), hex(hello_runtime.Address_encode(table_with_unknowns))) end