From 8ef6873e0e14309a1715a252a650bab0ae1a33ef Mon Sep 17 00:00:00 2001 From: Josh Haberman Date: Sun, 20 Mar 2011 13:13:51 -0700 Subject: upb_stream: all callbacks registered ahead-of-time. This is a significant change to the upb_stream protocol, and should hopefully be the last significant change. All callbacks are now registered ahead-of-time instead of having delegated callbacks registered at runtime, which makes it much easier to aggressively optimize ahead-of-time (like with a JIT). Other impacts of this change: - You no longer need to have loaded descriptor.proto as a upb_def to load other descriptors! This means the special-case code we used for bootstrapping is no longer necessary, and we no longer need to link the descriptor for descriptor.proto into upb. - A client can now register any upb_value as what will be delivered to their value callback, not just a upb_fielddef*. This should allow for other clients to get more bang out of the streaming decoder. This change unfortunately causes a bit of a performance regression -- I think largely due to highly suboptimal code that GCC generates when structs are returned by value. See: http://blog.reverberate.org/2011/03/19/when-a-compilers-slow-code-actually-bites-you/ On the other hand, once we have a JIT this should no longer matter. Performance numbers: plain.parsestream_googlemessage1.upb_table: 374 -> 396 (5.88) plain.parsestream_googlemessage2.upb_table: 616 -> 449 (-27.11) plain.parsetostruct_googlemessage1.upb_table_byref: 268 -> 269 (0.37) plain.parsetostruct_googlemessage1.upb_table_byval: 215 -> 204 (-5.12) plain.parsetostruct_googlemessage2.upb_table_byref: 307 -> 281 (-8.47) plain.parsetostruct_googlemessage2.upb_table_byval: 297 -> 272 (-8.42) omitfp.parsestream_googlemessage1.upb_table: 423 -> 410 (-3.07) omitfp.parsestream_googlemessage2.upb_table: 679 -> 483 (-28.87) omitfp.parsetostruct_googlemessage1.upb_table_byref: 287 -> 282 (-1.74) omitfp.parsetostruct_googlemessage1.upb_table_byval: 226 -> 219 (-3.10) omitfp.parsetostruct_googlemessage2.upb_table_byref: 315 -> 298 (-5.40) omitfp.parsetostruct_googlemessage2.upb_table_byval: 297 -> 287 (-3.37) --- src/descriptor.c | 331 ----------------------- src/descriptor_const.h | 438 ++++++++++++++++++++---------- src/upb.c | 8 +- src/upb.h | 19 +- src/upb_decoder.c | 156 +++++------ src/upb_decoder.h | 38 +-- src/upb_decoder_x64.asm | 10 +- src/upb_def.c | 705 ++++++++++++++++-------------------------------- src/upb_def.h | 54 ++-- src/upb_encoder.h | 2 +- src/upb_glue.c | 43 ++- src/upb_msg.c | 122 +++------ src/upb_msg.h | 31 +-- src/upb_stdio.c | 1 - src/upb_stream.c | 328 ++++++++++++++++++++++ src/upb_stream.h | 508 +++++++++++++++++++++++----------- src/upb_stream_vtbl.h | 303 --------------------- src/upb_strstream.c | 2 - src/upb_table.c | 1 - src/upb_textprinter.c | 38 +-- src/upb_textprinter.h | 6 +- 21 files changed, 1418 insertions(+), 1726 deletions(-) delete mode 100644 src/descriptor.c create mode 100644 src/upb_stream.c delete mode 100644 src/upb_stream_vtbl.h (limited to 'src') diff --git a/src/descriptor.c b/src/descriptor.c deleted file mode 100644 index 9f30183..0000000 --- a/src/descriptor.c +++ /dev/null @@ -1,331 +0,0 @@ -unsigned char descriptor_pb[] = { - 0x0a, 0xd8, 0x1e, 0x0a, 0x14, 0x73, 0x72, 0x63, 0x2f, 0x64, 0x65, 0x73, - 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x12, 0x0f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x22, 0x47, 0x0a, 0x11, 0x46, 0x69, - 0x6c, 0x65, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, - 0x53, 0x65, 0x74, 0x12, 0x32, 0x0a, 0x04, 0x66, 0x69, 0x6c, 0x65, 0x18, - 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, - 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, - 0x46, 0x69, 0x6c, 0x65, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, - 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x97, 0x03, 0x0a, 0x13, - 0x46, 0x69, 0x6c, 0x65, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, - 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0c, 0x0a, 0x04, 0x6e, - 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x12, 0x0f, 0x0a, - 0x07, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x09, 0x12, 0x12, 0x0a, 0x0a, 0x64, 0x65, 0x70, 0x65, 0x6e, 0x64, - 0x65, 0x6e, 0x63, 0x79, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x12, 0x36, - 0x0a, 0x0c, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x74, 0x79, - 0x70, 0x65, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x67, - 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, - 0x75, 0x66, 0x2e, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, - 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x37, 0x0a, 0x09, 0x65, 0x6e, - 0x75, 0x6d, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x05, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6e, 0x75, 0x6d, - 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, - 0x6f, 0x74, 0x6f, 0x12, 0x38, 0x0a, 0x07, 0x73, 0x65, 0x72, 0x76, 0x69, - 0x63, 0x65, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x67, - 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, - 0x75, 0x66, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x44, 0x65, - 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, - 0x6f, 0x12, 0x38, 0x0a, 0x09, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, - 0x6f, 0x6e, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x67, - 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, - 0x75, 0x66, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x44, 0x65, 0x73, 0x63, - 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x12, - 0x2d, 0x0a, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x08, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, - 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, - 0x69, 0x6c, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x39, - 0x0a, 0x10, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x63, 0x6f, 0x64, - 0x65, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x1f, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x43, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x22, 0xa9, 0x03, - 0x0a, 0x0f, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, - 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0c, 0x0a, 0x04, 0x6e, 0x61, 0x6d, - 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x12, 0x34, 0x0a, 0x05, 0x66, - 0x69, 0x65, 0x6c, 0x64, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x25, - 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x44, 0x65, - 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, - 0x6f, 0x12, 0x38, 0x0a, 0x09, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, - 0x6f, 0x6e, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x67, - 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, - 0x75, 0x66, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x44, 0x65, 0x73, 0x63, - 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x12, - 0x35, 0x0a, 0x0b, 0x6e, 0x65, 0x73, 0x74, 0x65, 0x64, 0x5f, 0x74, 0x79, - 0x70, 0x65, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x67, - 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, - 0x75, 0x66, 0x2e, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, - 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x37, 0x0a, 0x09, 0x65, 0x6e, - 0x75, 0x6d, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x04, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6e, 0x75, 0x6d, - 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, - 0x6f, 0x74, 0x6f, 0x12, 0x48, 0x0a, 0x0f, 0x65, 0x78, 0x74, 0x65, 0x6e, - 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x05, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, - 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, - 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, - 0x74, 0x6f, 0x2e, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, - 0x52, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x30, 0x0a, 0x07, 0x6f, 0x70, 0x74, - 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, - 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, - 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x1a, 0x2c, 0x0a, 0x0e, 0x45, - 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x61, 0x6e, 0x67, - 0x65, 0x12, 0x0d, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x05, 0x12, 0x0b, 0x0a, 0x03, 0x65, 0x6e, 0x64, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x05, 0x22, 0x94, 0x05, 0x0a, 0x14, 0x46, 0x69, - 0x65, 0x6c, 0x64, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, - 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0c, 0x0a, 0x04, 0x6e, 0x61, - 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x12, 0x0e, 0x0a, 0x06, - 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, - 0x12, 0x3a, 0x0a, 0x05, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x18, 0x04, 0x20, - 0x01, 0x28, 0x0e, 0x32, 0x2b, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, - 0x65, 0x6c, 0x64, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, - 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x4c, 0x61, 0x62, 0x65, 0x6c, - 0x12, 0x38, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x05, 0x20, 0x01, - 0x28, 0x0e, 0x32, 0x2a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x65, - 0x6c, 0x64, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, - 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x12, 0x11, - 0x0a, 0x09, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, - 0x06, 0x20, 0x01, 0x28, 0x09, 0x12, 0x10, 0x0a, 0x08, 0x65, 0x78, 0x74, - 0x65, 0x6e, 0x64, 0x65, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x12, - 0x15, 0x0a, 0x0d, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x76, - 0x61, 0x6c, 0x75, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x12, 0x2e, - 0x0a, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x08, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, - 0x65, 0x6c, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0xb6, - 0x02, 0x0a, 0x04, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0f, 0x0a, 0x0b, 0x54, - 0x59, 0x50, 0x45, 0x5f, 0x44, 0x4f, 0x55, 0x42, 0x4c, 0x45, 0x10, 0x01, - 0x12, 0x0e, 0x0a, 0x0a, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x46, 0x4c, 0x4f, - 0x41, 0x54, 0x10, 0x02, 0x12, 0x0e, 0x0a, 0x0a, 0x54, 0x59, 0x50, 0x45, - 0x5f, 0x49, 0x4e, 0x54, 0x36, 0x34, 0x10, 0x03, 0x12, 0x0f, 0x0a, 0x0b, - 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x49, 0x4e, 0x54, 0x36, 0x34, 0x10, - 0x04, 0x12, 0x0e, 0x0a, 0x0a, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x49, 0x4e, - 0x54, 0x33, 0x32, 0x10, 0x05, 0x12, 0x10, 0x0a, 0x0c, 0x54, 0x59, 0x50, - 0x45, 0x5f, 0x46, 0x49, 0x58, 0x45, 0x44, 0x36, 0x34, 0x10, 0x06, 0x12, - 0x10, 0x0a, 0x0c, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x46, 0x49, 0x58, 0x45, - 0x44, 0x33, 0x32, 0x10, 0x07, 0x12, 0x0d, 0x0a, 0x09, 0x54, 0x59, 0x50, - 0x45, 0x5f, 0x42, 0x4f, 0x4f, 0x4c, 0x10, 0x08, 0x12, 0x0f, 0x0a, 0x0b, - 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x54, 0x52, 0x49, 0x4e, 0x47, 0x10, - 0x09, 0x12, 0x0e, 0x0a, 0x0a, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x47, 0x52, - 0x4f, 0x55, 0x50, 0x10, 0x0a, 0x12, 0x10, 0x0a, 0x0c, 0x54, 0x59, 0x50, - 0x45, 0x5f, 0x4d, 0x45, 0x53, 0x53, 0x41, 0x47, 0x45, 0x10, 0x0b, 0x12, - 0x0e, 0x0a, 0x0a, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x42, 0x59, 0x54, 0x45, - 0x53, 0x10, 0x0c, 0x12, 0x0f, 0x0a, 0x0b, 0x54, 0x59, 0x50, 0x45, 0x5f, - 0x55, 0x49, 0x4e, 0x54, 0x33, 0x32, 0x10, 0x0d, 0x12, 0x0d, 0x0a, 0x09, - 0x54, 0x59, 0x50, 0x45, 0x5f, 0x45, 0x4e, 0x55, 0x4d, 0x10, 0x0e, 0x12, - 0x11, 0x0a, 0x0d, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x46, 0x49, 0x58, - 0x45, 0x44, 0x33, 0x32, 0x10, 0x0f, 0x12, 0x11, 0x0a, 0x0d, 0x54, 0x59, - 0x50, 0x45, 0x5f, 0x53, 0x46, 0x49, 0x58, 0x45, 0x44, 0x36, 0x34, 0x10, - 0x10, 0x12, 0x0f, 0x0a, 0x0b, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x49, - 0x4e, 0x54, 0x33, 0x32, 0x10, 0x11, 0x12, 0x0f, 0x0a, 0x0b, 0x54, 0x59, - 0x50, 0x45, 0x5f, 0x53, 0x49, 0x4e, 0x54, 0x36, 0x34, 0x10, 0x12, 0x22, - 0x43, 0x0a, 0x05, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x12, 0x12, 0x0a, 0x0e, - 0x4c, 0x41, 0x42, 0x45, 0x4c, 0x5f, 0x4f, 0x50, 0x54, 0x49, 0x4f, 0x4e, - 0x41, 0x4c, 0x10, 0x01, 0x12, 0x12, 0x0a, 0x0e, 0x4c, 0x41, 0x42, 0x45, - 0x4c, 0x5f, 0x52, 0x45, 0x51, 0x55, 0x49, 0x52, 0x45, 0x44, 0x10, 0x02, - 0x12, 0x12, 0x0a, 0x0e, 0x4c, 0x41, 0x42, 0x45, 0x4c, 0x5f, 0x52, 0x45, - 0x50, 0x45, 0x41, 0x54, 0x45, 0x44, 0x10, 0x03, 0x22, 0x8c, 0x01, 0x0a, - 0x13, 0x45, 0x6e, 0x75, 0x6d, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, - 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0c, 0x0a, 0x04, - 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x12, 0x38, - 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x29, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6e, 0x75, 0x6d, - 0x56, 0x61, 0x6c, 0x75, 0x65, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, - 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x2d, 0x0a, 0x07, - 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6e, 0x75, 0x6d, - 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x6c, 0x0a, 0x18, 0x45, - 0x6e, 0x75, 0x6d, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x44, 0x65, 0x73, 0x63, - 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x12, - 0x0c, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x12, 0x0e, 0x0a, 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x05, 0x12, 0x32, 0x0a, 0x07, 0x6f, 0x70, 0x74, - 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, - 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6e, 0x75, 0x6d, 0x56, 0x61, 0x6c, - 0x75, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x90, 0x01, - 0x0a, 0x16, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x44, 0x65, 0x73, - 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, - 0x12, 0x0c, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x12, 0x36, 0x0a, 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, - 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x67, 0x6f, 0x6f, - 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, - 0x2e, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x44, 0x65, 0x73, 0x63, 0x72, - 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x30, - 0x0a, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x65, - 0x72, 0x76, 0x69, 0x63, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, - 0x22, 0x7f, 0x0a, 0x15, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x44, 0x65, - 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, - 0x6f, 0x12, 0x0c, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x12, 0x12, 0x0a, 0x0a, 0x69, 0x6e, 0x70, 0x75, 0x74, - 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x12, - 0x13, 0x0a, 0x0b, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x5f, 0x74, 0x79, - 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x12, 0x2f, 0x0a, 0x07, - 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x1e, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x4d, 0x65, 0x74, 0x68, - 0x6f, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0xd5, 0x03, - 0x0a, 0x0b, 0x46, 0x69, 0x6c, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, - 0x73, 0x12, 0x14, 0x0a, 0x0c, 0x6a, 0x61, 0x76, 0x61, 0x5f, 0x70, 0x61, - 0x63, 0x6b, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x12, - 0x1c, 0x0a, 0x14, 0x6a, 0x61, 0x76, 0x61, 0x5f, 0x6f, 0x75, 0x74, 0x65, - 0x72, 0x5f, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x6e, 0x61, 0x6d, 0x65, 0x18, - 0x08, 0x20, 0x01, 0x28, 0x09, 0x12, 0x22, 0x0a, 0x13, 0x6a, 0x61, 0x76, - 0x61, 0x5f, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x5f, 0x66, - 0x69, 0x6c, 0x65, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, - 0x66, 0x61, 0x6c, 0x73, 0x65, 0x12, 0x2c, 0x0a, 0x1d, 0x6a, 0x61, 0x76, - 0x61, 0x5f, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x5f, 0x65, - 0x71, 0x75, 0x61, 0x6c, 0x73, 0x5f, 0x61, 0x6e, 0x64, 0x5f, 0x68, 0x61, - 0x73, 0x68, 0x18, 0x14, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, - 0x6c, 0x73, 0x65, 0x12, 0x46, 0x0a, 0x0c, 0x6f, 0x70, 0x74, 0x69, 0x6d, - 0x69, 0x7a, 0x65, 0x5f, 0x66, 0x6f, 0x72, 0x18, 0x09, 0x20, 0x01, 0x28, - 0x0e, 0x32, 0x29, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x6c, 0x65, - 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x4f, 0x70, 0x74, 0x69, - 0x6d, 0x69, 0x7a, 0x65, 0x4d, 0x6f, 0x64, 0x65, 0x3a, 0x05, 0x53, 0x50, - 0x45, 0x45, 0x44, 0x12, 0x22, 0x0a, 0x13, 0x63, 0x63, 0x5f, 0x67, 0x65, - 0x6e, 0x65, 0x72, 0x69, 0x63, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, - 0x65, 0x73, 0x18, 0x10, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, - 0x6c, 0x73, 0x65, 0x12, 0x24, 0x0a, 0x15, 0x6a, 0x61, 0x76, 0x61, 0x5f, - 0x67, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x5f, 0x73, 0x65, 0x72, 0x76, - 0x69, 0x63, 0x65, 0x73, 0x18, 0x11, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, - 0x66, 0x61, 0x6c, 0x73, 0x65, 0x12, 0x22, 0x0a, 0x13, 0x70, 0x79, 0x5f, - 0x67, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x5f, 0x73, 0x65, 0x72, 0x76, - 0x69, 0x63, 0x65, 0x73, 0x18, 0x12, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, - 0x66, 0x61, 0x6c, 0x73, 0x65, 0x12, 0x43, 0x0a, 0x14, 0x75, 0x6e, 0x69, - 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x5f, 0x6f, - 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0xe7, 0x07, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x6e, 0x69, 0x6e, 0x74, - 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, - 0x6f, 0x6e, 0x22, 0x3a, 0x0a, 0x0c, 0x4f, 0x70, 0x74, 0x69, 0x6d, 0x69, - 0x7a, 0x65, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x09, 0x0a, 0x05, 0x53, 0x50, - 0x45, 0x45, 0x44, 0x10, 0x01, 0x12, 0x0d, 0x0a, 0x09, 0x43, 0x4f, 0x44, - 0x45, 0x5f, 0x53, 0x49, 0x5a, 0x45, 0x10, 0x02, 0x12, 0x10, 0x0a, 0x0c, - 0x4c, 0x49, 0x54, 0x45, 0x5f, 0x52, 0x55, 0x4e, 0x54, 0x49, 0x4d, 0x45, - 0x10, 0x03, 0x2a, 0x09, 0x08, 0xe8, 0x07, 0x10, 0x80, 0x80, 0x80, 0x80, - 0x02, 0x22, 0xb8, 0x01, 0x0a, 0x0e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, - 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x26, 0x0a, 0x17, - 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x73, 0x65, 0x74, 0x5f, - 0x77, 0x69, 0x72, 0x65, 0x5f, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, - 0x12, 0x2e, 0x0a, 0x1f, 0x6e, 0x6f, 0x5f, 0x73, 0x74, 0x61, 0x6e, 0x64, - 0x61, 0x72, 0x64, 0x5f, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, - 0x6f, 0x72, 0x5f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x6f, 0x72, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, - 0x12, 0x43, 0x0a, 0x14, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, - 0x72, 0x65, 0x74, 0x65, 0x64, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, - 0x18, 0xe7, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, - 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, - 0x66, 0x2e, 0x55, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, - 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x2a, 0x09, 0x08, - 0xe8, 0x07, 0x10, 0x80, 0x80, 0x80, 0x80, 0x02, 0x22, 0x94, 0x02, 0x0a, - 0x0c, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, - 0x73, 0x12, 0x3a, 0x0a, 0x05, 0x63, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0e, 0x32, 0x23, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, - 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, - 0x69, 0x65, 0x6c, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, - 0x43, 0x54, 0x79, 0x70, 0x65, 0x3a, 0x06, 0x53, 0x54, 0x52, 0x49, 0x4e, - 0x47, 0x12, 0x0e, 0x0a, 0x06, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x64, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x08, 0x12, 0x19, 0x0a, 0x0a, 0x64, 0x65, 0x70, - 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x12, 0x1c, 0x0a, 0x14, - 0x65, 0x78, 0x70, 0x65, 0x72, 0x69, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x6c, - 0x5f, 0x6d, 0x61, 0x70, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x09, 0x20, 0x01, - 0x28, 0x09, 0x12, 0x43, 0x0a, 0x14, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, - 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x5f, 0x6f, 0x70, 0x74, 0x69, - 0x6f, 0x6e, 0x18, 0xe7, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, - 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x62, 0x75, 0x66, 0x2e, 0x55, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, - 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x22, - 0x2f, 0x0a, 0x05, 0x43, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0a, 0x0a, 0x06, - 0x53, 0x54, 0x52, 0x49, 0x4e, 0x47, 0x10, 0x00, 0x12, 0x08, 0x0a, 0x04, - 0x43, 0x4f, 0x52, 0x44, 0x10, 0x01, 0x12, 0x10, 0x0a, 0x0c, 0x53, 0x54, - 0x52, 0x49, 0x4e, 0x47, 0x5f, 0x50, 0x49, 0x45, 0x43, 0x45, 0x10, 0x02, - 0x2a, 0x09, 0x08, 0xe8, 0x07, 0x10, 0x80, 0x80, 0x80, 0x80, 0x02, 0x22, - 0x5d, 0x0a, 0x0b, 0x45, 0x6e, 0x75, 0x6d, 0x4f, 0x70, 0x74, 0x69, 0x6f, - 0x6e, 0x73, 0x12, 0x43, 0x0a, 0x14, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, - 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x5f, 0x6f, 0x70, 0x74, 0x69, - 0x6f, 0x6e, 0x18, 0xe7, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, - 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x62, 0x75, 0x66, 0x2e, 0x55, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, - 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x2a, - 0x09, 0x08, 0xe8, 0x07, 0x10, 0x80, 0x80, 0x80, 0x80, 0x02, 0x22, 0x62, - 0x0a, 0x10, 0x45, 0x6e, 0x75, 0x6d, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x4f, - 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x43, 0x0a, 0x14, 0x75, 0x6e, - 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x5f, - 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0xe7, 0x07, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x6e, 0x69, 0x6e, - 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, - 0x69, 0x6f, 0x6e, 0x2a, 0x09, 0x08, 0xe8, 0x07, 0x10, 0x80, 0x80, 0x80, - 0x80, 0x02, 0x22, 0x60, 0x0a, 0x0e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, - 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x43, 0x0a, 0x14, - 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, - 0x64, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0xe7, 0x07, 0x20, - 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x6e, - 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, - 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x2a, 0x09, 0x08, 0xe8, 0x07, 0x10, 0x80, - 0x80, 0x80, 0x80, 0x02, 0x22, 0x5f, 0x0a, 0x0d, 0x4d, 0x65, 0x74, 0x68, - 0x6f, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x43, 0x0a, - 0x14, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, - 0x65, 0x64, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0xe7, 0x07, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, - 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, - 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, - 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x2a, 0x09, 0x08, 0xe8, 0x07, 0x10, - 0x80, 0x80, 0x80, 0x80, 0x02, 0x22, 0x9e, 0x02, 0x0a, 0x13, 0x55, 0x6e, - 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, - 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x3b, 0x0a, 0x04, 0x6e, 0x61, 0x6d, - 0x65, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x67, 0x6f, - 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, - 0x66, 0x2e, 0x55, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, - 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x4e, 0x61, - 0x6d, 0x65, 0x50, 0x61, 0x72, 0x74, 0x12, 0x18, 0x0a, 0x10, 0x69, 0x64, - 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x5f, 0x76, 0x61, 0x6c, - 0x75, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x12, 0x1a, 0x0a, 0x12, - 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x69, 0x6e, 0x74, - 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, - 0x12, 0x1a, 0x0a, 0x12, 0x6e, 0x65, 0x67, 0x61, 0x74, 0x69, 0x76, 0x65, - 0x5f, 0x69, 0x6e, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x05, - 0x20, 0x01, 0x28, 0x03, 0x12, 0x14, 0x0a, 0x0c, 0x64, 0x6f, 0x75, 0x62, - 0x6c, 0x65, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x06, 0x20, 0x01, - 0x28, 0x01, 0x12, 0x14, 0x0a, 0x0c, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, - 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0c, - 0x12, 0x17, 0x0a, 0x0f, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, - 0x65, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, - 0x09, 0x1a, 0x33, 0x0a, 0x08, 0x4e, 0x61, 0x6d, 0x65, 0x50, 0x61, 0x72, - 0x74, 0x12, 0x11, 0x0a, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x70, 0x61, - 0x72, 0x74, 0x18, 0x01, 0x20, 0x02, 0x28, 0x09, 0x12, 0x14, 0x0a, 0x0c, - 0x69, 0x73, 0x5f, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, - 0x18, 0x02, 0x20, 0x02, 0x28, 0x08, 0x22, 0x7c, 0x0a, 0x0e, 0x53, 0x6f, - 0x75, 0x72, 0x63, 0x65, 0x43, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, - 0x12, 0x3a, 0x0a, 0x08, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x67, 0x6f, 0x6f, - 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, - 0x2e, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x6f, 0x64, 0x65, 0x49, - 0x6e, 0x66, 0x6f, 0x2e, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x1a, 0x2e, 0x0a, 0x08, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x12, 0x10, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x03, - 0x28, 0x05, 0x42, 0x02, 0x10, 0x01, 0x12, 0x10, 0x0a, 0x04, 0x73, 0x70, - 0x61, 0x6e, 0x18, 0x02, 0x20, 0x03, 0x28, 0x05, 0x42, 0x02, 0x10, 0x01, - 0x42, 0x29, 0x0a, 0x13, 0x63, 0x6f, 0x6d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, - 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x42, - 0x10, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, - 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x48, 0x01 -}; -unsigned int descriptor_pb_len = 3931; diff --git a/src/descriptor_const.h b/src/descriptor_const.h index f02eb75..228c95a 100644 --- a/src/descriptor_const.h +++ b/src/descriptor_const.h @@ -50,152 +50,298 @@ typedef enum google_protobuf_FileOptions_OptimizeMode { /* Constants for field names and numbers. */ -#define GOOGLE_PROTOBUF_FILEDESCRIPTORSET_FILE_FIELDNUM 1 -#define GOOGLE_PROTOBUF_FILEDESCRIPTORSET_FILE_FIELDNAME "file" -#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_NAME_FIELDNUM 1 -#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_NAME_FIELDNAME "name" -#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_FIELD_FIELDNUM 2 -#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_FIELD_FIELDNAME "field" -#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_NESTED_TYPE_FIELDNUM 3 -#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_NESTED_TYPE_FIELDNAME "nested_type" -#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_ENUM_TYPE_FIELDNUM 4 -#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_ENUM_TYPE_FIELDNAME "enum_type" -#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSION_RANGE_FIELDNUM 5 -#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSION_RANGE_FIELDNAME "extension_range" -#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSION_FIELDNUM 6 -#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSION_FIELDNAME "extension" -#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_OPTIONS_FIELDNUM 7 -#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_OPTIONS_FIELDNAME "options" -#define GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_PATH_FIELDNUM 1 -#define GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_PATH_FIELDNAME "path" -#define GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_SPAN_FIELDNUM 2 -#define GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_SPAN_FIELDNAME "span" -#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NAME_FIELDNUM 2 -#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NAME_FIELDNAME "name" -#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_IDENTIFIER_VALUE_FIELDNUM 3 -#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_IDENTIFIER_VALUE_FIELDNAME "identifier_value" -#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_POSITIVE_INT_VALUE_FIELDNUM 4 -#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_POSITIVE_INT_VALUE_FIELDNAME "positive_int_value" -#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NEGATIVE_INT_VALUE_FIELDNUM 5 -#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NEGATIVE_INT_VALUE_FIELDNAME "negative_int_value" -#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_DOUBLE_VALUE_FIELDNUM 6 -#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_DOUBLE_VALUE_FIELDNAME "double_value" -#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_STRING_VALUE_FIELDNUM 7 -#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_STRING_VALUE_FIELDNAME "string_value" -#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_AGGREGATE_VALUE_FIELDNUM 8 -#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_AGGREGATE_VALUE_FIELDNAME "aggregate_value" -#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_NAME_FIELDNUM 1 -#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_NAME_FIELDNAME "name" -#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_PACKAGE_FIELDNUM 2 -#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_PACKAGE_FIELDNAME "package" -#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_DEPENDENCY_FIELDNUM 3 -#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_DEPENDENCY_FIELDNAME "dependency" -#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_MESSAGE_TYPE_FIELDNUM 4 -#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_MESSAGE_TYPE_FIELDNAME "message_type" -#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_ENUM_TYPE_FIELDNUM 5 -#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_ENUM_TYPE_FIELDNAME "enum_type" -#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_SERVICE_FIELDNUM 6 -#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_SERVICE_FIELDNAME "service" -#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_EXTENSION_FIELDNUM 7 -#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_EXTENSION_FIELDNAME "extension" -#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_OPTIONS_FIELDNUM 8 -#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_OPTIONS_FIELDNAME "options" -#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_SOURCE_CODE_INFO_FIELDNUM 9 -#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_SOURCE_CODE_INFO_FIELDNAME "source_code_info" -#define GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_NAME_FIELDNUM 1 -#define GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_NAME_FIELDNAME "name" -#define GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_INPUT_TYPE_FIELDNUM 2 -#define GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_INPUT_TYPE_FIELDNAME "input_type" -#define GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_OUTPUT_TYPE_FIELDNUM 3 -#define GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_OUTPUT_TYPE_FIELDNAME "output_type" -#define GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_OPTIONS_FIELDNUM 4 -#define GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_OPTIONS_FIELDNAME "options" -#define GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_NAME_FIELDNUM 1 -#define GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_NAME_FIELDNAME "name" -#define GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_VALUE_FIELDNUM 2 -#define GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_VALUE_FIELDNAME "value" -#define GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_OPTIONS_FIELDNUM 3 -#define GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_OPTIONS_FIELDNAME "options" -#define GOOGLE_PROTOBUF_ENUMVALUEOPTIONS_UNINTERPRETED_OPTION_FIELDNUM 999 -#define GOOGLE_PROTOBUF_ENUMVALUEOPTIONS_UNINTERPRETED_OPTION_FIELDNAME "uninterpreted_option" -#define GOOGLE_PROTOBUF_ENUMVALUEDESCRIPTORPROTO_NAME_FIELDNUM 1 -#define GOOGLE_PROTOBUF_ENUMVALUEDESCRIPTORPROTO_NAME_FIELDNAME "name" -#define GOOGLE_PROTOBUF_ENUMVALUEDESCRIPTORPROTO_NUMBER_FIELDNUM 2 -#define GOOGLE_PROTOBUF_ENUMVALUEDESCRIPTORPROTO_NUMBER_FIELDNAME "number" -#define GOOGLE_PROTOBUF_ENUMVALUEDESCRIPTORPROTO_OPTIONS_FIELDNUM 3 -#define GOOGLE_PROTOBUF_ENUMVALUEDESCRIPTORPROTO_OPTIONS_FIELDNAME "options" -#define GOOGLE_PROTOBUF_SERVICEDESCRIPTORPROTO_NAME_FIELDNUM 1 -#define GOOGLE_PROTOBUF_SERVICEDESCRIPTORPROTO_NAME_FIELDNAME "name" -#define GOOGLE_PROTOBUF_SERVICEDESCRIPTORPROTO_METHOD_FIELDNUM 2 -#define GOOGLE_PROTOBUF_SERVICEDESCRIPTORPROTO_METHOD_FIELDNAME "method" -#define GOOGLE_PROTOBUF_SERVICEDESCRIPTORPROTO_OPTIONS_FIELDNUM 3 -#define GOOGLE_PROTOBUF_SERVICEDESCRIPTORPROTO_OPTIONS_FIELDNAME "options" -#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NAMEPART_NAME_PART_FIELDNUM 1 -#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NAMEPART_NAME_PART_FIELDNAME "name_part" -#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NAMEPART_IS_EXTENSION_FIELDNUM 2 -#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NAMEPART_IS_EXTENSION_FIELDNAME "is_extension" -#define GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_FIELDNUM 1 -#define GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_FIELDNAME "location" -#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSIONRANGE_START_FIELDNUM 1 -#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSIONRANGE_START_FIELDNAME "start" -#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSIONRANGE_END_FIELDNUM 2 -#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSIONRANGE_END_FIELDNAME "end" -#define GOOGLE_PROTOBUF_FIELDOPTIONS_CTYPE_FIELDNUM 1 -#define GOOGLE_PROTOBUF_FIELDOPTIONS_CTYPE_FIELDNAME "ctype" -#define GOOGLE_PROTOBUF_FIELDOPTIONS_PACKED_FIELDNUM 2 -#define GOOGLE_PROTOBUF_FIELDOPTIONS_PACKED_FIELDNAME "packed" -#define GOOGLE_PROTOBUF_FIELDOPTIONS_DEPRECATED_FIELDNUM 3 -#define GOOGLE_PROTOBUF_FIELDOPTIONS_DEPRECATED_FIELDNAME "deprecated" -#define GOOGLE_PROTOBUF_FIELDOPTIONS_EXPERIMENTAL_MAP_KEY_FIELDNUM 9 -#define GOOGLE_PROTOBUF_FIELDOPTIONS_EXPERIMENTAL_MAP_KEY_FIELDNAME "experimental_map_key" -#define GOOGLE_PROTOBUF_FIELDOPTIONS_UNINTERPRETED_OPTION_FIELDNUM 999 -#define GOOGLE_PROTOBUF_FIELDOPTIONS_UNINTERPRETED_OPTION_FIELDNAME "uninterpreted_option" -#define GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_PACKAGE_FIELDNUM 1 -#define GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_PACKAGE_FIELDNAME "java_package" -#define GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_OUTER_CLASSNAME_FIELDNUM 8 -#define GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_OUTER_CLASSNAME_FIELDNAME "java_outer_classname" -#define GOOGLE_PROTOBUF_FILEOPTIONS_OPTIMIZE_FOR_FIELDNUM 9 -#define GOOGLE_PROTOBUF_FILEOPTIONS_OPTIMIZE_FOR_FIELDNAME "optimize_for" -#define GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_MULTIPLE_FILES_FIELDNUM 10 -#define GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_MULTIPLE_FILES_FIELDNAME "java_multiple_files" -#define GOOGLE_PROTOBUF_FILEOPTIONS_CC_GENERIC_SERVICES_FIELDNUM 16 -#define GOOGLE_PROTOBUF_FILEOPTIONS_CC_GENERIC_SERVICES_FIELDNAME "cc_generic_services" -#define GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_GENERIC_SERVICES_FIELDNUM 17 -#define GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_GENERIC_SERVICES_FIELDNAME "java_generic_services" -#define GOOGLE_PROTOBUF_FILEOPTIONS_PY_GENERIC_SERVICES_FIELDNUM 18 -#define GOOGLE_PROTOBUF_FILEOPTIONS_PY_GENERIC_SERVICES_FIELDNAME "py_generic_services" -#define GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_GENERATE_EQUALS_AND_HASH_FIELDNUM 20 -#define GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_GENERATE_EQUALS_AND_HASH_FIELDNAME "java_generate_equals_and_hash" -#define GOOGLE_PROTOBUF_FILEOPTIONS_UNINTERPRETED_OPTION_FIELDNUM 999 -#define GOOGLE_PROTOBUF_FILEOPTIONS_UNINTERPRETED_OPTION_FIELDNAME "uninterpreted_option" -#define GOOGLE_PROTOBUF_MESSAGEOPTIONS_MESSAGE_SET_WIRE_FORMAT_FIELDNUM 1 -#define GOOGLE_PROTOBUF_MESSAGEOPTIONS_MESSAGE_SET_WIRE_FORMAT_FIELDNAME "message_set_wire_format" -#define GOOGLE_PROTOBUF_MESSAGEOPTIONS_NO_STANDARD_DESCRIPTOR_ACCESSOR_FIELDNUM 2 -#define GOOGLE_PROTOBUF_MESSAGEOPTIONS_NO_STANDARD_DESCRIPTOR_ACCESSOR_FIELDNAME "no_standard_descriptor_accessor" -#define GOOGLE_PROTOBUF_MESSAGEOPTIONS_UNINTERPRETED_OPTION_FIELDNUM 999 -#define GOOGLE_PROTOBUF_MESSAGEOPTIONS_UNINTERPRETED_OPTION_FIELDNAME "uninterpreted_option" -#define GOOGLE_PROTOBUF_ENUMOPTIONS_UNINTERPRETED_OPTION_FIELDNUM 999 -#define GOOGLE_PROTOBUF_ENUMOPTIONS_UNINTERPRETED_OPTION_FIELDNAME "uninterpreted_option" -#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_NAME_FIELDNUM 1 -#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_NAME_FIELDNAME "name" -#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_EXTENDEE_FIELDNUM 2 -#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_EXTENDEE_FIELDNAME "extendee" -#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_NUMBER_FIELDNUM 3 -#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_NUMBER_FIELDNAME "number" -#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_LABEL_FIELDNUM 4 -#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_LABEL_FIELDNAME "label" -#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_FIELDNUM 5 -#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_FIELDNAME "type" -#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_NAME_FIELDNUM 6 -#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_NAME_FIELDNAME "type_name" -#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_DEFAULT_VALUE_FIELDNUM 7 -#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_DEFAULT_VALUE_FIELDNAME "default_value" -#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_OPTIONS_FIELDNUM 8 -#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_OPTIONS_FIELDNAME "options" -#define GOOGLE_PROTOBUF_SERVICEOPTIONS_UNINTERPRETED_OPTION_FIELDNUM 999 -#define GOOGLE_PROTOBUF_SERVICEOPTIONS_UNINTERPRETED_OPTION_FIELDNAME "uninterpreted_option" -#define GOOGLE_PROTOBUF_METHODOPTIONS_UNINTERPRETED_OPTION_FIELDNUM 999 -#define GOOGLE_PROTOBUF_METHODOPTIONS_UNINTERPRETED_OPTION_FIELDNAME "uninterpreted_option" +#define GOOGLE_PROTOBUF_FILEDESCRIPTORSET_FILE__FIELDNUM 1 +#define GOOGLE_PROTOBUF_FILEDESCRIPTORSET_FILE__FIELDNAME "file" +#define GOOGLE_PROTOBUF_FILEDESCRIPTORSET_FILE__FIELDTYPE 11 + +#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_NAME__FIELDNUM 1 +#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_NAME__FIELDNAME "name" +#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_NAME__FIELDTYPE 9 + +#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_FIELD__FIELDNUM 2 +#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_FIELD__FIELDNAME "field" +#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_FIELD__FIELDTYPE 11 + +#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_NESTED_TYPE__FIELDNUM 3 +#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_NESTED_TYPE__FIELDNAME "nested_type" +#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_NESTED_TYPE__FIELDTYPE 11 + +#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_ENUM_TYPE__FIELDNUM 4 +#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_ENUM_TYPE__FIELDNAME "enum_type" +#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_ENUM_TYPE__FIELDTYPE 11 + +#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSION_RANGE__FIELDNUM 5 +#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSION_RANGE__FIELDNAME "extension_range" +#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSION_RANGE__FIELDTYPE 11 + +#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSION__FIELDNUM 6 +#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSION__FIELDNAME "extension" +#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSION__FIELDTYPE 11 + +#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_OPTIONS__FIELDNUM 7 +#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_OPTIONS__FIELDNAME "options" +#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_OPTIONS__FIELDTYPE 11 + +#define GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_PATH__FIELDNUM 1 +#define GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_PATH__FIELDNAME "path" +#define GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_PATH__FIELDTYPE 5 + +#define GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_SPAN__FIELDNUM 2 +#define GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_SPAN__FIELDNAME "span" +#define GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_SPAN__FIELDTYPE 5 + +#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NAME__FIELDNUM 2 +#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NAME__FIELDNAME "name" +#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NAME__FIELDTYPE 11 + +#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_IDENTIFIER_VALUE__FIELDNUM 3 +#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_IDENTIFIER_VALUE__FIELDNAME "identifier_value" +#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_IDENTIFIER_VALUE__FIELDTYPE 9 + +#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_POSITIVE_INT_VALUE__FIELDNUM 4 +#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_POSITIVE_INT_VALUE__FIELDNAME "positive_int_value" +#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_POSITIVE_INT_VALUE__FIELDTYPE 4 + +#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NEGATIVE_INT_VALUE__FIELDNUM 5 +#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NEGATIVE_INT_VALUE__FIELDNAME "negative_int_value" +#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NEGATIVE_INT_VALUE__FIELDTYPE 3 + +#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_DOUBLE_VALUE__FIELDNUM 6 +#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_DOUBLE_VALUE__FIELDNAME "double_value" +#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_DOUBLE_VALUE__FIELDTYPE 1 + +#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_STRING_VALUE__FIELDNUM 7 +#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_STRING_VALUE__FIELDNAME "string_value" +#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_STRING_VALUE__FIELDTYPE 12 + +#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_AGGREGATE_VALUE__FIELDNUM 8 +#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_AGGREGATE_VALUE__FIELDNAME "aggregate_value" +#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_AGGREGATE_VALUE__FIELDTYPE 9 + +#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_NAME__FIELDNUM 1 +#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_NAME__FIELDNAME "name" +#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_NAME__FIELDTYPE 9 + +#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_PACKAGE__FIELDNUM 2 +#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_PACKAGE__FIELDNAME "package" +#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_PACKAGE__FIELDTYPE 9 + +#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_DEPENDENCY__FIELDNUM 3 +#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_DEPENDENCY__FIELDNAME "dependency" +#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_DEPENDENCY__FIELDTYPE 9 + +#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_MESSAGE_TYPE__FIELDNUM 4 +#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_MESSAGE_TYPE__FIELDNAME "message_type" +#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_MESSAGE_TYPE__FIELDTYPE 11 + +#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_ENUM_TYPE__FIELDNUM 5 +#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_ENUM_TYPE__FIELDNAME "enum_type" +#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_ENUM_TYPE__FIELDTYPE 11 + +#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_SERVICE__FIELDNUM 6 +#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_SERVICE__FIELDNAME "service" +#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_SERVICE__FIELDTYPE 11 + +#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_EXTENSION__FIELDNUM 7 +#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_EXTENSION__FIELDNAME "extension" +#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_EXTENSION__FIELDTYPE 11 + +#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_OPTIONS__FIELDNUM 8 +#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_OPTIONS__FIELDNAME "options" +#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_OPTIONS__FIELDTYPE 11 + +#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_SOURCE_CODE_INFO__FIELDNUM 9 +#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_SOURCE_CODE_INFO__FIELDNAME "source_code_info" +#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_SOURCE_CODE_INFO__FIELDTYPE 11 + +#define GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_NAME__FIELDNUM 1 +#define GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_NAME__FIELDNAME "name" +#define GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_NAME__FIELDTYPE 9 + +#define GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_INPUT_TYPE__FIELDNUM 2 +#define GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_INPUT_TYPE__FIELDNAME "input_type" +#define GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_INPUT_TYPE__FIELDTYPE 9 + +#define GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_OUTPUT_TYPE__FIELDNUM 3 +#define GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_OUTPUT_TYPE__FIELDNAME "output_type" +#define GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_OUTPUT_TYPE__FIELDTYPE 9 + +#define GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_OPTIONS__FIELDNUM 4 +#define GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_OPTIONS__FIELDNAME "options" +#define GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_OPTIONS__FIELDTYPE 11 + +#define GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_NAME__FIELDNUM 1 +#define GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_NAME__FIELDNAME "name" +#define GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_NAME__FIELDTYPE 9 + +#define GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_VALUE__FIELDNUM 2 +#define GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_VALUE__FIELDNAME "value" +#define GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_VALUE__FIELDTYPE 11 + +#define GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_OPTIONS__FIELDNUM 3 +#define GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_OPTIONS__FIELDNAME "options" +#define GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_OPTIONS__FIELDTYPE 11 + +#define GOOGLE_PROTOBUF_ENUMVALUEOPTIONS_UNINTERPRETED_OPTION__FIELDNUM 999 +#define GOOGLE_PROTOBUF_ENUMVALUEOPTIONS_UNINTERPRETED_OPTION__FIELDNAME "uninterpreted_option" +#define GOOGLE_PROTOBUF_ENUMVALUEOPTIONS_UNINTERPRETED_OPTION__FIELDTYPE 11 + +#define GOOGLE_PROTOBUF_ENUMVALUEDESCRIPTORPROTO_NAME__FIELDNUM 1 +#define GOOGLE_PROTOBUF_ENUMVALUEDESCRIPTORPROTO_NAME__FIELDNAME "name" +#define GOOGLE_PROTOBUF_ENUMVALUEDESCRIPTORPROTO_NAME__FIELDTYPE 9 + +#define GOOGLE_PROTOBUF_ENUMVALUEDESCRIPTORPROTO_NUMBER__FIELDNUM 2 +#define GOOGLE_PROTOBUF_ENUMVALUEDESCRIPTORPROTO_NUMBER__FIELDNAME "number" +#define GOOGLE_PROTOBUF_ENUMVALUEDESCRIPTORPROTO_NUMBER__FIELDTYPE 5 + +#define GOOGLE_PROTOBUF_ENUMVALUEDESCRIPTORPROTO_OPTIONS__FIELDNUM 3 +#define GOOGLE_PROTOBUF_ENUMVALUEDESCRIPTORPROTO_OPTIONS__FIELDNAME "options" +#define GOOGLE_PROTOBUF_ENUMVALUEDESCRIPTORPROTO_OPTIONS__FIELDTYPE 11 + +#define GOOGLE_PROTOBUF_SERVICEDESCRIPTORPROTO_NAME__FIELDNUM 1 +#define GOOGLE_PROTOBUF_SERVICEDESCRIPTORPROTO_NAME__FIELDNAME "name" +#define GOOGLE_PROTOBUF_SERVICEDESCRIPTORPROTO_NAME__FIELDTYPE 9 + +#define GOOGLE_PROTOBUF_SERVICEDESCRIPTORPROTO_METHOD__FIELDNUM 2 +#define GOOGLE_PROTOBUF_SERVICEDESCRIPTORPROTO_METHOD__FIELDNAME "method" +#define GOOGLE_PROTOBUF_SERVICEDESCRIPTORPROTO_METHOD__FIELDTYPE 11 + +#define GOOGLE_PROTOBUF_SERVICEDESCRIPTORPROTO_OPTIONS__FIELDNUM 3 +#define GOOGLE_PROTOBUF_SERVICEDESCRIPTORPROTO_OPTIONS__FIELDNAME "options" +#define GOOGLE_PROTOBUF_SERVICEDESCRIPTORPROTO_OPTIONS__FIELDTYPE 11 + +#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NAMEPART_NAME_PART__FIELDNUM 1 +#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NAMEPART_NAME_PART__FIELDNAME "name_part" +#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NAMEPART_NAME_PART__FIELDTYPE 9 + +#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NAMEPART_IS_EXTENSION__FIELDNUM 2 +#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NAMEPART_IS_EXTENSION__FIELDNAME "is_extension" +#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NAMEPART_IS_EXTENSION__FIELDTYPE 8 + +#define GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION__FIELDNUM 1 +#define GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION__FIELDNAME "location" +#define GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION__FIELDTYPE 11 + +#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSIONRANGE_START__FIELDNUM 1 +#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSIONRANGE_START__FIELDNAME "start" +#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSIONRANGE_START__FIELDTYPE 5 + +#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSIONRANGE_END__FIELDNUM 2 +#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSIONRANGE_END__FIELDNAME "end" +#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSIONRANGE_END__FIELDTYPE 5 + +#define GOOGLE_PROTOBUF_FIELDOPTIONS_CTYPE__FIELDNUM 1 +#define GOOGLE_PROTOBUF_FIELDOPTIONS_CTYPE__FIELDNAME "ctype" +#define GOOGLE_PROTOBUF_FIELDOPTIONS_CTYPE__FIELDTYPE 14 + +#define GOOGLE_PROTOBUF_FIELDOPTIONS_PACKED__FIELDNUM 2 +#define GOOGLE_PROTOBUF_FIELDOPTIONS_PACKED__FIELDNAME "packed" +#define GOOGLE_PROTOBUF_FIELDOPTIONS_PACKED__FIELDTYPE 8 + +#define GOOGLE_PROTOBUF_FIELDOPTIONS_DEPRECATED__FIELDNUM 3 +#define GOOGLE_PROTOBUF_FIELDOPTIONS_DEPRECATED__FIELDNAME "deprecated" +#define GOOGLE_PROTOBUF_FIELDOPTIONS_DEPRECATED__FIELDTYPE 8 + +#define GOOGLE_PROTOBUF_FIELDOPTIONS_EXPERIMENTAL_MAP_KEY__FIELDNUM 9 +#define GOOGLE_PROTOBUF_FIELDOPTIONS_EXPERIMENTAL_MAP_KEY__FIELDNAME "experimental_map_key" +#define GOOGLE_PROTOBUF_FIELDOPTIONS_EXPERIMENTAL_MAP_KEY__FIELDTYPE 9 + +#define GOOGLE_PROTOBUF_FIELDOPTIONS_UNINTERPRETED_OPTION__FIELDNUM 999 +#define GOOGLE_PROTOBUF_FIELDOPTIONS_UNINTERPRETED_OPTION__FIELDNAME "uninterpreted_option" +#define GOOGLE_PROTOBUF_FIELDOPTIONS_UNINTERPRETED_OPTION__FIELDTYPE 11 + +#define GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_PACKAGE__FIELDNUM 1 +#define GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_PACKAGE__FIELDNAME "java_package" +#define GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_PACKAGE__FIELDTYPE 9 + +#define GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_OUTER_CLASSNAME__FIELDNUM 8 +#define GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_OUTER_CLASSNAME__FIELDNAME "java_outer_classname" +#define GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_OUTER_CLASSNAME__FIELDTYPE 9 + +#define GOOGLE_PROTOBUF_FILEOPTIONS_OPTIMIZE_FOR__FIELDNUM 9 +#define GOOGLE_PROTOBUF_FILEOPTIONS_OPTIMIZE_FOR__FIELDNAME "optimize_for" +#define GOOGLE_PROTOBUF_FILEOPTIONS_OPTIMIZE_FOR__FIELDTYPE 14 + +#define GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_MULTIPLE_FILES__FIELDNUM 10 +#define GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_MULTIPLE_FILES__FIELDNAME "java_multiple_files" +#define GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_MULTIPLE_FILES__FIELDTYPE 8 + +#define GOOGLE_PROTOBUF_FILEOPTIONS_CC_GENERIC_SERVICES__FIELDNUM 16 +#define GOOGLE_PROTOBUF_FILEOPTIONS_CC_GENERIC_SERVICES__FIELDNAME "cc_generic_services" +#define GOOGLE_PROTOBUF_FILEOPTIONS_CC_GENERIC_SERVICES__FIELDTYPE 8 + +#define GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_GENERIC_SERVICES__FIELDNUM 17 +#define GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_GENERIC_SERVICES__FIELDNAME "java_generic_services" +#define GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_GENERIC_SERVICES__FIELDTYPE 8 + +#define GOOGLE_PROTOBUF_FILEOPTIONS_PY_GENERIC_SERVICES__FIELDNUM 18 +#define GOOGLE_PROTOBUF_FILEOPTIONS_PY_GENERIC_SERVICES__FIELDNAME "py_generic_services" +#define GOOGLE_PROTOBUF_FILEOPTIONS_PY_GENERIC_SERVICES__FIELDTYPE 8 + +#define GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_GENERATE_EQUALS_AND_HASH__FIELDNUM 20 +#define GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_GENERATE_EQUALS_AND_HASH__FIELDNAME "java_generate_equals_and_hash" +#define GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_GENERATE_EQUALS_AND_HASH__FIELDTYPE 8 + +#define GOOGLE_PROTOBUF_FILEOPTIONS_UNINTERPRETED_OPTION__FIELDNUM 999 +#define GOOGLE_PROTOBUF_FILEOPTIONS_UNINTERPRETED_OPTION__FIELDNAME "uninterpreted_option" +#define GOOGLE_PROTOBUF_FILEOPTIONS_UNINTERPRETED_OPTION__FIELDTYPE 11 + +#define GOOGLE_PROTOBUF_MESSAGEOPTIONS_MESSAGE_SET_WIRE_FORMAT__FIELDNUM 1 +#define GOOGLE_PROTOBUF_MESSAGEOPTIONS_MESSAGE_SET_WIRE_FORMAT__FIELDNAME "message_set_wire_format" +#define GOOGLE_PROTOBUF_MESSAGEOPTIONS_MESSAGE_SET_WIRE_FORMAT__FIELDTYPE 8 + +#define GOOGLE_PROTOBUF_MESSAGEOPTIONS_NO_STANDARD_DESCRIPTOR_ACCESSOR__FIELDNUM 2 +#define GOOGLE_PROTOBUF_MESSAGEOPTIONS_NO_STANDARD_DESCRIPTOR_ACCESSOR__FIELDNAME "no_standard_descriptor_accessor" +#define GOOGLE_PROTOBUF_MESSAGEOPTIONS_NO_STANDARD_DESCRIPTOR_ACCESSOR__FIELDTYPE 8 + +#define GOOGLE_PROTOBUF_MESSAGEOPTIONS_UNINTERPRETED_OPTION__FIELDNUM 999 +#define GOOGLE_PROTOBUF_MESSAGEOPTIONS_UNINTERPRETED_OPTION__FIELDNAME "uninterpreted_option" +#define GOOGLE_PROTOBUF_MESSAGEOPTIONS_UNINTERPRETED_OPTION__FIELDTYPE 11 + +#define GOOGLE_PROTOBUF_ENUMOPTIONS_UNINTERPRETED_OPTION__FIELDNUM 999 +#define GOOGLE_PROTOBUF_ENUMOPTIONS_UNINTERPRETED_OPTION__FIELDNAME "uninterpreted_option" +#define GOOGLE_PROTOBUF_ENUMOPTIONS_UNINTERPRETED_OPTION__FIELDTYPE 11 + +#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_NAME__FIELDNUM 1 +#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_NAME__FIELDNAME "name" +#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_NAME__FIELDTYPE 9 + +#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_EXTENDEE__FIELDNUM 2 +#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_EXTENDEE__FIELDNAME "extendee" +#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_EXTENDEE__FIELDTYPE 9 + +#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_NUMBER__FIELDNUM 3 +#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_NUMBER__FIELDNAME "number" +#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_NUMBER__FIELDTYPE 5 + +#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_LABEL__FIELDNUM 4 +#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_LABEL__FIELDNAME "label" +#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_LABEL__FIELDTYPE 14 + +#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE__FIELDNUM 5 +#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE__FIELDNAME "type" +#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE__FIELDTYPE 14 + +#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_NAME__FIELDNUM 6 +#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_NAME__FIELDNAME "type_name" +#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_NAME__FIELDTYPE 9 + +#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_DEFAULT_VALUE__FIELDNUM 7 +#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_DEFAULT_VALUE__FIELDNAME "default_value" +#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_DEFAULT_VALUE__FIELDTYPE 9 + +#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_OPTIONS__FIELDNUM 8 +#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_OPTIONS__FIELDNAME "options" +#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_OPTIONS__FIELDTYPE 11 + +#define GOOGLE_PROTOBUF_SERVICEOPTIONS_UNINTERPRETED_OPTION__FIELDNUM 999 +#define GOOGLE_PROTOBUF_SERVICEOPTIONS_UNINTERPRETED_OPTION__FIELDNAME "uninterpreted_option" +#define GOOGLE_PROTOBUF_SERVICEOPTIONS_UNINTERPRETED_OPTION__FIELDTYPE 11 + +#define GOOGLE_PROTOBUF_METHODOPTIONS_UNINTERPRETED_OPTION__FIELDNUM 999 +#define GOOGLE_PROTOBUF_METHODOPTIONS_UNINTERPRETED_OPTION__FIELDNAME "uninterpreted_option" +#define GOOGLE_PROTOBUF_METHODOPTIONS_UNINTERPRETED_OPTION__FIELDTYPE 11 + #ifdef __cplusplus } /* extern "C" */ #endif diff --git a/src/upb.c b/src/upb.c index 6bb1ccc..fdf5c07 100644 --- a/src/upb.c +++ b/src/upb.c @@ -8,7 +8,7 @@ #include #include #include - +#include "descriptor_const.h" #include "upb.h" #include "upb_string.h" @@ -40,6 +40,12 @@ const upb_type_info upb_types[] = { TYPE_INFO(UPB_WIRE_TYPE_VARINT, int64_t, 1, INT64) // SINT64 }; +#ifdef NDEBUG +upb_value UPB_NO_VALUE = {{0}}; +#else +upb_value UPB_NO_VALUE = {{0}, UPB_VALUETYPE_RAW}; +#endif + void upb_seterr(upb_status *status, enum upb_status_code code, const char *msg, ...) { status->code = code; diff --git a/src/upb.h b/src/upb.h index c8d707d..01de8cf 100644 --- a/src/upb.h +++ b/src/upb.h @@ -46,11 +46,15 @@ INLINE size_t upb_align_up(size_t val, size_t align) { // The maximum that any submessages can be nested. Matches proto2's limit. +// At the moment this specifies the size of several statically-sized arrays +// and therefore setting it high will cause more memory to be used. Will +// be replaced by a runtime-configurable limit and dynamically-resizing arrays. #define UPB_MAX_NESTING 64 // The maximum number of fields that any one .proto type can have. Note that // this is very different than the max field number. It is hard to imagine a -// scenario where more than 32k fields makes sense. +// scenario where more than 32k fields (each with its own name and field number) +// makes sense. #define UPB_MAX_FIELDS (1<<15) typedef int16_t upb_field_count_t; @@ -72,7 +76,9 @@ typedef int16_t upb_field_count_t; // The maximum depth that the type graph can have. Note that this setting does // not automatically constrain UPB_MAX_NESTING, because type cycles allow for -// unlimited nesting if we do not limit it. +// unlimited nesting if we do not limit it. Many algorithms in upb call +// recursive functions that traverse the type graph, so we must limit this to +// avoid blowing the C stack. #define UPB_MAX_TYPE_DEPTH 64 // The biggest possible single value is a 10-byte varint. @@ -145,6 +151,8 @@ struct _upb_msg; typedef struct _upb_msg upb_msg; struct _upb_bytesrc; typedef struct _upb_bytesrc upb_bytesrc; +struct _upb_fielddef; +typedef struct _upb_fielddef upb_fielddef; typedef int32_t upb_strlen_t; #define UPB_STRLEN_MAX INT32_MAX @@ -155,23 +163,25 @@ typedef uint8_t upb_valuetype_t; #define UPB_VALUETYPE_ARRAY 32 #define UPB_VALUETYPE_BYTESRC 32 #define UPB_VALUETYPE_RAW 33 +#define UPB_VALUETYPE_FIELDDEF 34 // A single .proto value. The owner must have an out-of-band way of knowing // the type, so that it knows which union member to use. typedef struct { union { + uint64_t uint64; double _double; float _float; int32_t int32; int64_t int64; uint32_t uint32; - uint64_t uint64; bool _bool; upb_string *str; upb_bytesrc *bytesrc; upb_msg *msg; upb_array *arr; upb_atomic_refcount_t *refcount; + upb_fielddef *fielddef; void *_void; } val; @@ -208,6 +218,9 @@ UPB_VALUE_ACCESSORS(str, str, upb_string*, UPB_TYPE(STRING)); UPB_VALUE_ACCESSORS(msg, msg, upb_msg*, UPB_TYPE(MESSAGE)); UPB_VALUE_ACCESSORS(arr, arr, upb_array*, UPB_VALUETYPE_ARRAY); UPB_VALUE_ACCESSORS(bytesrc, bytesrc, upb_bytesrc*, UPB_VALUETYPE_BYTESRC); +UPB_VALUE_ACCESSORS(fielddef, fielddef, upb_fielddef*, UPB_VALUETYPE_FIELDDEF); + +extern upb_value UPB_NO_VALUE; INLINE void upb_value_setraw(upb_value *val, uint64_t cval) { SET_TYPE(val->type, UPB_VALUETYPE_RAW); diff --git a/src/upb_decoder.c b/src/upb_decoder.c index dc5dafd..6fa37b4 100644 --- a/src/upb_decoder.c +++ b/src/upb_decoder.c @@ -4,13 +4,11 @@ * Copyright (c) 2008-2011 Joshua Haberman. See LICENSE for details. */ -#include "upb_decoder.h" -#include "upb_varint_decoder.h" - #include #include #include -#include "upb_def.h" +#include "upb_decoder.h" +#include "upb_varint_decoder.h" // If the return value is other than UPB_CONTINUE, that is what the last // callback returned. @@ -37,7 +35,12 @@ INLINE int64_t upb_zzdec_64(uint64_t n) { return (n >> 1) ^ -(int64_t)(n & 1); } INLINE void upb_decoder_advance(upb_decoder *d, size_t len) { d->ptr += len; - //d->bytes_parsed_slow += len; +} + +INLINE size_t upb_decoder_offset(upb_decoder *d) { + size_t offset = d->buf_stream_offset; + if (d->buf) offset += (d->ptr - upb_string_getrobuf(d->buf)); + return offset; } INLINE size_t upb_decoder_bufleft(upb_decoder *d) { @@ -45,13 +48,11 @@ INLINE size_t upb_decoder_bufleft(upb_decoder *d) { } INLINE void upb_dstate_setmsgend(upb_decoder *d) { - d->submsg_end = (d->top->end_offset == UPB_GROUP_END_OFFSET) ? - (void*)UINTPTR_MAX : - upb_string_getrobuf(d->buf) + (d->top->end_offset - d->buf_stream_offset); + size_t end_offset = d->dispatcher.top->end_offset; + d->submsg_end = (end_offset == UPB_GROUP_END_OFFSET) ? (void*)UINTPTR_MAX : + d->ptr + (end_offset - upb_decoder_offset(d)); } -static upb_flow_t upb_pop(upb_decoder *d); - // Called only from the slow path, this function copies the next "len" bytes // from the stream to "data", adjusting the dstate appropriately. static bool upb_getbuf(upb_decoder *d, void *data, size_t bytes_wanted) { @@ -186,54 +187,44 @@ INLINE bool upb_check_type(upb_wire_type_t wt, upb_fieldtype_t ft) { return upb_types[ft].native_wire_type == wt; } -static upb_flow_t upb_push(upb_decoder *d, upb_fielddef *f, - upb_value submsg_len, upb_fieldtype_t type) { - ++d->top; - if(d->top >= d->limit) { - upb_seterr(d->status, UPB_ERROR, "Nesting too deep."); - return UPB_ERROR; - } - d->top->end_offset = (type == UPB_TYPE(GROUP)) ? - UPB_GROUP_END_OFFSET : - d->buf_stream_offset + (d->ptr - upb_string_getrobuf(d->buf)) + - upb_value_getint32(submsg_len); - d->top->f = f; - d->msgdef = upb_downcast_msgdef(f->def); +static upb_flow_t upb_pop(upb_decoder *d) { + upb_flow_t ret = upb_dispatch_endsubmsg(&d->dispatcher); upb_dstate_setmsgend(d); - upb_flow_t ret = upb_dispatch_startsubmsg(&d->dispatcher, f); - if (ret == UPB_SKIPSUBMSG) { - if (type == UPB_TYPE(GROUP)) { - fprintf(stderr, "upb_decoder: Can't skip groups yet.\n"); - abort(); - } - upb_decoder_advance(d, upb_value_getint32(submsg_len)); - --d->top; - upb_dstate_setmsgend(d); - ret = UPB_CONTINUE; - } return ret; } -static upb_flow_t upb_pop(upb_decoder *d) { - --d->top; - d->msgdef = upb_downcast_msgdef(d->top->f->def); +static upb_flow_t upb_decoder_skipsubmsg(upb_decoder *d) { + if (d->dispatcher.top->f->type == UPB_TYPE(GROUP)) { + fprintf(stderr, "upb_decoder: Can't skip groups yet.\n"); + abort(); + } + upb_decoder_advance(d, d->dispatcher.top->end_offset - d->buf_stream_offset - + (d->ptr - upb_string_getrobuf(d->buf))); + upb_pop(d); + return UPB_CONTINUE; +} + +static upb_flow_t upb_push(upb_decoder *d, upb_handlers_fieldent *f, + upb_value submsg_len) { + upb_flow_t flow = upb_dispatch_startsubmsg(&d->dispatcher, f, + (f->type == UPB_TYPE(GROUP)) ? UPB_GROUP_END_OFFSET : + upb_decoder_offset(d) + upb_value_getint32(submsg_len)); upb_dstate_setmsgend(d); - return upb_dispatch_endsubmsg(&d->dispatcher, d->top->f); + return flow; } -void upb_decoder_run(upb_src *src, upb_status *status) { - upb_decoder *d = (upb_decoder*)src; +void upb_decoder_decode(upb_decoder *d, upb_status *status) { d->status = status; - d->ptr = NULL; - d->end = NULL; // Force a buffer pull. - d->submsg_end = (void*)0x1; // But don't let end-of-message get triggered. - d->msgdef = upb_downcast_msgdef(d->top->f->def); -// TODO: handle UPB_SKIPSUBMSG -#define CHECK_FLOW(expr) if ((expr) == UPB_BREAK) { /*assert(!upb_ok(status));*/ goto callback_err; } +#define CHECK_FLOW(expr) \ + switch (expr) { \ + case UPB_BREAK: goto callback_err; \ + case UPB_SKIPSUBMSG: upb_decoder_skipsubmsg(d); continue; \ + default: break; /* continue normally. */ \ + } #define CHECK(expr) if (!expr) { assert(!upb_ok(status)); goto err; } - CHECK_FLOW(upb_dispatch_startmsg(&d->dispatcher)); + if (upb_dispatch_startmsg(&d->dispatcher, d->closure) != UPB_CONTINUE) goto err; // Main loop: executed once per tag/field pair. while(1) { @@ -261,10 +252,10 @@ void upb_decoder_run(upb_src *src, upb_status *status) { // Parse/handle tag. upb_tag tag; if (!upb_decode_tag(d, &tag)) { - if (status->code == UPB_EOF && d->top == d->stack) { + if (status->code == UPB_EOF && upb_dispatcher_stackempty(&d->dispatcher)) { // Normal end-of-file. upb_clearerr(status); - CHECK_FLOW(upb_dispatch_endmsg(&d->dispatcher)); + upb_dispatch_endmsg(&d->dispatcher, status); return; } else { if (status->code == UPB_EOF) { @@ -282,7 +273,7 @@ void upb_decoder_run(upb_src *src, upb_status *status) { case UPB_WIRE_TYPE_START_GROUP: break; // Nothing to do now, below we will push appropriately. case UPB_WIRE_TYPE_END_GROUP: - if(d->top->end_offset != UPB_GROUP_END_OFFSET) { + if(d->dispatcher.top->end_offset != UPB_GROUP_END_OFFSET) { upb_seterr(status, UPB_ERROR, "Unexpected END_GROUP tag."); goto err; } @@ -302,41 +293,38 @@ void upb_decoder_run(upb_src *src, upb_status *status) { } // Look up field by tag number. - upb_itof_ent *e = upb_msgdef_itofent(d->msgdef, tag.field_number); + upb_dispatcher_field *f = + upb_dispatcher_lookup(&d->dispatcher, tag.field_number); - if (!e) { + if (!f) { if (tag.wire_type == UPB_WIRE_TYPE_DELIMITED) CHECK(upb_decode_string(d, &val, &d->tmp)); CHECK_FLOW(upb_dispatch_unknownval(&d->dispatcher, tag.field_number, val)); continue; } - upb_fielddef *f = e->f; - assert(e->field_type == f->type); - assert(e->native_wire_type == upb_types[f->type].native_wire_type); - - if (tag.wire_type != e->native_wire_type) { + if (tag.wire_type != f->native_wire_type) { // TODO: Support packed fields. - upb_seterr(status, UPB_ERROR, "Field had incorrect type, name: " UPB_STRFMT - ", field type: %d, expected wire type %d, actual wire type: %d", - UPB_STRARG(f->name), f->type, upb_types[f->type].native_wire_type, - tag.wire_type); - upb_printerr(status); + upb_seterr(status, UPB_ERROR, "Field had incorrect type, field number: %d" + ", field type: %d, expected wire type: %d, " + "actual wire type: %d, offset: %d", + tag.field_number, f->type, upb_types[f->type].native_wire_type, + tag.wire_type, upb_decoder_offset(d)); goto err; } - // Perform any further massaging of the data now that we have the fielddef. - // Now we can distinguish strings from submessages, and we know about - // zig-zag-encoded types. + // Perform any further massaging of the data now that we have the field's + // type. Now we can distinguish strings from submessages, and we know + // about zig-zag-encoded types. // TODO: handle packed encoding. // TODO: if we were being paranoid, we could check for 32-bit-varint types // that the top 32 bits all match the highest bit of the low 32 bits. // If this is not true we are losing data. But the main protobuf library // doesn't check this, and it would slow us down, so pass for now. - switch (e->field_type) { + switch (f->type) { case UPB_TYPE(MESSAGE): case UPB_TYPE(GROUP): - CHECK_FLOW(upb_push(d, f, val, e->field_type)); + CHECK_FLOW(upb_push(d, f, val)); continue; // We have no value to dispatch. case UPB_TYPE(STRING): case UPB_TYPE(BYTES): @@ -358,7 +346,6 @@ void upb_decoder_run(upb_src *src, upb_status *status) { } callback_err: - upb_copyerr(status, d->dispatcher.top->handlers.status); if (upb_ok(status)) { upb_seterr(status, UPB_ERROR, "Callback returned UPB_BREAK"); } @@ -366,37 +353,24 @@ err: assert(!upb_ok(status)); } -void upb_decoder_sethandlers(upb_src *src, upb_handlers *handlers) { - upb_decoder *d = (upb_decoder*)src; - upb_dispatcher_reset(&d->dispatcher, handlers, true); - d->top = d->stack; - d->buf_stream_offset = 0; -} - -void upb_decoder_init(upb_decoder *d, upb_msgdef *msgdef) { - static upb_src_vtbl vtbl = { - &upb_decoder_sethandlers, - &upb_decoder_run, - }; - upb_src_init(&d->src, &vtbl); - upb_dispatcher_init(&d->dispatcher); - d->f.def = UPB_UPCAST(msgdef); - d->stack[0].f = &d->f; - // Never want to end top-level message, so treat it like a group. - d->stack[0].end_offset = UPB_GROUP_END_OFFSET; - d->limit = &d->stack[UPB_MAX_NESTING]; +void upb_decoder_init(upb_decoder *d, upb_handlers *handlers) { + upb_dispatcher_init(&d->dispatcher, handlers, UPB_GROUP_END_OFFSET); d->buf = NULL; d->tmp = NULL; } -void upb_decoder_reset(upb_decoder *d, upb_bytesrc *bytesrc) { +void upb_decoder_reset(upb_decoder *d, upb_bytesrc *bytesrc, void *closure) { d->bytesrc = bytesrc; - d->top = &d->stack[0]; + d->closure = closure; + upb_dispatcher_reset(&d->dispatcher); + d->ptr = NULL; + d->end = NULL; // Force a buffer pull. + d->submsg_end = (void*)0x1; // But don't let end-of-message get triggered. + d->buf_stream_offset = 0; } void upb_decoder_uninit(upb_decoder *d) { + upb_dispatcher_uninit(&d->dispatcher); upb_string_unref(d->buf); upb_string_unref(d->tmp); } - -upb_src *upb_decoder_src(upb_decoder *d) { return &d->src; } diff --git a/src/upb_decoder.h b/src/upb_decoder.h index 98b1b94..af2124c 100644 --- a/src/upb_decoder.h +++ b/src/upb_decoder.h @@ -18,7 +18,6 @@ #include #include -#include "upb_def.h" #include "upb_stream.h" #ifdef __cplusplus @@ -27,31 +26,17 @@ extern "C" { /* upb_decoder *****************************************************************/ -// The decoder keeps a stack with one entry per level of recursion. -// upb_decoder_frame is one frame of that stack. -typedef struct { - upb_fielddef *f; - size_t end_offset; // For groups, 0. -} upb_decoder_frame; - struct _upb_decoder { - // Immutable state of the decoder. - upb_src src; - upb_dispatcher dispatcher; + // Bytesrc from which we pull serialized data. upb_bytesrc *bytesrc; - // Mutable state of the decoder. - - // Msgdef for the current level. - upb_msgdef *msgdef; - - // Stack entries store the offset where the submsg ends (for groups, 0). - upb_decoder_frame *top, *limit; + // Dispatcher to which we push parsed data. + upb_dispatcher dispatcher; // Current input buffer. upb_string *buf; - // Temporary string for passing to callbacks. + // Temporary string for passing string data to callbacks. upb_string *tmp; // The offset within the overall stream represented by the *beginning* of buf. @@ -66,12 +51,11 @@ struct _upb_decoder { // End of this submessage, relative to *ptr. const char *submsg_end; + // The closure that was passed by the caller for the top-level message. + void *closure; + // Where we will store any errors that occur. upb_status *status; - - // A fake fielddef for storing the msgdef for the top-level message. - upb_fielddef f; - upb_decoder_frame stack[UPB_MAX_NESTING]; }; // A upb_decoder decodes the binary protocol buffer format, writing the data it @@ -80,18 +64,16 @@ struct _upb_decoder; typedef struct _upb_decoder upb_decoder; // Allocates and frees a upb_decoder, respectively. -void upb_decoder_init(upb_decoder *d, upb_msgdef *md); +void upb_decoder_init(upb_decoder *d, upb_handlers *handlers); void upb_decoder_uninit(upb_decoder *d); // Resets the internal state of an already-allocated decoder. This puts it in a // state where it has not seen any data, and expects the next data to be from // the beginning of a new protobuf. Parsers must be reset before they can be // used. A decoder can be reset multiple times. -void upb_decoder_reset(upb_decoder *d, upb_bytesrc *bytesrc); +void upb_decoder_reset(upb_decoder *d, upb_bytesrc *bytesrc, void *closure); -// Returns a upb_src pointer by which the decoder can be used. The returned -// upb_src is invalidated by upb_decoder_reset() or upb_decoder_free(). -upb_src *upb_decoder_src(upb_decoder *d); +void upb_decoder_decode(upb_decoder *d, upb_status *status); #ifdef __cplusplus } /* extern "C" */ diff --git a/src/upb_decoder_x64.asm b/src/upb_decoder_x64.asm index 032ea86..c417644 100644 --- a/src/upb_decoder_x64.asm +++ b/src/upb_decoder_x64.asm @@ -34,8 +34,8 @@ SECTION .text %define BUF rbx ; const char *p, current buf position. %define END rbp ; const char *end, where the buf ends (either submsg end or buf end) %define STRING r12 ; unused -%define FIELDDEF r13 ; upb_fielddef *f, needs to be preserved across varint decoding call. -%define CALLBACK r14 +%define FVAL r13 ; upb_value fval, needs to be preserved across varint decoding call. +%define UNUSED r14 %define CLOSURE r15 ; Stack layout: *tableptr, uint32_t maxfield_times_8 @@ -57,10 +57,10 @@ SECTION .text ; path that goes into a tight loop if the encoding was packed). ; - check_6: the field is not a group or a message (or string, TODO) ; (this could be relaxed, but due to delegation it's a bit tricky). -; - if the value is a string, the entire string is available in +; - check_7: if the value is a string, the entire string is available in ; the buffer, and our cached string object can be recycled, and ; our string object already references the source buffer, so -; absolutely no refcount twiddling is required. (check_7) +; absolutely no refcount twiddling is required. %macro decode_and_dispatch_ 0 @@ -78,7 +78,7 @@ align 16 ; Decode a 1 or 2-byte varint -> eax. mov cl, byte [BUF] lea rdi, [BUF+1] - movzx rax, cl ; Need all of rax since we're doing a 64-bit lea later. + movzx eax, cl and eax, 0x7f test cl, cl jns .one_byte_tag ; Should be predictable if fields are in order. diff --git a/src/upb_def.c b/src/upb_def.c index 61d1a3e..08e5a8c 100644 --- a/src/upb_def.c +++ b/src/upb_def.c @@ -7,8 +7,6 @@ #include #include #include -#include "descriptor.c" -#include "descriptor_const.h" #include "upb_def.h" #include "upb_msg.h" @@ -190,16 +188,11 @@ static void upb_def_uninit(upb_def *def) { // We use a separate object (upb_defbuilder) instead of having the defs handle // the parse themselves because we need to store state that is only necessary // during the building process itself. - -// When we are bootstrapping descriptor.proto, we must help the bare decoder out -// by telling it when to descend into a submessage, because with the wire format -// alone we cannot tell the difference between a submessage and a string. // -// TODO: In the long-term, we should bootstrap from a serialization format that -// contains this information, so we can remove this special-case code. This -// would involve defining a serialization format very similar to the existing -// protobuf format, but that contains more information about the wire type. -#define BEGIN_SUBMSG 100 +// All of the handlers registration in this file must be done using the +// low-level upb_register_typed_* interface, since we might not have a msgdef +// yet (in the case of bootstrapping). This makes it more laborious than it +// will be for real users. // upb_deflist: A little dynamic array for storing a growing list of upb_defs. typedef struct { @@ -257,6 +250,7 @@ struct _upb_defbuilder { upb_defbuilder_frame stack[UPB_MAX_TYPE_DEPTH]; int stack_len; upb_status status; + upb_symtab *symtab; uint32_t number; upb_string *name; @@ -267,23 +261,23 @@ struct _upb_defbuilder { upb_fielddef *f; }; -typedef struct _upb_defbuilder upb_defbuilder; // Forward declares for top-level file descriptors. -static void upb_msgdef_register_DescriptorProto(upb_defbuilder *b, upb_handlers *h); -static void upb_enumdef_register_EnumDescriptorProto(upb_defbuilder *b, - upb_handlers *h); - +static void upb_msgdef_register_DescriptorProto(upb_handlers *h); +static void upb_enumdef_register_EnumDescriptorProto(upb_handlers *h); -static void upb_defbuilder_init(upb_defbuilder *b) { +upb_defbuilder *upb_defbuilder_new(upb_symtab *s) { + upb_defbuilder *b = malloc(sizeof(*b)); upb_deflist_init(&b->defs); upb_status_init(&b->status); + b->symtab = s; b->stack_len = 0; b->name = NULL; b->default_string = NULL; + return b; } -static void upb_defbuilder_uninit(upb_defbuilder *b) { +static void upb_defbuilder_free(upb_defbuilder *b) { upb_string_unref(b->name); upb_status_uninit(&b->status); upb_deflist_uninit(&b->defs); @@ -292,6 +286,7 @@ static void upb_defbuilder_uninit(upb_defbuilder *b) { upb_defbuilder_frame *f = &b->stack[--b->stack_len]; upb_string_unref(f->name); } + free(b); } static upb_msgdef *upb_defbuilder_top(upb_defbuilder *b) { @@ -332,89 +327,67 @@ static upb_flow_t upb_defbuilder_FileDescriptorProto_startmsg(void *_b) { return UPB_CONTINUE; } -static upb_flow_t upb_defbuilder_FileDescriptorProto_endmsg(void *_b) { +static void upb_defbuilder_FileDescriptorProto_endmsg(void *_b, + upb_status *status) { + (void)status; upb_defbuilder *b = _b; upb_defbuilder_endcontainer(b); - return UPB_CONTINUE; } -static upb_flow_t upb_defbuilder_FileDescriptorProto_value(void *_b, - upb_fielddef *f, - upb_value val) { +static upb_flow_t upb_defbuilder_FileDescriptorProto_package(void *_b, + upb_value fval, + upb_value val) { + (void)fval; upb_defbuilder *b = _b; - switch(f->number) { - case GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_PACKAGE_FIELDNUM: - upb_defbuilder_setscopename(b, upb_value_getstr(val)); - break; - case GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_MESSAGE_TYPE_FIELDNUM: - case GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_ENUM_TYPE_FIELDNUM: - return BEGIN_SUBMSG; - } + upb_defbuilder_setscopename(b, upb_value_getstr(val)); return UPB_CONTINUE; } -static upb_flow_t upb_defbuilder_FileDescriptorProto_startsubmsg( - void *_b, upb_fielddef *f, upb_handlers *h) { - upb_defbuilder *b = _b; - switch(f->number) { - case GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_MESSAGE_TYPE_FIELDNUM: - upb_msgdef_register_DescriptorProto(b, h); - return UPB_DELEGATE; - case GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_ENUM_TYPE_FIELDNUM: - upb_enumdef_register_EnumDescriptorProto(b, h); - return UPB_DELEGATE; - default: - // TODO: services and extensions. - return UPB_SKIPSUBMSG; - } -} +static void upb_defbuilder_register_FileDescriptorProto(upb_handlers *h) { + upb_register_startend(h, upb_defbuilder_FileDescriptorProto_startmsg, + upb_defbuilder_FileDescriptorProto_endmsg); + upb_register_typed_value(h, + GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_PACKAGE__FIELDNUM, + GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_PACKAGE__FIELDTYPE, + &upb_defbuilder_FileDescriptorProto_package, UPB_NO_VALUE); + + upb_handlers_typed_push(h, + GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_MESSAGE_TYPE__FIELDNUM, + GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_MESSAGE_TYPE__FIELDTYPE); + upb_msgdef_register_DescriptorProto(h); + upb_handlers_typed_pop(h); -static void upb_defbuilder_register_FileDescriptorProto(upb_defbuilder *b, - upb_handlers *h) { - static upb_handlerset handlers = { - &upb_defbuilder_FileDescriptorProto_startmsg, - &upb_defbuilder_FileDescriptorProto_endmsg, - &upb_defbuilder_FileDescriptorProto_value, - &upb_defbuilder_FileDescriptorProto_startsubmsg, - }; - upb_register_handlerset(h, &handlers); - upb_set_handler_closure(h, b, &b->status); + upb_handlers_typed_push(h, + GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_ENUM_TYPE__FIELDNUM, + GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_ENUM_TYPE__FIELDTYPE); + upb_enumdef_register_EnumDescriptorProto(h); + upb_handlers_typed_pop(h); + + // TODO: services and extensions. } // Handlers for google.protobuf.FileDescriptorSet. -static upb_flow_t upb_defbuilder_FileDescriptorSet_value(void *b, - upb_fielddef *f, - upb_value val) { - (void)b; - (void)val; - switch(f->number) { - case GOOGLE_PROTOBUF_FILEDESCRIPTORSET_FILE_FIELDNUM: - return BEGIN_SUBMSG; - } - return UPB_CONTINUE; -} +static bool upb_symtab_add_defs(upb_symtab *s, upb_def **defs, int num_defs, + bool allow_redef, upb_status *status); -static upb_flow_t upb_defbuilder_FileDescriptorSet_startsubmsg( - void *_b, upb_fielddef *f, upb_handlers *h) { +static void upb_defbuilder_FileDescriptorSet_onendmsg(void *_b, + upb_status *status) { upb_defbuilder *b = _b; - switch(f->number) { - case GOOGLE_PROTOBUF_FILEDESCRIPTORSET_FILE_FIELDNUM: - upb_defbuilder_register_FileDescriptorProto(b, h); - return UPB_DELEGATE; - } - return UPB_SKIPSUBMSG; + if (upb_ok(status)) + upb_symtab_add_defs(b->symtab, b->defs.defs, b->defs.len, false, status); + upb_defbuilder_free(b); } -static void upb_defbuilder_register_FileDescriptorSet( - upb_defbuilder *b, upb_handlers *h) { - static upb_handlerset handlers = { - NULL, // startmsg - NULL, // endmsg - &upb_defbuilder_FileDescriptorSet_value, - &upb_defbuilder_FileDescriptorSet_startsubmsg, - }; - upb_register_handlerset(h, &handlers); - upb_set_handler_closure(h, b, &b->status); +static void upb_defbuilder_register_FileDescriptorSet(upb_handlers *h) { + upb_register_startend(h, NULL, upb_defbuilder_FileDescriptorSet_onendmsg); + upb_handlers_typed_push(h, + GOOGLE_PROTOBUF_FILEDESCRIPTORSET_FILE__FIELDNUM, + GOOGLE_PROTOBUF_FILEDESCRIPTORSET_FILE__FIELDTYPE); + upb_defbuilder_register_FileDescriptorProto(h); + upb_handlers_typed_pop(h); +} +void upb_defbuilder_reghandlers(upb_handlers *h) { + upb_defbuilder_register_FileDescriptorSet(h); } @@ -469,31 +442,33 @@ static upb_flow_t upb_enumdef_EnumValueDescriptorProto_startmsg(void *_b) { return UPB_CONTINUE; } -static upb_flow_t upb_enumdef_EnumValueDescriptorProto_value(void *_b, - upb_fielddef *f, - upb_value val) { +static upb_flow_t upb_enumdef_EnumValueDescriptorProto_name(void *_b, + upb_value fval, + upb_value val) { + (void)fval; upb_defbuilder *b = _b; - switch(f->number) { - case GOOGLE_PROTOBUF_ENUMVALUEDESCRIPTORPROTO_NAME_FIELDNUM: - upb_string_unref(b->name); - b->name = upb_string_getref(upb_value_getstr(val)); - b->saw_name = true; - break; - case GOOGLE_PROTOBUF_ENUMVALUEDESCRIPTORPROTO_NUMBER_FIELDNUM: - b->number = upb_value_getint32(val); - b->saw_number = true; - break; - default: - break; - } + upb_string_unref(b->name); + b->name = upb_string_getref(upb_value_getstr(val)); + b->saw_name = true; return UPB_CONTINUE; } -static upb_flow_t upb_enumdef_EnumValueDescriptorProto_endmsg(void *_b) { +static upb_flow_t upb_enumdef_EnumValueDescriptorProto_number(void *_b, + upb_value fval, + upb_value val) { + (void)fval; + upb_defbuilder *b = _b; + b->number = upb_value_getint32(val); + b->saw_number = true; + return UPB_CONTINUE; +} + +static void upb_enumdef_EnumValueDescriptorProto_endmsg(void *_b, + upb_status *status) { upb_defbuilder *b = _b; if(!b->saw_number || !b->saw_name) { - upb_seterr(&b->status, UPB_ERROR, "Enum value missing name or number."); - return UPB_BREAK; + upb_seterr(status, UPB_ERROR, "Enum value missing name or number."); + return; } upb_enumdef *e = upb_downcast_enumdef(upb_defbuilder_last(b)); if (upb_inttable_count(&e->iton) == 0) { @@ -509,18 +484,19 @@ static upb_flow_t upb_enumdef_EnumValueDescriptorProto_endmsg(void *_b) { // table. strtables can ref their keys, but the inttable doesn't know that // the value is a string. b->name = NULL; - return UPB_CONTINUE; } -static void upb_enumdef_register_EnumValueDescriptorProto(upb_defbuilder *b, - upb_handlers *h) { - static upb_handlerset handlers = { - &upb_enumdef_EnumValueDescriptorProto_startmsg, - &upb_enumdef_EnumValueDescriptorProto_endmsg, - &upb_enumdef_EnumValueDescriptorProto_value, - }; - upb_register_handlerset(h, &handlers); - upb_set_handler_closure(h, b, &b->status); +static void upb_enumdef_register_EnumValueDescriptorProto(upb_handlers *h) { + upb_register_startend(h, upb_enumdef_EnumValueDescriptorProto_startmsg, + upb_enumdef_EnumValueDescriptorProto_endmsg); + upb_register_typed_value(h, + GOOGLE_PROTOBUF_ENUMVALUEDESCRIPTORPROTO_NAME__FIELDNUM, + GOOGLE_PROTOBUF_ENUMVALUEDESCRIPTORPROTO_NAME__FIELDTYPE, + &upb_enumdef_EnumValueDescriptorProto_name, UPB_NO_VALUE); + upb_register_typed_value(h, + GOOGLE_PROTOBUF_ENUMVALUEDESCRIPTORPROTO_NUMBER__FIELDNUM, + GOOGLE_PROTOBUF_ENUMVALUEDESCRIPTORPROTO_NUMBER__FIELDTYPE, + &upb_enumdef_EnumValueDescriptorProto_number, UPB_NO_VALUE); } // google.protobuf.EnumDescriptorProto. @@ -534,61 +510,43 @@ static upb_flow_t upb_enumdef_EnumDescriptorProto_startmsg(void *_b) { return UPB_CONTINUE; } -static upb_flow_t upb_enumdef_EnumDescriptorProto_endmsg(void *_b) { +static void upb_enumdef_EnumDescriptorProto_endmsg(void *_b, upb_status *status) { upb_defbuilder *b = _b; upb_enumdef *e = upb_downcast_enumdef(upb_defbuilder_last(b)); if (upb_defbuilder_last((upb_defbuilder*)_b)->fqname == NULL) { - upb_seterr(&b->status, UPB_ERROR, "Enum had no name."); - return UPB_BREAK; + upb_seterr(status, UPB_ERROR, "Enum had no name."); + return; } if (upb_inttable_count(&e->iton) == 0) { - upb_seterr(&b->status, UPB_ERROR, "Enum had no values."); - return UPB_BREAK; + upb_seterr(status, UPB_ERROR, "Enum had no values."); + return; } - return UPB_CONTINUE; } -static upb_flow_t upb_enumdef_EnumDescriptorProto_value(void *_b, - upb_fielddef *f, - upb_value val) { +static upb_flow_t upb_enumdef_EnumDescriptorProto_name(void *_b, + upb_value fval, + upb_value val) { + (void)fval; upb_defbuilder *b = _b; - switch(f->number) { - case GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_NAME_FIELDNUM: { - upb_enumdef *e = upb_downcast_enumdef(upb_defbuilder_last(b)); - upb_string_unref(e->base.fqname); - e->base.fqname = upb_string_getref(upb_value_getstr(val)); - return UPB_CONTINUE; - } - case GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_VALUE_FIELDNUM: - return BEGIN_SUBMSG; - default: - return UPB_CONTINUE; - } + upb_enumdef *e = upb_downcast_enumdef(upb_defbuilder_last(b)); + upb_string_unref(e->base.fqname); + e->base.fqname = upb_string_getref(upb_value_getstr(val)); + return UPB_CONTINUE; } -static upb_flow_t upb_enumdef_EnumDescriptorProto_startsubmsg(void *_b, - upb_fielddef *f, - upb_handlers *h) { - upb_defbuilder *b = _b; - switch(f->number) { - case GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_VALUE_FIELDNUM: - upb_enumdef_register_EnumValueDescriptorProto(b, h); - return UPB_DELEGATE; - default: - return UPB_SKIPSUBMSG; - } -} +static void upb_enumdef_register_EnumDescriptorProto(upb_handlers *h) { + upb_register_startend(h, &upb_enumdef_EnumDescriptorProto_startmsg, + &upb_enumdef_EnumDescriptorProto_endmsg); + upb_register_typed_value(h, + GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_NAME__FIELDNUM, + GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_NAME__FIELDTYPE, + &upb_enumdef_EnumDescriptorProto_name, UPB_NO_VALUE); -static void upb_enumdef_register_EnumDescriptorProto(upb_defbuilder *b, - upb_handlers *h) { - static upb_handlerset handlers = { - &upb_enumdef_EnumDescriptorProto_startmsg, - &upb_enumdef_EnumDescriptorProto_endmsg, - &upb_enumdef_EnumDescriptorProto_value, - &upb_enumdef_EnumDescriptorProto_startsubmsg, - }; - upb_register_handlerset(h, &handlers); - upb_set_handler_closure(h, b, &b->status); + upb_handlers_typed_push(h, + GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_VALUE__FIELDNUM, + GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_VALUE__FIELDTYPE); + upb_enumdef_register_EnumValueDescriptorProto(h); + upb_handlers_typed_pop(h); } upb_enum_iter upb_enum_begin(upb_enumdef *e) { @@ -650,7 +608,7 @@ static bool upb_fielddef_resolve(upb_fielddef *f, upb_def *def, upb_status *s) { upb_string *str = upb_value_getstr(f->default_value); assert(str); // Should point to either a real default or the empty string. upb_enumdef *e = upb_downcast_enumdef(f->def); - upb_enumval_t val; + upb_enumval_t val = 0; if (str == upb_emptystring()) { upb_value_setint32(&f->default_value, e->default_value); } else { @@ -776,7 +734,7 @@ static bool upb_fielddef_setdefault(upb_string *dstr, upb_value *d, int type) { return success; } -static upb_flow_t upb_fielddef_endmsg(void *_b) { +static void upb_fielddef_endmsg(void *_b, upb_status *status) { upb_defbuilder *b = _b; upb_fielddef *f = b->f; // TODO: verify that all required fields were present. @@ -795,53 +753,87 @@ static upb_flow_t upb_fielddef_endmsg(void *_b) { if (!upb_fielddef_setdefault(dstr, &f->default_value, f->type)) { // We don't worry too much about giving a great error message since the // compiler should have ensured this was correct. - upb_seterr(&b->status, UPB_ERROR, "Error converting default value."); - return UPB_BREAK; + upb_seterr(status, UPB_ERROR, "Error converting default value."); + return; } +} + +static upb_flow_t upb_fielddef_ontype(void *_b, upb_value fval, upb_value val) { + (void)fval; + upb_defbuilder *b = _b; + b->f->type = upb_value_getint32(val); return UPB_CONTINUE; } -static upb_flow_t upb_fielddef_value(void *_b, upb_fielddef *f, upb_value val) { +static upb_flow_t upb_fielddef_onlabel(void *_b, upb_value fval, upb_value val) { + (void)fval; upb_defbuilder *b = _b; - switch(f->number) { - case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_FIELDNUM: - b->f->type = upb_value_getint32(val); - break; - case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_LABEL_FIELDNUM: - b->f->label = upb_value_getint32(val); - break; - case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_NUMBER_FIELDNUM: - b->f->number = upb_value_getint32(val); - break; - case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_NAME_FIELDNUM: - upb_string_unref(b->f->name); - b->f->name = upb_string_getref(upb_value_getstr(val)); - break; - case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_NAME_FIELDNUM: { - upb_def_unref(b->f->def); - b->f->def = UPB_UPCAST(upb_unresolveddef_new(upb_value_getstr(val))); - b->f->owned = true; - break; - } - case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_DEFAULT_VALUE_FIELDNUM: - // Have to convert from string to the correct type, but we might not know - // the type yet. - upb_string_unref(b->default_string); - b->default_string = upb_string_getref(upb_value_getstr(val)); - break; - } + b->f->label = upb_value_getint32(val); + return UPB_CONTINUE; +} + +static upb_flow_t upb_fielddef_onnumber(void *_b, upb_value fval, upb_value val) { + (void)fval; + upb_defbuilder *b = _b; + b->f->number = upb_value_getint32(val); + return UPB_CONTINUE; +} + +static upb_flow_t upb_fielddef_onname(void *_b, upb_value fval, upb_value val) { + (void)fval; + upb_defbuilder *b = _b; + upb_string_unref(b->f->name); + b->f->name = upb_string_getref(upb_value_getstr(val)); + return UPB_CONTINUE; +} + +static upb_flow_t upb_fielddef_ontypename(void *_b, upb_value fval, + upb_value val) { + (void)fval; + upb_defbuilder *b = _b; + upb_def_unref(b->f->def); + b->f->def = UPB_UPCAST(upb_unresolveddef_new(upb_value_getstr(val))); + b->f->owned = true; + return UPB_CONTINUE; +} + +static upb_flow_t upb_fielddef_ondefaultval(void *_b, upb_value fval, + upb_value val) { + (void)fval; + upb_defbuilder *b = _b; + // Have to convert from string to the correct type, but we might not know the + // type yet. + upb_string_unref(b->default_string); + b->default_string = upb_string_getref(upb_value_getstr(val)); return UPB_CONTINUE; } -static void upb_fielddef_register_FieldDescriptorProto(upb_defbuilder *b, - upb_handlers *h) { - static upb_handlerset handlers = { - &upb_fielddef_startmsg, - &upb_fielddef_endmsg, - &upb_fielddef_value, - }; - upb_register_handlerset(h, &handlers); - upb_set_handler_closure(h, b, &b->status); +static void upb_fielddef_register_FieldDescriptorProto(upb_handlers *h) { + upb_register_startend(h, upb_fielddef_startmsg, upb_fielddef_endmsg); + upb_register_typed_value(h, + GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE__FIELDNUM, + GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE__FIELDTYPE, + &upb_fielddef_ontype, UPB_NO_VALUE); + upb_register_typed_value(h, + GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_LABEL__FIELDNUM, + GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_LABEL__FIELDTYPE, + &upb_fielddef_onlabel, UPB_NO_VALUE); + upb_register_typed_value(h, + GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_NUMBER__FIELDNUM, + GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_NUMBER__FIELDTYPE, + &upb_fielddef_onnumber, UPB_NO_VALUE); + upb_register_typed_value(h, + GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_NAME__FIELDNUM, + GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_NAME__FIELDTYPE, + &upb_fielddef_onname, UPB_NO_VALUE); + upb_register_typed_value(h, + GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_NAME__FIELDNUM, + GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_NAME__FIELDTYPE, + &upb_fielddef_ontypename, UPB_NO_VALUE); + upb_register_typed_value(h, + GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_DEFAULT_VALUE__FIELDNUM, + GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_DEFAULT_VALUE__FIELDTYPE, + &upb_fielddef_ondefaultval, UPB_NO_VALUE); } @@ -874,12 +866,12 @@ static upb_flow_t upb_msgdef_startmsg(void *_b) { return UPB_CONTINUE; } -static upb_flow_t upb_msgdef_endmsg(void *_b) { +static void upb_msgdef_endmsg(void *_b, upb_status *status) { upb_defbuilder *b = _b; upb_msgdef *m = upb_defbuilder_top(b); if(!m->base.fqname) { - upb_seterr(&b->status, UPB_ERROR, "Encountered message with no name."); - return UPB_BREAK; + upb_seterr(status, UPB_ERROR, "Encountered message with no name."); + return; } upb_inttable_compact(&m->itof); @@ -944,58 +936,44 @@ static upb_flow_t upb_msgdef_endmsg(void *_b) { } upb_defbuilder_endcontainer(b); - return UPB_CONTINUE; } -static upb_flow_t upb_msgdef_value(void *_b, upb_fielddef *f, upb_value val) { +static upb_flow_t upb_msgdef_onname(void *_b, upb_value fval, upb_value val) { + (void)fval; upb_defbuilder *b = _b; - switch(f->number) { - case GOOGLE_PROTOBUF_DESCRIPTORPROTO_NAME_FIELDNUM: { - assert(val.type == UPB_TYPE(STRING)); - upb_msgdef *m = upb_defbuilder_top(b); - upb_string_unref(m->base.fqname); - m->base.fqname = upb_string_getref(upb_value_getstr(val)); - upb_defbuilder_setscopename(b, upb_value_getstr(val)); - return UPB_CONTINUE; - } - case GOOGLE_PROTOBUF_DESCRIPTORPROTO_FIELD_FIELDNUM: - case GOOGLE_PROTOBUF_DESCRIPTORPROTO_NESTED_TYPE_FIELDNUM: - case GOOGLE_PROTOBUF_DESCRIPTORPROTO_ENUM_TYPE_FIELDNUM: - return BEGIN_SUBMSG; - default: - // TODO: extensions. - return UPB_CONTINUE; - } + assert(val.type == UPB_TYPE(STRING)); + upb_msgdef *m = upb_defbuilder_top(b); + upb_string_unref(m->base.fqname); + m->base.fqname = upb_string_getref(upb_value_getstr(val)); + upb_defbuilder_setscopename(b, upb_value_getstr(val)); + return UPB_CONTINUE; } -static upb_flow_t upb_msgdef_startsubmsg(void *_b, upb_fielddef *f, - upb_handlers *h) { - upb_defbuilder *b = _b; - switch(f->number) { - case GOOGLE_PROTOBUF_DESCRIPTORPROTO_FIELD_FIELDNUM: - upb_fielddef_register_FieldDescriptorProto(b, h); - return UPB_DELEGATE; - case GOOGLE_PROTOBUF_DESCRIPTORPROTO_NESTED_TYPE_FIELDNUM: - upb_msgdef_register_DescriptorProto(b, h); - return UPB_DELEGATE; - case GOOGLE_PROTOBUF_DESCRIPTORPROTO_ENUM_TYPE_FIELDNUM: - upb_enumdef_register_EnumDescriptorProto(b, h); - return UPB_DELEGATE; - default: - return UPB_SKIPSUBMSG; - } -} +static void upb_msgdef_register_DescriptorProto(upb_handlers *h) { + upb_register_startend(h, &upb_msgdef_startmsg, &upb_msgdef_endmsg); + upb_register_typed_value(h, + GOOGLE_PROTOBUF_DESCRIPTORPROTO_NAME__FIELDNUM, + GOOGLE_PROTOBUF_DESCRIPTORPROTO_NAME__FIELDTYPE, + &upb_msgdef_onname, UPB_NO_VALUE); + + upb_handlers_typed_push(h, + GOOGLE_PROTOBUF_DESCRIPTORPROTO_FIELD__FIELDNUM, + GOOGLE_PROTOBUF_DESCRIPTORPROTO_FIELD__FIELDTYPE); + upb_fielddef_register_FieldDescriptorProto(h); + upb_handlers_typed_pop(h); + + // DescriptorProto is self-recursive, so we must link the definition. + upb_handlers_typed_link(h, + GOOGLE_PROTOBUF_DESCRIPTORPROTO_NESTED_TYPE__FIELDNUM, + GOOGLE_PROTOBUF_DESCRIPTORPROTO_NESTED_TYPE__FIELDTYPE, 0); -static void upb_msgdef_register_DescriptorProto(upb_defbuilder *b, - upb_handlers *h) { - static upb_handlerset handlers = { - &upb_msgdef_startmsg, - &upb_msgdef_endmsg, - &upb_msgdef_value, - &upb_msgdef_startsubmsg, - }; - upb_register_handlerset(h, &handlers); - upb_set_handler_closure(h, b, &b->status); + upb_handlers_typed_push(h, + GOOGLE_PROTOBUF_DESCRIPTORPROTO_ENUM_TYPE__FIELDNUM, + GOOGLE_PROTOBUF_DESCRIPTORPROTO_ENUM_TYPE__FIELDTYPE); + upb_enumdef_register_EnumDescriptorProto(h); + upb_handlers_typed_pop(h); + + // TODO: extensions. } static void upb_msgdef_free(upb_msgdef *m) @@ -1185,8 +1163,8 @@ bool upb_resolverefs(upb_strtable *tmptab, upb_strtable *symtab, // indicating whether the new defs can overwrite existing defs in the symtab, // attempts to add the given defs to the symtab. The whole operation either // succeeds or fails. Ownership of "defs" and "exts" is taken. -bool upb_symtab_add_defs(upb_symtab *s, upb_def **defs, int num_defs, - bool allow_redef, upb_status *status) +static bool upb_symtab_add_defs(upb_symtab *s, upb_def **defs, int num_defs, + bool allow_redef, upb_status *status) { upb_rwlock_wrlock(&s->lock); @@ -1325,232 +1303,3 @@ upb_def *upb_symtab_resolve(upb_symtab *s, upb_string *base, upb_string *symbol) upb_rwlock_unlock(&s->lock); return ret; } - -void upb_symtab_addfds(upb_symtab *s, upb_src *src, upb_status *status) -{ - upb_defbuilder b; - upb_defbuilder_init(&b); - upb_handlers handlers; - upb_handlers_init(&handlers); - upb_defbuilder_register_FileDescriptorSet(&b, &handlers); - upb_src_sethandlers(src, &handlers); - upb_src_run(src, status); - if (upb_ok(status)) - upb_symtab_add_defs(s, b.defs.defs, b.defs.len, false, status); - upb_defbuilder_uninit(&b); - upb_handlers_uninit(&handlers); -} - - -/* upb_baredecoder ************************************************************/ - -// upb_baredecoder is a upb_src that can parse a subset of the protocol buffer -// binary format. It is only used for bootstrapping. It can parse without -// having a upb_msgdef, which is why it is useful for bootstrapping the first -// msgdef. On the downside, it does not support: -// -// * having its input span multiple upb_strings. -// * reading any field of the returned upb_fielddef's except f->number. -// * keeping a pointer to the upb_fielddef* and reading it later (the same -// upb_fielddef is reused over and over). -// * detecting errors in the input (we trust that our input is known-good). -// * skipping the rest of the submessage (UPB_SKIPSUBMSG). -// -// It also does not support any of the follow protobuf features: -// * packed fields. -// * groups. -// * zig-zag-encoded types like sint32 and sint64. -// -// Since it cannot tell the difference between submessages and strings, it -// always reports them as strings first, but if the value callback returns -// UPB_TREAT_AS_SUBMSG this signals to the baredecoder that it should be -// treated like a submessage instead. -// -// TODO: for bootstrapping we should define a slightly different wire format -// that includes enough information to know the precise integer types and -// that distinguishes between strings and submessages. This will allow -// us to get rid of the UPB_TREAT_AS_SUBMSG hack. It will also allow us -// to get rid of the upb_value_setraw() scheme, which would be more -// complicated to support on big-endian machines. - -typedef struct { - upb_src src; - upb_string *input; - upb_strlen_t offset; - upb_dispatcher dispatcher; -} upb_baredecoder; - -static uint64_t upb_baredecoder_readv64(upb_baredecoder *d) -{ - const uint8_t *start = (uint8_t*)upb_string_getrobuf(d->input) + d->offset; - const uint8_t *buf = start; - uint8_t last = 0x80; - uint64_t val = 0; - for(int bitpos = 0; (last & 0x80); buf++, bitpos += 7) - val |= ((uint64_t)((last = *buf) & 0x7F)) << bitpos; - d->offset += buf - start; - return val; -} - -static uint32_t upb_baredecoder_readv32(upb_baredecoder *d) -{ - return (uint32_t)upb_baredecoder_readv64(d); // Truncate. -} - -static uint64_t upb_baredecoder_readf64(upb_baredecoder *d) -{ - uint64_t val; - memcpy(&val, upb_string_getrobuf(d->input) + d->offset, 8); - d->offset += 8; - return val; -} - -static uint32_t upb_baredecoder_readf32(upb_baredecoder *d) -{ - uint32_t val; - memcpy(&val, upb_string_getrobuf(d->input) + d->offset, 4); - d->offset += 4; - return val; -} - -static void upb_baredecoder_sethandlers(upb_src *src, upb_handlers *handlers) { - upb_baredecoder *d = (upb_baredecoder*)src; - upb_dispatcher_reset(&d->dispatcher, handlers, false); -} - -static void upb_baredecoder_run(upb_src *src, upb_status *status) { - upb_baredecoder *d = (upb_baredecoder*)src; - assert(!upb_handlers_isempty(&d->dispatcher.top->handlers)); - upb_string *str = NULL; - upb_strlen_t stack[UPB_MAX_NESTING] = {UPB_STRLEN_MAX}; - upb_strlen_t *top = &stack[0]; - d->offset = 0; - -#define CHECK(x) if (x != UPB_CONTINUE && x != BEGIN_SUBMSG) goto err; - - CHECK(upb_dispatch_startmsg(&d->dispatcher)); - while(d->offset < upb_string_len(d->input)) { - uint32_t key = upb_baredecoder_readv64(d); - upb_fielddef f; - f.number = key >> 3; - upb_wire_type_t wt = key & 0x7; - if(wt == UPB_WIRE_TYPE_DELIMITED) { - uint32_t delim_len = upb_baredecoder_readv32(d); - // We don't know if it's a string or a submessage; deliver first as - // string. - upb_string_recycle(&str); - upb_string_substr(str, d->input, d->offset, delim_len); - upb_value v; - upb_value_setstr(&v, str); - upb_flow_t ret = upb_dispatch_value(&d->dispatcher, &f, v); - CHECK(ret); - if(ret == BEGIN_SUBMSG) { - // Should deliver as a submessage instead. - CHECK(upb_dispatch_startsubmsg(&d->dispatcher, &f)); - *(++top) = d->offset + delim_len; - } else { - d->offset += delim_len; - } - } else { - upb_value v; - switch(wt) { - case UPB_WIRE_TYPE_VARINT: - upb_value_setraw(&v, upb_baredecoder_readv64(d)); - break; - case UPB_WIRE_TYPE_64BIT: - upb_value_setraw(&v, upb_baredecoder_readf64(d)); - break; - case UPB_WIRE_TYPE_32BIT: - upb_value_setraw(&v, upb_baredecoder_readf32(d)); - break; - default: - assert(false); - abort(); - } - CHECK(upb_dispatch_value(&d->dispatcher, &f, v)); - } - // Detect end-of-submessage. - while(d->offset >= *top) { - CHECK(upb_dispatch_endsubmsg(&d->dispatcher, &f)); - d->offset = *(top--); - } - } - CHECK(upb_dispatch_endmsg(&d->dispatcher)); - upb_string_unref(str); - return; - -err: - upb_copyerr(status, d->dispatcher.top->handlers.status); - upb_string_unref(str); -} - -static upb_baredecoder *upb_baredecoder_new(upb_string *str) { - static upb_src_vtbl vtbl = { - &upb_baredecoder_sethandlers, - &upb_baredecoder_run, - }; - upb_baredecoder *d = malloc(sizeof(*d)); - upb_src_init(&d->src, &vtbl); - d->input = upb_string_getref(str); - d->offset = 0; - upb_dispatcher_init(&d->dispatcher); - return d; -} - -static void upb_baredecoder_free(upb_baredecoder *d) { - upb_string_unref(d->input); - free(d); -} - -static upb_src *upb_baredecoder_src(upb_baredecoder *d) { - return &d->src; -} - -static upb_symtab *descriptor_symtab = NULL; - -static void upb_free_descriptor_symtab() { - if (descriptor_symtab) { - // There should be no way for anyone to acquire a ref on this symtab. - assert(upb_atomic_only(&descriptor_symtab->refcount)); - _upb_symtab_free(descriptor_symtab); - descriptor_symtab = NULL; - } -} - -upb_def *upb_getdescriptordef(upb_string *str) { - // TODO: add locking. - if (descriptor_symtab == NULL) { - descriptor_symtab = upb_symtab_new(); - - static upb_string descriptor_str = - UPB_STATIC_STRING_ARRAY(descriptor_pb); - upb_baredecoder *decoder = upb_baredecoder_new(&descriptor_str); - upb_status status = UPB_STATUS_INIT; - upb_symtab_addfds(descriptor_symtab, upb_baredecoder_src(decoder), &status); - upb_baredecoder_free(decoder); - - if(!upb_ok(&status)) { - // upb itself is corrupt. - upb_printerr(&status); - upb_clearerr(&status); - abort(); - } - upb_status_uninit(&status); - - // As a sanity check, make sure that FileDescriptorSet was loaded. - upb_msgdef *def = upb_getfdsdef(); - if (!def) { - // upb itself is corrupt. - abort(); - } - upb_msgdef_unref(def); // The symtab already holds a ref on it. - atexit(upb_free_descriptor_symtab); - } - return upb_symtab_resolve( - descriptor_symtab, UPB_STRLIT("google.protobuf"), str); -} - -upb_msgdef *upb_getfdsdef() { - return upb_downcast_msgdef( - upb_getdescriptordef(UPB_STRLIT("FileDescriptorSet"))); -} diff --git a/src/upb_def.h b/src/upb_def.h index 4a2bcbd..9950c86 100644 --- a/src/upb_def.h +++ b/src/upb_def.h @@ -28,7 +28,6 @@ #define UPB_DEF_H_ #include "upb_atomic.h" -#include "upb_stream.h" #include "upb_table.h" #ifdef __cplusplus @@ -90,7 +89,7 @@ INLINE void upb_def_unref(upb_def *def) { // in the sense that it derives from upb_def. It cannot stand on its own; it // is either a field of a upb_msgdef or contained inside a upb_extensiondef. // It is also reference-counted. -typedef struct _upb_fielddef { +struct _upb_fielddef { uint8_t type; uint8_t label; // True if we own a ref on "def" (above). This is true unless this edge is @@ -111,11 +110,14 @@ typedef struct _upb_fielddef { // For the case of an enum or a submessage, points to the def for that type. upb_def *def; upb_atomic_refcount_t refcount; -} upb_fielddef; +}; // A variety of tests about the type of a field. +INLINE bool upb_issubmsgtype(upb_fieldtype_t type) { + return type == UPB_TYPE(GROUP) || type == UPB_TYPE(MESSAGE); +} INLINE bool upb_issubmsg(upb_fielddef *f) { - return f->type == UPB_TYPE(GROUP) || f->type == UPB_TYPE(MESSAGE); + return upb_issubmsgtype(f->type); } INLINE bool upb_isstring(upb_fielddef *f) { return f->type == UPB_TYPE(STRING) || f->type == UPB_TYPE(BYTES); @@ -225,6 +227,7 @@ INLINE upb_fielddef *upb_msg_iter_field(upb_msg_iter iter) { return ent->f; } + /* upb_enumdef ****************************************************************/ typedef int32_t upb_enumval_t; @@ -274,8 +277,8 @@ INLINE int32_t upb_enum_iter_number(upb_enum_iter iter) { /* upb_symtab *****************************************************************/ // A SymbolTable is where upb_defs live. It is empty when first constructed. -// Clients add definitions to the symtab by supplying unserialized or -// serialized descriptors (as defined in descriptor.proto). +// Clients add definitions to the symtab by supplying descriptors (as defined +// in descriptor.proto) via the upb_stream interface. struct _upb_symtab { upb_atomic_refcount_t refcount; upb_rwlock_t lock; // Protects all members except the refcount. @@ -284,7 +287,7 @@ struct _upb_symtab { }; typedef struct _upb_symtab upb_symtab; -// Initializes a upb_symtab. Contexts are not freed explicitly, but unref'd +// Initializes a upb_symtab. Symtabs are not freed explicitly, but unref'd // when the caller is done with them. upb_symtab *upb_symtab_new(void); void _upb_symtab_free(upb_symtab *s); // Must not be called directly! @@ -316,33 +319,22 @@ upb_def *upb_symtab_lookup(upb_symtab *s, upb_string *sym); // returned, otherwise only defs of the required type are returned. upb_def **upb_symtab_getdefs(upb_symtab *s, int *count, upb_deftype_t type); -// "fds" is a upb_src that will yield data from the -// google.protobuf.FileDescriptorSet message type. It is not necessary that -// the upb_def for FileDescriptorSet came from this symtab, but it must be -// compatible with the official descriptor.proto, as published by Google. -// -// upb_symtab_addfds() adds all the definitions from the given -// FileDescriptorSet and adds them to the symtab. status indicates whether the -// operation was successful or not, and the error message (if any). +// upb_defbuilder: For adding defs to the symtab. +// You allocate the defbuilder, which can handle a single descriptor. +// It will be freed automatically when the parse completes. +struct _upb_defbuilder; +typedef struct _upb_defbuilder upb_defbuilder; +struct _upb_handlers; + +// Allocates a new defbuilder that will add defs to the given symtab. +upb_defbuilder *upb_defbuilder_new(upb_symtab *s); + +// Registers handlers that will operate on a defbuilder to add the defs +// to the defbuilder's symtab. Will free itself when the parse finishes. // // TODO: should this allow redefinition? Either is possible, but which is // more useful? Maybe it should be an option. -void upb_symtab_addfds(upb_symtab *s, upb_src *desc, upb_status *status); - -// Returns a def corresponding to the given name, from descriptor.proto. -// upb internally bootstraps the defs in descriptor.proto, since they are -// necessary for loading other descriptors. The caller owns a ref on the -// returned def (which is NULL if no such def exists in descriptor.proto). -// -// The name should *not* be qualified by the package, to promote -// interoperability between the internal and external releases of Protocol -// Buffers (inside Google, these are in the "proto2" package, externally they -// are in "google.protobuf". -upb_def *upb_getdescriptordef(upb_string *str); - -// A convenience method for getting the upb_def for FileDescriptorProto. -// Return should never be NULL. -upb_msgdef *upb_getfdsdef(); +void upb_defbuilder_reghandlers(struct _upb_handlers *h); /* upb_def casts **************************************************************/ diff --git a/src/upb_encoder.h b/src/upb_encoder.h index e879b0b..d8d4b4f 100644 --- a/src/upb_encoder.h +++ b/src/upb_encoder.h @@ -14,7 +14,7 @@ #define UPB_ENCODER_H_ #include "upb.h" -#include "upb_srcsink.h" +#include "upb_stream.h" #ifdef __cplusplus extern "C" { diff --git a/src/upb_glue.c b/src/upb_glue.c index 86022d8..8194d4a 100644 --- a/src/upb_glue.c +++ b/src/upb_glue.c @@ -16,25 +16,18 @@ void upb_strtomsg(upb_string *str, upb_msg *msg, upb_msgdef *md, upb_stringsrc_init(&strsrc); upb_stringsrc_reset(&strsrc, str); - upb_decoder d; - upb_decoder_init(&d, md); - upb_decoder_reset(&d, upb_stringsrc_bytesrc(&strsrc)); - upb_src *src = upb_decoder_src(&d); - - upb_msgpopulator p; - upb_msgpopulator_init(&p); - upb_msgpopulator_reset(&p, msg, md); - upb_handlers h; - upb_handlers_init(&h); - upb_msgpopulator_register_handlers(&p, &h); - upb_src_sethandlers(src, &h); + upb_handlers_init(&h, md); + upb_msg_regdhandlers(&h); + + upb_decoder d; + upb_decoder_init(&d, &h); + upb_decoder_reset(&d, upb_stringsrc_bytesrc(&strsrc), msg); - upb_src_run(src, status); + upb_decoder_decode(&d, status); upb_stringsrc_uninit(&strsrc); upb_decoder_uninit(&d); - upb_msgpopulator_uninit(&p); upb_handlers_uninit(&h); } @@ -46,11 +39,12 @@ void upb_msgtotext(upb_string *str, upb_msg *msg, upb_msgdef *md, upb_textprinter *p = upb_textprinter_new(); upb_handlers h; - upb_handlers_init(&h); - upb_textprinter_reset(p, &h, upb_stringsink_bytesink(&strsink), single_line); + upb_handlers_init(&h, md); + upb_textprinter_reghandlers(&h); + upb_textprinter_reset(p, upb_stringsink_bytesink(&strsink), single_line); upb_status status = UPB_STATUS_INIT; - upb_msg_runhandlers(msg, md, &h, &status); + upb_msg_runhandlers(msg, md, &h, p, &status); // None of {upb_msg_runhandlers, upb_textprinter, upb_stringsink} should be // capable of returning an error. assert(upb_ok(&status)); @@ -66,13 +60,18 @@ void upb_parsedesc(upb_symtab *symtab, upb_string *str, upb_status *status) { upb_stringsrc_init(&strsrc); upb_stringsrc_reset(&strsrc, str); + upb_handlers h; + upb_handlers_init(&h, NULL); + upb_defbuilder_reghandlers(&h); + upb_decoder d; - upb_msgdef *fds_msgdef = upb_getfdsdef(); - upb_decoder_init(&d, fds_msgdef); - upb_decoder_reset(&d, upb_stringsrc_bytesrc(&strsrc)); + upb_decoder_init(&d, &h); + upb_defbuilder *b = upb_defbuilder_new(symtab); + upb_decoder_reset(&d, upb_stringsrc_bytesrc(&strsrc), b); - upb_symtab_addfds(symtab, upb_decoder_src(&d), status); + upb_decoder_decode(&d, status); + + upb_handlers_uninit(&h); upb_stringsrc_uninit(&strsrc); upb_decoder_uninit(&d); - upb_def_unref(UPB_UPCAST(fds_msgdef)); } diff --git a/src/upb_msg.c b/src/upb_msg.c index a3fd825..a9167e8 100644 --- a/src/upb_msg.c +++ b/src/upb_msg.c @@ -7,8 +7,6 @@ */ #include "upb_msg.h" -#include "upb_decoder.h" -#include "upb_strstream.h" static uint32_t upb_round_up_pow2(uint32_t v) { // http://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2 @@ -181,75 +179,66 @@ upb_value upb_msg_get(upb_msg *msg, upb_fielddef *f) { } static upb_flow_t upb_msg_dispatch(upb_msg *msg, upb_msgdef *md, - upb_dispatcher *d, upb_status *s); + upb_dispatcher *d); static upb_flow_t upb_msg_pushval(upb_value val, upb_fielddef *f, - upb_dispatcher *d, upb_status *s) { + upb_dispatcher *d, upb_handlers_fieldent *hf) { #define CHECK_FLOW(x) do { \ - flow = x; if (flow != UPB_CONTINUE) return flow; \ + upb_flow_t flow = x; if (flow != UPB_CONTINUE) return flow; \ } while(0) // For when a SKIP can be implemented just through an early return. #define CHECK_FLOW_LOCAL(x) do { \ - flow = x; \ + upb_flow_t flow = x; \ if (flow != UPB_CONTINUE) { \ if (flow == UPB_SKIPSUBMSG) flow = UPB_CONTINUE; \ - goto end; \ + return flow; \ } \ } while (0) - upb_flow_t flow; if (upb_issubmsg(f)) { upb_msg *msg = upb_value_getmsg(val); - CHECK_FLOW_LOCAL(upb_dispatch_startsubmsg(d, f)); - CHECK_FLOW_LOCAL(upb_msg_dispatch(msg, upb_downcast_msgdef(f->def), d, s)); - CHECK_FLOW(upb_dispatch_endsubmsg(d, f)); + CHECK_FLOW_LOCAL(upb_dispatch_startsubmsg(d, hf, 0)); + CHECK_FLOW_LOCAL(upb_msg_dispatch(msg, upb_downcast_msgdef(f->def), d)); + CHECK_FLOW(upb_dispatch_endsubmsg(d)); } else { - CHECK_FLOW(upb_dispatch_value(d, f, val)); + CHECK_FLOW(upb_dispatch_value(d, hf, val)); } - -end: - return flow; + return UPB_CONTINUE; } static upb_flow_t upb_msg_dispatch(upb_msg *msg, upb_msgdef *md, - upb_dispatcher *d, upb_status *s) { + upb_dispatcher *d) { upb_msg_iter i; - upb_flow_t flow; for(i = upb_msg_begin(md); !upb_msg_done(i); i = upb_msg_next(md, i)) { upb_fielddef *f = upb_msg_iter_field(i); if (!upb_msg_has(msg, f)) continue; + upb_handlers_fieldent *hf = upb_dispatcher_lookup(d, f->number); + if (!hf) continue; upb_value val = upb_msg_get(msg, f); if (upb_isarray(f)) { upb_array *arr = upb_value_getarr(val); for (uint32_t j = 0; j < upb_array_len(arr); ++j) { - CHECK_FLOW_LOCAL(upb_msg_pushval(upb_array_get(arr, f, j), f, d, s)); + CHECK_FLOW_LOCAL(upb_msg_pushval(upb_array_get(arr, f, j), f, d, hf)); } } else { - CHECK_FLOW_LOCAL(upb_msg_pushval(val, f, d, s)); + CHECK_FLOW_LOCAL(upb_msg_pushval(val, f, d, hf)); } } return UPB_CONTINUE; - -end: - // Need to copy/massage the error. - upb_copyerr(s, d->top->handlers.status); - if (upb_ok(s)) { - upb_seterr(s, UPB_ERROR, "Callback returned UPB_BREAK"); - } - return flow; #undef CHECK_FLOW #undef CHECK_FLOW_LOCAL } void upb_msg_runhandlers(upb_msg *msg, upb_msgdef *md, upb_handlers *h, - upb_status *status) { + void *closure, upb_status *status) { upb_dispatcher d; - upb_dispatcher_init(&d); - upb_dispatcher_reset(&d, h, true); + upb_dispatcher_init(&d, h, 0); - if (upb_dispatch_startmsg(&d) != UPB_CONTINUE) return; - if (upb_msg_dispatch(msg, md, &d, status) != UPB_CONTINUE) return; - if (upb_dispatch_endmsg(&d) != UPB_CONTINUE) return; + upb_dispatch_startmsg(&d, closure); + upb_msg_dispatch(msg, md, &d); + upb_dispatch_endmsg(&d, status); + + upb_dispatcher_uninit(&d); } static upb_valueptr upb_msg_getappendptr(upb_msg *msg, upb_fielddef *f) { @@ -283,7 +272,7 @@ static void upb_msg_appendval(upb_msg *msg, upb_fielddef *f, upb_value val) { // If you were using this to copy one upb_msg to another this would // allocate string objects whereas a upb_string_getref could have avoided // those allocations completely; if this is an issue, we could make it an - // option of the upb_msgpopulator which behavior is desired. + // option of the upb_msgsink which behavior is desired. upb_string *src = upb_value_getstr(val); upb_string_recycle(p.str); upb_string_substr(*p.str, src, 0, upb_string_len(src)); @@ -303,59 +292,28 @@ upb_msg *upb_msg_appendmsg(upb_msg *msg, upb_fielddef *f, upb_msgdef *msgdef) { } -/* upb_msgpopulator ***********************************************************/ - -void upb_msgpopulator_init(upb_msgpopulator *p) { - upb_status_init(&p->status); -} - -void upb_msgpopulator_reset(upb_msgpopulator *p, upb_msg *m, upb_msgdef *md) { - p->top = p->stack; - p->limit = p->stack + sizeof(p->stack); - p->top->msg = m; - p->top->msgdef = md; -} - -void upb_msgpopulator_uninit(upb_msgpopulator *p) { - upb_status_uninit(&p->status); -} +/* upb_msg dynhandlers *******************************************************/ -static upb_flow_t upb_msgpopulator_value(void *_p, upb_fielddef *f, upb_value val) { - upb_msgpopulator *p = _p; - upb_msg_appendval(p->top->msg, f, val); +static upb_flow_t upb_dmsgsink_value(void *_m, upb_value fval, upb_value val) { + upb_msg *m = _m; + upb_fielddef *f = upb_value_getfielddef(fval); + upb_msg_appendval(m, f, val); return UPB_CONTINUE; } -static upb_flow_t upb_msgpopulator_startsubmsg(void *_p, upb_fielddef *f, - upb_handlers *delegate_to) { - upb_msgpopulator *p = _p; - (void)delegate_to; - upb_msg *oldmsg = p->top->msg; - if (++p->top == p->limit) { - upb_seterr(&p->status, UPB_ERROR, "Exceeded maximum nesting"); - return UPB_BREAK; - } +static upb_sflow_t upb_dmsgsink_startsubmsg(void *_m, upb_value fval) { + upb_msg *m = _m; + upb_fielddef *f = upb_value_getfielddef(fval); upb_msgdef *msgdef = upb_downcast_msgdef(f->def); - p->top->msgdef = msgdef; - p->top->msg = upb_msg_appendmsg(oldmsg, f, msgdef); - return UPB_CONTINUE; -} - -static upb_flow_t upb_msgpopulator_endsubmsg(void *_p, upb_fielddef *f) { - (void)f; - upb_msgpopulator *p = _p; - --p->top; - return UPB_CONTINUE; + return UPB_CONTINUE_WITH(upb_msg_appendmsg(m, f, msgdef)); } -void upb_msgpopulator_register_handlers(upb_msgpopulator *p, upb_handlers *h) { - static upb_handlerset handlerset = { - NULL, // startmsg - NULL, // endmsg - &upb_msgpopulator_value, - &upb_msgpopulator_startsubmsg, - &upb_msgpopulator_endsubmsg, - }; - upb_register_handlerset(h, &handlerset); - upb_set_handler_closure(h, p, &p->status); +void upb_msg_regdhandlers(upb_handlers *h) { + upb_register_all(h, + NULL, // startmsg + NULL, // endmsg + &upb_dmsgsink_value, + &upb_dmsgsink_startsubmsg, + NULL, // endsubmsg + NULL); // unknown } diff --git a/src/upb_msg.h b/src/upb_msg.h index fd5750f..4895c4b 100644 --- a/src/upb_msg.h +++ b/src/upb_msg.h @@ -17,8 +17,7 @@ #ifndef UPB_MSG_H #define UPB_MSG_H -#include "upb.h" -#include "upb_def.h" +#include "upb_stream.h" #include #ifdef __cplusplus @@ -274,26 +273,16 @@ INLINE void upb_msg_clear(upb_msg *msg, upb_msgdef *md) { memset(msg->data, 0, md->set_flags_bytes); } -// A non-resumable upb_src that pushes the current contents of the message to -// the given handlers. +// Registers handlers for populating a msg for the given upb_msgdef. +// The upb_msg itself must be passed as the param to the src. +void upb_msg_reghandlers(upb_handlers *h, upb_msgdef *md); + +// Registers handlers that are suitable for populating a msg of *any* +// upb_msgdef ("dynamic" handlers). May be slower than upb_msg_reghandlers(). +void upb_msg_regdhandlers(upb_handlers *h); + void upb_msg_runhandlers(upb_msg *msg, upb_msgdef *md, upb_handlers *h, - upb_status *status); - -typedef struct { - upb_msg *msg; - upb_msgdef *msgdef; -} upb_msgpopulator_frame; - -typedef struct { - upb_msgpopulator_frame *top, *limit; - upb_status status; - upb_msgpopulator_frame stack[UPB_MAX_NESTING]; -} upb_msgpopulator; - -void upb_msgpopulator_init(upb_msgpopulator *p); -void upb_msgpopulator_uninit(upb_msgpopulator *p); -void upb_msgpopulator_reset(upb_msgpopulator *p, upb_msg *m, upb_msgdef *md); -void upb_msgpopulator_register_handlers(upb_msgpopulator *p, upb_handlers *h); + void *closure, upb_status *status); #ifdef __cplusplus } /* extern "C" */ diff --git a/src/upb_stdio.c b/src/upb_stdio.c index 8857677..b4f2fce 100644 --- a/src/upb_stdio.c +++ b/src/upb_stdio.c @@ -85,7 +85,6 @@ upb_stdio *upb_stdio_new() { }; static upb_bytesink_vtbl bytesink_vtbl = { - NULL, upb_stdio_putstr, upb_stdio_vprintf }; diff --git a/src/upb_stream.c b/src/upb_stream.c new file mode 100644 index 0000000..3634d5d --- /dev/null +++ b/src/upb_stream.c @@ -0,0 +1,328 @@ +/* + * upb - a minimalist implementation of protocol buffers. + * + * Copyright (c) 2011 Joshua Haberman. See LICENSE for details. + */ + +#include +#include "upb_stream.h" + + +/* upb_handlers ***************************************************************/ + +static upb_flow_t upb_startmsg_nop(void *closure) { + (void)closure; + return UPB_CONTINUE; +} + +static void upb_endmsg_nop(void *closure, upb_status *status) { + (void)closure; + (void)status; +} + +static upb_flow_t upb_value_nop(void *closure, upb_value fval, upb_value val) { + (void)closure; + (void)fval; + (void)val; + return UPB_CONTINUE; +} + +static upb_sflow_t upb_startsubmsg_nop(void *closure, upb_value fval) { + (void)fval; + return UPB_CONTINUE_WITH(closure); +} + +static upb_flow_t upb_endsubmsg_nop(void *closure, upb_value fval) { + (void)closure; + (void)fval; + return UPB_CONTINUE; +} + +static upb_flow_t upb_unknownval_nop(void *closure, upb_field_number_t fieldnum, + upb_value val) { + (void)closure; + (void)fieldnum; + (void)val; + return UPB_CONTINUE; +} + +static void upb_msgent_init(upb_handlers_msgent *e) { + upb_inttable_init(&e->fieldtab, 8, sizeof(upb_handlers_fieldent)); + e->startmsg = &upb_startmsg_nop; + e->endmsg = &upb_endmsg_nop; + e->unknownval = &upb_unknownval_nop; +} + +void upb_handlers_init(upb_handlers *h, upb_msgdef *md) { + h->msgs_len = 1; + h->msgs_size = 4; + h->msgs = malloc(h->msgs_size * sizeof(*h->msgs)); + h->top = &h->stack[0]; + h->limit = &h->stack[UPB_MAX_TYPE_DEPTH]; + h->toplevel_msgdef = md; + if (md) upb_msgdef_ref(md); + + h->top->msgent_index = 0; + h->top->msgdef = md; + h->msgent = &h->msgs[0]; + upb_msgent_init(h->msgent); +} + +void upb_handlers_uninit(upb_handlers *h) { + for (int i = 0; i < h->msgs_len; i++) upb_inttable_free(&h->msgs[i].fieldtab); + free(h->msgs); + upb_msgdef_unref(h->toplevel_msgdef); +} + +static upb_handlers_fieldent *upb_handlers_getorcreate_without_fval( + upb_handlers *h, upb_field_number_t fieldnum, upb_fieldtype_t type) { + upb_handlers_fieldent *f = + upb_inttable_lookup(&h->msgent->fieldtab, fieldnum); + if (!f) { + upb_wire_type_t native_wire_type = upb_types[type].native_wire_type; + upb_handlers_fieldent new_f = { + false, type, native_wire_type, -1, UPB_NO_VALUE, + {&upb_value_nop}, &upb_endsubmsg_nop}; + if (upb_issubmsgtype(type)) new_f.cb.startsubmsg = &upb_startsubmsg_nop; + upb_inttable_insert(&h->msgent->fieldtab, fieldnum, &new_f); + + f = upb_inttable_lookup(&h->msgent->fieldtab, fieldnum); + assert(f); + } + assert(f->type == type); + return f; +} + +static upb_handlers_fieldent *upb_handlers_getorcreate( + upb_handlers *h, upb_field_number_t fieldnum, + upb_fieldtype_t type, upb_value fval) { + upb_handlers_fieldent *f = + upb_handlers_getorcreate_without_fval(h, fieldnum, type); + f->fval = fval; + return f; +} + +void upb_register_startend(upb_handlers *h, upb_startmsg_handler_t startmsg, + upb_endmsg_handler_t endmsg) { + h->msgent->startmsg = startmsg ? startmsg : &upb_startmsg_nop; + h->msgent->endmsg = endmsg ? endmsg : &upb_endmsg_nop; +} + +// TODO: +// void upb_register_unknownval(upb_handlers *h, +// upb_unknownval_handler_t unknown); +// bool upb_handlers_link(upb_handlers *h, upb_fielddef *f); +// void upb_register_path_value(upb_handlers *h, const char *path, +// upb_value_handler_t value, upb_value fval); + +void upb_register_all(upb_handlers *h, upb_startmsg_handler_t start, + upb_endmsg_handler_t end, + upb_value_handler_t value, + upb_startsubmsg_handler_t startsubmsg, + upb_endsubmsg_handler_t endsubmsg, + upb_unknownval_handler_t unknown) { + upb_register_startend(h, start, end); + //upb_register_unknownval(h, unknown); + upb_msgdef *m = h->top->msgdef; + upb_msg_iter i; + for(i = upb_msg_begin(m); !upb_msg_done(i); i = upb_msg_next(m, i)) { + upb_fielddef *f = upb_msg_iter_field(i); + upb_value fval; + upb_value_setfielddef(&fval, f); + if (upb_issubmsg(f)) { + upb_handlers_push(h, f, startsubmsg, endsubmsg, fval, false); + upb_register_all(h, start, end, value, startsubmsg, endsubmsg, unknown); + upb_handlers_pop(h, f); + } else { + upb_register_value(h, f, value, fval); + } + } +} + +void upb_register_typed_value(upb_handlers *h, upb_field_number_t fieldnum, + upb_fieldtype_t type, upb_value_handler_t value, + upb_value fval) { + upb_handlers_getorcreate(h, fieldnum, type, fval)->cb.value = + value ? value : &upb_value_nop; +} + +void upb_register_value(upb_handlers *h, upb_fielddef *f, + upb_value_handler_t value, upb_value fval) { + assert(f->msgdef == h->top->msgdef); + upb_register_typed_value(h, f->number, f->type, value, fval); +} + +void upb_register_typed_submsg(upb_handlers *h, upb_field_number_t fieldnum, + upb_fieldtype_t type, + upb_startsubmsg_handler_t start, + upb_endsubmsg_handler_t end, + upb_value fval) { + upb_handlers_fieldent *f = upb_handlers_getorcreate(h, fieldnum, type, fval); + f->cb.startsubmsg = start ? start : &upb_startsubmsg_nop; + f->endsubmsg = end ? end : &upb_endsubmsg_nop; +} + +void upb_handlers_typed_link(upb_handlers *h, + upb_field_number_t fieldnum, + upb_fieldtype_t type, + int frames) { + assert(frames <= (h->top - h->stack)); + upb_handlers_fieldent *f = + upb_handlers_getorcreate_without_fval(h, fieldnum, type); + f->msgent_index = (h->top - frames)->msgent_index; +} + +void upb_handlers_typed_push(upb_handlers *h, upb_field_number_t fieldnum, + upb_fieldtype_t type) { + upb_handlers_fieldent *f = + upb_handlers_getorcreate_without_fval(h, fieldnum, type); + if (h->top == h->limit) abort(); // TODO: make growable. + ++h->top; + if (f->msgent_index == -1) { + // Need to push a new msgent. + if (h->msgs_size == h->msgs_len) { + h->msgs_size *= 2; + h->msgs = realloc(h->msgs, h->msgs_size * sizeof(*h->msgs)); + } + f->msgent_index = h->msgs_len++; + h->msgent = &h->msgs[f->msgent_index]; + upb_msgent_init(h->msgent); + } else { + h->msgent = &h->msgs[f->msgent_index]; + } + h->top->msgent_index = f->msgent_index; + if (h->toplevel_msgdef) { + upb_fielddef *f = upb_msgdef_itof((h->top - 1)->msgdef, fieldnum); + assert(f); + h->top->msgdef = upb_downcast_msgdef(f->def); + } +} + +void upb_handlers_push(upb_handlers *h, upb_fielddef *f, + upb_startsubmsg_handler_t start, + upb_endsubmsg_handler_t end, upb_value fval, + bool delegate) { + assert(f->msgdef == h->top->msgdef); + (void)delegate; // TODO + upb_register_typed_submsg(h, f->number, f->type, start, end, fval); + upb_handlers_typed_push(h, f->number, f->type); +} + +void upb_handlers_typed_pop(upb_handlers *h) { + assert(h->top > h->stack); + --h->top; + h->msgent = &h->msgs[h->top->msgent_index]; +} + +void upb_handlers_pop(upb_handlers *h, upb_fielddef *f) { + (void)f; // TODO: Check that this matches the corresponding push. + upb_handlers_typed_pop(h); +} + +/* upb_dispatcher *************************************************************/ + +static upb_handlers_fieldent toplevel_f = { + false, 0, 0, 0, // The one value that is actually read +#ifdef NDEBUG + {{0}}, +#else + {{0}, UPB_VALUETYPE_RAW}, +#endif + {NULL}, NULL}; + +void upb_dispatcher_init(upb_dispatcher *d, upb_handlers *h, + size_t top_end_offset) { + d->handlers = h; + for (int i = 0; i < h->msgs_len; i++) + upb_inttable_compact(&h->msgs[i].fieldtab); + d->stack[0].end_offset = top_end_offset; + d->stack[0].f = &toplevel_f; + upb_status_init(&d->status); +} + +void upb_dispatcher_reset(upb_dispatcher *d) { + d->msgent = &d->handlers->msgs[0]; + d->dispatch_table = &d->msgent->fieldtab; + d->current_depth = 0; + d->skip_depth = INT_MAX; + d->noframe_depth = INT_MAX; + d->delegated_depth = 0; + d->top = d->stack; + d->limit = &d->stack[UPB_MAX_NESTING]; +} + +void upb_dispatcher_uninit(upb_dispatcher *d) { + upb_status_uninit(&d->status); +} + +void upb_dispatcher_break(upb_dispatcher *d) { + assert(d->skip_depth == INT_MAX); + assert(d->noframe_depth == INT_MAX); + d->noframe_depth = d->current_depth; +} + +upb_flow_t upb_dispatch_startmsg(upb_dispatcher *d, void *closure) { + d->top->closure = closure; + upb_flow_t flow = d->msgent->startmsg(closure); + if (flow != UPB_CONTINUE) { + d->noframe_depth = d->current_depth + 1; + d->skip_depth = (flow == UPB_BREAK) ? d->delegated_depth : d->current_depth; + return UPB_SKIPSUBMSG; + } + return UPB_CONTINUE; +} + +void upb_dispatch_endmsg(upb_dispatcher *d, upb_status *status) { + assert(d->top == d->stack); + d->msgent->endmsg(d->top->closure, &d->status); + // TODO: should we avoid this copy by passing client's status obj to cbs? + upb_copyerr(status, &d->status); +} + +upb_flow_t upb_dispatch_startsubmsg(upb_dispatcher *d, + upb_dispatcher_field *f, + size_t userval) { + ++d->current_depth; + if (upb_dispatcher_skipping(d)) return UPB_SKIPSUBMSG; + upb_sflow_t sflow = f->cb.startsubmsg(d->top->closure, f->fval); + if (sflow.flow != UPB_CONTINUE) { + d->noframe_depth = d->current_depth; + d->skip_depth = (sflow.flow == UPB_BREAK) ? + d->delegated_depth : d->current_depth; + return UPB_SKIPSUBMSG; + } + + ++d->top; + if(d->top >= d->limit) { + upb_seterr(&d->status, UPB_ERROR, "Nesting too deep."); + d->noframe_depth = d->current_depth; + d->skip_depth = d->delegated_depth; + return UPB_SKIPSUBMSG; + } + d->top->f = f; + d->top->end_offset = userval; + d->top->closure = sflow.closure; + d->msgent = upb_handlers_getmsgent(d->handlers, f); + d->dispatch_table = &d->msgent->fieldtab; + return upb_dispatch_startmsg(d, d->top->closure); +} + +upb_flow_t upb_dispatch_endsubmsg(upb_dispatcher *d) { + upb_flow_t flow; + if (upb_dispatcher_noframe(d)) { + flow = UPB_SKIPSUBMSG; + } else { + assert(d->top > d->stack); + upb_dispatcher_field *old_f = d->top->f; + d->msgent->endmsg(d->top->closure, &d->status); + --d->top; + d->msgent = upb_handlers_getmsgent(d->handlers, d->top->f); + d->dispatch_table = &d->msgent->fieldtab; + d->noframe_depth = INT_MAX; + if (!upb_dispatcher_skipping(d)) d->skip_depth = INT_MAX; + // Deliver like a regular value. + flow = old_f->endsubmsg(d->top->closure, old_f->fval); + } + --d->current_depth; + return flow; +} diff --git a/src/upb_stream.h b/src/upb_stream.h index 34e2710..9221a6b 100644 --- a/src/upb_stream.h +++ b/src/upb_stream.h @@ -1,26 +1,12 @@ /* * upb - a minimalist implementation of protocol buffers. * - * This file defines four general-purpose streaming data interfaces. + * This file defines general-purpose streaming data interfaces: * * - upb_handlers: represents a set of callbacks, very much like in XML's SAX * API, that a client can register to do a streaming tree traversal over a * stream of structured protobuf data, without knowing where that data is - * coming from. There is only one upb_handlers type (it is not a virtual - * base class), but the object lets you register any set of handlers. - * - * The upb_handlers interface supports delegation: when entering a submessage, - * you can delegate to another set of upb_handlers instead of handling the - * submessage yourself. This allows upb_handlers objects to *compose* -- you - * can implement a set of upb_handlers without knowing or caring whether this - * is the top-level message or not. - * - * The other interfaces are the C equivalent of "virtual base classes" that - * anyone can implement: - * - * - upb_src: an interface that represents a source of streaming protobuf data. - * It lets you register a set of upb_handlers, and then call upb_src_run(), - * which pulls the protobuf data from somewhere and then calls the handlers. + * coming from. * * - upb_bytesrc: a pull interface for streams of bytes, basically an * abstraction of read()/fread(), but it avoids copies where possible. @@ -42,92 +28,149 @@ #ifndef UPB_STREAM_H #define UPB_STREAM_H +#include #include "upb.h" +#include "upb_def.h" #ifdef __cplusplus extern "C" { #endif -// Forward-declare. We can't include upb_def.h; it would be circular. -struct _upb_fielddef; - /* upb_handlers ***************************************************************/ -// upb_handlers define the interface by which a upb_src passes data to a -// upb_sink. +// A upb_handlers object is a table of callbacks that are bound to specific +// messages and fields. A consumer of data registers callbacks and then +// passes the upb_handlers object to the producer, which calls them at the +// appropriate times. -// Constants that a handler returns to indicate to its caller whether it should -// continue or not. +// All handlers except the endmsg handler return a value from this enum, to +// control whether parsing will continue or not. typedef enum { - // Caller should continue sending values to the sink. + // Data source should continue calling callbacks. UPB_CONTINUE = 0, - // Stop processing for now; check status for details. If no status was set, - // a generic error will be returned. If the error is resumable, it is not - // (yet) defined where processing will resume -- waiting for real-world - // examples of resumable decoders and resume-requiring clients. upb_src - // implementations that are not capable of resuming will override the return - // status to be non-resumable if a resumable status was set by the handlers. + // Halt processing permanently (in a non-resumable way). The endmsg handlers + // for any currently open messages will be called which can supply a more + // specific status message. If UPB_BREAK is returned from inside a delegated + // message, processing will continue normally in the containing message (though + // the containing message can inspect the returned status and choose to also + // return UPB_BREAK if it is not ok). UPB_BREAK, // Skips to the end of the current submessage (or if we are at the top - // level, skips to the end of the entire message). + // level, skips to the end of the entire message). In other words, it is + // like a UPB_BREAK that applies only to the current level. + // + // If you UPB_SKIPSUBMSG from a startmsg handler, the endmsg handler will + // be called to perform cleanup and return a status. Returning + // UPB_SKIPSUBMSG from a startsubmsg handler will *not* call the startmsg, + // endmsg, or endsubmsg handlers. UPB_SKIPSUBMSG, - // When returned from a startsubmsg handler, indicates that the submessage - // should be handled by a different set of handlers, which have been - // registered on the provided upb_handlers object. This allows upb_handlers - // objects to compose; a set of upb_handlers need not know whether it is the - // top-level message or a sub-message. May not be returned from any other - // callback. - // - // WARNING! The delegation API is slated for some significant changes. - // See: http://code.google.com/p/upb/issues/detail?id=6 - UPB_DELEGATE, + // TODO: Add UPB_SUSPEND, for resumable producers/consumers. } upb_flow_t; -// upb_handlers -struct _upb_handlers; +typedef struct _upb_sflow upb_sflow_t; +typedef upb_flow_t (*upb_startmsg_handler_t)(void *closure); +typedef void (*upb_endmsg_handler_t)(void *closure, upb_status *status); +typedef upb_flow_t (*upb_value_handler_t)( + void *closure, upb_value fval, upb_value val); +typedef upb_sflow_t (*upb_startsubmsg_handler_t)( + void *closure, upb_value fval); +typedef upb_flow_t (*upb_endsubmsg_handler_t)(void *closure, upb_value fval); +typedef upb_flow_t (*upb_unknownval_handler_t)( + void *closure, upb_field_number_t fieldnum, upb_value val); + +typedef struct { + bool junk; + upb_fieldtype_t type; + upb_wire_type_t native_wire_type; + // For upb_issubmsg(f) only, the index into the msgdef array of the submsg. + // -1 if unset (indicates that submsg should be skipped). + int32_t msgent_index; + upb_value fval; + union { + upb_value_handler_t value; + upb_startsubmsg_handler_t startsubmsg; + } cb; + upb_endsubmsg_handler_t endsubmsg; +} upb_handlers_fieldent; + +typedef struct { + upb_startmsg_handler_t startmsg; + upb_endmsg_handler_t endmsg; + upb_unknownval_handler_t unknownval; + // Maps field number -> upb_handlers_fieldent. + upb_inttable fieldtab; +} upb_handlers_msgent; + +typedef struct { + upb_msgdef *msgdef; + int msgent_index; +} upb_handlers_frame; + +struct _upb_handlers { + // Array of msgdefs, [0]=toplevel. + upb_handlers_msgent *msgs; + int msgs_len, msgs_size; + upb_msgdef *toplevel_msgdef; // We own a ref. + upb_handlers_msgent *msgent; + upb_handlers_frame stack[UPB_MAX_TYPE_DEPTH], *top, *limit; +}; typedef struct _upb_handlers upb_handlers; -typedef upb_flow_t (*upb_startmsg_handler_t)(void *closure); -typedef upb_flow_t (*upb_endmsg_handler_t)(void *closure); -typedef upb_flow_t (*upb_value_handler_t)(void *closure, - struct _upb_fielddef *f, - upb_value val); -typedef upb_flow_t (*upb_startsubmsg_handler_t)(void *closure, - struct _upb_fielddef *f, - upb_handlers *delegate_to); -typedef upb_flow_t (*upb_endsubmsg_handler_t)(void *closure, - struct _upb_fielddef *f); -typedef upb_flow_t (*upb_unknownval_handler_t)(void *closure, - upb_field_number_t fieldnum, - upb_value val); - -// An empty set of handlers, for convenient copy/paste: +// The handlers object takes a ref on md. md can be NULL iff the client calls +// only upb_*_typed_*() (only upb_symtab should do this). +void upb_handlers_init(upb_handlers *h, upb_msgdef *md); +void upb_handlers_uninit(upb_handlers *h); + +// The startsubmsg handler needs to also pass a closure to the submsg. +struct _upb_sflow { + upb_flow_t flow; + void *closure; +}; +INLINE upb_sflow_t UPB_SFLOW(upb_flow_t flow, void *closure) { + upb_sflow_t ret = {flow, closure}; + return ret; +} +#define UPB_CONTINUE_WITH(c) UPB_SFLOW(UPB_CONTINUE, c) +#define UPB_S_BREAK UPB_SFLOW(UPB_BREAK, NULL) + +// Each message can have its own set of handlers. Here are empty definitions +// of the handlers for convenient copy/paste. +// TODO: Should endsubmsg get a copy of the upb_status*, so it can decide what +// to do in the case of a delegated failure? // // static upb_flow_t startmsg(void *closure) { -// // Called when the top-level message begins. +// // Called when the message begins. "closure" was supplied by our caller. +// // "mval" is whatever was bound to this message at registration time (for +// // upb_register_all() it will be its upb_msgdef*). // return UPB_CONTINUE; // } // -// static upb_flow_t endmsg(void *closure) { -// // Called when the top-level message ends. -// return UPB_CONTINUE; +// static void endmsg(void *closure, upb_status *status) { +// // Called when processing of this top-level message ends, whether in +// // success or failure. "status" indicates the final status of processing, +// // and can also be modified in-place to update the final status. +// // +// // Since this callback is guaranteed to always be called eventually, it +// // can be used to free any resources that were allocated during processing. // } // -// static upb_flow_t value(void *closure, upb_fielddef *f, upb_value val) { -// // Called for every value in the stream. +// static upb_flow_t value(void *closure, upb_value fval, upb_value val) { +// // Called for every non-submessage value in the stream. "fval" contains +// // whatever value was bound to this field at registration type +// // (for upb_register_all(), this will be the field's upb_fielddef*). // return UPB_CONTINUE; // } // -// static upb_flow_t startsubmsg(void *closure, upb_fielddef *f, -// upb_handlers *delegate_to) { -// // Called when a submessage begins; can delegate by returning UPB_DELEGATE. -// return UPB_CONTINUE; +// static upb_sflow_t startsubmsg(void *closure, upb_value fval) { +// // Called when a submessage begins. The second element of the return +// // value is the closure for the submessage. +// return UPB_CONTINUE_WITH(closure); // } // -// static upb_flow_t endsubmsg(void *closure, upb_fielddef *f) { +// static upb_flow_t endsubmsg(void *closure, upb_value fval) { // // Called when a submessage ends. // return UPB_CONTINUE; // } @@ -137,91 +180,222 @@ typedef upb_flow_t (*upb_unknownval_handler_t)(void *closure, // // Called with an unknown value is encountered. // return UPB_CONTINUE; // } -// -// // Any handlers you don't need can be set to NULL. -// static upb_handlerset handlers = { -// startmsg, -// endmsg, -// value, -// startsubmsg, -// endsubmsg, -// unknownval, -// }; -typedef struct { - upb_startmsg_handler_t startmsg; - upb_endmsg_handler_t endmsg; - upb_value_handler_t value; - upb_startsubmsg_handler_t startsubmsg; - upb_endsubmsg_handler_t endsubmsg; - upb_unknownval_handler_t unknownval; -} upb_handlerset; -// Functions to register handlers on a upb_handlers object. -INLINE void upb_handlers_init(upb_handlers *h); -INLINE void upb_handlers_uninit(upb_handlers *h); -INLINE void upb_handlers_reset(upb_handlers *h); -INLINE bool upb_handlers_isempty(upb_handlers *h); -INLINE void upb_register_handlerset(upb_handlers *h, upb_handlerset *set); +// Functions to register the above handlers. +// TODO: as an optimization, we could special-case handlers that don't +// need fval, to avoid even generating the code that sets the argument. +// If a value does not have a handler registered and there is no unknownval +// handler, the value will be skipped. +void upb_register_startend(upb_handlers *h, upb_startmsg_handler_t startmsg, + upb_endmsg_handler_t endmsg); +void upb_register_value(upb_handlers *h, upb_fielddef *f, + upb_value_handler_t value, upb_value fval); +void upb_register_unknownval(upb_handlers *h, upb_unknownval_handler_t unknown); + +// To register handlers for a submessage, push the fielddef and pop it +// when you're done. This can be used to delegate a submessage to a +// different processing component which does not need to be aware whether +// it is at the top level or not. +void upb_handlers_push(upb_handlers *h, upb_fielddef *f, + upb_startsubmsg_handler_t start, + upb_endsubmsg_handler_t end, upb_value fval, + bool delegate); +void upb_handlers_pop(upb_handlers *h, upb_fielddef *f); + +// In the case where types are self-recursive or mutually recursive, you can +// use this function which will link a set of handlers to a set that is +// already on our stack. This allows us to handle a tree of arbitrary +// depth without having to register an arbitrary number of levels of handlers. +// Returns "true" if the given type is indeed on the stack already and was +// linked. +// +// If more than one message of this type is on the stack, it chooses the +// one that is deepest in the tree (if necessary, we could give the caller +// more control over this). +bool upb_handlers_link(upb_handlers *h, upb_fielddef *f); + +// Convenience function for registering the given handler for the given +// field path. This will overwrite any startsubmsg handlers that were +// previously registered along the path. These can be overwritten again +// later if desired. +// TODO: upb_register_path_submsg()? +void upb_register_path_value(upb_handlers *h, const char *path, + upb_value_handler_t value, upb_value fval); + +// Convenience function for registering a single set of handlers on every +// message in our hierarchy. mvals are bound to upb_msgdef* and fvals are +// bound to upb_fielddef*. Any of the handlers can be NULL. +void upb_register_all(upb_handlers *h, upb_startmsg_handler_t start, + upb_endmsg_handler_t end, + upb_value_handler_t value, + upb_startsubmsg_handler_t startsubmsg, + upb_endsubmsg_handler_t endsubmsg, + upb_unknownval_handler_t unknown); // TODO: for clients that want to increase efficiency by preventing bytesrcs // from automatically being converted to strings in the value callback. -// INLINE void upb_handlers_use_bytesrcs(bool use_bytesrcs); - -// The closure will be passed to every handler. The status will be read by the -// upb_src immediately after a handler has returned UPB_BREAK and used as the -// overall upb_src status; it will not be referenced at any other time. -INLINE void upb_set_handler_closure(upb_handlers *h, void *closure, - upb_status *status); - - -/* upb_src ********************************************************************/ - -struct _upb_src; -typedef struct _upb_src upb_src; - -// upb_src_sethandlers() must be called once and only once before upb_src_run() -// is called. This sets up the callbacks that will handle the parse. A -// upb_src that is fully initialized except for the call to -// upb_src_sethandlers() is called "prepared" -- this is useful for library -// functions that want to consume the output of a generic upb_src. -// Calling sethandlers() multiple times is an error and will trigger an abort(). -INLINE void upb_src_sethandlers(upb_src *src, upb_handlers *handlers); - -// Runs the src, calling the callbacks that were registered with -// upb_src_sethandlers(), and returning the status of the operation in -// "status." The status might indicate UPB_TRYAGAIN (indicating EAGAIN on a -// non-blocking socket) or a resumable error; in both cases upb_src_run can be -// called again later. TRYAGAIN could come from either the src (input buffers -// are empty) or the handlers (output buffers are full). -INLINE void upb_src_run(upb_src *src, upb_status *status); - - -// A convenience object that a upb_src can use to invoke handlers. It -// transparently handles delegation so that the upb_src needs only follow the -// protocol as if delegation did not exist. -struct _upb_dispatcher; -typedef struct _upb_dispatcher upb_dispatcher; -INLINE void upb_dispatcher_init(upb_dispatcher *d); -INLINE void upb_dispatcher_reset(upb_dispatcher *d, upb_handlers *h, - bool supports_skip); -INLINE upb_flow_t upb_dispatch_startmsg(upb_dispatcher *d); -INLINE upb_flow_t upb_dispatch_endmsg(upb_dispatcher *d); -INLINE upb_flow_t upb_dispatch_startsubmsg(upb_dispatcher *d, - struct _upb_fielddef *f); -INLINE upb_flow_t upb_dispatch_endsubmsg(upb_dispatcher *d, - struct _upb_fielddef *f); -INLINE upb_flow_t upb_dispatch_value(upb_dispatcher *d, struct _upb_fielddef *f, - upb_value val); -INLINE upb_flow_t upb_dispatch_unknownval(upb_dispatcher *d, - upb_field_number_t fieldnum, - upb_value val); +// INLINE void upb_handlers_use_bytesrcs(upb_handlers *h, bool use_bytesrcs); + +// Low-level functions -- internal-only. +void upb_register_typed_value(upb_handlers *h, upb_field_number_t fieldnum, + upb_fieldtype_t type, upb_value_handler_t value, + upb_value fval); +void upb_register_typed_submsg(upb_handlers *h, upb_field_number_t fieldnum, + upb_fieldtype_t type, + upb_startsubmsg_handler_t start, + upb_endsubmsg_handler_t end, + upb_value fval); +void upb_handlers_typed_link(upb_handlers *h, + upb_field_number_t fieldnum, + upb_fieldtype_t type, + int frames); +void upb_handlers_typed_push(upb_handlers *h, upb_field_number_t fieldnum, + upb_fieldtype_t type); +void upb_handlers_typed_pop(upb_handlers *h); + +INLINE upb_handlers_msgent *upb_handlers_getmsgent(upb_handlers *h, + upb_handlers_fieldent *f) { + assert(f->msgent_index != -1); + return &h->msgs[f->msgent_index]; +} +upb_handlers_fieldent *upb_handlers_lookup(upb_inttable *dispatch_table, upb_field_number_t fieldnum); + + +/* upb_dispatcher *************************************************************/ + +// upb_dispatcher can be used by sources of data to invoke the appropriate +// handlers. It takes care of details such as: +// - ensuring all endmsg callbacks (cleanup handlers) are called. +// - propagating status all the way back to the top-level message. +// - handling UPB_BREAK properly (clients only need to handle UPB_SKIPSUBMSG). +// - handling UPB_SKIPSUBMSG if the client doesn't (but this is less +// efficient, because then you can't skip the actual work). +// - tracking the stack of closures. +// +// TODO: it might be best to actually surface UPB_BREAK to clients in the case +// that the can't efficiently skip the submsg; eg. with groups. Then the client +// would know to just unwind the stack without bothering to consume the rest of +// the input. On the other hand, it might be important for all the input to be +// consumed, like if this is a submessage of a larger stream. + +typedef struct { + upb_handlers_fieldent *f; + void *closure; + size_t end_offset; // For groups, 0. +} upb_dispatcher_frame; + +typedef struct { + upb_dispatcher_frame *top, *limit; + + upb_handlers *handlers; + + // Msg and dispatch table for the current level. + upb_handlers_msgent *msgent; + upb_inttable *dispatch_table; + + // The number of startsubmsg calls without a corresponding endsubmsg call. + int current_depth; + + // For all frames >= skip_depth, we are skipping all values in the submsg. + // For all frames >= noframe_depth, we did not even push a frame. + // These are INT_MAX when nothing is being skipped. + // Invariant: noframe_depth >= skip_depth + int skip_depth; + int noframe_depth; + + // Depth of stack entries we'll skip if a callback returns UPB_BREAK. + int delegated_depth; + + // Stack. + upb_dispatcher_frame stack[UPB_MAX_NESTING]; + upb_status status; +} upb_dispatcher; + +INLINE bool upb_dispatcher_skipping(upb_dispatcher *d) { + return d->current_depth >= d->skip_depth; +} + +// If true, upb_dispatcher_skipping(d) must also be true. +INLINE bool upb_dispatcher_noframe(upb_dispatcher *d) { + return d->current_depth >= d->noframe_depth; +} + + +typedef upb_handlers_fieldent upb_dispatcher_field; + +void upb_dispatcher_init(upb_dispatcher *d, upb_handlers *h, size_t top_end_offset); +void upb_dispatcher_reset(upb_dispatcher *d); +void upb_dispatcher_uninit(upb_dispatcher *d); + +upb_flow_t upb_dispatch_startmsg(upb_dispatcher *d, void *closure); +void upb_dispatch_endmsg(upb_dispatcher *d, upb_status *status); + +// Looks up a field by number for the current message. +INLINE upb_dispatcher_field *upb_dispatcher_lookup(upb_dispatcher *d, + upb_field_number_t n) { + return (upb_dispatcher_field*)upb_inttable_fastlookup( + d->dispatch_table, n, sizeof(upb_dispatcher_field)); +} + +// Dispatches values or submessages -- the client is responsible for having +// previously looked up the field. +upb_flow_t upb_dispatch_startsubmsg(upb_dispatcher *d, + upb_dispatcher_field *f, + size_t userval); +upb_flow_t upb_dispatch_endsubmsg(upb_dispatcher *d); + +INLINE upb_flow_t upb_dispatch_value(upb_dispatcher *d, upb_dispatcher_field *f, + upb_value val) { + if (upb_dispatcher_skipping(d)) return UPB_SKIPSUBMSG; + upb_flow_t flow = f->cb.value(d->top->closure, f->fval, val); + if (flow != UPB_CONTINUE) { + d->noframe_depth = d->current_depth + 1; + d->skip_depth = (flow == UPB_BREAK) ? d->delegated_depth : d->current_depth; + return UPB_SKIPSUBMSG; + } + return UPB_CONTINUE; +} +INLINE upb_flow_t upb_dispatch_unknownval(upb_dispatcher *d, upb_field_number_t n, + upb_value val) { + // TODO. + (void)d; + (void)n; + (void)val; + return UPB_CONTINUE; +} +INLINE bool upb_dispatcher_stackempty(upb_dispatcher *d) { + return d->top == d->stack; +} /* upb_bytesrc ****************************************************************/ +// upb_bytesrc is a pull interface for streams of bytes, basically an +// abstraction of read()/fread(), but it avoids copies where possible. + +typedef upb_strlen_t (*upb_bytesrc_read_fptr)( + upb_bytesrc *src, void *buf, upb_strlen_t count, upb_status *status); +typedef bool (*upb_bytesrc_getstr_fptr)( + upb_bytesrc *src, upb_string *str, upb_status *status); + +typedef struct { + upb_bytesrc_read_fptr read; + upb_bytesrc_getstr_fptr getstr; +} upb_bytesrc_vtbl; + +struct _upb_bytesrc { + upb_bytesrc_vtbl *vtbl; +}; + +INLINE void upb_bytesrc_init(upb_bytesrc *s, upb_bytesrc_vtbl *vtbl) { + s->vtbl = vtbl; +} + // Reads up to "count" bytes into "buf", returning the total number of bytes // read. If 0, indicates error and puts details in "status". INLINE upb_strlen_t upb_bytesrc_read(upb_bytesrc *src, void *buf, - upb_strlen_t count, upb_status *status); + upb_strlen_t count, upb_status *status) { + return src->vtbl->read(src, buf, count, status); +} // Like upb_bytesrc_read(), but modifies "str" in-place. Caller must ensure // that "str" is created or just recycled. Returns "false" if no data was @@ -234,22 +408,36 @@ INLINE upb_strlen_t upb_bytesrc_read(upb_bytesrc *src, void *buf, // put it into a different kind of string object) then upb_bytesrc_get() could // save you a copy. INLINE bool upb_bytesrc_getstr(upb_bytesrc *src, upb_string *str, - upb_status *status); - -// A convenience function for getting all the remaining data in a upb_bytesrc -// as a upb_string. Returns false and sets "status" if the operation fails. -INLINE bool upb_bytesrc_getfullstr(upb_bytesrc *src, upb_string *str, - upb_status *status); -INLINE bool upb_value_getfullstr(upb_value val, upb_string *str, - upb_status *status) { - return upb_bytesrc_getfullstr(upb_value_getbytesrc(val), str, status); + upb_status *status) { + return src->vtbl->getstr(src, str, status); } /* upb_bytesink ***************************************************************/ +// upb_bytesink: push interface for streams of bytes, basically an abstraction +// of write()/fwrite(), but it avoids copies where possible. + struct _upb_bytesink; typedef struct _upb_bytesink upb_bytesink; +typedef upb_strlen_t (*upb_bytesink_putstr_fptr)( + upb_bytesink *bytesink, upb_string *str, upb_status *status); +typedef upb_strlen_t (*upb_bytesink_vprintf_fptr)( + upb_bytesink *bytesink, upb_status *status, const char *fmt, va_list args); + +typedef struct { + upb_bytesink_putstr_fptr putstr; + upb_bytesink_vprintf_fptr vprintf; +} upb_bytesink_vtbl; + +struct _upb_bytesink { + upb_bytesink_vtbl *vtbl; +}; + +INLINE void upb_bytesink_init(upb_bytesink *s, upb_bytesink_vtbl *vtbl) { + s->vtbl = vtbl; +} + // TODO: Figure out how buffering should be handled. Should the caller buffer // data and only call these functions when a buffer is full? Seems most @@ -264,15 +452,21 @@ typedef struct _upb_bytesink upb_bytesink; // Returns the number of bytes written. INLINE upb_strlen_t upb_bytesink_printf(upb_bytesink *sink, upb_status *status, - const char *fmt, ...); + const char *fmt, ...) { + va_list args; + va_start(args, fmt); + upb_strlen_t ret = sink->vtbl->vprintf(sink, status, fmt, args); + va_end(args); + return ret; +} // Puts the given string, returning true if the operation was successful, otherwise // check "status" for details. Ownership of the string is *not* passed; if // the callee wants a reference he must call upb_string_getref() on it. INLINE upb_strlen_t upb_bytesink_putstr(upb_bytesink *sink, upb_string *str, - upb_status *status); - -#include "upb_stream_vtbl.h" + upb_status *status) { + return sink->vtbl->putstr(sink, str, status); +} #ifdef __cplusplus } /* extern "C" */ diff --git a/src/upb_stream_vtbl.h b/src/upb_stream_vtbl.h deleted file mode 100644 index e9a4043..0000000 --- a/src/upb_stream_vtbl.h +++ /dev/null @@ -1,303 +0,0 @@ -/* - * upb - a minimalist implementation of protocol buffers. - * - * vtable declarations for types that are implementing any of the src or sink - * interfaces. Only components that are implementing these interfaces need - * to worry about this file. - * - * Copyright (c) 2010 Joshua Haberman. See LICENSE for details. - */ - -#ifndef UPB_SRCSINK_VTBL_H_ -#define UPB_SRCSINK_VTBL_H_ - -#include -#include "upb_stream.h" -#include "upb_string.h" - -#ifdef __cplusplus -extern "C" { -#endif - -// Typedefs for function pointers to all of the virtual functions. - -// upb_src -typedef void (*upb_src_sethandlers_fptr)(upb_src *src, upb_handlers *handlers); -typedef void (*upb_src_run_fptr)(upb_src *src, upb_status *status); - -// upb_bytesrc. -typedef upb_strlen_t (*upb_bytesrc_read_fptr)( - upb_bytesrc *src, void *buf, upb_strlen_t count, upb_status *status); -typedef bool (*upb_bytesrc_getstr_fptr)( - upb_bytesrc *src, upb_string *str, upb_status *status); - -// upb_bytesink. -typedef upb_strlen_t (*upb_bytesink_write_fptr)( - upb_bytesink *bytesink, void *buf, upb_strlen_t count); -typedef upb_strlen_t (*upb_bytesink_putstr_fptr)( - upb_bytesink *bytesink, upb_string *str, upb_status *status); -typedef upb_strlen_t (*upb_bytesink_vprintf_fptr)( - upb_bytesink *bytesink, upb_status *status, const char *fmt, va_list args); - -// Vtables for the above interfaces. -typedef struct { - upb_bytesrc_read_fptr read; - upb_bytesrc_getstr_fptr getstr; -} upb_bytesrc_vtbl; - -typedef struct { - upb_bytesink_write_fptr write; - upb_bytesink_putstr_fptr putstr; - upb_bytesink_vprintf_fptr vprintf; -} upb_bytesink_vtbl; - -typedef struct { - upb_src_sethandlers_fptr sethandlers; - upb_src_run_fptr run; -} upb_src_vtbl; - - -// "Base Class" definitions; components that implement these interfaces should -// contain one of these structures. - -struct _upb_bytesrc { - upb_bytesrc_vtbl *vtbl; -}; - -struct _upb_bytesink { - upb_bytesink_vtbl *vtbl; -}; - -struct _upb_src { - upb_src_vtbl *vtbl; -}; - -INLINE void upb_bytesrc_init(upb_bytesrc *s, upb_bytesrc_vtbl *vtbl) { - s->vtbl = vtbl; -} - -INLINE void upb_bytesink_init(upb_bytesink *s, upb_bytesink_vtbl *vtbl) { - s->vtbl = vtbl; -} - -INLINE void upb_src_init(upb_src *s, upb_src_vtbl *vtbl) { - s->vtbl = vtbl; -} - -// Implementation of virtual function dispatch. - -// upb_src -INLINE void upb_src_sethandlers(upb_src *src, upb_handlers *handlers) { - src->vtbl->sethandlers(src, handlers); -} - -INLINE void upb_src_run(upb_src *src, upb_status *status) { - src->vtbl->run(src, status); -} - -// upb_bytesrc -INLINE upb_strlen_t upb_bytesrc_read(upb_bytesrc *src, void *buf, - upb_strlen_t count, upb_status *status) { - return src->vtbl->read(src, buf, count, status); -} - -INLINE bool upb_bytesrc_getstr(upb_bytesrc *src, upb_string *str, - upb_status *status) { - return src->vtbl->getstr(src, str, status); -} - -INLINE bool upb_bytesrc_getfullstr(upb_bytesrc *src, upb_string *str, - upb_status *status) { - // We start with a getstr, because that could possibly alias data instead of - // copying. - if (!upb_bytesrc_getstr(src, str, status)) return false; - // Trade-off between number of read calls and amount of overallocation. - const size_t bufsize = 4096; - do { - upb_strlen_t len = upb_string_len(str); - char *buf = upb_string_getrwbuf(str, len + bufsize); - upb_strlen_t read = upb_bytesrc_read(src, buf + len, bufsize, status); - if (read < 0) return false; - // Resize to proper size. - upb_string_getrwbuf(str, len + read); - } while (!status->code != UPB_EOF); - return true; -} - - -// upb_bytesink -INLINE upb_strlen_t upb_bytesink_write(upb_bytesink *sink, void *buf, - upb_strlen_t count) { - return sink->vtbl->write(sink, buf, count); -} - -INLINE upb_strlen_t upb_bytesink_putstr(upb_bytesink *sink, upb_string *str, upb_status *status) { - return sink->vtbl->putstr(sink, str, status); -} - -INLINE upb_strlen_t upb_bytesink_printf(upb_bytesink *sink, upb_status *status, const char *fmt, ...) { - va_list args; - va_start(args, fmt); - upb_strlen_t ret = sink->vtbl->vprintf(sink, status, fmt, args); - va_end(args); - return ret; -} - -// upb_handlers -struct _upb_handlers { - upb_handlerset *set; - void *closure; - upb_status *status; // We don't own this. -}; - -INLINE void upb_handlers_init(upb_handlers *h) { - (void)h; -} -INLINE void upb_handlers_uninit(upb_handlers *h) { - (void)h; -} - -INLINE void upb_handlers_reset(upb_handlers *h) { - h->set = NULL; - h->closure = NULL; -} - -INLINE bool upb_handlers_isempty(upb_handlers *h) { - return !h->set && !h->closure; -} - -INLINE upb_flow_t upb_nop(void *closure) { - (void)closure; - return UPB_CONTINUE; -} - -INLINE upb_flow_t upb_value_nop(void *closure, struct _upb_fielddef *f, upb_value val) { - (void)closure; - (void)f; - (void)val; - return UPB_CONTINUE; -} - -INLINE upb_flow_t upb_startsubmsg_nop(void *closure, struct _upb_fielddef *f, - upb_handlers *delegate_to) { - (void)closure; - (void)f; - (void)delegate_to; - return UPB_CONTINUE; -} - -INLINE upb_flow_t upb_endsubmsg_nop(void *closure, struct _upb_fielddef *f) { - (void)closure; - (void)f; - return UPB_CONTINUE; -} - -INLINE upb_flow_t upb_unknownval_nop(void *closure, upb_field_number_t fieldnum, - upb_value val) { - (void)closure; - (void)fieldnum; - (void)val; - return UPB_CONTINUE; -} - -INLINE void upb_register_handlerset(upb_handlers *h, upb_handlerset *set) { - if (!set->startmsg) set->startmsg = &upb_nop; - if (!set->endmsg) set->endmsg = &upb_nop; - if (!set->value) set->value = &upb_value_nop; - if (!set->startsubmsg) set->startsubmsg = &upb_startsubmsg_nop; - if (!set->endsubmsg) set->endsubmsg = &upb_endsubmsg_nop; - if (!set->unknownval) set->unknownval = &upb_unknownval_nop; - h->set = set; -} - -INLINE void upb_set_handler_closure(upb_handlers *h, void *closure, - upb_status *status) { - h->closure = closure; - h->status = status; -} - -// upb_dispatcher -typedef struct { - upb_handlers handlers; - int depth; -} upb_dispatcher_frame; - -struct _upb_dispatcher { - upb_dispatcher_frame stack[UPB_MAX_NESTING], *top, *limit; - bool supports_skip; -}; - -INLINE void upb_dispatcher_init(upb_dispatcher *d) { - d->limit = d->stack + sizeof(d->stack); -} - -INLINE void upb_dispatcher_reset(upb_dispatcher *d, upb_handlers *h, - bool supports_skip) { - d->top = d->stack; - d->top->depth = 1; // Never want to trigger end-of-delegation. - d->top->handlers = *h; - d->supports_skip = supports_skip; -} - -INLINE upb_flow_t upb_dispatch_startmsg(upb_dispatcher *d) { - assert(d->stack == d->top); - return d->top->handlers.set->startmsg(d->top->handlers.closure); -} - -INLINE upb_flow_t upb_dispatch_endmsg(upb_dispatcher *d) { - assert(d->stack == d->top); - return d->top->handlers.set->endmsg(d->top->handlers.closure); -} - -// TODO: several edge cases to fix: -// - delegated start returns UPB_BREAK, should replay the start on resume. -// - endsubmsg returns UPB_BREAK, should NOT replay the delegated endmsg. -INLINE upb_flow_t upb_dispatch_startsubmsg(upb_dispatcher *d, - struct _upb_fielddef *f) { - upb_handlers handlers; - upb_handlers_init(&handlers); - upb_handlers_reset(&handlers); - upb_flow_t ret = d->top->handlers.set->startsubmsg(d->top->handlers.closure, f, &handlers); - assert((ret == UPB_DELEGATE) == !upb_handlers_isempty(&handlers)); - if (ret == UPB_DELEGATE) { - ++d->top; - d->top->handlers = handlers; - d->top->depth = 0; - ret = d->top->handlers.set->startmsg(d->top->handlers.closure); - } - if (ret == UPB_CONTINUE || !d->supports_skip) ++d->top->depth; - upb_handlers_uninit(&handlers); - return ret; -} - -INLINE upb_flow_t upb_dispatch_endsubmsg(upb_dispatcher *d, - struct _upb_fielddef *f) { - upb_flow_t ret; - if (--d->top->depth == 0) { - ret = d->top->handlers.set->endmsg(d->top->handlers.closure); - //assert(ret != UPB_BREAK); - if (ret != UPB_CONTINUE) return ret; - --d->top; - assert(d->top >= d->stack); - } - return d->top->handlers.set->endsubmsg(d->top->handlers.closure, f); -} - -INLINE upb_flow_t upb_dispatch_value(upb_dispatcher *d, - struct _upb_fielddef *f, - upb_value val) { - return d->top->handlers.set->value(d->top->handlers.closure, f, val); -} - -INLINE upb_flow_t upb_dispatch_unknownval(upb_dispatcher *d, - upb_field_number_t fieldnum, - upb_value val) { - return d->top->handlers.set->unknownval(d->top->handlers.closure, - fieldnum, val); -} - -#ifdef __cplusplus -} /* extern "C" */ -#endif - -#endif diff --git a/src/upb_strstream.c b/src/upb_strstream.c index c957648..8ef9884 100644 --- a/src/upb_strstream.c +++ b/src/upb_strstream.c @@ -7,7 +7,6 @@ #include "upb_strstream.h" #include -#include "upb_string.h" /* upb_stringsrc **************************************************************/ @@ -108,7 +107,6 @@ static upb_strlen_t upb_stringsink_putstr(upb_bytesink *_sink, upb_string *str, void upb_stringsink_init(upb_stringsink *s) { static upb_bytesink_vtbl vtbl = { - NULL, upb_stringsink_putstr, upb_stringsink_vprintf }; diff --git a/src/upb_table.c b/src/upb_table.c index d2cb5da..54af32d 100644 --- a/src/upb_table.c +++ b/src/upb_table.c @@ -7,7 +7,6 @@ */ #include "upb_table.h" -#include "upb_string.h" #include #include diff --git a/src/upb_textprinter.c b/src/upb_textprinter.c index 076e1df..6f123d6 100644 --- a/src/upb_textprinter.c +++ b/src/upb_textprinter.c @@ -9,8 +9,6 @@ #include #include #include -#include "upb_def.h" -#include "upb_string.h" struct _upb_textprinter { upb_bytesink *bytesink; @@ -91,9 +89,10 @@ err: return -1; } -static upb_flow_t upb_textprinter_value(void *_p, upb_fielddef *f, +static upb_flow_t upb_textprinter_value(void *_p, upb_value fval, upb_value val) { upb_textprinter *p = _p; + upb_fielddef *f = upb_value_getfielddef(fval); upb_textprinter_indent(p); CHECK(upb_bytesink_printf(p->bytesink, &p->status, UPB_STRFMT ": ", UPB_STRARG(f->name))); #define CASE(fmtstr, member) \ @@ -144,21 +143,20 @@ err: return UPB_BREAK; } -static upb_flow_t upb_textprinter_startsubmsg(void *_p, upb_fielddef *f, - upb_handlers *delegate_to) { - (void)delegate_to; +static upb_sflow_t upb_textprinter_startsubmsg(void *_p, upb_value fval) { upb_textprinter *p = _p; + upb_fielddef *f = upb_value_getfielddef(fval); upb_textprinter_indent(p); CHECK(upb_bytesink_printf(p->bytesink, &p->status, UPB_STRFMT " {", UPB_STRARG(f->name))); if(!p->single_line) upb_bytesink_putstr(p->bytesink, UPB_STRLIT("\n"), &p->status); p->indent_depth++; - return UPB_CONTINUE; + return UPB_CONTINUE_WITH(_p); err: - return UPB_BREAK; + return UPB_S_BREAK; } -static upb_flow_t upb_textprinter_endsubmsg(void *_p, upb_fielddef *f) { - (void)f; +static upb_flow_t upb_textprinter_endsubmsg(void *_p, upb_value fval) { + (void)fval; upb_textprinter *p = _p; p->indent_depth--; upb_textprinter_indent(p); @@ -176,18 +174,20 @@ void upb_textprinter_free(upb_textprinter *p) { free(p); } -void upb_textprinter_reset(upb_textprinter *p, upb_handlers *handlers, - upb_bytesink *sink, bool single_line) { - static upb_handlerset handlerset = { +void upb_textprinter_reset(upb_textprinter *p, upb_bytesink *sink, + bool single_line) { + p->bytesink = sink; + p->single_line = single_line; + p->indent_depth = 0; +} + +void upb_textprinter_reghandlers(upb_handlers *h) { + upb_register_all(h, NULL, // startmsg NULL, // endmsg upb_textprinter_value, upb_textprinter_startsubmsg, upb_textprinter_endsubmsg, - }; - p->bytesink = sink; - p->single_line = single_line; - p->indent_depth = 0; - upb_register_handlerset(handlers, &handlerset); - upb_set_handler_closure(handlers, p, &p->status); + NULL // Unknown + ); } diff --git a/src/upb_textprinter.h b/src/upb_textprinter.h index a880626..40f392b 100644 --- a/src/upb_textprinter.h +++ b/src/upb_textprinter.h @@ -18,9 +18,9 @@ typedef struct _upb_textprinter upb_textprinter; upb_textprinter *upb_textprinter_new(); void upb_textprinter_free(upb_textprinter *p); -void upb_textprinter_reset(upb_textprinter *p, upb_handlers *handlers, - upb_bytesink *sink, bool single_line); -void upb_textprinter_sethandlers(upb_textprinter *p, upb_handlers *h); +void upb_textprinter_reset(upb_textprinter *p, upb_bytesink *sink, + bool single_line); +void upb_textprinter_reghandlers(upb_handlers *h); #ifdef __cplusplus } /* extern "C" */ -- cgit v1.2.3