From 9ac11326dfc75c829e530c9a255b9f2a0e19f1d9 Mon Sep 17 00:00:00 2001 From: Erik Benoist Date: Sat, 17 Nov 2018 16:50:24 -0600 Subject: [PATCH] Adds the ability to ignore unknown fields on parse This adds the ability for the MRI Ruby library to optionally pass in a ignore_unknown_fields option when decoding JSON. The functionality was added upstream in upb, this change exposes that option. --- conformance/failure_list_ruby.txt | 50 +- ruby/ext/google/protobuf_c/encode_decode.c | 30 +- ruby/ext/google/protobuf_c/message.c | 2 +- ruby/ext/google/protobuf_c/protobuf.h | 2 +- ruby/ext/google/protobuf_c/upb.c | 4118 ++++++++++++++------ ruby/ext/google/protobuf_c/upb.h | 1484 +++++-- ruby/lib/google/protobuf.rb | 4 +- ruby/tests/basic.rb | 13 + 8 files changed, 4058 insertions(+), 1645 deletions(-) diff --git a/conformance/failure_list_ruby.txt b/conformance/failure_list_ruby.txt index 53b4970164..89270326c4 100644 --- a/conformance/failure_list_ruby.txt +++ b/conformance/failure_list_ruby.txt @@ -5,8 +5,6 @@ Recommended.Proto3.JsonInput.BytesFieldBase64Url.JsonOutput Recommended.Proto3.JsonInput.BytesFieldBase64Url.ProtobufOutput Recommended.Proto3.JsonInput.DurationHas3FractionalDigits.Validator Recommended.Proto3.JsonInput.DurationHas6FractionalDigits.Validator -Recommended.Proto3.JsonInput.DurationHas9FractionalDigits.Validator -Recommended.Proto3.JsonInput.DurationHasZeroFractionalDigit.Validator Recommended.Proto3.JsonInput.Int64FieldBeString.Validator Recommended.Proto3.JsonInput.MapFieldValueIsNull Recommended.Proto3.JsonInput.RepeatedFieldMessageElementIsNull @@ -17,9 +15,6 @@ Recommended.Proto3.JsonInput.StringFieldUnpairedHighSurrogate Recommended.Proto3.JsonInput.StringFieldUnpairedLowSurrogate Recommended.Proto3.JsonInput.TimestampHas3FractionalDigits.Validator Recommended.Proto3.JsonInput.TimestampHas6FractionalDigits.Validator -Recommended.Proto3.JsonInput.TimestampHas9FractionalDigits.Validator -Recommended.Proto3.JsonInput.TimestampHasZeroFractionalDigit.Validator -Recommended.Proto3.JsonInput.TimestampZeroNormalized.Validator Recommended.Proto3.JsonInput.Uint64FieldBeString.Validator Required.DurationProtoInputTooLarge.JsonOutput Required.DurationProtoInputTooSmall.JsonOutput @@ -48,12 +43,8 @@ Required.Proto3.JsonInput.DoubleFieldMaxNegativeValue.ProtobufOutput Required.Proto3.JsonInput.DoubleFieldMinPositiveValue.JsonOutput Required.Proto3.JsonInput.DoubleFieldMinPositiveValue.ProtobufOutput Required.Proto3.JsonInput.DoubleFieldNan.JsonOutput -Required.Proto3.JsonInput.DurationMaxValue.JsonOutput -Required.Proto3.JsonInput.DurationMaxValue.ProtobufOutput Required.Proto3.JsonInput.DurationMinValue.JsonOutput -Required.Proto3.JsonInput.DurationMinValue.ProtobufOutput Required.Proto3.JsonInput.DurationRepeatedValue.JsonOutput -Required.Proto3.JsonInput.DurationRepeatedValue.ProtobufOutput Required.Proto3.JsonInput.FieldMask.JsonOutput Required.Proto3.JsonInput.FieldMask.ProtobufOutput Required.Proto3.JsonInput.FloatFieldInfinity.JsonOutput @@ -61,71 +52,32 @@ Required.Proto3.JsonInput.FloatFieldNan.JsonOutput Required.Proto3.JsonInput.FloatFieldNegativeInfinity.JsonOutput Required.Proto3.JsonInput.OneofFieldDuplicate Required.Proto3.JsonInput.OptionalBoolWrapper.JsonOutput -Required.Proto3.JsonInput.OptionalBoolWrapper.ProtobufOutput Required.Proto3.JsonInput.OptionalBytesWrapper.JsonOutput -Required.Proto3.JsonInput.OptionalBytesWrapper.ProtobufOutput Required.Proto3.JsonInput.OptionalDoubleWrapper.JsonOutput -Required.Proto3.JsonInput.OptionalDoubleWrapper.ProtobufOutput Required.Proto3.JsonInput.OptionalFloatWrapper.JsonOutput -Required.Proto3.JsonInput.OptionalFloatWrapper.ProtobufOutput Required.Proto3.JsonInput.OptionalInt32Wrapper.JsonOutput -Required.Proto3.JsonInput.OptionalInt32Wrapper.ProtobufOutput Required.Proto3.JsonInput.OptionalInt64Wrapper.JsonOutput -Required.Proto3.JsonInput.OptionalInt64Wrapper.ProtobufOutput Required.Proto3.JsonInput.OptionalStringWrapper.JsonOutput -Required.Proto3.JsonInput.OptionalStringWrapper.ProtobufOutput Required.Proto3.JsonInput.OptionalUint32Wrapper.JsonOutput -Required.Proto3.JsonInput.OptionalUint32Wrapper.ProtobufOutput Required.Proto3.JsonInput.OptionalUint64Wrapper.JsonOutput -Required.Proto3.JsonInput.OptionalUint64Wrapper.ProtobufOutput Required.Proto3.JsonInput.OptionalWrapperTypesWithNonDefaultValue.JsonOutput Required.Proto3.JsonInput.OptionalWrapperTypesWithNonDefaultValue.ProtobufOutput Required.Proto3.JsonInput.RepeatedBoolWrapper.JsonOutput -Required.Proto3.JsonInput.RepeatedBoolWrapper.ProtobufOutput Required.Proto3.JsonInput.RepeatedBytesWrapper.JsonOutput -Required.Proto3.JsonInput.RepeatedBytesWrapper.ProtobufOutput Required.Proto3.JsonInput.RepeatedDoubleWrapper.JsonOutput -Required.Proto3.JsonInput.RepeatedDoubleWrapper.ProtobufOutput Required.Proto3.JsonInput.RepeatedFloatWrapper.JsonOutput -Required.Proto3.JsonInput.RepeatedFloatWrapper.ProtobufOutput Required.Proto3.JsonInput.RepeatedInt32Wrapper.JsonOutput -Required.Proto3.JsonInput.RepeatedInt32Wrapper.ProtobufOutput Required.Proto3.JsonInput.RepeatedInt64Wrapper.JsonOutput -Required.Proto3.JsonInput.RepeatedInt64Wrapper.ProtobufOutput Required.Proto3.JsonInput.RepeatedStringWrapper.JsonOutput -Required.Proto3.JsonInput.RepeatedStringWrapper.ProtobufOutput Required.Proto3.JsonInput.RepeatedUint32Wrapper.JsonOutput -Required.Proto3.JsonInput.RepeatedUint32Wrapper.ProtobufOutput Required.Proto3.JsonInput.RepeatedUint64Wrapper.JsonOutput -Required.Proto3.JsonInput.RepeatedUint64Wrapper.ProtobufOutput Required.Proto3.JsonInput.StringFieldSurrogatePair.JsonOutput Required.Proto3.JsonInput.StringFieldSurrogatePair.ProtobufOutput -Required.Proto3.JsonInput.Struct.JsonOutput -Required.Proto3.JsonInput.Struct.ProtobufOutput -Required.Proto3.JsonInput.TimestampMaxValue.JsonOutput -Required.Proto3.JsonInput.TimestampMaxValue.ProtobufOutput +Required.Proto3.JsonInput.TimestampJsonInputTooSmall Required.Proto3.JsonInput.TimestampMinValue.JsonOutput Required.Proto3.JsonInput.TimestampMinValue.ProtobufOutput Required.Proto3.JsonInput.TimestampRepeatedValue.JsonOutput Required.Proto3.JsonInput.TimestampRepeatedValue.ProtobufOutput -Required.Proto3.JsonInput.TimestampWithNegativeOffset.JsonOutput -Required.Proto3.JsonInput.TimestampWithNegativeOffset.ProtobufOutput -Required.Proto3.JsonInput.TimestampWithPositiveOffset.JsonOutput -Required.Proto3.JsonInput.TimestampWithPositiveOffset.ProtobufOutput -Required.Proto3.JsonInput.ValueAcceptBool.JsonOutput -Required.Proto3.JsonInput.ValueAcceptBool.ProtobufOutput -Required.Proto3.JsonInput.ValueAcceptFloat.JsonOutput -Required.Proto3.JsonInput.ValueAcceptFloat.ProtobufOutput -Required.Proto3.JsonInput.ValueAcceptInteger.JsonOutput -Required.Proto3.JsonInput.ValueAcceptInteger.ProtobufOutput -Required.Proto3.JsonInput.ValueAcceptList.JsonOutput -Required.Proto3.JsonInput.ValueAcceptList.ProtobufOutput -Required.Proto3.JsonInput.ValueAcceptNull.JsonOutput -Required.Proto3.JsonInput.ValueAcceptNull.ProtobufOutput -Required.Proto3.JsonInput.ValueAcceptObject.JsonOutput -Required.Proto3.JsonInput.ValueAcceptObject.ProtobufOutput -Required.Proto3.JsonInput.ValueAcceptString.JsonOutput -Required.Proto3.JsonInput.ValueAcceptString.ProtobufOutput Required.Proto3.ProtobufInput.DoubleFieldNormalizeQuietNan.JsonOutput Required.Proto3.ProtobufInput.DoubleFieldNormalizeSignalingNan.JsonOutput Required.Proto3.ProtobufInput.FloatFieldNormalizeQuietNan.JsonOutput diff --git a/ruby/ext/google/protobuf_c/encode_decode.c b/ruby/ext/google/protobuf_c/encode_decode.c index 0c5a74abd1..a14f0bc80d 100644 --- a/ruby/ext/google/protobuf_c/encode_decode.c +++ b/ruby/ext/google/protobuf_c/encode_decode.c @@ -891,19 +891,38 @@ VALUE Message_decode(VALUE klass, VALUE data) { /* * call-seq: - * MessageClass.decode_json(data) => message + * MessageClass.decode_json(data, options = {}) => message * * Decodes the given data (as a string containing bytes in protocol buffers wire * format) under the interpretration given by this message class's definition * and returns a message object with the corresponding field values. + * + * @param options [Hash] options for the decoder + * ignore_unknown_fields: set true to ignore unknown fields (default is to raise an error) */ -VALUE Message_decode_json(VALUE klass, VALUE data) { +VALUE Message_decode_json(int argc, VALUE* argv, VALUE klass) { VALUE descriptor = rb_ivar_get(klass, descriptor_instancevar_interned); Descriptor* desc = ruby_to_Descriptor(descriptor); VALUE msgklass = Descriptor_msgclass(descriptor); VALUE msg_rb; + VALUE data = argv[0]; + VALUE ignore_unknown_fields = Qfalse; MessageHeader* msg; + if (argc < 1 || argc > 2) { + rb_raise(rb_eArgError, "Expected 1 or 2 arguments."); + } + + if (argc == 2) { + VALUE hash_args = argv[1]; + if (TYPE(hash_args) != T_HASH) { + rb_raise(rb_eArgError, "Expected hash arguments."); + } + + ignore_unknown_fields = rb_hash_lookup2( + hash_args, ID2SYM(rb_intern("ignore_unknown_fields")), Qfalse); + } + if (TYPE(data) != T_STRING) { rb_raise(rb_eArgError, "Expected string for JSON data."); } @@ -922,7 +941,7 @@ VALUE Message_decode_json(VALUE klass, VALUE data) { stackenv_init(&se, "Error occurred during parsing: %s"); upb_sink_reset(&sink, get_fill_handlers(desc), msg); - parser = upb_json_parser_create(&se.env, method, &sink); + parser = upb_json_parser_create(&se.env, method, &sink, ignore_unknown_fields); upb_bufsrc_putbuf(RSTRING_PTR(data), RSTRING_LEN(data), upb_json_parser_input(parser)); @@ -1310,9 +1329,12 @@ VALUE Message_encode(VALUE klass, VALUE msg_rb) { /* * call-seq: - * MessageClass.encode_json(msg) => json_string + * MessageClass.encode_json(msg, options = {}) => json_string * * Encodes the given message object into its serialized JSON representation. + * @param options [Hash] options for the decoder + * preserve_proto_fieldnames: set true to use original fieldnames (default is to camelCase) + * emit_defaults: set true to emit 0/false values (default is to omit them) */ VALUE Message_encode_json(int argc, VALUE* argv, VALUE klass) { VALUE descriptor = rb_ivar_get(klass, descriptor_instancevar_interned); diff --git a/ruby/ext/google/protobuf_c/message.c b/ruby/ext/google/protobuf_c/message.c index 81a782766f..61823c1de2 100644 --- a/ruby/ext/google/protobuf_c/message.c +++ b/ruby/ext/google/protobuf_c/message.c @@ -628,7 +628,7 @@ VALUE build_class_from_descriptor(Descriptor* desc) { rb_define_method(klass, "[]=", Message_index_set, 2); rb_define_singleton_method(klass, "decode", Message_decode, 1); rb_define_singleton_method(klass, "encode", Message_encode, 1); - rb_define_singleton_method(klass, "decode_json", Message_decode_json, 1); + rb_define_singleton_method(klass, "decode_json", Message_decode_json, -1); rb_define_singleton_method(klass, "encode_json", Message_encode_json, -1); rb_define_singleton_method(klass, "descriptor", Message_descriptor, 0); diff --git a/ruby/ext/google/protobuf_c/protobuf.h b/ruby/ext/google/protobuf_c/protobuf.h index 0aa385a09f..616947c251 100644 --- a/ruby/ext/google/protobuf_c/protobuf.h +++ b/ruby/ext/google/protobuf_c/protobuf.h @@ -570,7 +570,7 @@ VALUE Message_index_set(VALUE _self, VALUE field_name, VALUE value); VALUE Message_descriptor(VALUE klass); VALUE Message_decode(VALUE klass, VALUE data); VALUE Message_encode(VALUE klass, VALUE msg_rb); -VALUE Message_decode_json(VALUE klass, VALUE data); +VALUE Message_decode_json(int argc, VALUE* argv, VALUE klass); VALUE Message_encode_json(int argc, VALUE* argv, VALUE klass); VALUE Google_Protobuf_discard_unknown(VALUE self, VALUE msg_rb); diff --git a/ruby/ext/google/protobuf_c/upb.c b/ruby/ext/google/protobuf_c/upb.c index c02a5ce4a4..049e2bb061 100644 --- a/ruby/ext/google/protobuf_c/upb.c +++ b/ruby/ext/google/protobuf_c/upb.c @@ -1,9 +1,506 @@ // Amalgamated source file #include "upb.h" +#if UINTPTR_MAX == 0xffffffff +#define UPB_SIZE(size32, size64) size32 +#else +#define UPB_SIZE(size32, size64) size64 +#endif + +#define UPB_FIELD_AT(msg, fieldtype, offset) \ + *(fieldtype*)((const char*)(msg) + offset) + +#define UPB_READ_ONEOF(msg, fieldtype, offset, case_offset, case_val, default) \ + UPB_FIELD_AT(msg, int, case_offset) == case_val \ + ? UPB_FIELD_AT(msg, fieldtype, offset) \ + : default + +#define UPB_WRITE_ONEOF(msg, fieldtype, offset, value, case_offset, case_val) \ + UPB_FIELD_AT(msg, int, case_offset) = case_val; \ + UPB_FIELD_AT(msg, fieldtype, offset) = value; +/* This file was generated by upbc (the upb compiler) from the input + * file: + * + * google/protobuf/descriptor.proto + * + * Do not edit -- your changes will be discarded when the file is + * regenerated. */ + +#include + + +static const upb_msglayout *const google_protobuf_FileDescriptorSet_submsgs[1] = { + &google_protobuf_FileDescriptorProto_msginit, +}; + +static const upb_msglayout_field google_protobuf_FileDescriptorSet__fields[1] = { + {1, UPB_SIZE(0, 0), 0, 0, 11, 3}, +}; + +const upb_msglayout google_protobuf_FileDescriptorSet_msginit = { + &google_protobuf_FileDescriptorSet_submsgs[0], + &google_protobuf_FileDescriptorSet__fields[0], + UPB_SIZE(4, 8), 1, false, +}; + +static const upb_msglayout *const google_protobuf_FileDescriptorProto_submsgs[6] = { + &google_protobuf_DescriptorProto_msginit, + &google_protobuf_EnumDescriptorProto_msginit, + &google_protobuf_FieldDescriptorProto_msginit, + &google_protobuf_FileOptions_msginit, + &google_protobuf_ServiceDescriptorProto_msginit, + &google_protobuf_SourceCodeInfo_msginit, +}; + +static const upb_msglayout_field google_protobuf_FileDescriptorProto__fields[12] = { + {1, UPB_SIZE(8, 16), 1, 0, 9, 1}, + {2, UPB_SIZE(16, 32), 2, 0, 9, 1}, + {3, UPB_SIZE(40, 80), 0, 0, 9, 3}, + {4, UPB_SIZE(44, 88), 0, 0, 11, 3}, + {5, UPB_SIZE(48, 96), 0, 1, 11, 3}, + {6, UPB_SIZE(52, 104), 0, 4, 11, 3}, + {7, UPB_SIZE(56, 112), 0, 2, 11, 3}, + {8, UPB_SIZE(32, 64), 4, 3, 11, 1}, + {9, UPB_SIZE(36, 72), 5, 5, 11, 1}, + {10, UPB_SIZE(60, 120), 0, 0, 5, 3}, + {11, UPB_SIZE(64, 128), 0, 0, 5, 3}, + {12, UPB_SIZE(24, 48), 3, 0, 9, 1}, +}; + +const upb_msglayout google_protobuf_FileDescriptorProto_msginit = { + &google_protobuf_FileDescriptorProto_submsgs[0], + &google_protobuf_FileDescriptorProto__fields[0], + UPB_SIZE(72, 144), 12, false, +}; + +static const upb_msglayout *const google_protobuf_DescriptorProto_submsgs[8] = { + &google_protobuf_DescriptorProto_msginit, + &google_protobuf_DescriptorProto_ExtensionRange_msginit, + &google_protobuf_DescriptorProto_ReservedRange_msginit, + &google_protobuf_EnumDescriptorProto_msginit, + &google_protobuf_FieldDescriptorProto_msginit, + &google_protobuf_MessageOptions_msginit, + &google_protobuf_OneofDescriptorProto_msginit, +}; + +static const upb_msglayout_field google_protobuf_DescriptorProto__fields[10] = { + {1, UPB_SIZE(8, 16), 1, 0, 9, 1}, + {2, UPB_SIZE(20, 40), 0, 4, 11, 3}, + {3, UPB_SIZE(24, 48), 0, 0, 11, 3}, + {4, UPB_SIZE(28, 56), 0, 3, 11, 3}, + {5, UPB_SIZE(32, 64), 0, 1, 11, 3}, + {6, UPB_SIZE(36, 72), 0, 4, 11, 3}, + {7, UPB_SIZE(16, 32), 2, 5, 11, 1}, + {8, UPB_SIZE(40, 80), 0, 6, 11, 3}, + {9, UPB_SIZE(44, 88), 0, 2, 11, 3}, + {10, UPB_SIZE(48, 96), 0, 0, 9, 3}, +}; + +const upb_msglayout google_protobuf_DescriptorProto_msginit = { + &google_protobuf_DescriptorProto_submsgs[0], + &google_protobuf_DescriptorProto__fields[0], + UPB_SIZE(56, 112), 10, false, +}; + +static const upb_msglayout *const google_protobuf_DescriptorProto_ExtensionRange_submsgs[1] = { + &google_protobuf_ExtensionRangeOptions_msginit, +}; + +static const upb_msglayout_field google_protobuf_DescriptorProto_ExtensionRange__fields[3] = { + {1, UPB_SIZE(4, 4), 1, 0, 5, 1}, + {2, UPB_SIZE(8, 8), 2, 0, 5, 1}, + {3, UPB_SIZE(12, 16), 3, 0, 11, 1}, +}; + +const upb_msglayout google_protobuf_DescriptorProto_ExtensionRange_msginit = { + &google_protobuf_DescriptorProto_ExtensionRange_submsgs[0], + &google_protobuf_DescriptorProto_ExtensionRange__fields[0], + UPB_SIZE(16, 24), 3, false, +}; + +static const upb_msglayout_field google_protobuf_DescriptorProto_ReservedRange__fields[2] = { + {1, UPB_SIZE(4, 4), 1, 0, 5, 1}, + {2, UPB_SIZE(8, 8), 2, 0, 5, 1}, +}; + +const upb_msglayout google_protobuf_DescriptorProto_ReservedRange_msginit = { + NULL, + &google_protobuf_DescriptorProto_ReservedRange__fields[0], + UPB_SIZE(12, 12), 2, false, +}; + +static const upb_msglayout *const google_protobuf_ExtensionRangeOptions_submsgs[1] = { + &google_protobuf_UninterpretedOption_msginit, +}; + +static const upb_msglayout_field google_protobuf_ExtensionRangeOptions__fields[1] = { + {999, UPB_SIZE(0, 0), 0, 0, 11, 3}, +}; + +const upb_msglayout google_protobuf_ExtensionRangeOptions_msginit = { + &google_protobuf_ExtensionRangeOptions_submsgs[0], + &google_protobuf_ExtensionRangeOptions__fields[0], + UPB_SIZE(4, 8), 1, false, +}; + +static const upb_msglayout *const google_protobuf_FieldDescriptorProto_submsgs[1] = { + &google_protobuf_FieldOptions_msginit, +}; + +static const upb_msglayout_field google_protobuf_FieldDescriptorProto__fields[10] = { + {1, UPB_SIZE(32, 32), 5, 0, 9, 1}, + {2, UPB_SIZE(40, 48), 6, 0, 9, 1}, + {3, UPB_SIZE(24, 24), 3, 0, 5, 1}, + {4, UPB_SIZE(8, 8), 1, 0, 14, 1}, + {5, UPB_SIZE(16, 16), 2, 0, 14, 1}, + {6, UPB_SIZE(48, 64), 7, 0, 9, 1}, + {7, UPB_SIZE(56, 80), 8, 0, 9, 1}, + {8, UPB_SIZE(72, 112), 10, 0, 11, 1}, + {9, UPB_SIZE(28, 28), 4, 0, 5, 1}, + {10, UPB_SIZE(64, 96), 9, 0, 9, 1}, +}; + +const upb_msglayout google_protobuf_FieldDescriptorProto_msginit = { + &google_protobuf_FieldDescriptorProto_submsgs[0], + &google_protobuf_FieldDescriptorProto__fields[0], + UPB_SIZE(80, 128), 10, false, +}; + +static const upb_msglayout *const google_protobuf_OneofDescriptorProto_submsgs[1] = { + &google_protobuf_OneofOptions_msginit, +}; + +static const upb_msglayout_field google_protobuf_OneofDescriptorProto__fields[2] = { + {1, UPB_SIZE(8, 16), 1, 0, 9, 1}, + {2, UPB_SIZE(16, 32), 2, 0, 11, 1}, +}; + +const upb_msglayout google_protobuf_OneofDescriptorProto_msginit = { + &google_protobuf_OneofDescriptorProto_submsgs[0], + &google_protobuf_OneofDescriptorProto__fields[0], + UPB_SIZE(24, 48), 2, false, +}; + +static const upb_msglayout *const google_protobuf_EnumDescriptorProto_submsgs[3] = { + &google_protobuf_EnumDescriptorProto_EnumReservedRange_msginit, + &google_protobuf_EnumOptions_msginit, + &google_protobuf_EnumValueDescriptorProto_msginit, +}; + +static const upb_msglayout_field google_protobuf_EnumDescriptorProto__fields[5] = { + {1, UPB_SIZE(8, 16), 1, 0, 9, 1}, + {2, UPB_SIZE(20, 40), 0, 2, 11, 3}, + {3, UPB_SIZE(16, 32), 2, 1, 11, 1}, + {4, UPB_SIZE(24, 48), 0, 0, 11, 3}, + {5, UPB_SIZE(28, 56), 0, 0, 9, 3}, +}; + +const upb_msglayout google_protobuf_EnumDescriptorProto_msginit = { + &google_protobuf_EnumDescriptorProto_submsgs[0], + &google_protobuf_EnumDescriptorProto__fields[0], + UPB_SIZE(32, 64), 5, false, +}; + +static const upb_msglayout_field google_protobuf_EnumDescriptorProto_EnumReservedRange__fields[2] = { + {1, UPB_SIZE(4, 4), 1, 0, 5, 1}, + {2, UPB_SIZE(8, 8), 2, 0, 5, 1}, +}; + +const upb_msglayout google_protobuf_EnumDescriptorProto_EnumReservedRange_msginit = { + NULL, + &google_protobuf_EnumDescriptorProto_EnumReservedRange__fields[0], + UPB_SIZE(12, 12), 2, false, +}; + +static const upb_msglayout *const google_protobuf_EnumValueDescriptorProto_submsgs[1] = { + &google_protobuf_EnumValueOptions_msginit, +}; + +static const upb_msglayout_field google_protobuf_EnumValueDescriptorProto__fields[3] = { + {1, UPB_SIZE(8, 16), 2, 0, 9, 1}, + {2, UPB_SIZE(4, 4), 1, 0, 5, 1}, + {3, UPB_SIZE(16, 32), 3, 0, 11, 1}, +}; + +const upb_msglayout google_protobuf_EnumValueDescriptorProto_msginit = { + &google_protobuf_EnumValueDescriptorProto_submsgs[0], + &google_protobuf_EnumValueDescriptorProto__fields[0], + UPB_SIZE(24, 48), 3, false, +}; + +static const upb_msglayout *const google_protobuf_ServiceDescriptorProto_submsgs[2] = { + &google_protobuf_MethodDescriptorProto_msginit, + &google_protobuf_ServiceOptions_msginit, +}; + +static const upb_msglayout_field google_protobuf_ServiceDescriptorProto__fields[3] = { + {1, UPB_SIZE(8, 16), 1, 0, 9, 1}, + {2, UPB_SIZE(20, 40), 0, 0, 11, 3}, + {3, UPB_SIZE(16, 32), 2, 1, 11, 1}, +}; + +const upb_msglayout google_protobuf_ServiceDescriptorProto_msginit = { + &google_protobuf_ServiceDescriptorProto_submsgs[0], + &google_protobuf_ServiceDescriptorProto__fields[0], + UPB_SIZE(24, 48), 3, false, +}; + +static const upb_msglayout *const google_protobuf_MethodDescriptorProto_submsgs[1] = { + &google_protobuf_MethodOptions_msginit, +}; + +static const upb_msglayout_field google_protobuf_MethodDescriptorProto__fields[6] = { + {1, UPB_SIZE(8, 16), 3, 0, 9, 1}, + {2, UPB_SIZE(16, 32), 4, 0, 9, 1}, + {3, UPB_SIZE(24, 48), 5, 0, 9, 1}, + {4, UPB_SIZE(32, 64), 6, 0, 11, 1}, + {5, UPB_SIZE(1, 1), 1, 0, 8, 1}, + {6, UPB_SIZE(2, 2), 2, 0, 8, 1}, +}; + +const upb_msglayout google_protobuf_MethodDescriptorProto_msginit = { + &google_protobuf_MethodDescriptorProto_submsgs[0], + &google_protobuf_MethodDescriptorProto__fields[0], + UPB_SIZE(40, 80), 6, false, +}; + +static const upb_msglayout *const google_protobuf_FileOptions_submsgs[1] = { + &google_protobuf_UninterpretedOption_msginit, +}; + +static const upb_msglayout_field google_protobuf_FileOptions__fields[19] = { + {1, UPB_SIZE(32, 32), 11, 0, 9, 1}, + {8, UPB_SIZE(40, 48), 12, 0, 9, 1}, + {9, UPB_SIZE(8, 8), 1, 0, 14, 1}, + {10, UPB_SIZE(16, 16), 2, 0, 8, 1}, + {11, UPB_SIZE(48, 64), 13, 0, 9, 1}, + {16, UPB_SIZE(17, 17), 3, 0, 8, 1}, + {17, UPB_SIZE(18, 18), 4, 0, 8, 1}, + {18, UPB_SIZE(19, 19), 5, 0, 8, 1}, + {20, UPB_SIZE(20, 20), 6, 0, 8, 1}, + {23, UPB_SIZE(21, 21), 7, 0, 8, 1}, + {27, UPB_SIZE(22, 22), 8, 0, 8, 1}, + {31, UPB_SIZE(23, 23), 9, 0, 8, 1}, + {36, UPB_SIZE(56, 80), 14, 0, 9, 1}, + {37, UPB_SIZE(64, 96), 15, 0, 9, 1}, + {39, UPB_SIZE(72, 112), 16, 0, 9, 1}, + {40, UPB_SIZE(80, 128), 17, 0, 9, 1}, + {41, UPB_SIZE(88, 144), 18, 0, 9, 1}, + {42, UPB_SIZE(24, 24), 10, 0, 8, 1}, + {999, UPB_SIZE(96, 160), 0, 0, 11, 3}, +}; + +const upb_msglayout google_protobuf_FileOptions_msginit = { + &google_protobuf_FileOptions_submsgs[0], + &google_protobuf_FileOptions__fields[0], + UPB_SIZE(104, 176), 19, false, +}; + +static const upb_msglayout *const google_protobuf_MessageOptions_submsgs[1] = { + &google_protobuf_UninterpretedOption_msginit, +}; + +static const upb_msglayout_field google_protobuf_MessageOptions__fields[5] = { + {1, UPB_SIZE(1, 1), 1, 0, 8, 1}, + {2, UPB_SIZE(2, 2), 2, 0, 8, 1}, + {3, UPB_SIZE(3, 3), 3, 0, 8, 1}, + {7, UPB_SIZE(4, 4), 4, 0, 8, 1}, + {999, UPB_SIZE(8, 8), 0, 0, 11, 3}, +}; + +const upb_msglayout google_protobuf_MessageOptions_msginit = { + &google_protobuf_MessageOptions_submsgs[0], + &google_protobuf_MessageOptions__fields[0], + UPB_SIZE(12, 16), 5, false, +}; + +static const upb_msglayout *const google_protobuf_FieldOptions_submsgs[1] = { + &google_protobuf_UninterpretedOption_msginit, +}; + +static const upb_msglayout_field google_protobuf_FieldOptions__fields[7] = { + {1, UPB_SIZE(8, 8), 1, 0, 14, 1}, + {2, UPB_SIZE(24, 24), 3, 0, 8, 1}, + {3, UPB_SIZE(25, 25), 4, 0, 8, 1}, + {5, UPB_SIZE(26, 26), 5, 0, 8, 1}, + {6, UPB_SIZE(16, 16), 2, 0, 14, 1}, + {10, UPB_SIZE(27, 27), 6, 0, 8, 1}, + {999, UPB_SIZE(28, 32), 0, 0, 11, 3}, +}; + +const upb_msglayout google_protobuf_FieldOptions_msginit = { + &google_protobuf_FieldOptions_submsgs[0], + &google_protobuf_FieldOptions__fields[0], + UPB_SIZE(32, 40), 7, false, +}; + +static const upb_msglayout *const google_protobuf_OneofOptions_submsgs[1] = { + &google_protobuf_UninterpretedOption_msginit, +}; + +static const upb_msglayout_field google_protobuf_OneofOptions__fields[1] = { + {999, UPB_SIZE(0, 0), 0, 0, 11, 3}, +}; + +const upb_msglayout google_protobuf_OneofOptions_msginit = { + &google_protobuf_OneofOptions_submsgs[0], + &google_protobuf_OneofOptions__fields[0], + UPB_SIZE(4, 8), 1, false, +}; + +static const upb_msglayout *const google_protobuf_EnumOptions_submsgs[1] = { + &google_protobuf_UninterpretedOption_msginit, +}; + +static const upb_msglayout_field google_protobuf_EnumOptions__fields[3] = { + {2, UPB_SIZE(1, 1), 1, 0, 8, 1}, + {3, UPB_SIZE(2, 2), 2, 0, 8, 1}, + {999, UPB_SIZE(4, 8), 0, 0, 11, 3}, +}; + +const upb_msglayout google_protobuf_EnumOptions_msginit = { + &google_protobuf_EnumOptions_submsgs[0], + &google_protobuf_EnumOptions__fields[0], + UPB_SIZE(8, 16), 3, false, +}; + +static const upb_msglayout *const google_protobuf_EnumValueOptions_submsgs[1] = { + &google_protobuf_UninterpretedOption_msginit, +}; + +static const upb_msglayout_field google_protobuf_EnumValueOptions__fields[2] = { + {1, UPB_SIZE(1, 1), 1, 0, 8, 1}, + {999, UPB_SIZE(4, 8), 0, 0, 11, 3}, +}; + +const upb_msglayout google_protobuf_EnumValueOptions_msginit = { + &google_protobuf_EnumValueOptions_submsgs[0], + &google_protobuf_EnumValueOptions__fields[0], + UPB_SIZE(8, 16), 2, false, +}; + +static const upb_msglayout *const google_protobuf_ServiceOptions_submsgs[1] = { + &google_protobuf_UninterpretedOption_msginit, +}; + +static const upb_msglayout_field google_protobuf_ServiceOptions__fields[2] = { + {33, UPB_SIZE(1, 1), 1, 0, 8, 1}, + {999, UPB_SIZE(4, 8), 0, 0, 11, 3}, +}; + +const upb_msglayout google_protobuf_ServiceOptions_msginit = { + &google_protobuf_ServiceOptions_submsgs[0], + &google_protobuf_ServiceOptions__fields[0], + UPB_SIZE(8, 16), 2, false, +}; + +static const upb_msglayout *const google_protobuf_MethodOptions_submsgs[1] = { + &google_protobuf_UninterpretedOption_msginit, +}; + +static const upb_msglayout_field google_protobuf_MethodOptions__fields[3] = { + {33, UPB_SIZE(16, 16), 2, 0, 8, 1}, + {34, UPB_SIZE(8, 8), 1, 0, 14, 1}, + {999, UPB_SIZE(20, 24), 0, 0, 11, 3}, +}; + +const upb_msglayout google_protobuf_MethodOptions_msginit = { + &google_protobuf_MethodOptions_submsgs[0], + &google_protobuf_MethodOptions__fields[0], + UPB_SIZE(24, 32), 3, false, +}; + +static const upb_msglayout *const google_protobuf_UninterpretedOption_submsgs[1] = { + &google_protobuf_UninterpretedOption_NamePart_msginit, +}; + +static const upb_msglayout_field google_protobuf_UninterpretedOption__fields[7] = { + {2, UPB_SIZE(56, 80), 0, 0, 11, 3}, + {3, UPB_SIZE(32, 32), 4, 0, 9, 1}, + {4, UPB_SIZE(8, 8), 1, 0, 4, 1}, + {5, UPB_SIZE(16, 16), 2, 0, 3, 1}, + {6, UPB_SIZE(24, 24), 3, 0, 1, 1}, + {7, UPB_SIZE(40, 48), 5, 0, 12, 1}, + {8, UPB_SIZE(48, 64), 6, 0, 9, 1}, +}; + +const upb_msglayout google_protobuf_UninterpretedOption_msginit = { + &google_protobuf_UninterpretedOption_submsgs[0], + &google_protobuf_UninterpretedOption__fields[0], + UPB_SIZE(64, 96), 7, false, +}; + +static const upb_msglayout_field google_protobuf_UninterpretedOption_NamePart__fields[2] = { + {1, UPB_SIZE(8, 16), 2, 0, 9, 2}, + {2, UPB_SIZE(1, 1), 1, 0, 8, 2}, +}; + +const upb_msglayout google_protobuf_UninterpretedOption_NamePart_msginit = { + NULL, + &google_protobuf_UninterpretedOption_NamePart__fields[0], + UPB_SIZE(16, 32), 2, false, +}; + +static const upb_msglayout *const google_protobuf_SourceCodeInfo_submsgs[1] = { + &google_protobuf_SourceCodeInfo_Location_msginit, +}; + +static const upb_msglayout_field google_protobuf_SourceCodeInfo__fields[1] = { + {1, UPB_SIZE(0, 0), 0, 0, 11, 3}, +}; + +const upb_msglayout google_protobuf_SourceCodeInfo_msginit = { + &google_protobuf_SourceCodeInfo_submsgs[0], + &google_protobuf_SourceCodeInfo__fields[0], + UPB_SIZE(4, 8), 1, false, +}; + +static const upb_msglayout_field google_protobuf_SourceCodeInfo_Location__fields[5] = { + {1, UPB_SIZE(24, 48), 0, 0, 5, 3}, + {2, UPB_SIZE(28, 56), 0, 0, 5, 3}, + {3, UPB_SIZE(8, 16), 1, 0, 9, 1}, + {4, UPB_SIZE(16, 32), 2, 0, 9, 1}, + {6, UPB_SIZE(32, 64), 0, 0, 9, 3}, +}; + +const upb_msglayout google_protobuf_SourceCodeInfo_Location_msginit = { + NULL, + &google_protobuf_SourceCodeInfo_Location__fields[0], + UPB_SIZE(40, 80), 5, false, +}; + +static const upb_msglayout *const google_protobuf_GeneratedCodeInfo_submsgs[1] = { + &google_protobuf_GeneratedCodeInfo_Annotation_msginit, +}; + +static const upb_msglayout_field google_protobuf_GeneratedCodeInfo__fields[1] = { + {1, UPB_SIZE(0, 0), 0, 0, 11, 3}, +}; + +const upb_msglayout google_protobuf_GeneratedCodeInfo_msginit = { + &google_protobuf_GeneratedCodeInfo_submsgs[0], + &google_protobuf_GeneratedCodeInfo__fields[0], + UPB_SIZE(4, 8), 1, false, +}; + +static const upb_msglayout_field google_protobuf_GeneratedCodeInfo_Annotation__fields[4] = { + {1, UPB_SIZE(24, 32), 0, 0, 5, 3}, + {2, UPB_SIZE(16, 16), 3, 0, 9, 1}, + {3, UPB_SIZE(4, 4), 1, 0, 5, 1}, + {4, UPB_SIZE(8, 8), 2, 0, 5, 1}, +}; + +const upb_msglayout google_protobuf_GeneratedCodeInfo_Annotation_msginit = { + NULL, + &google_protobuf_GeneratedCodeInfo_Annotation__fields[0], + UPB_SIZE(32, 48), 4, false, +}; + + + /* Maps descriptor type -> upb field type. */ -static const uint8_t upb_desctype_to_fieldtype[] = { +const uint8_t upb_desctype_to_fieldtype[] = { UPB_WIRE_TYPE_END_GROUP, /* ENDGROUP */ UPB_TYPE_DOUBLE, /* DOUBLE */ UPB_TYPE_FLOAT, /* FLOAT */ @@ -27,7 +524,6 @@ static const uint8_t upb_desctype_to_fieldtype[] = { /* Data pertaining to the parse. */ typedef struct { - upb_env *env; /* Current decoding pointer. Points to the beginning of a field until we * have finished decoding the whole field. */ const char *ptr; @@ -40,7 +536,7 @@ typedef struct { /* These members are unset for an unknown group frame. */ char *msg; - const upb_msglayout_msginit_v1 *m; + const upb_msglayout *m; } upb_decframe; #define CHK(x) if (!(x)) { return false; } @@ -49,7 +545,7 @@ static bool upb_skip_unknowngroup(upb_decstate *d, int field_number, const char *limit); static bool upb_decode_message(upb_decstate *d, const char *limit, int group_number, char *msg, - const upb_msglayout_msginit_v1 *l); + const upb_msglayout *l); static bool upb_decode_varint(const char **ptr, const char *limit, uint64_t *val) { @@ -130,9 +626,7 @@ static void upb_set32(void *msg, size_t ofs, uint32_t val) { static bool upb_append_unknown(upb_decstate *d, upb_decframe *frame, const char *start) { - UPB_UNUSED(d); - UPB_UNUSED(frame); - UPB_UNUSED(start); + upb_msg_addunknown(frame->msg, start, d->ptr - start); return true; } @@ -171,6 +665,7 @@ static bool upb_array_grow(upb_array *arr, size_t elements) { size_t new_bytes; size_t old_bytes; void *new_data; + upb_alloc *alloc = upb_arena_alloc(arr->arena); while (new_size < needed) { new_size *= 2; @@ -178,7 +673,7 @@ static bool upb_array_grow(upb_array *arr, size_t elements) { old_bytes = arr->len * arr->element_size; new_bytes = new_size * arr->element_size; - new_data = upb_realloc(arr->alloc, arr->data, old_bytes, new_bytes); + new_data = upb_realloc(alloc, arr->data, old_bytes, new_bytes); CHK(new_data); arr->data = new_data; @@ -200,23 +695,21 @@ static void *upb_array_add(upb_array *arr, size_t elements) { } static upb_array *upb_getarr(upb_decframe *frame, - const upb_msglayout_fieldinit_v1 *field) { + const upb_msglayout_field *field) { UPB_ASSERT(field->label == UPB_LABEL_REPEATED); return *(upb_array**)&frame->msg[field->offset]; } -static upb_array *upb_getorcreatearr(upb_decstate *d, - upb_decframe *frame, - const upb_msglayout_fieldinit_v1 *field) { +static upb_array *upb_getorcreatearr(upb_decframe *frame, + const upb_msglayout_field *field) { upb_array *arr = upb_getarr(frame, field); if (!arr) { - arr = upb_env_malloc(d->env, sizeof(*arr)); + upb_fieldtype_t type = upb_desctype_to_fieldtype[field->descriptortype]; + arr = upb_array_new(type, upb_msg_arena(frame->msg)); if (!arr) { return NULL; } - upb_array_init(arr, upb_desctype_to_fieldtype[field->type], - upb_arena_alloc(upb_env_arena(d->env))); *(upb_array**)&frame->msg[field->offset] = arr; } @@ -224,26 +717,25 @@ static upb_array *upb_getorcreatearr(upb_decstate *d, } static void upb_sethasbit(upb_decframe *frame, - const upb_msglayout_fieldinit_v1 *field) { - UPB_ASSERT(field->hasbit != UPB_NO_HASBIT); - frame->msg[field->hasbit / 8] |= (1 << (field->hasbit % 8)); + const upb_msglayout_field *field) { + int32_t hasbit = field->presence; + UPB_ASSERT(field->presence > 0); + frame->msg[hasbit / 8] |= (1 << (hasbit % 8)); } static void upb_setoneofcase(upb_decframe *frame, - const upb_msglayout_fieldinit_v1 *field) { - UPB_ASSERT(field->oneof_index != UPB_NOT_IN_ONEOF); - upb_set32(frame->msg, frame->m->oneofs[field->oneof_index].case_offset, - field->number); + const upb_msglayout_field *field) { + UPB_ASSERT(field->presence < 0); + upb_set32(frame->msg, ~field->presence, field->number); } -static char *upb_decode_prepareslot(upb_decstate *d, - upb_decframe *frame, - const upb_msglayout_fieldinit_v1 *field) { +static char *upb_decode_prepareslot(upb_decframe *frame, + const upb_msglayout_field *field) { char *field_mem = frame->msg + field->offset; upb_array *arr; if (field->label == UPB_LABEL_REPEATED) { - arr = upb_getorcreatearr(d, frame, field); + arr = upb_getorcreatearr(frame, field); field_mem = upb_array_reserve(arr, 1); } @@ -251,36 +743,33 @@ static char *upb_decode_prepareslot(upb_decstate *d, } static void upb_decode_setpresent(upb_decframe *frame, - const upb_msglayout_fieldinit_v1 *field) { + const upb_msglayout_field *field) { if (field->label == UPB_LABEL_REPEATED) { upb_array *arr = upb_getarr(frame, field); UPB_ASSERT(arr->len < arr->size); arr->len++; - } else if (field->oneof_index != UPB_NOT_IN_ONEOF) { + } else if (field->presence < 0) { upb_setoneofcase(frame, field); - } else if (field->hasbit != UPB_NO_HASBIT) { + } else if (field->presence > 0) { upb_sethasbit(frame, field); } } -static bool upb_decode_submsg(upb_decstate *d, - upb_decframe *frame, +static bool upb_decode_submsg(upb_decstate *d, upb_decframe *frame, const char *limit, - const upb_msglayout_fieldinit_v1 *field, + const upb_msglayout_field *field, int group_number) { - char *submsg = *(void**)&frame->msg[field->offset]; - const upb_msglayout_msginit_v1 *subm; + char *submsg_slot = upb_decode_prepareslot(frame, field); + char *submsg = *(void **)submsg_slot; + const upb_msglayout *subm; - UPB_ASSERT(field->submsg_index != UPB_NO_SUBMSG); subm = frame->m->submsgs[field->submsg_index]; UPB_ASSERT(subm); if (!submsg) { - submsg = upb_env_malloc(d->env, upb_msg_sizeof((upb_msglayout *)subm)); + submsg = upb_msg_new(subm, upb_msg_arena(frame->msg)); CHK(submsg); - submsg = upb_msg_init( - submsg, (upb_msglayout*)subm, upb_arena_alloc(upb_env_arena(d->env))); - *(void**)&frame->msg[field->offset] = submsg; + *(void**)submsg_slot = submsg; } upb_decode_message(d, limit, group_number, submsg, subm); @@ -290,15 +779,15 @@ static bool upb_decode_submsg(upb_decstate *d, static bool upb_decode_varintfield(upb_decstate *d, upb_decframe *frame, const char *field_start, - const upb_msglayout_fieldinit_v1 *field) { + const upb_msglayout_field *field) { uint64_t val; void *field_mem; - field_mem = upb_decode_prepareslot(d, frame, field); + field_mem = upb_decode_prepareslot(frame, field); CHK(field_mem); CHK(upb_decode_varint(&d->ptr, frame->limit, &val)); - switch ((upb_descriptortype_t)field->type) { + switch ((upb_descriptortype_t)field->descriptortype) { case UPB_DESCRIPTOR_TYPE_INT64: case UPB_DESCRIPTOR_TYPE_UINT64: memcpy(field_mem, &val, sizeof(val)); @@ -335,15 +824,15 @@ static bool upb_decode_varintfield(upb_decstate *d, upb_decframe *frame, static bool upb_decode_64bitfield(upb_decstate *d, upb_decframe *frame, const char *field_start, - const upb_msglayout_fieldinit_v1 *field) { + const upb_msglayout_field *field) { void *field_mem; uint64_t val; - field_mem = upb_decode_prepareslot(d, frame, field); + field_mem = upb_decode_prepareslot(frame, field); CHK(field_mem); CHK(upb_decode_64bit(&d->ptr, frame->limit, &val)); - switch ((upb_descriptortype_t)field->type) { + switch ((upb_descriptortype_t)field->descriptortype) { case UPB_DESCRIPTOR_TYPE_DOUBLE: case UPB_DESCRIPTOR_TYPE_FIXED64: case UPB_DESCRIPTOR_TYPE_SFIXED64: @@ -359,15 +848,15 @@ static bool upb_decode_64bitfield(upb_decstate *d, upb_decframe *frame, static bool upb_decode_32bitfield(upb_decstate *d, upb_decframe *frame, const char *field_start, - const upb_msglayout_fieldinit_v1 *field) { + const upb_msglayout_field *field) { void *field_mem; uint32_t val; - field_mem = upb_decode_prepareslot(d, frame, field); + field_mem = upb_decode_prepareslot(frame, field); CHK(field_mem); CHK(upb_decode_32bit(&d->ptr, frame->limit, &val)); - switch ((upb_descriptortype_t)field->type) { + switch ((upb_descriptortype_t)field->descriptortype) { case UPB_DESCRIPTOR_TYPE_FLOAT: case UPB_DESCRIPTOR_TYPE_FIXED32: case UPB_DESCRIPTOR_TYPE_SFIXED32: @@ -395,9 +884,9 @@ static bool upb_decode_fixedpacked(upb_array *arr, upb_stringview data, static bool upb_decode_toarray(upb_decstate *d, upb_decframe *frame, const char *field_start, - const upb_msglayout_fieldinit_v1 *field, + const upb_msglayout_field *field, upb_stringview val) { - upb_array *arr = upb_getorcreatearr(d, frame, field); + upb_array *arr = upb_getorcreatearr(frame, field); #define VARINT_CASE(ctype, decode) { \ const char *ptr = val.data; \ @@ -415,7 +904,7 @@ static bool upb_decode_toarray(upb_decstate *d, upb_decframe *frame, return true; \ } - switch ((upb_descriptortype_t)field->type) { + switch ((upb_descriptortype_t)field->descriptortype) { case UPB_DESCRIPTOR_TYPE_STRING: case UPB_DESCRIPTOR_TYPE_BYTES: { void *field_mem = upb_array_add(arr, 1); @@ -445,9 +934,28 @@ static bool upb_decode_toarray(upb_decstate *d, upb_decframe *frame, VARINT_CASE(int32_t, upb_zzdecode_32); case UPB_DESCRIPTOR_TYPE_SINT64: VARINT_CASE(int64_t, upb_zzdecode_64); - case UPB_DESCRIPTOR_TYPE_MESSAGE: + case UPB_DESCRIPTOR_TYPE_MESSAGE: { + const upb_msglayout *subm; + char *submsg; + void *field_mem; + CHK(val.size <= (size_t)(frame->limit - val.data)); - return upb_decode_submsg(d, frame, val.data + val.size, field, 0); + d->ptr -= val.size; + + /* Create elemente message. */ + subm = frame->m->submsgs[field->submsg_index]; + UPB_ASSERT(subm); + + submsg = upb_msg_new(subm, upb_msg_arena(frame->msg)); + CHK(submsg); + + field_mem = upb_array_add(arr, 1); + CHK(field_mem); + *(void**)field_mem = submsg; + + return upb_decode_message( + d, val.data + val.size, frame->group_number, submsg, subm); + } case UPB_DESCRIPTOR_TYPE_GROUP: return upb_append_unknown(d, frame, field_start); } @@ -457,7 +965,7 @@ static bool upb_decode_toarray(upb_decstate *d, upb_decframe *frame, static bool upb_decode_delimitedfield(upb_decstate *d, upb_decframe *frame, const char *field_start, - const upb_msglayout_fieldinit_v1 *field) { + const upb_msglayout_field *field) { upb_stringview val; CHK(upb_decode_string(&d->ptr, frame->limit, &val)); @@ -465,16 +973,17 @@ static bool upb_decode_delimitedfield(upb_decstate *d, upb_decframe *frame, if (field->label == UPB_LABEL_REPEATED) { return upb_decode_toarray(d, frame, field_start, field, val); } else { - switch ((upb_descriptortype_t)field->type) { + switch ((upb_descriptortype_t)field->descriptortype) { case UPB_DESCRIPTOR_TYPE_STRING: case UPB_DESCRIPTOR_TYPE_BYTES: { - void *field_mem = upb_decode_prepareslot(d, frame, field); + void *field_mem = upb_decode_prepareslot(frame, field); CHK(field_mem); memcpy(field_mem, &val, sizeof(val)); break; } case UPB_DESCRIPTOR_TYPE_MESSAGE: CHK(val.size <= (size_t)(frame->limit - val.data)); + d->ptr -= val.size; CHK(upb_decode_submsg(d, frame, val.data + val.size, field, 0)); break; default: @@ -486,8 +995,8 @@ static bool upb_decode_delimitedfield(upb_decstate *d, upb_decframe *frame, } } -static const upb_msglayout_fieldinit_v1 *upb_find_field( - const upb_msglayout_msginit_v1 *l, uint32_t field_number) { +static const upb_msglayout_field *upb_find_field(const upb_msglayout *l, + uint32_t field_number) { /* Lots of optimization opportunities here. */ int i; for (i = 0; i < l->field_count; i++) { @@ -503,7 +1012,7 @@ static bool upb_decode_field(upb_decstate *d, upb_decframe *frame) { int field_number; int wire_type; const char *field_start = d->ptr; - const upb_msglayout_fieldinit_v1 *field; + const upb_msglayout_field *field; CHK(upb_decode_tag(&d->ptr, frame->limit, &field_number, &wire_type)); field = upb_find_field(frame->m, field_number); @@ -519,7 +1028,7 @@ static bool upb_decode_field(upb_decstate *d, upb_decframe *frame) { case UPB_WIRE_TYPE_DELIMITED: return upb_decode_delimitedfield(d, frame, field_start, field); case UPB_WIRE_TYPE_START_GROUP: - CHK(field->type == UPB_DESCRIPTOR_TYPE_GROUP); + CHK(field->descriptortype == UPB_DESCRIPTOR_TYPE_GROUP); return upb_decode_submsg(d, frame, frame->limit, field, field_number); case UPB_WIRE_TYPE_END_GROUP: CHK(frame->group_number == field_number) @@ -530,7 +1039,9 @@ static bool upb_decode_field(upb_decstate *d, upb_decframe *frame) { } } else { CHK(field_number != 0); - return upb_skip_unknownfielddata(d, frame, field_number, wire_type); + CHK(upb_skip_unknownfielddata(d, frame, field_number, wire_type)); + CHK(upb_append_unknown(d, frame, field_start)); + return true; } } @@ -555,7 +1066,7 @@ static bool upb_skip_unknowngroup(upb_decstate *d, int field_number, static bool upb_decode_message(upb_decstate *d, const char *limit, int group_number, char *msg, - const upb_msglayout_msginit_v1 *l) { + const upb_msglayout *l) { upb_decframe frame; frame.group_number = group_number; frame.limit = limit; @@ -569,11 +1080,9 @@ static bool upb_decode_message(upb_decstate *d, const char *limit, return true; } -bool upb_decode(upb_stringview buf, void *msg, - const upb_msglayout_msginit_v1 *l, upb_env *env) { +bool upb_decode(upb_stringview buf, void *msg, const upb_msglayout *l) { upb_decstate state; state.ptr = buf.data; - state.env = env; return upb_decode_message(&state, buf.data + buf.size, 0, msg, l); } @@ -943,6 +1452,45 @@ static bool assign_msg_indices(upb_msgdef *m, upb_status *s) { return true; } +static void assign_msg_wellknowntype(upb_msgdef *m) { + const char *name = upb_msgdef_fullname(m); + if (name == NULL) { + m->well_known_type = UPB_WELLKNOWN_UNSPECIFIED; + return; + } + if (!strcmp(name, "google.protobuf.Duration")) { + m->well_known_type = UPB_WELLKNOWN_DURATION; + } else if (!strcmp(name, "google.protobuf.Timestamp")) { + m->well_known_type = UPB_WELLKNOWN_TIMESTAMP; + } else if (!strcmp(name, "google.protobuf.DoubleValue")) { + m->well_known_type = UPB_WELLKNOWN_DOUBLEVALUE; + } else if (!strcmp(name, "google.protobuf.FloatValue")) { + m->well_known_type = UPB_WELLKNOWN_FLOATVALUE; + } else if (!strcmp(name, "google.protobuf.Int64Value")) { + m->well_known_type = UPB_WELLKNOWN_INT64VALUE; + } else if (!strcmp(name, "google.protobuf.UInt64Value")) { + m->well_known_type = UPB_WELLKNOWN_UINT64VALUE; + } else if (!strcmp(name, "google.protobuf.Int32Value")) { + m->well_known_type = UPB_WELLKNOWN_INT32VALUE; + } else if (!strcmp(name, "google.protobuf.UInt32Value")) { + m->well_known_type = UPB_WELLKNOWN_UINT32VALUE; + } else if (!strcmp(name, "google.protobuf.BoolValue")) { + m->well_known_type = UPB_WELLKNOWN_BOOLVALUE; + } else if (!strcmp(name, "google.protobuf.StringValue")) { + m->well_known_type = UPB_WELLKNOWN_STRINGVALUE; + } else if (!strcmp(name, "google.protobuf.BytesValue")) { + m->well_known_type = UPB_WELLKNOWN_BYTESVALUE; + } else if (!strcmp(name, "google.protobuf.Value")) { + m->well_known_type = UPB_WELLKNOWN_VALUE; + } else if (!strcmp(name, "google.protobuf.ListValue")) { + m->well_known_type = UPB_WELLKNOWN_LISTVALUE; + } else if (!strcmp(name, "google.protobuf.Struct")) { + m->well_known_type = UPB_WELLKNOWN_STRUCT; + } else { + m->well_known_type = UPB_WELLKNOWN_UNSPECIFIED; + } +} + bool _upb_def_validate(upb_def *const*defs, size_t n, upb_status *s) { size_t i; @@ -979,6 +1527,8 @@ bool _upb_def_validate(upb_def *const*defs, size_t n, upb_status *s) { if (!assign_msg_indices(m, s)) { goto err; } + assign_msg_wellknowntype(m); + /* m->well_known_type = UPB_WELLKNOWN_UNSPECIFIED; */ } else if (e) { upb_inttable_compact(&e->iton); } @@ -2171,6 +2721,16 @@ bool upb_msgdef_mapentry(const upb_msgdef *m) { return m->map_entry; } +upb_wellknowntype_t upb_msgdef_wellknowntype(const upb_msgdef *m) { + return m->well_known_type; +} + +bool upb_msgdef_isnumberwrapper(const upb_msgdef *m) { + upb_wellknowntype_t type = upb_msgdef_wellknowntype(m); + return type >= UPB_WELLKNOWN_DOUBLEVALUE && + type <= UPB_WELLKNOWN_UINT32VALUE; +} + void upb_msg_field_begin(upb_msg_field_iter *iter, const upb_msgdef *m) { upb_inttable_begin(iter, &m->itof); } @@ -2985,7 +3545,7 @@ static uint32_t upb_zzencode_32(int32_t n) { return (n << 1) ^ (n >> 31); } static uint64_t upb_zzencode_64(int64_t n) { return (n << 1) ^ (n >> 63); } typedef struct { - upb_env *env; + upb_alloc *alloc; char *buf, *ptr, *limit; } upb_encstate; @@ -3000,11 +3560,11 @@ static size_t upb_roundup_pow2(size_t bytes) { static bool upb_encode_growbuffer(upb_encstate *e, size_t bytes) { size_t old_size = e->limit - e->buf; size_t new_size = upb_roundup_pow2(bytes + (e->limit - e->ptr)); - char *new_buf = upb_env_realloc(e->env, e->buf, old_size, new_size); + char *new_buf = upb_realloc(e->alloc, e->buf, old_size, new_size); CHK(new_buf); /* We want previous data at the end, realloc() put it at the beginning. */ - memmove(e->limit - old_size, e->buf, old_size); + memmove(new_buf + new_size - old_size, e->buf, old_size); e->ptr = new_buf + new_size - (e->limit - e->ptr); e->limit = new_buf + new_size; @@ -3064,17 +3624,17 @@ static bool upb_put_float(upb_encstate *e, float d) { return upb_put_fixed32(e, u32); } -static uint32_t upb_readcase(const char *msg, const upb_msglayout_msginit_v1 *m, - int oneof_index) { +static uint32_t upb_readcase(const char *msg, const upb_msglayout_field *f) { uint32_t ret; - memcpy(&ret, msg + m->oneofs[oneof_index].case_offset, sizeof(ret)); + uint32_t offset = ~f->presence; + memcpy(&ret, msg + offset, sizeof(ret)); return ret; } -static bool upb_readhasbit(const char *msg, - const upb_msglayout_fieldinit_v1 *f) { - UPB_ASSERT(f->hasbit != UPB_NO_HASBIT); - return msg[f->hasbit / 8] & (1 << (f->hasbit % 8)); +static bool upb_readhasbit(const char *msg, const upb_msglayout_field *f) { + uint32_t hasbit = f->presence; + UPB_ASSERT(f->presence > 0); + return msg[hasbit / 8] & (1 << (hasbit % 8)); } static bool upb_put_tag(upb_encstate *e, int field_number, int wire_type) { @@ -3088,19 +3648,18 @@ static bool upb_put_fixedarray(upb_encstate *e, const upb_array *arr, } bool upb_encode_message(upb_encstate *e, const char *msg, - const upb_msglayout_msginit_v1 *m, - size_t *size); + const upb_msglayout *m, size_t *size); static bool upb_encode_array(upb_encstate *e, const char *field_mem, - const upb_msglayout_msginit_v1 *m, - const upb_msglayout_fieldinit_v1 *f) { + const upb_msglayout *m, + const upb_msglayout_field *f) { const upb_array *arr = *(const upb_array**)field_mem; if (arr == NULL || arr->len == 0) { return true; } - UPB_ASSERT(arr->type == upb_desctype_to_fieldtype2[f->type]); + UPB_ASSERT(arr->type == upb_desctype_to_fieldtype2[f->descriptortype]); #define VARINT_CASE(ctype, encode) { \ ctype *start = arr->data; \ @@ -3115,7 +3674,7 @@ static bool upb_encode_array(upb_encstate *e, const char *field_mem, break; \ do { ; } while(0) - switch (f->type) { + switch (f->descriptortype) { case UPB_DESCRIPTOR_TYPE_DOUBLE: CHK(upb_put_fixedarray(e, arr, sizeof(double))); break; @@ -3134,9 +3693,10 @@ do { ; } while(0) case UPB_DESCRIPTOR_TYPE_UINT64: VARINT_CASE(uint64_t, *ptr); case UPB_DESCRIPTOR_TYPE_UINT32: + VARINT_CASE(uint32_t, *ptr); case UPB_DESCRIPTOR_TYPE_INT32: case UPB_DESCRIPTOR_TYPE_ENUM: - VARINT_CASE(uint32_t, *ptr); + VARINT_CASE(int32_t, (int64_t)*ptr); case UPB_DESCRIPTOR_TYPE_BOOL: VARINT_CASE(bool, *ptr); case UPB_DESCRIPTOR_TYPE_SINT32: @@ -3158,7 +3718,7 @@ do { ; } while(0) case UPB_DESCRIPTOR_TYPE_GROUP: { void **start = arr->data; void **ptr = start + arr->len; - const upb_msglayout_msginit_v1 *subm = m->submsgs[f->submsg_index]; + const upb_msglayout *subm = m->submsgs[f->submsg_index]; do { size_t size; ptr--; @@ -3171,7 +3731,7 @@ do { ; } while(0) case UPB_DESCRIPTOR_TYPE_MESSAGE: { void **start = arr->data; void **ptr = start + arr->len; - const upb_msglayout_msginit_v1 *subm = m->submsgs[f->submsg_index]; + const upb_msglayout *subm = m->submsgs[f->submsg_index]; do { size_t size; ptr--; @@ -3191,11 +3751,9 @@ do { ; } while(0) } static bool upb_encode_scalarfield(upb_encstate *e, const char *field_mem, - const upb_msglayout_msginit_v1 *m, - const upb_msglayout_fieldinit_v1 *f, - bool is_proto3) { - bool skip_zero_value = is_proto3 && f->oneof_index == UPB_NOT_IN_ONEOF; - + const upb_msglayout *m, + const upb_msglayout_field *f, + bool skip_zero_value) { #define CASE(ctype, type, wire_type, encodeval) do { \ ctype val = *(ctype*)field_mem; \ if (skip_zero_value && val == 0) { \ @@ -3205,7 +3763,7 @@ static bool upb_encode_scalarfield(upb_encstate *e, const char *field_mem, upb_put_tag(e, f->number, wire_type); \ } while(0) - switch (f->type) { + switch (f->descriptortype) { case UPB_DESCRIPTOR_TYPE_DOUBLE: CASE(double, double, UPB_WIRE_TYPE_64BIT, val); case UPB_DESCRIPTOR_TYPE_FLOAT: @@ -3214,9 +3772,10 @@ static bool upb_encode_scalarfield(upb_encstate *e, const char *field_mem, case UPB_DESCRIPTOR_TYPE_UINT64: CASE(uint64_t, varint, UPB_WIRE_TYPE_VARINT, val); case UPB_DESCRIPTOR_TYPE_UINT32: + CASE(uint32_t, varint, UPB_WIRE_TYPE_VARINT, val); case UPB_DESCRIPTOR_TYPE_INT32: case UPB_DESCRIPTOR_TYPE_ENUM: - CASE(uint32_t, varint, UPB_WIRE_TYPE_VARINT, val); + CASE(int32_t, varint, UPB_WIRE_TYPE_VARINT, (int64_t)val); case UPB_DESCRIPTOR_TYPE_SFIXED64: case UPB_DESCRIPTOR_TYPE_FIXED64: CASE(uint64_t, fixed64, UPB_WIRE_TYPE_64BIT, val); @@ -3241,9 +3800,9 @@ static bool upb_encode_scalarfield(upb_encstate *e, const char *field_mem, } case UPB_DESCRIPTOR_TYPE_GROUP: { size_t size; - void *submsg = *(void**)field_mem; - const upb_msglayout_msginit_v1 *subm = m->submsgs[f->submsg_index]; - if (skip_zero_value && submsg == NULL) { + void *submsg = *(void **)field_mem; + const upb_msglayout *subm = m->submsgs[f->submsg_index]; + if (submsg == NULL) { return true; } return upb_put_tag(e, f->number, UPB_WIRE_TYPE_END_GROUP) && @@ -3252,9 +3811,9 @@ static bool upb_encode_scalarfield(upb_encstate *e, const char *field_mem, } case UPB_DESCRIPTOR_TYPE_MESSAGE: { size_t size; - void *submsg = *(void**)field_mem; - const upb_msglayout_msginit_v1 *subm = m->submsgs[f->submsg_index]; - if (skip_zero_value && submsg == NULL) { + void *submsg = *(void **)field_mem; + const upb_msglayout *subm = m->submsgs[f->submsg_index]; + if (submsg == NULL) { return true; } return upb_encode_message(e, submsg, subm, &size) && @@ -3266,49 +3825,52 @@ static bool upb_encode_scalarfield(upb_encstate *e, const char *field_mem, UPB_UNREACHABLE(); } -bool upb_encode_hasscalarfield(const char *msg, - const upb_msglayout_msginit_v1 *m, - const upb_msglayout_fieldinit_v1 *f) { - if (f->oneof_index != UPB_NOT_IN_ONEOF) { - return upb_readcase(msg, m, f->oneof_index) == f->number; - } else if (m->is_proto2) { - return upb_readhasbit(msg, f); - } else { - /* For proto3, we'll test for the field being empty later. */ - return true; - } -} - -bool upb_encode_message(upb_encstate* e, const char *msg, - const upb_msglayout_msginit_v1 *m, - size_t *size) { +bool upb_encode_message(upb_encstate *e, const char *msg, + const upb_msglayout *m, size_t *size) { int i; - char *buf_end = e->ptr; - - if (msg == NULL) { - return true; - } + size_t pre_len = e->limit - e->ptr; + const char *unknown; + size_t unknown_size; for (i = m->field_count - 1; i >= 0; i--) { - const upb_msglayout_fieldinit_v1 *f = &m->fields[i]; + const upb_msglayout_field *f = &m->fields[i]; if (f->label == UPB_LABEL_REPEATED) { CHK(upb_encode_array(e, msg + f->offset, m, f)); } else { - if (upb_encode_hasscalarfield(msg, m, f)) { - CHK(upb_encode_scalarfield(e, msg + f->offset, m, f, !m->is_proto2)); + bool skip_empty = false; + if (f->presence == 0) { + /* Proto3 presence. */ + skip_empty = true; + } else if (f->presence > 0) { + /* Proto2 presence: hasbit. */ + if (!upb_readhasbit(msg, f)) { + continue; + } + } else { + /* Field is in a oneof. */ + if (upb_readcase(msg, f) != f->number) { + continue; + } } + CHK(upb_encode_scalarfield(e, msg + f->offset, m, f, skip_empty)); } } - *size = buf_end - e->ptr; + unknown = upb_msg_getunknown(msg, &unknown_size); + + if (unknown) { + upb_put_bytes(e, unknown, unknown_size); + } + + *size = (e->limit - e->ptr) - pre_len; return true; } -char *upb_encode(const void *msg, const upb_msglayout_msginit_v1 *m, - upb_env *env, size_t *size) { +char *upb_encode(const void *msg, const upb_msglayout *m, upb_arena *arena, + size_t *size) { upb_encstate e; - e.env = env; + e.alloc = upb_arena_alloc(arena); e.buf = NULL; e.limit = NULL; e.ptr = NULL; @@ -4033,30 +4595,109 @@ bool upb_byteshandler_setendstr(upb_byteshandler *h, } -static bool is_power_of_two(size_t val) { - return (val & (val - 1)) == 0; -} +/** Handlers for upb_msg ******************************************************/ -/* Align up to the given power of 2. */ -static size_t align_up(size_t val, size_t align) { - UPB_ASSERT(is_power_of_two(align)); - return (val + align - 1) & ~(align - 1); -} +typedef struct { + size_t offset; + int32_t hasbit; +} upb_msg_handlerdata; -static size_t div_round_up(size_t n, size_t d) { - return (n + d - 1) / d; -} +/* Fallback implementation if the handler is not specialized by the producer. */ +#define MSG_WRITER(type, ctype) \ + bool upb_msg_set ## type (void *c, const void *hd, ctype val) { \ + uint8_t *m = c; \ + const upb_msg_handlerdata *d = hd; \ + if (d->hasbit > 0) \ + *(uint8_t*)&m[d->hasbit / 8] |= 1 << (d->hasbit % 8); \ + *(ctype*)&m[d->offset] = val; \ + return true; \ + } \ -bool upb_fieldtype_mapkeyok(upb_fieldtype_t type) { - return type == UPB_TYPE_BOOL || type == UPB_TYPE_INT32 || - type == UPB_TYPE_UINT32 || type == UPB_TYPE_INT64 || - type == UPB_TYPE_UINT64 || type == UPB_TYPE_STRING; -} +MSG_WRITER(double, double) +MSG_WRITER(float, float) +MSG_WRITER(int32, int32_t) +MSG_WRITER(int64, int64_t) +MSG_WRITER(uint32, uint32_t) +MSG_WRITER(uint64, uint64_t) +MSG_WRITER(bool, bool) -void *upb_array_pack(const upb_array *arr, void *p, size_t *ofs, size_t size); -void *upb_map_pack(const upb_map *map, void *p, size_t *ofs, size_t size); +bool upb_msg_setscalarhandler(upb_handlers *h, const upb_fielddef *f, + size_t offset, int32_t hasbit) { + upb_handlerattr attr = UPB_HANDLERATTR_INITIALIZER; + bool ok; -#define PTR_AT(msg, ofs, type) (type*)((char*)msg + ofs) + upb_msg_handlerdata *d = upb_gmalloc(sizeof(*d)); + if (!d) return false; + d->offset = offset; + d->hasbit = hasbit; + + upb_handlerattr_sethandlerdata(&attr, d); + upb_handlerattr_setalwaysok(&attr, true); + upb_handlers_addcleanup(h, d, upb_gfree); + +#define TYPE(u, l) \ + case UPB_TYPE_##u: \ + ok = upb_handlers_set##l(h, f, upb_msg_set##l, &attr); break; + + ok = false; + + switch (upb_fielddef_type(f)) { + TYPE(INT64, int64); + TYPE(INT32, int32); + TYPE(ENUM, int32); + TYPE(UINT64, uint64); + TYPE(UINT32, uint32); + TYPE(DOUBLE, double); + TYPE(FLOAT, float); + TYPE(BOOL, bool); + default: UPB_ASSERT(false); break; + } +#undef TYPE + + upb_handlerattr_uninit(&attr); + return ok; +} + +bool upb_msg_getscalarhandlerdata(const upb_handlers *h, + upb_selector_t s, + upb_fieldtype_t *type, + size_t *offset, + int32_t *hasbit) { + const upb_msg_handlerdata *d; + upb_func *f = upb_handlers_gethandler(h, s); + + if ((upb_int64_handlerfunc*)f == upb_msg_setint64) { + *type = UPB_TYPE_INT64; + } else if ((upb_int32_handlerfunc*)f == upb_msg_setint32) { + *type = UPB_TYPE_INT32; + } else if ((upb_uint64_handlerfunc*)f == upb_msg_setuint64) { + *type = UPB_TYPE_UINT64; + } else if ((upb_uint32_handlerfunc*)f == upb_msg_setuint32) { + *type = UPB_TYPE_UINT32; + } else if ((upb_double_handlerfunc*)f == upb_msg_setdouble) { + *type = UPB_TYPE_DOUBLE; + } else if ((upb_float_handlerfunc*)f == upb_msg_setfloat) { + *type = UPB_TYPE_FLOAT; + } else if ((upb_bool_handlerfunc*)f == upb_msg_setbool) { + *type = UPB_TYPE_BOOL; + } else { + return false; + } + + d = upb_handlers_gethandlerdata(h, s); + *offset = d->offset; + *hasbit = d->hasbit; + return true; +} + + +bool upb_fieldtype_mapkeyok(upb_fieldtype_t type) { + return type == UPB_TYPE_BOOL || type == UPB_TYPE_INT32 || + type == UPB_TYPE_UINT32 || type == UPB_TYPE_INT64 || + type == UPB_TYPE_UINT64 || type == UPB_TYPE_STRING; +} + +#define PTR_AT(msg, ofs, type) (type*)((char*)msg + ofs) #define VOIDPTR_AT(msg, ofs) PTR_AT(msg, ofs, void) #define ENCODE_MAX_NESTING 64 #define CHECK_TRUE(x) if (!(x)) { return false; } @@ -4094,576 +4735,57 @@ static size_t upb_msgval_sizeof(upb_fieldtype_t type) { case UPB_TYPE_FLOAT: return 4; case UPB_TYPE_BOOL: - return 1; - case UPB_TYPE_BYTES: - case UPB_TYPE_MESSAGE: - return sizeof(void*); - case UPB_TYPE_STRING: - return sizeof(upb_stringview); - } - UPB_UNREACHABLE(); -} - -static uint8_t upb_msg_fieldsize(const upb_msglayout_fieldinit_v1 *field) { - if (field->label == UPB_LABEL_REPEATED) { - return sizeof(void*); - } else { - return upb_msgval_sizeof(field->type); - } -} - -static uint8_t upb_msg_fielddefsize(const upb_fielddef *f) { - if (upb_fielddef_isseq(f)) { - return sizeof(void*); - } else { - return upb_msgval_sizeof(upb_fielddef_type(f)); - } -} - -/* TODO(haberman): this is broken right now because upb_msgval can contain - * a char* / size_t pair, which is too big for a upb_value. To fix this - * we'll probably need to dynamically allocate a upb_msgval and store a - * pointer to that in the tables for extensions/maps. */ -static upb_value upb_toval(upb_msgval val) { - upb_value ret; - UPB_UNUSED(val); - memset(&ret, 0, sizeof(upb_value)); /* XXX */ - return ret; -} - -static upb_msgval upb_msgval_fromval(upb_value val) { - upb_msgval ret; - UPB_UNUSED(val); - memset(&ret, 0, sizeof(upb_msgval)); /* XXX */ - return ret; -} - -static upb_ctype_t upb_fieldtotabtype(upb_fieldtype_t type) { - switch (type) { - case UPB_TYPE_FLOAT: return UPB_CTYPE_FLOAT; - case UPB_TYPE_DOUBLE: return UPB_CTYPE_DOUBLE; - case UPB_TYPE_BOOL: return UPB_CTYPE_BOOL; - case UPB_TYPE_BYTES: - case UPB_TYPE_MESSAGE: - case UPB_TYPE_STRING: return UPB_CTYPE_CONSTPTR; - case UPB_TYPE_ENUM: - case UPB_TYPE_INT32: return UPB_CTYPE_INT32; - case UPB_TYPE_UINT32: return UPB_CTYPE_UINT32; - case UPB_TYPE_INT64: return UPB_CTYPE_INT64; - case UPB_TYPE_UINT64: return UPB_CTYPE_UINT64; - default: UPB_ASSERT(false); return 0; - } -} - -static upb_msgval upb_msgval_fromdefault(const upb_fielddef *f) { - switch (upb_fielddef_type(f)) { - case UPB_TYPE_FLOAT: - return upb_msgval_float(upb_fielddef_defaultfloat(f)); - case UPB_TYPE_DOUBLE: - return upb_msgval_double(upb_fielddef_defaultdouble(f)); - case UPB_TYPE_BOOL: - return upb_msgval_bool(upb_fielddef_defaultbool(f)); - case UPB_TYPE_STRING: - case UPB_TYPE_BYTES: { - size_t len; - const char *ptr = upb_fielddef_defaultstr(f, &len); - return upb_msgval_makestr(ptr, len); - } - case UPB_TYPE_MESSAGE: - return upb_msgval_msg(NULL); - case UPB_TYPE_ENUM: - case UPB_TYPE_INT32: - return upb_msgval_int32(upb_fielddef_defaultint32(f)); - case UPB_TYPE_UINT32: - return upb_msgval_uint32(upb_fielddef_defaultuint32(f)); - case UPB_TYPE_INT64: - return upb_msgval_int64(upb_fielddef_defaultint64(f)); - case UPB_TYPE_UINT64: - return upb_msgval_uint64(upb_fielddef_defaultuint64(f)); - default: - UPB_ASSERT(false); - return upb_msgval_msg(NULL); - } -} - - -/** upb_msglayout *************************************************************/ - -struct upb_msglayout { - struct upb_msglayout_msginit_v1 data; -}; - -static void upb_msglayout_free(upb_msglayout *l) { - upb_gfree(l->data.default_msg); - upb_gfree(l); -} - -static size_t upb_msglayout_place(upb_msglayout *l, size_t size) { - size_t ret; - - l->data.size = align_up(l->data.size, size); - ret = l->data.size; - l->data.size += size; - return ret; -} - -static uint32_t upb_msglayout_offset(const upb_msglayout *l, - const upb_fielddef *f) { - return l->data.fields[upb_fielddef_index(f)].offset; -} - -static uint32_t upb_msglayout_hasbit(const upb_msglayout *l, - const upb_fielddef *f) { - return l->data.fields[upb_fielddef_index(f)].hasbit; -} - -static bool upb_msglayout_initdefault(upb_msglayout *l, const upb_msgdef *m) { - upb_msg_field_iter it; - - if (upb_msgdef_syntax(m) == UPB_SYNTAX_PROTO2 && l->data.size) { - /* Allocate default message and set default values in it. */ - l->data.default_msg = upb_gmalloc(l->data.size); - if (!l->data.default_msg) { - return false; - } - - memset(l->data.default_msg, 0, l->data.size); - - for (upb_msg_field_begin(&it, m); !upb_msg_field_done(&it); - upb_msg_field_next(&it)) { - const upb_fielddef* f = upb_msg_iter_field(&it); - - if (upb_fielddef_containingoneof(f)) { - continue; - } - - /* TODO(haberman): handle strings. */ - if (!upb_fielddef_isstring(f) && - !upb_fielddef_issubmsg(f) && - !upb_fielddef_isseq(f)) { - upb_msg_set(l->data.default_msg, - upb_fielddef_index(f), - upb_msgval_fromdefault(f), - l); - } - } - } - - return true; -} - -static upb_msglayout *upb_msglayout_new(const upb_msgdef *m) { - upb_msg_field_iter it; - upb_msg_oneof_iter oit; - upb_msglayout *l; - size_t hasbit; - size_t submsg_count = 0; - const upb_msglayout_msginit_v1 **submsgs; - upb_msglayout_fieldinit_v1 *fields; - upb_msglayout_oneofinit_v1 *oneofs; - - for (upb_msg_field_begin(&it, m); - !upb_msg_field_done(&it); - upb_msg_field_next(&it)) { - const upb_fielddef* f = upb_msg_iter_field(&it); - if (upb_fielddef_issubmsg(f)) { - submsg_count++; - } - } - - l = upb_gmalloc(sizeof(*l)); - if (!l) return NULL; - - memset(l, 0, sizeof(*l)); - - fields = upb_gmalloc(upb_msgdef_numfields(m) * sizeof(*fields)); - submsgs = upb_gmalloc(submsg_count * sizeof(*submsgs)); - oneofs = upb_gmalloc(upb_msgdef_numoneofs(m) * sizeof(*oneofs)); - - if ((!fields && upb_msgdef_numfields(m)) || - (!submsgs && submsg_count) || - (!oneofs && upb_msgdef_numoneofs(m))) { - /* OOM. */ - upb_gfree(l); - upb_gfree(fields); - upb_gfree(submsgs); - upb_gfree(oneofs); - return NULL; - } - - l->data.field_count = upb_msgdef_numfields(m); - l->data.oneof_count = upb_msgdef_numoneofs(m); - l->data.fields = fields; - l->data.submsgs = submsgs; - l->data.oneofs = oneofs; - l->data.is_proto2 = (upb_msgdef_syntax(m) == UPB_SYNTAX_PROTO2); - - /* Allocate data offsets in three stages: - * - * 1. hasbits. - * 2. regular fields. - * 3. oneof fields. - * - * OPT: There is a lot of room for optimization here to minimize the size. - */ - - /* Allocate hasbits and set basic field attributes. */ - for (upb_msg_field_begin(&it, m), hasbit = 0; - !upb_msg_field_done(&it); - upb_msg_field_next(&it)) { - const upb_fielddef* f = upb_msg_iter_field(&it); - upb_msglayout_fieldinit_v1 *field = &fields[upb_fielddef_index(f)]; - - field->number = upb_fielddef_number(f); - field->type = upb_fielddef_type(f); - field->label = upb_fielddef_label(f); - - if (upb_fielddef_containingoneof(f)) { - field->oneof_index = upb_oneofdef_index(upb_fielddef_containingoneof(f)); - } else { - field->oneof_index = UPB_NOT_IN_ONEOF; - } - - if (upb_fielddef_haspresence(f) && !upb_fielddef_containingoneof(f)) { - field->hasbit = hasbit++; - } - } - - /* Account for space used by hasbits. */ - l->data.size = div_round_up(hasbit, 8); - - /* Allocate non-oneof fields. */ - for (upb_msg_field_begin(&it, m); !upb_msg_field_done(&it); - upb_msg_field_next(&it)) { - const upb_fielddef* f = upb_msg_iter_field(&it); - size_t field_size = upb_msg_fielddefsize(f); - size_t index = upb_fielddef_index(f); - - if (upb_fielddef_containingoneof(f)) { - /* Oneofs are handled separately below. */ - continue; - } - - fields[index].offset = upb_msglayout_place(l, field_size); - } - - /* Allocate oneof fields. Each oneof field consists of a uint32 for the case - * and space for the actual data. */ - for (upb_msg_oneof_begin(&oit, m); !upb_msg_oneof_done(&oit); - upb_msg_oneof_next(&oit)) { - const upb_oneofdef* o = upb_msg_iter_oneof(&oit); - upb_oneof_iter fit; - - size_t case_size = sizeof(uint32_t); /* Could potentially optimize this. */ - upb_msglayout_oneofinit_v1 *oneof = &oneofs[upb_oneofdef_index(o)]; - size_t field_size = 0; - - /* Calculate field size: the max of all field sizes. */ - for (upb_oneof_begin(&fit, o); - !upb_oneof_done(&fit); - upb_oneof_next(&fit)) { - const upb_fielddef* f = upb_oneof_iter_field(&fit); - field_size = UPB_MAX(field_size, upb_msg_fielddefsize(f)); - } - - /* Align and allocate case offset. */ - oneof->case_offset = upb_msglayout_place(l, case_size); - oneof->data_offset = upb_msglayout_place(l, field_size); - } - - /* Size of the entire structure should be a multiple of its greatest - * alignment. TODO: track overall alignment for real? */ - l->data.size = align_up(l->data.size, 8); - - if (upb_msglayout_initdefault(l, m)) { - return l; - } else { - upb_msglayout_free(l); - return NULL; - } -} - - -/** upb_msgfactory ************************************************************/ - -struct upb_msgfactory { - const upb_symtab *symtab; /* We own a ref. */ - upb_inttable layouts; - upb_inttable mergehandlers; -}; - -upb_msgfactory *upb_msgfactory_new(const upb_symtab *symtab) { - upb_msgfactory *ret = upb_gmalloc(sizeof(*ret)); - - ret->symtab = symtab; - upb_inttable_init(&ret->layouts, UPB_CTYPE_PTR); - upb_inttable_init(&ret->mergehandlers, UPB_CTYPE_CONSTPTR); - - return ret; -} - -void upb_msgfactory_free(upb_msgfactory *f) { - upb_inttable_iter i; - upb_inttable_begin(&i, &f->layouts); - for(; !upb_inttable_done(&i); upb_inttable_next(&i)) { - upb_msglayout *l = upb_value_getptr(upb_inttable_iter_value(&i)); - upb_msglayout_free(l); - } - - upb_inttable_begin(&i, &f->mergehandlers); - for(; !upb_inttable_done(&i); upb_inttable_next(&i)) { - const upb_handlers *h = upb_value_getconstptr(upb_inttable_iter_value(&i)); - upb_handlers_unref(h, f); - } - - upb_inttable_uninit(&f->layouts); - upb_inttable_uninit(&f->mergehandlers); - upb_gfree(f); -} - -const upb_symtab *upb_msgfactory_symtab(const upb_msgfactory *f) { - return f->symtab; -} - -const upb_msglayout *upb_msgfactory_getlayout(upb_msgfactory *f, - const upb_msgdef *m) { - upb_value v; - UPB_ASSERT(upb_symtab_lookupmsg(f->symtab, upb_msgdef_fullname(m)) == m); - UPB_ASSERT(!upb_msgdef_mapentry(m)); - - if (upb_inttable_lookupptr(&f->layouts, m, &v)) { - UPB_ASSERT(upb_value_getptr(v)); - return upb_value_getptr(v); - } else { - upb_msgfactory *mutable_f = (void*)f; - upb_msglayout *l = upb_msglayout_new(m); - upb_inttable_insertptr(&mutable_f->layouts, m, upb_value_ptr(l)); - UPB_ASSERT(l); - return l; - } -} - -/* Our handlers that we don't expose externally. */ - -void *upb_msg_startstr(void *msg, const void *hd, size_t size_hint) { - uint32_t ofs = (uintptr_t)hd; - upb_alloc *alloc = upb_msg_alloc(msg); - upb_msgval val; - UPB_UNUSED(size_hint); - - val = upb_msgval_read(msg, ofs, upb_msgval_sizeof(UPB_TYPE_STRING)); - - upb_free(alloc, (void*)val.str.data); - val.str.data = NULL; - val.str.size = 0; - - upb_msgval_write(msg, ofs, val, upb_msgval_sizeof(UPB_TYPE_STRING)); - return msg; -} - -size_t upb_msg_str(void *msg, const void *hd, const char *ptr, size_t size, - const upb_bufhandle *handle) { - uint32_t ofs = (uintptr_t)hd; - upb_alloc *alloc = upb_msg_alloc(msg); - upb_msgval val; - size_t newsize; - UPB_UNUSED(handle); - - val = upb_msgval_read(msg, ofs, upb_msgval_sizeof(UPB_TYPE_STRING)); - - newsize = val.str.size + size; - val.str.data = upb_realloc(alloc, (void*)val.str.data, val.str.size, newsize); - - if (!val.str.data) { - return false; - } - - memcpy((char*)val.str.data + val.str.size, ptr, size); - val.str.size = newsize; - upb_msgval_write(msg, ofs, val, upb_msgval_sizeof(UPB_TYPE_STRING)); - return size; -} - -static void callback(const void *closure, upb_handlers *h) { - upb_msgfactory *factory = (upb_msgfactory*)closure; - const upb_msgdef *md = upb_handlers_msgdef(h); - const upb_msglayout* layout = upb_msgfactory_getlayout(factory, md); - upb_msg_field_iter i; - UPB_UNUSED(factory); - - for(upb_msg_field_begin(&i, md); - !upb_msg_field_done(&i); - upb_msg_field_next(&i)) { - const upb_fielddef *f = upb_msg_iter_field(&i); - size_t offset = upb_msglayout_offset(layout, f); - upb_handlerattr attr = UPB_HANDLERATTR_INITIALIZER; - upb_handlerattr_sethandlerdata(&attr, (void*)offset); - - if (upb_fielddef_isseq(f)) { - } else if (upb_fielddef_isstring(f)) { - upb_handlers_setstartstr(h, f, upb_msg_startstr, &attr); - upb_handlers_setstring(h, f, upb_msg_str, &attr); - } else { - upb_msg_setscalarhandler( - h, f, offset, upb_msglayout_hasbit(layout, f)); - } - } -} - -const upb_handlers *upb_msgfactory_getmergehandlers(upb_msgfactory *f, - const upb_msgdef *m) { - upb_msgfactory *mutable_f = (void*)f; - - /* TODO(haberman): properly cache these. */ - const upb_handlers *ret = upb_handlers_newfrozen(m, f, callback, f); - upb_inttable_push(&mutable_f->mergehandlers, upb_value_constptr(ret)); - - return ret; -} - -const upb_visitorplan *upb_msgfactory_getvisitorplan(upb_msgfactory *f, - const upb_handlers *h) { - const upb_msgdef *md = upb_handlers_msgdef(h); - return (const upb_visitorplan*)upb_msgfactory_getlayout(f, md); -} - - -/** upb_visitor ***************************************************************/ - -struct upb_visitor { - const upb_msglayout *layout; - upb_sink *sink; -}; - -static upb_selector_t getsel2(const upb_fielddef *f, upb_handlertype_t type) { - upb_selector_t ret; - bool ok = upb_handlers_getselector(f, type, &ret); - UPB_ASSERT(ok); - return ret; -} - -static bool upb_visitor_hasfield(const upb_msg *msg, const upb_fielddef *f, - const upb_msglayout *layout) { - int field_index = upb_fielddef_index(f); - if (upb_fielddef_isseq(f)) { - return upb_msgval_getarr(upb_msg_get(msg, field_index, layout)) != NULL; - } else if (upb_msgdef_syntax(upb_fielddef_containingtype(f)) == - UPB_SYNTAX_PROTO2) { - return upb_msg_has(msg, field_index, layout); - } else { - upb_msgval val = upb_msg_get(msg, field_index, layout); - switch (upb_fielddef_type(f)) { - case UPB_TYPE_FLOAT: - return upb_msgval_getfloat(val) != 0; - case UPB_TYPE_DOUBLE: - return upb_msgval_getdouble(val) != 0; - case UPB_TYPE_BOOL: - return upb_msgval_getbool(val); - case UPB_TYPE_ENUM: - case UPB_TYPE_INT32: - return upb_msgval_getint32(val) != 0; - case UPB_TYPE_UINT32: - return upb_msgval_getuint32(val) != 0; - case UPB_TYPE_INT64: - return upb_msgval_getint64(val) != 0; - case UPB_TYPE_UINT64: - return upb_msgval_getuint64(val) != 0; - case UPB_TYPE_STRING: - case UPB_TYPE_BYTES: - return upb_msgval_getstr(val).size > 0; - case UPB_TYPE_MESSAGE: - return upb_msgval_getmsg(val) != NULL; - } - UPB_UNREACHABLE(); + return 1; + case UPB_TYPE_MESSAGE: + return sizeof(void*); + case UPB_TYPE_BYTES: + case UPB_TYPE_STRING: + return sizeof(upb_stringview); } + UPB_UNREACHABLE(); } -static bool upb_visitor_visitmsg2(const upb_msg *msg, - const upb_msglayout *layout, upb_sink *sink, - int depth) { - const upb_msgdef *md = upb_handlers_msgdef(sink->handlers); - upb_msg_field_iter i; - upb_status status; - - upb_sink_startmsg(sink); - - /* Protect against cycles (possible because users may freely reassign message - * and repeated fields) by imposing a maximum recursion depth. */ - if (depth > ENCODE_MAX_NESTING) { - return false; - } - - for (upb_msg_field_begin(&i, md); - !upb_msg_field_done(&i); - upb_msg_field_next(&i)) { - upb_fielddef *f = upb_msg_iter_field(&i); - upb_msgval val; - - if (!upb_visitor_hasfield(msg, f, layout)) { - continue; - } - - val = upb_msg_get(msg, upb_fielddef_index(f), layout); - - if (upb_fielddef_isseq(f)) { - const upb_array *arr = upb_msgval_getarr(val); - UPB_ASSERT(arr); - /* TODO: putary(ary, f, sink, depth);*/ - } else if (upb_fielddef_issubmsg(f)) { - const upb_map *map = upb_msgval_getmap(val); - UPB_ASSERT(map); - /* TODO: putmap(map, f, sink, depth);*/ - } else if (upb_fielddef_isstring(f)) { - /* TODO putstr(); */ - } else { - upb_selector_t sel = getsel2(f, upb_handlers_getprimitivehandlertype(f)); - UPB_ASSERT(upb_fielddef_isprimitive(f)); - - switch (upb_fielddef_type(f)) { - case UPB_TYPE_FLOAT: - CHECK_TRUE(upb_sink_putfloat(sink, sel, upb_msgval_getfloat(val))); - break; - case UPB_TYPE_DOUBLE: - CHECK_TRUE(upb_sink_putdouble(sink, sel, upb_msgval_getdouble(val))); - break; - case UPB_TYPE_BOOL: - CHECK_TRUE(upb_sink_putbool(sink, sel, upb_msgval_getbool(val))); - break; - case UPB_TYPE_ENUM: - case UPB_TYPE_INT32: - CHECK_TRUE(upb_sink_putint32(sink, sel, upb_msgval_getint32(val))); - break; - case UPB_TYPE_UINT32: - CHECK_TRUE(upb_sink_putuint32(sink, sel, upb_msgval_getuint32(val))); - break; - case UPB_TYPE_INT64: - CHECK_TRUE(upb_sink_putint64(sink, sel, upb_msgval_getint64(val))); - break; - case UPB_TYPE_UINT64: - CHECK_TRUE(upb_sink_putuint64(sink, sel, upb_msgval_getuint64(val))); - break; - case UPB_TYPE_STRING: - case UPB_TYPE_BYTES: - case UPB_TYPE_MESSAGE: - UPB_UNREACHABLE(); - } - } +static uint8_t upb_msg_fieldsize(const upb_msglayout_field *field) { + if (field->label == UPB_LABEL_REPEATED) { + return sizeof(void*); + } else { + return upb_msgval_sizeof(upb_desctype_to_fieldtype[field->descriptortype]); } +} - upb_sink_endmsg(sink, &status); - return true; +/* TODO(haberman): this is broken right now because upb_msgval can contain + * a char* / size_t pair, which is too big for a upb_value. To fix this + * we'll probably need to dynamically allocate a upb_msgval and store a + * pointer to that in the tables for extensions/maps. */ +static upb_value upb_toval(upb_msgval val) { + upb_value ret; + UPB_UNUSED(val); + memset(&ret, 0, sizeof(upb_value)); /* XXX */ + return ret; } -upb_visitor *upb_visitor_create(upb_env *e, const upb_visitorplan *vp, - upb_sink *output) { - upb_visitor *visitor = upb_env_malloc(e, sizeof(*visitor)); - visitor->layout = (const upb_msglayout*)vp; - visitor->sink = output; - return visitor; +static upb_msgval upb_msgval_fromval(upb_value val) { + upb_msgval ret; + UPB_UNUSED(val); + memset(&ret, 0, sizeof(upb_msgval)); /* XXX */ + return ret; } -bool upb_visitor_visitmsg(upb_visitor *visitor, const upb_msg *msg) { - return upb_visitor_visitmsg2(msg, visitor->layout, visitor->sink, 0); +static upb_ctype_t upb_fieldtotabtype(upb_fieldtype_t type) { + switch (type) { + case UPB_TYPE_FLOAT: return UPB_CTYPE_FLOAT; + case UPB_TYPE_DOUBLE: return UPB_CTYPE_DOUBLE; + case UPB_TYPE_BOOL: return UPB_CTYPE_BOOL; + case UPB_TYPE_BYTES: + case UPB_TYPE_MESSAGE: + case UPB_TYPE_STRING: return UPB_CTYPE_CONSTPTR; + case UPB_TYPE_ENUM: + case UPB_TYPE_INT32: return UPB_CTYPE_INT32; + case UPB_TYPE_UINT32: return UPB_CTYPE_UINT32; + case UPB_TYPE_INT64: return UPB_CTYPE_INT64; + case UPB_TYPE_UINT64: return UPB_CTYPE_UINT64; + default: UPB_ASSERT(false); return 0; + } } @@ -4680,8 +4802,12 @@ bool upb_visitor_visitmsg(upb_visitor *visitor, const upb_msg *msg) { /* Used when a message is not extendable. */ typedef struct { - /* TODO(haberman): add unknown fields. */ - upb_alloc *alloc; + /* TODO(haberman): use pointer tagging so we we are slim when known unknown + * fields are not present. */ + upb_arena *arena; + char *unknown; + size_t unknown_len; + size_t unknown_size; } upb_msg_internal; /* Used when a message is extendable. */ @@ -4691,7 +4817,7 @@ typedef struct { } upb_msg_internal_withext; static int upb_msg_internalsize(const upb_msglayout *l) { - return sizeof(upb_msg_internal) - l->data.extendable * sizeof(void*); + return sizeof(upb_msg_internal) - l->extendable * sizeof(void *); } static upb_msg_internal *upb_msg_getinternal(upb_msg *msg) { @@ -4704,123 +4830,112 @@ static const upb_msg_internal *upb_msg_getinternal_const(const upb_msg *msg) { static upb_msg_internal_withext *upb_msg_getinternalwithext( upb_msg *msg, const upb_msglayout *l) { - UPB_ASSERT(l->data.extendable); + UPB_ASSERT(l->extendable); return VOIDPTR_AT(msg, -sizeof(upb_msg_internal_withext)); } -static const upb_msglayout_fieldinit_v1 *upb_msg_checkfield( - int field_index, const upb_msglayout *l) { - UPB_ASSERT(field_index >= 0 && field_index < l->data.field_count); - return &l->data.fields[field_index]; +void upb_msg_addunknown(upb_msg *msg, const char *data, size_t len) { + upb_msg_internal* in = upb_msg_getinternal(msg); + if (len > in->unknown_size - in->unknown_len) { + upb_alloc *alloc = upb_arena_alloc(in->arena); + size_t need = in->unknown_size + len; + size_t newsize = UPB_MAX(in->unknown_size * 2, need); + in->unknown = upb_realloc(alloc, in->unknown, in->unknown_size, newsize); + in->unknown_size = newsize; + } + memcpy(in->unknown + in->unknown_len, data, len); + in->unknown_len += len; +} + +const char *upb_msg_getunknown(const upb_msg *msg, size_t *len) { + const upb_msg_internal* in = upb_msg_getinternal_const(msg); + *len = in->unknown_len; + return in->unknown; +} + +static const upb_msglayout_field *upb_msg_checkfield(int field_index, + const upb_msglayout *l) { + UPB_ASSERT(field_index >= 0 && field_index < l->field_count); + return &l->fields[field_index]; } -static bool upb_msg_inoneof(const upb_msglayout_fieldinit_v1 *field) { - return field->oneof_index != UPB_NOT_IN_ONEOF; +static bool upb_msg_inoneof(const upb_msglayout_field *field) { + return field->presence < 0; } static uint32_t *upb_msg_oneofcase(const upb_msg *msg, int field_index, const upb_msglayout *l) { - const upb_msglayout_fieldinit_v1 *field = upb_msg_checkfield(field_index, l); + const upb_msglayout_field *field = upb_msg_checkfield(field_index, l); UPB_ASSERT(upb_msg_inoneof(field)); - return PTR_AT(msg, l->data.oneofs[field->oneof_index].case_offset, uint32_t); + return PTR_AT(msg, ~field->presence, uint32_t); } -size_t upb_msg_sizeof(const upb_msglayout *l) { - return l->data.size + upb_msg_internalsize(l); +static size_t upb_msg_sizeof(const upb_msglayout *l) { + return l->size + upb_msg_internalsize(l); } -upb_msg *upb_msg_init(void *mem, const upb_msglayout *l, upb_alloc *a) { - upb_msg *msg = VOIDPTR_AT(mem, upb_msg_internalsize(l)); +upb_msg *upb_msg_new(const upb_msglayout *l, upb_arena *a) { + upb_alloc *alloc = upb_arena_alloc(a); + void *mem = upb_malloc(alloc, upb_msg_sizeof(l)); + upb_msg_internal *in; + upb_msg *msg; - /* Initialize normal members. */ - if (l->data.default_msg) { - memcpy(msg, l->data.default_msg, l->data.size); - } else { - memset(msg, 0, l->data.size); + if (!mem) { + return NULL; } + msg = VOIDPTR_AT(mem, upb_msg_internalsize(l)); + + /* Initialize normal members. */ + memset(msg, 0, l->size); + /* Initialize internal members. */ - upb_msg_getinternal(msg)->alloc = a; + in = upb_msg_getinternal(msg); + in->arena = a; + in->unknown = NULL; + in->unknown_len = 0; + in->unknown_size = 0; - if (l->data.extendable) { + if (l->extendable) { upb_msg_getinternalwithext(msg, l)->extdict = NULL; } return msg; } -void *upb_msg_uninit(upb_msg *msg, const upb_msglayout *l) { - if (l->data.extendable) { - upb_inttable *ext_dict = upb_msg_getinternalwithext(msg, l)->extdict; - if (ext_dict) { - upb_inttable_uninit2(ext_dict, upb_msg_alloc(msg)); - upb_free(upb_msg_alloc(msg), ext_dict); - } - } - - return VOIDPTR_AT(msg, -upb_msg_internalsize(l)); -} - -upb_msg *upb_msg_new(const upb_msglayout *l, upb_alloc *a) { - void *mem = upb_malloc(a, upb_msg_sizeof(l)); - return mem ? upb_msg_init(mem, l, a) : NULL; -} - -void upb_msg_free(upb_msg *msg, const upb_msglayout *l) { - upb_free(upb_msg_alloc(msg), upb_msg_uninit(msg, l)); -} - -upb_alloc *upb_msg_alloc(const upb_msg *msg) { - return upb_msg_getinternal_const(msg)->alloc; +upb_arena *upb_msg_arena(const upb_msg *msg) { + return upb_msg_getinternal_const(msg)->arena; } bool upb_msg_has(const upb_msg *msg, int field_index, const upb_msglayout *l) { - const upb_msglayout_fieldinit_v1 *field = upb_msg_checkfield(field_index, l); + const upb_msglayout_field *field = upb_msg_checkfield(field_index, l); - UPB_ASSERT(l->data.is_proto2); + UPB_ASSERT(field->presence); if (upb_msg_inoneof(field)) { /* Oneofs are set when the oneof number is set to this field. */ return *upb_msg_oneofcase(msg, field_index, l) == field->number; } else { /* Other fields are set when their hasbit is set. */ - uint32_t hasbit = l->data.fields[field_index].hasbit; + uint32_t hasbit = field->presence; return DEREF(msg, hasbit / 8, char) | (1 << (hasbit % 8)); } } upb_msgval upb_msg_get(const upb_msg *msg, int field_index, const upb_msglayout *l) { - const upb_msglayout_fieldinit_v1 *field = upb_msg_checkfield(field_index, l); + const upb_msglayout_field *field = upb_msg_checkfield(field_index, l); int size = upb_msg_fieldsize(field); - - if (upb_msg_inoneof(field)) { - if (*upb_msg_oneofcase(msg, field_index, l) == field->number) { - size_t ofs = l->data.oneofs[field->oneof_index].data_offset; - return upb_msgval_read(msg, ofs, size); - } else { - /* Return default. */ - return upb_msgval_read(l->data.default_msg, field->offset, size); - } - } else { - return upb_msgval_read(msg, field->offset, size); - } + return upb_msgval_read(msg, field->offset, size); } void upb_msg_set(upb_msg *msg, int field_index, upb_msgval val, const upb_msglayout *l) { - const upb_msglayout_fieldinit_v1 *field = upb_msg_checkfield(field_index, l); + const upb_msglayout_field *field = upb_msg_checkfield(field_index, l); int size = upb_msg_fieldsize(field); - - if (upb_msg_inoneof(field)) { - size_t ofs = l->data.oneofs[field->oneof_index].data_offset; - *upb_msg_oneofcase(msg, field_index, l) = field->number; - upb_msgval_write(msg, ofs, val, size); - } else { - upb_msgval_write(msg, field->offset, val, size); - } + upb_msgval_write(msg, field->offset, val, size); } @@ -4828,37 +4943,22 @@ void upb_msg_set(upb_msg *msg, int field_index, upb_msgval val, #define DEREF_ARR(arr, i, type) ((type*)arr->data)[i] -size_t upb_array_sizeof(upb_fieldtype_t type) { - UPB_UNUSED(type); - return sizeof(upb_array); -} - -void upb_array_init(upb_array *arr, upb_fieldtype_t type, upb_alloc *alloc) { - arr->type = type; - arr->data = NULL; - arr->len = 0; - arr->size = 0; - arr->element_size = upb_msgval_sizeof(type); - arr->alloc = alloc; -} - -void upb_array_uninit(upb_array *arr) { - upb_free(arr->alloc, arr->data); -} - -upb_array *upb_array_new(upb_fieldtype_t type, upb_alloc *a) { - upb_array *ret = upb_malloc(a, upb_array_sizeof(type)); +upb_array *upb_array_new(upb_fieldtype_t type, upb_arena *a) { + upb_alloc *alloc = upb_arena_alloc(a); + upb_array *ret = upb_malloc(alloc, sizeof(upb_array)); - if (ret) { - upb_array_init(ret, type, a); + if (!ret) { + return NULL; } - return ret; -} + ret->type = type; + ret->data = NULL; + ret->len = 0; + ret->size = 0; + ret->element_size = upb_msgval_sizeof(type); + ret->arena = a; -void upb_array_free(upb_array *arr) { - upb_array_uninit(arr); - upb_free(arr->alloc, arr); + return ret; } size_t upb_array_size(const upb_array *arr) { @@ -4885,8 +4985,9 @@ bool upb_array_set(upb_array *arr, size_t i, upb_msgval val) { size_t new_size = UPB_MAX(arr->size * 2, 8); size_t new_bytes = new_size * arr->element_size; size_t old_bytes = arr->size * arr->element_size; + upb_alloc *alloc = upb_arena_alloc(arr->arena); upb_msgval *new_data = - upb_realloc(arr->alloc, arr->data, old_bytes, new_bytes); + upb_realloc(alloc, arr->data, old_bytes, new_bytes); if (!new_data) { return false; @@ -4912,7 +5013,7 @@ struct upb_map { /* We may want to optimize this to use inttable where possible, for greater * efficiency and lower memory footprint. */ upb_strtable strtab; - upb_alloc *alloc; + upb_arena *arena; }; static void upb_map_tokey(upb_fieldtype_t type, upb_msgval *key, @@ -4963,52 +5064,28 @@ static upb_msgval upb_map_fromkey(upb_fieldtype_t type, const char *key, UPB_UNREACHABLE(); } -size_t upb_map_sizeof(upb_fieldtype_t ktype, upb_fieldtype_t vtype) { - /* Size does not currently depend on key/value type. */ - UPB_UNUSED(ktype); - UPB_UNUSED(vtype); - return sizeof(upb_map); -} - -bool upb_map_init(upb_map *map, upb_fieldtype_t ktype, upb_fieldtype_t vtype, - upb_alloc *a) { - upb_ctype_t vtabtype = upb_fieldtotabtype(vtype); - UPB_ASSERT(upb_fieldtype_mapkeyok(ktype)); - map->key_type = ktype; - map->val_type = vtype; - map->alloc = a; - - if (!upb_strtable_init2(&map->strtab, vtabtype, a)) { - return false; - } - - return true; -} - -void upb_map_uninit(upb_map *map) { - upb_strtable_uninit2(&map->strtab, map->alloc); -} - upb_map *upb_map_new(upb_fieldtype_t ktype, upb_fieldtype_t vtype, - upb_alloc *a) { - upb_map *map = upb_malloc(a, upb_map_sizeof(ktype, vtype)); + upb_arena *a) { + upb_ctype_t vtabtype = upb_fieldtotabtype(vtype); + upb_alloc *alloc = upb_arena_alloc(a); + upb_map *map = upb_malloc(alloc, sizeof(upb_map)); if (!map) { return NULL; } - if (!upb_map_init(map, ktype, vtype, a)) { + UPB_ASSERT(upb_fieldtype_mapkeyok(ktype)); + map->key_type = ktype; + map->val_type = vtype; + map->arena = a; + + if (!upb_strtable_init2(&map->strtab, vtabtype, alloc)) { return NULL; } return map; } -void upb_map_free(upb_map *map) { - upb_map_uninit(map); - upb_free(map->alloc, map); -} - size_t upb_map_size(const upb_map *map) { return upb_strtable_count(&map->strtab); } @@ -5042,7 +5119,7 @@ bool upb_map_set(upb_map *map, upb_msgval key, upb_msgval val, size_t key_len; upb_value tabval = upb_toval(val); upb_value removedtabval; - upb_alloc *a = map->alloc; + upb_alloc *a = upb_arena_alloc(map->arena); upb_map_tokey(map->key_type, &key, &key_str, &key_len); @@ -5058,163 +5135,321 @@ bool upb_map_set(upb_map *map, upb_msgval key, upb_msgval val, bool upb_map_del(upb_map *map, upb_msgval key) { const char *key_str; size_t key_len; - upb_alloc *a = map->alloc; + upb_alloc *a = upb_arena_alloc(map->arena); + + upb_map_tokey(map->key_type, &key, &key_str, &key_len); + return upb_strtable_remove3(&map->strtab, key_str, key_len, NULL, a); +} + + +/** upb_mapiter ***************************************************************/ + +struct upb_mapiter { + upb_strtable_iter iter; + upb_fieldtype_t key_type; +}; + +size_t upb_mapiter_sizeof() { + return sizeof(upb_mapiter); +} + +void upb_mapiter_begin(upb_mapiter *i, const upb_map *map) { + upb_strtable_begin(&i->iter, &map->strtab); + i->key_type = map->key_type; +} + +upb_mapiter *upb_mapiter_new(const upb_map *t, upb_alloc *a) { + upb_mapiter *ret = upb_malloc(a, upb_mapiter_sizeof()); + + if (!ret) { + return NULL; + } + + upb_mapiter_begin(ret, t); + return ret; +} + +void upb_mapiter_free(upb_mapiter *i, upb_alloc *a) { + upb_free(a, i); +} + +void upb_mapiter_next(upb_mapiter *i) { + upb_strtable_next(&i->iter); +} + +bool upb_mapiter_done(const upb_mapiter *i) { + return upb_strtable_done(&i->iter); +} + +upb_msgval upb_mapiter_key(const upb_mapiter *i) { + return upb_map_fromkey(i->key_type, upb_strtable_iter_key(&i->iter), + upb_strtable_iter_keylength(&i->iter)); +} + +upb_msgval upb_mapiter_value(const upb_mapiter *i) { + return upb_msgval_fromval(upb_strtable_iter_value(&i->iter)); +} + +void upb_mapiter_setdone(upb_mapiter *i) { + upb_strtable_iter_setdone(&i->iter); +} + +bool upb_mapiter_isequal(const upb_mapiter *i1, const upb_mapiter *i2) { + return upb_strtable_iter_isequal(&i1->iter, &i2->iter); +} + + +static bool is_power_of_two(size_t val) { + return (val & (val - 1)) == 0; +} + +/* Align up to the given power of 2. */ +static size_t align_up(size_t val, size_t align) { + UPB_ASSERT(is_power_of_two(align)); + return (val + align - 1) & ~(align - 1); +} + +static size_t div_round_up(size_t n, size_t d) { + return (n + d - 1) / d; +} + +static size_t upb_msgval_sizeof2(upb_fieldtype_t type) { + switch (type) { + case UPB_TYPE_DOUBLE: + case UPB_TYPE_INT64: + case UPB_TYPE_UINT64: + return 8; + case UPB_TYPE_ENUM: + case UPB_TYPE_INT32: + case UPB_TYPE_UINT32: + case UPB_TYPE_FLOAT: + return 4; + case UPB_TYPE_BOOL: + return 1; + case UPB_TYPE_MESSAGE: + return sizeof(void*); + case UPB_TYPE_BYTES: + case UPB_TYPE_STRING: + return sizeof(upb_stringview); + } + UPB_UNREACHABLE(); +} + +static uint8_t upb_msg_fielddefsize(const upb_fielddef *f) { + if (upb_fielddef_isseq(f)) { + return sizeof(void*); + } else { + return upb_msgval_sizeof2(upb_fielddef_type(f)); + } +} + + +/** upb_msglayout *************************************************************/ + +static void upb_msglayout_free(upb_msglayout *l) { + upb_gfree(l); +} + +static size_t upb_msglayout_place(upb_msglayout *l, size_t size) { + size_t ret; + + l->size = align_up(l->size, size); + ret = l->size; + l->size += size; + return ret; +} + +static bool upb_msglayout_init(const upb_msgdef *m, + upb_msglayout *l, + upb_msgfactory *factory) { + upb_msg_field_iter it; + upb_msg_oneof_iter oit; + size_t hasbit; + size_t submsg_count = 0; + const upb_msglayout **submsgs; + upb_msglayout_field *fields; + + for (upb_msg_field_begin(&it, m); + !upb_msg_field_done(&it); + upb_msg_field_next(&it)) { + const upb_fielddef* f = upb_msg_iter_field(&it); + if (upb_fielddef_issubmsg(f)) { + submsg_count++; + } + } - upb_map_tokey(map->key_type, &key, &key_str, &key_len); - return upb_strtable_remove3(&map->strtab, key_str, key_len, NULL, a); -} + memset(l, 0, sizeof(*l)); + fields = upb_gmalloc(upb_msgdef_numfields(m) * sizeof(*fields)); + submsgs = upb_gmalloc(submsg_count * sizeof(*submsgs)); -/** upb_mapiter ***************************************************************/ + if ((!fields && upb_msgdef_numfields(m)) || + (!submsgs && submsg_count)) { + /* OOM. */ + upb_gfree(fields); + upb_gfree(submsgs); + return false; + } -struct upb_mapiter { - upb_strtable_iter iter; - upb_fieldtype_t key_type; -}; + l->field_count = upb_msgdef_numfields(m); + l->fields = fields; + l->submsgs = submsgs; -size_t upb_mapiter_sizeof() { - return sizeof(upb_mapiter); -} + /* Allocate data offsets in three stages: + * + * 1. hasbits. + * 2. regular fields. + * 3. oneof fields. + * + * OPT: There is a lot of room for optimization here to minimize the size. + */ -void upb_mapiter_begin(upb_mapiter *i, const upb_map *map) { - upb_strtable_begin(&i->iter, &map->strtab); - i->key_type = map->key_type; -} + /* Allocate hasbits and set basic field attributes. */ + submsg_count = 0; + for (upb_msg_field_begin(&it, m), hasbit = 0; + !upb_msg_field_done(&it); + upb_msg_field_next(&it)) { + const upb_fielddef* f = upb_msg_iter_field(&it); + upb_msglayout_field *field = &fields[upb_fielddef_index(f)]; -upb_mapiter *upb_mapiter_new(const upb_map *t, upb_alloc *a) { - upb_mapiter *ret = upb_malloc(a, upb_mapiter_sizeof()); + field->number = upb_fielddef_number(f); + field->descriptortype = upb_fielddef_descriptortype(f); + field->label = upb_fielddef_label(f); - if (!ret) { - return NULL; + if (upb_fielddef_issubmsg(f)) { + const upb_msglayout *sub_layout = + upb_msgfactory_getlayout(factory, upb_fielddef_msgsubdef(f)); + field->submsg_index = submsg_count++; + submsgs[field->submsg_index] = sub_layout; + } + + if (upb_fielddef_haspresence(f) && !upb_fielddef_containingoneof(f)) { + field->presence = (hasbit++); + } else { + field->presence = 0; + } } - upb_mapiter_begin(ret, t); - return ret; -} + /* Account for space used by hasbits. */ + l->size = div_round_up(hasbit, 8); -void upb_mapiter_free(upb_mapiter *i, upb_alloc *a) { - upb_free(a, i); -} + /* Allocate non-oneof fields. */ + for (upb_msg_field_begin(&it, m); !upb_msg_field_done(&it); + upb_msg_field_next(&it)) { + const upb_fielddef* f = upb_msg_iter_field(&it); + size_t field_size = upb_msg_fielddefsize(f); + size_t index = upb_fielddef_index(f); -void upb_mapiter_next(upb_mapiter *i) { - upb_strtable_next(&i->iter); -} + if (upb_fielddef_containingoneof(f)) { + /* Oneofs are handled separately below. */ + continue; + } -bool upb_mapiter_done(const upb_mapiter *i) { - return upb_strtable_done(&i->iter); -} + fields[index].offset = upb_msglayout_place(l, field_size); + } -upb_msgval upb_mapiter_key(const upb_mapiter *i) { - return upb_map_fromkey(i->key_type, upb_strtable_iter_key(&i->iter), - upb_strtable_iter_keylength(&i->iter)); -} + /* Allocate oneof fields. Each oneof field consists of a uint32 for the case + * and space for the actual data. */ + for (upb_msg_oneof_begin(&oit, m); !upb_msg_oneof_done(&oit); + upb_msg_oneof_next(&oit)) { + const upb_oneofdef* o = upb_msg_iter_oneof(&oit); + upb_oneof_iter fit; -upb_msgval upb_mapiter_value(const upb_mapiter *i) { - return upb_msgval_fromval(upb_strtable_iter_value(&i->iter)); -} + size_t case_size = sizeof(uint32_t); /* Could potentially optimize this. */ + size_t field_size = 0; + uint32_t case_offset; + uint32_t data_offset; -void upb_mapiter_setdone(upb_mapiter *i) { - upb_strtable_iter_setdone(&i->iter); -} + /* Calculate field size: the max of all field sizes. */ + for (upb_oneof_begin(&fit, o); + !upb_oneof_done(&fit); + upb_oneof_next(&fit)) { + const upb_fielddef* f = upb_oneof_iter_field(&fit); + field_size = UPB_MAX(field_size, upb_msg_fielddefsize(f)); + } -bool upb_mapiter_isequal(const upb_mapiter *i1, const upb_mapiter *i2) { - return upb_strtable_iter_isequal(&i1->iter, &i2->iter); -} + /* Align and allocate case offset. */ + case_offset = upb_msglayout_place(l, case_size); + data_offset = upb_msglayout_place(l, field_size); + for (upb_oneof_begin(&fit, o); + !upb_oneof_done(&fit); + upb_oneof_next(&fit)) { + const upb_fielddef* f = upb_oneof_iter_field(&fit); + fields[upb_fielddef_index(f)].offset = data_offset; + fields[upb_fielddef_index(f)].presence = ~case_offset; + } + } -/** Handlers for upb_msg ******************************************************/ + /* Size of the entire structure should be a multiple of its greatest + * alignment. TODO: track overall alignment for real? */ + l->size = align_up(l->size, 8); -typedef struct { - size_t offset; - int32_t hasbit; -} upb_msg_handlerdata; + return true; +} -/* Fallback implementation if the handler is not specialized by the producer. */ -#define MSG_WRITER(type, ctype) \ - bool upb_msg_set ## type (void *c, const void *hd, ctype val) { \ - uint8_t *m = c; \ - const upb_msg_handlerdata *d = hd; \ - if (d->hasbit > 0) \ - *(uint8_t*)&m[d->hasbit / 8] |= 1 << (d->hasbit % 8); \ - *(ctype*)&m[d->offset] = val; \ - return true; \ - } \ -MSG_WRITER(double, double) -MSG_WRITER(float, float) -MSG_WRITER(int32, int32_t) -MSG_WRITER(int64, int64_t) -MSG_WRITER(uint32, uint32_t) -MSG_WRITER(uint64, uint64_t) -MSG_WRITER(bool, bool) +/** upb_msgfactory ************************************************************/ -bool upb_msg_setscalarhandler(upb_handlers *h, const upb_fielddef *f, - size_t offset, int32_t hasbit) { - upb_handlerattr attr = UPB_HANDLERATTR_INITIALIZER; - bool ok; +struct upb_msgfactory { + const upb_symtab *symtab; /* We own a ref. */ + upb_inttable layouts; + upb_inttable mergehandlers; +}; - upb_msg_handlerdata *d = upb_gmalloc(sizeof(*d)); - if (!d) return false; - d->offset = offset; - d->hasbit = hasbit; +upb_msgfactory *upb_msgfactory_new(const upb_symtab *symtab) { + upb_msgfactory *ret = upb_gmalloc(sizeof(*ret)); - upb_handlerattr_sethandlerdata(&attr, d); - upb_handlerattr_setalwaysok(&attr, true); - upb_handlers_addcleanup(h, d, upb_gfree); + ret->symtab = symtab; + upb_inttable_init(&ret->layouts, UPB_CTYPE_PTR); + upb_inttable_init(&ret->mergehandlers, UPB_CTYPE_CONSTPTR); -#define TYPE(u, l) \ - case UPB_TYPE_##u: \ - ok = upb_handlers_set##l(h, f, upb_msg_set##l, &attr); break; + return ret; +} - ok = false; +void upb_msgfactory_free(upb_msgfactory *f) { + upb_inttable_iter i; + upb_inttable_begin(&i, &f->layouts); + for(; !upb_inttable_done(&i); upb_inttable_next(&i)) { + upb_msglayout *l = upb_value_getptr(upb_inttable_iter_value(&i)); + upb_msglayout_free(l); + } - switch (upb_fielddef_type(f)) { - TYPE(INT64, int64); - TYPE(INT32, int32); - TYPE(ENUM, int32); - TYPE(UINT64, uint64); - TYPE(UINT32, uint32); - TYPE(DOUBLE, double); - TYPE(FLOAT, float); - TYPE(BOOL, bool); - default: UPB_ASSERT(false); break; + upb_inttable_begin(&i, &f->mergehandlers); + for(; !upb_inttable_done(&i); upb_inttable_next(&i)) { + const upb_handlers *h = upb_value_getconstptr(upb_inttable_iter_value(&i)); + upb_handlers_unref(h, f); } -#undef TYPE - upb_handlerattr_uninit(&attr); - return ok; + upb_inttable_uninit(&f->layouts); + upb_inttable_uninit(&f->mergehandlers); + upb_gfree(f); } -bool upb_msg_getscalarhandlerdata(const upb_handlers *h, - upb_selector_t s, - upb_fieldtype_t *type, - size_t *offset, - int32_t *hasbit) { - const upb_msg_handlerdata *d; - upb_func *f = upb_handlers_gethandler(h, s); +const upb_symtab *upb_msgfactory_symtab(const upb_msgfactory *f) { + return f->symtab; +} - if ((upb_int64_handlerfunc*)f == upb_msg_setint64) { - *type = UPB_TYPE_INT64; - } else if ((upb_int32_handlerfunc*)f == upb_msg_setint32) { - *type = UPB_TYPE_INT32; - } else if ((upb_uint64_handlerfunc*)f == upb_msg_setuint64) { - *type = UPB_TYPE_UINT64; - } else if ((upb_uint32_handlerfunc*)f == upb_msg_setuint32) { - *type = UPB_TYPE_UINT32; - } else if ((upb_double_handlerfunc*)f == upb_msg_setdouble) { - *type = UPB_TYPE_DOUBLE; - } else if ((upb_float_handlerfunc*)f == upb_msg_setfloat) { - *type = UPB_TYPE_FLOAT; - } else if ((upb_bool_handlerfunc*)f == upb_msg_setbool) { - *type = UPB_TYPE_BOOL; +const upb_msglayout *upb_msgfactory_getlayout(upb_msgfactory *f, + const upb_msgdef *m) { + upb_value v; + UPB_ASSERT(upb_symtab_lookupmsg(f->symtab, upb_msgdef_fullname(m)) == m); + UPB_ASSERT(!upb_msgdef_mapentry(m)); + + if (upb_inttable_lookupptr(&f->layouts, m, &v)) { + UPB_ASSERT(upb_value_getptr(v)); + return upb_value_getptr(v); } else { - return false; + /* In case of circular dependency, layout has to be inserted first. */ + upb_msglayout *l = upb_gmalloc(sizeof(*l)); + upb_msgfactory *mutable_f = (void*)f; + upb_inttable_insertptr(&mutable_f->layouts, m, upb_value_ptr(l)); + UPB_ASSERT(l); + if (!upb_msglayout_init(m, l, f)) { + upb_msglayout_free(l); + } + return l; } - - d = upb_handlers_gethandlerdata(h, s); - *offset = d->offset; - *hasbit = d->hasbit; - return true; } /* ** upb::RefCounted Implementation @@ -6425,9 +6660,10 @@ static size_t begin(const upb_table *t) { /* A simple "subclass" of upb_table that only adds a hash function for strings. */ static upb_tabkey strcopy(lookupkey_t k2, upb_alloc *a) { + uint32_t len = (uint32_t) k2.str.len; char *str = upb_malloc(a, k2.str.len + sizeof(uint32_t) + 1); if (str == NULL) return 0; - memcpy(str, &k2.str.len, sizeof(uint32_t)); + memcpy(str, &len, sizeof(uint32_t)); memcpy(str + sizeof(uint32_t), k2.str.str, k2.str.len + 1); return (uintptr_t)str; } @@ -7406,28 +7642,28 @@ static upb_inttable reftables[268]; #endif static const upb_msgdef msgs[22] = { - UPB_MSGDEF_INIT("google.protobuf.DescriptorProto", 41, 8, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[0], 11, 10), UPB_STRTABLE_INIT(10, 15, UPB_CTYPE_PTR, 4, &strentries[0]), false, UPB_SYNTAX_PROTO2, &reftables[0], &reftables[1]), - UPB_MSGDEF_INIT("google.protobuf.DescriptorProto.ExtensionRange", 5, 0, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[11], 3, 2), UPB_STRTABLE_INIT(2, 3, UPB_CTYPE_PTR, 2, &strentries[16]), false, UPB_SYNTAX_PROTO2, &reftables[2], &reftables[3]), - UPB_MSGDEF_INIT("google.protobuf.DescriptorProto.ReservedRange", 5, 0, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[14], 3, 2), UPB_STRTABLE_INIT(2, 3, UPB_CTYPE_PTR, 2, &strentries[20]), false, UPB_SYNTAX_PROTO2, &reftables[4], &reftables[5]), - UPB_MSGDEF_INIT("google.protobuf.EnumDescriptorProto", 12, 2, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[17], 4, 3), UPB_STRTABLE_INIT(3, 3, UPB_CTYPE_PTR, 2, &strentries[24]), false, UPB_SYNTAX_PROTO2, &reftables[6], &reftables[7]), - UPB_MSGDEF_INIT("google.protobuf.EnumOptions", 9, 1, UPB_INTTABLE_INIT(1, 1, UPB_CTYPE_PTR, 1, &intentries[0], &arrays[21], 4, 2), UPB_STRTABLE_INIT(3, 3, UPB_CTYPE_PTR, 2, &strentries[28]), false, UPB_SYNTAX_PROTO2, &reftables[8], &reftables[9]), - UPB_MSGDEF_INIT("google.protobuf.EnumValueDescriptorProto", 9, 1, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[25], 4, 3), UPB_STRTABLE_INIT(3, 3, UPB_CTYPE_PTR, 2, &strentries[32]), false, UPB_SYNTAX_PROTO2, &reftables[10], &reftables[11]), - UPB_MSGDEF_INIT("google.protobuf.EnumValueOptions", 8, 1, UPB_INTTABLE_INIT(1, 1, UPB_CTYPE_PTR, 1, &intentries[2], &arrays[29], 2, 1), UPB_STRTABLE_INIT(2, 3, UPB_CTYPE_PTR, 2, &strentries[36]), false, UPB_SYNTAX_PROTO2, &reftables[12], &reftables[13]), - UPB_MSGDEF_INIT("google.protobuf.FieldDescriptorProto", 24, 1, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[31], 11, 10), UPB_STRTABLE_INIT(10, 15, UPB_CTYPE_PTR, 4, &strentries[40]), false, UPB_SYNTAX_PROTO2, &reftables[14], &reftables[15]), - UPB_MSGDEF_INIT("google.protobuf.FieldOptions", 13, 1, UPB_INTTABLE_INIT(1, 1, UPB_CTYPE_PTR, 1, &intentries[4], &arrays[42], 11, 6), UPB_STRTABLE_INIT(7, 15, UPB_CTYPE_PTR, 4, &strentries[56]), false, UPB_SYNTAX_PROTO2, &reftables[16], &reftables[17]), - UPB_MSGDEF_INIT("google.protobuf.FileDescriptorProto", 43, 6, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[53], 13, 12), UPB_STRTABLE_INIT(12, 15, UPB_CTYPE_PTR, 4, &strentries[72]), false, UPB_SYNTAX_PROTO2, &reftables[18], &reftables[19]), - UPB_MSGDEF_INIT("google.protobuf.FileDescriptorSet", 7, 1, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[66], 2, 1), UPB_STRTABLE_INIT(1, 3, UPB_CTYPE_PTR, 2, &strentries[88]), false, UPB_SYNTAX_PROTO2, &reftables[20], &reftables[21]), - UPB_MSGDEF_INIT("google.protobuf.FileOptions", 38, 1, UPB_INTTABLE_INIT(1, 1, UPB_CTYPE_PTR, 1, &intentries[6], &arrays[68], 42, 17), UPB_STRTABLE_INIT(18, 31, UPB_CTYPE_PTR, 5, &strentries[92]), false, UPB_SYNTAX_PROTO2, &reftables[22], &reftables[23]), - UPB_MSGDEF_INIT("google.protobuf.MessageOptions", 11, 1, UPB_INTTABLE_INIT(1, 1, UPB_CTYPE_PTR, 1, &intentries[8], &arrays[110], 8, 4), UPB_STRTABLE_INIT(5, 7, UPB_CTYPE_PTR, 3, &strentries[124]), false, UPB_SYNTAX_PROTO2, &reftables[24], &reftables[25]), - UPB_MSGDEF_INIT("google.protobuf.MethodDescriptorProto", 16, 1, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[118], 7, 6), UPB_STRTABLE_INIT(6, 7, UPB_CTYPE_PTR, 3, &strentries[132]), false, UPB_SYNTAX_PROTO2, &reftables[26], &reftables[27]), - UPB_MSGDEF_INIT("google.protobuf.MethodOptions", 8, 1, UPB_INTTABLE_INIT(2, 3, UPB_CTYPE_PTR, 2, &intentries[10], &arrays[125], 1, 0), UPB_STRTABLE_INIT(2, 3, UPB_CTYPE_PTR, 2, &strentries[140]), false, UPB_SYNTAX_PROTO2, &reftables[28], &reftables[29]), - UPB_MSGDEF_INIT("google.protobuf.OneofDescriptorProto", 6, 0, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[126], 2, 1), UPB_STRTABLE_INIT(1, 3, UPB_CTYPE_PTR, 2, &strentries[144]), false, UPB_SYNTAX_PROTO2, &reftables[30], &reftables[31]), - UPB_MSGDEF_INIT("google.protobuf.ServiceDescriptorProto", 12, 2, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[128], 4, 3), UPB_STRTABLE_INIT(3, 3, UPB_CTYPE_PTR, 2, &strentries[148]), false, UPB_SYNTAX_PROTO2, &reftables[32], &reftables[33]), - UPB_MSGDEF_INIT("google.protobuf.ServiceOptions", 8, 1, UPB_INTTABLE_INIT(2, 3, UPB_CTYPE_PTR, 2, &intentries[14], &arrays[132], 1, 0), UPB_STRTABLE_INIT(2, 3, UPB_CTYPE_PTR, 2, &strentries[152]), false, UPB_SYNTAX_PROTO2, &reftables[34], &reftables[35]), - UPB_MSGDEF_INIT("google.protobuf.SourceCodeInfo", 7, 1, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[133], 2, 1), UPB_STRTABLE_INIT(1, 3, UPB_CTYPE_PTR, 2, &strentries[156]), false, UPB_SYNTAX_PROTO2, &reftables[36], &reftables[37]), - UPB_MSGDEF_INIT("google.protobuf.SourceCodeInfo.Location", 20, 0, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[135], 7, 5), UPB_STRTABLE_INIT(5, 7, UPB_CTYPE_PTR, 3, &strentries[160]), false, UPB_SYNTAX_PROTO2, &reftables[38], &reftables[39]), - UPB_MSGDEF_INIT("google.protobuf.UninterpretedOption", 19, 1, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[142], 9, 7), UPB_STRTABLE_INIT(7, 15, UPB_CTYPE_PTR, 4, &strentries[168]), false, UPB_SYNTAX_PROTO2, &reftables[40], &reftables[41]), - UPB_MSGDEF_INIT("google.protobuf.UninterpretedOption.NamePart", 7, 0, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[151], 3, 2), UPB_STRTABLE_INIT(2, 3, UPB_CTYPE_PTR, 2, &strentries[184]), false, UPB_SYNTAX_PROTO2, &reftables[42], &reftables[43]), + UPB_MSGDEF_INIT("google.protobuf.DescriptorProto", 41, 8, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[0], 11, 10), UPB_STRTABLE_INIT(10, 15, UPB_CTYPE_PTR, 4, &strentries[0]), false, UPB_SYNTAX_PROTO2, UPB_WELLKNOWN_UNSPECIFIED, &reftables[0], &reftables[1]), + UPB_MSGDEF_INIT("google.protobuf.DescriptorProto.ExtensionRange", 5, 0, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[11], 3, 2), UPB_STRTABLE_INIT(2, 3, UPB_CTYPE_PTR, 2, &strentries[16]), false, UPB_SYNTAX_PROTO2, UPB_WELLKNOWN_UNSPECIFIED, &reftables[2], &reftables[3]), + UPB_MSGDEF_INIT("google.protobuf.DescriptorProto.ReservedRange", 5, 0, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[14], 3, 2), UPB_STRTABLE_INIT(2, 3, UPB_CTYPE_PTR, 2, &strentries[20]), false, UPB_SYNTAX_PROTO2, UPB_WELLKNOWN_UNSPECIFIED, &reftables[4], &reftables[5]), + UPB_MSGDEF_INIT("google.protobuf.EnumDescriptorProto", 12, 2, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[17], 4, 3), UPB_STRTABLE_INIT(3, 3, UPB_CTYPE_PTR, 2, &strentries[24]), false, UPB_SYNTAX_PROTO2, UPB_WELLKNOWN_UNSPECIFIED, &reftables[6], &reftables[7]), + UPB_MSGDEF_INIT("google.protobuf.EnumOptions", 9, 1, UPB_INTTABLE_INIT(1, 1, UPB_CTYPE_PTR, 1, &intentries[0], &arrays[21], 4, 2), UPB_STRTABLE_INIT(3, 3, UPB_CTYPE_PTR, 2, &strentries[28]), false, UPB_SYNTAX_PROTO2, UPB_WELLKNOWN_UNSPECIFIED, &reftables[8], &reftables[9]), + UPB_MSGDEF_INIT("google.protobuf.EnumValueDescriptorProto", 9, 1, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[25], 4, 3), UPB_STRTABLE_INIT(3, 3, UPB_CTYPE_PTR, 2, &strentries[32]), false, UPB_SYNTAX_PROTO2, UPB_WELLKNOWN_UNSPECIFIED, &reftables[10], &reftables[11]), + UPB_MSGDEF_INIT("google.protobuf.EnumValueOptions", 8, 1, UPB_INTTABLE_INIT(1, 1, UPB_CTYPE_PTR, 1, &intentries[2], &arrays[29], 2, 1), UPB_STRTABLE_INIT(2, 3, UPB_CTYPE_PTR, 2, &strentries[36]), false, UPB_SYNTAX_PROTO2, UPB_WELLKNOWN_UNSPECIFIED, &reftables[12], &reftables[13]), + UPB_MSGDEF_INIT("google.protobuf.FieldDescriptorProto", 24, 1, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[31], 11, 10), UPB_STRTABLE_INIT(10, 15, UPB_CTYPE_PTR, 4, &strentries[40]), false, UPB_SYNTAX_PROTO2, UPB_WELLKNOWN_UNSPECIFIED, &reftables[14], &reftables[15]), + UPB_MSGDEF_INIT("google.protobuf.FieldOptions", 13, 1, UPB_INTTABLE_INIT(1, 1, UPB_CTYPE_PTR, 1, &intentries[4], &arrays[42], 11, 6), UPB_STRTABLE_INIT(7, 15, UPB_CTYPE_PTR, 4, &strentries[56]), false, UPB_SYNTAX_PROTO2, UPB_WELLKNOWN_UNSPECIFIED, &reftables[16], &reftables[17]), + UPB_MSGDEF_INIT("google.protobuf.FileDescriptorProto", 43, 6, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[53], 13, 12), UPB_STRTABLE_INIT(12, 15, UPB_CTYPE_PTR, 4, &strentries[72]), false, UPB_SYNTAX_PROTO2, UPB_WELLKNOWN_UNSPECIFIED, &reftables[18], &reftables[19]), + UPB_MSGDEF_INIT("google.protobuf.FileDescriptorSet", 7, 1, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[66], 2, 1), UPB_STRTABLE_INIT(1, 3, UPB_CTYPE_PTR, 2, &strentries[88]), false, UPB_SYNTAX_PROTO2, UPB_WELLKNOWN_UNSPECIFIED, &reftables[20], &reftables[21]), + UPB_MSGDEF_INIT("google.protobuf.FileOptions", 38, 1, UPB_INTTABLE_INIT(1, 1, UPB_CTYPE_PTR, 1, &intentries[6], &arrays[68], 42, 17), UPB_STRTABLE_INIT(18, 31, UPB_CTYPE_PTR, 5, &strentries[92]), false, UPB_SYNTAX_PROTO2, UPB_WELLKNOWN_UNSPECIFIED, &reftables[22], &reftables[23]), + UPB_MSGDEF_INIT("google.protobuf.MessageOptions", 11, 1, UPB_INTTABLE_INIT(1, 1, UPB_CTYPE_PTR, 1, &intentries[8], &arrays[110], 8, 4), UPB_STRTABLE_INIT(5, 7, UPB_CTYPE_PTR, 3, &strentries[124]), false, UPB_SYNTAX_PROTO2, UPB_WELLKNOWN_UNSPECIFIED, &reftables[24], &reftables[25]), + UPB_MSGDEF_INIT("google.protobuf.MethodDescriptorProto", 16, 1, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[118], 7, 6), UPB_STRTABLE_INIT(6, 7, UPB_CTYPE_PTR, 3, &strentries[132]), false, UPB_SYNTAX_PROTO2, UPB_WELLKNOWN_UNSPECIFIED, &reftables[26], &reftables[27]), + UPB_MSGDEF_INIT("google.protobuf.MethodOptions", 8, 1, UPB_INTTABLE_INIT(2, 3, UPB_CTYPE_PTR, 2, &intentries[10], &arrays[125], 1, 0), UPB_STRTABLE_INIT(2, 3, UPB_CTYPE_PTR, 2, &strentries[140]), false, UPB_SYNTAX_PROTO2, UPB_WELLKNOWN_UNSPECIFIED, &reftables[28], &reftables[29]), + UPB_MSGDEF_INIT("google.protobuf.OneofDescriptorProto", 6, 0, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[126], 2, 1), UPB_STRTABLE_INIT(1, 3, UPB_CTYPE_PTR, 2, &strentries[144]), false, UPB_SYNTAX_PROTO2, UPB_WELLKNOWN_UNSPECIFIED, &reftables[30], &reftables[31]), + UPB_MSGDEF_INIT("google.protobuf.ServiceDescriptorProto", 12, 2, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[128], 4, 3), UPB_STRTABLE_INIT(3, 3, UPB_CTYPE_PTR, 2, &strentries[148]), false, UPB_SYNTAX_PROTO2, UPB_WELLKNOWN_UNSPECIFIED, &reftables[32], &reftables[33]), + UPB_MSGDEF_INIT("google.protobuf.ServiceOptions", 8, 1, UPB_INTTABLE_INIT(2, 3, UPB_CTYPE_PTR, 2, &intentries[14], &arrays[132], 1, 0), UPB_STRTABLE_INIT(2, 3, UPB_CTYPE_PTR, 2, &strentries[152]), false, UPB_SYNTAX_PROTO2, UPB_WELLKNOWN_UNSPECIFIED, &reftables[34], &reftables[35]), + UPB_MSGDEF_INIT("google.protobuf.SourceCodeInfo", 7, 1, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[133], 2, 1), UPB_STRTABLE_INIT(1, 3, UPB_CTYPE_PTR, 2, &strentries[156]), false, UPB_SYNTAX_PROTO2, UPB_WELLKNOWN_UNSPECIFIED, &reftables[36], &reftables[37]), + UPB_MSGDEF_INIT("google.protobuf.SourceCodeInfo.Location", 20, 0, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[135], 7, 5), UPB_STRTABLE_INIT(5, 7, UPB_CTYPE_PTR, 3, &strentries[160]), false, UPB_SYNTAX_PROTO2, UPB_WELLKNOWN_UNSPECIFIED, &reftables[38], &reftables[39]), + UPB_MSGDEF_INIT("google.protobuf.UninterpretedOption", 19, 1, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[142], 9, 7), UPB_STRTABLE_INIT(7, 15, UPB_CTYPE_PTR, 4, &strentries[168]), false, UPB_SYNTAX_PROTO2, UPB_WELLKNOWN_UNSPECIFIED, &reftables[40], &reftables[41]), + UPB_MSGDEF_INIT("google.protobuf.UninterpretedOption.NamePart", 7, 0, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[151], 3, 2), UPB_STRTABLE_INIT(2, 3, UPB_CTYPE_PTR, 2, &strentries[184]), false, UPB_SYNTAX_PROTO2, UPB_WELLKNOWN_UNSPECIFIED, &reftables[42], &reftables[43]), }; static const upb_fielddef fields[107] = { @@ -8995,6 +9231,7 @@ static size_t msg_name(void *closure, const void *hd, const char *buf, upb_def_setfullname(upb_msgdef_upcast_mutable(m), name, NULL); upb_descreader_setscopename(r, name); /* Passes ownership of name. */ + return n; } @@ -12309,7 +12546,7 @@ done: return r; } -#line 1 "upb/json/parser.rl" +//#line 1 "upb/json/parser.rl" /* ** upb::json::Parser (upb_json_parser) ** @@ -12335,12 +12572,66 @@ done: #include #include #include +#include #include #include +/* Need to define __USE_XOPEN before including time.h to make strptime work. */ +#ifndef __USE_XOPEN +#define __USE_XOPEN +#endif +#include + #define UPB_JSON_MAX_DEPTH 64 +/* Type of value message */ +enum { + VALUE_NULLVALUE = 0, + VALUE_NUMBERVALUE = 1, + VALUE_STRINGVALUE = 2, + VALUE_BOOLVALUE = 3, + VALUE_STRUCTVALUE = 4, + VALUE_LISTVALUE = 5 +}; + +/* Forward declare */ +static bool is_top_level(upb_json_parser *p); +static bool is_wellknown_msg(upb_json_parser *p, upb_wellknowntype_t type); +static bool is_wellknown_field(upb_json_parser *p, upb_wellknowntype_t type); + +static bool is_number_wrapper_object(upb_json_parser *p); +static bool does_number_wrapper_start(upb_json_parser *p); +static bool does_number_wrapper_end(upb_json_parser *p); + +static bool is_string_wrapper_object(upb_json_parser *p); +static bool does_string_wrapper_start(upb_json_parser *p); +static bool does_string_wrapper_end(upb_json_parser *p); + +static void start_wrapper_object(upb_json_parser *p); +static void end_wrapper_object(upb_json_parser *p); + +static void start_value_object(upb_json_parser *p, int value_type); +static void end_value_object(upb_json_parser *p); + +static void start_listvalue_object(upb_json_parser *p); +static void end_listvalue_object(upb_json_parser *p); + +static void start_structvalue_object(upb_json_parser *p); +static void end_structvalue_object(upb_json_parser *p); + +static void start_object(upb_json_parser *p); +static void end_object(upb_json_parser *p); + +static bool start_subobject(upb_json_parser *p); +static void end_subobject(upb_json_parser *p); + +static void start_member(upb_json_parser *p); +static void end_member(upb_json_parser *p); +static bool end_membername(upb_json_parser *p); + +static const char eof_ch = 'e'; + typedef struct { upb_sink sink; @@ -12368,6 +12659,9 @@ typedef struct { * because |f| is the field in the *current* message (i.e., the map-entry * message itself), not the parent's field that leads to this map. */ const upb_fielddef *mapfield; + + /* True if the field to be parsed is unknown. */ + bool is_unknown_field; } upb_jsonparser_frame; struct upb_json_parser { @@ -12405,6 +12699,13 @@ struct upb_json_parser { /* Intermediate result of parsing a unicode escape sequence. */ uint32_t digit; + + /* Whether to proceed if unknown field is met. */ + bool ignore_json_unknown; + + /* Cache for parsing timestamp due to base and zone are handled in different + * handlers. */ + struct tm tm; }; struct upb_json_parsermethod { @@ -12913,21 +13214,71 @@ static bool end_text(upb_json_parser *p, const char *ptr) { return capture_end(p, ptr); } -static void start_number(upb_json_parser *p, const char *ptr) { +static bool start_number(upb_json_parser *p, const char *ptr) { + if (is_top_level(p)) { + if (is_number_wrapper_object(p)) { + start_wrapper_object(p); + } else if (is_wellknown_msg(p, UPB_WELLKNOWN_VALUE)) { + start_value_object(p, VALUE_NUMBERVALUE); + } else { + return false; + } + } else if (does_number_wrapper_start(p)) { + if (!start_subobject(p)) { + return false; + } + start_wrapper_object(p); + } else if (is_wellknown_field(p, UPB_WELLKNOWN_VALUE)) { + if (!start_subobject(p)) { + return false; + } + start_value_object(p, VALUE_NUMBERVALUE); + } + multipart_startaccum(p); capture_begin(p, ptr); + return true; } static bool parse_number(upb_json_parser *p, bool is_quoted); -static bool end_number(upb_json_parser *p, const char *ptr) { +static bool end_number_nontop(upb_json_parser *p, const char *ptr) { if (!capture_end(p, ptr)) { return false; } + if (p->top->f == NULL) { + multipart_end(p); + return true; + } + return parse_number(p, false); } +static bool end_number(upb_json_parser *p, const char *ptr) { + if (!end_number_nontop(p, ptr)) { + return false; + } + + if (does_number_wrapper_end(p)) { + end_wrapper_object(p); + if (!is_top_level(p)) { + end_subobject(p); + } + return true; + } + + if (is_wellknown_msg(p, UPB_WELLKNOWN_VALUE)) { + end_value_object(p); + if (!is_top_level(p)) { + end_subobject(p); + } + return true; + } + + return true; +} + /* |buf| is NULL-terminated. |buf| itself will never include quotes; * |is_quoted| tells us whether this text originally appeared inside quotes. */ static bool parse_number_from_buffer(upb_json_parser *p, const char *buf, @@ -13077,6 +13428,10 @@ static bool parse_number(upb_json_parser *p, bool is_quoted) { static bool parser_putbool(upb_json_parser *p, bool val) { bool ok; + if (p->top->f == NULL) { + return true; + } + if (upb_fielddef_type(p->top->f) != UPB_TYPE_BOOL) { upb_status_seterrf(&p->status, "Boolean value specified for non-bool field: %s", @@ -13091,8 +13446,120 @@ static bool parser_putbool(upb_json_parser *p, bool val) { return true; } +static bool end_bool(upb_json_parser *p, bool val) { + if (is_top_level(p)) { + if (is_wellknown_msg(p, UPB_WELLKNOWN_BOOLVALUE)) { + start_wrapper_object(p); + } else if (is_wellknown_msg(p, UPB_WELLKNOWN_VALUE)) { + start_value_object(p, VALUE_BOOLVALUE); + } else { + return false; + } + } else if (is_wellknown_field(p, UPB_WELLKNOWN_BOOLVALUE)) { + if (!start_subobject(p)) { + return false; + } + start_wrapper_object(p); + } else if (is_wellknown_field(p, UPB_WELLKNOWN_VALUE)) { + if (!start_subobject(p)) { + return false; + } + start_value_object(p, VALUE_BOOLVALUE); + } + + if (p->top->is_unknown_field) { + return true; + } + + if (!parser_putbool(p, val)) { + return false; + } + + if (is_wellknown_msg(p, UPB_WELLKNOWN_BOOLVALUE)) { + end_wrapper_object(p); + if (!is_top_level(p)) { + end_subobject(p); + } + return true; + } + + if (is_wellknown_msg(p, UPB_WELLKNOWN_VALUE)) { + end_value_object(p); + if (!is_top_level(p)) { + end_subobject(p); + } + return true; + } + + return true; +} + +static bool end_null(upb_json_parser *p) { + const char *zero_ptr = "0"; + + if (is_top_level(p)) { + if (is_wellknown_msg(p, UPB_WELLKNOWN_VALUE)) { + start_value_object(p, VALUE_NULLVALUE); + } else { + return true; + } + } else if (is_wellknown_field(p, UPB_WELLKNOWN_VALUE)) { + if (!start_subobject(p)) { + return false; + } + start_value_object(p, VALUE_NULLVALUE); + } else { + return true; + } + + /* Fill null_value field. */ + multipart_startaccum(p); + capture_begin(p, zero_ptr); + capture_end(p, zero_ptr + 1); + parse_number(p, false); + + end_value_object(p); + if (!is_top_level(p)) { + end_subobject(p); + } + + return true; +} + static bool start_stringval(upb_json_parser *p) { - UPB_ASSERT(p->top->f); + if (is_top_level(p)) { + if (is_string_wrapper_object(p)) { + start_wrapper_object(p); + } else if (is_wellknown_msg(p, UPB_WELLKNOWN_TIMESTAMP) || + is_wellknown_msg(p, UPB_WELLKNOWN_DURATION)) { + start_object(p); + } else if (is_wellknown_msg(p, UPB_WELLKNOWN_VALUE)) { + start_value_object(p, VALUE_STRINGVALUE); + } else { + return false; + } + } else if (does_string_wrapper_start(p)) { + if (!start_subobject(p)) { + return false; + } + start_wrapper_object(p); + } else if (is_wellknown_field(p, UPB_WELLKNOWN_TIMESTAMP) || + is_wellknown_field(p, UPB_WELLKNOWN_DURATION)) { + if (!start_subobject(p)) { + return false; + } + start_object(p); + } else if (is_wellknown_field(p, UPB_WELLKNOWN_VALUE)) { + if (!start_subobject(p)) { + return false; + } + start_value_object(p, VALUE_STRINGVALUE); + } + + if (p->top->f == NULL) { + multipart_startaccum(p); + return true; + } if (upb_fielddef_isstring(p->top->f)) { upb_jsonparser_frame *inner; @@ -13110,6 +13577,7 @@ static bool start_stringval(upb_json_parser *p) { inner->name_table = NULL; inner->is_map = false; inner->is_mapentry = false; + inner->is_unknown_field = false; p->top = inner; if (upb_fielddef_type(p->top->f) == UPB_TYPE_STRING) { @@ -13133,73 +13601,369 @@ static bool start_stringval(upb_json_parser *p) { return true; } else { upb_status_seterrf(&p->status, - "String specified for bool or submessage field: %s", - upb_fielddef_name(p->top->f)); + "String specified for bool or submessage field: %s", + upb_fielddef_name(p->top->f)); + upb_env_reporterror(p->env, &p->status); + return false; + } +} + +static bool end_stringval_nontop(upb_json_parser *p) { + bool ok = true; + + if (is_wellknown_msg(p, UPB_WELLKNOWN_TIMESTAMP) || + is_wellknown_msg(p, UPB_WELLKNOWN_DURATION)) { + multipart_end(p); + return true; + } + + if (p->top->f == NULL) { + multipart_end(p); + return true; + } + + switch (upb_fielddef_type(p->top->f)) { + case UPB_TYPE_BYTES: + if (!base64_push(p, getsel_for_handlertype(p, UPB_HANDLER_STRING), + p->accumulated, p->accumulated_len)) { + return false; + } + /* Fall through. */ + + case UPB_TYPE_STRING: { + upb_selector_t sel = getsel_for_handlertype(p, UPB_HANDLER_ENDSTR); + p->top--; + upb_sink_endstr(&p->top->sink, sel); + break; + } + + case UPB_TYPE_ENUM: { + /* Resolve enum symbolic name to integer value. */ + const upb_enumdef *enumdef = + (const upb_enumdef*)upb_fielddef_subdef(p->top->f); + + size_t len; + const char *buf = accumulate_getptr(p, &len); + + int32_t int_val = 0; + ok = upb_enumdef_ntoi(enumdef, buf, len, &int_val); + + if (ok) { + upb_selector_t sel = parser_getsel(p); + upb_sink_putint32(&p->top->sink, sel, int_val); + } else { + upb_status_seterrf(&p->status, "Enum value unknown: '%.*s'", len, buf); + upb_env_reporterror(p->env, &p->status); + } + + break; + } + + case UPB_TYPE_INT32: + case UPB_TYPE_INT64: + case UPB_TYPE_UINT32: + case UPB_TYPE_UINT64: + case UPB_TYPE_DOUBLE: + case UPB_TYPE_FLOAT: + ok = parse_number(p, true); + break; + + default: + UPB_ASSERT(false); + upb_status_seterrmsg(&p->status, "Internal error in JSON decoder"); + upb_env_reporterror(p->env, &p->status); + ok = false; + break; + } + + multipart_end(p); + + return ok; +} + +static bool end_stringval(upb_json_parser *p) { + if (!end_stringval_nontop(p)) { + return false; + } + + if (does_string_wrapper_end(p)) { + end_wrapper_object(p); + if (!is_top_level(p)) { + end_subobject(p); + } + return true; + } + + if (is_wellknown_msg(p, UPB_WELLKNOWN_VALUE)) { + end_value_object(p); + if (!is_top_level(p)) { + end_subobject(p); + } + return true; + } + + if (is_wellknown_msg(p, UPB_WELLKNOWN_TIMESTAMP) || + is_wellknown_msg(p, UPB_WELLKNOWN_DURATION)) { + end_object(p); + if (!is_top_level(p)) { + end_subobject(p); + } + return true; + } + + return true; +} + +static void start_duration_base(upb_json_parser *p, const char *ptr) { + capture_begin(p, ptr); +} + +static bool end_duration_base(upb_json_parser *p, const char *ptr) { + size_t len; + const char *buf; + char seconds_buf[14]; + char nanos_buf[12]; + char *end; + int64_t seconds = 0; + int32_t nanos = 0; + double val = 0.0; + const char *seconds_membername = "seconds"; + const char *nanos_membername = "nanos"; + size_t fraction_start; + + if (!capture_end(p, ptr)) { + return false; + } + + buf = accumulate_getptr(p, &len); + + memset(seconds_buf, 0, 14); + memset(nanos_buf, 0, 12); + + /* Find out base end. The maximus duration is 315576000000, which cannot be + * represented by double without losing precision. Thus, we need to handle + * fraction and base separately. */ + for (fraction_start = 0; fraction_start < len && buf[fraction_start] != '.'; + fraction_start++); + + /* Parse base */ + memcpy(seconds_buf, buf, fraction_start); + seconds = strtol(seconds_buf, &end, 10); + if (errno == ERANGE || end != seconds_buf + fraction_start) { + upb_status_seterrf(&p->status, "error parsing duration: %s", + seconds_buf); + upb_env_reporterror(p->env, &p->status); + return false; + } + + if (seconds > 315576000000) { + upb_status_seterrf(&p->status, "error parsing duration: " + "maximum acceptable value is " + "315576000000"); + upb_env_reporterror(p->env, &p->status); + return false; + } + + if (seconds < -315576000000) { + upb_status_seterrf(&p->status, "error parsing duration: " + "minimum acceptable value is " + "-315576000000"); + upb_env_reporterror(p->env, &p->status); + return false; + } + + /* Parse fraction */ + nanos_buf[0] = '0'; + memcpy(nanos_buf + 1, buf + fraction_start, len - fraction_start); + val = strtod(nanos_buf, &end); + if (errno == ERANGE || end != nanos_buf + len - fraction_start + 1) { + upb_status_seterrf(&p->status, "error parsing duration: %s", + nanos_buf); + upb_env_reporterror(p->env, &p->status); + return false; + } + + nanos = val * 1000000000; + if (seconds < 0) nanos = -nanos; + + /* Clean up buffer */ + multipart_end(p); + + /* Set seconds */ + start_member(p); + capture_begin(p, seconds_membername); + capture_end(p, seconds_membername + 7); + end_membername(p); + upb_sink_putint64(&p->top->sink, parser_getsel(p), seconds); + end_member(p); + + /* Set nanos */ + start_member(p); + capture_begin(p, nanos_membername); + capture_end(p, nanos_membername + 5); + end_membername(p); + upb_sink_putint32(&p->top->sink, parser_getsel(p), nanos); + end_member(p); + + /* Continue previous environment */ + multipart_startaccum(p); + + return true; +} + +static void start_timestamp_base(upb_json_parser *p, const char *ptr) { + capture_begin(p, ptr); +} + +#define UPB_TIMESTAMP_BASE_SIZE 19 + +static bool end_timestamp_base(upb_json_parser *p, const char *ptr) { + size_t len; + const char *buf; + /* 3 for GMT and 1 for ending 0 */ + char timestamp_buf[UPB_TIMESTAMP_BASE_SIZE + 4]; + + if (!capture_end(p, ptr)) { + return false; + } + + buf = accumulate_getptr(p, &len); + UPB_ASSERT(len == UPB_TIMESTAMP_BASE_SIZE); + memcpy(timestamp_buf, buf, UPB_TIMESTAMP_BASE_SIZE); + memcpy(timestamp_buf + UPB_TIMESTAMP_BASE_SIZE, "GMT", 3); + timestamp_buf[UPB_TIMESTAMP_BASE_SIZE + 3] = 0; + + /* Parse seconds */ + if (strptime(timestamp_buf, "%FT%H:%M:%S%Z", &p->tm) == NULL) { + upb_status_seterrf(&p->status, "error parsing timestamp: %s", buf); + upb_env_reporterror(p->env, &p->status); + return false; + } + + /* Clean up buffer */ + multipart_end(p); + multipart_startaccum(p); + + return true; +} + +static void start_timestamp_fraction(upb_json_parser *p, const char *ptr) { + capture_begin(p, ptr); +} + +static bool end_timestamp_fraction(upb_json_parser *p, const char *ptr) { + size_t len; + const char *buf; + char nanos_buf[12]; + char *end; + double val = 0.0; + int32_t nanos; + const char *nanos_membername = "nanos"; + + memset(nanos_buf, 0, 12); + + if (!capture_end(p, ptr)) { + return false; + } + + buf = accumulate_getptr(p, &len); + + if (len > 10) { + upb_status_seterrf(&p->status, + "error parsing timestamp: at most 9-digit fraction."); upb_env_reporterror(p->env, &p->status); return false; } -} -static bool end_stringval(upb_json_parser *p) { - bool ok = true; + /* Parse nanos */ + nanos_buf[0] = '0'; + memcpy(nanos_buf + 1, buf, len); + val = strtod(nanos_buf, &end); - switch (upb_fielddef_type(p->top->f)) { - case UPB_TYPE_BYTES: - if (!base64_push(p, getsel_for_handlertype(p, UPB_HANDLER_STRING), - p->accumulated, p->accumulated_len)) { - return false; - } - /* Fall through. */ + if (errno == ERANGE || end != nanos_buf + len + 1) { + upb_status_seterrf(&p->status, "error parsing timestamp nanos: %s", + nanos_buf); + upb_env_reporterror(p->env, &p->status); + return false; + } - case UPB_TYPE_STRING: { - upb_selector_t sel = getsel_for_handlertype(p, UPB_HANDLER_ENDSTR); - p->top--; - upb_sink_endstr(&p->top->sink, sel); - break; - } + nanos = val * 1000000000; - case UPB_TYPE_ENUM: { - /* Resolve enum symbolic name to integer value. */ - const upb_enumdef *enumdef = - (const upb_enumdef*)upb_fielddef_subdef(p->top->f); + /* Clean up previous environment */ + multipart_end(p); - size_t len; - const char *buf = accumulate_getptr(p, &len); + /* Set nanos */ + start_member(p); + capture_begin(p, nanos_membername); + capture_end(p, nanos_membername + 5); + end_membername(p); + upb_sink_putint32(&p->top->sink, parser_getsel(p), nanos); + end_member(p); - int32_t int_val = 0; - ok = upb_enumdef_ntoi(enumdef, buf, len, &int_val); + /* Continue previous environment */ + multipart_startaccum(p); - if (ok) { - upb_selector_t sel = parser_getsel(p); - upb_sink_putint32(&p->top->sink, sel, int_val); - } else { - upb_status_seterrf(&p->status, "Enum value unknown: '%.*s'", len, buf); - upb_env_reporterror(p->env, &p->status); - } + return true; +} - break; - } +static void start_timestamp_zone(upb_json_parser *p, const char *ptr) { + capture_begin(p, ptr); +} - case UPB_TYPE_INT32: - case UPB_TYPE_INT64: - case UPB_TYPE_UINT32: - case UPB_TYPE_UINT64: - case UPB_TYPE_DOUBLE: - case UPB_TYPE_FLOAT: - ok = parse_number(p, true); - break; +static bool end_timestamp_zone(upb_json_parser *p, const char *ptr) { + size_t len; + const char *buf; + int hours; + int64_t seconds; + const char *seconds_membername = "seconds"; - default: - UPB_ASSERT(false); - upb_status_seterrmsg(&p->status, "Internal error in JSON decoder"); + if (!capture_end(p, ptr)) { + return false; + } + + buf = accumulate_getptr(p, &len); + + if (buf[0] != 'Z') { + if (sscanf(buf + 1, "%2d:00", &hours) != 1) { + upb_status_seterrf(&p->status, "error parsing timestamp offset"); upb_env_reporterror(p->env, &p->status); - ok = false; - break; + return false; + } + + if (buf[0] == '+') { + hours = -hours; + } + + p->tm.tm_hour += hours; + } + + /* Normalize tm */ + seconds = mktime(&p->tm); + + /* Check timestamp boundary */ + if (seconds < -62135596800) { + upb_status_seterrf(&p->status, "error parsing timestamp: " + "minimum acceptable value is " + "0001-01-01T00:00:00Z"); + upb_env_reporterror(p->env, &p->status); + return false; } + /* Clean up previous environment */ multipart_end(p); - return ok; + /* Set seconds */ + start_member(p); + capture_begin(p, seconds_membername); + capture_end(p, seconds_membername + 7); + end_membername(p); + upb_sink_putint64(&p->top->sink, parser_getsel(p), seconds); + end_member(p); + + /* Continue previous environment */ + multipart_startaccum(p); + + return true; } static void start_member(upb_json_parser *p) { @@ -13305,6 +14069,7 @@ static bool handle_mapentry(upb_json_parser *p) { inner->name_table = NULL; inner->mapfield = mapfield; inner->is_map = false; + inner->is_unknown_field = false; /* Don't set this to true *yet* -- we reuse parsing handlers below to push * the key field value to the sink, and these handlers will pop the frame @@ -13334,6 +14099,12 @@ static bool handle_mapentry(upb_json_parser *p) { static bool end_membername(upb_json_parser *p) { UPB_ASSERT(!p->top->f); + if (!p->top->m) { + p->top->is_unknown_field = true; + multipart_end(p); + return true; + } + if (p->top->is_map) { return handle_mapentry(p); } else { @@ -13345,10 +14116,12 @@ static bool end_membername(upb_json_parser *p) { p->top->f = upb_value_getconstptr(v); multipart_end(p); + return true; + } else if (p->ignore_json_unknown) { + p->top->is_unknown_field = true; + multipart_end(p); return true; } else { - /* TODO(haberman): Ignore unknown fields if requested/configured to do - * so. */ upb_status_seterrf(&p->status, "No such field: %.*s\n", (int)len, buf); upb_env_reporterror(p->env, &p->status); return false; @@ -13377,10 +14150,23 @@ static void end_member(upb_json_parser *p) { } p->top->f = NULL; + p->top->is_unknown_field = false; } static bool start_subobject(upb_json_parser *p) { - UPB_ASSERT(p->top->f); + if (p->top->is_unknown_field) { + upb_jsonparser_frame *inner; + if (!check_stack(p)) return false; + + inner = p->top + 1; + inner->m = NULL; + inner->f = NULL; + inner->is_map = false; + inner->is_mapentry = false; + inner->is_unknown_field = false; + p->top = inner; + return true; + } if (upb_fielddef_ismap(p->top->f)) { upb_jsonparser_frame *inner; @@ -13399,6 +14185,7 @@ static bool start_subobject(upb_json_parser *p) { inner->f = NULL; inner->is_map = true; inner->is_mapentry = false; + inner->is_unknown_field = false; p->top = inner; return true; @@ -13419,6 +14206,7 @@ static bool start_subobject(upb_json_parser *p) { inner->f = NULL; inner->is_map = false; inner->is_mapentry = false; + inner->is_unknown_field = false; p->top = inner; return true; @@ -13431,7 +14219,35 @@ static bool start_subobject(upb_json_parser *p) { } } +static bool start_subobject_full(upb_json_parser *p) { + if (is_top_level(p)) { + if (is_wellknown_msg(p, UPB_WELLKNOWN_VALUE)) { + start_value_object(p, VALUE_STRUCTVALUE); + if (!start_subobject(p)) return false; + start_structvalue_object(p); + } else if (is_wellknown_msg(p, UPB_WELLKNOWN_STRUCT)) { + start_structvalue_object(p); + } else { + return true; + } + } else if (is_wellknown_field(p, UPB_WELLKNOWN_STRUCT)) { + if (!start_subobject(p)) return false; + start_structvalue_object(p); + } else if (is_wellknown_field(p, UPB_WELLKNOWN_VALUE)) { + if (!start_subobject(p)) return false; + start_value_object(p, VALUE_STRUCTVALUE); + if (!start_subobject(p)) return false; + start_structvalue_object(p); + } + + return start_subobject(p); +} + static void end_subobject(upb_json_parser *p) { + if (is_top_level(p)) { + return; + } + if (p->top->is_map) { upb_selector_t sel; p->top--; @@ -13439,9 +14255,30 @@ static void end_subobject(upb_json_parser *p) { upb_sink_endseq(&p->top->sink, sel); } else { upb_selector_t sel; + bool is_unknown = p->top->m == NULL; p->top--; - sel = getsel_for_handlertype(p, UPB_HANDLER_ENDSUBMSG); - upb_sink_endsubmsg(&p->top->sink, sel); + if (!is_unknown) { + sel = getsel_for_handlertype(p, UPB_HANDLER_ENDSUBMSG); + upb_sink_endsubmsg(&p->top->sink, sel); + } + } +} + +static void end_subobject_full(upb_json_parser *p) { + end_subobject(p); + + if (is_wellknown_msg(p, UPB_WELLKNOWN_STRUCT)) { + end_structvalue_object(p); + if (!is_top_level(p)) { + end_subobject(p); + } + } + + if (is_wellknown_msg(p, UPB_WELLKNOWN_VALUE)) { + end_value_object(p); + if (!is_top_level(p)) { + end_subobject(p); + } } } @@ -13449,7 +14286,38 @@ static bool start_array(upb_json_parser *p) { upb_jsonparser_frame *inner; upb_selector_t sel; - UPB_ASSERT(p->top->f); + if (is_top_level(p)) { + if (is_wellknown_msg(p, UPB_WELLKNOWN_VALUE)) { + start_value_object(p, VALUE_LISTVALUE); + if (!start_subobject(p)) return false; + start_listvalue_object(p); + } else if (is_wellknown_msg(p, UPB_WELLKNOWN_LISTVALUE)) { + start_listvalue_object(p); + } else { + return false; + } + } else if (is_wellknown_field(p, UPB_WELLKNOWN_LISTVALUE)) { + if (!start_subobject(p)) return false; + start_listvalue_object(p); + } else if (is_wellknown_field(p, UPB_WELLKNOWN_VALUE)) { + if (!start_subobject(p)) return false; + start_value_object(p, VALUE_LISTVALUE); + if (!start_subobject(p)) return false; + start_listvalue_object(p); + } + + if (p->top->is_unknown_field) { + inner = p->top + 1; + inner->m = NULL; + inner->name_table = NULL; + inner->f = NULL; + inner->is_map = false; + inner->is_mapentry = false; + inner->is_unknown_field = true; + p->top = inner; + + return true; + } if (!upb_fielddef_isseq(p->top->f)) { upb_status_seterrf(&p->status, @@ -13469,6 +14337,7 @@ static bool start_array(upb_json_parser *p) { inner->f = p->top->f; inner->is_map = false; inner->is_mapentry = false; + inner->is_unknown_field = false; p->top = inner; return true; @@ -13480,18 +14349,37 @@ static void end_array(upb_json_parser *p) { UPB_ASSERT(p->top > p->stack); p->top--; + + if (p->top->is_unknown_field) { + return; + } + sel = getsel_for_handlertype(p, UPB_HANDLER_ENDSEQ); upb_sink_endseq(&p->top->sink, sel); + + if (is_wellknown_msg(p, UPB_WELLKNOWN_LISTVALUE)) { + end_listvalue_object(p); + if (!is_top_level(p)) { + end_subobject(p); + } + } + + if (is_wellknown_msg(p, UPB_WELLKNOWN_VALUE)) { + end_value_object(p); + if (!is_top_level(p)) { + end_subobject(p); + } + } } static void start_object(upb_json_parser *p) { - if (!p->top->is_map) { + if (!p->top->is_map && p->top->m != NULL) { upb_sink_startmsg(&p->top->sink); } } static void end_object(upb_json_parser *p) { - if (!p->top->is_map) { + if (!p->top->is_map && p->top->m != NULL) { upb_status status; upb_status_clear(&status); upb_sink_endmsg(&p->top->sink, &status); @@ -13501,6 +14389,149 @@ static void end_object(upb_json_parser *p) { } } +static bool is_string_wrapper(const upb_msgdef *m) { + upb_wellknowntype_t type = upb_msgdef_wellknowntype(m); + return type == UPB_WELLKNOWN_STRINGVALUE || + type == UPB_WELLKNOWN_BYTESVALUE; +} + +static void start_wrapper_object(upb_json_parser *p) { + const char *membername = "value"; + + start_object(p); + + /* Set up context for parsing value */ + start_member(p); + capture_begin(p, membername); + capture_end(p, membername + 5); + end_membername(p); +} + +static void end_wrapper_object(upb_json_parser *p) { + end_member(p); + end_object(p); +} + +static void start_value_object(upb_json_parser *p, int value_type) { + const char *nullmember = "null_value"; + const char *numbermember = "number_value"; + const char *stringmember = "string_value"; + const char *boolmember = "bool_value"; + const char *structmember = "struct_value"; + const char *listmember = "list_value"; + const char *membername = ""; + + switch (value_type) { + case VALUE_NULLVALUE: + membername = nullmember; + break; + case VALUE_NUMBERVALUE: + membername = numbermember; + break; + case VALUE_STRINGVALUE: + membername = stringmember; + break; + case VALUE_BOOLVALUE: + membername = boolmember; + break; + case VALUE_STRUCTVALUE: + membername = structmember; + break; + case VALUE_LISTVALUE: + membername = listmember; + break; + } + + start_object(p); + + /* Set up context for parsing value */ + start_member(p); + capture_begin(p, membername); + capture_end(p, membername + strlen(membername)); + end_membername(p); +} + +static void end_value_object(upb_json_parser *p) { + end_member(p); + end_object(p); +} + +static void start_listvalue_object(upb_json_parser *p) { + const char *membername = "values"; + + start_object(p); + + /* Set up context for parsing value */ + start_member(p); + capture_begin(p, membername); + capture_end(p, membername + strlen(membername)); + end_membername(p); +} + +static void end_listvalue_object(upb_json_parser *p) { + end_member(p); + end_object(p); +} + +static void start_structvalue_object(upb_json_parser *p) { + const char *membername = "fields"; + + start_object(p); + + /* Set up context for parsing value */ + start_member(p); + capture_begin(p, membername); + capture_end(p, membername + strlen(membername)); + end_membername(p); +} + +static void end_structvalue_object(upb_json_parser *p) { + end_member(p); + end_object(p); +} + +static bool is_top_level(upb_json_parser *p) { + return p->top == p->stack && p->top->f == NULL && !p->top->is_unknown_field; +} + +static bool is_wellknown_msg(upb_json_parser *p, upb_wellknowntype_t type) { + return p->top->m != NULL && upb_msgdef_wellknowntype(p->top->m) == type; +} + +static bool is_wellknown_field(upb_json_parser *p, upb_wellknowntype_t type) { + return p->top->f != NULL && + upb_fielddef_issubmsg(p->top->f) && + (upb_msgdef_wellknowntype(upb_fielddef_msgsubdef(p->top->f)) + == type); +} + +static bool does_number_wrapper_start(upb_json_parser *p) { + return p->top->f != NULL && + upb_fielddef_issubmsg(p->top->f) && + upb_msgdef_isnumberwrapper(upb_fielddef_msgsubdef(p->top->f)); +} + +static bool does_number_wrapper_end(upb_json_parser *p) { + return p->top->m != NULL && upb_msgdef_isnumberwrapper(p->top->m); +} + +static bool is_number_wrapper_object(upb_json_parser *p) { + return p->top->m != NULL && upb_msgdef_isnumberwrapper(p->top->m); +} + +static bool does_string_wrapper_start(upb_json_parser *p) { + return p->top->f != NULL && + upb_fielddef_issubmsg(p->top->f) && + is_string_wrapper(upb_fielddef_msgsubdef(p->top->f)); +} + +static bool does_string_wrapper_end(upb_json_parser *p) { + return p->top->m != NULL && is_string_wrapper(p->top->m); +} + +static bool is_string_wrapper_object(upb_json_parser *p) { + return p->top->m != NULL && is_string_wrapper(p->top->m); +} #define CHECK_RETURN_TOP(x) if (!(x)) goto error @@ -13523,160 +14554,262 @@ static void end_object(upb_json_parser *p) { * final state once, when the closing '"' is seen. */ -#line 1310 "upb/json/parser.rl" +//#line 2147 "upb/json/parser.rl" -#line 1222 "upb/json/parser.c" +//#line 2016 "upb/json/parser.c" static const char _json_actions[] = { - 0, 1, 0, 1, 2, 1, 3, 1, - 5, 1, 6, 1, 7, 1, 8, 1, - 10, 1, 12, 1, 13, 1, 14, 1, - 15, 1, 16, 1, 17, 1, 21, 1, - 25, 1, 27, 2, 3, 8, 2, 4, - 5, 2, 6, 2, 2, 6, 8, 2, - 11, 9, 2, 13, 15, 2, 14, 15, - 2, 18, 1, 2, 19, 27, 2, 20, - 9, 2, 22, 27, 2, 23, 27, 2, - 24, 27, 2, 26, 27, 3, 14, 11, - 9 + 0, 1, 0, 1, 1, 1, 3, 1, + 4, 1, 6, 1, 7, 1, 8, 1, + 9, 1, 10, 1, 11, 1, 12, 1, + 13, 1, 21, 1, 23, 1, 24, 1, + 25, 1, 27, 1, 28, 1, 30, 1, + 32, 1, 33, 1, 34, 1, 35, 1, + 36, 1, 38, 2, 4, 9, 2, 5, + 6, 2, 7, 3, 2, 7, 9, 2, + 14, 15, 2, 16, 17, 2, 18, 19, + 2, 22, 20, 2, 26, 37, 2, 29, + 2, 2, 30, 38, 2, 31, 20, 2, + 33, 38, 2, 34, 38, 2, 35, 38, + 3, 25, 22, 20, 3, 26, 37, 38, + 4, 14, 15, 16, 17 }; -static const unsigned char _json_key_offsets[] = { - 0, 0, 4, 9, 14, 15, 19, 24, - 29, 34, 38, 42, 45, 48, 50, 54, - 58, 60, 62, 67, 69, 71, 80, 86, - 92, 98, 104, 106, 115, 116, 116, 116, - 121, 126, 131, 132, 133, 134, 135, 135, - 136, 137, 138, 138, 139, 140, 141, 141, - 146, 151, 152, 156, 161, 166, 171, 175, - 175, 178, 178, 178 +static const short _json_key_offsets[] = { + 0, 0, 12, 13, 18, 23, 28, 29, + 30, 31, 32, 33, 34, 35, 36, 37, + 38, 43, 48, 49, 53, 58, 63, 68, + 72, 76, 79, 82, 84, 88, 92, 94, + 96, 101, 103, 105, 114, 120, 126, 132, + 138, 140, 144, 147, 149, 151, 154, 155, + 159, 161, 163, 165, 167, 168, 170, 172, + 173, 175, 177, 178, 180, 182, 183, 185, + 187, 188, 190, 192, 196, 198, 200, 201, + 202, 203, 204, 206, 211, 220, 221, 221, + 221, 226, 231, 236, 237, 238, 239, 240, + 240, 241, 242, 243, 243, 244, 245, 246, + 246, 251, 256, 257, 261, 266, 271, 276, + 280, 280, 283, 286, 289, 292, 295, 298, + 298, 298, 298, 298 }; static const char _json_trans_keys[] = { - 32, 123, 9, 13, 32, 34, 125, 9, - 13, 32, 34, 125, 9, 13, 34, 32, - 58, 9, 13, 32, 93, 125, 9, 13, - 32, 44, 125, 9, 13, 32, 44, 125, - 9, 13, 32, 34, 9, 13, 45, 48, - 49, 57, 48, 49, 57, 46, 69, 101, - 48, 57, 69, 101, 48, 57, 43, 45, - 48, 57, 48, 57, 48, 57, 46, 69, - 101, 48, 57, 34, 92, 34, 92, 34, - 47, 92, 98, 102, 110, 114, 116, 117, + 32, 34, 45, 91, 102, 110, 116, 123, + 9, 13, 48, 57, 34, 32, 93, 125, + 9, 13, 32, 44, 93, 9, 13, 32, + 93, 125, 9, 13, 97, 108, 115, 101, + 117, 108, 108, 114, 117, 101, 32, 34, + 125, 9, 13, 32, 34, 125, 9, 13, + 34, 32, 58, 9, 13, 32, 93, 125, + 9, 13, 32, 44, 125, 9, 13, 32, + 44, 125, 9, 13, 32, 34, 9, 13, + 45, 48, 49, 57, 48, 49, 57, 46, + 69, 101, 48, 57, 69, 101, 48, 57, + 43, 45, 48, 57, 48, 57, 48, 57, + 46, 69, 101, 48, 57, 34, 92, 34, + 92, 34, 47, 92, 98, 102, 110, 114, + 116, 117, 48, 57, 65, 70, 97, 102, 48, 57, 65, 70, 97, 102, 48, 57, 65, 70, 97, 102, 48, 57, 65, 70, - 97, 102, 48, 57, 65, 70, 97, 102, - 34, 92, 34, 45, 91, 102, 110, 116, - 123, 48, 57, 34, 32, 93, 125, 9, - 13, 32, 44, 93, 9, 13, 32, 93, - 125, 9, 13, 97, 108, 115, 101, 117, - 108, 108, 114, 117, 101, 32, 34, 125, - 9, 13, 32, 34, 125, 9, 13, 34, - 32, 58, 9, 13, 32, 93, 125, 9, - 13, 32, 44, 125, 9, 13, 32, 44, - 125, 9, 13, 32, 34, 9, 13, 32, + 97, 102, 34, 92, 45, 48, 49, 57, + 48, 49, 57, 46, 115, 48, 57, 115, + 48, 57, 34, 46, 115, 48, 57, 48, + 57, 48, 57, 48, 57, 48, 57, 45, + 48, 57, 48, 57, 45, 48, 57, 48, + 57, 84, 48, 57, 48, 57, 58, 48, + 57, 48, 57, 58, 48, 57, 48, 57, + 43, 45, 46, 90, 48, 57, 48, 57, + 58, 48, 48, 34, 48, 57, 43, 45, + 90, 48, 57, 34, 45, 91, 102, 110, + 116, 123, 48, 57, 34, 32, 93, 125, + 9, 13, 32, 44, 93, 9, 13, 32, + 93, 125, 9, 13, 97, 108, 115, 101, + 117, 108, 108, 114, 117, 101, 32, 34, + 125, 9, 13, 32, 34, 125, 9, 13, + 34, 32, 58, 9, 13, 32, 93, 125, + 9, 13, 32, 44, 125, 9, 13, 32, + 44, 125, 9, 13, 32, 34, 9, 13, + 32, 9, 13, 32, 9, 13, 32, 9, + 13, 32, 9, 13, 32, 9, 13, 32, 9, 13, 0 }; static const char _json_single_lengths[] = { - 0, 2, 3, 3, 1, 2, 3, 3, - 3, 2, 2, 1, 3, 0, 2, 2, - 0, 0, 3, 2, 2, 9, 0, 0, - 0, 0, 2, 7, 1, 0, 0, 3, - 3, 3, 1, 1, 1, 1, 0, 1, - 1, 1, 0, 1, 1, 1, 0, 3, - 3, 1, 2, 3, 3, 3, 2, 0, - 1, 0, 0, 0 + 0, 8, 1, 3, 3, 3, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 3, 3, 1, 2, 3, 3, 3, 2, + 2, 1, 3, 0, 2, 2, 0, 0, + 3, 2, 2, 9, 0, 0, 0, 0, + 2, 2, 1, 2, 0, 1, 1, 2, + 0, 0, 0, 0, 1, 0, 0, 1, + 0, 0, 1, 0, 0, 1, 0, 0, + 1, 0, 0, 4, 0, 0, 1, 1, + 1, 1, 0, 3, 7, 1, 0, 0, + 3, 3, 3, 1, 1, 1, 1, 0, + 1, 1, 1, 0, 1, 1, 1, 0, + 3, 3, 1, 2, 3, 3, 3, 2, + 0, 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0 }; static const char _json_range_lengths[] = { - 0, 1, 1, 1, 0, 1, 1, 1, - 1, 1, 1, 1, 0, 1, 1, 1, - 1, 1, 1, 0, 0, 0, 3, 3, - 3, 3, 0, 1, 0, 0, 0, 1, - 1, 1, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 1, - 1, 0, 1, 1, 1, 1, 1, 0, - 1, 0, 0, 0 + 0, 2, 0, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 1, 1, 1, 1, 1, + 1, 1, 0, 1, 1, 1, 1, 1, + 1, 0, 0, 0, 3, 3, 3, 3, + 0, 1, 1, 0, 1, 1, 0, 1, + 1, 1, 1, 1, 0, 1, 1, 0, + 1, 1, 0, 1, 1, 0, 1, 1, + 0, 1, 1, 0, 1, 1, 0, 0, + 0, 0, 1, 1, 1, 0, 0, 0, + 1, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 1, 1, 1, 1, 1, + 0, 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0 }; static const short _json_index_offsets[] = { - 0, 0, 4, 9, 14, 16, 20, 25, - 30, 35, 39, 43, 46, 50, 52, 56, - 60, 62, 64, 69, 72, 75, 85, 89, - 93, 97, 101, 104, 113, 115, 116, 117, - 122, 127, 132, 134, 136, 138, 140, 141, - 143, 145, 147, 148, 150, 152, 154, 155, - 160, 165, 167, 171, 176, 181, 186, 190, - 191, 194, 195, 196 + 0, 0, 11, 13, 18, 23, 28, 30, + 32, 34, 36, 38, 40, 42, 44, 46, + 48, 53, 58, 60, 64, 69, 74, 79, + 83, 87, 90, 94, 96, 100, 104, 106, + 108, 113, 116, 119, 129, 133, 137, 141, + 145, 148, 152, 155, 158, 160, 163, 165, + 169, 171, 173, 175, 177, 179, 181, 183, + 185, 187, 189, 191, 193, 195, 197, 199, + 201, 203, 205, 207, 212, 214, 216, 218, + 220, 222, 224, 226, 231, 240, 242, 243, + 244, 249, 254, 259, 261, 263, 265, 267, + 268, 270, 272, 274, 275, 277, 279, 281, + 282, 287, 292, 294, 298, 303, 308, 313, + 317, 318, 321, 324, 327, 330, 333, 336, + 337, 338, 339, 340 }; -static const char _json_indicies[] = { - 0, 2, 0, 1, 3, 4, 5, 3, - 1, 6, 7, 8, 6, 1, 9, 1, - 10, 11, 10, 1, 11, 1, 1, 11, - 12, 13, 14, 15, 13, 1, 16, 17, - 8, 16, 1, 17, 7, 17, 1, 18, - 19, 20, 1, 19, 20, 1, 22, 23, - 23, 21, 24, 1, 23, 23, 24, 21, - 25, 25, 26, 1, 26, 1, 26, 21, - 22, 23, 23, 20, 21, 28, 29, 27, - 31, 32, 30, 33, 33, 33, 33, 33, - 33, 33, 33, 34, 1, 35, 35, 35, - 1, 36, 36, 36, 1, 37, 37, 37, - 1, 38, 38, 38, 1, 40, 41, 39, - 42, 43, 44, 45, 46, 47, 48, 43, - 1, 49, 1, 50, 51, 53, 54, 1, - 53, 52, 55, 56, 54, 55, 1, 56, - 1, 1, 56, 52, 57, 1, 58, 1, - 59, 1, 60, 1, 61, 62, 1, 63, - 1, 64, 1, 65, 66, 1, 67, 1, - 68, 1, 69, 70, 71, 72, 70, 1, - 73, 74, 75, 73, 1, 76, 1, 77, - 78, 77, 1, 78, 1, 1, 78, 79, - 80, 81, 82, 80, 1, 83, 84, 75, - 83, 1, 84, 74, 84, 1, 85, 86, - 86, 1, 1, 1, 1, 0 +static const unsigned char _json_indicies[] = { + 0, 2, 3, 4, 5, 6, 7, 8, + 0, 3, 1, 9, 1, 11, 12, 1, + 11, 10, 13, 14, 12, 13, 1, 14, + 1, 1, 14, 10, 15, 1, 16, 1, + 17, 1, 18, 1, 19, 1, 20, 1, + 21, 1, 22, 1, 23, 1, 24, 1, + 25, 26, 27, 25, 1, 28, 29, 30, + 28, 1, 31, 1, 32, 33, 32, 1, + 33, 1, 1, 33, 34, 35, 36, 37, + 35, 1, 38, 39, 30, 38, 1, 39, + 29, 39, 1, 40, 41, 42, 1, 41, + 42, 1, 44, 45, 45, 43, 46, 1, + 45, 45, 46, 43, 47, 47, 48, 1, + 48, 1, 48, 43, 44, 45, 45, 42, + 43, 50, 51, 49, 53, 54, 52, 55, + 55, 55, 55, 55, 55, 55, 55, 56, + 1, 57, 57, 57, 1, 58, 58, 58, + 1, 59, 59, 59, 1, 60, 60, 60, + 1, 62, 63, 61, 64, 65, 66, 1, + 67, 68, 1, 69, 70, 1, 71, 1, + 70, 71, 1, 72, 1, 69, 70, 68, + 1, 73, 1, 74, 1, 75, 1, 76, + 1, 77, 1, 78, 1, 79, 1, 80, + 1, 81, 1, 82, 1, 83, 1, 84, + 1, 85, 1, 86, 1, 87, 1, 88, + 1, 89, 1, 90, 1, 91, 1, 92, + 92, 93, 94, 1, 95, 1, 96, 1, + 97, 1, 98, 1, 99, 1, 100, 1, + 101, 1, 102, 102, 103, 101, 1, 104, + 105, 106, 107, 108, 109, 110, 105, 1, + 111, 1, 112, 113, 115, 116, 1, 115, + 114, 117, 118, 116, 117, 1, 118, 1, + 1, 118, 114, 119, 1, 120, 1, 121, + 1, 122, 1, 123, 124, 1, 125, 1, + 126, 1, 127, 128, 1, 129, 1, 130, + 1, 131, 132, 133, 134, 132, 1, 135, + 136, 137, 135, 1, 138, 1, 139, 140, + 139, 1, 140, 1, 1, 140, 141, 142, + 143, 144, 142, 1, 145, 146, 137, 145, + 1, 146, 136, 146, 1, 147, 148, 148, + 1, 149, 149, 1, 150, 150, 1, 151, + 151, 1, 152, 152, 1, 153, 153, 1, + 1, 1, 1, 1, 1, 0 }; static const char _json_trans_targs[] = { - 1, 0, 2, 3, 4, 56, 3, 4, - 56, 5, 5, 6, 7, 8, 9, 56, - 8, 9, 11, 12, 18, 57, 13, 15, - 14, 16, 17, 20, 58, 21, 20, 58, - 21, 19, 22, 23, 24, 25, 26, 20, - 58, 21, 28, 30, 31, 34, 39, 43, - 47, 29, 59, 59, 32, 31, 29, 32, - 33, 35, 36, 37, 38, 59, 40, 41, - 42, 59, 44, 45, 46, 59, 48, 49, - 55, 48, 49, 55, 50, 50, 51, 52, - 53, 54, 55, 53, 54, 59, 56 + 1, 0, 2, 106, 3, 6, 10, 13, + 16, 105, 4, 3, 105, 4, 5, 7, + 8, 9, 107, 11, 12, 108, 14, 15, + 109, 17, 18, 110, 17, 18, 110, 19, + 19, 20, 21, 22, 23, 110, 22, 23, + 25, 26, 32, 111, 27, 29, 28, 30, + 31, 34, 112, 35, 34, 112, 35, 33, + 36, 37, 38, 39, 40, 34, 112, 35, + 42, 43, 47, 43, 47, 44, 46, 45, + 113, 49, 50, 51, 52, 53, 54, 55, + 56, 57, 58, 59, 60, 61, 62, 63, + 64, 65, 66, 67, 68, 74, 73, 69, + 70, 71, 72, 73, 114, 75, 68, 73, + 77, 79, 80, 83, 88, 92, 96, 78, + 115, 115, 81, 80, 78, 81, 82, 84, + 85, 86, 87, 115, 89, 90, 91, 115, + 93, 94, 95, 115, 97, 98, 104, 97, + 98, 104, 99, 99, 100, 101, 102, 103, + 104, 102, 103, 115, 105, 105, 105, 105, + 105, 105 }; static const char _json_trans_actions[] = { - 0, 0, 0, 21, 77, 53, 0, 47, - 23, 17, 0, 0, 15, 19, 19, 50, - 0, 0, 0, 0, 0, 1, 0, 0, - 0, 0, 0, 3, 13, 0, 0, 35, - 5, 11, 0, 38, 7, 7, 7, 41, - 44, 9, 62, 56, 25, 0, 0, 0, - 31, 29, 33, 59, 15, 0, 27, 0, - 0, 0, 0, 0, 0, 68, 0, 0, - 0, 71, 0, 0, 0, 65, 21, 77, - 53, 0, 47, 23, 17, 0, 0, 15, - 19, 19, 50, 0, 0, 74, 0 + 0, 0, 84, 78, 33, 0, 0, 0, + 47, 39, 25, 0, 35, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 31, 96, 31, 0, 72, 0, 27, + 0, 0, 25, 29, 29, 29, 0, 0, + 0, 0, 0, 3, 0, 0, 0, 0, + 0, 5, 15, 0, 0, 51, 7, 13, + 0, 54, 9, 9, 9, 57, 60, 11, + 17, 17, 17, 0, 0, 0, 19, 0, + 21, 23, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 104, 63, 104, 0, + 0, 0, 0, 0, 69, 0, 66, 66, + 84, 78, 33, 0, 0, 0, 47, 39, + 49, 81, 25, 0, 35, 0, 0, 0, + 0, 0, 0, 90, 0, 0, 0, 93, + 0, 0, 0, 87, 31, 96, 31, 0, + 72, 0, 27, 0, 0, 25, 29, 29, + 29, 0, 0, 100, 0, 37, 43, 45, + 41, 75 +}; + +static const char _json_eof_actions[] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 1, 0, 0, 1, + 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 37, 43, 45, 41, 75, 0, + 0, 0, 0, 0 }; static const int json_start = 1; -static const int json_en_number_machine = 10; -static const int json_en_string_machine = 19; -static const int json_en_value_machine = 27; +static const int json_en_number_machine = 24; +static const int json_en_string_machine = 33; +static const int json_en_duration_machine = 41; +static const int json_en_timestamp_machine = 48; +static const int json_en_value_machine = 76; static const int json_en_main = 1; -#line 1313 "upb/json/parser.rl" +//#line 2150 "upb/json/parser.rl" size_t parse(void *closure, const void *hd, const char *buf, size_t size, const upb_bufhandle *handle) { @@ -13689,6 +14822,7 @@ size_t parse(void *closure, const void *hd, const char *buf, size_t size, const char *p = buf; const char *pe = buf + size; + const char *eof = &eof_ch; parser->handle = handle; @@ -13698,7 +14832,7 @@ size_t parse(void *closure, const void *hd, const char *buf, size_t size, capture_resume(parser, buf); -#line 1393 "upb/json/parser.c" +//#line 2290 "upb/json/parser.c" { int _klen; unsigned int _trans; @@ -13772,119 +14906,167 @@ _match: { switch ( *_acts++ ) { - case 0: -#line 1225 "upb/json/parser.rl" - { p--; {cs = stack[--top]; goto _again;} } - break; case 1: -#line 1226 "upb/json/parser.rl" - { p--; {stack[top++] = cs; cs = 10; goto _again;} } +//#line 2021 "upb/json/parser.rl" + { p--; {cs = stack[--top]; goto _again;} } break; case 2: -#line 1230 "upb/json/parser.rl" - { start_text(parser, p); } +//#line 2023 "upb/json/parser.rl" + { p--; {stack[top++] = cs; cs = 24; goto _again;} } break; case 3: -#line 1231 "upb/json/parser.rl" - { CHECK_RETURN_TOP(end_text(parser, p)); } +//#line 2027 "upb/json/parser.rl" + { start_text(parser, p); } break; case 4: -#line 1237 "upb/json/parser.rl" - { start_hex(parser); } +//#line 2028 "upb/json/parser.rl" + { CHECK_RETURN_TOP(end_text(parser, p)); } break; case 5: -#line 1238 "upb/json/parser.rl" - { hexdigit(parser, p); } +//#line 2034 "upb/json/parser.rl" + { start_hex(parser); } break; case 6: -#line 1239 "upb/json/parser.rl" - { CHECK_RETURN_TOP(end_hex(parser)); } +//#line 2035 "upb/json/parser.rl" + { hexdigit(parser, p); } break; case 7: -#line 1245 "upb/json/parser.rl" - { CHECK_RETURN_TOP(escape(parser, p)); } +//#line 2036 "upb/json/parser.rl" + { CHECK_RETURN_TOP(end_hex(parser)); } break; case 8: -#line 1251 "upb/json/parser.rl" - { p--; {cs = stack[--top]; goto _again;} } +//#line 2042 "upb/json/parser.rl" + { CHECK_RETURN_TOP(escape(parser, p)); } break; case 9: -#line 1254 "upb/json/parser.rl" - { {stack[top++] = cs; cs = 19; goto _again;} } +//#line 2048 "upb/json/parser.rl" + { p--; {cs = stack[--top]; goto _again;} } break; case 10: -#line 1256 "upb/json/parser.rl" - { p--; {stack[top++] = cs; cs = 27; goto _again;} } +//#line 2060 "upb/json/parser.rl" + { start_duration_base(parser, p); } break; case 11: -#line 1261 "upb/json/parser.rl" - { start_member(parser); } +//#line 2061 "upb/json/parser.rl" + { CHECK_RETURN_TOP(end_duration_base(parser, p)); } break; case 12: -#line 1262 "upb/json/parser.rl" - { CHECK_RETURN_TOP(end_membername(parser)); } +//#line 2063 "upb/json/parser.rl" + { p--; {cs = stack[--top]; goto _again;} } break; case 13: -#line 1265 "upb/json/parser.rl" - { end_member(parser); } +//#line 2068 "upb/json/parser.rl" + { start_timestamp_base(parser, p); } break; case 14: -#line 1271 "upb/json/parser.rl" - { start_object(parser); } +//#line 2069 "upb/json/parser.rl" + { CHECK_RETURN_TOP(end_timestamp_base(parser, p)); } break; case 15: -#line 1274 "upb/json/parser.rl" - { end_object(parser); } +//#line 2071 "upb/json/parser.rl" + { start_timestamp_fraction(parser, p); } break; case 16: -#line 1280 "upb/json/parser.rl" - { CHECK_RETURN_TOP(start_array(parser)); } +//#line 2072 "upb/json/parser.rl" + { CHECK_RETURN_TOP(end_timestamp_fraction(parser, p)); } break; case 17: -#line 1284 "upb/json/parser.rl" +//#line 2074 "upb/json/parser.rl" + { start_timestamp_zone(parser, p); } + break; + case 18: +//#line 2075 "upb/json/parser.rl" + { CHECK_RETURN_TOP(end_timestamp_zone(parser, p)); } + break; + case 19: +//#line 2077 "upb/json/parser.rl" + { p--; {cs = stack[--top]; goto _again;} } + break; + case 20: +//#line 2082 "upb/json/parser.rl" + { + if (is_wellknown_msg(parser, UPB_WELLKNOWN_TIMESTAMP)) { + {stack[top++] = cs; cs = 48; goto _again;} + } else if (is_wellknown_msg(parser, UPB_WELLKNOWN_DURATION)) { + {stack[top++] = cs; cs = 41; goto _again;} + } else { + {stack[top++] = cs; cs = 33; goto _again;} + } + } + break; + case 21: +//#line 2093 "upb/json/parser.rl" + { p--; {stack[top++] = cs; cs = 76; goto _again;} } + break; + case 22: +//#line 2098 "upb/json/parser.rl" + { start_member(parser); } + break; + case 23: +//#line 2099 "upb/json/parser.rl" + { CHECK_RETURN_TOP(end_membername(parser)); } + break; + case 24: +//#line 2102 "upb/json/parser.rl" + { end_member(parser); } + break; + case 25: +//#line 2108 "upb/json/parser.rl" + { start_object(parser); } + break; + case 26: +//#line 2111 "upb/json/parser.rl" + { end_object(parser); } + break; + case 27: +//#line 2117 "upb/json/parser.rl" + { CHECK_RETURN_TOP(start_array(parser)); } + break; + case 28: +//#line 2121 "upb/json/parser.rl" { end_array(parser); } break; - case 18: -#line 1289 "upb/json/parser.rl" - { start_number(parser, p); } + case 29: +//#line 2126 "upb/json/parser.rl" + { CHECK_RETURN_TOP(start_number(parser, p)); } break; - case 19: -#line 1290 "upb/json/parser.rl" + case 30: +//#line 2127 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_number(parser, p)); } break; - case 20: -#line 1292 "upb/json/parser.rl" + case 31: +//#line 2129 "upb/json/parser.rl" { CHECK_RETURN_TOP(start_stringval(parser)); } break; - case 21: -#line 1293 "upb/json/parser.rl" + case 32: +//#line 2130 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_stringval(parser)); } break; - case 22: -#line 1295 "upb/json/parser.rl" - { CHECK_RETURN_TOP(parser_putbool(parser, true)); } + case 33: +//#line 2132 "upb/json/parser.rl" + { CHECK_RETURN_TOP(end_bool(parser, true)); } break; - case 23: -#line 1297 "upb/json/parser.rl" - { CHECK_RETURN_TOP(parser_putbool(parser, false)); } + case 34: +//#line 2134 "upb/json/parser.rl" + { CHECK_RETURN_TOP(end_bool(parser, false)); } break; - case 24: -#line 1299 "upb/json/parser.rl" - { /* null value */ } + case 35: +//#line 2136 "upb/json/parser.rl" + { CHECK_RETURN_TOP(end_null(parser)); } break; - case 25: -#line 1301 "upb/json/parser.rl" - { CHECK_RETURN_TOP(start_subobject(parser)); } + case 36: +//#line 2138 "upb/json/parser.rl" + { CHECK_RETURN_TOP(start_subobject_full(parser)); } break; - case 26: -#line 1302 "upb/json/parser.rl" - { end_subobject(parser); } + case 37: +//#line 2139 "upb/json/parser.rl" + { end_subobject_full(parser); } break; - case 27: -#line 1307 "upb/json/parser.rl" + case 38: +//#line 2144 "upb/json/parser.rl" { p--; {cs = stack[--top]; goto _again;} } break; -#line 1579 "upb/json/parser.c" +//#line 2524 "upb/json/parser.c" } } @@ -13894,10 +15076,49 @@ _again: if ( ++p != pe ) goto _resume; _test_eof: {} + if ( p == eof ) + { + const char *__acts = _json_actions + _json_eof_actions[cs]; + unsigned int __nacts = (unsigned int) *__acts++; + while ( __nacts-- > 0 ) { + switch ( *__acts++ ) { + case 0: +//#line 2019 "upb/json/parser.rl" + { p--; {cs = stack[--top]; goto _again;} } + break; + case 26: +//#line 2111 "upb/json/parser.rl" + { end_object(parser); } + break; + case 30: +//#line 2127 "upb/json/parser.rl" + { CHECK_RETURN_TOP(end_number(parser, p)); } + break; + case 33: +//#line 2132 "upb/json/parser.rl" + { CHECK_RETURN_TOP(end_bool(parser, true)); } + break; + case 34: +//#line 2134 "upb/json/parser.rl" + { CHECK_RETURN_TOP(end_bool(parser, false)); } + break; + case 35: +//#line 2136 "upb/json/parser.rl" + { CHECK_RETURN_TOP(end_null(parser)); } + break; + case 37: +//#line 2139 "upb/json/parser.rl" + { end_subobject_full(parser); } + break; +//#line 2568 "upb/json/parser.c" + } + } + } + _out: {} } -#line 1334 "upb/json/parser.rl" +//#line 2172 "upb/json/parser.rl" if (p != pe) { upb_status_seterrf(&parser->status, "Parse error at '%.*s'\n", pe - p, p); @@ -13915,16 +15136,24 @@ error: } bool end(void *closure, const void *hd) { - UPB_UNUSED(closure); - UPB_UNUSED(hd); + upb_json_parser *parser = closure; /* Prevent compile warning on unused static constants. */ UPB_UNUSED(json_start); + UPB_UNUSED(json_en_duration_machine); UPB_UNUSED(json_en_number_machine); UPB_UNUSED(json_en_string_machine); + UPB_UNUSED(json_en_timestamp_machine); UPB_UNUSED(json_en_value_machine); UPB_UNUSED(json_en_main); - return true; + + parse(parser, hd, &eof_ch, 0, NULL); + + return parser->current_state >= +//#line 2608 "upb/json/parser.c" +105 +//#line 2202 "upb/json/parser.rl" +; } static void json_parser_reset(upb_json_parser *p) { @@ -13935,16 +15164,17 @@ static void json_parser_reset(upb_json_parser *p) { p->top->f = NULL; p->top->is_map = false; p->top->is_mapentry = false; + p->top->is_unknown_field = false; /* Emit Ragel initialization of the parser. */ -#line 1633 "upb/json/parser.c" +//#line 2626 "upb/json/parser.c" { cs = json_start; top = 0; } -#line 1374 "upb/json/parser.rl" +//#line 2217 "upb/json/parser.rl" p->current_state = cs; p->parser_top = top; accumulate_clear(p); @@ -14031,7 +15261,8 @@ static void add_jsonname_table(upb_json_parsermethod *m, const upb_msgdef* md) { upb_json_parser *upb_json_parser_create(upb_env *env, const upb_json_parsermethod *method, - upb_sink *output) { + upb_sink *output, + bool ignore_json_unknown) { #ifndef NDEBUG const size_t size_before = upb_env_bytesallocated(env); #endif @@ -14050,6 +15281,8 @@ upb_json_parser *upb_json_parser_create(upb_env *env, p->top->m = upb_handlers_msgdef(output->handlers); set_name_table(p, p->top); + p->ignore_json_unknown = ignore_json_unknown; + /* If this fails, uncomment and increase the value in parser.h. */ /* fprintf(stderr, "%zd\n", upb_env_bytesallocated(env) - size_before); */ UPB_ASSERT_DEBUGVAR(upb_env_bytesallocated(env) - size_before <= @@ -14094,6 +15327,7 @@ const upb_byteshandler *upb_json_parsermethod_inputhandler( #include #include +#include struct upb_json_printer { upb_sink input_; @@ -14114,6 +15348,12 @@ struct upb_json_printer { * repeated fields and messages (maps), and the worst case is a * message->repeated field->submessage->repeated field->... nesting. */ bool first_elem_[UPB_MAX_HANDLER_DEPTH * 2]; + + /* To print timestamp, printer needs to cache its seconds and nanos values + * and convert them when ending timestamp message. See comments of + * printer_sethandlers_timestamp for more detail. */ + int64_t seconds; + int32_t nanos; }; /* StringPiece; a pointer plus a length. */ @@ -14772,6 +16012,369 @@ void printer_sethandlers_mapentry(const void *closure, bool preserve_fieldnames, upb_handlerattr_uninit(&empty_attr); } +static bool putseconds(void *closure, const void *handler_data, + int64_t seconds) { + upb_json_printer *p = closure; + p->seconds = seconds; + UPB_UNUSED(handler_data); + return true; +} + +static bool putnanos(void *closure, const void *handler_data, + int32_t nanos) { + upb_json_printer *p = closure; + p->nanos = nanos; + UPB_UNUSED(handler_data); + return true; +} + +static void *scalar_startstr_nokey(void *closure, const void *handler_data, + size_t size_hint) { + upb_json_printer *p = closure; + UPB_UNUSED(handler_data); + UPB_UNUSED(size_hint); + print_data(p, "\"", 1); + return p; +} + +static size_t putstr_nokey(void *closure, const void *handler_data, + const char *str, size_t len, + const upb_bufhandle *handle) { + upb_json_printer *p = closure; + UPB_UNUSED(handler_data); + UPB_UNUSED(handle); + print_data(p, "\"", 1); + putstring(p, str, len); + print_data(p, "\"", 1); + return len + 2; +} + +static void *startseq_nokey(void *closure, const void *handler_data) { + upb_json_printer *p = closure; + UPB_UNUSED(handler_data); + p->depth_++; + p->first_elem_[p->depth_] = true; + print_data(p, "[", 1); + return closure; +} + +static void *startmap_nokey(void *closure, const void *handler_data) { + upb_json_printer *p = closure; + UPB_UNUSED(handler_data); + p->depth_++; + p->first_elem_[p->depth_] = true; + print_data(p, "{", 1); + return closure; +} + +static bool putnull(void *closure, const void *handler_data, + int32_t null) { + upb_json_printer *p = closure; + print_data(p, "null", 4); + UPB_UNUSED(handler_data); + UPB_UNUSED(null); + return true; +} + +static bool printer_startdurationmsg(void *closure, const void *handler_data) { + upb_json_printer *p = closure; + UPB_UNUSED(handler_data); + if (p->depth_ == 0) { + upb_bytessink_start(p->output_, 0, &p->subc_); + } + return true; +} + +#define UPB_DURATION_MAX_JSON_LEN 23 +#define UPB_DURATION_MAX_NANO_LEN 9 + +static bool printer_enddurationmsg(void *closure, const void *handler_data, + upb_status *s) { + upb_json_printer *p = closure; + char buffer[UPB_DURATION_MAX_JSON_LEN]; + size_t base_len; + size_t curr; + size_t i; + + memset(buffer, 0, UPB_DURATION_MAX_JSON_LEN); + + if (p->seconds < -315576000000) { + upb_status_seterrf(s, "error parsing duration: " + "minimum acceptable value is " + "-315576000000"); + return false; + } + + if (p->seconds > 315576000000) { + upb_status_seterrf(s, "error serializing duration: " + "maximum acceptable value is " + "315576000000"); + return false; + } + + _upb_snprintf(buffer, sizeof(buffer), "%ld", (long)p->seconds); + base_len = strlen(buffer); + + if (p->nanos != 0) { + char nanos_buffer[UPB_DURATION_MAX_NANO_LEN + 3]; + _upb_snprintf(nanos_buffer, sizeof(nanos_buffer), "%.9f", + p->nanos / 1000000000.0); + /* Remove trailing 0. */ + for (i = UPB_DURATION_MAX_NANO_LEN + 2; + nanos_buffer[i] == '0'; i--) { + nanos_buffer[i] = 0; + } + strcpy(buffer + base_len, nanos_buffer + 1); + } + + curr = strlen(buffer); + strcpy(buffer + curr, "s"); + + p->seconds = 0; + p->nanos = 0; + + print_data(p, "\"", 1); + print_data(p, buffer, strlen(buffer)); + print_data(p, "\"", 1); + + if (p->depth_ == 0) { + upb_bytessink_end(p->output_); + } + + UPB_UNUSED(handler_data); + return true; +} + +static bool printer_starttimestampmsg(void *closure, const void *handler_data) { + upb_json_printer *p = closure; + UPB_UNUSED(handler_data); + if (p->depth_ == 0) { + upb_bytessink_start(p->output_, 0, &p->subc_); + } + return true; +} + +#define UPB_TIMESTAMP_MAX_JSON_LEN 31 +#define UPB_TIMESTAMP_BEFORE_NANO_LEN 19 +#define UPB_TIMESTAMP_MAX_NANO_LEN 9 + +static bool printer_endtimestampmsg(void *closure, const void *handler_data, + upb_status *s) { + upb_json_printer *p = closure; + char buffer[UPB_TIMESTAMP_MAX_JSON_LEN]; + time_t time = p->seconds; + size_t curr; + size_t i; + size_t year_length = + strftime(buffer, UPB_TIMESTAMP_MAX_JSON_LEN, "%Y", gmtime(&time)); + + if (p->seconds < -62135596800) { + upb_status_seterrf(s, "error parsing timestamp: " + "minimum acceptable value is " + "0001-01-01T00:00:00Z"); + return false; + } + + if (p->seconds > 253402300799) { + upb_status_seterrf(s, "error parsing timestamp: " + "maximum acceptable value is " + "9999-12-31T23:59:59Z"); + return false; + } + + /* strftime doesn't guarantee 4 digits for year. Prepend 0 by ourselves. */ + for (i = 0; i < 4 - year_length; i++) { + buffer[i] = '0'; + } + + strftime(buffer + (4 - year_length), UPB_TIMESTAMP_MAX_JSON_LEN, + "%Y-%m-%dT%H:%M:%S", gmtime(&time)); + if (p->nanos != 0) { + char nanos_buffer[UPB_TIMESTAMP_MAX_NANO_LEN + 3]; + _upb_snprintf(nanos_buffer, sizeof(nanos_buffer), "%.9f", + p->nanos / 1000000000.0); + /* Remove trailing 0. */ + for (i = UPB_TIMESTAMP_MAX_NANO_LEN + 2; + nanos_buffer[i] == '0'; i--) { + nanos_buffer[i] = 0; + } + strcpy(buffer + UPB_TIMESTAMP_BEFORE_NANO_LEN, nanos_buffer + 1); + } + + curr = strlen(buffer); + strcpy(buffer + curr, "Z"); + + p->seconds = 0; + p->nanos = 0; + + print_data(p, "\"", 1); + print_data(p, buffer, strlen(buffer)); + print_data(p, "\"", 1); + + if (p->depth_ == 0) { + upb_bytessink_end(p->output_); + } + + UPB_UNUSED(handler_data); + UPB_UNUSED(s); + return true; +} + +static bool printer_startmsg_noframe(void *closure, const void *handler_data) { + upb_json_printer *p = closure; + UPB_UNUSED(handler_data); + if (p->depth_ == 0) { + upb_bytessink_start(p->output_, 0, &p->subc_); + } + return true; +} + +static bool printer_endmsg_noframe( + void *closure, const void *handler_data, upb_status *s) { + upb_json_printer *p = closure; + UPB_UNUSED(handler_data); + UPB_UNUSED(s); + if (p->depth_ == 0) { + upb_bytessink_end(p->output_); + } + return true; +} + +/* Set up handlers for a duration submessage. */ +void printer_sethandlers_duration(const void *closure, upb_handlers *h) { + const upb_msgdef *md = upb_handlers_msgdef(h); + + const upb_fielddef* seconds_field = + upb_msgdef_itof(md, UPB_DURATION_SECONDS); + const upb_fielddef* nanos_field = + upb_msgdef_itof(md, UPB_DURATION_NANOS); + + upb_handlerattr empty_attr = UPB_HANDLERATTR_INITIALIZER; + + upb_handlers_setstartmsg(h, printer_startdurationmsg, &empty_attr); + upb_handlers_setint64(h, seconds_field, putseconds, &empty_attr); + upb_handlers_setint32(h, nanos_field, putnanos, &empty_attr); + upb_handlers_setendmsg(h, printer_enddurationmsg, &empty_attr); + + UPB_UNUSED(closure); +} + +/* Set up handlers for a timestamp submessage. Instead of printing fields + * separately, the json representation of timestamp follows RFC 3339 */ +void printer_sethandlers_timestamp(const void *closure, upb_handlers *h) { + const upb_msgdef *md = upb_handlers_msgdef(h); + + const upb_fielddef* seconds_field = + upb_msgdef_itof(md, UPB_TIMESTAMP_SECONDS); + const upb_fielddef* nanos_field = + upb_msgdef_itof(md, UPB_TIMESTAMP_NANOS); + + upb_handlerattr empty_attr = UPB_HANDLERATTR_INITIALIZER; + + upb_handlers_setstartmsg(h, printer_starttimestampmsg, &empty_attr); + upb_handlers_setint64(h, seconds_field, putseconds, &empty_attr); + upb_handlers_setint32(h, nanos_field, putnanos, &empty_attr); + upb_handlers_setendmsg(h, printer_endtimestampmsg, &empty_attr); + + UPB_UNUSED(closure); +} + +void printer_sethandlers_value(const void *closure, upb_handlers *h) { + const upb_msgdef *md = upb_handlers_msgdef(h); + upb_msg_field_iter i; + + upb_handlerattr empty_attr = UPB_HANDLERATTR_INITIALIZER; + + upb_handlers_setstartmsg(h, printer_startmsg_noframe, &empty_attr); + upb_handlers_setendmsg(h, printer_endmsg_noframe, &empty_attr); + + upb_msg_field_begin(&i, md); + for(; !upb_msg_field_done(&i); upb_msg_field_next(&i)) { + const upb_fielddef *f = upb_msg_iter_field(&i); + + switch (upb_fielddef_type(f)) { + case UPB_TYPE_ENUM: + upb_handlers_setint32(h, f, putnull, &empty_attr); + break; + case UPB_TYPE_DOUBLE: + upb_handlers_setdouble(h, f, putdouble, &empty_attr); + break; + case UPB_TYPE_STRING: + upb_handlers_setstartstr(h, f, scalar_startstr_nokey, &empty_attr); + upb_handlers_setstring(h, f, scalar_str, &empty_attr); + upb_handlers_setendstr(h, f, scalar_endstr, &empty_attr); + break; + case UPB_TYPE_BOOL: + upb_handlers_setbool(h, f, putbool, &empty_attr); + break; + case UPB_TYPE_MESSAGE: + break; + default: + UPB_ASSERT(false); + break; + } + } + + UPB_UNUSED(closure); +} + +#define WRAPPER_SETHANDLERS(wrapper, type, putmethod) \ +void printer_sethandlers_##wrapper(const void *closure, upb_handlers *h) { \ + const upb_msgdef *md = upb_handlers_msgdef(h); \ + const upb_fielddef* f = upb_msgdef_itof(md, 1); \ + upb_handlerattr empty_attr = UPB_HANDLERATTR_INITIALIZER; \ + upb_handlers_setstartmsg(h, printer_startmsg_noframe, &empty_attr); \ + upb_handlers_setendmsg(h, printer_endmsg_noframe, &empty_attr); \ + upb_handlers_set##type(h, f, putmethod, &empty_attr); \ + UPB_UNUSED(closure); \ +} + +WRAPPER_SETHANDLERS(doublevalue, double, putdouble) +WRAPPER_SETHANDLERS(floatvalue, float, putfloat) +WRAPPER_SETHANDLERS(int64value, int64, putint64_t) +WRAPPER_SETHANDLERS(uint64value, uint64, putuint64_t) +WRAPPER_SETHANDLERS(int32value, int32, putint32_t) +WRAPPER_SETHANDLERS(uint32value, uint32, putuint32_t) +WRAPPER_SETHANDLERS(boolvalue, bool, putbool) +WRAPPER_SETHANDLERS(stringvalue, string, putstr_nokey) +WRAPPER_SETHANDLERS(bytesvalue, string, putbytes) + +#undef WRAPPER_SETHANDLERS + +void printer_sethandlers_listvalue(const void *closure, upb_handlers *h) { + const upb_msgdef *md = upb_handlers_msgdef(h); + const upb_fielddef* f = upb_msgdef_itof(md, 1); + + upb_handlerattr empty_attr = UPB_HANDLERATTR_INITIALIZER; + + upb_handlers_setstartseq(h, f, startseq_nokey, &empty_attr); + upb_handlers_setendseq(h, f, endseq, &empty_attr); + + upb_handlers_setstartmsg(h, printer_startmsg_noframe, &empty_attr); + upb_handlers_setendmsg(h, printer_endmsg_noframe, &empty_attr); + + upb_handlers_setstartsubmsg(h, f, repeated_startsubmsg, &empty_attr); + + UPB_UNUSED(closure); +} + +void printer_sethandlers_structvalue(const void *closure, upb_handlers *h) { + const upb_msgdef *md = upb_handlers_msgdef(h); + const upb_fielddef* f = upb_msgdef_itof(md, 1); + + upb_handlerattr empty_attr = UPB_HANDLERATTR_INITIALIZER; + + upb_handlers_setstartseq(h, f, startmap_nokey, &empty_attr); + upb_handlers_setendseq(h, f, endmap, &empty_attr); + + upb_handlers_setstartmsg(h, printer_startmsg_noframe, &empty_attr); + upb_handlers_setendmsg(h, printer_endmsg_noframe, &empty_attr); + + upb_handlers_setstartsubmsg(h, f, repeated_startsubmsg, &empty_attr); + + UPB_UNUSED(closure); +} + void printer_sethandlers(const void *closure, upb_handlers *h) { const upb_msgdef *md = upb_handlers_msgdef(h); bool is_mapentry = upb_msgdef_mapentry(md); @@ -14787,6 +16390,42 @@ void printer_sethandlers(const void *closure, upb_handlers *h) { return; } + switch (upb_msgdef_wellknowntype(md)) { + case UPB_WELLKNOWN_UNSPECIFIED: + break; + case UPB_WELLKNOWN_DURATION: + printer_sethandlers_duration(closure, h); + return; + case UPB_WELLKNOWN_TIMESTAMP: + printer_sethandlers_timestamp(closure, h); + return; + case UPB_WELLKNOWN_VALUE: + printer_sethandlers_value(closure, h); + return; + case UPB_WELLKNOWN_LISTVALUE: + printer_sethandlers_listvalue(closure, h); + return; + case UPB_WELLKNOWN_STRUCT: + printer_sethandlers_structvalue(closure, h); + return; +#define WRAPPER(wellknowntype, name) \ + case wellknowntype: \ + printer_sethandlers_##name(closure, h); \ + return; \ + + WRAPPER(UPB_WELLKNOWN_DOUBLEVALUE, doublevalue); + WRAPPER(UPB_WELLKNOWN_FLOATVALUE, floatvalue); + WRAPPER(UPB_WELLKNOWN_INT64VALUE, int64value); + WRAPPER(UPB_WELLKNOWN_UINT64VALUE, uint64value); + WRAPPER(UPB_WELLKNOWN_INT32VALUE, int32value); + WRAPPER(UPB_WELLKNOWN_UINT32VALUE, uint32value); + WRAPPER(UPB_WELLKNOWN_BOOLVALUE, boolvalue); + WRAPPER(UPB_WELLKNOWN_STRINGVALUE, stringvalue); + WRAPPER(UPB_WELLKNOWN_BYTESVALUE, bytesvalue); + +#undef WRAPPER + } + upb_handlers_setstartmsg(h, printer_startmsg, &empty_attr); upb_handlers_setendmsg(h, printer_endmsg, &empty_attr); @@ -14894,6 +16533,8 @@ upb_json_printer *upb_json_printer_create(upb_env *e, const upb_handlers *h, p->output_ = output; json_printer_reset(p); upb_sink_reset(&p->input_, h, p); + p->seconds = 0; + p->nanos = 0; /* If this fails, increase the value in printer.h. */ UPB_ASSERT_DEBUGVAR(upb_env_bytesallocated(e) - size_before <= @@ -14911,3 +16552,8 @@ const upb_handlers *upb_json_printer_newhandlers(const upb_msgdef *md, return upb_handlers_newfrozen( md, owner, printer_sethandlers, &preserve_fieldnames); } + +#undef UPB_SIZE +#undef UPB_FIELD_AT +#undef UPB_READ_ONEOF +#undef UPB_WRITE_ONEOF diff --git a/ruby/ext/google/protobuf_c/upb.h b/ruby/ext/google/protobuf_c/upb.h index f441c89c83..0670a8123c 100644 --- a/ruby/ext/google/protobuf_c/upb.h +++ b/ruby/ext/google/protobuf_c/upb.h @@ -1,4 +1,116 @@ // Amalgamated source file + +// php.h intentionally defined NDEBUG. We have to define this macro in order to +// be used together with php.h +#ifndef NDEBUG +#define NDEBUG +#endif + +#if UINTPTR_MAX == 0xffffffff +#define UPB_SIZE(size32, size64) size32 +#else +#define UPB_SIZE(size32, size64) size64 +#endif + +#define UPB_FIELD_AT(msg, fieldtype, offset) \ + *(fieldtype*)((const char*)(msg) + offset) + +#define UPB_READ_ONEOF(msg, fieldtype, offset, case_offset, case_val, default) \ + UPB_FIELD_AT(msg, int, case_offset) == case_val \ + ? UPB_FIELD_AT(msg, fieldtype, offset) \ + : default + +#define UPB_WRITE_ONEOF(msg, fieldtype, offset, value, case_offset, case_val) \ + UPB_FIELD_AT(msg, int, case_offset) = case_val; \ + UPB_FIELD_AT(msg, fieldtype, offset) = value; +/* +** upb::Message is a representation for protobuf messages. +** +** However it differs from other common representations like +** google::protobuf::Message in one key way: it does not prescribe any +** ownership between messages and submessages, and it relies on the +** client to ensure that each submessage/array/map outlives its parent. +** +** All messages, arrays, and maps live in an Arena. If the entire message +** tree is in the same arena, ensuring proper lifetimes is simple. However +** the client can mix arenas as long as they ensure that there are no +** dangling pointers. +** +** A client can access a upb::Message without knowing anything about +** ownership semantics, but to create or mutate a message a user needs +** to implement the memory management themselves. +** +** TODO: UTF-8 checking? +**/ + +#ifndef UPB_MSG_H_ +#define UPB_MSG_H_ + +/* +** Defs are upb's internal representation of the constructs that can appear +** in a .proto file: +** +** - upb::MessageDef (upb_msgdef): describes a "message" construct. +** - upb::FieldDef (upb_fielddef): describes a message field. +** - upb::FileDef (upb_filedef): describes a .proto file and its defs. +** - upb::EnumDef (upb_enumdef): describes an enum. +** - upb::OneofDef (upb_oneofdef): describes a oneof. +** - upb::Def (upb_def): base class of all the others. +** +** TODO: definitions of services. +** +** Like upb_refcounted objects, defs are mutable only until frozen, and are +** only thread-safe once frozen. +** +** This is a mixed C/C++ interface that offers a full API to both languages. +** See the top-level README for more information. +*/ + +#ifndef UPB_DEF_H_ +#define UPB_DEF_H_ + +/* +** upb::RefCounted (upb_refcounted) +** +** A refcounting scheme that supports circular refs. It accomplishes this by +** partitioning the set of objects into groups such that no cycle spans groups; +** we can then reference-count the group as a whole and ignore refs within the +** group. When objects are mutable, these groups are computed very +** conservatively; we group any objects that have ever had a link between them. +** When objects are frozen, we compute strongly-connected components which +** allows us to be precise and only group objects that are actually cyclic. +** +** This is a mixed C/C++ interface that offers a full API to both languages. +** See the top-level README for more information. +*/ + +#ifndef UPB_REFCOUNTED_H_ +#define UPB_REFCOUNTED_H_ + +/* +** upb_table +** +** This header is INTERNAL-ONLY! Its interfaces are not public or stable! +** This file defines very fast int->upb_value (inttable) and string->upb_value +** (strtable) hash tables. +** +** The table uses chained scatter with Brent's variation (inspired by the Lua +** implementation of hash tables). The hash function for strings is Austin +** Appleby's "MurmurHash." +** +** The inttable uses uintptr_t as its key, which guarantees it can be used to +** store pointers or integers of at least 32 bits (upb isn't really useful on +** systems where sizeof(void*) < 4). +** +** The table must be homogenous (all values of the same type). In debug +** mode, we check this on insert and lookup. +*/ + +#ifndef UPB_TABLE_H_ +#define UPB_TABLE_H_ + +#include +#include /* ** This file contains shared definitions that are widely used across upb. ** @@ -737,106 +849,6 @@ template class upb::InlinedEnvironment : public upb::Environment { #endif /* UPB_H_ */ -/* -** upb_decode: parsing into a upb_msg using a upb_msglayout. -*/ - -#ifndef UPB_DECODE_H_ -#define UPB_DECODE_H_ - -/* -** upb::Message is a representation for protobuf messages. -** -** However it differs from other common representations like -** google::protobuf::Message in one key way: it does not prescribe any -** ownership between messages and submessages, and it relies on the -** client to delete each message/submessage/array/map at the appropriate -** time. -** -** A client can access a upb::Message without knowing anything about -** ownership semantics, but to create or mutate a message a user needs -** to implement the memory management themselves. -** -** Currently all messages, arrays, and maps store a upb_alloc* internally. -** Mutating operations use this when they require dynamically-allocated -** memory. We could potentially eliminate this size overhead later by -** letting the user flip a bit on the factory that prevents this from -** being stored. The user would then need to use separate functions where -** the upb_alloc* is passed explicitly. However for handlers to populate -** such structures, they would need a place to store this upb_alloc* during -** parsing; upb_handlers don't currently have a good way to accommodate this. -** -** TODO: UTF-8 checking? -**/ - -#ifndef UPB_MSG_H_ -#define UPB_MSG_H_ - -/* -** Defs are upb's internal representation of the constructs that can appear -** in a .proto file: -** -** - upb::MessageDef (upb_msgdef): describes a "message" construct. -** - upb::FieldDef (upb_fielddef): describes a message field. -** - upb::FileDef (upb_filedef): describes a .proto file and its defs. -** - upb::EnumDef (upb_enumdef): describes an enum. -** - upb::OneofDef (upb_oneofdef): describes a oneof. -** - upb::Def (upb_def): base class of all the others. -** -** TODO: definitions of services. -** -** Like upb_refcounted objects, defs are mutable only until frozen, and are -** only thread-safe once frozen. -** -** This is a mixed C/C++ interface that offers a full API to both languages. -** See the top-level README for more information. -*/ - -#ifndef UPB_DEF_H_ -#define UPB_DEF_H_ - -/* -** upb::RefCounted (upb_refcounted) -** -** A refcounting scheme that supports circular refs. It accomplishes this by -** partitioning the set of objects into groups such that no cycle spans groups; -** we can then reference-count the group as a whole and ignore refs within the -** group. When objects are mutable, these groups are computed very -** conservatively; we group any objects that have ever had a link between them. -** When objects are frozen, we compute strongly-connected components which -** allows us to be precise and only group objects that are actually cyclic. -** -** This is a mixed C/C++ interface that offers a full API to both languages. -** See the top-level README for more information. -*/ - -#ifndef UPB_REFCOUNTED_H_ -#define UPB_REFCOUNTED_H_ - -/* -** upb_table -** -** This header is INTERNAL-ONLY! Its interfaces are not public or stable! -** This file defines very fast int->upb_value (inttable) and string->upb_value -** (strtable) hash tables. -** -** The table uses chained scatter with Brent's variation (inspired by the Lua -** implementation of hash tables). The hash function for strings is Austin -** Appleby's "MurmurHash." -** -** The inttable uses uintptr_t as its key, which guarantees it can be used to -** store pointers or integers of at least 32 bits (upb isn't really useful on -** systems where sizeof(void*) < 4). -** -** The table must be homogenous (all values of the same type). In debug -** mode, we check this on insert and lookup. -*/ - -#ifndef UPB_TABLE_H_ -#define UPB_TABLE_H_ - -#include -#include #ifdef __cplusplus extern "C" { @@ -1995,6 +2007,34 @@ typedef enum { UPB_SYNTAX_PROTO3 = 3 } upb_syntax_t; +/* All the different kind of well known type messages. For simplicity of check, + * number wrappers and string wrappers are grouped together. Make sure the + * order and merber of these groups are not changed. + */ +typedef enum { + UPB_WELLKNOWN_UNSPECIFIED, + UPB_WELLKNOWN_DURATION, + UPB_WELLKNOWN_TIMESTAMP, + /* number wrappers */ + UPB_WELLKNOWN_DOUBLEVALUE, + UPB_WELLKNOWN_FLOATVALUE, + UPB_WELLKNOWN_INT64VALUE, + UPB_WELLKNOWN_UINT64VALUE, + UPB_WELLKNOWN_INT32VALUE, + UPB_WELLKNOWN_UINT32VALUE, + /* string wrappers */ + UPB_WELLKNOWN_STRINGVALUE, + UPB_WELLKNOWN_BYTESVALUE, + UPB_WELLKNOWN_BOOLVALUE, + UPB_WELLKNOWN_VALUE, + UPB_WELLKNOWN_LISTVALUE, + UPB_WELLKNOWN_STRUCT +} upb_wellknowntype_t; + + +/* Maps descriptor type -> upb field type. */ +extern const uint8_t upb_desctype_to_fieldtype[]; + /* Maximum field number allowed for FieldDefs. This is an inherent limit of the * protobuf wire format. */ #define UPB_MAX_FIELDNUMBER ((1 << 29) - 1) @@ -2376,6 +2416,14 @@ typedef upb_strtable_iter upb_msg_oneof_iter; #define UPB_MAPENTRY_KEY 1 #define UPB_MAPENTRY_VALUE 2 +/* Well-known field tag numbers for timestamp messages. */ +#define UPB_DURATION_SECONDS 1 +#define UPB_DURATION_NANOS 2 + +/* Well-known field tag numbers for duration messages. */ +#define UPB_TIMESTAMP_SECONDS 1 +#define UPB_TIMESTAMP_NANOS 2 + #ifdef __cplusplus /* Structure that describes a single .proto message type. @@ -2490,6 +2538,13 @@ class upb::MessageDef { void setmapentry(bool map_entry); bool mapentry() const; + /* Return the type of well known type message. UPB_WELLKNOWN_UNSPECIFIED for + * non-well-known message. */ + upb_wellknowntype_t wellknowntype() const; + + /* Whether is a number wrapper. */ + bool isnumberwrapper() const; + /* Iteration over fields. The order is undefined. */ class field_iterator : public std::iterator { @@ -2631,6 +2686,8 @@ bool upb_msgdef_addoneof(upb_msgdef *m, upb_oneofdef *o, const void *ref_donor, bool upb_msgdef_setfullname(upb_msgdef *m, const char *fullname, upb_status *s); void upb_msgdef_setmapentry(upb_msgdef *m, bool map_entry); bool upb_msgdef_mapentry(const upb_msgdef *m); +upb_wellknowntype_t upb_msgdef_wellknowntype(const upb_msgdef *m); +bool upb_msgdef_isnumberwrapper(const upb_msgdef *m); bool upb_msgdef_setsyntax(upb_msgdef *m, upb_syntax_t syntax); /* Field lookup in a couple of different variations: @@ -3570,6 +3627,12 @@ inline void MessageDef::setmapentry(bool map_entry) { inline bool MessageDef::mapentry() const { return upb_msgdef_mapentry(this); } +inline upb_wellknowntype_t MessageDef::wellknowntype() const { + return upb_msgdef_wellknowntype(this); +} +inline bool MessageDef::isnumberwrapper() const { + return upb_msgdef_isnumberwrapper(this); +} inline MessageDef::field_iterator MessageDef::field_begin() { return field_iterator(this); } @@ -4697,6 +4760,34 @@ UPB_INLINE upb_selector_t upb_handlers_getendselector(upb_selector_t start) { uint32_t upb_handlers_selectorbaseoffset(const upb_fielddef *f); uint32_t upb_handlers_selectorcount(const upb_fielddef *f); + +/** Message handlers ******************************************************************/ + +/* These are the handlers used internally by upb_msgfactory_getmergehandlers(). + * They write scalar data to a known offset from the message pointer. + * + * These would be trivial for anyone to implement themselves, but it's better + * to use these because some JITs will recognize and specialize these instead + * of actually calling the function. */ + +/* Sets a handler for the given primitive field that will write the data at the + * given offset. If hasbit > 0, also sets a hasbit at the given bit offset + * (addressing each byte low to high). */ +bool upb_msg_setscalarhandler(upb_handlers *h, + const upb_fielddef *f, + size_t offset, + int32_t hasbit); + +/* If the given handler is a msghandlers_primitive field, returns true and sets + * *type, *offset and *hasbit. Otherwise returns false. */ +bool upb_msg_getscalarhandlerdata(const upb_handlers *h, + upb_selector_t s, + upb_fieldtype_t *type, + size_t *offset, + int32_t *hasbit); + + + UPB_END_EXTERN_C /* @@ -6381,21 +6472,14 @@ namespace upb { class Array; class Map; class MapIterator; -class MessageFactory; class MessageLayout; -class Visitor; -class VisitorPlan; } #endif -UPB_DECLARE_TYPE(upb::MessageFactory, upb_msgfactory) -UPB_DECLARE_TYPE(upb::MessageLayout, upb_msglayout) UPB_DECLARE_TYPE(upb::Array, upb_array) UPB_DECLARE_TYPE(upb::Map, upb_map) UPB_DECLARE_TYPE(upb::MapIterator, upb_mapiter) -UPB_DECLARE_TYPE(upb::Visitor, upb_visitor) -UPB_DECLARE_TYPE(upb::VisitorPlan, upb_visitorplan) /* TODO(haberman): C++ accessors */ @@ -6406,73 +6490,48 @@ typedef void upb_msg; /** upb_msglayout *************************************************************/ -/* upb_msglayout represents the memory layout of a given upb_msgdef. You get - * instances of this from a upb_msgfactory, and the factory always owns the - * msglayout. */ +/* upb_msglayout represents the memory layout of a given upb_msgdef. The + * members are public so generated code can initialize them, but users MUST NOT + * read or write any of its members. */ +typedef struct { + uint32_t number; + uint16_t offset; + int16_t presence; /* If >0, hasbit_index+1. If <0, oneof_index+1. */ + uint16_t submsg_index; /* undefined if descriptortype != MESSAGE or GROUP. */ + uint8_t descriptortype; + uint8_t label; +} upb_msglayout_field; -/** upb_visitor ***************************************************************/ +typedef struct upb_msglayout { + const struct upb_msglayout *const* submsgs; + const upb_msglayout_field *fields; + /* Must be aligned to sizeof(void*). Doesn't include internal members like + * unknown fields, extension dict, pointer to msglayout, etc. */ + uint16_t size; + uint16_t field_count; + bool extendable; +} upb_msglayout; -/* upb_visitor will visit all the fields of a message and its submessages. It - * uses a upb_visitorplan which you can obtain from a upb_msgfactory. */ -upb_visitor *upb_visitor_create(upb_env *e, const upb_visitorplan *vp, - upb_sink *output); -bool upb_visitor_visitmsg(upb_visitor *v, const upb_msg *msg); +/** upb_stringview ************************************************************/ +typedef struct { + const char *data; + size_t size; +} upb_stringview; -/** upb_msgfactory ************************************************************/ +UPB_INLINE upb_stringview upb_stringview_make(const char *data, size_t size) { + upb_stringview ret; + ret.data = data; + ret.size = size; + return ret; +} -/* A upb_msgfactory contains a cache of upb_msglayout, upb_handlers, and - * upb_visitorplan objects. These are the objects necessary to represent, - * populate, and and visit upb_msg objects. - * - * These caches are all populated by upb_msgdef, and lazily created on demand. - */ +#define UPB_STRINGVIEW_INIT(ptr, len) {ptr, len} -/* Creates and destroys a msgfactory, respectively. The messages for this - * msgfactory must come from |symtab| (which should outlive the msgfactory). */ -upb_msgfactory *upb_msgfactory_new(const upb_symtab *symtab); -void upb_msgfactory_free(upb_msgfactory *f); -const upb_symtab *upb_msgfactory_symtab(const upb_msgfactory *f); - -/* The functions to get cached objects, lazily creating them on demand. These - * all require: - * - * - m is in upb_msgfactory_symtab(f) - * - upb_msgdef_mapentry(m) == false (since map messages can't have layouts). - * - * The returned objects will live for as long as the msgfactory does. - * - * TODO(haberman): consider making this thread-safe and take a const - * upb_msgfactory. */ -const upb_msglayout *upb_msgfactory_getlayout(upb_msgfactory *f, - const upb_msgdef *m); -const upb_handlers *upb_msgfactory_getmergehandlers(upb_msgfactory *f, - const upb_msgdef *m); -const upb_visitorplan *upb_msgfactory_getvisitorplan(upb_msgfactory *f, - const upb_handlers *h); - - -/** upb_stringview ************************************************************/ - -typedef struct { - const char *data; - size_t size; -} upb_stringview; - -UPB_INLINE upb_stringview upb_stringview_make(const char *data, size_t size) { - upb_stringview ret; - ret.data = data; - ret.size = size; - return ret; -} - -#define UPB_STRINGVIEW_INIT(ptr, len) {ptr, len} - - -/** upb_msgval ****************************************************************/ +/** upb_msgval ****************************************************************/ /* A union representing all possible protobuf values. Used for generic get/set * operations. */ @@ -6528,52 +6587,16 @@ UPB_INLINE upb_msgval upb_msgval_makestr(const char *data, size_t size) { /** upb_msg *******************************************************************/ /* A upb_msg represents a protobuf message. It always corresponds to a specific - * upb_msglayout, which describes how it is laid out in memory. - * - * The message will have a fixed size, as returned by upb_msg_sizeof(), which - * will be used to store fixed-length fields. The upb_msg may also allocate - * dynamic memory internally to store data such as: - * - * - extensions - * - unknown fields - */ + * upb_msglayout, which describes how it is laid out in memory. */ -/* Returns the size of a message given this layout. */ -size_t upb_msg_sizeof(const upb_msglayout *l); +/* Creates a new message of the given type/layout in this arena. */ +upb_msg *upb_msg_new(const upb_msglayout *l, upb_arena *a); -/* upb_msg_init() / upb_msg_uninit() allow the user to use a pre-allocated - * block of memory as a message. The block's size should be upb_msg_sizeof(). - * upb_msg_uninit() must be called to release internally-allocated memory - * unless the allocator is an arena that does not require freeing. - * - * Please note that upb_msg_init() may return a value that is different than - * |msg|, so you must assign the return value and not cast your memory block - * to upb_msg* directly! - * - * Please note that upb_msg_uninit() does *not* free any submessages, maps, - * or arrays referred to by this message's fields. You must free them manually - * yourself. - * - * upb_msg_uninit returns the original memory block, which may be useful if - * you dynamically allocated it (though upb_msg_new() would normally be more - * appropriate in this case). */ -upb_msg *upb_msg_init(void *msg, const upb_msglayout *l, upb_alloc *a); -void *upb_msg_uninit(upb_msg *msg, const upb_msglayout *l); - -/* Like upb_msg_init() / upb_msg_uninit(), except the message's memory is - * allocated / freed from the given upb_alloc. */ -upb_msg *upb_msg_new(const upb_msglayout *l, upb_alloc *a); -void upb_msg_free(upb_msg *msg, const upb_msglayout *l); - -/* Returns the upb_alloc for the given message. - * TODO(haberman): get rid of this? Not sure we want to be storing this - * for every message. */ -upb_alloc *upb_msg_alloc(const upb_msg *msg); - -/* Packs the tree of messages rooted at "msg" into a single hunk of memory, - * allocated from the given allocator. */ -void *upb_msg_pack(const upb_msg *msg, const upb_msglayout *l, - void *p, size_t *ofs, size_t size); +/* Returns the arena for the given message. */ +upb_arena *upb_msg_arena(const upb_msg *msg); + +void upb_msg_addunknown(upb_msg *msg, const char *data, size_t len); +const char *upb_msg_getunknown(const upb_msg *msg, size_t *len); /* Read-only message API. Can be safely called by anyone. */ @@ -6627,16 +6650,12 @@ bool upb_msg_clearfield(upb_msg *msg, * semantics are the same as upb_msg. A upb_array allocates dynamic * memory internally for the array elements. */ -size_t upb_array_sizeof(upb_fieldtype_t type); -void upb_array_init(upb_array *arr, upb_fieldtype_t type, upb_alloc *a); -void upb_array_uninit(upb_array *arr); -upb_array *upb_array_new(upb_fieldtype_t type, upb_alloc *a); -void upb_array_free(upb_array *arr); +upb_array *upb_array_new(upb_fieldtype_t type, upb_arena *a); +upb_fieldtype_t upb_array_type(const upb_array *arr); /* Read-only interface. Safe for anyone to call. */ size_t upb_array_size(const upb_array *arr); -upb_fieldtype_t upb_array_type(const upb_array *arr); upb_msgval upb_array_get(const upb_array *arr, size_t i); /* Write interface. May only be called by the message's owner who can enforce @@ -6653,12 +6672,8 @@ bool upb_array_set(upb_array *arr, size_t i, upb_msgval val); * So you must ensure that any string or message values outlive the map, and you * must delete them manually when they are no longer required. */ -size_t upb_map_sizeof(upb_fieldtype_t ktype, upb_fieldtype_t vtype); -bool upb_map_init(upb_map *map, upb_fieldtype_t ktype, upb_fieldtype_t vtype, - upb_alloc *a); -void upb_map_uninit(upb_map *map); -upb_map *upb_map_new(upb_fieldtype_t ktype, upb_fieldtype_t vtype, upb_alloc *a); -void upb_map_free(upb_map *map); +upb_map *upb_map_new(upb_fieldtype_t ktype, upb_fieldtype_t vtype, + upb_arena *a); /* Read-only interface. Safe for anyone to call. */ @@ -6702,90 +6717,869 @@ upb_msgval upb_mapiter_value(const upb_mapiter *i); void upb_mapiter_setdone(upb_mapiter *i); bool upb_mapiter_isequal(const upb_mapiter *i1, const upb_mapiter *i2); +UPB_END_EXTERN_C -/** Handlers ******************************************************************/ - -/* These are the handlers used internally by upb_msgfactory_getmergehandlers(). - * They write scalar data to a known offset from the message pointer. +#endif /* UPB_MSG_H_ */ +/* This file was generated by upbc (the upb compiler) from the input + * file: * - * These would be trivial for anyone to implement themselves, but it's better - * to use these because some JITs will recognize and specialize these instead - * of actually calling the function. */ + * google/protobuf/descriptor.proto + * + * Do not edit -- your changes will be discarded when the file is + * regenerated. */ -/* Sets a handler for the given primitive field that will write the data at the - * given offset. If hasbit > 0, also sets a hasbit at the given bit offset - * (addressing each byte low to high). */ -bool upb_msg_setscalarhandler(upb_handlers *h, - const upb_fielddef *f, - size_t offset, - int32_t hasbit); +#ifndef GOOGLE_PROTOBUF_DESCRIPTOR_PROTO_UPB_H_ +#define GOOGLE_PROTOBUF_DESCRIPTOR_PROTO_UPB_H_ -/* If the given handler is a msghandlers_primitive field, returns true and sets - * *type, *offset and *hasbit. Otherwise returns false. */ -bool upb_msg_getscalarhandlerdata(const upb_handlers *h, - upb_selector_t s, - upb_fieldtype_t *type, - size_t *offset, - int32_t *hasbit); +/* +** upb_decode: parsing into a upb_msg using a upb_msglayout. +*/ -/** Interfaces for generated code *********************************************/ +#ifndef UPB_DECODE_H_ +#define UPB_DECODE_H_ -#define UPB_NOT_IN_ONEOF UINT16_MAX -#define UPB_NO_HASBIT UINT16_MAX -#define UPB_NO_SUBMSG UINT16_MAX -typedef struct { - uint32_t number; - uint32_t offset; /* If in a oneof, offset of default in default_msg below. */ - uint16_t hasbit; /* UPB_NO_HASBIT if no hasbit. */ - uint16_t oneof_index; /* UPB_NOT_IN_ONEOF if not in a oneof. */ - uint16_t submsg_index; /* UPB_NO_SUBMSG if no submsg. */ - uint8_t type; - uint8_t label; -} upb_msglayout_fieldinit_v1; +UPB_BEGIN_EXTERN_C -typedef struct { - uint32_t data_offset; - uint32_t case_offset; -} upb_msglayout_oneofinit_v1; - -typedef struct upb_msglayout_msginit_v1 { - const struct upb_msglayout_msginit_v1 *const* submsgs; - const upb_msglayout_fieldinit_v1 *fields; - const upb_msglayout_oneofinit_v1 *oneofs; - void *default_msg; - /* Must be aligned to sizeof(void*). Doesn't include internal members like - * unknown fields, extension dict, pointer to msglayout, etc. */ - uint32_t size; - uint16_t field_count; - uint16_t oneof_count; - bool extendable; - bool is_proto2; -} upb_msglayout_msginit_v1; +bool upb_decode(upb_stringview buf, upb_msg *msg, const upb_msglayout *l); -#define UPB_ALIGN_UP_TO(val, align) ((val + (align - 1)) & -align) -#define UPB_ALIGNED_SIZEOF(type) UPB_ALIGN_UP_TO(sizeof(type), sizeof(void*)) +UPB_END_EXTERN_C -/* Initialize/uninitialize a msglayout from a msginit. If upb uses v1 - * internally, this will not allocate any memory. Should only be used by - * generated code. */ -upb_msglayout *upb_msglayout_frominit_v1( - const upb_msglayout_msginit_v1 *init, upb_alloc *a); -void upb_msglayout_uninit_v1(upb_msglayout *layout, upb_alloc *a); +#endif /* UPB_DECODE_H_ */ +/* +** upb_encode: parsing into a upb_msg using a upb_msglayout. +*/ -UPB_END_EXTERN_C +#ifndef UPB_ENCODE_H_ +#define UPB_ENCODE_H_ -#endif /* UPB_MSG_H_ */ UPB_BEGIN_EXTERN_C -bool upb_decode(upb_stringview buf, void *msg, - const upb_msglayout_msginit_v1 *l, upb_env *env); +char *upb_encode(const void *msg, const upb_msglayout *l, upb_arena *arena, + size_t *size); UPB_END_EXTERN_C -#endif /* UPB_DECODE_H_ */ +#endif /* UPB_ENCODE_H_ */ +UPB_BEGIN_EXTERN_C + +struct google_protobuf_FileDescriptorSet; +struct google_protobuf_FileDescriptorProto; +struct google_protobuf_DescriptorProto; +struct google_protobuf_DescriptorProto_ExtensionRange; +struct google_protobuf_DescriptorProto_ReservedRange; +struct google_protobuf_ExtensionRangeOptions; +struct google_protobuf_FieldDescriptorProto; +struct google_protobuf_OneofDescriptorProto; +struct google_protobuf_EnumDescriptorProto; +struct google_protobuf_EnumDescriptorProto_EnumReservedRange; +struct google_protobuf_EnumValueDescriptorProto; +struct google_protobuf_ServiceDescriptorProto; +struct google_protobuf_MethodDescriptorProto; +struct google_protobuf_FileOptions; +struct google_protobuf_MessageOptions; +struct google_protobuf_FieldOptions; +struct google_protobuf_OneofOptions; +struct google_protobuf_EnumOptions; +struct google_protobuf_EnumValueOptions; +struct google_protobuf_ServiceOptions; +struct google_protobuf_MethodOptions; +struct google_protobuf_UninterpretedOption; +struct google_protobuf_UninterpretedOption_NamePart; +struct google_protobuf_SourceCodeInfo; +struct google_protobuf_SourceCodeInfo_Location; +struct google_protobuf_GeneratedCodeInfo; +struct google_protobuf_GeneratedCodeInfo_Annotation; +typedef struct google_protobuf_FileDescriptorSet google_protobuf_FileDescriptorSet; +typedef struct google_protobuf_FileDescriptorProto google_protobuf_FileDescriptorProto; +typedef struct google_protobuf_DescriptorProto google_protobuf_DescriptorProto; +typedef struct google_protobuf_DescriptorProto_ExtensionRange google_protobuf_DescriptorProto_ExtensionRange; +typedef struct google_protobuf_DescriptorProto_ReservedRange google_protobuf_DescriptorProto_ReservedRange; +typedef struct google_protobuf_ExtensionRangeOptions google_protobuf_ExtensionRangeOptions; +typedef struct google_protobuf_FieldDescriptorProto google_protobuf_FieldDescriptorProto; +typedef struct google_protobuf_OneofDescriptorProto google_protobuf_OneofDescriptorProto; +typedef struct google_protobuf_EnumDescriptorProto google_protobuf_EnumDescriptorProto; +typedef struct google_protobuf_EnumDescriptorProto_EnumReservedRange google_protobuf_EnumDescriptorProto_EnumReservedRange; +typedef struct google_protobuf_EnumValueDescriptorProto google_protobuf_EnumValueDescriptorProto; +typedef struct google_protobuf_ServiceDescriptorProto google_protobuf_ServiceDescriptorProto; +typedef struct google_protobuf_MethodDescriptorProto google_protobuf_MethodDescriptorProto; +typedef struct google_protobuf_FileOptions google_protobuf_FileOptions; +typedef struct google_protobuf_MessageOptions google_protobuf_MessageOptions; +typedef struct google_protobuf_FieldOptions google_protobuf_FieldOptions; +typedef struct google_protobuf_OneofOptions google_protobuf_OneofOptions; +typedef struct google_protobuf_EnumOptions google_protobuf_EnumOptions; +typedef struct google_protobuf_EnumValueOptions google_protobuf_EnumValueOptions; +typedef struct google_protobuf_ServiceOptions google_protobuf_ServiceOptions; +typedef struct google_protobuf_MethodOptions google_protobuf_MethodOptions; +typedef struct google_protobuf_UninterpretedOption google_protobuf_UninterpretedOption; +typedef struct google_protobuf_UninterpretedOption_NamePart google_protobuf_UninterpretedOption_NamePart; +typedef struct google_protobuf_SourceCodeInfo google_protobuf_SourceCodeInfo; +typedef struct google_protobuf_SourceCodeInfo_Location google_protobuf_SourceCodeInfo_Location; +typedef struct google_protobuf_GeneratedCodeInfo google_protobuf_GeneratedCodeInfo; +typedef struct google_protobuf_GeneratedCodeInfo_Annotation google_protobuf_GeneratedCodeInfo_Annotation; + +/* Enums */ + +typedef enum { + google_protobuf_FieldDescriptorProto_LABEL_OPTIONAL = 1, + google_protobuf_FieldDescriptorProto_LABEL_REQUIRED = 2, + google_protobuf_FieldDescriptorProto_LABEL_REPEATED = 3 +} google_protobuf_FieldDescriptorProto_Label; + +typedef enum { + google_protobuf_FieldDescriptorProto_TYPE_DOUBLE = 1, + google_protobuf_FieldDescriptorProto_TYPE_FLOAT = 2, + google_protobuf_FieldDescriptorProto_TYPE_INT64 = 3, + google_protobuf_FieldDescriptorProto_TYPE_UINT64 = 4, + google_protobuf_FieldDescriptorProto_TYPE_INT32 = 5, + google_protobuf_FieldDescriptorProto_TYPE_FIXED64 = 6, + google_protobuf_FieldDescriptorProto_TYPE_FIXED32 = 7, + google_protobuf_FieldDescriptorProto_TYPE_BOOL = 8, + google_protobuf_FieldDescriptorProto_TYPE_STRING = 9, + google_protobuf_FieldDescriptorProto_TYPE_GROUP = 10, + google_protobuf_FieldDescriptorProto_TYPE_MESSAGE = 11, + google_protobuf_FieldDescriptorProto_TYPE_BYTES = 12, + google_protobuf_FieldDescriptorProto_TYPE_UINT32 = 13, + google_protobuf_FieldDescriptorProto_TYPE_ENUM = 14, + google_protobuf_FieldDescriptorProto_TYPE_SFIXED32 = 15, + google_protobuf_FieldDescriptorProto_TYPE_SFIXED64 = 16, + google_protobuf_FieldDescriptorProto_TYPE_SINT32 = 17, + google_protobuf_FieldDescriptorProto_TYPE_SINT64 = 18 +} google_protobuf_FieldDescriptorProto_Type; + +typedef enum { + google_protobuf_FieldOptions_STRING = 0, + google_protobuf_FieldOptions_CORD = 1, + google_protobuf_FieldOptions_STRING_PIECE = 2 +} google_protobuf_FieldOptions_CType; + +typedef enum { + google_protobuf_FieldOptions_JS_NORMAL = 0, + google_protobuf_FieldOptions_JS_STRING = 1, + google_protobuf_FieldOptions_JS_NUMBER = 2 +} google_protobuf_FieldOptions_JSType; + +typedef enum { + google_protobuf_FileOptions_SPEED = 1, + google_protobuf_FileOptions_CODE_SIZE = 2, + google_protobuf_FileOptions_LITE_RUNTIME = 3 +} google_protobuf_FileOptions_OptimizeMode; + +typedef enum { + google_protobuf_MethodOptions_IDEMPOTENCY_UNKNOWN = 0, + google_protobuf_MethodOptions_NO_SIDE_EFFECTS = 1, + google_protobuf_MethodOptions_IDEMPOTENT = 2 +} google_protobuf_MethodOptions_IdempotencyLevel; + +/* google.protobuf.FileDescriptorSet */ + +extern const upb_msglayout google_protobuf_FileDescriptorSet_msginit; +UPB_INLINE google_protobuf_FileDescriptorSet *google_protobuf_FileDescriptorSet_new(upb_arena *arena) { + return upb_msg_new(&google_protobuf_FileDescriptorSet_msginit, arena); +} +UPB_INLINE google_protobuf_FileDescriptorSet *google_protobuf_FileDescriptorSet_parsenew(upb_stringview buf, upb_arena *arena) { + google_protobuf_FileDescriptorSet *ret = google_protobuf_FileDescriptorSet_new(arena); + return (ret && upb_decode(buf, ret, &google_protobuf_FileDescriptorSet_msginit)) ? ret : NULL; +} +UPB_INLINE char *google_protobuf_FileDescriptorSet_serialize(const google_protobuf_FileDescriptorSet *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &google_protobuf_FileDescriptorSet_msginit, arena, len); +} + +UPB_INLINE const upb_array* google_protobuf_FileDescriptorSet_file(const google_protobuf_FileDescriptorSet *msg) { return UPB_FIELD_AT(msg, const upb_array*, UPB_SIZE(0, 0)); } + +UPB_INLINE void google_protobuf_FileDescriptorSet_set_file(google_protobuf_FileDescriptorSet *msg, upb_array* value) { UPB_FIELD_AT(msg, upb_array*, UPB_SIZE(0, 0)) = value; } + + +/* google.protobuf.FileDescriptorProto */ + +extern const upb_msglayout google_protobuf_FileDescriptorProto_msginit; +UPB_INLINE google_protobuf_FileDescriptorProto *google_protobuf_FileDescriptorProto_new(upb_arena *arena) { + return upb_msg_new(&google_protobuf_FileDescriptorProto_msginit, arena); +} +UPB_INLINE google_protobuf_FileDescriptorProto *google_protobuf_FileDescriptorProto_parsenew(upb_stringview buf, upb_arena *arena) { + google_protobuf_FileDescriptorProto *ret = google_protobuf_FileDescriptorProto_new(arena); + return (ret && upb_decode(buf, ret, &google_protobuf_FileDescriptorProto_msginit)) ? ret : NULL; +} +UPB_INLINE char *google_protobuf_FileDescriptorProto_serialize(const google_protobuf_FileDescriptorProto *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &google_protobuf_FileDescriptorProto_msginit, arena, len); +} + +UPB_INLINE upb_stringview google_protobuf_FileDescriptorProto_name(const google_protobuf_FileDescriptorProto *msg) { return UPB_FIELD_AT(msg, upb_stringview, UPB_SIZE(8, 16)); } +UPB_INLINE upb_stringview google_protobuf_FileDescriptorProto_package(const google_protobuf_FileDescriptorProto *msg) { return UPB_FIELD_AT(msg, upb_stringview, UPB_SIZE(16, 32)); } +UPB_INLINE const upb_array* google_protobuf_FileDescriptorProto_dependency(const google_protobuf_FileDescriptorProto *msg) { return UPB_FIELD_AT(msg, const upb_array*, UPB_SIZE(40, 80)); } +UPB_INLINE const upb_array* google_protobuf_FileDescriptorProto_message_type(const google_protobuf_FileDescriptorProto *msg) { return UPB_FIELD_AT(msg, const upb_array*, UPB_SIZE(44, 88)); } +UPB_INLINE const upb_array* google_protobuf_FileDescriptorProto_enum_type(const google_protobuf_FileDescriptorProto *msg) { return UPB_FIELD_AT(msg, const upb_array*, UPB_SIZE(48, 96)); } +UPB_INLINE const upb_array* google_protobuf_FileDescriptorProto_service(const google_protobuf_FileDescriptorProto *msg) { return UPB_FIELD_AT(msg, const upb_array*, UPB_SIZE(52, 104)); } +UPB_INLINE const upb_array* google_protobuf_FileDescriptorProto_extension(const google_protobuf_FileDescriptorProto *msg) { return UPB_FIELD_AT(msg, const upb_array*, UPB_SIZE(56, 112)); } +UPB_INLINE const google_protobuf_FileOptions* google_protobuf_FileDescriptorProto_options(const google_protobuf_FileDescriptorProto *msg) { return UPB_FIELD_AT(msg, const google_protobuf_FileOptions*, UPB_SIZE(32, 64)); } +UPB_INLINE const google_protobuf_SourceCodeInfo* google_protobuf_FileDescriptorProto_source_code_info(const google_protobuf_FileDescriptorProto *msg) { return UPB_FIELD_AT(msg, const google_protobuf_SourceCodeInfo*, UPB_SIZE(36, 72)); } +UPB_INLINE const upb_array* google_protobuf_FileDescriptorProto_public_dependency(const google_protobuf_FileDescriptorProto *msg) { return UPB_FIELD_AT(msg, const upb_array*, UPB_SIZE(60, 120)); } +UPB_INLINE const upb_array* google_protobuf_FileDescriptorProto_weak_dependency(const google_protobuf_FileDescriptorProto *msg) { return UPB_FIELD_AT(msg, const upb_array*, UPB_SIZE(64, 128)); } +UPB_INLINE upb_stringview google_protobuf_FileDescriptorProto_syntax(const google_protobuf_FileDescriptorProto *msg) { return UPB_FIELD_AT(msg, upb_stringview, UPB_SIZE(24, 48)); } + +UPB_INLINE void google_protobuf_FileDescriptorProto_set_name(google_protobuf_FileDescriptorProto *msg, upb_stringview value) { UPB_FIELD_AT(msg, upb_stringview, UPB_SIZE(8, 16)) = value; } +UPB_INLINE void google_protobuf_FileDescriptorProto_set_package(google_protobuf_FileDescriptorProto *msg, upb_stringview value) { UPB_FIELD_AT(msg, upb_stringview, UPB_SIZE(16, 32)) = value; } +UPB_INLINE void google_protobuf_FileDescriptorProto_set_dependency(google_protobuf_FileDescriptorProto *msg, upb_array* value) { UPB_FIELD_AT(msg, upb_array*, UPB_SIZE(40, 80)) = value; } +UPB_INLINE void google_protobuf_FileDescriptorProto_set_message_type(google_protobuf_FileDescriptorProto *msg, upb_array* value) { UPB_FIELD_AT(msg, upb_array*, UPB_SIZE(44, 88)) = value; } +UPB_INLINE void google_protobuf_FileDescriptorProto_set_enum_type(google_protobuf_FileDescriptorProto *msg, upb_array* value) { UPB_FIELD_AT(msg, upb_array*, UPB_SIZE(48, 96)) = value; } +UPB_INLINE void google_protobuf_FileDescriptorProto_set_service(google_protobuf_FileDescriptorProto *msg, upb_array* value) { UPB_FIELD_AT(msg, upb_array*, UPB_SIZE(52, 104)) = value; } +UPB_INLINE void google_protobuf_FileDescriptorProto_set_extension(google_protobuf_FileDescriptorProto *msg, upb_array* value) { UPB_FIELD_AT(msg, upb_array*, UPB_SIZE(56, 112)) = value; } +UPB_INLINE void google_protobuf_FileDescriptorProto_set_options(google_protobuf_FileDescriptorProto *msg, google_protobuf_FileOptions* value) { UPB_FIELD_AT(msg, google_protobuf_FileOptions*, UPB_SIZE(32, 64)) = value; } +UPB_INLINE void google_protobuf_FileDescriptorProto_set_source_code_info(google_protobuf_FileDescriptorProto *msg, google_protobuf_SourceCodeInfo* value) { UPB_FIELD_AT(msg, google_protobuf_SourceCodeInfo*, UPB_SIZE(36, 72)) = value; } +UPB_INLINE void google_protobuf_FileDescriptorProto_set_public_dependency(google_protobuf_FileDescriptorProto *msg, upb_array* value) { UPB_FIELD_AT(msg, upb_array*, UPB_SIZE(60, 120)) = value; } +UPB_INLINE void google_protobuf_FileDescriptorProto_set_weak_dependency(google_protobuf_FileDescriptorProto *msg, upb_array* value) { UPB_FIELD_AT(msg, upb_array*, UPB_SIZE(64, 128)) = value; } +UPB_INLINE void google_protobuf_FileDescriptorProto_set_syntax(google_protobuf_FileDescriptorProto *msg, upb_stringview value) { UPB_FIELD_AT(msg, upb_stringview, UPB_SIZE(24, 48)) = value; } + + +/* google.protobuf.DescriptorProto */ + +extern const upb_msglayout google_protobuf_DescriptorProto_msginit; +UPB_INLINE google_protobuf_DescriptorProto *google_protobuf_DescriptorProto_new(upb_arena *arena) { + return upb_msg_new(&google_protobuf_DescriptorProto_msginit, arena); +} +UPB_INLINE google_protobuf_DescriptorProto *google_protobuf_DescriptorProto_parsenew(upb_stringview buf, upb_arena *arena) { + google_protobuf_DescriptorProto *ret = google_protobuf_DescriptorProto_new(arena); + return (ret && upb_decode(buf, ret, &google_protobuf_DescriptorProto_msginit)) ? ret : NULL; +} +UPB_INLINE char *google_protobuf_DescriptorProto_serialize(const google_protobuf_DescriptorProto *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &google_protobuf_DescriptorProto_msginit, arena, len); +} + +UPB_INLINE upb_stringview google_protobuf_DescriptorProto_name(const google_protobuf_DescriptorProto *msg) { return UPB_FIELD_AT(msg, upb_stringview, UPB_SIZE(8, 16)); } +UPB_INLINE const upb_array* google_protobuf_DescriptorProto_field(const google_protobuf_DescriptorProto *msg) { return UPB_FIELD_AT(msg, const upb_array*, UPB_SIZE(20, 40)); } +UPB_INLINE const upb_array* google_protobuf_DescriptorProto_nested_type(const google_protobuf_DescriptorProto *msg) { return UPB_FIELD_AT(msg, const upb_array*, UPB_SIZE(24, 48)); } +UPB_INLINE const upb_array* google_protobuf_DescriptorProto_enum_type(const google_protobuf_DescriptorProto *msg) { return UPB_FIELD_AT(msg, const upb_array*, UPB_SIZE(28, 56)); } +UPB_INLINE const upb_array* google_protobuf_DescriptorProto_extension_range(const google_protobuf_DescriptorProto *msg) { return UPB_FIELD_AT(msg, const upb_array*, UPB_SIZE(32, 64)); } +UPB_INLINE const upb_array* google_protobuf_DescriptorProto_extension(const google_protobuf_DescriptorProto *msg) { return UPB_FIELD_AT(msg, const upb_array*, UPB_SIZE(36, 72)); } +UPB_INLINE const google_protobuf_MessageOptions* google_protobuf_DescriptorProto_options(const google_protobuf_DescriptorProto *msg) { return UPB_FIELD_AT(msg, const google_protobuf_MessageOptions*, UPB_SIZE(16, 32)); } +UPB_INLINE const upb_array* google_protobuf_DescriptorProto_oneof_decl(const google_protobuf_DescriptorProto *msg) { return UPB_FIELD_AT(msg, const upb_array*, UPB_SIZE(40, 80)); } +UPB_INLINE const upb_array* google_protobuf_DescriptorProto_reserved_range(const google_protobuf_DescriptorProto *msg) { return UPB_FIELD_AT(msg, const upb_array*, UPB_SIZE(44, 88)); } +UPB_INLINE const upb_array* google_protobuf_DescriptorProto_reserved_name(const google_protobuf_DescriptorProto *msg) { return UPB_FIELD_AT(msg, const upb_array*, UPB_SIZE(48, 96)); } + +UPB_INLINE void google_protobuf_DescriptorProto_set_name(google_protobuf_DescriptorProto *msg, upb_stringview value) { UPB_FIELD_AT(msg, upb_stringview, UPB_SIZE(8, 16)) = value; } +UPB_INLINE void google_protobuf_DescriptorProto_set_field(google_protobuf_DescriptorProto *msg, upb_array* value) { UPB_FIELD_AT(msg, upb_array*, UPB_SIZE(20, 40)) = value; } +UPB_INLINE void google_protobuf_DescriptorProto_set_nested_type(google_protobuf_DescriptorProto *msg, upb_array* value) { UPB_FIELD_AT(msg, upb_array*, UPB_SIZE(24, 48)) = value; } +UPB_INLINE void google_protobuf_DescriptorProto_set_enum_type(google_protobuf_DescriptorProto *msg, upb_array* value) { UPB_FIELD_AT(msg, upb_array*, UPB_SIZE(28, 56)) = value; } +UPB_INLINE void google_protobuf_DescriptorProto_set_extension_range(google_protobuf_DescriptorProto *msg, upb_array* value) { UPB_FIELD_AT(msg, upb_array*, UPB_SIZE(32, 64)) = value; } +UPB_INLINE void google_protobuf_DescriptorProto_set_extension(google_protobuf_DescriptorProto *msg, upb_array* value) { UPB_FIELD_AT(msg, upb_array*, UPB_SIZE(36, 72)) = value; } +UPB_INLINE void google_protobuf_DescriptorProto_set_options(google_protobuf_DescriptorProto *msg, google_protobuf_MessageOptions* value) { UPB_FIELD_AT(msg, google_protobuf_MessageOptions*, UPB_SIZE(16, 32)) = value; } +UPB_INLINE void google_protobuf_DescriptorProto_set_oneof_decl(google_protobuf_DescriptorProto *msg, upb_array* value) { UPB_FIELD_AT(msg, upb_array*, UPB_SIZE(40, 80)) = value; } +UPB_INLINE void google_protobuf_DescriptorProto_set_reserved_range(google_protobuf_DescriptorProto *msg, upb_array* value) { UPB_FIELD_AT(msg, upb_array*, UPB_SIZE(44, 88)) = value; } +UPB_INLINE void google_protobuf_DescriptorProto_set_reserved_name(google_protobuf_DescriptorProto *msg, upb_array* value) { UPB_FIELD_AT(msg, upb_array*, UPB_SIZE(48, 96)) = value; } + + +/* google.protobuf.DescriptorProto.ExtensionRange */ + +extern const upb_msglayout google_protobuf_DescriptorProto_ExtensionRange_msginit; +UPB_INLINE google_protobuf_DescriptorProto_ExtensionRange *google_protobuf_DescriptorProto_ExtensionRange_new(upb_arena *arena) { + return upb_msg_new(&google_protobuf_DescriptorProto_ExtensionRange_msginit, arena); +} +UPB_INLINE google_protobuf_DescriptorProto_ExtensionRange *google_protobuf_DescriptorProto_ExtensionRange_parsenew(upb_stringview buf, upb_arena *arena) { + google_protobuf_DescriptorProto_ExtensionRange *ret = google_protobuf_DescriptorProto_ExtensionRange_new(arena); + return (ret && upb_decode(buf, ret, &google_protobuf_DescriptorProto_ExtensionRange_msginit)) ? ret : NULL; +} +UPB_INLINE char *google_protobuf_DescriptorProto_ExtensionRange_serialize(const google_protobuf_DescriptorProto_ExtensionRange *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &google_protobuf_DescriptorProto_ExtensionRange_msginit, arena, len); +} + +UPB_INLINE int32_t google_protobuf_DescriptorProto_ExtensionRange_start(const google_protobuf_DescriptorProto_ExtensionRange *msg) { return UPB_FIELD_AT(msg, int32_t, UPB_SIZE(4, 4)); } +UPB_INLINE int32_t google_protobuf_DescriptorProto_ExtensionRange_end(const google_protobuf_DescriptorProto_ExtensionRange *msg) { return UPB_FIELD_AT(msg, int32_t, UPB_SIZE(8, 8)); } +UPB_INLINE const google_protobuf_ExtensionRangeOptions* google_protobuf_DescriptorProto_ExtensionRange_options(const google_protobuf_DescriptorProto_ExtensionRange *msg) { return UPB_FIELD_AT(msg, const google_protobuf_ExtensionRangeOptions*, UPB_SIZE(12, 16)); } + +UPB_INLINE void google_protobuf_DescriptorProto_ExtensionRange_set_start(google_protobuf_DescriptorProto_ExtensionRange *msg, int32_t value) { UPB_FIELD_AT(msg, int32_t, UPB_SIZE(4, 4)) = value; } +UPB_INLINE void google_protobuf_DescriptorProto_ExtensionRange_set_end(google_protobuf_DescriptorProto_ExtensionRange *msg, int32_t value) { UPB_FIELD_AT(msg, int32_t, UPB_SIZE(8, 8)) = value; } +UPB_INLINE void google_protobuf_DescriptorProto_ExtensionRange_set_options(google_protobuf_DescriptorProto_ExtensionRange *msg, google_protobuf_ExtensionRangeOptions* value) { UPB_FIELD_AT(msg, google_protobuf_ExtensionRangeOptions*, UPB_SIZE(12, 16)) = value; } + + +/* google.protobuf.DescriptorProto.ReservedRange */ + +extern const upb_msglayout google_protobuf_DescriptorProto_ReservedRange_msginit; +UPB_INLINE google_protobuf_DescriptorProto_ReservedRange *google_protobuf_DescriptorProto_ReservedRange_new(upb_arena *arena) { + return upb_msg_new(&google_protobuf_DescriptorProto_ReservedRange_msginit, arena); +} +UPB_INLINE google_protobuf_DescriptorProto_ReservedRange *google_protobuf_DescriptorProto_ReservedRange_parsenew(upb_stringview buf, upb_arena *arena) { + google_protobuf_DescriptorProto_ReservedRange *ret = google_protobuf_DescriptorProto_ReservedRange_new(arena); + return (ret && upb_decode(buf, ret, &google_protobuf_DescriptorProto_ReservedRange_msginit)) ? ret : NULL; +} +UPB_INLINE char *google_protobuf_DescriptorProto_ReservedRange_serialize(const google_protobuf_DescriptorProto_ReservedRange *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &google_protobuf_DescriptorProto_ReservedRange_msginit, arena, len); +} + +UPB_INLINE int32_t google_protobuf_DescriptorProto_ReservedRange_start(const google_protobuf_DescriptorProto_ReservedRange *msg) { return UPB_FIELD_AT(msg, int32_t, UPB_SIZE(4, 4)); } +UPB_INLINE int32_t google_protobuf_DescriptorProto_ReservedRange_end(const google_protobuf_DescriptorProto_ReservedRange *msg) { return UPB_FIELD_AT(msg, int32_t, UPB_SIZE(8, 8)); } + +UPB_INLINE void google_protobuf_DescriptorProto_ReservedRange_set_start(google_protobuf_DescriptorProto_ReservedRange *msg, int32_t value) { UPB_FIELD_AT(msg, int32_t, UPB_SIZE(4, 4)) = value; } +UPB_INLINE void google_protobuf_DescriptorProto_ReservedRange_set_end(google_protobuf_DescriptorProto_ReservedRange *msg, int32_t value) { UPB_FIELD_AT(msg, int32_t, UPB_SIZE(8, 8)) = value; } + + +/* google.protobuf.ExtensionRangeOptions */ + +extern const upb_msglayout google_protobuf_ExtensionRangeOptions_msginit; +UPB_INLINE google_protobuf_ExtensionRangeOptions *google_protobuf_ExtensionRangeOptions_new(upb_arena *arena) { + return upb_msg_new(&google_protobuf_ExtensionRangeOptions_msginit, arena); +} +UPB_INLINE google_protobuf_ExtensionRangeOptions *google_protobuf_ExtensionRangeOptions_parsenew(upb_stringview buf, upb_arena *arena) { + google_protobuf_ExtensionRangeOptions *ret = google_protobuf_ExtensionRangeOptions_new(arena); + return (ret && upb_decode(buf, ret, &google_protobuf_ExtensionRangeOptions_msginit)) ? ret : NULL; +} +UPB_INLINE char *google_protobuf_ExtensionRangeOptions_serialize(const google_protobuf_ExtensionRangeOptions *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &google_protobuf_ExtensionRangeOptions_msginit, arena, len); +} + +UPB_INLINE const upb_array* google_protobuf_ExtensionRangeOptions_uninterpreted_option(const google_protobuf_ExtensionRangeOptions *msg) { return UPB_FIELD_AT(msg, const upb_array*, UPB_SIZE(0, 0)); } + +UPB_INLINE void google_protobuf_ExtensionRangeOptions_set_uninterpreted_option(google_protobuf_ExtensionRangeOptions *msg, upb_array* value) { UPB_FIELD_AT(msg, upb_array*, UPB_SIZE(0, 0)) = value; } + + +/* google.protobuf.FieldDescriptorProto */ + +extern const upb_msglayout google_protobuf_FieldDescriptorProto_msginit; +UPB_INLINE google_protobuf_FieldDescriptorProto *google_protobuf_FieldDescriptorProto_new(upb_arena *arena) { + return upb_msg_new(&google_protobuf_FieldDescriptorProto_msginit, arena); +} +UPB_INLINE google_protobuf_FieldDescriptorProto *google_protobuf_FieldDescriptorProto_parsenew(upb_stringview buf, upb_arena *arena) { + google_protobuf_FieldDescriptorProto *ret = google_protobuf_FieldDescriptorProto_new(arena); + return (ret && upb_decode(buf, ret, &google_protobuf_FieldDescriptorProto_msginit)) ? ret : NULL; +} +UPB_INLINE char *google_protobuf_FieldDescriptorProto_serialize(const google_protobuf_FieldDescriptorProto *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &google_protobuf_FieldDescriptorProto_msginit, arena, len); +} + +UPB_INLINE upb_stringview google_protobuf_FieldDescriptorProto_name(const google_protobuf_FieldDescriptorProto *msg) { return UPB_FIELD_AT(msg, upb_stringview, UPB_SIZE(32, 32)); } +UPB_INLINE upb_stringview google_protobuf_FieldDescriptorProto_extendee(const google_protobuf_FieldDescriptorProto *msg) { return UPB_FIELD_AT(msg, upb_stringview, UPB_SIZE(40, 48)); } +UPB_INLINE int32_t google_protobuf_FieldDescriptorProto_number(const google_protobuf_FieldDescriptorProto *msg) { return UPB_FIELD_AT(msg, int32_t, UPB_SIZE(24, 24)); } +UPB_INLINE google_protobuf_FieldDescriptorProto_Label google_protobuf_FieldDescriptorProto_label(const google_protobuf_FieldDescriptorProto *msg) { return UPB_FIELD_AT(msg, google_protobuf_FieldDescriptorProto_Label, UPB_SIZE(8, 8)); } +UPB_INLINE google_protobuf_FieldDescriptorProto_Type google_protobuf_FieldDescriptorProto_type(const google_protobuf_FieldDescriptorProto *msg) { return UPB_FIELD_AT(msg, google_protobuf_FieldDescriptorProto_Type, UPB_SIZE(16, 16)); } +UPB_INLINE upb_stringview google_protobuf_FieldDescriptorProto_type_name(const google_protobuf_FieldDescriptorProto *msg) { return UPB_FIELD_AT(msg, upb_stringview, UPB_SIZE(48, 64)); } +UPB_INLINE upb_stringview google_protobuf_FieldDescriptorProto_default_value(const google_protobuf_FieldDescriptorProto *msg) { return UPB_FIELD_AT(msg, upb_stringview, UPB_SIZE(56, 80)); } +UPB_INLINE const google_protobuf_FieldOptions* google_protobuf_FieldDescriptorProto_options(const google_protobuf_FieldDescriptorProto *msg) { return UPB_FIELD_AT(msg, const google_protobuf_FieldOptions*, UPB_SIZE(72, 112)); } +UPB_INLINE int32_t google_protobuf_FieldDescriptorProto_oneof_index(const google_protobuf_FieldDescriptorProto *msg) { return UPB_FIELD_AT(msg, int32_t, UPB_SIZE(28, 28)); } +UPB_INLINE upb_stringview google_protobuf_FieldDescriptorProto_json_name(const google_protobuf_FieldDescriptorProto *msg) { return UPB_FIELD_AT(msg, upb_stringview, UPB_SIZE(64, 96)); } + +UPB_INLINE void google_protobuf_FieldDescriptorProto_set_name(google_protobuf_FieldDescriptorProto *msg, upb_stringview value) { UPB_FIELD_AT(msg, upb_stringview, UPB_SIZE(32, 32)) = value; } +UPB_INLINE void google_protobuf_FieldDescriptorProto_set_extendee(google_protobuf_FieldDescriptorProto *msg, upb_stringview value) { UPB_FIELD_AT(msg, upb_stringview, UPB_SIZE(40, 48)) = value; } +UPB_INLINE void google_protobuf_FieldDescriptorProto_set_number(google_protobuf_FieldDescriptorProto *msg, int32_t value) { UPB_FIELD_AT(msg, int32_t, UPB_SIZE(24, 24)) = value; } +UPB_INLINE void google_protobuf_FieldDescriptorProto_set_label(google_protobuf_FieldDescriptorProto *msg, google_protobuf_FieldDescriptorProto_Label value) { UPB_FIELD_AT(msg, google_protobuf_FieldDescriptorProto_Label, UPB_SIZE(8, 8)) = value; } +UPB_INLINE void google_protobuf_FieldDescriptorProto_set_type(google_protobuf_FieldDescriptorProto *msg, google_protobuf_FieldDescriptorProto_Type value) { UPB_FIELD_AT(msg, google_protobuf_FieldDescriptorProto_Type, UPB_SIZE(16, 16)) = value; } +UPB_INLINE void google_protobuf_FieldDescriptorProto_set_type_name(google_protobuf_FieldDescriptorProto *msg, upb_stringview value) { UPB_FIELD_AT(msg, upb_stringview, UPB_SIZE(48, 64)) = value; } +UPB_INLINE void google_protobuf_FieldDescriptorProto_set_default_value(google_protobuf_FieldDescriptorProto *msg, upb_stringview value) { UPB_FIELD_AT(msg, upb_stringview, UPB_SIZE(56, 80)) = value; } +UPB_INLINE void google_protobuf_FieldDescriptorProto_set_options(google_protobuf_FieldDescriptorProto *msg, google_protobuf_FieldOptions* value) { UPB_FIELD_AT(msg, google_protobuf_FieldOptions*, UPB_SIZE(72, 112)) = value; } +UPB_INLINE void google_protobuf_FieldDescriptorProto_set_oneof_index(google_protobuf_FieldDescriptorProto *msg, int32_t value) { UPB_FIELD_AT(msg, int32_t, UPB_SIZE(28, 28)) = value; } +UPB_INLINE void google_protobuf_FieldDescriptorProto_set_json_name(google_protobuf_FieldDescriptorProto *msg, upb_stringview value) { UPB_FIELD_AT(msg, upb_stringview, UPB_SIZE(64, 96)) = value; } + + +/* google.protobuf.OneofDescriptorProto */ + +extern const upb_msglayout google_protobuf_OneofDescriptorProto_msginit; +UPB_INLINE google_protobuf_OneofDescriptorProto *google_protobuf_OneofDescriptorProto_new(upb_arena *arena) { + return upb_msg_new(&google_protobuf_OneofDescriptorProto_msginit, arena); +} +UPB_INLINE google_protobuf_OneofDescriptorProto *google_protobuf_OneofDescriptorProto_parsenew(upb_stringview buf, upb_arena *arena) { + google_protobuf_OneofDescriptorProto *ret = google_protobuf_OneofDescriptorProto_new(arena); + return (ret && upb_decode(buf, ret, &google_protobuf_OneofDescriptorProto_msginit)) ? ret : NULL; +} +UPB_INLINE char *google_protobuf_OneofDescriptorProto_serialize(const google_protobuf_OneofDescriptorProto *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &google_protobuf_OneofDescriptorProto_msginit, arena, len); +} + +UPB_INLINE upb_stringview google_protobuf_OneofDescriptorProto_name(const google_protobuf_OneofDescriptorProto *msg) { return UPB_FIELD_AT(msg, upb_stringview, UPB_SIZE(8, 16)); } +UPB_INLINE const google_protobuf_OneofOptions* google_protobuf_OneofDescriptorProto_options(const google_protobuf_OneofDescriptorProto *msg) { return UPB_FIELD_AT(msg, const google_protobuf_OneofOptions*, UPB_SIZE(16, 32)); } + +UPB_INLINE void google_protobuf_OneofDescriptorProto_set_name(google_protobuf_OneofDescriptorProto *msg, upb_stringview value) { UPB_FIELD_AT(msg, upb_stringview, UPB_SIZE(8, 16)) = value; } +UPB_INLINE void google_protobuf_OneofDescriptorProto_set_options(google_protobuf_OneofDescriptorProto *msg, google_protobuf_OneofOptions* value) { UPB_FIELD_AT(msg, google_protobuf_OneofOptions*, UPB_SIZE(16, 32)) = value; } + + +/* google.protobuf.EnumDescriptorProto */ + +extern const upb_msglayout google_protobuf_EnumDescriptorProto_msginit; +UPB_INLINE google_protobuf_EnumDescriptorProto *google_protobuf_EnumDescriptorProto_new(upb_arena *arena) { + return upb_msg_new(&google_protobuf_EnumDescriptorProto_msginit, arena); +} +UPB_INLINE google_protobuf_EnumDescriptorProto *google_protobuf_EnumDescriptorProto_parsenew(upb_stringview buf, upb_arena *arena) { + google_protobuf_EnumDescriptorProto *ret = google_protobuf_EnumDescriptorProto_new(arena); + return (ret && upb_decode(buf, ret, &google_protobuf_EnumDescriptorProto_msginit)) ? ret : NULL; +} +UPB_INLINE char *google_protobuf_EnumDescriptorProto_serialize(const google_protobuf_EnumDescriptorProto *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &google_protobuf_EnumDescriptorProto_msginit, arena, len); +} + +UPB_INLINE upb_stringview google_protobuf_EnumDescriptorProto_name(const google_protobuf_EnumDescriptorProto *msg) { return UPB_FIELD_AT(msg, upb_stringview, UPB_SIZE(8, 16)); } +UPB_INLINE const upb_array* google_protobuf_EnumDescriptorProto_value(const google_protobuf_EnumDescriptorProto *msg) { return UPB_FIELD_AT(msg, const upb_array*, UPB_SIZE(20, 40)); } +UPB_INLINE const google_protobuf_EnumOptions* google_protobuf_EnumDescriptorProto_options(const google_protobuf_EnumDescriptorProto *msg) { return UPB_FIELD_AT(msg, const google_protobuf_EnumOptions*, UPB_SIZE(16, 32)); } +UPB_INLINE const upb_array* google_protobuf_EnumDescriptorProto_reserved_range(const google_protobuf_EnumDescriptorProto *msg) { return UPB_FIELD_AT(msg, const upb_array*, UPB_SIZE(24, 48)); } +UPB_INLINE const upb_array* google_protobuf_EnumDescriptorProto_reserved_name(const google_protobuf_EnumDescriptorProto *msg) { return UPB_FIELD_AT(msg, const upb_array*, UPB_SIZE(28, 56)); } + +UPB_INLINE void google_protobuf_EnumDescriptorProto_set_name(google_protobuf_EnumDescriptorProto *msg, upb_stringview value) { UPB_FIELD_AT(msg, upb_stringview, UPB_SIZE(8, 16)) = value; } +UPB_INLINE void google_protobuf_EnumDescriptorProto_set_value(google_protobuf_EnumDescriptorProto *msg, upb_array* value) { UPB_FIELD_AT(msg, upb_array*, UPB_SIZE(20, 40)) = value; } +UPB_INLINE void google_protobuf_EnumDescriptorProto_set_options(google_protobuf_EnumDescriptorProto *msg, google_protobuf_EnumOptions* value) { UPB_FIELD_AT(msg, google_protobuf_EnumOptions*, UPB_SIZE(16, 32)) = value; } +UPB_INLINE void google_protobuf_EnumDescriptorProto_set_reserved_range(google_protobuf_EnumDescriptorProto *msg, upb_array* value) { UPB_FIELD_AT(msg, upb_array*, UPB_SIZE(24, 48)) = value; } +UPB_INLINE void google_protobuf_EnumDescriptorProto_set_reserved_name(google_protobuf_EnumDescriptorProto *msg, upb_array* value) { UPB_FIELD_AT(msg, upb_array*, UPB_SIZE(28, 56)) = value; } + + +/* google.protobuf.EnumDescriptorProto.EnumReservedRange */ + +extern const upb_msglayout google_protobuf_EnumDescriptorProto_EnumReservedRange_msginit; +UPB_INLINE google_protobuf_EnumDescriptorProto_EnumReservedRange *google_protobuf_EnumDescriptorProto_EnumReservedRange_new(upb_arena *arena) { + return upb_msg_new(&google_protobuf_EnumDescriptorProto_EnumReservedRange_msginit, arena); +} +UPB_INLINE google_protobuf_EnumDescriptorProto_EnumReservedRange *google_protobuf_EnumDescriptorProto_EnumReservedRange_parsenew(upb_stringview buf, upb_arena *arena) { + google_protobuf_EnumDescriptorProto_EnumReservedRange *ret = google_protobuf_EnumDescriptorProto_EnumReservedRange_new(arena); + return (ret && upb_decode(buf, ret, &google_protobuf_EnumDescriptorProto_EnumReservedRange_msginit)) ? ret : NULL; +} +UPB_INLINE char *google_protobuf_EnumDescriptorProto_EnumReservedRange_serialize(const google_protobuf_EnumDescriptorProto_EnumReservedRange *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &google_protobuf_EnumDescriptorProto_EnumReservedRange_msginit, arena, len); +} + +UPB_INLINE int32_t google_protobuf_EnumDescriptorProto_EnumReservedRange_start(const google_protobuf_EnumDescriptorProto_EnumReservedRange *msg) { return UPB_FIELD_AT(msg, int32_t, UPB_SIZE(4, 4)); } +UPB_INLINE int32_t google_protobuf_EnumDescriptorProto_EnumReservedRange_end(const google_protobuf_EnumDescriptorProto_EnumReservedRange *msg) { return UPB_FIELD_AT(msg, int32_t, UPB_SIZE(8, 8)); } + +UPB_INLINE void google_protobuf_EnumDescriptorProto_EnumReservedRange_set_start(google_protobuf_EnumDescriptorProto_EnumReservedRange *msg, int32_t value) { UPB_FIELD_AT(msg, int32_t, UPB_SIZE(4, 4)) = value; } +UPB_INLINE void google_protobuf_EnumDescriptorProto_EnumReservedRange_set_end(google_protobuf_EnumDescriptorProto_EnumReservedRange *msg, int32_t value) { UPB_FIELD_AT(msg, int32_t, UPB_SIZE(8, 8)) = value; } + + +/* google.protobuf.EnumValueDescriptorProto */ + +extern const upb_msglayout google_protobuf_EnumValueDescriptorProto_msginit; +UPB_INLINE google_protobuf_EnumValueDescriptorProto *google_protobuf_EnumValueDescriptorProto_new(upb_arena *arena) { + return upb_msg_new(&google_protobuf_EnumValueDescriptorProto_msginit, arena); +} +UPB_INLINE google_protobuf_EnumValueDescriptorProto *google_protobuf_EnumValueDescriptorProto_parsenew(upb_stringview buf, upb_arena *arena) { + google_protobuf_EnumValueDescriptorProto *ret = google_protobuf_EnumValueDescriptorProto_new(arena); + return (ret && upb_decode(buf, ret, &google_protobuf_EnumValueDescriptorProto_msginit)) ? ret : NULL; +} +UPB_INLINE char *google_protobuf_EnumValueDescriptorProto_serialize(const google_protobuf_EnumValueDescriptorProto *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &google_protobuf_EnumValueDescriptorProto_msginit, arena, len); +} + +UPB_INLINE upb_stringview google_protobuf_EnumValueDescriptorProto_name(const google_protobuf_EnumValueDescriptorProto *msg) { return UPB_FIELD_AT(msg, upb_stringview, UPB_SIZE(8, 16)); } +UPB_INLINE int32_t google_protobuf_EnumValueDescriptorProto_number(const google_protobuf_EnumValueDescriptorProto *msg) { return UPB_FIELD_AT(msg, int32_t, UPB_SIZE(4, 4)); } +UPB_INLINE const google_protobuf_EnumValueOptions* google_protobuf_EnumValueDescriptorProto_options(const google_protobuf_EnumValueDescriptorProto *msg) { return UPB_FIELD_AT(msg, const google_protobuf_EnumValueOptions*, UPB_SIZE(16, 32)); } + +UPB_INLINE void google_protobuf_EnumValueDescriptorProto_set_name(google_protobuf_EnumValueDescriptorProto *msg, upb_stringview value) { UPB_FIELD_AT(msg, upb_stringview, UPB_SIZE(8, 16)) = value; } +UPB_INLINE void google_protobuf_EnumValueDescriptorProto_set_number(google_protobuf_EnumValueDescriptorProto *msg, int32_t value) { UPB_FIELD_AT(msg, int32_t, UPB_SIZE(4, 4)) = value; } +UPB_INLINE void google_protobuf_EnumValueDescriptorProto_set_options(google_protobuf_EnumValueDescriptorProto *msg, google_protobuf_EnumValueOptions* value) { UPB_FIELD_AT(msg, google_protobuf_EnumValueOptions*, UPB_SIZE(16, 32)) = value; } + + +/* google.protobuf.ServiceDescriptorProto */ + +extern const upb_msglayout google_protobuf_ServiceDescriptorProto_msginit; +UPB_INLINE google_protobuf_ServiceDescriptorProto *google_protobuf_ServiceDescriptorProto_new(upb_arena *arena) { + return upb_msg_new(&google_protobuf_ServiceDescriptorProto_msginit, arena); +} +UPB_INLINE google_protobuf_ServiceDescriptorProto *google_protobuf_ServiceDescriptorProto_parsenew(upb_stringview buf, upb_arena *arena) { + google_protobuf_ServiceDescriptorProto *ret = google_protobuf_ServiceDescriptorProto_new(arena); + return (ret && upb_decode(buf, ret, &google_protobuf_ServiceDescriptorProto_msginit)) ? ret : NULL; +} +UPB_INLINE char *google_protobuf_ServiceDescriptorProto_serialize(const google_protobuf_ServiceDescriptorProto *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &google_protobuf_ServiceDescriptorProto_msginit, arena, len); +} + +UPB_INLINE upb_stringview google_protobuf_ServiceDescriptorProto_name(const google_protobuf_ServiceDescriptorProto *msg) { return UPB_FIELD_AT(msg, upb_stringview, UPB_SIZE(8, 16)); } +UPB_INLINE const upb_array* google_protobuf_ServiceDescriptorProto_method(const google_protobuf_ServiceDescriptorProto *msg) { return UPB_FIELD_AT(msg, const upb_array*, UPB_SIZE(20, 40)); } +UPB_INLINE const google_protobuf_ServiceOptions* google_protobuf_ServiceDescriptorProto_options(const google_protobuf_ServiceDescriptorProto *msg) { return UPB_FIELD_AT(msg, const google_protobuf_ServiceOptions*, UPB_SIZE(16, 32)); } + +UPB_INLINE void google_protobuf_ServiceDescriptorProto_set_name(google_protobuf_ServiceDescriptorProto *msg, upb_stringview value) { UPB_FIELD_AT(msg, upb_stringview, UPB_SIZE(8, 16)) = value; } +UPB_INLINE void google_protobuf_ServiceDescriptorProto_set_method(google_protobuf_ServiceDescriptorProto *msg, upb_array* value) { UPB_FIELD_AT(msg, upb_array*, UPB_SIZE(20, 40)) = value; } +UPB_INLINE void google_protobuf_ServiceDescriptorProto_set_options(google_protobuf_ServiceDescriptorProto *msg, google_protobuf_ServiceOptions* value) { UPB_FIELD_AT(msg, google_protobuf_ServiceOptions*, UPB_SIZE(16, 32)) = value; } + + +/* google.protobuf.MethodDescriptorProto */ + +extern const upb_msglayout google_protobuf_MethodDescriptorProto_msginit; +UPB_INLINE google_protobuf_MethodDescriptorProto *google_protobuf_MethodDescriptorProto_new(upb_arena *arena) { + return upb_msg_new(&google_protobuf_MethodDescriptorProto_msginit, arena); +} +UPB_INLINE google_protobuf_MethodDescriptorProto *google_protobuf_MethodDescriptorProto_parsenew(upb_stringview buf, upb_arena *arena) { + google_protobuf_MethodDescriptorProto *ret = google_protobuf_MethodDescriptorProto_new(arena); + return (ret && upb_decode(buf, ret, &google_protobuf_MethodDescriptorProto_msginit)) ? ret : NULL; +} +UPB_INLINE char *google_protobuf_MethodDescriptorProto_serialize(const google_protobuf_MethodDescriptorProto *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &google_protobuf_MethodDescriptorProto_msginit, arena, len); +} + +UPB_INLINE upb_stringview google_protobuf_MethodDescriptorProto_name(const google_protobuf_MethodDescriptorProto *msg) { return UPB_FIELD_AT(msg, upb_stringview, UPB_SIZE(8, 16)); } +UPB_INLINE upb_stringview google_protobuf_MethodDescriptorProto_input_type(const google_protobuf_MethodDescriptorProto *msg) { return UPB_FIELD_AT(msg, upb_stringview, UPB_SIZE(16, 32)); } +UPB_INLINE upb_stringview google_protobuf_MethodDescriptorProto_output_type(const google_protobuf_MethodDescriptorProto *msg) { return UPB_FIELD_AT(msg, upb_stringview, UPB_SIZE(24, 48)); } +UPB_INLINE const google_protobuf_MethodOptions* google_protobuf_MethodDescriptorProto_options(const google_protobuf_MethodDescriptorProto *msg) { return UPB_FIELD_AT(msg, const google_protobuf_MethodOptions*, UPB_SIZE(32, 64)); } +UPB_INLINE bool google_protobuf_MethodDescriptorProto_client_streaming(const google_protobuf_MethodDescriptorProto *msg) { return UPB_FIELD_AT(msg, bool, UPB_SIZE(1, 1)); } +UPB_INLINE bool google_protobuf_MethodDescriptorProto_server_streaming(const google_protobuf_MethodDescriptorProto *msg) { return UPB_FIELD_AT(msg, bool, UPB_SIZE(2, 2)); } + +UPB_INLINE void google_protobuf_MethodDescriptorProto_set_name(google_protobuf_MethodDescriptorProto *msg, upb_stringview value) { UPB_FIELD_AT(msg, upb_stringview, UPB_SIZE(8, 16)) = value; } +UPB_INLINE void google_protobuf_MethodDescriptorProto_set_input_type(google_protobuf_MethodDescriptorProto *msg, upb_stringview value) { UPB_FIELD_AT(msg, upb_stringview, UPB_SIZE(16, 32)) = value; } +UPB_INLINE void google_protobuf_MethodDescriptorProto_set_output_type(google_protobuf_MethodDescriptorProto *msg, upb_stringview value) { UPB_FIELD_AT(msg, upb_stringview, UPB_SIZE(24, 48)) = value; } +UPB_INLINE void google_protobuf_MethodDescriptorProto_set_options(google_protobuf_MethodDescriptorProto *msg, google_protobuf_MethodOptions* value) { UPB_FIELD_AT(msg, google_protobuf_MethodOptions*, UPB_SIZE(32, 64)) = value; } +UPB_INLINE void google_protobuf_MethodDescriptorProto_set_client_streaming(google_protobuf_MethodDescriptorProto *msg, bool value) { UPB_FIELD_AT(msg, bool, UPB_SIZE(1, 1)) = value; } +UPB_INLINE void google_protobuf_MethodDescriptorProto_set_server_streaming(google_protobuf_MethodDescriptorProto *msg, bool value) { UPB_FIELD_AT(msg, bool, UPB_SIZE(2, 2)) = value; } + + +/* google.protobuf.FileOptions */ + +extern const upb_msglayout google_protobuf_FileOptions_msginit; +UPB_INLINE google_protobuf_FileOptions *google_protobuf_FileOptions_new(upb_arena *arena) { + return upb_msg_new(&google_protobuf_FileOptions_msginit, arena); +} +UPB_INLINE google_protobuf_FileOptions *google_protobuf_FileOptions_parsenew(upb_stringview buf, upb_arena *arena) { + google_protobuf_FileOptions *ret = google_protobuf_FileOptions_new(arena); + return (ret && upb_decode(buf, ret, &google_protobuf_FileOptions_msginit)) ? ret : NULL; +} +UPB_INLINE char *google_protobuf_FileOptions_serialize(const google_protobuf_FileOptions *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &google_protobuf_FileOptions_msginit, arena, len); +} + +UPB_INLINE upb_stringview google_protobuf_FileOptions_java_package(const google_protobuf_FileOptions *msg) { return UPB_FIELD_AT(msg, upb_stringview, UPB_SIZE(32, 32)); } +UPB_INLINE upb_stringview google_protobuf_FileOptions_java_outer_classname(const google_protobuf_FileOptions *msg) { return UPB_FIELD_AT(msg, upb_stringview, UPB_SIZE(40, 48)); } +UPB_INLINE google_protobuf_FileOptions_OptimizeMode google_protobuf_FileOptions_optimize_for(const google_protobuf_FileOptions *msg) { return UPB_FIELD_AT(msg, google_protobuf_FileOptions_OptimizeMode, UPB_SIZE(8, 8)); } +UPB_INLINE bool google_protobuf_FileOptions_java_multiple_files(const google_protobuf_FileOptions *msg) { return UPB_FIELD_AT(msg, bool, UPB_SIZE(16, 16)); } +UPB_INLINE upb_stringview google_protobuf_FileOptions_go_package(const google_protobuf_FileOptions *msg) { return UPB_FIELD_AT(msg, upb_stringview, UPB_SIZE(48, 64)); } +UPB_INLINE bool google_protobuf_FileOptions_cc_generic_services(const google_protobuf_FileOptions *msg) { return UPB_FIELD_AT(msg, bool, UPB_SIZE(17, 17)); } +UPB_INLINE bool google_protobuf_FileOptions_java_generic_services(const google_protobuf_FileOptions *msg) { return UPB_FIELD_AT(msg, bool, UPB_SIZE(18, 18)); } +UPB_INLINE bool google_protobuf_FileOptions_py_generic_services(const google_protobuf_FileOptions *msg) { return UPB_FIELD_AT(msg, bool, UPB_SIZE(19, 19)); } +UPB_INLINE bool google_protobuf_FileOptions_java_generate_equals_and_hash(const google_protobuf_FileOptions *msg) { return UPB_FIELD_AT(msg, bool, UPB_SIZE(20, 20)); } +UPB_INLINE bool google_protobuf_FileOptions_deprecated(const google_protobuf_FileOptions *msg) { return UPB_FIELD_AT(msg, bool, UPB_SIZE(21, 21)); } +UPB_INLINE bool google_protobuf_FileOptions_java_string_check_utf8(const google_protobuf_FileOptions *msg) { return UPB_FIELD_AT(msg, bool, UPB_SIZE(22, 22)); } +UPB_INLINE bool google_protobuf_FileOptions_cc_enable_arenas(const google_protobuf_FileOptions *msg) { return UPB_FIELD_AT(msg, bool, UPB_SIZE(23, 23)); } +UPB_INLINE upb_stringview google_protobuf_FileOptions_objc_class_prefix(const google_protobuf_FileOptions *msg) { return UPB_FIELD_AT(msg, upb_stringview, UPB_SIZE(56, 80)); } +UPB_INLINE upb_stringview google_protobuf_FileOptions_csharp_namespace(const google_protobuf_FileOptions *msg) { return UPB_FIELD_AT(msg, upb_stringview, UPB_SIZE(64, 96)); } +UPB_INLINE upb_stringview google_protobuf_FileOptions_swift_prefix(const google_protobuf_FileOptions *msg) { return UPB_FIELD_AT(msg, upb_stringview, UPB_SIZE(72, 112)); } +UPB_INLINE upb_stringview google_protobuf_FileOptions_php_class_prefix(const google_protobuf_FileOptions *msg) { return UPB_FIELD_AT(msg, upb_stringview, UPB_SIZE(80, 128)); } +UPB_INLINE upb_stringview google_protobuf_FileOptions_php_namespace(const google_protobuf_FileOptions *msg) { return UPB_FIELD_AT(msg, upb_stringview, UPB_SIZE(88, 144)); } +UPB_INLINE bool google_protobuf_FileOptions_php_generic_services(const google_protobuf_FileOptions *msg) { return UPB_FIELD_AT(msg, bool, UPB_SIZE(24, 24)); } +UPB_INLINE const upb_array* google_protobuf_FileOptions_uninterpreted_option(const google_protobuf_FileOptions *msg) { return UPB_FIELD_AT(msg, const upb_array*, UPB_SIZE(96, 160)); } + +UPB_INLINE void google_protobuf_FileOptions_set_java_package(google_protobuf_FileOptions *msg, upb_stringview value) { UPB_FIELD_AT(msg, upb_stringview, UPB_SIZE(32, 32)) = value; } +UPB_INLINE void google_protobuf_FileOptions_set_java_outer_classname(google_protobuf_FileOptions *msg, upb_stringview value) { UPB_FIELD_AT(msg, upb_stringview, UPB_SIZE(40, 48)) = value; } +UPB_INLINE void google_protobuf_FileOptions_set_optimize_for(google_protobuf_FileOptions *msg, google_protobuf_FileOptions_OptimizeMode value) { UPB_FIELD_AT(msg, google_protobuf_FileOptions_OptimizeMode, UPB_SIZE(8, 8)) = value; } +UPB_INLINE void google_protobuf_FileOptions_set_java_multiple_files(google_protobuf_FileOptions *msg, bool value) { UPB_FIELD_AT(msg, bool, UPB_SIZE(16, 16)) = value; } +UPB_INLINE void google_protobuf_FileOptions_set_go_package(google_protobuf_FileOptions *msg, upb_stringview value) { UPB_FIELD_AT(msg, upb_stringview, UPB_SIZE(48, 64)) = value; } +UPB_INLINE void google_protobuf_FileOptions_set_cc_generic_services(google_protobuf_FileOptions *msg, bool value) { UPB_FIELD_AT(msg, bool, UPB_SIZE(17, 17)) = value; } +UPB_INLINE void google_protobuf_FileOptions_set_java_generic_services(google_protobuf_FileOptions *msg, bool value) { UPB_FIELD_AT(msg, bool, UPB_SIZE(18, 18)) = value; } +UPB_INLINE void google_protobuf_FileOptions_set_py_generic_services(google_protobuf_FileOptions *msg, bool value) { UPB_FIELD_AT(msg, bool, UPB_SIZE(19, 19)) = value; } +UPB_INLINE void google_protobuf_FileOptions_set_java_generate_equals_and_hash(google_protobuf_FileOptions *msg, bool value) { UPB_FIELD_AT(msg, bool, UPB_SIZE(20, 20)) = value; } +UPB_INLINE void google_protobuf_FileOptions_set_deprecated(google_protobuf_FileOptions *msg, bool value) { UPB_FIELD_AT(msg, bool, UPB_SIZE(21, 21)) = value; } +UPB_INLINE void google_protobuf_FileOptions_set_java_string_check_utf8(google_protobuf_FileOptions *msg, bool value) { UPB_FIELD_AT(msg, bool, UPB_SIZE(22, 22)) = value; } +UPB_INLINE void google_protobuf_FileOptions_set_cc_enable_arenas(google_protobuf_FileOptions *msg, bool value) { UPB_FIELD_AT(msg, bool, UPB_SIZE(23, 23)) = value; } +UPB_INLINE void google_protobuf_FileOptions_set_objc_class_prefix(google_protobuf_FileOptions *msg, upb_stringview value) { UPB_FIELD_AT(msg, upb_stringview, UPB_SIZE(56, 80)) = value; } +UPB_INLINE void google_protobuf_FileOptions_set_csharp_namespace(google_protobuf_FileOptions *msg, upb_stringview value) { UPB_FIELD_AT(msg, upb_stringview, UPB_SIZE(64, 96)) = value; } +UPB_INLINE void google_protobuf_FileOptions_set_swift_prefix(google_protobuf_FileOptions *msg, upb_stringview value) { UPB_FIELD_AT(msg, upb_stringview, UPB_SIZE(72, 112)) = value; } +UPB_INLINE void google_protobuf_FileOptions_set_php_class_prefix(google_protobuf_FileOptions *msg, upb_stringview value) { UPB_FIELD_AT(msg, upb_stringview, UPB_SIZE(80, 128)) = value; } +UPB_INLINE void google_protobuf_FileOptions_set_php_namespace(google_protobuf_FileOptions *msg, upb_stringview value) { UPB_FIELD_AT(msg, upb_stringview, UPB_SIZE(88, 144)) = value; } +UPB_INLINE void google_protobuf_FileOptions_set_php_generic_services(google_protobuf_FileOptions *msg, bool value) { UPB_FIELD_AT(msg, bool, UPB_SIZE(24, 24)) = value; } +UPB_INLINE void google_protobuf_FileOptions_set_uninterpreted_option(google_protobuf_FileOptions *msg, upb_array* value) { UPB_FIELD_AT(msg, upb_array*, UPB_SIZE(96, 160)) = value; } + + +/* google.protobuf.MessageOptions */ + +extern const upb_msglayout google_protobuf_MessageOptions_msginit; +UPB_INLINE google_protobuf_MessageOptions *google_protobuf_MessageOptions_new(upb_arena *arena) { + return upb_msg_new(&google_protobuf_MessageOptions_msginit, arena); +} +UPB_INLINE google_protobuf_MessageOptions *google_protobuf_MessageOptions_parsenew(upb_stringview buf, upb_arena *arena) { + google_protobuf_MessageOptions *ret = google_protobuf_MessageOptions_new(arena); + return (ret && upb_decode(buf, ret, &google_protobuf_MessageOptions_msginit)) ? ret : NULL; +} +UPB_INLINE char *google_protobuf_MessageOptions_serialize(const google_protobuf_MessageOptions *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &google_protobuf_MessageOptions_msginit, arena, len); +} + +UPB_INLINE bool google_protobuf_MessageOptions_message_set_wire_format(const google_protobuf_MessageOptions *msg) { return UPB_FIELD_AT(msg, bool, UPB_SIZE(1, 1)); } +UPB_INLINE bool google_protobuf_MessageOptions_no_standard_descriptor_accessor(const google_protobuf_MessageOptions *msg) { return UPB_FIELD_AT(msg, bool, UPB_SIZE(2, 2)); } +UPB_INLINE bool google_protobuf_MessageOptions_deprecated(const google_protobuf_MessageOptions *msg) { return UPB_FIELD_AT(msg, bool, UPB_SIZE(3, 3)); } +UPB_INLINE bool google_protobuf_MessageOptions_map_entry(const google_protobuf_MessageOptions *msg) { return UPB_FIELD_AT(msg, bool, UPB_SIZE(4, 4)); } +UPB_INLINE const upb_array* google_protobuf_MessageOptions_uninterpreted_option(const google_protobuf_MessageOptions *msg) { return UPB_FIELD_AT(msg, const upb_array*, UPB_SIZE(8, 8)); } + +UPB_INLINE void google_protobuf_MessageOptions_set_message_set_wire_format(google_protobuf_MessageOptions *msg, bool value) { UPB_FIELD_AT(msg, bool, UPB_SIZE(1, 1)) = value; } +UPB_INLINE void google_protobuf_MessageOptions_set_no_standard_descriptor_accessor(google_protobuf_MessageOptions *msg, bool value) { UPB_FIELD_AT(msg, bool, UPB_SIZE(2, 2)) = value; } +UPB_INLINE void google_protobuf_MessageOptions_set_deprecated(google_protobuf_MessageOptions *msg, bool value) { UPB_FIELD_AT(msg, bool, UPB_SIZE(3, 3)) = value; } +UPB_INLINE void google_protobuf_MessageOptions_set_map_entry(google_protobuf_MessageOptions *msg, bool value) { UPB_FIELD_AT(msg, bool, UPB_SIZE(4, 4)) = value; } +UPB_INLINE void google_protobuf_MessageOptions_set_uninterpreted_option(google_protobuf_MessageOptions *msg, upb_array* value) { UPB_FIELD_AT(msg, upb_array*, UPB_SIZE(8, 8)) = value; } + + +/* google.protobuf.FieldOptions */ + +extern const upb_msglayout google_protobuf_FieldOptions_msginit; +UPB_INLINE google_protobuf_FieldOptions *google_protobuf_FieldOptions_new(upb_arena *arena) { + return upb_msg_new(&google_protobuf_FieldOptions_msginit, arena); +} +UPB_INLINE google_protobuf_FieldOptions *google_protobuf_FieldOptions_parsenew(upb_stringview buf, upb_arena *arena) { + google_protobuf_FieldOptions *ret = google_protobuf_FieldOptions_new(arena); + return (ret && upb_decode(buf, ret, &google_protobuf_FieldOptions_msginit)) ? ret : NULL; +} +UPB_INLINE char *google_protobuf_FieldOptions_serialize(const google_protobuf_FieldOptions *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &google_protobuf_FieldOptions_msginit, arena, len); +} + +UPB_INLINE google_protobuf_FieldOptions_CType google_protobuf_FieldOptions_ctype(const google_protobuf_FieldOptions *msg) { return UPB_FIELD_AT(msg, google_protobuf_FieldOptions_CType, UPB_SIZE(8, 8)); } +UPB_INLINE bool google_protobuf_FieldOptions_packed(const google_protobuf_FieldOptions *msg) { return UPB_FIELD_AT(msg, bool, UPB_SIZE(24, 24)); } +UPB_INLINE bool google_protobuf_FieldOptions_deprecated(const google_protobuf_FieldOptions *msg) { return UPB_FIELD_AT(msg, bool, UPB_SIZE(25, 25)); } +UPB_INLINE bool google_protobuf_FieldOptions_lazy(const google_protobuf_FieldOptions *msg) { return UPB_FIELD_AT(msg, bool, UPB_SIZE(26, 26)); } +UPB_INLINE google_protobuf_FieldOptions_JSType google_protobuf_FieldOptions_jstype(const google_protobuf_FieldOptions *msg) { return UPB_FIELD_AT(msg, google_protobuf_FieldOptions_JSType, UPB_SIZE(16, 16)); } +UPB_INLINE bool google_protobuf_FieldOptions_weak(const google_protobuf_FieldOptions *msg) { return UPB_FIELD_AT(msg, bool, UPB_SIZE(27, 27)); } +UPB_INLINE const upb_array* google_protobuf_FieldOptions_uninterpreted_option(const google_protobuf_FieldOptions *msg) { return UPB_FIELD_AT(msg, const upb_array*, UPB_SIZE(28, 32)); } + +UPB_INLINE void google_protobuf_FieldOptions_set_ctype(google_protobuf_FieldOptions *msg, google_protobuf_FieldOptions_CType value) { UPB_FIELD_AT(msg, google_protobuf_FieldOptions_CType, UPB_SIZE(8, 8)) = value; } +UPB_INLINE void google_protobuf_FieldOptions_set_packed(google_protobuf_FieldOptions *msg, bool value) { UPB_FIELD_AT(msg, bool, UPB_SIZE(24, 24)) = value; } +UPB_INLINE void google_protobuf_FieldOptions_set_deprecated(google_protobuf_FieldOptions *msg, bool value) { UPB_FIELD_AT(msg, bool, UPB_SIZE(25, 25)) = value; } +UPB_INLINE void google_protobuf_FieldOptions_set_lazy(google_protobuf_FieldOptions *msg, bool value) { UPB_FIELD_AT(msg, bool, UPB_SIZE(26, 26)) = value; } +UPB_INLINE void google_protobuf_FieldOptions_set_jstype(google_protobuf_FieldOptions *msg, google_protobuf_FieldOptions_JSType value) { UPB_FIELD_AT(msg, google_protobuf_FieldOptions_JSType, UPB_SIZE(16, 16)) = value; } +UPB_INLINE void google_protobuf_FieldOptions_set_weak(google_protobuf_FieldOptions *msg, bool value) { UPB_FIELD_AT(msg, bool, UPB_SIZE(27, 27)) = value; } +UPB_INLINE void google_protobuf_FieldOptions_set_uninterpreted_option(google_protobuf_FieldOptions *msg, upb_array* value) { UPB_FIELD_AT(msg, upb_array*, UPB_SIZE(28, 32)) = value; } + + +/* google.protobuf.OneofOptions */ + +extern const upb_msglayout google_protobuf_OneofOptions_msginit; +UPB_INLINE google_protobuf_OneofOptions *google_protobuf_OneofOptions_new(upb_arena *arena) { + return upb_msg_new(&google_protobuf_OneofOptions_msginit, arena); +} +UPB_INLINE google_protobuf_OneofOptions *google_protobuf_OneofOptions_parsenew(upb_stringview buf, upb_arena *arena) { + google_protobuf_OneofOptions *ret = google_protobuf_OneofOptions_new(arena); + return (ret && upb_decode(buf, ret, &google_protobuf_OneofOptions_msginit)) ? ret : NULL; +} +UPB_INLINE char *google_protobuf_OneofOptions_serialize(const google_protobuf_OneofOptions *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &google_protobuf_OneofOptions_msginit, arena, len); +} + +UPB_INLINE const upb_array* google_protobuf_OneofOptions_uninterpreted_option(const google_protobuf_OneofOptions *msg) { return UPB_FIELD_AT(msg, const upb_array*, UPB_SIZE(0, 0)); } + +UPB_INLINE void google_protobuf_OneofOptions_set_uninterpreted_option(google_protobuf_OneofOptions *msg, upb_array* value) { UPB_FIELD_AT(msg, upb_array*, UPB_SIZE(0, 0)) = value; } + + +/* google.protobuf.EnumOptions */ + +extern const upb_msglayout google_protobuf_EnumOptions_msginit; +UPB_INLINE google_protobuf_EnumOptions *google_protobuf_EnumOptions_new(upb_arena *arena) { + return upb_msg_new(&google_protobuf_EnumOptions_msginit, arena); +} +UPB_INLINE google_protobuf_EnumOptions *google_protobuf_EnumOptions_parsenew(upb_stringview buf, upb_arena *arena) { + google_protobuf_EnumOptions *ret = google_protobuf_EnumOptions_new(arena); + return (ret && upb_decode(buf, ret, &google_protobuf_EnumOptions_msginit)) ? ret : NULL; +} +UPB_INLINE char *google_protobuf_EnumOptions_serialize(const google_protobuf_EnumOptions *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &google_protobuf_EnumOptions_msginit, arena, len); +} + +UPB_INLINE bool google_protobuf_EnumOptions_allow_alias(const google_protobuf_EnumOptions *msg) { return UPB_FIELD_AT(msg, bool, UPB_SIZE(1, 1)); } +UPB_INLINE bool google_protobuf_EnumOptions_deprecated(const google_protobuf_EnumOptions *msg) { return UPB_FIELD_AT(msg, bool, UPB_SIZE(2, 2)); } +UPB_INLINE const upb_array* google_protobuf_EnumOptions_uninterpreted_option(const google_protobuf_EnumOptions *msg) { return UPB_FIELD_AT(msg, const upb_array*, UPB_SIZE(4, 8)); } + +UPB_INLINE void google_protobuf_EnumOptions_set_allow_alias(google_protobuf_EnumOptions *msg, bool value) { UPB_FIELD_AT(msg, bool, UPB_SIZE(1, 1)) = value; } +UPB_INLINE void google_protobuf_EnumOptions_set_deprecated(google_protobuf_EnumOptions *msg, bool value) { UPB_FIELD_AT(msg, bool, UPB_SIZE(2, 2)) = value; } +UPB_INLINE void google_protobuf_EnumOptions_set_uninterpreted_option(google_protobuf_EnumOptions *msg, upb_array* value) { UPB_FIELD_AT(msg, upb_array*, UPB_SIZE(4, 8)) = value; } + + +/* google.protobuf.EnumValueOptions */ + +extern const upb_msglayout google_protobuf_EnumValueOptions_msginit; +UPB_INLINE google_protobuf_EnumValueOptions *google_protobuf_EnumValueOptions_new(upb_arena *arena) { + return upb_msg_new(&google_protobuf_EnumValueOptions_msginit, arena); +} +UPB_INLINE google_protobuf_EnumValueOptions *google_protobuf_EnumValueOptions_parsenew(upb_stringview buf, upb_arena *arena) { + google_protobuf_EnumValueOptions *ret = google_protobuf_EnumValueOptions_new(arena); + return (ret && upb_decode(buf, ret, &google_protobuf_EnumValueOptions_msginit)) ? ret : NULL; +} +UPB_INLINE char *google_protobuf_EnumValueOptions_serialize(const google_protobuf_EnumValueOptions *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &google_protobuf_EnumValueOptions_msginit, arena, len); +} + +UPB_INLINE bool google_protobuf_EnumValueOptions_deprecated(const google_protobuf_EnumValueOptions *msg) { return UPB_FIELD_AT(msg, bool, UPB_SIZE(1, 1)); } +UPB_INLINE const upb_array* google_protobuf_EnumValueOptions_uninterpreted_option(const google_protobuf_EnumValueOptions *msg) { return UPB_FIELD_AT(msg, const upb_array*, UPB_SIZE(4, 8)); } + +UPB_INLINE void google_protobuf_EnumValueOptions_set_deprecated(google_protobuf_EnumValueOptions *msg, bool value) { UPB_FIELD_AT(msg, bool, UPB_SIZE(1, 1)) = value; } +UPB_INLINE void google_protobuf_EnumValueOptions_set_uninterpreted_option(google_protobuf_EnumValueOptions *msg, upb_array* value) { UPB_FIELD_AT(msg, upb_array*, UPB_SIZE(4, 8)) = value; } + + +/* google.protobuf.ServiceOptions */ + +extern const upb_msglayout google_protobuf_ServiceOptions_msginit; +UPB_INLINE google_protobuf_ServiceOptions *google_protobuf_ServiceOptions_new(upb_arena *arena) { + return upb_msg_new(&google_protobuf_ServiceOptions_msginit, arena); +} +UPB_INLINE google_protobuf_ServiceOptions *google_protobuf_ServiceOptions_parsenew(upb_stringview buf, upb_arena *arena) { + google_protobuf_ServiceOptions *ret = google_protobuf_ServiceOptions_new(arena); + return (ret && upb_decode(buf, ret, &google_protobuf_ServiceOptions_msginit)) ? ret : NULL; +} +UPB_INLINE char *google_protobuf_ServiceOptions_serialize(const google_protobuf_ServiceOptions *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &google_protobuf_ServiceOptions_msginit, arena, len); +} + +UPB_INLINE bool google_protobuf_ServiceOptions_deprecated(const google_protobuf_ServiceOptions *msg) { return UPB_FIELD_AT(msg, bool, UPB_SIZE(1, 1)); } +UPB_INLINE const upb_array* google_protobuf_ServiceOptions_uninterpreted_option(const google_protobuf_ServiceOptions *msg) { return UPB_FIELD_AT(msg, const upb_array*, UPB_SIZE(4, 8)); } + +UPB_INLINE void google_protobuf_ServiceOptions_set_deprecated(google_protobuf_ServiceOptions *msg, bool value) { UPB_FIELD_AT(msg, bool, UPB_SIZE(1, 1)) = value; } +UPB_INLINE void google_protobuf_ServiceOptions_set_uninterpreted_option(google_protobuf_ServiceOptions *msg, upb_array* value) { UPB_FIELD_AT(msg, upb_array*, UPB_SIZE(4, 8)) = value; } + + +/* google.protobuf.MethodOptions */ + +extern const upb_msglayout google_protobuf_MethodOptions_msginit; +UPB_INLINE google_protobuf_MethodOptions *google_protobuf_MethodOptions_new(upb_arena *arena) { + return upb_msg_new(&google_protobuf_MethodOptions_msginit, arena); +} +UPB_INLINE google_protobuf_MethodOptions *google_protobuf_MethodOptions_parsenew(upb_stringview buf, upb_arena *arena) { + google_protobuf_MethodOptions *ret = google_protobuf_MethodOptions_new(arena); + return (ret && upb_decode(buf, ret, &google_protobuf_MethodOptions_msginit)) ? ret : NULL; +} +UPB_INLINE char *google_protobuf_MethodOptions_serialize(const google_protobuf_MethodOptions *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &google_protobuf_MethodOptions_msginit, arena, len); +} + +UPB_INLINE bool google_protobuf_MethodOptions_deprecated(const google_protobuf_MethodOptions *msg) { return UPB_FIELD_AT(msg, bool, UPB_SIZE(16, 16)); } +UPB_INLINE google_protobuf_MethodOptions_IdempotencyLevel google_protobuf_MethodOptions_idempotency_level(const google_protobuf_MethodOptions *msg) { return UPB_FIELD_AT(msg, google_protobuf_MethodOptions_IdempotencyLevel, UPB_SIZE(8, 8)); } +UPB_INLINE const upb_array* google_protobuf_MethodOptions_uninterpreted_option(const google_protobuf_MethodOptions *msg) { return UPB_FIELD_AT(msg, const upb_array*, UPB_SIZE(20, 24)); } + +UPB_INLINE void google_protobuf_MethodOptions_set_deprecated(google_protobuf_MethodOptions *msg, bool value) { UPB_FIELD_AT(msg, bool, UPB_SIZE(16, 16)) = value; } +UPB_INLINE void google_protobuf_MethodOptions_set_idempotency_level(google_protobuf_MethodOptions *msg, google_protobuf_MethodOptions_IdempotencyLevel value) { UPB_FIELD_AT(msg, google_protobuf_MethodOptions_IdempotencyLevel, UPB_SIZE(8, 8)) = value; } +UPB_INLINE void google_protobuf_MethodOptions_set_uninterpreted_option(google_protobuf_MethodOptions *msg, upb_array* value) { UPB_FIELD_AT(msg, upb_array*, UPB_SIZE(20, 24)) = value; } + + +/* google.protobuf.UninterpretedOption */ + +extern const upb_msglayout google_protobuf_UninterpretedOption_msginit; +UPB_INLINE google_protobuf_UninterpretedOption *google_protobuf_UninterpretedOption_new(upb_arena *arena) { + return upb_msg_new(&google_protobuf_UninterpretedOption_msginit, arena); +} +UPB_INLINE google_protobuf_UninterpretedOption *google_protobuf_UninterpretedOption_parsenew(upb_stringview buf, upb_arena *arena) { + google_protobuf_UninterpretedOption *ret = google_protobuf_UninterpretedOption_new(arena); + return (ret && upb_decode(buf, ret, &google_protobuf_UninterpretedOption_msginit)) ? ret : NULL; +} +UPB_INLINE char *google_protobuf_UninterpretedOption_serialize(const google_protobuf_UninterpretedOption *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &google_protobuf_UninterpretedOption_msginit, arena, len); +} + +UPB_INLINE const upb_array* google_protobuf_UninterpretedOption_name(const google_protobuf_UninterpretedOption *msg) { return UPB_FIELD_AT(msg, const upb_array*, UPB_SIZE(56, 80)); } +UPB_INLINE upb_stringview google_protobuf_UninterpretedOption_identifier_value(const google_protobuf_UninterpretedOption *msg) { return UPB_FIELD_AT(msg, upb_stringview, UPB_SIZE(32, 32)); } +UPB_INLINE uint64_t google_protobuf_UninterpretedOption_positive_int_value(const google_protobuf_UninterpretedOption *msg) { return UPB_FIELD_AT(msg, uint64_t, UPB_SIZE(8, 8)); } +UPB_INLINE int64_t google_protobuf_UninterpretedOption_negative_int_value(const google_protobuf_UninterpretedOption *msg) { return UPB_FIELD_AT(msg, int64_t, UPB_SIZE(16, 16)); } +UPB_INLINE double google_protobuf_UninterpretedOption_double_value(const google_protobuf_UninterpretedOption *msg) { return UPB_FIELD_AT(msg, double, UPB_SIZE(24, 24)); } +UPB_INLINE upb_stringview google_protobuf_UninterpretedOption_string_value(const google_protobuf_UninterpretedOption *msg) { return UPB_FIELD_AT(msg, upb_stringview, UPB_SIZE(40, 48)); } +UPB_INLINE upb_stringview google_protobuf_UninterpretedOption_aggregate_value(const google_protobuf_UninterpretedOption *msg) { return UPB_FIELD_AT(msg, upb_stringview, UPB_SIZE(48, 64)); } + +UPB_INLINE void google_protobuf_UninterpretedOption_set_name(google_protobuf_UninterpretedOption *msg, upb_array* value) { UPB_FIELD_AT(msg, upb_array*, UPB_SIZE(56, 80)) = value; } +UPB_INLINE void google_protobuf_UninterpretedOption_set_identifier_value(google_protobuf_UninterpretedOption *msg, upb_stringview value) { UPB_FIELD_AT(msg, upb_stringview, UPB_SIZE(32, 32)) = value; } +UPB_INLINE void google_protobuf_UninterpretedOption_set_positive_int_value(google_protobuf_UninterpretedOption *msg, uint64_t value) { UPB_FIELD_AT(msg, uint64_t, UPB_SIZE(8, 8)) = value; } +UPB_INLINE void google_protobuf_UninterpretedOption_set_negative_int_value(google_protobuf_UninterpretedOption *msg, int64_t value) { UPB_FIELD_AT(msg, int64_t, UPB_SIZE(16, 16)) = value; } +UPB_INLINE void google_protobuf_UninterpretedOption_set_double_value(google_protobuf_UninterpretedOption *msg, double value) { UPB_FIELD_AT(msg, double, UPB_SIZE(24, 24)) = value; } +UPB_INLINE void google_protobuf_UninterpretedOption_set_string_value(google_protobuf_UninterpretedOption *msg, upb_stringview value) { UPB_FIELD_AT(msg, upb_stringview, UPB_SIZE(40, 48)) = value; } +UPB_INLINE void google_protobuf_UninterpretedOption_set_aggregate_value(google_protobuf_UninterpretedOption *msg, upb_stringview value) { UPB_FIELD_AT(msg, upb_stringview, UPB_SIZE(48, 64)) = value; } + + +/* google.protobuf.UninterpretedOption.NamePart */ + +extern const upb_msglayout google_protobuf_UninterpretedOption_NamePart_msginit; +UPB_INLINE google_protobuf_UninterpretedOption_NamePart *google_protobuf_UninterpretedOption_NamePart_new(upb_arena *arena) { + return upb_msg_new(&google_protobuf_UninterpretedOption_NamePart_msginit, arena); +} +UPB_INLINE google_protobuf_UninterpretedOption_NamePart *google_protobuf_UninterpretedOption_NamePart_parsenew(upb_stringview buf, upb_arena *arena) { + google_protobuf_UninterpretedOption_NamePart *ret = google_protobuf_UninterpretedOption_NamePart_new(arena); + return (ret && upb_decode(buf, ret, &google_protobuf_UninterpretedOption_NamePart_msginit)) ? ret : NULL; +} +UPB_INLINE char *google_protobuf_UninterpretedOption_NamePart_serialize(const google_protobuf_UninterpretedOption_NamePart *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &google_protobuf_UninterpretedOption_NamePart_msginit, arena, len); +} + +UPB_INLINE upb_stringview google_protobuf_UninterpretedOption_NamePart_name_part(const google_protobuf_UninterpretedOption_NamePart *msg) { return UPB_FIELD_AT(msg, upb_stringview, UPB_SIZE(8, 16)); } +UPB_INLINE bool google_protobuf_UninterpretedOption_NamePart_is_extension(const google_protobuf_UninterpretedOption_NamePart *msg) { return UPB_FIELD_AT(msg, bool, UPB_SIZE(1, 1)); } + +UPB_INLINE void google_protobuf_UninterpretedOption_NamePart_set_name_part(google_protobuf_UninterpretedOption_NamePart *msg, upb_stringview value) { UPB_FIELD_AT(msg, upb_stringview, UPB_SIZE(8, 16)) = value; } +UPB_INLINE void google_protobuf_UninterpretedOption_NamePart_set_is_extension(google_protobuf_UninterpretedOption_NamePart *msg, bool value) { UPB_FIELD_AT(msg, bool, UPB_SIZE(1, 1)) = value; } + + +/* google.protobuf.SourceCodeInfo */ + +extern const upb_msglayout google_protobuf_SourceCodeInfo_msginit; +UPB_INLINE google_protobuf_SourceCodeInfo *google_protobuf_SourceCodeInfo_new(upb_arena *arena) { + return upb_msg_new(&google_protobuf_SourceCodeInfo_msginit, arena); +} +UPB_INLINE google_protobuf_SourceCodeInfo *google_protobuf_SourceCodeInfo_parsenew(upb_stringview buf, upb_arena *arena) { + google_protobuf_SourceCodeInfo *ret = google_protobuf_SourceCodeInfo_new(arena); + return (ret && upb_decode(buf, ret, &google_protobuf_SourceCodeInfo_msginit)) ? ret : NULL; +} +UPB_INLINE char *google_protobuf_SourceCodeInfo_serialize(const google_protobuf_SourceCodeInfo *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &google_protobuf_SourceCodeInfo_msginit, arena, len); +} + +UPB_INLINE const upb_array* google_protobuf_SourceCodeInfo_location(const google_protobuf_SourceCodeInfo *msg) { return UPB_FIELD_AT(msg, const upb_array*, UPB_SIZE(0, 0)); } + +UPB_INLINE void google_protobuf_SourceCodeInfo_set_location(google_protobuf_SourceCodeInfo *msg, upb_array* value) { UPB_FIELD_AT(msg, upb_array*, UPB_SIZE(0, 0)) = value; } + + +/* google.protobuf.SourceCodeInfo.Location */ + +extern const upb_msglayout google_protobuf_SourceCodeInfo_Location_msginit; +UPB_INLINE google_protobuf_SourceCodeInfo_Location *google_protobuf_SourceCodeInfo_Location_new(upb_arena *arena) { + return upb_msg_new(&google_protobuf_SourceCodeInfo_Location_msginit, arena); +} +UPB_INLINE google_protobuf_SourceCodeInfo_Location *google_protobuf_SourceCodeInfo_Location_parsenew(upb_stringview buf, upb_arena *arena) { + google_protobuf_SourceCodeInfo_Location *ret = google_protobuf_SourceCodeInfo_Location_new(arena); + return (ret && upb_decode(buf, ret, &google_protobuf_SourceCodeInfo_Location_msginit)) ? ret : NULL; +} +UPB_INLINE char *google_protobuf_SourceCodeInfo_Location_serialize(const google_protobuf_SourceCodeInfo_Location *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &google_protobuf_SourceCodeInfo_Location_msginit, arena, len); +} + +UPB_INLINE const upb_array* google_protobuf_SourceCodeInfo_Location_path(const google_protobuf_SourceCodeInfo_Location *msg) { return UPB_FIELD_AT(msg, const upb_array*, UPB_SIZE(24, 48)); } +UPB_INLINE const upb_array* google_protobuf_SourceCodeInfo_Location_span(const google_protobuf_SourceCodeInfo_Location *msg) { return UPB_FIELD_AT(msg, const upb_array*, UPB_SIZE(28, 56)); } +UPB_INLINE upb_stringview google_protobuf_SourceCodeInfo_Location_leading_comments(const google_protobuf_SourceCodeInfo_Location *msg) { return UPB_FIELD_AT(msg, upb_stringview, UPB_SIZE(8, 16)); } +UPB_INLINE upb_stringview google_protobuf_SourceCodeInfo_Location_trailing_comments(const google_protobuf_SourceCodeInfo_Location *msg) { return UPB_FIELD_AT(msg, upb_stringview, UPB_SIZE(16, 32)); } +UPB_INLINE const upb_array* google_protobuf_SourceCodeInfo_Location_leading_detached_comments(const google_protobuf_SourceCodeInfo_Location *msg) { return UPB_FIELD_AT(msg, const upb_array*, UPB_SIZE(32, 64)); } + +UPB_INLINE void google_protobuf_SourceCodeInfo_Location_set_path(google_protobuf_SourceCodeInfo_Location *msg, upb_array* value) { UPB_FIELD_AT(msg, upb_array*, UPB_SIZE(24, 48)) = value; } +UPB_INLINE void google_protobuf_SourceCodeInfo_Location_set_span(google_protobuf_SourceCodeInfo_Location *msg, upb_array* value) { UPB_FIELD_AT(msg, upb_array*, UPB_SIZE(28, 56)) = value; } +UPB_INLINE void google_protobuf_SourceCodeInfo_Location_set_leading_comments(google_protobuf_SourceCodeInfo_Location *msg, upb_stringview value) { UPB_FIELD_AT(msg, upb_stringview, UPB_SIZE(8, 16)) = value; } +UPB_INLINE void google_protobuf_SourceCodeInfo_Location_set_trailing_comments(google_protobuf_SourceCodeInfo_Location *msg, upb_stringview value) { UPB_FIELD_AT(msg, upb_stringview, UPB_SIZE(16, 32)) = value; } +UPB_INLINE void google_protobuf_SourceCodeInfo_Location_set_leading_detached_comments(google_protobuf_SourceCodeInfo_Location *msg, upb_array* value) { UPB_FIELD_AT(msg, upb_array*, UPB_SIZE(32, 64)) = value; } + + +/* google.protobuf.GeneratedCodeInfo */ + +extern const upb_msglayout google_protobuf_GeneratedCodeInfo_msginit; +UPB_INLINE google_protobuf_GeneratedCodeInfo *google_protobuf_GeneratedCodeInfo_new(upb_arena *arena) { + return upb_msg_new(&google_protobuf_GeneratedCodeInfo_msginit, arena); +} +UPB_INLINE google_protobuf_GeneratedCodeInfo *google_protobuf_GeneratedCodeInfo_parsenew(upb_stringview buf, upb_arena *arena) { + google_protobuf_GeneratedCodeInfo *ret = google_protobuf_GeneratedCodeInfo_new(arena); + return (ret && upb_decode(buf, ret, &google_protobuf_GeneratedCodeInfo_msginit)) ? ret : NULL; +} +UPB_INLINE char *google_protobuf_GeneratedCodeInfo_serialize(const google_protobuf_GeneratedCodeInfo *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &google_protobuf_GeneratedCodeInfo_msginit, arena, len); +} + +UPB_INLINE const upb_array* google_protobuf_GeneratedCodeInfo_annotation(const google_protobuf_GeneratedCodeInfo *msg) { return UPB_FIELD_AT(msg, const upb_array*, UPB_SIZE(0, 0)); } + +UPB_INLINE void google_protobuf_GeneratedCodeInfo_set_annotation(google_protobuf_GeneratedCodeInfo *msg, upb_array* value) { UPB_FIELD_AT(msg, upb_array*, UPB_SIZE(0, 0)) = value; } + + +/* google.protobuf.GeneratedCodeInfo.Annotation */ + +extern const upb_msglayout google_protobuf_GeneratedCodeInfo_Annotation_msginit; +UPB_INLINE google_protobuf_GeneratedCodeInfo_Annotation *google_protobuf_GeneratedCodeInfo_Annotation_new(upb_arena *arena) { + return upb_msg_new(&google_protobuf_GeneratedCodeInfo_Annotation_msginit, arena); +} +UPB_INLINE google_protobuf_GeneratedCodeInfo_Annotation *google_protobuf_GeneratedCodeInfo_Annotation_parsenew(upb_stringview buf, upb_arena *arena) { + google_protobuf_GeneratedCodeInfo_Annotation *ret = google_protobuf_GeneratedCodeInfo_Annotation_new(arena); + return (ret && upb_decode(buf, ret, &google_protobuf_GeneratedCodeInfo_Annotation_msginit)) ? ret : NULL; +} +UPB_INLINE char *google_protobuf_GeneratedCodeInfo_Annotation_serialize(const google_protobuf_GeneratedCodeInfo_Annotation *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &google_protobuf_GeneratedCodeInfo_Annotation_msginit, arena, len); +} + +UPB_INLINE const upb_array* google_protobuf_GeneratedCodeInfo_Annotation_path(const google_protobuf_GeneratedCodeInfo_Annotation *msg) { return UPB_FIELD_AT(msg, const upb_array*, UPB_SIZE(24, 32)); } +UPB_INLINE upb_stringview google_protobuf_GeneratedCodeInfo_Annotation_source_file(const google_protobuf_GeneratedCodeInfo_Annotation *msg) { return UPB_FIELD_AT(msg, upb_stringview, UPB_SIZE(16, 16)); } +UPB_INLINE int32_t google_protobuf_GeneratedCodeInfo_Annotation_begin(const google_protobuf_GeneratedCodeInfo_Annotation *msg) { return UPB_FIELD_AT(msg, int32_t, UPB_SIZE(4, 4)); } +UPB_INLINE int32_t google_protobuf_GeneratedCodeInfo_Annotation_end(const google_protobuf_GeneratedCodeInfo_Annotation *msg) { return UPB_FIELD_AT(msg, int32_t, UPB_SIZE(8, 8)); } + +UPB_INLINE void google_protobuf_GeneratedCodeInfo_Annotation_set_path(google_protobuf_GeneratedCodeInfo_Annotation *msg, upb_array* value) { UPB_FIELD_AT(msg, upb_array*, UPB_SIZE(24, 32)) = value; } +UPB_INLINE void google_protobuf_GeneratedCodeInfo_Annotation_set_source_file(google_protobuf_GeneratedCodeInfo_Annotation *msg, upb_stringview value) { UPB_FIELD_AT(msg, upb_stringview, UPB_SIZE(16, 16)) = value; } +UPB_INLINE void google_protobuf_GeneratedCodeInfo_Annotation_set_begin(google_protobuf_GeneratedCodeInfo_Annotation *msg, int32_t value) { UPB_FIELD_AT(msg, int32_t, UPB_SIZE(4, 4)) = value; } +UPB_INLINE void google_protobuf_GeneratedCodeInfo_Annotation_set_end(google_protobuf_GeneratedCodeInfo_Annotation *msg, int32_t value) { UPB_FIELD_AT(msg, int32_t, UPB_SIZE(8, 8)) = value; } + + +UPB_END_EXTERN_C + + +#endif /* GOOGLE_PROTOBUF_DESCRIPTOR_PROTO_UPB_H_ */ /* ** structs.int.h: structures definitions that are internal to upb. */ @@ -6799,7 +7593,7 @@ struct upb_array { void *data; /* Each element is element_size. */ size_t len; /* Measured in elements. */ size_t size; /* Measured in elements. */ - upb_alloc *alloc; + upb_arena *arena; }; #endif /* UPB_STRUCTS_H_ */ @@ -6920,6 +7714,10 @@ struct upb_msgdef { /* Whether this message has proto2 or proto3 semantics. */ upb_syntax_t syntax; + /* Type of well known type message. UPB_WELLKNOWN_UNSPECIFIED for + * non-well-known message. */ + upb_wellknowntype_t well_known_type; + /* TODO(haberman): proper extension ranges (there can be multiple). */ }; @@ -6928,10 +7726,11 @@ extern const struct upb_refcounted_vtbl upb_msgdef_vtbl; /* TODO: also support static initialization of the oneofs table. This will be * needed if we compile in descriptors that contain oneofs. */ #define UPB_MSGDEF_INIT(name, selector_count, submsg_field_count, itof, ntof, \ - map_entry, syntax, refs, ref2s) \ + map_entry, syntax, well_known_type, refs, ref2s) \ { \ UPB_DEF_INIT(name, UPB_DEF_MSG, &upb_fielddef_vtbl, refs, ref2s), \ - selector_count, submsg_field_count, itof, ntof, map_entry, syntax \ + selector_count, submsg_field_count, itof, ntof, map_entry, syntax, \ + well_known_type \ } @@ -6994,22 +7793,44 @@ struct upb_filedef { extern const struct upb_refcounted_vtbl upb_filedef_vtbl; #endif /* UPB_STATICINIT_H_ */ -/* -** upb_encode: parsing into a upb_msg using a upb_msglayout. -*/ -#ifndef UPB_ENCODE_H_ -#define UPB_ENCODE_H_ +#ifndef UPB_MSGFACTORY_H_ +#define UPB_MSGFACTORY_H_ -UPB_BEGIN_EXTERN_C +UPB_DECLARE_TYPE(upb::MessageFactory, upb_msgfactory) -char *upb_encode(const void *msg, const upb_msglayout_msginit_v1 *l, - upb_env *env, size_t *size); +/** upb_msgfactory ************************************************************/ -UPB_END_EXTERN_C +/* A upb_msgfactory contains a cache of upb_msglayout, upb_handlers, and + * upb_visitorplan objects. These are the objects necessary to represent, + * populate, and and visit upb_msg objects. + * + * These caches are all populated by upb_msgdef, and lazily created on demand. + */ -#endif /* UPB_ENCODE_H_ */ +/* Creates and destroys a msgfactory, respectively. The messages for this + * msgfactory must come from |symtab| (which should outlive the msgfactory). */ +upb_msgfactory *upb_msgfactory_new(const upb_symtab *symtab); +void upb_msgfactory_free(upb_msgfactory *f); + +const upb_symtab *upb_msgfactory_symtab(const upb_msgfactory *f); + +/* The functions to get cached objects, lazily creating them on demand. These + * all require: + * + * - m is in upb_msgfactory_symtab(f) + * - upb_msgdef_mapentry(m) == false (since map messages can't have layouts). + * + * The returned objects will live for as long as the msgfactory does. + * + * TODO(haberman): consider making this thread-safe and take a const + * upb_msgfactory. */ +const upb_msglayout *upb_msgfactory_getlayout(upb_msgfactory *f, + const upb_msgdef *m); + + +#endif /* UPB_MSGFACTORY_H_ */ /* ** upb::descriptor::Reader (upb_descreader) ** @@ -7112,53 +7933,6 @@ inline FileDef* Reader::file(size_t i) const { UPB_BEGIN_EXTERN_C -/* Enums */ - -typedef enum { - google_protobuf_FieldDescriptorProto_LABEL_OPTIONAL = 1, - google_protobuf_FieldDescriptorProto_LABEL_REQUIRED = 2, - google_protobuf_FieldDescriptorProto_LABEL_REPEATED = 3 -} google_protobuf_FieldDescriptorProto_Label; - -typedef enum { - google_protobuf_FieldDescriptorProto_TYPE_DOUBLE = 1, - google_protobuf_FieldDescriptorProto_TYPE_FLOAT = 2, - google_protobuf_FieldDescriptorProto_TYPE_INT64 = 3, - google_protobuf_FieldDescriptorProto_TYPE_UINT64 = 4, - google_protobuf_FieldDescriptorProto_TYPE_INT32 = 5, - google_protobuf_FieldDescriptorProto_TYPE_FIXED64 = 6, - google_protobuf_FieldDescriptorProto_TYPE_FIXED32 = 7, - google_protobuf_FieldDescriptorProto_TYPE_BOOL = 8, - google_protobuf_FieldDescriptorProto_TYPE_STRING = 9, - google_protobuf_FieldDescriptorProto_TYPE_GROUP = 10, - google_protobuf_FieldDescriptorProto_TYPE_MESSAGE = 11, - google_protobuf_FieldDescriptorProto_TYPE_BYTES = 12, - google_protobuf_FieldDescriptorProto_TYPE_UINT32 = 13, - google_protobuf_FieldDescriptorProto_TYPE_ENUM = 14, - google_protobuf_FieldDescriptorProto_TYPE_SFIXED32 = 15, - google_protobuf_FieldDescriptorProto_TYPE_SFIXED64 = 16, - google_protobuf_FieldDescriptorProto_TYPE_SINT32 = 17, - google_protobuf_FieldDescriptorProto_TYPE_SINT64 = 18 -} google_protobuf_FieldDescriptorProto_Type; - -typedef enum { - google_protobuf_FieldOptions_STRING = 0, - google_protobuf_FieldOptions_CORD = 1, - google_protobuf_FieldOptions_STRING_PIECE = 2 -} google_protobuf_FieldOptions_CType; - -typedef enum { - google_protobuf_FieldOptions_JS_NORMAL = 0, - google_protobuf_FieldOptions_JS_STRING = 1, - google_protobuf_FieldOptions_JS_NUMBER = 2 -} google_protobuf_FieldOptions_JSType; - -typedef enum { - google_protobuf_FileOptions_SPEED = 1, - google_protobuf_FileOptions_CODE_SIZE = 2, - google_protobuf_FileOptions_LITE_RUNTIME = 3 -} google_protobuf_FileOptions_OptimizeMode; - /* MessageDefs: call these functions to get a ref to a msgdef. */ const upb_msgdef *upbdefs_google_protobuf_DescriptorProto_get(const void *owner); const upb_msgdef *upbdefs_google_protobuf_DescriptorProto_ExtensionRange_get(const void *owner); @@ -8793,7 +9567,7 @@ UPB_DECLARE_DERIVED_TYPE(upb::json::ParserMethod, upb::RefCounted, * constructed. This hint may be an overestimate for some build configurations. * But if the parser library is upgraded without recompiling the application, * it may be an underestimate. */ -#define UPB_JSON_PARSER_SIZE 4112 +#define UPB_JSON_PARSER_SIZE 4160 #ifdef __cplusplus @@ -8802,7 +9576,7 @@ UPB_DECLARE_DERIVED_TYPE(upb::json::ParserMethod, upb::RefCounted, class upb::json::Parser { public: static Parser* Create(Environment* env, const ParserMethod* method, - Sink* output); + Sink* output, bool ignore_json_unknown); BytesSink* input(); @@ -8836,7 +9610,8 @@ UPB_BEGIN_EXTERN_C upb_json_parser* upb_json_parser_create(upb_env* e, const upb_json_parsermethod* m, - upb_sink* output); + upb_sink* output, + bool ignore_json_unknown); upb_bytessink *upb_json_parser_input(upb_json_parser *p); upb_json_parsermethod* upb_json_parsermethod_new(const upb_msgdef* md, @@ -8856,8 +9631,8 @@ UPB_END_EXTERN_C namespace upb { namespace json { inline Parser* Parser::Create(Environment* env, const ParserMethod* method, - Sink* output) { - return upb_json_parser_create(env, method, output); + Sink* output, bool ignore_json_unknown) { + return upb_json_parser_create(env, method, output, ignore_json_unknown); } inline BytesSink* Parser::input() { return upb_json_parser_input(this); @@ -8906,7 +9681,7 @@ UPB_DECLARE_TYPE(upb::json::Printer, upb_json_printer) /* upb::json::Printer *********************************************************/ -#define UPB_JSON_PRINTER_SIZE 176 +#define UPB_JSON_PRINTER_SIZE 192 #ifdef __cplusplus @@ -8967,3 +9742,8 @@ inline reffed_ptr Printer::NewHandlers( #endif #endif /* UPB_JSON_TYPED_PRINTER_H_ */ + +#undef UPB_SIZE +#undef UPB_FIELD_AT +#undef UPB_READ_ONEOF +#undef UPB_WRITE_ONEOF diff --git a/ruby/lib/google/protobuf.rb b/ruby/lib/google/protobuf.rb index e20a584e80..464982e303 100644 --- a/ruby/lib/google/protobuf.rb +++ b/ruby/lib/google/protobuf.rb @@ -69,8 +69,8 @@ module Google klass.decode(proto) end - def self.decode_json(klass, json) - klass.decode_json(json) + def self.decode_json(klass, json, options = {}) + klass.decode_json(json, options) end end diff --git a/ruby/tests/basic.rb b/ruby/tests/basic.rb index 77dfead404..5e17bef65b 100644 --- a/ruby/tests/basic.rb +++ b/ruby/tests/basic.rb @@ -254,6 +254,19 @@ module BasicTest "b" => TestMessage2.new(:foo => 2)} end + def test_protobuf_decode_json_ignore_unknown_fields + m = TestMessage.decode_json({ + optional_string: "foo", + not_in_message: "some_value" + }.to_json, { ignore_unknown_fields: true }) + + assert_equal m.optional_string, "foo" + e = assert_raise Google::Protobuf::ParseError do + TestMessage.decode_json({ not_in_message: "some_value" }.to_json) + end + assert_match(/No such field: not_in_message/, e.message) + end + def test_to_h m = TestMessage.new(:optional_bool => true, :optional_double => -10.100001, :optional_string => 'foo', :repeated_string => ['bar1', 'bar2'], :repeated_msg => [TestMessage2.new(:foo => 100)]) expected_result = {