From a2cbd5a8246e7203b27cb938bc170c29e33269ec Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Mon, 6 Apr 2020 16:40:50 +0200 Subject: [PATCH 01/38] serialization benchmark improvements --- ...ionConfig.cs => BenchmarkDatasetConfig.cs} | 14 ++++---- ...Benchmark.cs => GoogleMessageBenchmark.cs} | 32 +++++++++++-------- 2 files changed, 25 insertions(+), 21 deletions(-) rename csharp/src/Google.Protobuf.Benchmarks/{SerializationConfig.cs => BenchmarkDatasetConfig.cs} (89%) rename csharp/src/Google.Protobuf.Benchmarks/{SerializationBenchmark.cs => GoogleMessageBenchmark.cs} (74%) diff --git a/csharp/src/Google.Protobuf.Benchmarks/SerializationConfig.cs b/csharp/src/Google.Protobuf.Benchmarks/BenchmarkDatasetConfig.cs similarity index 89% rename from csharp/src/Google.Protobuf.Benchmarks/SerializationConfig.cs rename to csharp/src/Google.Protobuf.Benchmarks/BenchmarkDatasetConfig.cs index 679f16cb9a..c0754190b6 100644 --- a/csharp/src/Google.Protobuf.Benchmarks/SerializationConfig.cs +++ b/csharp/src/Google.Protobuf.Benchmarks/BenchmarkDatasetConfig.cs @@ -43,20 +43,20 @@ namespace Google.Protobuf.Benchmarks /// /// The configuration for a single serialization test, loaded from a dataset. /// - public class SerializationConfig + public class BenchmarkDatasetConfig { private static readonly Dictionary parsersByMessageName = - typeof(SerializationBenchmark).Assembly.GetTypes() + typeof(GoogleMessageBenchmark).Assembly.GetTypes() .Where(t => typeof(IMessage).IsAssignableFrom(t)) .ToDictionary( t => ((MessageDescriptor) t.GetProperty("Descriptor", BindingFlags.Static | BindingFlags.Public).GetValue(null)).FullName, t => ((MessageParser) t.GetProperty("Parser", BindingFlags.Static | BindingFlags.Public).GetValue(null))); public MessageParser Parser { get; } - public IEnumerable Payloads { get; } + public List Payloads { get; } public string Name { get; } - public SerializationConfig(string resource) + public BenchmarkDatasetConfig(string resource, string shortName = null) { var data = LoadData(resource); var dataset = BenchmarkDataset.Parser.ParseFrom(data); @@ -66,13 +66,13 @@ namespace Google.Protobuf.Benchmarks throw new ArgumentException($"No parser for message {dataset.MessageName} in this assembly"); } Parser = parser; - Payloads = dataset.Payload; - Name = dataset.Name; + Payloads = new List(dataset.Payload.Select(p => p.ToByteArray())); + Name = shortName ?? dataset.Name; } private static byte[] LoadData(string resource) { - using (var stream = typeof(SerializationBenchmark).Assembly.GetManifestResourceStream($"Google.Protobuf.Benchmarks.{resource}")) + using (var stream = typeof(GoogleMessageBenchmark).Assembly.GetManifestResourceStream($"Google.Protobuf.Benchmarks.{resource}")) { if (stream == null) { diff --git a/csharp/src/Google.Protobuf.Benchmarks/SerializationBenchmark.cs b/csharp/src/Google.Protobuf.Benchmarks/GoogleMessageBenchmark.cs similarity index 74% rename from csharp/src/Google.Protobuf.Benchmarks/SerializationBenchmark.cs rename to csharp/src/Google.Protobuf.Benchmarks/GoogleMessageBenchmark.cs index d8c2ec11d7..132967e00a 100644 --- a/csharp/src/Google.Protobuf.Benchmarks/SerializationBenchmark.cs +++ b/csharp/src/Google.Protobuf.Benchmarks/GoogleMessageBenchmark.cs @@ -38,23 +38,27 @@ using System.Linq; namespace Google.Protobuf.Benchmarks { /// - /// Benchmark for serializing (to a MemoryStream) and deserializing (from a ByteString). + /// Benchmark for serializing and deserializing of standard datasets that are also + /// measured by benchmarks in other languages. /// Over time we may wish to test the various different approaches to serialization and deserialization separately. + /// See https://github.com/protocolbuffers/protobuf/blob/master/benchmarks/README.md + /// See https://github.com/protocolbuffers/protobuf/blob/master/docs/performance.md /// [MemoryDiagnoser] - public class SerializationBenchmark + public class GoogleMessageBenchmark { /// - /// All the configurations to be tested. Add more datasets to the array as they're available. + /// All the datasets to be tested. Add more datasets to the array as they're available. /// (When C# supports proto2, this will increase significantly.) /// - public static SerializationConfig[] Configurations => new[] + public static BenchmarkDatasetConfig[] DatasetConfigurations => new[] { - new SerializationConfig("dataset.google_message1_proto3.pb") + // short name is specified to make results table more readable + new BenchmarkDatasetConfig("dataset.google_message1_proto3.pb", "goog_msg1_proto3") }; - [ParamsSource(nameof(Configurations))] - public SerializationConfig Configuration { get; set; } + [ParamsSource(nameof(DatasetConfigurations))] + public BenchmarkDatasetConfig Dataset { get; set; } private MessageParser parser; /// @@ -67,8 +71,8 @@ namespace Google.Protobuf.Benchmarks [GlobalSetup] public void GlobalSetup() { - parser = Configuration.Parser; - subTests = Configuration.Payloads.Select(p => new SubTest(p, parser.ParseFrom(p))).ToList(); + parser = Dataset.Parser; + subTests = Dataset.Payloads.Select(p => new SubTest(p, parser.ParseFrom(p))).ToList(); } [Benchmark] @@ -78,7 +82,7 @@ namespace Google.Protobuf.Benchmarks public void ToByteArray() => subTests.ForEach(item => item.ToByteArray()); [Benchmark] - public void ParseFromByteString() => subTests.ForEach(item => item.ParseFromByteString(parser)); + public void ParseFromByteArray() => subTests.ForEach(item => item.ParseFromByteArray(parser)); [Benchmark] public void ParseFromStream() => subTests.ForEach(item => item.ParseFromStream(parser)); @@ -87,13 +91,13 @@ namespace Google.Protobuf.Benchmarks { private readonly Stream destinationStream; private readonly Stream sourceStream; - private readonly ByteString data; + private readonly byte[] data; private readonly IMessage message; - public SubTest(ByteString data, IMessage message) + public SubTest(byte[] data, IMessage message) { destinationStream = new MemoryStream(data.Length); - sourceStream = new MemoryStream(data.ToByteArray()); + sourceStream = new MemoryStream(data); this.data = data; this.message = message; } @@ -108,7 +112,7 @@ namespace Google.Protobuf.Benchmarks public void ToByteArray() => message.ToByteArray(); - public void ParseFromByteString(MessageParser parser) => parser.ParseFrom(data); + public void ParseFromByteArray(MessageParser parser) => parser.ParseFrom(data); public void ParseFromStream(MessageParser parser) { From 79cfc73293e3c1d86af8937f3747e1ee1d015873 Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Mon, 6 Apr 2020 18:24:13 +0200 Subject: [PATCH 02/38] refactor WrapperBechmark --- ...Benchmark.cs => ParseMessagesBenchmark.cs} | 72 +++++++++++++++++-- 1 file changed, 67 insertions(+), 5 deletions(-) rename csharp/src/Google.Protobuf.Benchmarks/{WrapperBenchmark.cs => ParseMessagesBenchmark.cs} (59%) diff --git a/csharp/src/Google.Protobuf.Benchmarks/WrapperBenchmark.cs b/csharp/src/Google.Protobuf.Benchmarks/ParseMessagesBenchmark.cs similarity index 59% rename from csharp/src/Google.Protobuf.Benchmarks/WrapperBenchmark.cs rename to csharp/src/Google.Protobuf.Benchmarks/ParseMessagesBenchmark.cs index ae17c1819a..02310aac7e 100644 --- a/csharp/src/Google.Protobuf.Benchmarks/WrapperBenchmark.cs +++ b/csharp/src/Google.Protobuf.Benchmarks/ParseMessagesBenchmark.cs @@ -34,37 +34,87 @@ using BenchmarkDotNet.Attributes; using System.Collections.Generic; using System.IO; using System.Linq; +using System.Buffers; +using Google.Protobuf.WellKnownTypes; namespace Google.Protobuf.Benchmarks { /// - /// Benchmark that tests serialization/deserialization of wrapper fields. + /// Benchmark that tests parsing performance for various messages. /// [MemoryDiagnoser] - public class WrapperBenchmark + public class ParseMessagesBenchmark { + const int MaxMessages = 100; + byte[] manyWrapperFieldsData; byte[] manyPrimitiveFieldsData; + byte[] manyWrapperFieldsMultipleMessagesData; + byte[] manyPrimitiveFieldsMultipleMessagesData; + + byte[] emptyData = new byte[0]; + + public IEnumerable MessageCountValues => new[] { 10, 100 }; + [GlobalSetup] public void GlobalSetup() { manyWrapperFieldsData = CreateManyWrapperFieldsMessage().ToByteArray(); manyPrimitiveFieldsData = CreateManyPrimitiveFieldsMessage().ToByteArray(); + manyWrapperFieldsMultipleMessagesData = CreateBufferWithMultipleMessages(CreateManyWrapperFieldsMessage(), MaxMessages); + manyPrimitiveFieldsMultipleMessagesData = CreateBufferWithMultipleMessages(CreateManyPrimitiveFieldsMessage(), MaxMessages); } [Benchmark] - public ManyWrapperFieldsMessage ParseWrapperFields() + public ManyWrapperFieldsMessage ManyWrapperFieldsMessage_ParseFromByteArray() { return ManyWrapperFieldsMessage.Parser.ParseFrom(manyWrapperFieldsData); } [Benchmark] - public ManyPrimitiveFieldsMessage ParsePrimitiveFields() + public ManyPrimitiveFieldsMessage ManyPrimitiveFieldsMessage_ParseFromByteArray() { return ManyPrimitiveFieldsMessage.Parser.ParseFrom(manyPrimitiveFieldsData); } + [Benchmark] + public Empty EmptyMessage_ParseFromByteArray() + { + return Empty.Parser.ParseFrom(emptyData); + } + + [Benchmark] + [ArgumentsSource(nameof(MessageCountValues))] + public long ManyWrapperFieldsMessage_ParseDelimitedMessagesFromByteArray(int messageCount) + { + long sum = 0; + var input = new CodedInputStream(manyWrapperFieldsMultipleMessagesData); + for (int i = 0; i < messageCount; i++) + { + var msg = new ManyWrapperFieldsMessage(); + input.ReadMessage(msg); + sum += msg.Int64Field19.Value; + } + return sum; + } + + [Benchmark] + [ArgumentsSource(nameof(MessageCountValues))] + public long ManyPrimitiveFieldsMessage_ParseDelimitedMessagesFromByteArray(int messageCount) + { + long sum = 0; + var input = new CodedInputStream(manyPrimitiveFieldsMultipleMessagesData); + for (int i = 0; i < messageCount; i++) + { + var msg = new ManyPrimitiveFieldsMessage(); + input.ReadMessage(msg); + sum += msg.Int64Field19; + } + return sum; + } + + private static ManyWrapperFieldsMessage CreateManyWrapperFieldsMessage() { // Example data match data of an internal benchmarks @@ -98,5 +148,17 @@ namespace Google.Protobuf.Benchmarks DoubleField50 = 2.45 }; } + + private static byte[] CreateBufferWithMultipleMessages(IMessage msg, int msgCount) + { + var ms = new MemoryStream(); + var cos = new CodedOutputStream(ms); + for (int i = 0; i < msgCount; i++) + { + cos.WriteMessage(msg); + } + cos.Flush(); + return ms.ToArray(); + } } -} +} \ No newline at end of file From 4116e659843082e2544f83b362b0a16f1470b555 Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Tue, 7 Apr 2020 11:56:37 +0200 Subject: [PATCH 03/38] improve ParseMessageBenchmark maintainability --- .../ParseMessagesBenchmark.cs | 98 ++++++++++--------- 1 file changed, 52 insertions(+), 46 deletions(-) diff --git a/csharp/src/Google.Protobuf.Benchmarks/ParseMessagesBenchmark.cs b/csharp/src/Google.Protobuf.Benchmarks/ParseMessagesBenchmark.cs index 02310aac7e..cbc47328fa 100644 --- a/csharp/src/Google.Protobuf.Benchmarks/ParseMessagesBenchmark.cs +++ b/csharp/src/Google.Protobuf.Benchmarks/ParseMessagesBenchmark.cs @@ -31,6 +31,7 @@ #endregion using BenchmarkDotNet.Attributes; +using System; using System.Collections.Generic; using System.IO; using System.Linq; @@ -47,74 +48,49 @@ namespace Google.Protobuf.Benchmarks { const int MaxMessages = 100; - byte[] manyWrapperFieldsData; - byte[] manyPrimitiveFieldsData; - - byte[] manyWrapperFieldsMultipleMessagesData; - byte[] manyPrimitiveFieldsMultipleMessagesData; - - byte[] emptyData = new byte[0]; + SubTest manyWrapperFieldsTest = new SubTest(CreateManyWrapperFieldsMessage(), ManyWrapperFieldsMessage.Parser, () => new ManyWrapperFieldsMessage(), MaxMessages); + SubTest manyPrimitiveFieldsTest = new SubTest(CreateManyPrimitiveFieldsMessage(), ManyPrimitiveFieldsMessage.Parser, () => new ManyPrimitiveFieldsMessage(), MaxMessages); + SubTest emptyMessageTest = new SubTest(new Empty(), Empty.Parser, () => new Empty(), MaxMessages); public IEnumerable MessageCountValues => new[] { 10, 100 }; [GlobalSetup] public void GlobalSetup() { - manyWrapperFieldsData = CreateManyWrapperFieldsMessage().ToByteArray(); - manyPrimitiveFieldsData = CreateManyPrimitiveFieldsMessage().ToByteArray(); - manyWrapperFieldsMultipleMessagesData = CreateBufferWithMultipleMessages(CreateManyWrapperFieldsMessage(), MaxMessages); - manyPrimitiveFieldsMultipleMessagesData = CreateBufferWithMultipleMessages(CreateManyPrimitiveFieldsMessage(), MaxMessages); } [Benchmark] - public ManyWrapperFieldsMessage ManyWrapperFieldsMessage_ParseFromByteArray() + public IMessage ManyWrapperFieldsMessage_ParseFromByteArray() { - return ManyWrapperFieldsMessage.Parser.ParseFrom(manyWrapperFieldsData); + return manyWrapperFieldsTest.ParseFromByteArray(); } [Benchmark] - public ManyPrimitiveFieldsMessage ManyPrimitiveFieldsMessage_ParseFromByteArray() + public IMessage ManyPrimitiveFieldsMessage_ParseFromByteArray() { - return ManyPrimitiveFieldsMessage.Parser.ParseFrom(manyPrimitiveFieldsData); + return manyPrimitiveFieldsTest.ParseFromByteArray(); } [Benchmark] - public Empty EmptyMessage_ParseFromByteArray() + public IMessage EmptyMessage_ParseFromByteArray() { - return Empty.Parser.ParseFrom(emptyData); + return emptyMessageTest.ParseFromByteArray(); } [Benchmark] [ArgumentsSource(nameof(MessageCountValues))] - public long ManyWrapperFieldsMessage_ParseDelimitedMessagesFromByteArray(int messageCount) + public void ManyWrapperFieldsMessage_ParseDelimitedMessagesFromByteArray(int messageCount) { - long sum = 0; - var input = new CodedInputStream(manyWrapperFieldsMultipleMessagesData); - for (int i = 0; i < messageCount; i++) - { - var msg = new ManyWrapperFieldsMessage(); - input.ReadMessage(msg); - sum += msg.Int64Field19.Value; - } - return sum; + manyWrapperFieldsTest.ParseDelimitedMessagesFromByteArray(messageCount); } [Benchmark] [ArgumentsSource(nameof(MessageCountValues))] - public long ManyPrimitiveFieldsMessage_ParseDelimitedMessagesFromByteArray(int messageCount) + public void ManyPrimitiveFieldsMessage_ParseDelimitedMessagesFromByteArray(int messageCount) { - long sum = 0; - var input = new CodedInputStream(manyPrimitiveFieldsMultipleMessagesData); - for (int i = 0; i < messageCount; i++) - { - var msg = new ManyPrimitiveFieldsMessage(); - input.ReadMessage(msg); - sum += msg.Int64Field19; - } - return sum; + manyPrimitiveFieldsTest.ParseDelimitedMessagesFromByteArray(messageCount); } - private static ManyWrapperFieldsMessage CreateManyWrapperFieldsMessage() { // Example data match data of an internal benchmarks @@ -149,16 +125,46 @@ namespace Google.Protobuf.Benchmarks }; } - private static byte[] CreateBufferWithMultipleMessages(IMessage msg, int msgCount) + private class SubTest { - var ms = new MemoryStream(); - var cos = new CodedOutputStream(ms); - for (int i = 0; i < msgCount; i++) + private readonly IMessage message; + private readonly MessageParser parser; + private readonly Func factory; + private readonly byte[] data; + private readonly byte[] multipleMessagesData; + + public SubTest(IMessage message, MessageParser parser, Func factory, int maxMessageCount) + { + this.message = message; + this.parser = parser; + this.factory = factory; + this.data = message.ToByteArray(); + this.multipleMessagesData = CreateBufferWithMultipleMessages(message, maxMessageCount); + } + + public IMessage ParseFromByteArray() => parser.ParseFrom(data); + + public void ParseDelimitedMessagesFromByteArray(int messageCount) + { + var input = new CodedInputStream(multipleMessagesData); + for (int i = 0; i < messageCount; i++) + { + var msg = factory(); + input.ReadMessage(msg); + } + } + + private static byte[] CreateBufferWithMultipleMessages(IMessage msg, int msgCount) { - cos.WriteMessage(msg); + var ms = new MemoryStream(); + var cos = new CodedOutputStream(ms); + for (int i = 0; i < msgCount; i++) + { + cos.WriteMessage(msg); + } + cos.Flush(); + return ms.ToArray(); } - cos.Flush(); - return ms.ToArray(); } } -} \ No newline at end of file +} From c762a3bb2a8ea865df2fd3c8f832a19b67aee4c4 Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Tue, 7 Apr 2020 12:01:29 +0200 Subject: [PATCH 04/38] update Makefile.am --- Makefile.am | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Makefile.am b/Makefile.am index 9b0e68bc76..d01afea52b 100644 --- a/Makefile.am +++ b/Makefile.am @@ -85,15 +85,15 @@ csharp_EXTRA_DIST= \ csharp/src/AddressBook/ListPeople.cs \ csharp/src/AddressBook/Program.cs \ csharp/src/AddressBook/SampleUsage.cs \ + csharp/src/Google.Protobuf.Benchmarks/BenchmarkDatasetConfig.cs \ csharp/src/Google.Protobuf.Benchmarks/BenchmarkMessage1Proto3.cs \ csharp/src/Google.Protobuf.Benchmarks/Benchmarks.cs \ csharp/src/Google.Protobuf.Benchmarks/Google.Protobuf.Benchmarks.csproj \ + csharp/src/Google.Protobuf.Benchmarks/GoogleMessageBenchmark.cs \ csharp/src/Google.Protobuf.Benchmarks/ParseRawPrimitivesBenchmark.cs \ + csharp/src/Google.Protobuf.Benchmarks/ParseMessagesBenchmark.cs \ csharp/src/Google.Protobuf.Benchmarks/Program.cs \ - csharp/src/Google.Protobuf.Benchmarks/SerializationBenchmark.cs \ - csharp/src/Google.Protobuf.Benchmarks/SerializationConfig.cs \ csharp/src/Google.Protobuf.Benchmarks/wrapper_benchmark_messages.proto \ - csharp/src/Google.Protobuf.Benchmarks/WrapperBenchmark.cs \ csharp/src/Google.Protobuf.Benchmarks/WrapperBenchmarkMessages.cs \ csharp/src/Google.Protobuf.Conformance/Conformance.cs \ csharp/src/Google.Protobuf.Conformance/Google.Protobuf.Conformance.csproj \ From 0d43ba41ee207f401412ef4f3f5782a893b25131 Mon Sep 17 00:00:00 2001 From: Joshua Haberman Date: Sat, 11 Apr 2020 09:46:20 -0700 Subject: [PATCH 05/38] Update to new upb version (#7372) --- ruby/ext/google/protobuf_c/encode_decode.c | 10 +- ruby/ext/google/protobuf_c/map.c | 66 +- ruby/ext/google/protobuf_c/upb.c | 3031 ++++++++++++-------- ruby/ext/google/protobuf_c/upb.h | 1665 +++++++---- ruby/tests/common_tests.rb | 2 +- 5 files changed, 2810 insertions(+), 1964 deletions(-) diff --git a/ruby/ext/google/protobuf_c/encode_decode.c b/ruby/ext/google/protobuf_c/encode_decode.c index 8b0a22efd1..4a1d724d8f 100644 --- a/ruby/ext/google/protobuf_c/encode_decode.c +++ b/ruby/ext/google/protobuf_c/encode_decode.c @@ -434,10 +434,8 @@ static void *startmap_handler(void *closure, const void *hd) { } static bool endmap_handler(void *closure, const void *hd) { - MessageHeader* msg = closure; - const map_handlerdata_t* mapdata = hd; - VALUE map_rb = DEREF(msg, mapdata->ofs, VALUE); - Map_set_frame(map_rb, Qnil); + map_parse_frame_t* frame = closure; + Map_set_frame(frame->map, Qnil); return true; } @@ -1200,7 +1198,7 @@ static void putsubmsg(VALUE submsg, const upb_fielddef *f, upb_sink sink, upb_sink_startsubmsg(sink, getsel(f, UPB_HANDLER_STARTSUBMSG), &subsink); putmsg(submsg, subdesc, subsink, depth + 1, emit_defaults, is_json, true); - upb_sink_endsubmsg(sink, getsel(f, UPB_HANDLER_ENDSUBMSG)); + upb_sink_endsubmsg(sink, subsink, getsel(f, UPB_HANDLER_ENDSUBMSG)); } static void putary(VALUE ary, const upb_fielddef* f, upb_sink sink, int depth, @@ -1345,7 +1343,7 @@ static void putmap(VALUE map, const upb_fielddef* f, upb_sink sink, int depth, entry_sink, emit_defaults, is_json); upb_sink_endmsg(entry_sink, &status); - upb_sink_endsubmsg(subsink, getsel(f, UPB_HANDLER_ENDSUBMSG)); + upb_sink_endsubmsg(subsink, entry_sink, getsel(f, UPB_HANDLER_ENDSUBMSG)); } upb_sink_endseq(sink, getsel(f, UPB_HANDLER_ENDSEQ)); diff --git a/ruby/ext/google/protobuf_c/map.c b/ruby/ext/google/protobuf_c/map.c index 719706b9dd..00d23a76fa 100644 --- a/ruby/ext/google/protobuf_c/map.c +++ b/ruby/ext/google/protobuf_c/map.c @@ -100,11 +100,11 @@ static VALUE table_key(Map* self, VALUE key, return key; } -static VALUE table_key_to_ruby(Map* self, const char* buf, size_t length) { +static VALUE table_key_to_ruby(Map* self, upb_strview key) { switch (self->key_type) { case UPB_TYPE_BYTES: case UPB_TYPE_STRING: { - VALUE ret = rb_str_new(buf, length); + VALUE ret = rb_str_new(key.data, key.size); rb_enc_associate(ret, (self->key_type == UPB_TYPE_BYTES) ? kRubyString8bitEncoding : kRubyStringUtf8Encoding); @@ -116,7 +116,7 @@ static VALUE table_key_to_ruby(Map* self, const char* buf, size_t length) { case UPB_TYPE_INT64: case UPB_TYPE_UINT32: case UPB_TYPE_UINT64: - return native_slot_get(self->key_type, Qnil, buf); + return native_slot_get(self->key_type, Qnil, key.data); default: assert(false); @@ -289,9 +289,7 @@ VALUE Map_each(VALUE _self) { for (upb_strtable_begin(&it, &self->table); !upb_strtable_done(&it); upb_strtable_next(&it)) { - - VALUE key = table_key_to_ruby( - self, upb_strtable_iter_key(&it), upb_strtable_iter_keylength(&it)); + VALUE key = table_key_to_ruby(self, upb_strtable_iter_key(&it)); upb_value v = upb_strtable_iter_value(&it); void* mem = value_memory(&v); @@ -319,9 +317,7 @@ VALUE Map_keys(VALUE _self) { for (upb_strtable_begin(&it, &self->table); !upb_strtable_done(&it); upb_strtable_next(&it)) { - - VALUE key = table_key_to_ruby( - self, upb_strtable_iter_key(&it), upb_strtable_iter_keylength(&it)); + VALUE key = table_key_to_ruby(self, upb_strtable_iter_key(&it)); rb_ary_push(ret, key); } @@ -526,17 +522,14 @@ VALUE Map_dup(VALUE _self) { for (upb_strtable_begin(&it, &self->table); !upb_strtable_done(&it); upb_strtable_next(&it)) { - + upb_strview k = upb_strtable_iter_key(&it); upb_value v = upb_strtable_iter_value(&it); void* mem = value_memory(&v); upb_value dup; void* dup_mem = value_memory(&dup); native_slot_dup(self->value_type, dup_mem, mem); - if (!upb_strtable_insert2(&new_self->table, - upb_strtable_iter_key(&it), - upb_strtable_iter_keylength(&it), - dup)) { + if (!upb_strtable_insert2(&new_self->table, k.data, k.size, dup)) { rb_raise(rb_eRuntimeError, "Error inserting value into new table"); } } @@ -554,7 +547,7 @@ VALUE Map_deep_copy(VALUE _self) { for (upb_strtable_begin(&it, &self->table); !upb_strtable_done(&it); upb_strtable_next(&it)) { - + upb_strview k = upb_strtable_iter_key(&it); upb_value v = upb_strtable_iter_value(&it); void* mem = value_memory(&v); upb_value dup; @@ -562,10 +555,7 @@ VALUE Map_deep_copy(VALUE _self) { native_slot_deep_copy(self->value_type, self->value_type_class, dup_mem, mem); - if (!upb_strtable_insert2(&new_self->table, - upb_strtable_iter_key(&it), - upb_strtable_iter_keylength(&it), - dup)) { + if (!upb_strtable_insert2(&new_self->table, k.data, k.size, dup)) { rb_raise(rb_eRuntimeError, "Error inserting value into new table"); } } @@ -618,16 +608,13 @@ VALUE Map_eq(VALUE _self, VALUE _other) { for (upb_strtable_begin(&it, &self->table); !upb_strtable_done(&it); upb_strtable_next(&it)) { - + upb_strview k = upb_strtable_iter_key(&it); upb_value v = upb_strtable_iter_value(&it); void* mem = value_memory(&v); upb_value other_v; void* other_mem = value_memory(&other_v); - if (!upb_strtable_lookup2(&other->table, - upb_strtable_iter_key(&it), - upb_strtable_iter_keylength(&it), - &other_v)) { + if (!upb_strtable_lookup2(&other->table, k.data, k.size, &other_v)) { // Not present in other map. return Qfalse; } @@ -655,11 +642,9 @@ VALUE Map_hash(VALUE _self) { VALUE hash_sym = rb_intern("hash"); upb_strtable_iter it; - for (upb_strtable_begin(&it, &self->table); - !upb_strtable_done(&it); + for (upb_strtable_begin(&it, &self->table); !upb_strtable_done(&it); upb_strtable_next(&it)) { - VALUE key = table_key_to_ruby( - self, upb_strtable_iter_key(&it), upb_strtable_iter_keylength(&it)); + VALUE key = table_key_to_ruby(self, upb_strtable_iter_key(&it)); upb_value v = upb_strtable_iter_value(&it); void* mem = value_memory(&v); @@ -687,8 +672,7 @@ VALUE Map_to_h(VALUE _self) { for (upb_strtable_begin(&it, &self->table); !upb_strtable_done(&it); upb_strtable_next(&it)) { - VALUE key = table_key_to_ruby( - self, upb_strtable_iter_key(&it), upb_strtable_iter_keylength(&it)); + VALUE key = table_key_to_ruby(self, upb_strtable_iter_key(&it)); upb_value v = upb_strtable_iter_value(&it); void* mem = value_memory(&v); VALUE value = native_slot_get(self->value_type, @@ -720,11 +704,9 @@ VALUE Map_inspect(VALUE _self) { VALUE inspect_sym = rb_intern("inspect"); upb_strtable_iter it; - for (upb_strtable_begin(&it, &self->table); - !upb_strtable_done(&it); + for (upb_strtable_begin(&it, &self->table); !upb_strtable_done(&it); upb_strtable_next(&it)) { - VALUE key = table_key_to_ruby( - self, upb_strtable_iter_key(&it), upb_strtable_iter_keylength(&it)); + VALUE key = table_key_to_ruby(self, upb_strtable_iter_key(&it)); upb_value v = upb_strtable_iter_value(&it); void* mem = value_memory(&v); @@ -785,20 +767,15 @@ VALUE Map_merge_into_self(VALUE _self, VALUE hashmap) { for (upb_strtable_begin(&it, &other->table); !upb_strtable_done(&it); upb_strtable_next(&it)) { + upb_strview k = upb_strtable_iter_key(&it); // Replace any existing value by issuing a 'remove' operation first. upb_value v; upb_value oldv; - upb_strtable_remove2(&self->table, - upb_strtable_iter_key(&it), - upb_strtable_iter_keylength(&it), - &oldv); + upb_strtable_remove2(&self->table, k.data, k.size, &oldv); v = upb_strtable_iter_value(&it); - upb_strtable_insert2(&self->table, - upb_strtable_iter_key(&it), - upb_strtable_iter_keylength(&it), - v); + upb_strtable_insert2(&self->table, k.data, k.size, v); } } else { rb_raise(rb_eArgError, "Unknown type merging into Map"); @@ -822,10 +799,7 @@ bool Map_done(Map_iter* iter) { } VALUE Map_iter_key(Map_iter* iter) { - return table_key_to_ruby( - iter->self, - upb_strtable_iter_key(&iter->it), - upb_strtable_iter_keylength(&iter->it)); + return table_key_to_ruby(iter->self, upb_strtable_iter_key(&iter->it)); } VALUE Map_iter_value(Map_iter* iter) { diff --git a/ruby/ext/google/protobuf_c/upb.c b/ruby/ext/google/protobuf_c/upb.c index b7d7c162cf..ffa55fbb2a 100644 --- a/ruby/ext/google/protobuf_c/upb.c +++ b/ruby/ext/google/protobuf_c/upb.c @@ -22,9 +22,7 @@ * * This file is private and must not be included by users! */ -#ifndef UINTPTR_MAX -#error must include stdint.h first -#endif +#include #if UINTPTR_MAX == 0xffffffff #define UPB_SIZE(size32, size64) size32 @@ -32,17 +30,21 @@ #define UPB_SIZE(size32, size64) size64 #endif -#define UPB_FIELD_AT(msg, fieldtype, offset) \ - *(fieldtype*)((const char*)(msg) + offset) +/* If we always read/write as a consistent type to each address, this shouldn't + * violate aliasing. + */ +#define UPB_PTR_AT(msg, ofs, type) ((type*)((char*)(msg) + (ofs))) #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) \ + *UPB_PTR_AT(msg, case_offset, int) == case_val \ + ? *UPB_PTR_AT(msg, offset, fieldtype) \ : 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_PTR_AT(msg, case_offset, int) = case_val; \ + *UPB_PTR_AT(msg, offset, fieldtype) = value; + +#define UPB_MAPTYPE_STRING 0 /* UPB_INLINE: inline if possible, emit standalone code if required. */ #ifdef __cplusplus @@ -116,7 +118,7 @@ int msvc_vsnprintf(char* s, size_t n, const char* format, va_list arg); #ifdef __cplusplus #if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__) || \ (defined(_MSC_VER) && _MSC_VER >= 1900) -// C++11 is present +/* C++11 is present */ #else #error upb requires C++11 for C++ support #endif @@ -127,6 +129,18 @@ int msvc_vsnprintf(char* s, size_t n, const char* format, va_list arg); #define UPB_UNUSED(var) (void)var +/* UPB_ASSUME(): in release mode, we tell the compiler to assume this is true. + */ +#ifdef NDEBUG +#ifdef __GNUC__ +#define UPB_ASSUME(expr) if (!(expr)) __builtin_unreachable() +#else +#define UPB_ASSUME(expr) do {} if (false && (expr)) +#endif +#else +#define UPB_ASSUME(expr) assert(expr) +#endif + /* UPB_ASSERT(): in release mode, we use the expression without letting it be * evaluated. This prevents "unused variable" warnings. */ #ifdef NDEBUG @@ -153,606 +167,572 @@ int msvc_vsnprintf(char* s, size_t n, const char* format, va_list arg); #define UPB_INFINITY (1.0 / 0.0) #endif +#include #include + /* Maps descriptor type -> upb field type. */ -const uint8_t upb_desctype_to_fieldtype[] = { - UPB_WIRE_TYPE_END_GROUP, /* ENDGROUP */ - UPB_TYPE_DOUBLE, /* DOUBLE */ - UPB_TYPE_FLOAT, /* FLOAT */ - UPB_TYPE_INT64, /* INT64 */ - UPB_TYPE_UINT64, /* UINT64 */ - UPB_TYPE_INT32, /* INT32 */ - UPB_TYPE_UINT64, /* FIXED64 */ - UPB_TYPE_UINT32, /* FIXED32 */ - UPB_TYPE_BOOL, /* BOOL */ - UPB_TYPE_STRING, /* STRING */ - UPB_TYPE_MESSAGE, /* GROUP */ - UPB_TYPE_MESSAGE, /* MESSAGE */ - UPB_TYPE_BYTES, /* BYTES */ - UPB_TYPE_UINT32, /* UINT32 */ - UPB_TYPE_ENUM, /* ENUM */ - UPB_TYPE_INT32, /* SFIXED32 */ - UPB_TYPE_INT64, /* SFIXED64 */ - UPB_TYPE_INT32, /* SINT32 */ - UPB_TYPE_INT64, /* SINT64 */ +static const uint8_t desctype_to_fieldtype[] = { + -1, /* invalid descriptor type */ + UPB_TYPE_DOUBLE, /* DOUBLE */ + UPB_TYPE_FLOAT, /* FLOAT */ + UPB_TYPE_INT64, /* INT64 */ + UPB_TYPE_UINT64, /* UINT64 */ + UPB_TYPE_INT32, /* INT32 */ + UPB_TYPE_UINT64, /* FIXED64 */ + UPB_TYPE_UINT32, /* FIXED32 */ + UPB_TYPE_BOOL, /* BOOL */ + UPB_TYPE_STRING, /* STRING */ + UPB_TYPE_MESSAGE, /* GROUP */ + UPB_TYPE_MESSAGE, /* MESSAGE */ + UPB_TYPE_BYTES, /* BYTES */ + UPB_TYPE_UINT32, /* UINT32 */ + UPB_TYPE_ENUM, /* ENUM */ + UPB_TYPE_INT32, /* SFIXED32 */ + UPB_TYPE_INT64, /* SFIXED64 */ + UPB_TYPE_INT32, /* SINT32 */ + UPB_TYPE_INT64, /* SINT64 */ +}; + +/* Maps descriptor type -> upb map size. */ +static const uint8_t desctype_to_mapsize[] = { + -1, /* invalid descriptor type */ + 8, /* DOUBLE */ + 4, /* FLOAT */ + 8, /* INT64 */ + 8, /* UINT64 */ + 4, /* INT32 */ + 8, /* FIXED64 */ + 4, /* FIXED32 */ + 1, /* BOOL */ + UPB_MAPTYPE_STRING, /* STRING */ + sizeof(void *), /* GROUP */ + sizeof(void *), /* MESSAGE */ + UPB_MAPTYPE_STRING, /* BYTES */ + 4, /* UINT32 */ + 4, /* ENUM */ + 4, /* SFIXED32 */ + 8, /* SFIXED64 */ + 4, /* SINT32 */ + 8, /* SINT64 */ +}; + +static const unsigned fixed32_ok = (1 << UPB_DTYPE_FLOAT) | + (1 << UPB_DTYPE_FIXED32) | + (1 << UPB_DTYPE_SFIXED32); + +static const unsigned fixed64_ok = (1 << UPB_DTYPE_DOUBLE) | + (1 << UPB_DTYPE_FIXED64) | + (1 << UPB_DTYPE_SFIXED64); + +/* Op: an action to be performed for a wire-type/field-type combination. */ +#define OP_SCALAR_LG2(n) (n) +#define OP_FIXPCK_LG2(n) (n + 4) +#define OP_VARPCK_LG2(n) (n + 8) +#define OP_STRING 4 +#define OP_SUBMSG 5 + +static const int8_t varint_ops[19] = { + -1, /* field not found */ + -1, /* DOUBLE */ + -1, /* FLOAT */ + OP_SCALAR_LG2(3), /* INT64 */ + OP_SCALAR_LG2(3), /* UINT64 */ + OP_SCALAR_LG2(2), /* INT32 */ + -1, /* FIXED64 */ + -1, /* FIXED32 */ + OP_SCALAR_LG2(0), /* BOOL */ + -1, /* STRING */ + -1, /* GROUP */ + -1, /* MESSAGE */ + -1, /* BYTES */ + OP_SCALAR_LG2(2), /* UINT32 */ + OP_SCALAR_LG2(2), /* ENUM */ + -1, /* SFIXED32 */ + -1, /* SFIXED64 */ + OP_SCALAR_LG2(2), /* SINT32 */ + OP_SCALAR_LG2(3), /* SINT64 */ +}; + +static const int8_t delim_ops[37] = { + /* For non-repeated field type. */ + -1, /* field not found */ + -1, /* DOUBLE */ + -1, /* FLOAT */ + -1, /* INT64 */ + -1, /* UINT64 */ + -1, /* INT32 */ + -1, /* FIXED64 */ + -1, /* FIXED32 */ + -1, /* BOOL */ + OP_STRING, /* STRING */ + -1, /* GROUP */ + OP_SUBMSG, /* MESSAGE */ + OP_STRING, /* BYTES */ + -1, /* UINT32 */ + -1, /* ENUM */ + -1, /* SFIXED32 */ + -1, /* SFIXED64 */ + -1, /* SINT32 */ + -1, /* SINT64 */ + /* For repeated field type. */ + OP_FIXPCK_LG2(3), /* REPEATED DOUBLE */ + OP_FIXPCK_LG2(2), /* REPEATED FLOAT */ + OP_VARPCK_LG2(3), /* REPEATED INT64 */ + OP_VARPCK_LG2(3), /* REPEATED UINT64 */ + OP_VARPCK_LG2(2), /* REPEATED INT32 */ + OP_FIXPCK_LG2(3), /* REPEATED FIXED64 */ + OP_FIXPCK_LG2(2), /* REPEATED FIXED32 */ + OP_VARPCK_LG2(0), /* REPEATED BOOL */ + OP_STRING, /* REPEATED STRING */ + OP_SUBMSG, /* REPEATED GROUP */ + OP_SUBMSG, /* REPEATED MESSAGE */ + OP_STRING, /* REPEATED BYTES */ + OP_VARPCK_LG2(2), /* REPEATED UINT32 */ + OP_VARPCK_LG2(2), /* REPEATED ENUM */ + OP_FIXPCK_LG2(2), /* REPEATED SFIXED32 */ + OP_FIXPCK_LG2(3), /* REPEATED SFIXED64 */ + OP_VARPCK_LG2(2), /* REPEATED SINT32 */ + OP_VARPCK_LG2(3), /* REPEATED SINT64 */ }; /* Data pertaining to the parse. */ typedef struct { - const char *ptr; /* Current parsing position. */ - const char *field_start; /* Start of this field. */ - const char *limit; /* End of delimited region or end of buffer. */ + const char *limit; /* End of delimited region or end of buffer. */ upb_arena *arena; int depth; - uint32_t end_group; /* Set to field number of END_GROUP tag, if any. */ + uint32_t end_group; /* Set to field number of END_GROUP tag, if any. */ + jmp_buf err; } upb_decstate; -/* Data passed by value to each parsing function. */ -typedef struct { - char *msg; - const upb_msglayout *layout; - upb_decstate *state; -} upb_decframe; +typedef union { + bool bool_val; + int32_t int32_val; + int64_t int64_val; + uint32_t uint32_val; + uint64_t uint64_val; + upb_strview str_val; +} wireval; -#define CHK(x) if (!(x)) { return 0; } +static const char *decode_msg(upb_decstate *d, const char *ptr, upb_msg *msg, + const upb_msglayout *layout); -static bool upb_skip_unknowngroup(upb_decstate *d, int field_number); -static bool upb_decode_message(upb_decstate *d, char *msg, - const upb_msglayout *l); +UPB_NORETURN static void decode_err(upb_decstate *d) { longjmp(d->err, 1); } + +static bool decode_reserve(upb_decstate *d, upb_array *arr, int elem) { + bool need_realloc = arr->size - arr->len < elem; + if (need_realloc && !_upb_array_realloc(arr, arr->len + elem, d->arena)) { + decode_err(d); + } + return need_realloc; +} -static bool upb_decode_varint(const char **ptr, const char *limit, - uint64_t *val) { +UPB_NOINLINE +static const char *decode_longvarint64(upb_decstate *d, const char *ptr, + const char *limit, uint64_t *val) { uint8_t byte; int bitpos = 0; - const char *p = *ptr; - *val = 0; + uint64_t out = 0; do { - CHK(bitpos < 70 && p < limit); - byte = *p; - *val |= (uint64_t)(byte & 0x7F) << bitpos; - p++; + if (bitpos >= 70 || ptr == limit) decode_err(d); + byte = *ptr; + out |= (uint64_t)(byte & 0x7F) << bitpos; + ptr++; bitpos += 7; } while (byte & 0x80); - *ptr = p; - return true; -} - -static bool upb_decode_varint32(const char **ptr, const char *limit, - uint32_t *val) { - uint64_t u64; - CHK(upb_decode_varint(ptr, limit, &u64) && u64 <= UINT32_MAX); - *val = (uint32_t)u64; - return true; + *val = out; + return ptr; } -static bool upb_decode_64bit(const char **ptr, const char *limit, - uint64_t *val) { - CHK(limit - *ptr >= 8); - memcpy(val, *ptr, 8); - *ptr += 8; - return true; -} - -static bool upb_decode_32bit(const char **ptr, const char *limit, - uint32_t *val) { - CHK(limit - *ptr >= 4); - memcpy(val, *ptr, 4); - *ptr += 4; - return true; -} - -static int32_t upb_zzdecode_32(uint32_t n) { - return (n >> 1) ^ -(int32_t)(n & 1); -} - -static int64_t upb_zzdecode_64(uint64_t n) { - return (n >> 1) ^ -(int64_t)(n & 1); -} - -static bool upb_decode_string(const char **ptr, const char *limit, - int *outlen) { - uint32_t len; - - CHK(upb_decode_varint32(ptr, limit, &len) && - len < INT32_MAX && - limit - *ptr >= (int32_t)len); - - *outlen = len; - return true; -} - -static void upb_set32(void *msg, size_t ofs, uint32_t val) { - memcpy((char*)msg + ofs, &val, sizeof(val)); +UPB_FORCEINLINE +static const char *decode_varint64(upb_decstate *d, const char *ptr, + const char *limit, uint64_t *val) { + if (UPB_LIKELY(ptr < limit && (*ptr & 0x80) == 0)) { + *val = (uint8_t)*ptr; + return ptr + 1; + } else { + return decode_longvarint64(d, ptr, limit, val); + } } -static bool upb_append_unknown(upb_decstate *d, upb_decframe *frame) { - upb_msg_addunknown(frame->msg, d->field_start, d->ptr - d->field_start, - d->arena); - return true; +static const char *decode_varint32(upb_decstate *d, const char *ptr, + const char *limit, uint32_t *val) { + uint64_t u64; + ptr = decode_varint64(d, ptr, limit, &u64); + if (u64 > UINT32_MAX) decode_err(d); + *val = (uint32_t)u64; + return ptr; } - -static bool upb_skip_unknownfielddata(upb_decstate *d, uint32_t tag, - uint32_t group_fieldnum) { - switch (tag & 7) { - case UPB_WIRE_TYPE_VARINT: { - uint64_t val; - return upb_decode_varint(&d->ptr, d->limit, &val); - } - case UPB_WIRE_TYPE_32BIT: { - uint32_t val; - return upb_decode_32bit(&d->ptr, d->limit, &val); - } - case UPB_WIRE_TYPE_64BIT: { - uint64_t val; - return upb_decode_64bit(&d->ptr, d->limit, &val); +static void decode_munge(int type, wireval *val) { + switch (type) { + case UPB_DESCRIPTOR_TYPE_BOOL: + val->bool_val = val->uint64_val != 0; + break; + case UPB_DESCRIPTOR_TYPE_SINT32: { + uint32_t n = val->uint32_val; + val->int32_val = (n >> 1) ^ -(int32_t)(n & 1); + break; } - case UPB_WIRE_TYPE_DELIMITED: { - int len; - CHK(upb_decode_string(&d->ptr, d->limit, &len)); - d->ptr += len; - return true; + case UPB_DESCRIPTOR_TYPE_SINT64: { + uint64_t n = val->uint64_val; + val->int64_val = (n >> 1) ^ -(int64_t)(n & 1); + break; } - case UPB_WIRE_TYPE_START_GROUP: - return upb_skip_unknowngroup(d, tag >> 3); - case UPB_WIRE_TYPE_END_GROUP: - return (tag >> 3) == group_fieldnum; } - return false; -} - -static bool upb_skip_unknowngroup(upb_decstate *d, int field_number) { - while (d->ptr < d->limit && d->end_group == 0) { - uint32_t tag = 0; - CHK(upb_decode_varint32(&d->ptr, d->limit, &tag)); - CHK(upb_skip_unknownfielddata(d, tag, field_number)); - } - - CHK(d->end_group == field_number); - d->end_group = 0; - return true; } -static bool upb_array_grow(upb_array *arr, size_t elements, size_t elem_size, - upb_arena *arena) { - size_t needed = arr->len + elements; - size_t new_size = UPB_MAX(arr->size, 8); - size_t new_bytes; - size_t old_bytes; - void *new_data; - upb_alloc *alloc = upb_arena_alloc(arena); +static const upb_msglayout_field *upb_find_field(const upb_msglayout *l, + uint32_t field_number) { + static upb_msglayout_field none = {0}; - while (new_size < needed) { - new_size *= 2; + /* Lots of optimization opportunities here. */ + int i; + if (l == NULL) return &none; + for (i = 0; i < l->field_count; i++) { + if (l->fields[i].number == field_number) { + return &l->fields[i]; + } } - old_bytes = arr->len * elem_size; - new_bytes = new_size * elem_size; - new_data = upb_realloc(alloc, arr->data, old_bytes, new_bytes); - CHK(new_data); - - arr->data = new_data; - arr->size = new_size; - return true; + return &none; /* Unknown field. */ } -static void *upb_array_reserve(upb_array *arr, size_t elements, - size_t elem_size, upb_arena *arena) { - if (arr->size - arr->len < elements) { - CHK(upb_array_grow(arr, elements, elem_size, arena)); - } - return (char*)arr->data + (arr->len * elem_size); +static upb_msg *decode_newsubmsg(upb_decstate *d, const upb_msglayout *layout, + const upb_msglayout_field *field) { + const upb_msglayout *subl = layout->submsgs[field->submsg_index]; + return _upb_msg_new(subl, d->arena); } -bool upb_array_add(upb_array *arr, size_t elements, size_t elem_size, - const void *data, upb_arena *arena) { - void *dest = upb_array_reserve(arr, elements, elem_size, arena); - - CHK(dest); - arr->len += elements; - memcpy(dest, data, elements * elem_size); +static void decode_tosubmsg(upb_decstate *d, upb_msg *submsg, + const upb_msglayout *layout, + const upb_msglayout_field *field, upb_strview val) { + const upb_msglayout *subl = layout->submsgs[field->submsg_index]; + const char *saved_limit = d->limit; + if (--d->depth < 0) decode_err(d); + d->limit = val.data + val.size; + decode_msg(d, val.data, submsg, subl); + d->limit = saved_limit; + if (d->end_group != 0) decode_err(d); + d->depth++; +} - return true; +static const char *decode_group(upb_decstate *d, const char *ptr, + upb_msg *submsg, const upb_msglayout *subl, + uint32_t number) { + if (--d->depth < 0) decode_err(d); + ptr = decode_msg(d, ptr, submsg, subl); + if (d->end_group != number) decode_err(d); + d->end_group = 0; + d->depth++; + return ptr; } -static upb_array *upb_getarr(upb_decframe *frame, - const upb_msglayout_field *field) { - UPB_ASSERT(field->label == UPB_LABEL_REPEATED); - return *(upb_array**)&frame->msg[field->offset]; +static const char *decode_togroup(upb_decstate *d, const char *ptr, + upb_msg *submsg, const upb_msglayout *layout, + const upb_msglayout_field *field) { + const upb_msglayout *subl = layout->submsgs[field->submsg_index]; + return decode_group(d, ptr, submsg, subl, field->number); } -static upb_array *upb_getorcreatearr(upb_decframe *frame, - const upb_msglayout_field *field) { - upb_array *arr = upb_getarr(frame, field); +static const char *decode_toarray(upb_decstate *d, const char *ptr, + upb_msg *msg, const upb_msglayout *layout, + const upb_msglayout_field *field, wireval val, + int op) { + upb_array **arrp = UPB_PTR_AT(msg, field->offset, void); + upb_array *arr = *arrp; + void *mem; if (!arr) { - arr = upb_array_new(frame->state->arena); - CHK(arr); - *(upb_array**)&frame->msg[field->offset] = arr; + upb_fieldtype_t type = desctype_to_fieldtype[field->descriptortype]; + arr = _upb_array_new(d->arena, type); + if (!arr) decode_err(d); + *arrp = arr; } - return arr; -} - -static upb_msg *upb_getorcreatemsg(upb_decframe *frame, - const upb_msglayout_field *field, - const upb_msglayout **subm) { - upb_msg **submsg = (void*)(frame->msg + field->offset); - *subm = frame->layout->submsgs[field->submsg_index]; + decode_reserve(d, arr, 1); - UPB_ASSERT(field->label != UPB_LABEL_REPEATED); - - if (!*submsg) { - *submsg = upb_msg_new(*subm, frame->state->arena); - CHK(*submsg); + switch (op) { + case OP_SCALAR_LG2(0): + case OP_SCALAR_LG2(2): + case OP_SCALAR_LG2(3): + /* Append scalar value. */ + mem = UPB_PTR_AT(_upb_array_ptr(arr), arr->len << op, void); + arr->len++; + memcpy(mem, &val, 1 << op); + return ptr; + case OP_STRING: + /* Append string. */ + mem = + UPB_PTR_AT(_upb_array_ptr(arr), arr->len * sizeof(upb_strview), void); + arr->len++; + memcpy(mem, &val, sizeof(upb_strview)); + return ptr; + case OP_SUBMSG: { + /* Append submessage / group. */ + upb_msg *submsg = decode_newsubmsg(d, layout, field); + *UPB_PTR_AT(_upb_array_ptr(arr), arr->len * sizeof(void *), upb_msg *) = + submsg; + arr->len++; + if (UPB_UNLIKELY(field->descriptortype == UPB_DTYPE_GROUP)) { + ptr = decode_togroup(d, ptr, submsg, layout, field); + } else { + decode_tosubmsg(d, submsg, layout, field, val.str_val); + } + return ptr; + } + case OP_FIXPCK_LG2(2): + case OP_FIXPCK_LG2(3): { + /* Fixed packed. */ + int lg2 = op - OP_FIXPCK_LG2(0); + int mask = (1 << lg2) - 1; + int count = val.str_val.size >> lg2; + if ((val.str_val.size & mask) != 0) { + decode_err(d); /* Length isn't a round multiple of elem size. */ + } + decode_reserve(d, arr, count); + mem = UPB_PTR_AT(_upb_array_ptr(arr), arr->len << lg2, void); + arr->len += count; + memcpy(mem, val.str_val.data, count << op); + return ptr; + } + case OP_VARPCK_LG2(0): + case OP_VARPCK_LG2(2): + case OP_VARPCK_LG2(3): { + /* Varint packed. */ + int lg2 = op - OP_VARPCK_LG2(0); + int scale = 1 << lg2; + const char *ptr = val.str_val.data; + const char *end = ptr + val.str_val.size; + char *out = UPB_PTR_AT(_upb_array_ptr(arr), arr->len << lg2, void); + while (ptr < end) { + wireval elem; + ptr = decode_varint64(d, ptr, end, &elem.uint64_val); + decode_munge(field->descriptortype, &elem); + if (decode_reserve(d, arr, 1)) { + out = UPB_PTR_AT(_upb_array_ptr(arr), arr->len << lg2, void); + } + arr->len++; + memcpy(out, &elem, scale); + out += scale; + } + if (ptr != end) decode_err(d); + return ptr; + } + default: + UPB_UNREACHABLE(); } - - return *submsg; } -static upb_msg *upb_addmsg(upb_decframe *frame, - const upb_msglayout_field *field, - const upb_msglayout **subm) { - upb_msg *submsg; - upb_array *arr = upb_getorcreatearr(frame, field); - - *subm = frame->layout->submsgs[field->submsg_index]; - submsg = upb_msg_new(*subm, frame->state->arena); - CHK(submsg); - upb_array_add(arr, 1, sizeof(submsg), &submsg, frame->state->arena); - - return submsg; -} +static void decode_tomap(upb_decstate *d, upb_msg *msg, + const upb_msglayout *layout, + const upb_msglayout_field *field, wireval val) { + upb_map **map_p = UPB_PTR_AT(msg, field->offset, upb_map *); + upb_map *map = *map_p; + upb_map_entry ent; + const upb_msglayout *entry = layout->submsgs[field->submsg_index]; -static void upb_sethasbit(upb_decframe *frame, - 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_field *field) { - UPB_ASSERT(field->presence < 0); - upb_set32(frame->msg, ~field->presence, field->number); -} - -static bool upb_decode_addval(upb_decframe *frame, - const upb_msglayout_field *field, void *val, - size_t size) { - char *field_mem = frame->msg + field->offset; - upb_array *arr; - - if (field->label == UPB_LABEL_REPEATED) { - arr = upb_getorcreatearr(frame, field); - CHK(arr); - field_mem = upb_array_reserve(arr, 1, size, frame->state->arena); - CHK(field_mem); + if (!map) { + /* Lazily create map. */ + const upb_msglayout *entry = layout->submsgs[field->submsg_index]; + const upb_msglayout_field *key_field = &entry->fields[0]; + const upb_msglayout_field *val_field = &entry->fields[1]; + char key_size = desctype_to_mapsize[key_field->descriptortype]; + char val_size = desctype_to_mapsize[val_field->descriptortype]; + UPB_ASSERT(key_field->offset == 0); + UPB_ASSERT(val_field->offset == sizeof(upb_strview)); + map = _upb_map_new(d->arena, key_size, val_size); + *map_p = map; } - memcpy(field_mem, val, size); - return true; -} + /* Parse map entry. */ + memset(&ent, 0, sizeof(ent)); -static void upb_decode_setpresent(upb_decframe *frame, - 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->presence < 0) { - upb_setoneofcase(frame, field); - } else if (field->presence > 0) { - upb_sethasbit(frame, field); + if (entry->fields[1].descriptortype == UPB_DESCRIPTOR_TYPE_MESSAGE || + entry->fields[1].descriptortype == UPB_DESCRIPTOR_TYPE_GROUP) { + /* Create proactively to handle the case where it doesn't appear. */ + ent.v.val.val = (uint64_t)_upb_msg_new(entry->submsgs[0], d->arena); } -} -static bool upb_decode_msgfield(upb_decstate *d, upb_msg *msg, - const upb_msglayout *layout, int limit) { - const char* saved_limit = d->limit; - d->limit = d->ptr + limit; - CHK(--d->depth >= 0); - upb_decode_message(d, msg, layout); - d->depth++; - d->limit = saved_limit; - CHK(d->end_group == 0); - return true; -} + decode_tosubmsg(d, &ent.k, layout, field, val.str_val); -static bool upb_decode_groupfield(upb_decstate *d, upb_msg *msg, - const upb_msglayout *layout, - int field_number) { - CHK(--d->depth >= 0); - upb_decode_message(d, msg, layout); - d->depth++; - CHK(d->end_group == field_number); - d->end_group = 0; - return true; + /* Insert into map. */ + _upb_map_set(map, &ent.k, map->key_size, &ent.v, map->val_size, d->arena); } -static bool upb_decode_varintfield(upb_decstate *d, upb_decframe *frame, - const upb_msglayout_field *field) { - uint64_t val; - CHK(upb_decode_varint(&d->ptr, d->limit, &val)); +static const char *decode_tomsg(upb_decstate *d, const char *ptr, upb_msg *msg, + const upb_msglayout *layout, + const upb_msglayout_field *field, wireval val, + int op) { + void *mem = UPB_PTR_AT(msg, field->offset, void); + int type = field->descriptortype; - switch (field->descriptortype) { - case UPB_DESCRIPTOR_TYPE_INT64: - case UPB_DESCRIPTOR_TYPE_UINT64: - CHK(upb_decode_addval(frame, field, &val, sizeof(val))); - break; - case UPB_DESCRIPTOR_TYPE_INT32: - case UPB_DESCRIPTOR_TYPE_UINT32: - case UPB_DESCRIPTOR_TYPE_ENUM: { - uint32_t val32 = (uint32_t)val; - CHK(upb_decode_addval(frame, field, &val32, sizeof(val32))); + /* Set presence if necessary. */ + if (field->presence < 0) { + /* Oneof case */ + *UPB_PTR_AT(msg, -field->presence, int32_t) = field->number; + } else if (field->presence > 0) { + /* Hasbit */ + uint32_t hasbit = field->presence; + *UPB_PTR_AT(msg, hasbit / 8, uint8_t) |= (1 << (hasbit % 8)); + } + + /* Store into message. */ + switch (op) { + case OP_SUBMSG: { + upb_msg **submsgp = mem; + upb_msg *submsg = *submsgp; + if (!submsg) { + submsg = decode_newsubmsg(d, layout, field); + *submsgp = submsg; + } + if (UPB_UNLIKELY(type == UPB_DTYPE_GROUP)) { + ptr = decode_togroup(d, ptr, submsg, layout, field); + } else { + decode_tosubmsg(d, submsg, layout, field, val.str_val); + } break; } - case UPB_DESCRIPTOR_TYPE_BOOL: { - bool valbool = val != 0; - CHK(upb_decode_addval(frame, field, &valbool, sizeof(valbool))); + case OP_STRING: + memcpy(mem, &val, sizeof(upb_strview)); break; - } - case UPB_DESCRIPTOR_TYPE_SINT32: { - int32_t decoded = upb_zzdecode_32((uint32_t)val); - CHK(upb_decode_addval(frame, field, &decoded, sizeof(decoded))); + case OP_SCALAR_LG2(3): + memcpy(mem, &val, 8); break; - } - case UPB_DESCRIPTOR_TYPE_SINT64: { - int64_t decoded = upb_zzdecode_64(val); - CHK(upb_decode_addval(frame, field, &decoded, sizeof(decoded))); + case OP_SCALAR_LG2(2): + memcpy(mem, &val, 4); break; - } - default: - return upb_append_unknown(d, frame); - } - - upb_decode_setpresent(frame, field); - return true; -} - -static bool upb_decode_64bitfield(upb_decstate *d, upb_decframe *frame, - const upb_msglayout_field *field) { - uint64_t val; - CHK(upb_decode_64bit(&d->ptr, d->limit, &val)); - - switch (field->descriptortype) { - case UPB_DESCRIPTOR_TYPE_DOUBLE: - case UPB_DESCRIPTOR_TYPE_FIXED64: - case UPB_DESCRIPTOR_TYPE_SFIXED64: - CHK(upb_decode_addval(frame, field, &val, sizeof(val))); + case OP_SCALAR_LG2(0): + memcpy(mem, &val, 1); break; default: - return upb_append_unknown(d, frame); + UPB_UNREACHABLE(); } - upb_decode_setpresent(frame, field); - return true; -} - -static bool upb_decode_32bitfield(upb_decstate *d, upb_decframe *frame, - const upb_msglayout_field *field) { - uint32_t val; - CHK(upb_decode_32bit(&d->ptr, d->limit, &val)); - - switch (field->descriptortype) { - case UPB_DESCRIPTOR_TYPE_FLOAT: - case UPB_DESCRIPTOR_TYPE_FIXED32: - case UPB_DESCRIPTOR_TYPE_SFIXED32: - CHK(upb_decode_addval(frame, field, &val, sizeof(val))); - break; - default: - return upb_append_unknown(d, frame); - } - - upb_decode_setpresent(frame, field); - return true; + return ptr; } -static bool upb_decode_fixedpacked(upb_decstate *d, upb_array *arr, - uint32_t len, int elem_size) { - size_t elements = len / elem_size; - - CHK((size_t)(elements * elem_size) == len); - CHK(upb_array_add(arr, elements, elem_size, d->ptr, d->arena)); - d->ptr += len; - - return true; -} - -static upb_strview upb_decode_strfield(upb_decstate *d, uint32_t len) { - upb_strview ret; - ret.data = d->ptr; - ret.size = len; - d->ptr += len; - return ret; -} - -static bool upb_decode_toarray(upb_decstate *d, upb_decframe *frame, - const upb_msglayout_field *field, int len) { - upb_array *arr = upb_getorcreatearr(frame, field); - CHK(arr); - -#define VARINT_CASE(ctype, decode) \ - VARINT_CASE_EX(ctype, decode, decode) - -#define VARINT_CASE_EX(ctype, decode, dtype) \ - { \ - const char *ptr = d->ptr; \ - const char *limit = ptr + len; \ - while (ptr < limit) { \ - uint64_t val; \ - ctype decoded; \ - CHK(upb_decode_varint(&ptr, limit, &val)); \ - decoded = (decode)((dtype)val); \ - CHK(upb_array_add(arr, 1, sizeof(decoded), &decoded, d->arena)); \ - } \ - d->ptr = ptr; \ - return true; \ - } - - switch (field->descriptortype) { - case UPB_DESCRIPTOR_TYPE_STRING: - case UPB_DESCRIPTOR_TYPE_BYTES: { - upb_strview str = upb_decode_strfield(d, len); - return upb_array_add(arr, 1, sizeof(str), &str, d->arena); - } - case UPB_DESCRIPTOR_TYPE_FLOAT: - case UPB_DESCRIPTOR_TYPE_FIXED32: - case UPB_DESCRIPTOR_TYPE_SFIXED32: - return upb_decode_fixedpacked(d, arr, len, sizeof(int32_t)); - case UPB_DESCRIPTOR_TYPE_DOUBLE: - case UPB_DESCRIPTOR_TYPE_FIXED64: - case UPB_DESCRIPTOR_TYPE_SFIXED64: - return upb_decode_fixedpacked(d, arr, len, sizeof(int64_t)); - case UPB_DESCRIPTOR_TYPE_INT32: - case UPB_DESCRIPTOR_TYPE_UINT32: - case UPB_DESCRIPTOR_TYPE_ENUM: - VARINT_CASE(uint32_t, uint32_t); - case UPB_DESCRIPTOR_TYPE_INT64: - case UPB_DESCRIPTOR_TYPE_UINT64: - VARINT_CASE(uint64_t, uint64_t); - case UPB_DESCRIPTOR_TYPE_BOOL: - VARINT_CASE(bool, bool); - case UPB_DESCRIPTOR_TYPE_SINT32: - VARINT_CASE_EX(int32_t, upb_zzdecode_32, uint32_t); - case UPB_DESCRIPTOR_TYPE_SINT64: - VARINT_CASE_EX(int64_t, upb_zzdecode_64, uint64_t); - case UPB_DESCRIPTOR_TYPE_MESSAGE: { - const upb_msglayout *subm; - upb_msg *submsg = upb_addmsg(frame, field, &subm); - CHK(submsg); - return upb_decode_msgfield(d, submsg, subm, len); - } - case UPB_DESCRIPTOR_TYPE_GROUP: - return upb_append_unknown(d, frame); - } -#undef VARINT_CASE - UPB_UNREACHABLE(); -} - -static bool upb_decode_delimitedfield(upb_decstate *d, upb_decframe *frame, - const upb_msglayout_field *field) { - int len; - - CHK(upb_decode_string(&d->ptr, d->limit, &len)); - - if (field->label == UPB_LABEL_REPEATED) { - return upb_decode_toarray(d, frame, field, len); - } else { - switch (field->descriptortype) { - case UPB_DESCRIPTOR_TYPE_STRING: - case UPB_DESCRIPTOR_TYPE_BYTES: { - upb_strview str = upb_decode_strfield(d, len); - CHK(upb_decode_addval(frame, field, &str, sizeof(str))); - break; - } - case UPB_DESCRIPTOR_TYPE_MESSAGE: { - const upb_msglayout *subm; - upb_msg *submsg = upb_getorcreatemsg(frame, field, &subm); - CHK(submsg); - CHK(upb_decode_msgfield(d, submsg, subm, len)); - break; - } - default: - /* TODO(haberman): should we accept the last element of a packed? */ - d->ptr += len; - return upb_append_unknown(d, frame); - } - upb_decode_setpresent(frame, field); - return true; - } -} - -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++) { - if (l->fields[i].number == field_number) { - return &l->fields[i]; - } - } - - return NULL; /* Unknown field. */ -} +static const char *decode_msg(upb_decstate *d, const char *ptr, upb_msg *msg, + const upb_msglayout *layout) { + while (ptr < d->limit) { + uint32_t tag; + const upb_msglayout_field *field; + int field_number; + int wire_type; + const char *field_start = ptr; + wireval val; + int op; -static bool upb_decode_field(upb_decstate *d, upb_decframe *frame) { - uint32_t tag; - const upb_msglayout_field *field; - int field_number; + ptr = decode_varint32(d, ptr, d->limit, &tag); + field_number = tag >> 3; + wire_type = tag & 7; - d->field_start = d->ptr; - CHK(upb_decode_varint32(&d->ptr, d->limit, &tag)); - field_number = tag >> 3; - field = upb_find_field(frame->layout, field_number); + field = upb_find_field(layout, field_number); - if (field) { - switch (tag & 7) { + switch (wire_type) { case UPB_WIRE_TYPE_VARINT: - return upb_decode_varintfield(d, frame, field); + ptr = decode_varint64(d, ptr, d->limit, &val.uint64_val); + op = varint_ops[field->descriptortype]; + decode_munge(field->descriptortype, &val); + break; case UPB_WIRE_TYPE_32BIT: - return upb_decode_32bitfield(d, frame, field); + if (d->limit - ptr < 4) decode_err(d); + memcpy(&val, ptr, 4); + ptr += 4; + op = OP_SCALAR_LG2(2); + if (((1 << field->descriptortype) & fixed32_ok) == 0) goto unknown; + break; case UPB_WIRE_TYPE_64BIT: - return upb_decode_64bitfield(d, frame, field); - case UPB_WIRE_TYPE_DELIMITED: - return upb_decode_delimitedfield(d, frame, field); - case UPB_WIRE_TYPE_START_GROUP: { - const upb_msglayout *layout; - upb_msg *group; - - if (field->label == UPB_LABEL_REPEATED) { - group = upb_addmsg(frame, field, &layout); - } else { - group = upb_getorcreatemsg(frame, field, &layout); + if (d->limit - ptr < 8) decode_err(d); + memcpy(&val, ptr, 8); + ptr += 8; + op = OP_SCALAR_LG2(3); + if (((1 << field->descriptortype) & fixed64_ok) == 0) goto unknown; + break; + case UPB_WIRE_TYPE_DELIMITED: { + uint32_t size; + int ndx = field->descriptortype; + if (_upb_isrepeated(field)) ndx += 18; + ptr = decode_varint32(d, ptr, d->limit, &size); + if (size >= INT32_MAX || (size_t)(d->limit - ptr) < size) { + decode_err(d); /* Length overflow. */ } - - return upb_decode_groupfield(d, group, layout, field_number); + val.str_val.data = ptr; + val.str_val.size = size; + ptr += size; + op = delim_ops[ndx]; + break; } + case UPB_WIRE_TYPE_START_GROUP: + val.int32_val = field_number; + op = OP_SUBMSG; + if (field->descriptortype != UPB_DTYPE_GROUP) goto unknown; + break; case UPB_WIRE_TYPE_END_GROUP: d->end_group = field_number; - return true; + return ptr; default: - CHK(false); + decode_err(d); + } + + if (op >= 0) { + /* Parse, using op for dispatch. */ + switch (field->label) { + case UPB_LABEL_REPEATED: + case _UPB_LABEL_PACKED: + ptr = decode_toarray(d, ptr, msg, layout, field, val, op); + break; + case _UPB_LABEL_MAP: + decode_tomap(d, msg, layout, field, val); + break; + default: + ptr = decode_tomsg(d, ptr, msg, layout, field, val, op); + break; + } + } else { + unknown: + /* Skip unknown field. */ + if (field_number == 0) decode_err(d); + if (wire_type == UPB_WIRE_TYPE_START_GROUP) { + ptr = decode_group(d, ptr, NULL, NULL, field_number); + } + if (msg) { + if (!_upb_msg_addunknown(msg, field_start, ptr - field_start, + d->arena)) { + decode_err(d); + } + } } - } else { - CHK(field_number != 0); - CHK(upb_skip_unknownfielddata(d, tag, -1)); - CHK(upb_append_unknown(d, frame)); - return true; - } -} - -static bool upb_decode_message(upb_decstate *d, char *msg, const upb_msglayout *l) { - upb_decframe frame; - frame.msg = msg; - frame.layout = l; - frame.state = d; - - while (d->ptr < d->limit) { - CHK(upb_decode_field(d, &frame)); } - return true; + if (ptr != d->limit) decode_err(d); + return ptr; } bool upb_decode(const char *buf, size_t size, void *msg, const upb_msglayout *l, upb_arena *arena) { upb_decstate state; - state.ptr = buf; state.limit = buf + size; state.arena = arena; state.depth = 64; state.end_group = 0; - CHK(upb_decode_message(&state, msg, l)); + if (setjmp(state.err)) return false; + + if (size == 0) return true; + decode_msg(&state, buf, msg, l); + return state.end_group == 0; } -#undef CHK +#undef OP_SCALAR_LG2 +#undef OP_FIXPCK_LG2 +#undef OP_VARPCK_LG2 +#undef OP_STRING +#undef OP_SUBMSG /* We encode backwards, to avoid pre-computing lengths (one-pass encode). */ @@ -821,6 +801,7 @@ static bool upb_encode_reserve(upb_encstate *e, size_t bytes) { /* Writes the given bytes to the buffer, handling reserve/advance. */ static bool upb_put_bytes(upb_encstate *e, const void *data, size_t len) { + if (len == 0) return true; CHK(upb_encode_reserve(e, len)); memcpy(e->ptr, data, len); return true; @@ -863,15 +844,14 @@ static bool upb_put_float(upb_encstate *e, float d) { static uint32_t upb_readcase(const char *msg, const upb_msglayout_field *f) { uint32_t ret; - uint32_t offset = ~f->presence; - memcpy(&ret, msg + offset, sizeof(ret)); + memcpy(&ret, msg - f->presence, sizeof(ret)); return ret; } 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)); + return (*UPB_PTR_AT(msg, hasbit / 8, uint8_t)) & (1 << (hasbit % 8)); } static bool upb_put_tag(upb_encstate *e, int field_number, int wire_type) { @@ -879,50 +859,145 @@ static bool upb_put_tag(upb_encstate *e, int field_number, int wire_type) { } static bool upb_put_fixedarray(upb_encstate *e, const upb_array *arr, - size_t size) { - size_t bytes = arr->len * size; - return upb_put_bytes(e, arr->data, bytes) && upb_put_varint(e, bytes); + size_t elem_size, uint32_t tag) { + size_t bytes = arr->len * elem_size; + const char* data = _upb_array_constptr(arr); + const char* ptr = data + bytes - elem_size; + if (tag) { + while (true) { + CHK(upb_put_bytes(e, ptr, elem_size) && upb_put_varint(e, tag)); + if (ptr == data) break; + ptr -= elem_size; + } + return true; + } else { + return upb_put_bytes(e, data, bytes) && upb_put_varint(e, bytes); + } } bool upb_encode_message(upb_encstate *e, const char *msg, const upb_msglayout *m, size_t *size); +static bool upb_encode_scalarfield(upb_encstate *e, const void *_field_mem, + const upb_msglayout *m, + const upb_msglayout_field *f, + bool skip_zero_value) { + const char *field_mem = _field_mem; +#define CASE(ctype, type, wire_type, encodeval) do { \ + ctype val = *(ctype*)field_mem; \ + if (skip_zero_value && val == 0) { \ + return true; \ + } \ + return upb_put_ ## type(e, encodeval) && \ + upb_put_tag(e, f->number, wire_type); \ +} while(0) + + switch (f->descriptortype) { + case UPB_DESCRIPTOR_TYPE_DOUBLE: + CASE(double, double, UPB_WIRE_TYPE_64BIT, val); + case UPB_DESCRIPTOR_TYPE_FLOAT: + CASE(float, float, UPB_WIRE_TYPE_32BIT, val); + case UPB_DESCRIPTOR_TYPE_INT64: + 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(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); + case UPB_DESCRIPTOR_TYPE_FIXED32: + case UPB_DESCRIPTOR_TYPE_SFIXED32: + CASE(uint32_t, fixed32, UPB_WIRE_TYPE_32BIT, val); + case UPB_DESCRIPTOR_TYPE_BOOL: + CASE(bool, varint, UPB_WIRE_TYPE_VARINT, val); + case UPB_DESCRIPTOR_TYPE_SINT32: + CASE(int32_t, varint, UPB_WIRE_TYPE_VARINT, upb_zzencode_32(val)); + case UPB_DESCRIPTOR_TYPE_SINT64: + CASE(int64_t, varint, UPB_WIRE_TYPE_VARINT, upb_zzencode_64(val)); + case UPB_DESCRIPTOR_TYPE_STRING: + case UPB_DESCRIPTOR_TYPE_BYTES: { + upb_strview view = *(upb_strview*)field_mem; + if (skip_zero_value && view.size == 0) { + return true; + } + return upb_put_bytes(e, view.data, view.size) && + upb_put_varint(e, view.size) && + upb_put_tag(e, f->number, UPB_WIRE_TYPE_DELIMITED); + } + case UPB_DESCRIPTOR_TYPE_GROUP: { + size_t size; + 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) && + upb_encode_message(e, submsg, subm, &size) && + upb_put_tag(e, f->number, UPB_WIRE_TYPE_START_GROUP); + } + case UPB_DESCRIPTOR_TYPE_MESSAGE: { + size_t size; + 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) && + upb_put_varint(e, size) && + upb_put_tag(e, f->number, UPB_WIRE_TYPE_DELIMITED); + } + } +#undef CASE + UPB_UNREACHABLE(); +} + static bool upb_encode_array(upb_encstate *e, const char *field_mem, const upb_msglayout *m, const upb_msglayout_field *f) { const upb_array *arr = *(const upb_array**)field_mem; + bool packed = f->label == _UPB_LABEL_PACKED; if (arr == NULL || arr->len == 0) { return true; } -#define VARINT_CASE(ctype, encode) { \ - ctype *start = arr->data; \ - ctype *ptr = start + arr->len; \ - size_t pre_len = e->limit - e->ptr; \ - do { \ - ptr--; \ - CHK(upb_put_varint(e, encode)); \ - } while (ptr != start); \ - CHK(upb_put_varint(e, e->limit - e->ptr - pre_len)); \ -} \ -break; \ -do { ; } while(0) +#define VARINT_CASE(ctype, encode) \ + { \ + const ctype *start = _upb_array_constptr(arr); \ + const ctype *ptr = start + arr->len; \ + size_t pre_len = e->limit - e->ptr; \ + uint32_t tag = packed ? 0 : (f->number << 3) | UPB_WIRE_TYPE_VARINT; \ + do { \ + ptr--; \ + CHK(upb_put_varint(e, encode)); \ + if (tag) CHK(upb_put_varint(e, tag)); \ + } while (ptr != start); \ + if (!tag) CHK(upb_put_varint(e, e->limit - e->ptr - pre_len)); \ + } \ + break; \ + do { \ + ; \ + } while (0) + +#define TAG(wire_type) (packed ? 0 : (f->number << 3 | wire_type)) switch (f->descriptortype) { case UPB_DESCRIPTOR_TYPE_DOUBLE: - CHK(upb_put_fixedarray(e, arr, sizeof(double))); + CHK(upb_put_fixedarray(e, arr, sizeof(double), TAG(UPB_WIRE_TYPE_64BIT))); break; case UPB_DESCRIPTOR_TYPE_FLOAT: - CHK(upb_put_fixedarray(e, arr, sizeof(float))); + CHK(upb_put_fixedarray(e, arr, sizeof(float), TAG(UPB_WIRE_TYPE_32BIT))); break; case UPB_DESCRIPTOR_TYPE_SFIXED64: case UPB_DESCRIPTOR_TYPE_FIXED64: - CHK(upb_put_fixedarray(e, arr, sizeof(uint64_t))); + CHK(upb_put_fixedarray(e, arr, sizeof(uint64_t), TAG(UPB_WIRE_TYPE_64BIT))); break; case UPB_DESCRIPTOR_TYPE_FIXED32: case UPB_DESCRIPTOR_TYPE_SFIXED32: - CHK(upb_put_fixedarray(e, arr, sizeof(uint32_t))); + CHK(upb_put_fixedarray(e, arr, sizeof(uint32_t), TAG(UPB_WIRE_TYPE_32BIT))); break; case UPB_DESCRIPTOR_TYPE_INT64: case UPB_DESCRIPTOR_TYPE_UINT64: @@ -940,8 +1015,8 @@ do { ; } while(0) VARINT_CASE(int64_t, upb_zzencode_64(*ptr)); case UPB_DESCRIPTOR_TYPE_STRING: case UPB_DESCRIPTOR_TYPE_BYTES: { - upb_strview *start = arr->data; - upb_strview *ptr = start + arr->len; + const upb_strview *start = _upb_array_constptr(arr); + const upb_strview *ptr = start + arr->len; do { ptr--; CHK(upb_put_bytes(e, ptr->data, ptr->size) && @@ -951,8 +1026,8 @@ do { ; } while(0) return true; } case UPB_DESCRIPTOR_TYPE_GROUP: { - void **start = arr->data; - void **ptr = start + arr->len; + const void *const*start = _upb_array_constptr(arr); + const void *const*ptr = start + arr->len; const upb_msglayout *subm = m->submsgs[f->submsg_index]; do { size_t size; @@ -964,8 +1039,8 @@ do { ; } while(0) return true; } case UPB_DESCRIPTOR_TYPE_MESSAGE: { - void **start = arr->data; - void **ptr = start + arr->len; + const void *const*start = _upb_array_constptr(arr); + const void *const*ptr = start + arr->len; const upb_msglayout *subm = m->submsgs[f->submsg_index]; do { size_t size; @@ -979,87 +1054,46 @@ do { ; } while(0) } #undef VARINT_CASE - /* We encode all primitive arrays as packed, regardless of what was specified - * in the .proto file. Could special case 1-sized arrays. */ - CHK(upb_put_tag(e, f->number, UPB_WIRE_TYPE_DELIMITED)); + if (packed) { + CHK(upb_put_tag(e, f->number, UPB_WIRE_TYPE_DELIMITED)); + } return true; } -static bool upb_encode_scalarfield(upb_encstate *e, const char *field_mem, - 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) { \ - return true; \ - } \ - return upb_put_ ## type(e, encodeval) && \ - upb_put_tag(e, f->number, wire_type); \ -} while(0) +static bool upb_encode_map(upb_encstate *e, const char *field_mem, + const upb_msglayout *m, + const upb_msglayout_field *f) { + const upb_map *map = *(const upb_map**)field_mem; + const upb_msglayout *entry = m->submsgs[f->submsg_index]; + const upb_msglayout_field *key_field = &entry->fields[0]; + const upb_msglayout_field *val_field = &entry->fields[1]; + upb_strtable_iter i; + if (map == NULL) { + return true; + } - switch (f->descriptortype) { - case UPB_DESCRIPTOR_TYPE_DOUBLE: - CASE(double, double, UPB_WIRE_TYPE_64BIT, val); - case UPB_DESCRIPTOR_TYPE_FLOAT: - CASE(float, float, UPB_WIRE_TYPE_32BIT, val); - case UPB_DESCRIPTOR_TYPE_INT64: - 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(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); - case UPB_DESCRIPTOR_TYPE_FIXED32: - case UPB_DESCRIPTOR_TYPE_SFIXED32: - CASE(uint32_t, fixed32, UPB_WIRE_TYPE_32BIT, val); - case UPB_DESCRIPTOR_TYPE_BOOL: - CASE(bool, varint, UPB_WIRE_TYPE_VARINT, val); - case UPB_DESCRIPTOR_TYPE_SINT32: - CASE(int32_t, varint, UPB_WIRE_TYPE_VARINT, upb_zzencode_32(val)); - case UPB_DESCRIPTOR_TYPE_SINT64: - CASE(int64_t, varint, UPB_WIRE_TYPE_VARINT, upb_zzencode_64(val)); - case UPB_DESCRIPTOR_TYPE_STRING: - case UPB_DESCRIPTOR_TYPE_BYTES: { - upb_strview view = *(upb_strview*)field_mem; - if (skip_zero_value && view.size == 0) { - return true; - } - return upb_put_bytes(e, view.data, view.size) && - upb_put_varint(e, view.size) && - upb_put_tag(e, f->number, UPB_WIRE_TYPE_DELIMITED); - } - case UPB_DESCRIPTOR_TYPE_GROUP: { - size_t size; - 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) && - upb_encode_message(e, submsg, subm, &size) && - upb_put_tag(e, f->number, UPB_WIRE_TYPE_START_GROUP); - } - case UPB_DESCRIPTOR_TYPE_MESSAGE: { - size_t size; - 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) && - upb_put_varint(e, size) && - upb_put_tag(e, f->number, UPB_WIRE_TYPE_DELIMITED); - } + upb_strtable_begin(&i, &map->table); + for(; !upb_strtable_done(&i); upb_strtable_next(&i)) { + size_t pre_len = e->limit - e->ptr; + size_t size; + upb_strview key = upb_strtable_iter_key(&i); + const upb_value val = upb_strtable_iter_value(&i); + const void *keyp = + map->key_size == UPB_MAPTYPE_STRING ? (void *)&key : key.data; + const void *valp = + map->val_size == UPB_MAPTYPE_STRING ? upb_value_getptr(val) : &val; + + CHK(upb_encode_scalarfield(e, valp, entry, val_field, false)); + CHK(upb_encode_scalarfield(e, keyp, entry, key_field, false)); + size = (e->limit - e->ptr) - pre_len; + CHK(upb_put_varint(e, size)); + CHK(upb_put_tag(e, f->number, UPB_WIRE_TYPE_DELIMITED)); } -#undef CASE - UPB_UNREACHABLE(); + + return true; } + bool upb_encode_message(upb_encstate *e, const char *msg, const upb_msglayout *m, size_t *size) { int i; @@ -1067,11 +1101,19 @@ bool upb_encode_message(upb_encstate *e, const char *msg, const char *unknown; size_t unknown_size; + unknown = upb_msg_getunknown(msg, &unknown_size); + + if (unknown) { + upb_put_bytes(e, unknown, unknown_size); + } + for (i = m->field_count - 1; i >= 0; i--) { const upb_msglayout_field *f = &m->fields[i]; - if (f->label == UPB_LABEL_REPEATED) { + if (_upb_isrepeated(f)) { CHK(upb_encode_array(e, msg + f->offset, m, f)); + } else if (f->label == _UPB_LABEL_MAP) { + CHK(upb_encode_map(e, msg + f->offset, m, f)); } else { bool skip_empty = false; if (f->presence == 0) { @@ -1092,12 +1134,6 @@ bool upb_encode_message(upb_encstate *e, const char *msg, } } - 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; } @@ -1131,24 +1167,27 @@ char *upb_encode(const void *msg, const upb_msglayout *m, upb_arena *arena, -#define VOIDPTR_AT(msg, ofs) (void*)((char*)msg + (int)ofs) +/** upb_msg *******************************************************************/ -/* Internal members of a upb_msg. We can change this without breaking binary - * compatibility. We put these before the user's data. The user's upb_msg* - * points after the upb_msg_internal. */ - -/* Used when a message is not extendable. */ -typedef struct { - char *unknown; - size_t unknown_len; - size_t unknown_size; -} upb_msg_internal; +static const char _upb_fieldtype_to_sizelg2[12] = { + 0, + 0, /* UPB_TYPE_BOOL */ + 2, /* UPB_TYPE_FLOAT */ + 2, /* UPB_TYPE_INT32 */ + 2, /* UPB_TYPE_UINT32 */ + 2, /* UPB_TYPE_ENUM */ + UPB_SIZE(2, 3), /* UPB_TYPE_MESSAGE */ + 3, /* UPB_TYPE_DOUBLE */ + 3, /* UPB_TYPE_INT64 */ + 3, /* UPB_TYPE_UINT64 */ + UPB_SIZE(3, 4), /* UPB_TYPE_STRING */ + UPB_SIZE(3, 4), /* UPB_TYPE_BYTES */ +}; -/* Used when a message is extendable. */ -typedef struct { - upb_inttable *extdict; - upb_msg_internal base; -} upb_msg_internal_withext; +static uintptr_t tag_arrptr(void* ptr, int elem_size_lg2) { + UPB_ASSERT(elem_size_lg2 <= 4); + return (uintptr_t)ptr | elem_size_lg2; +} static int upb_msg_internalsize(const upb_msglayout *l) { return sizeof(upb_msg_internal) - l->extendable * sizeof(void *); @@ -1159,22 +1198,22 @@ static size_t upb_msg_sizeof(const upb_msglayout *l) { } static upb_msg_internal *upb_msg_getinternal(upb_msg *msg) { - return VOIDPTR_AT(msg, -sizeof(upb_msg_internal)); + return UPB_PTR_AT(msg, -sizeof(upb_msg_internal), upb_msg_internal); } static const upb_msg_internal *upb_msg_getinternal_const(const upb_msg *msg) { - return VOIDPTR_AT(msg, -sizeof(upb_msg_internal)); + return UPB_PTR_AT(msg, -sizeof(upb_msg_internal), upb_msg_internal); } static upb_msg_internal_withext *upb_msg_getinternalwithext( upb_msg *msg, const upb_msglayout *l) { UPB_ASSERT(l->extendable); - return VOIDPTR_AT(msg, -sizeof(upb_msg_internal_withext)); + return UPB_PTR_AT(msg, -sizeof(upb_msg_internal_withext), + upb_msg_internal_withext); } -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 *_upb_msg_new(const upb_msglayout *l, upb_arena *a) { + void *mem = upb_arena_malloc(a, upb_msg_sizeof(l)); upb_msg_internal *in; upb_msg *msg; @@ -1182,7 +1221,7 @@ upb_msg *upb_msg_new(const upb_msglayout *l, upb_arena *a) { return NULL; } - msg = VOIDPTR_AT(mem, upb_msg_internalsize(l)); + msg = UPB_PTR_AT(mem, upb_msg_internalsize(l), upb_msg); /* Initialize normal members. */ memset(msg, 0, l->size); @@ -1200,66 +1239,122 @@ upb_msg *upb_msg_new(const upb_msglayout *l, upb_arena *a) { return msg; } -upb_array *upb_array_new(upb_arena *a) { - upb_array *ret = upb_arena_malloc(a, sizeof(upb_array)); - - if (!ret) { - return NULL; - } - - ret->data = NULL; - ret->len = 0; - ret->size = 0; - - return ret; -} - -void upb_msg_addunknown(upb_msg *msg, const char *data, size_t len, - upb_arena *arena) { +bool _upb_msg_addunknown(upb_msg *msg, const char *data, size_t len, + upb_arena *arena) { upb_msg_internal *in = upb_msg_getinternal(msg); if (len > in->unknown_size - in->unknown_len) { upb_alloc *alloc = upb_arena_alloc(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); + void *mem = upb_realloc(alloc, in->unknown, in->unknown_size, newsize); + if (!mem) return false; + in->unknown = mem; in->unknown_size = newsize; } memcpy(in->unknown + in->unknown_len, data, len); in->unknown_len += len; + return true; } const char *upb_msg_getunknown(const upb_msg *msg, size_t *len) { - const upb_msg_internal* in = upb_msg_getinternal_const(msg); + const upb_msg_internal *in = upb_msg_getinternal_const(msg); *len = in->unknown_len; return in->unknown; } -#undef VOIDPTR_AT +/** upb_array *****************************************************************/ +upb_array *_upb_array_new(upb_arena *a, upb_fieldtype_t type) { + upb_array *arr = upb_arena_malloc(a, sizeof(upb_array)); -#ifdef UPB_MSVC_VSNPRINTF -/* Visual C++ earlier than 2015 doesn't have standard C99 snprintf and - * vsnprintf. To support them, missing functions are manually implemented - * using the existing secure functions. */ -int msvc_vsnprintf(char* s, size_t n, const char* format, va_list arg) { - if (!s) { - return _vscprintf(format, arg); + if (!arr) { + return NULL; } - int ret = _vsnprintf_s(s, n, _TRUNCATE, format, arg); - if (ret < 0) { - ret = _vscprintf(format, arg); + + arr->data = tag_arrptr(NULL, _upb_fieldtype_to_sizelg2[type]); + arr->len = 0; + arr->size = 0; + + return arr; +} + +bool _upb_array_realloc(upb_array *arr, size_t min_size, upb_arena *arena) { + size_t new_size = UPB_MAX(arr->size, 4); + int elem_size_lg2 = arr->data & 7; + size_t old_bytes = arr->size << elem_size_lg2; + size_t new_bytes; + void* ptr = _upb_array_ptr(arr); + + /* Log2 ceiling of size. */ + while (new_size < min_size) new_size *= 2; + + new_bytes = new_size << elem_size_lg2; + ptr = upb_arena_realloc(arena, ptr, old_bytes, new_bytes); + + if (!ptr) { + return false; } - return ret; + + arr->data = tag_arrptr(ptr, elem_size_lg2); + arr->size = new_size; + return true; +} + +static upb_array *getorcreate_array(upb_array **arr_ptr, upb_fieldtype_t type, + upb_arena *arena) { + upb_array *arr = *arr_ptr; + if (!arr) { + arr = _upb_array_new(arena, type); + if (!arr) return NULL; + *arr_ptr = arr; + } + return arr; } -int msvc_snprintf(char* s, size_t n, const char* format, ...) { - va_list arg; - va_start(arg, format); - int ret = msvc_vsnprintf(s, n, format, arg); - va_end(arg); - return ret; +static bool resize_array(upb_array *arr, size_t size, upb_arena *arena) { + if (size > arr->size && !_upb_array_realloc(arr, size, arena)) { + return false; + } + + arr->len = size; + return true; +} + +void *_upb_array_resize_fallback(upb_array **arr_ptr, size_t size, + upb_fieldtype_t type, upb_arena *arena) { + upb_array *arr = getorcreate_array(arr_ptr, type, arena); + return arr && resize_array(arr, size, arena) ? _upb_array_ptr(arr) : NULL; +} + +bool _upb_array_append_fallback(upb_array **arr_ptr, const void *value, + upb_fieldtype_t type, upb_arena *arena) { + upb_array *arr = getorcreate_array(arr_ptr, type, arena); + size_t elem = arr->len; + int lg2 = _upb_fieldtype_to_sizelg2[type]; + char *data; + + if (!arr || !resize_array(arr, elem + 1, arena)) return false; + + data = _upb_array_ptr(arr); + memcpy(data + (elem << lg2), value, 1 << lg2); + return true; +} + +/** upb_map *******************************************************************/ + +upb_map *_upb_map_new(upb_arena *a, size_t key_size, size_t value_size) { + upb_map *map = upb_arena_malloc(a, sizeof(upb_map)); + + if (!map) { + return NULL; + } + + upb_strtable_init2(&map->table, UPB_CTYPE_INT32, upb_arena_alloc(a)); + map->key_size = key_size; + map->val_size = value_size; + + return map; } -#endif /* ** upb_table Implementation ** @@ -1276,12 +1371,6 @@ int msvc_snprintf(char* s, size_t n, const char* format, ...) { #define ARRAY_SIZE(x) \ ((sizeof(x)/sizeof(0[x])) / ((size_t)(!(sizeof(x) % sizeof(0[x]))))) -static void upb_check_alloc(upb_table *t, upb_alloc *a) { - UPB_UNUSED(t); - UPB_UNUSED(a); - UPB_ASSERT_DEBUGVAR(t->alloc == a); -} - static const double MAX_LOAD = 0.85; /* The minimum utilization of the array part of a mixed hash/array table. This @@ -1360,17 +1449,12 @@ static bool isfull(upb_table *t) { } } -static bool init(upb_table *t, upb_ctype_t ctype, uint8_t size_lg2, - upb_alloc *a) { +static bool init(upb_table *t, uint8_t size_lg2, upb_alloc *a) { size_t bytes; t->count = 0; - t->ctype = ctype; t->size_lg2 = size_lg2; t->mask = upb_table_size(t) ? upb_table_size(t) - 1 : 0; -#ifndef NDEBUG - t->alloc = a; -#endif bytes = upb_table_size(t) * sizeof(upb_tabent); if (bytes > 0) { t->entries = upb_malloc(a, bytes); @@ -1383,7 +1467,6 @@ static bool init(upb_table *t, upb_ctype_t ctype, uint8_t size_lg2, } static void uninit(upb_table *t, upb_alloc *a) { - upb_check_alloc(t, a); upb_free(a, mutable_entries(t)); } @@ -1419,7 +1502,7 @@ static bool lookup(const upb_table *t, lookupkey_t key, upb_value *v, const upb_tabent *e = findentry(t, key, hash, eql); if (e) { if (v) { - _upb_value_setval(v, e->val.val, t->ctype); + _upb_value_setval(v, e->val.val); } return true; } else { @@ -1435,7 +1518,6 @@ static void insert(upb_table *t, lookupkey_t key, upb_tabkey tabkey, upb_tabent *our_e; UPB_ASSERT(findentry(t, key, hash, eql) == NULL); - UPB_ASSERT_DEBUGVAR(val.ctype == t->ctype); t->count++; mainpos_e = getentry_mutable(t, hash); @@ -1481,7 +1563,7 @@ static bool rm(upb_table *t, lookupkey_t key, upb_value *val, if (eql(chain->key, key)) { /* Element to remove is at the head of its chain. */ t->count--; - if (val) _upb_value_setval(val, chain->val.val, t->ctype); + if (val) _upb_value_setval(val, chain->val.val); if (removed) *removed = chain->key; if (chain->next) { upb_tabent *move = (upb_tabent*)chain->next; @@ -1501,7 +1583,7 @@ static bool rm(upb_table *t, lookupkey_t key, upb_value *val, /* Found element to remove. */ upb_tabent *rm = (upb_tabent*)chain->next; t->count--; - if (val) _upb_value_setval(val, chain->next->val.val, t->ctype); + if (val) _upb_value_setval(val, chain->next->val.val); if (removed) *removed = rm->key; rm->key = 0; /* Make the slot empty. */ chain->next = rm->next; @@ -1554,7 +1636,13 @@ static bool streql(upb_tabkey k1, lookupkey_t k2) { } bool upb_strtable_init2(upb_strtable *t, upb_ctype_t ctype, upb_alloc *a) { - return init(&t->t, ctype, 2, a); + return init(&t->t, 2, a); +} + +void upb_strtable_clear(upb_strtable *t) { + size_t bytes = upb_table_size(&t->t) * sizeof(upb_tabent); + t->t.count = 0; + memset((char*)t->t.entries, 0, bytes); } void upb_strtable_uninit2(upb_strtable *t, upb_alloc *a) { @@ -1568,18 +1656,14 @@ bool upb_strtable_resize(upb_strtable *t, size_t size_lg2, upb_alloc *a) { upb_strtable new_table; upb_strtable_iter i; - upb_check_alloc(&t->t, a); - - if (!init(&new_table.t, t->t.ctype, size_lg2, a)) + if (!init(&new_table.t, size_lg2, a)) return false; upb_strtable_begin(&i, t); for ( ; !upb_strtable_done(&i); upb_strtable_next(&i)) { + upb_strview key = upb_strtable_iter_key(&i); upb_strtable_insert3( - &new_table, - upb_strtable_iter_key(&i), - upb_strtable_iter_keylength(&i), - upb_strtable_iter_value(&i), - a); + &new_table, key.data, key.size, + upb_strtable_iter_value(&i), a); } upb_strtable_uninit2(t, a); *t = new_table; @@ -1592,8 +1676,6 @@ bool upb_strtable_insert3(upb_strtable *t, const char *k, size_t len, upb_tabkey tabkey; uint32_t hash; - upb_check_alloc(&t->t, a); - if (isfull(&t->t)) { /* Need to resize. New table of double the size, add old elements to it. */ if (!upb_strtable_resize(t, t->t.size_lg2 + 1, a)) { @@ -1621,7 +1703,10 @@ bool upb_strtable_remove3(upb_strtable *t, const char *key, size_t len, uint32_t hash = upb_murmur_hash2(key, len, 0); upb_tabkey tabkey; if (rm(&t->t, strkey2(key, len), val, &tabkey, hash, &streql)) { - upb_free(alloc, (void*)tabkey); + if (alloc) { + /* Arena-based allocs don't need to free and won't pass this. */ + upb_free(alloc, (void*)tabkey); + } return true; } else { return false; @@ -1630,10 +1715,6 @@ bool upb_strtable_remove3(upb_strtable *t, const char *key, size_t len, /* Iteration */ -static const upb_tabent *str_tabent(const upb_strtable_iter *i) { - return &i->t->t.entries[i->index]; -} - void upb_strtable_begin(upb_strtable_iter *i, const upb_strtable *t) { i->t = t; i->index = begin(&t->t); @@ -1649,21 +1730,18 @@ bool upb_strtable_done(const upb_strtable_iter *i) { upb_tabent_isempty(str_tabent(i)); } -const char *upb_strtable_iter_key(const upb_strtable_iter *i) { - UPB_ASSERT(!upb_strtable_done(i)); - return upb_tabstr(str_tabent(i)->key, NULL); -} - -size_t upb_strtable_iter_keylength(const upb_strtable_iter *i) { +upb_strview upb_strtable_iter_key(const upb_strtable_iter *i) { + upb_strview key; uint32_t len; UPB_ASSERT(!upb_strtable_done(i)); - upb_tabstr(str_tabent(i)->key, &len); - return len; + key.data = upb_tabstr(str_tabent(i)->key, &len); + key.size = len; + return key; } upb_value upb_strtable_iter_value(const upb_strtable_iter *i) { UPB_ASSERT(!upb_strtable_done(i)); - return _upb_value_val(str_tabent(i)->val.val, i->t->t.ctype); + return _upb_value_val(str_tabent(i)->val.val); } void upb_strtable_iter_setdone(upb_strtable_iter *i) { @@ -1729,11 +1807,11 @@ static void check(upb_inttable *t) { #endif } -bool upb_inttable_sizedinit(upb_inttable *t, upb_ctype_t ctype, - size_t asize, int hsize_lg2, upb_alloc *a) { +bool upb_inttable_sizedinit(upb_inttable *t, size_t asize, int hsize_lg2, + upb_alloc *a) { size_t array_bytes; - if (!init(&t->t, ctype, hsize_lg2, a)) return false; + if (!init(&t->t, hsize_lg2, a)) return false; /* Always make the array part at least 1 long, so that we know key 0 * won't be in the hash part, which simplifies things. */ t->array_size = UPB_MAX(1, asize); @@ -1750,7 +1828,7 @@ bool upb_inttable_sizedinit(upb_inttable *t, upb_ctype_t ctype, } bool upb_inttable_init2(upb_inttable *t, upb_ctype_t ctype, upb_alloc *a) { - return upb_inttable_sizedinit(t, ctype, 0, 4, a); + return upb_inttable_sizedinit(t, 0, 4, a); } void upb_inttable_uninit2(upb_inttable *t, upb_alloc *a) { @@ -1764,8 +1842,6 @@ bool upb_inttable_insert2(upb_inttable *t, uintptr_t key, upb_value val, tabval.val = val.val; UPB_ASSERT(upb_arrhas(tabval)); /* This will reject (uint64_t)-1. Fix this. */ - upb_check_alloc(&t->t, a); - if (key < t->array_size) { UPB_ASSERT(!upb_arrhas(t->array[key])); t->array_count++; @@ -1776,7 +1852,7 @@ bool upb_inttable_insert2(upb_inttable *t, uintptr_t key, upb_value val, size_t i; upb_table new_table; - if (!init(&new_table, t->t.ctype, t->t.size_lg2 + 1, a)) { + if (!init(&new_table, t->t.size_lg2 + 1, a)) { return false; } @@ -1785,7 +1861,7 @@ bool upb_inttable_insert2(upb_inttable *t, uintptr_t key, upb_value val, uint32_t hash; upb_value v; - _upb_value_setval(&v, e->val.val, t->t.ctype); + _upb_value_setval(&v, e->val.val); hash = upb_inthash(e->key); insert(&new_table, intkey(e->key), e->key, v, hash, &inthash, &inteql); } @@ -1804,7 +1880,7 @@ bool upb_inttable_insert2(upb_inttable *t, uintptr_t key, upb_value val, bool upb_inttable_lookup(const upb_inttable *t, uintptr_t key, upb_value *v) { const upb_tabval *table_v = inttable_val_const(t, key); if (!table_v) return false; - if (v) _upb_value_setval(v, table_v->val, t->t.ctype); + if (v) _upb_value_setval(v, table_v->val); return true; } @@ -1822,7 +1898,7 @@ bool upb_inttable_remove(upb_inttable *t, uintptr_t key, upb_value *val) { upb_tabval empty = UPB_TABVALUE_EMPTY_INIT; t->array_count--; if (val) { - _upb_value_setval(val, t->array[key].val, t->t.ctype); + _upb_value_setval(val, t->array[key].val); } mutable_array(t)[key] = empty; success = true; @@ -1837,7 +1913,6 @@ bool upb_inttable_remove(upb_inttable *t, uintptr_t key, upb_value *val) { } bool upb_inttable_push2(upb_inttable *t, upb_value val, upb_alloc *a) { - upb_check_alloc(&t->t, a); return upb_inttable_insert2(t, upb_inttable_count(t), val, a); } @@ -1850,7 +1925,6 @@ upb_value upb_inttable_pop(upb_inttable *t) { bool upb_inttable_insertptr2(upb_inttable *t, const void *key, upb_value val, upb_alloc *a) { - upb_check_alloc(&t->t, a); return upb_inttable_insert2(t, (uintptr_t)key, val, a); } @@ -1875,8 +1949,6 @@ void upb_inttable_compact2(upb_inttable *t, upb_alloc *a) { int size_lg2; upb_inttable new_t; - upb_check_alloc(&t->t, a); - upb_inttable_begin(&i, t); for (; !upb_inttable_done(&i); upb_inttable_next(&i)) { uintptr_t key = upb_inttable_iter_key(&i); @@ -1909,7 +1981,7 @@ void upb_inttable_compact2(upb_inttable *t, upb_alloc *a) { size_t hash_size = hash_count ? (hash_count / MAX_LOAD) + 1 : 0; int hashsize_lg2 = log2ceil(hash_size); - upb_inttable_sizedinit(&new_t, t->t.ctype, arr_size, hashsize_lg2, a); + upb_inttable_sizedinit(&new_t, arr_size, hashsize_lg2, a); upb_inttable_begin(&i, t); for (; !upb_inttable_done(&i); upb_inttable_next(&i)) { uintptr_t k = upb_inttable_iter_key(&i); @@ -1975,8 +2047,7 @@ uintptr_t upb_inttable_iter_key(const upb_inttable_iter *i) { upb_value upb_inttable_iter_value(const upb_inttable_iter *i) { UPB_ASSERT(!upb_inttable_done(i)); return _upb_value_val( - i->array_part ? i->t->array[i->index].val : int_tabent(i)->val.val, - i->t->t.ctype); + i->array_part ? i->t->array[i->index].val : int_tabent(i)->val.val); } void upb_inttable_iter_setdone(upb_inttable_iter *i) { @@ -2016,7 +2087,8 @@ uint32_t upb_murmur_hash2(const void *key, size_t len, uint32_t seed) { /* Mix 4 bytes at a time into the hash */ const uint8_t * data = (const uint8_t *)key; while(len >= 4) { - uint32_t k = *(uint32_t *)data; + uint32_t k; + memcpy(&k, data, sizeof(k)); k *= m; k ^= k >> r; @@ -2181,17 +2253,6 @@ uint32_t upb_murmur_hash2(const void * key, size_t len, uint32_t seed) { #include -/* Guarantee null-termination and provide ellipsis truncation. - * It may be tempting to "optimize" this by initializing these final - * four bytes up-front and then being careful never to overwrite them, - * this is safer and simpler. */ -static void nullz(upb_status *status) { - const char *ellipsis = "..."; - size_t len = strlen(ellipsis); - UPB_ASSERT(sizeof(status->msg) > len); - memcpy(status->msg + sizeof(status->msg) - len, ellipsis, len); -} - /* upb_status *****************************************************************/ void upb_status_clear(upb_status *status) { @@ -2207,8 +2268,8 @@ const char *upb_status_errmsg(const upb_status *status) { return status->msg; } void upb_status_seterrmsg(upb_status *status, const char *msg) { if (!status) return; status->ok = false; - strncpy(status->msg, msg, sizeof(status->msg)); - nullz(status); + strncpy(status->msg, msg, UPB_STATUS_MAX_MESSAGE - 1); + status->msg[UPB_STATUS_MAX_MESSAGE - 1] = '\0'; } void upb_status_seterrf(upb_status *status, const char *fmt, ...) { @@ -2222,7 +2283,7 @@ void upb_status_vseterrf(upb_status *status, const char *fmt, va_list args) { if (!status) return; status->ok = false; _upb_vsnprintf(status->msg, sizeof(status->msg), fmt, args); - nullz(status); + status->msg[UPB_STATUS_MAX_MESSAGE - 1] = '\0'; } /* upb_alloc ******************************************************************/ @@ -2244,16 +2305,10 @@ upb_alloc upb_alloc_global = {&upb_global_allocfunc}; /* upb_arena ******************************************************************/ /* Be conservative and choose 16 in case anyone is using SSE. */ -static const size_t maxalign = 16; - -static size_t align_up_max(size_t size) { - return ((size + maxalign - 1) / maxalign) * maxalign; -} struct upb_arena { - /* We implement the allocator interface. - * This must be the first member of upb_arena! */ - upb_alloc alloc; + _upb_arena_head head; + char *start; /* Allocator to allocate arena blocks. We are responsible for freeing these * when we are destroyed. */ @@ -2272,8 +2327,6 @@ struct upb_arena { typedef struct mem_block { struct mem_block *next; - size_t size; - size_t used; bool owned; /* Data follows. */ } mem_block; @@ -2288,12 +2341,17 @@ static void upb_arena_addblock(upb_arena *a, void *ptr, size_t size, bool owned) { mem_block *block = ptr; + if (a->block_head) { + a->bytes_allocated += a->head.ptr - a->start; + } + block->next = a->block_head; - block->size = size; - block->used = align_up_max(sizeof(mem_block)); block->owned = owned; a->block_head = block; + a->start = (char*)block + _upb_arena_alignup(sizeof(mem_block)); + a->head.ptr = a->start; + a->head.end = (char*)block + size; /* TODO(haberman): ASAN poison. */ } @@ -2312,39 +2370,31 @@ static mem_block *upb_arena_allocblock(upb_arena *a, size_t size) { return block; } +void *_upb_arena_slowmalloc(upb_arena *a, size_t size) { + mem_block *block = upb_arena_allocblock(a, size); + if (!block) return NULL; /* Out of memory. */ + return upb_arena_malloc(a, size); +} + static void *upb_arena_doalloc(upb_alloc *alloc, void *ptr, size_t oldsize, size_t size) { upb_arena *a = (upb_arena*)alloc; /* upb_alloc is initial member. */ - mem_block *block = a->block_head; void *ret; if (size == 0) { return NULL; /* We are an arena, don't need individual frees. */ } - size = align_up_max(size); + ret = upb_arena_malloc(a, size); + if (!ret) return NULL; /* TODO(haberman): special-case if this is a realloc of the last alloc? */ - if (!block || block->size - block->used < size) { - /* Slow path: have to allocate a new block. */ - block = upb_arena_allocblock(a, size); - - if (!block) { - return NULL; /* Out of memory. */ - } - } - - ret = (char*)block + block->used; - block->used += size; - if (oldsize > 0) { memcpy(ret, ptr, oldsize); /* Preserve existing data. */ } /* TODO(haberman): ASAN unpoison. */ - - a->bytes_allocated += size; return ret; } @@ -2373,7 +2423,10 @@ upb_arena *upb_arena_init(void *mem, size_t n, upb_alloc *alloc) { a = (void*)((char*)mem + n - sizeof(*a)); n -= sizeof(*a); - a->alloc.func = &upb_arena_doalloc; + a->head.alloc.func = &upb_arena_doalloc; + a->head.ptr = NULL; + a->head.end = NULL; + a->start = NULL; a->block_alloc = &upb_alloc_global; a->bytes_allocated = 0; a->next_block_size = 256; @@ -2413,7 +2466,7 @@ void upb_arena_free(upb_arena *a) { } bool upb_arena_addcleanup(upb_arena *a, void *ud, upb_cleanup_func *func) { - cleanup_ent *ent = upb_malloc(&a->alloc, sizeof(cleanup_ent)); + cleanup_ent *ent = upb_malloc(&a->head.alloc, sizeof(cleanup_ent)); if (!ent) { return false; /* Out of memory. */ } @@ -2427,7 +2480,7 @@ bool upb_arena_addcleanup(upb_arena *a, void *ud, upb_cleanup_func *func) { } size_t upb_arena_bytesallocated(const upb_arena *a) { - return a->bytes_allocated; + return a->bytes_allocated + (a->head.ptr - a->start); } /* This file was generated by upbc (the upb compiler) from the input * file: @@ -2558,23 +2611,24 @@ 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}, +static const upb_msglayout_field google_protobuf_FieldDescriptorProto__fields[11] = { + {1, UPB_SIZE(36, 40), 6, 0, 9, 1}, + {2, UPB_SIZE(44, 56), 7, 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}, + {6, UPB_SIZE(52, 72), 8, 0, 9, 1}, + {7, UPB_SIZE(60, 88), 9, 0, 9, 1}, + {8, UPB_SIZE(76, 120), 11, 0, 11, 1}, {9, UPB_SIZE(28, 28), 4, 0, 5, 1}, - {10, UPB_SIZE(64, 96), 9, 0, 9, 1}, + {10, UPB_SIZE(68, 104), 10, 0, 9, 1}, + {17, UPB_SIZE(32, 32), 5, 0, 8, 1}, }; const upb_msglayout google_protobuf_FieldDescriptorProto_msginit = { &google_protobuf_FieldDescriptorProto_submsgs[0], &google_protobuf_FieldDescriptorProto__fields[0], - UPB_SIZE(80, 128), 10, false, + UPB_SIZE(80, 128), 11, false, }; static const upb_msglayout *const google_protobuf_OneofDescriptorProto_submsgs[1] = { @@ -2869,8 +2923,8 @@ const upb_msglayout google_protobuf_SourceCodeInfo_msginit = { }; static const upb_msglayout_field google_protobuf_SourceCodeInfo_Location__fields[5] = { - {1, UPB_SIZE(20, 40), 0, 0, 5, 3}, - {2, UPB_SIZE(24, 48), 0, 0, 5, 3}, + {1, UPB_SIZE(20, 40), 0, 0, 5, _UPB_LABEL_PACKED}, + {2, UPB_SIZE(24, 48), 0, 0, 5, _UPB_LABEL_PACKED}, {3, UPB_SIZE(4, 8), 1, 0, 9, 1}, {4, UPB_SIZE(12, 24), 2, 0, 9, 1}, {6, UPB_SIZE(28, 56), 0, 0, 9, 3}, @@ -2897,7 +2951,7 @@ const upb_msglayout google_protobuf_GeneratedCodeInfo_msginit = { }; static const upb_msglayout_field google_protobuf_GeneratedCodeInfo_Annotation__fields[4] = { - {1, UPB_SIZE(20, 32), 0, 0, 5, 3}, + {1, UPB_SIZE(20, 32), 0, 0, 5, _UPB_LABEL_PACKED}, {2, UPB_SIZE(12, 16), 3, 0, 9, 1}, {3, UPB_SIZE(4, 4), 1, 0, 5, 1}, {4, UPB_SIZE(8, 8), 2, 0, 5, 1}, @@ -2936,6 +2990,7 @@ struct upb_fielddef { const upb_filedef *file; const upb_msgdef *msgdef; const char *full_name; + const char *json_name; union { int64_t sint; uint64_t uint; @@ -2951,16 +3006,19 @@ struct upb_fielddef { const google_protobuf_FieldDescriptorProto *unresolved; } sub; uint32_t number_; - uint32_t index_; + uint16_t index_; + uint16_t layout_index; uint32_t selector_base; /* Used to index into a upb::Handlers table. */ bool is_extension_; bool lazy_; bool packed_; + bool proto3_optional_; upb_descriptortype_t type_; upb_label_t label_; }; struct upb_msgdef { + const upb_msglayout *layout; const upb_filedef *file; const char *full_name; uint32_t selector_count; @@ -3024,10 +3082,15 @@ struct upb_symtab { /* Inside a symtab we store tagged pointers to specific def types. */ typedef enum { - UPB_DEFTYPE_MSG = 0, - UPB_DEFTYPE_ENUM = 1, - UPB_DEFTYPE_FIELD = 2, - UPB_DEFTYPE_ONEOF = 3 + UPB_DEFTYPE_FIELD = 0, + + /* Only inside symtab table. */ + UPB_DEFTYPE_MSG = 1, + UPB_DEFTYPE_ENUM = 2, + + /* Only inside message table. */ + UPB_DEFTYPE_ONEOF = 1, + UPB_DEFTYPE_FIELD_JSONNAME = 2 } upb_deftype_t; static const void *unpack_def(upb_value v, upb_deftype_t type) { @@ -3260,7 +3323,7 @@ int32_t upb_enumdef_default(const upb_enumdef *e) { } int upb_enumdef_numvals(const upb_enumdef *e) { - return upb_strtable_count(&e->ntoi); + return (int)upb_strtable_count(&e->ntoi); } void upb_enum_begin(upb_enum_iter *i, const upb_enumdef *e) { @@ -3288,7 +3351,7 @@ const char *upb_enumdef_iton(const upb_enumdef *def, int32_t num) { } const char *upb_enum_iter_name(upb_enum_iter *iter) { - return upb_strtable_iter_key(iter); + return upb_strtable_iter_key(iter).data; } int32_t upb_enum_iter_number(upb_enum_iter *iter) { @@ -3369,47 +3432,12 @@ const char *upb_fielddef_name(const upb_fielddef *f) { return shortdefname(f->full_name); } -uint32_t upb_fielddef_selectorbase(const upb_fielddef *f) { - return f->selector_base; +const char *upb_fielddef_jsonname(const upb_fielddef *f) { + return f->json_name; } -size_t upb_fielddef_getjsonname(const upb_fielddef *f, char *buf, size_t len) { - const char *name = upb_fielddef_name(f); - size_t src, dst = 0; - bool ucase_next = false; - -#define WRITE(byte) \ - ++dst; \ - if (dst < len) buf[dst - 1] = byte; \ - else if (dst == len) buf[dst - 1] = '\0' - - if (!name) { - WRITE('\0'); - return 0; - } - - /* Implement the transformation as described in the spec: - * 1. upper case all letters after an underscore. - * 2. remove all underscores. - */ - for (src = 0; name[src]; src++) { - if (name[src] == '_') { - ucase_next = true; - continue; - } - - if (ucase_next) { - WRITE(toupper(name[src])); - ucase_next = false; - } else { - WRITE(name[src]); - } - } - - WRITE('\0'); - return dst; - -#undef WRITE +uint32_t upb_fielddef_selectorbase(const upb_fielddef *f) { + return f->selector_base; } const upb_msgdef *upb_fielddef_containingtype(const upb_fielddef *f) { @@ -3432,7 +3460,7 @@ int64_t upb_fielddef_defaultint64(const upb_fielddef *f) { int32_t upb_fielddef_defaultint32(const upb_fielddef *f) { chkdefaulttype(f, UPB_TYPE_INT32); - return f->defaultval.sint; + return (int32_t)f->defaultval.sint; } uint64_t upb_fielddef_defaultuint64(const upb_fielddef *f) { @@ -3442,7 +3470,7 @@ uint64_t upb_fielddef_defaultuint64(const upb_fielddef *f) { uint32_t upb_fielddef_defaultuint32(const upb_fielddef *f) { chkdefaulttype(f, UPB_TYPE_UINT32); - return f->defaultval.uint; + return (uint32_t)f->defaultval.uint; } bool upb_fielddef_defaultbool(const upb_fielddef *f) { @@ -3484,6 +3512,10 @@ const upb_enumdef *upb_fielddef_enumsubdef(const upb_fielddef *f) { return f->sub.enumdef; } +const upb_msglayout_field *upb_fielddef_layout(const upb_fielddef *f) { + return &f->msgdef->layout->fields[f->layout_index]; +} + bool upb_fielddef_issubmsg(const upb_fielddef *f) { return upb_fielddef_type(f) == UPB_TYPE_MESSAGE; } @@ -3513,6 +3545,7 @@ bool upb_fielddef_hassubdef(const upb_fielddef *f) { bool upb_fielddef_haspresence(const upb_fielddef *f) { if (upb_fielddef_isseq(f)) return false; if (upb_fielddef_issubmsg(f)) return true; + if (f->proto3_optional_) return true; return f->file->syntax == UPB_SYNTAX_PROTO2; } @@ -3592,18 +3625,39 @@ bool upb_msgdef_lookupname(const upb_msgdef *m, const char *name, size_t len, *o = unpack_def(val, UPB_DEFTYPE_ONEOF); *f = unpack_def(val, UPB_DEFTYPE_FIELD); - UPB_ASSERT((*o != NULL) ^ (*f != NULL)); /* Exactly one of the two should be set. */ - return true; + return *o || *f; /* False if this was a JSON name. */ +} + +const upb_fielddef *upb_msgdef_lookupjsonname(const upb_msgdef *m, + const char *name, size_t len) { + upb_value val; + const upb_fielddef* f; + + if (!upb_strtable_lookup2(&m->ntof, name, len, &val)) { + return NULL; + } + + f = unpack_def(val, UPB_DEFTYPE_FIELD); + if (!f) f = unpack_def(val, UPB_DEFTYPE_FIELD_JSONNAME); + + return f; } int upb_msgdef_numfields(const upb_msgdef *m) { - /* The number table contains only fields. */ - return upb_inttable_count(&m->itof); + return m->field_count; } int upb_msgdef_numoneofs(const upb_msgdef *m) { - /* The name table includes oneofs, and the number table does not. */ - return upb_strtable_count(&m->ntof) - upb_inttable_count(&m->itof); + return m->oneof_count; +} + +const upb_msglayout *upb_msgdef_layout(const upb_msgdef *m) { + return m->layout; +} + +const upb_fielddef *_upb_msgdef_field(const upb_msgdef *m, int i) { + if (i >= m->field_count) return NULL; + return &m->fields[i]; } bool upb_msgdef_mapentry(const upb_msgdef *m) { @@ -3652,80 +3706,306 @@ void upb_msg_oneof_begin(upb_msg_oneof_iter *iter, const upb_msgdef *m) { } } -void upb_msg_oneof_next(upb_msg_oneof_iter *iter) { - /* We need to skip past fields to return only oneofs. */ - do { - upb_strtable_next(iter); - } while (!upb_strtable_done(iter) && - !unpack_def(upb_strtable_iter_value(iter), UPB_DEFTYPE_ONEOF)); -} +void upb_msg_oneof_next(upb_msg_oneof_iter *iter) { + /* We need to skip past fields to return only oneofs. */ + do { + upb_strtable_next(iter); + } while (!upb_strtable_done(iter) && + !unpack_def(upb_strtable_iter_value(iter), UPB_DEFTYPE_ONEOF)); +} + +bool upb_msg_oneof_done(const upb_msg_oneof_iter *iter) { + return upb_strtable_done(iter); +} + +const upb_oneofdef *upb_msg_iter_oneof(const upb_msg_oneof_iter *iter) { + return unpack_def(upb_strtable_iter_value(iter), UPB_DEFTYPE_ONEOF); +} + +void upb_msg_oneof_iter_setdone(upb_msg_oneof_iter *iter) { + upb_strtable_iter_setdone(iter); +} + +bool upb_msg_oneof_iter_isequal(const upb_msg_oneof_iter *iter1, + const upb_msg_oneof_iter *iter2) { + return upb_strtable_iter_isequal(iter1, iter2); +} + +/* upb_oneofdef ***************************************************************/ + +const char *upb_oneofdef_name(const upb_oneofdef *o) { + return shortdefname(o->full_name); +} + +const upb_msgdef *upb_oneofdef_containingtype(const upb_oneofdef *o) { + return o->parent; +} + +int upb_oneofdef_numfields(const upb_oneofdef *o) { + return (int)upb_strtable_count(&o->ntof); +} + +uint32_t upb_oneofdef_index(const upb_oneofdef *o) { + return o->index; +} + +bool upb_oneofdef_synthetic(const upb_oneofdef *o) { + upb_inttable_iter iter; + const upb_fielddef *f; + upb_inttable_begin(&iter, &o->itof); + if (upb_oneofdef_numfields(o) != 1) return false; + f = upb_value_getptr(upb_inttable_iter_value(&iter)); + UPB_ASSERT(f); + return f->proto3_optional_; +} + +const upb_fielddef *upb_oneofdef_ntof(const upb_oneofdef *o, + const char *name, size_t length) { + upb_value val; + return upb_strtable_lookup2(&o->ntof, name, length, &val) ? + upb_value_getptr(val) : NULL; +} + +const upb_fielddef *upb_oneofdef_itof(const upb_oneofdef *o, uint32_t num) { + upb_value val; + return upb_inttable_lookup32(&o->itof, num, &val) ? + upb_value_getptr(val) : NULL; +} + +void upb_oneof_begin(upb_oneof_iter *iter, const upb_oneofdef *o) { + upb_inttable_begin(iter, &o->itof); +} + +void upb_oneof_next(upb_oneof_iter *iter) { + upb_inttable_next(iter); +} + +bool upb_oneof_done(upb_oneof_iter *iter) { + return upb_inttable_done(iter); +} + +upb_fielddef *upb_oneof_iter_field(const upb_oneof_iter *iter) { + return (upb_fielddef *)upb_value_getconstptr(upb_inttable_iter_value(iter)); +} + +void upb_oneof_iter_setdone(upb_oneof_iter *iter) { + upb_inttable_iter_setdone(iter); +} + +/* Dynamic Layout Generation. *************************************************/ + +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_sizeof(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_strview); + } + UPB_UNREACHABLE(); +} + +static uint8_t upb_msg_fielddefsize(const upb_fielddef *f) { + if (upb_msgdef_mapentry(upb_fielddef_containingtype(f))) { + upb_map_entry ent; + UPB_ASSERT(sizeof(ent.k) == sizeof(ent.v)); + return sizeof(ent.k); + } else if (upb_fielddef_isseq(f)) { + return sizeof(void*); + } else { + return upb_msgval_sizeof(upb_fielddef_type(f)); + } +} + +static uint32_t upb_msglayout_place(upb_msglayout *l, size_t size) { + uint32_t ret; + + l->size = align_up(l->size, size); + ret = l->size; + l->size += size; + return ret; +} + +/* This function is the dynamic equivalent of message_layout.{cc,h} in upbc. + * It computes a dynamic layout for all of the fields in |m|. */ +static bool make_layout(const upb_symtab *symtab, const upb_msgdef *m) { + upb_msglayout *l = (upb_msglayout*)m->layout; + upb_msg_field_iter it; + upb_msg_oneof_iter oit; + size_t hasbit; + size_t submsg_count = m->submsg_field_count; + const upb_msglayout **submsgs; + upb_msglayout_field *fields; + upb_alloc *alloc = upb_arena_alloc(symtab->arena); + + memset(l, 0, sizeof(*l)); + + fields = upb_malloc(alloc, upb_msgdef_numfields(m) * sizeof(*fields)); + submsgs = upb_malloc(alloc, submsg_count * sizeof(*submsgs)); + + if ((!fields && upb_msgdef_numfields(m)) || + (!submsgs && submsg_count)) { + /* OOM. */ + return false; + } + + l->field_count = upb_msgdef_numfields(m); + l->fields = fields; + l->submsgs = submsgs; + + if (upb_msgdef_mapentry(m)) { + /* TODO(haberman): refactor this method so this special case is more + * elegant. */ + const upb_fielddef *key = upb_msgdef_itof(m, 1); + const upb_fielddef *val = upb_msgdef_itof(m, 2); + fields[0].number = 1; + fields[1].number = 2; + fields[0].label = UPB_LABEL_OPTIONAL; + fields[1].label = UPB_LABEL_OPTIONAL; + fields[0].presence = 0; + fields[1].presence = 0; + fields[0].descriptortype = upb_fielddef_descriptortype(key); + fields[1].descriptortype = upb_fielddef_descriptortype(val); + fields[0].offset = 0; + fields[1].offset = sizeof(upb_strview); + fields[1].submsg_index = 0; + + if (upb_fielddef_type(val) == UPB_TYPE_MESSAGE) { + submsgs[0] = upb_fielddef_msgsubdef(val)->layout; + } + + l->field_count = 2; + l->size = 2 * sizeof(upb_strview);align_up(l->size, 8); + return true; + } + + /* 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. */ + submsg_count = 0; + for (upb_msg_field_begin(&it, m), hasbit = 0; + !upb_msg_field_done(&it); + upb_msg_field_next(&it)) { + upb_fielddef* f = upb_msg_iter_field(&it); + upb_msglayout_field *field = &fields[upb_fielddef_index(f)]; -bool upb_msg_oneof_done(const upb_msg_oneof_iter *iter) { - return upb_strtable_done(iter); -} + field->number = upb_fielddef_number(f); + field->descriptortype = upb_fielddef_descriptortype(f); + field->label = upb_fielddef_label(f); -const upb_oneofdef *upb_msg_iter_oneof(const upb_msg_oneof_iter *iter) { - return unpack_def(upb_strtable_iter_value(iter), UPB_DEFTYPE_ONEOF); -} + if (upb_fielddef_ismap(f)) { + field->label = _UPB_LABEL_MAP; + } else if (upb_fielddef_packed(f)) { + field->label = _UPB_LABEL_PACKED; + } -void upb_msg_oneof_iter_setdone(upb_msg_oneof_iter *iter) { - upb_strtable_iter_setdone(iter); -} + /* TODO: we probably should sort the fields by field number to match the + * output of upbc, and to improve search speed for the table parser. */ + f->layout_index = f->index_; -bool upb_msg_oneof_iter_isequal(const upb_msg_oneof_iter *iter1, - const upb_msg_oneof_iter *iter2) { - return upb_strtable_iter_isequal(iter1, iter2); -} + if (upb_fielddef_issubmsg(f)) { + const upb_msgdef *subm = upb_fielddef_msgsubdef(f); + field->submsg_index = submsg_count++; + submsgs[field->submsg_index] = subm->layout; + } -/* upb_oneofdef ***************************************************************/ + if (upb_fielddef_haspresence(f) && !upb_fielddef_containingoneof(f)) { + /* We don't use hasbit 0, so that 0 can indicate "no presence" in the + * table. This wastes one hasbit, but we don't worry about it for now. */ + field->presence = ++hasbit; + } else { + field->presence = 0; + } + } -const char *upb_oneofdef_name(const upb_oneofdef *o) { - return shortdefname(o->full_name); -} + /* Account for space used by hasbits. */ + l->size = div_round_up(hasbit, 8); -const upb_msgdef *upb_oneofdef_containingtype(const upb_oneofdef *o) { - return o->parent; -} + /* 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); -int upb_oneofdef_numfields(const upb_oneofdef *o) { - return upb_strtable_count(&o->ntof); -} + if (upb_fielddef_containingoneof(f)) { + /* Oneofs are handled separately below. */ + continue; + } -uint32_t upb_oneofdef_index(const upb_oneofdef *o) { - return o->index; -} + fields[index].offset = upb_msglayout_place(l, field_size); + } -const upb_fielddef *upb_oneofdef_ntof(const upb_oneofdef *o, - const char *name, size_t length) { - upb_value val; - return upb_strtable_lookup2(&o->ntof, name, length, &val) ? - upb_value_getptr(val) : NULL; -} + /* 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; -const upb_fielddef *upb_oneofdef_itof(const upb_oneofdef *o, uint32_t num) { - upb_value val; - return upb_inttable_lookup32(&o->itof, num, &val) ? - upb_value_getptr(val) : NULL; -} + 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_oneof_begin(upb_oneof_iter *iter, const upb_oneofdef *o) { - upb_inttable_begin(iter, &o->itof); -} + /* 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)); + } -void upb_oneof_next(upb_oneof_iter *iter) { - upb_inttable_next(iter); -} + /* Align and allocate case offset. */ + case_offset = upb_msglayout_place(l, case_size); + data_offset = upb_msglayout_place(l, field_size); -bool upb_oneof_done(upb_oneof_iter *iter) { - return upb_inttable_done(iter); -} + 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; + } + } -upb_fielddef *upb_oneof_iter_field(const upb_oneof_iter *iter) { - return (upb_fielddef *)upb_value_getconstptr(upb_inttable_iter_value(iter)); -} + /* 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); -void upb_oneof_iter_setdone(upb_oneof_iter *iter) { - upb_inttable_iter_setdone(iter); + return true; } /* Code to build defs from descriptor protos. *********************************/ @@ -3740,11 +4020,12 @@ void upb_oneof_iter_setdone(upb_oneof_iter *iter) { typedef struct { const upb_symtab *symtab; - upb_filedef *file; /* File we are building. */ - upb_alloc *alloc; /* Allocate defs here. */ - upb_alloc *tmp; /* Alloc for addtab and any other tmp data. */ - upb_strtable *addtab; /* full_name -> packed def ptr for new defs. */ - upb_status *status; /* Record errors here. */ + upb_filedef *file; /* File we are building. */ + upb_alloc *alloc; /* Allocate defs here. */ + upb_alloc *tmp; /* Alloc for addtab and any other tmp data. */ + upb_strtable *addtab; /* full_name -> packed def ptr for new defs */ + const upb_msglayout **layouts; /* NULL if we should build layouts. */ + upb_status *status; /* Record errors here. */ } symtab_addctx; static char* strviewdup(const symtab_addctx *ctx, upb_strview view) { @@ -3776,6 +4057,51 @@ static const char *makefullname(const symtab_addctx *ctx, const char *prefix, } } +size_t getjsonname(const char *name, char *buf, size_t len) { + size_t src, dst = 0; + bool ucase_next = false; + +#define WRITE(byte) \ + ++dst; \ + if (dst < len) buf[dst - 1] = byte; \ + else if (dst == len) buf[dst - 1] = '\0' + + if (!name) { + WRITE('\0'); + return 0; + } + + /* Implement the transformation as described in the spec: + * 1. upper case all letters after an underscore. + * 2. remove all underscores. + */ + for (src = 0; name[src]; src++) { + if (name[src] == '_') { + ucase_next = true; + continue; + } + + if (ucase_next) { + WRITE(toupper(name[src])); + ucase_next = false; + } else { + WRITE(name[src]); + } + } + + WRITE('\0'); + return dst; + +#undef WRITE +} + +static char* makejsonname(const char* name, upb_alloc *alloc) { + size_t size = getjsonname(name, NULL, 0); + char* json_name = upb_malloc(alloc, size); + getjsonname(name, json_name, size); + return json_name; +} + static bool symtab_add(const symtab_addctx *ctx, const char *name, upb_value v) { upb_value tmp; @@ -3899,7 +4225,7 @@ static bool parse_default(const symtab_addctx *ctx, const char *str, size_t len, } case UPB_TYPE_INT64: { /* XXX: Need to write our own strtoll, since it's not available in c89. */ - long long val = strtol(str, &end, 0); + int64_t val = strtol(str, &end, 0); CHK(val <= INT64_MAX && val >= INT64_MIN && errno != ERANGE && !*end); f->defaultval.sint = val; break; @@ -3912,7 +4238,7 @@ static bool parse_default(const symtab_addctx *ctx, const char *str, size_t len, } case UPB_TYPE_UINT64: { /* XXX: Need to write our own strtoull, since it's not available in c89. */ - unsigned long long val = strtoul(str, &end, 0); + uint64_t val = strtoul(str, &end, 0); CHK(val <= UINT64_MAX && errno != ERANGE && !*end); f->defaultval.uint = val; break; @@ -3989,6 +4315,7 @@ static bool create_fielddef( const google_protobuf_FieldOptions *options; upb_strview name; const char *full_name; + const char *json_name; const char *shortname; uint32_t field_number; @@ -4002,6 +4329,13 @@ static bool create_fielddef( full_name = makefullname(ctx, prefix, name); shortname = shortdefname(full_name); + if (google_protobuf_FieldDescriptorProto_has_json_name(field_proto)) { + json_name = strviewdup( + ctx, google_protobuf_FieldDescriptorProto_json_name(field_proto)); + } else { + json_name = makejsonname(shortname, ctx->alloc); + } + field_number = google_protobuf_FieldDescriptorProto_number(field_proto); if (field_number == 0 || field_number > UPB_MAX_FIELDNUMBER) { @@ -4011,38 +4345,72 @@ static bool create_fielddef( if (m) { /* direct message field. */ - upb_value v, packed_v; + upb_value v, field_v, json_v; + size_t json_size; f = (upb_fielddef*)&m->fields[m->field_count++]; f->msgdef = m; f->is_extension_ = false; - packed_v = pack_def(f, UPB_DEFTYPE_FIELD); - v = upb_value_constptr(f); - - if (!upb_strtable_insert3(&m->ntof, name.data, name.size, packed_v, alloc)) { + if (upb_strtable_lookup(&m->ntof, shortname, NULL)) { upb_status_seterrf(ctx->status, "duplicate field name (%s)", shortname); return false; } - if (!upb_inttable_insert2(&m->itof, field_number, v, alloc)) { + if (upb_strtable_lookup(&m->ntof, json_name, NULL)) { + upb_status_seterrf(ctx->status, "duplicate json_name (%s)", json_name); + return false; + } + + if (upb_inttable_lookup(&m->itof, field_number, NULL)) { upb_status_seterrf(ctx->status, "duplicate field number (%u)", field_number); return false; } + + field_v = pack_def(f, UPB_DEFTYPE_FIELD); + json_v = pack_def(f, UPB_DEFTYPE_FIELD_JSONNAME); + v = upb_value_constptr(f); + json_size = strlen(json_name); + + CHK_OOM( + upb_strtable_insert3(&m->ntof, name.data, name.size, field_v, alloc)); + CHK_OOM(upb_inttable_insert2(&m->itof, field_number, v, alloc)); + + if (strcmp(shortname, json_name) != 0) { + upb_strtable_insert3(&m->ntof, json_name, json_size, json_v, alloc); + } + + if (ctx->layouts) { + const upb_msglayout_field *fields = m->layout->fields; + int count = m->layout->field_count; + bool found = false; + int i; + for (i = 0; i < count; i++) { + if (fields[i].number == field_number) { + f->layout_index = i; + found = true; + break; + } + } + UPB_ASSERT(found); + } } else { /* extension field. */ - f = (upb_fielddef*)&ctx->file->exts[ctx->file->ext_count]; + f = (upb_fielddef*)&ctx->file->exts[ctx->file->ext_count++]; f->is_extension_ = true; CHK_OOM(symtab_add(ctx, full_name, pack_def(f, UPB_DEFTYPE_FIELD))); } f->full_name = full_name; + f->json_name = json_name; f->file = ctx->file; f->type_ = (int)google_protobuf_FieldDescriptorProto_type(field_proto); f->label_ = (int)google_protobuf_FieldDescriptorProto_label(field_proto); f->number_ = field_number; f->oneof = NULL; + f->proto3_optional_ = + google_protobuf_FieldDescriptorProto_proto3_optional(field_proto); /* We can't resolve the subdef or (in the case of extensions) the containing * message yet, because it may not have been defined yet. We stash a pointer @@ -4166,7 +4534,7 @@ static bool create_enumdef( return true; } -static bool create_msgdef(const symtab_addctx *ctx, const char *prefix, +static bool create_msgdef(symtab_addctx *ctx, const char *prefix, const google_protobuf_DescriptorProto *msg_proto) { upb_msgdef *m; const google_protobuf_MessageOptions *options; @@ -4196,6 +4564,14 @@ static bool create_msgdef(const symtab_addctx *ctx, const char *prefix, m->map_entry = google_protobuf_MessageOptions_map_entry(options); } + if (ctx->layouts) { + m->layout = *ctx->layouts; + ctx->layouts++; + } else { + /* Allocate now (to allow cross-linking), populate later. */ + m->layout = upb_malloc(ctx->alloc, sizeof(*m->layout)); + } + oneofs = google_protobuf_DescriptorProto_oneof_decl(msg_proto, &n); m->oneof_count = 0; m->oneofs = upb_malloc(ctx->alloc, sizeof(*m->oneofs) * n); @@ -4342,7 +4718,7 @@ static bool resolve_fielddef(const symtab_addctx *ctx, const char *prefix, } static bool build_filedef( - const symtab_addctx *ctx, upb_filedef *file, + symtab_addctx *ctx, upb_filedef *file, const google_protobuf_FileDescriptorProto *file_proto) { upb_alloc *alloc = ctx->alloc; const google_protobuf_FileOptions *file_options_proto; @@ -4396,7 +4772,8 @@ static bool build_filedef( } else if (streql_view(syntax, "proto3")) { file->syntax = UPB_SYNTAX_PROTO3; } else { - upb_status_seterrf(ctx->status, "Invalid syntax '%s'", syntax); + upb_status_seterrf(ctx->status, "Invalid syntax '" UPB_STRVIEW_FORMAT "'", + UPB_STRVIEW_ARGS(syntax)); return false; } } else { @@ -4456,7 +4833,7 @@ static bool build_filedef( CHK(create_fielddef(ctx, file->package, NULL, exts[i])); } - /* Now that all names are in the table, resolve references. */ + /* Now that all names are in the table, build layouts and resolve refs. */ for (i = 0; i < file->ext_count; i++) { CHK(resolve_fielddef(ctx, file->package, (upb_fielddef*)&file->exts[i])); } @@ -4469,6 +4846,13 @@ static bool build_filedef( } } + if (!ctx->layouts) { + for (i = 0; i < file->msg_count; i++) { + const upb_msgdef *m = &file->msgs[i]; + make_layout(ctx->symtab, m); + } + } + return true; } @@ -4483,10 +4867,9 @@ static bool upb_symtab_addtotabs(upb_symtab *s, symtab_addctx *ctx, upb_strtable_begin(&iter, ctx->addtab); for (; !upb_strtable_done(&iter); upb_strtable_next(&iter)) { - const char *key = upb_strtable_iter_key(&iter); - size_t keylen = upb_strtable_iter_keylength(&iter); + upb_strview key = upb_strtable_iter_key(&iter); upb_value value = upb_strtable_iter_value(&iter); - CHK_OOM(upb_strtable_insert3(&s->syms, key, keylen, value, alloc)); + CHK_OOM(upb_strtable_insert3(&s->syms, key.data, key.size, value, alloc)); } return true; @@ -4588,9 +4971,13 @@ const upb_filedef *upb_symtab_lookupfile(const upb_symtab *s, const char *name) : NULL; } -const upb_filedef *upb_symtab_addfile( +int upb_symtab_filecount(const upb_symtab *s) { + return (int)upb_strtable_count(&s->files); +} + +static const upb_filedef *_upb_symtab_addfile( upb_symtab *s, const google_protobuf_FileDescriptorProto *file_proto, - upb_status *status) { + const upb_msglayout **layouts, upb_status *status) { upb_arena *tmparena = upb_arena_new(); upb_strtable addtab; upb_alloc *alloc = upb_arena_alloc(s->arena); @@ -4603,6 +4990,7 @@ const upb_filedef *upb_symtab_addfile( ctx.alloc = alloc; ctx.tmp = upb_arena_alloc(tmparena); ctx.addtab = &addtab; + ctx.layouts = layouts; ctx.status = status; ok = file && @@ -4614,6 +5002,12 @@ const upb_filedef *upb_symtab_addfile( return ok ? file : NULL; } +const upb_filedef *upb_symtab_addfile( + upb_symtab *s, const google_protobuf_FileDescriptorProto *file_proto, + upb_status *status) { + return _upb_symtab_addfile(s, file_proto, NULL, status); +} + /* Include here since we want most of this file to be stdio-free. */ #include @@ -4646,269 +5040,330 @@ bool _upb_symtab_loaddefinit(upb_symtab *s, const upb_def_init *init) { "Failed to parse compiled-in descriptor for file '%s'. This should " "never happen.", init->filename); - goto err; - } - - if (!upb_symtab_addfile(s, file, &status)) goto err; - - upb_arena_free(arena); - return true; - -err: - fprintf(stderr, "Error loading compiled-in descriptor: %s\n", - upb_status_errmsg(&status)); - upb_arena_free(arena); - return false; -} - -#undef CHK -#undef CHK_OOM - - - -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_strview); - } - 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)); + goto err; } + + if (!_upb_symtab_addfile(s, file, init->layouts, &status)) goto err; + + upb_arena_free(arena); + return true; + +err: + fprintf(stderr, "Error loading compiled-in descriptor: %s\n", + upb_status_errmsg(&status)); + upb_arena_free(arena); + return false; } +#undef CHK +#undef CHK_OOM + + +#include + + +static char field_size[] = { + 0,/* 0 */ + 8, /* UPB_DESCRIPTOR_TYPE_DOUBLE */ + 4, /* UPB_DESCRIPTOR_TYPE_FLOAT */ + 8, /* UPB_DESCRIPTOR_TYPE_INT64 */ + 8, /* UPB_DESCRIPTOR_TYPE_UINT64 */ + 4, /* UPB_DESCRIPTOR_TYPE_INT32 */ + 8, /* UPB_DESCRIPTOR_TYPE_FIXED64 */ + 4, /* UPB_DESCRIPTOR_TYPE_FIXED32 */ + 1, /* UPB_DESCRIPTOR_TYPE_BOOL */ + sizeof(upb_strview), /* UPB_DESCRIPTOR_TYPE_STRING */ + sizeof(void*), /* UPB_DESCRIPTOR_TYPE_GROUP */ + sizeof(void*), /* UPB_DESCRIPTOR_TYPE_MESSAGE */ + sizeof(upb_strview), /* UPB_DESCRIPTOR_TYPE_BYTES */ + 4, /* UPB_DESCRIPTOR_TYPE_UINT32 */ + 4, /* UPB_DESCRIPTOR_TYPE_ENUM */ + 4, /* UPB_DESCRIPTOR_TYPE_SFIXED32 */ + 8, /* UPB_DESCRIPTOR_TYPE_SFIXED64 */ + 4, /* UPB_DESCRIPTOR_TYPE_SINT32 */ + 8, /* UPB_DESCRIPTOR_TYPE_SINT64 */ +}; + +/* Strings/bytes are special-cased in maps. */ +static char _upb_fieldtype_to_mapsize[12] = { + 0, + 1, /* UPB_TYPE_BOOL */ + 4, /* UPB_TYPE_FLOAT */ + 4, /* UPB_TYPE_INT32 */ + 4, /* UPB_TYPE_UINT32 */ + 4, /* UPB_TYPE_ENUM */ + sizeof(void*), /* UPB_TYPE_MESSAGE */ + 8, /* UPB_TYPE_DOUBLE */ + 8, /* UPB_TYPE_INT64 */ + 8, /* UPB_TYPE_UINT64 */ + 0, /* UPB_TYPE_STRING */ + 0, /* UPB_TYPE_BYTES */ +}; -/** upb_msglayout *************************************************************/ +/** upb_msg *******************************************************************/ -static void upb_msglayout_free(upb_msglayout *l) { - upb_gfree(l); +upb_msg *upb_msg_new(const upb_msgdef *m, upb_arena *a) { + return _upb_msg_new(upb_msgdef_layout(m), a); } -static size_t upb_msglayout_place(upb_msglayout *l, size_t size) { - size_t ret; +static bool in_oneof(const upb_msglayout_field *field) { + return field->presence < 0; +} - l->size = align_up(l->size, size); - ret = l->size; - l->size += size; - return ret; +static uint32_t *oneofcase(const upb_msg *msg, + const upb_msglayout_field *field) { + UPB_ASSERT(in_oneof(field)); + return UPB_PTR_AT(msg, -field->presence, uint32_t); } -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; +static upb_msgval _upb_msg_getraw(const upb_msg *msg, const upb_fielddef *f) { + const upb_msglayout_field *field = upb_fielddef_layout(f); + const char *mem = UPB_PTR_AT(msg, field->offset, char); + upb_msgval val = {0}; + int size = upb_fielddef_isseq(f) ? sizeof(void *) + : field_size[field->descriptortype]; + memcpy(&val, mem, size); + return val; +} - 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++; - } +bool upb_msg_has(const upb_msg *msg, const upb_fielddef *f) { + const upb_msglayout_field *field = upb_fielddef_layout(f); + if (in_oneof(field)) { + return *oneofcase(msg, field) == field->number; + } else if (field->presence > 0) { + uint32_t hasbit = field->presence; + return *UPB_PTR_AT(msg, hasbit / 8, uint8_t) & (1 << (hasbit % 8)); + } else { + UPB_ASSERT(field->descriptortype == UPB_DESCRIPTOR_TYPE_MESSAGE || + field->descriptortype == UPB_DESCRIPTOR_TYPE_GROUP); + return _upb_msg_getraw(msg, f).msg_val != NULL; } +} - memset(l, 0, sizeof(*l)); +bool upb_msg_hasoneof(const upb_msg *msg, const upb_oneofdef *o) { + upb_oneof_iter i; + const upb_fielddef *f; + const upb_msglayout_field *field; - fields = upb_gmalloc(upb_msgdef_numfields(m) * sizeof(*fields)); - submsgs = upb_gmalloc(submsg_count * sizeof(*submsgs)); + upb_oneof_begin(&i, o); + if (upb_oneof_done(&i)) return false; + f = upb_oneof_iter_field(&i); + field = upb_fielddef_layout(f); + return *oneofcase(msg, field) != 0; +} - if ((!fields && upb_msgdef_numfields(m)) || - (!submsgs && submsg_count)) { - /* OOM. */ - upb_gfree(fields); - upb_gfree(submsgs); - return false; +upb_msgval upb_msg_get(const upb_msg *msg, const upb_fielddef *f) { + if (!upb_fielddef_haspresence(f) || upb_msg_has(msg, f)) { + return _upb_msg_getraw(msg, f); + } else { + /* TODO(haberman): change upb_fielddef to not require this switch(). */ + upb_msgval val = {0}; + switch (upb_fielddef_type(f)) { + case UPB_TYPE_INT32: + case UPB_TYPE_ENUM: + val.int32_val = upb_fielddef_defaultint32(f); + break; + case UPB_TYPE_INT64: + val.int64_val = upb_fielddef_defaultint64(f); + break; + case UPB_TYPE_UINT32: + val.uint32_val = upb_fielddef_defaultuint32(f); + break; + case UPB_TYPE_UINT64: + val.uint64_val = upb_fielddef_defaultuint64(f); + break; + case UPB_TYPE_FLOAT: + val.float_val = upb_fielddef_defaultfloat(f); + break; + case UPB_TYPE_DOUBLE: + val.double_val = upb_fielddef_defaultdouble(f); + break; + case UPB_TYPE_BOOL: + val.double_val = upb_fielddef_defaultbool(f); + break; + case UPB_TYPE_STRING: + case UPB_TYPE_BYTES: + val.str_val.data = upb_fielddef_defaultstr(f, &val.str_val.size); + break; + case UPB_TYPE_MESSAGE: + val.msg_val = NULL; + break; + } + return val; } +} - l->field_count = upb_msgdef_numfields(m); - l->fields = fields; - l->submsgs = submsgs; - - /* 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. */ - 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_mutmsgval upb_msg_mutable(upb_msg *msg, const upb_fielddef *f, + upb_arena *a) { + const upb_msglayout_field *field = upb_fielddef_layout(f); + upb_mutmsgval ret; + char *mem = UPB_PTR_AT(msg, field->offset, char); + bool wrong_oneof = in_oneof(field) && *oneofcase(msg, field) != field->number; - field->number = upb_fielddef_number(f); - field->descriptortype = upb_fielddef_descriptortype(f); - field->label = upb_fielddef_label(f); + memcpy(&ret, mem, sizeof(void*)); - 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 (a && (!ret.msg || wrong_oneof)) { + if (upb_fielddef_ismap(f)) { + const upb_msgdef *entry = upb_fielddef_msgsubdef(f); + const upb_fielddef *key = upb_msgdef_itof(entry, UPB_MAPENTRY_KEY); + const upb_fielddef *value = upb_msgdef_itof(entry, UPB_MAPENTRY_VALUE); + ret.map = upb_map_new(a, upb_fielddef_type(key), upb_fielddef_type(value)); + } else if (upb_fielddef_isseq(f)) { + ret.array = upb_array_new(a, upb_fielddef_type(f)); + } else { + UPB_ASSERT(upb_fielddef_issubmsg(f)); + ret.msg = upb_msg_new(upb_fielddef_msgsubdef(f), a); } - if (upb_fielddef_haspresence(f) && !upb_fielddef_containingoneof(f)) { - field->presence = (hasbit++); - } else { - field->presence = 0; + memcpy(mem, &ret, sizeof(void*)); + + if (wrong_oneof) { + *oneofcase(msg, field) = field->number; } } + return ret; +} - /* Account for space used by hasbits. */ - l->size = div_round_up(hasbit, 8); +void upb_msg_set(upb_msg *msg, const upb_fielddef *f, upb_msgval val, + upb_arena *a) { + const upb_msglayout_field *field = upb_fielddef_layout(f); + char *mem = UPB_PTR_AT(msg, field->offset, char); + int size = upb_fielddef_isseq(f) ? sizeof(void *) + : field_size[field->descriptortype]; + memcpy(mem, &val, size); + if (in_oneof(field)) { + *oneofcase(msg, field) = field->number; + } +} - /* 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); +bool upb_msg_next(const upb_msg *msg, const upb_msgdef *m, + const upb_symtab *ext_pool, const upb_fielddef **out_f, + upb_msgval *out_val, size_t *iter) { + size_t i = *iter; + const upb_msgval zero = {0}; + const upb_fielddef *f; + while ((f = _upb_msgdef_field(m, (int)++i)) != NULL) { + upb_msgval val = _upb_msg_getraw(msg, f); - if (upb_fielddef_containingoneof(f)) { - /* Oneofs are handled separately below. */ - continue; + /* Skip field if unset or empty. */ + if (upb_fielddef_haspresence(f)) { + if (!upb_msg_has(msg, f)) continue; + } else { + upb_msgval test = val; + if (upb_fielddef_isstring(f) && !upb_fielddef_isseq(f)) { + /* Clear string pointer, only size matters (ptr could be non-NULL). */ + test.str_val.data = NULL; + } + /* Continue if NULL or 0. */ + if (memcmp(&test, &zero, sizeof(test)) == 0) continue; + + /* Continue on empty array or map. */ + if (upb_fielddef_ismap(f)) { + if (upb_map_size(test.map_val) == 0) continue; + } else if (upb_fielddef_isseq(f)) { + if (upb_array_size(test.array_val) == 0) continue; + } } - fields[index].offset = upb_msglayout_place(l, field_size); + *out_val = val; + *out_f = f; + *iter = i; + return true; } + *iter = i; + return false; +} - /* 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. */ - size_t field_size = 0; - uint32_t case_offset; - uint32_t data_offset; +/** upb_array *****************************************************************/ - /* 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)); - } +upb_array *upb_array_new(upb_arena *a, upb_fieldtype_t type) { + return _upb_array_new(a, type); +} - /* Align and allocate case offset. */ - case_offset = upb_msglayout_place(l, case_size); - data_offset = upb_msglayout_place(l, field_size); +size_t upb_array_size(const upb_array *arr) { + return arr->len; +} - 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; - } - } +upb_msgval upb_array_get(const upb_array *arr, size_t i) { + upb_msgval ret; + const char* data = _upb_array_constptr(arr); + int lg2 = arr->data & 7; + UPB_ASSERT(i < arr->len); + memcpy(&ret, data + (i << lg2), 1 << lg2); + return ret; +} - /* 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); +void upb_array_set(upb_array *arr, size_t i, upb_msgval val) { + char* data = _upb_array_ptr(arr); + int lg2 = arr->data & 7; + UPB_ASSERT(i < arr->len); + memcpy(data + (i << lg2), &val, 1 << lg2); +} +bool upb_array_append(upb_array *arr, upb_msgval val, upb_arena *arena) { + if (!_upb_array_realloc(arr, arr->len + 1, arena)) { + return false; + } + arr->len++; + upb_array_set(arr, arr->len - 1, val); return true; } +/* Resizes the array to the given size, reallocating if necessary, and returns a + * pointer to the new array elements. */ +bool upb_array_resize(upb_array *arr, size_t size, upb_arena *arena) { + return _upb_array_realloc(arr, size, arena); +} -/** upb_msgfactory ************************************************************/ - -struct upb_msgfactory { - const upb_symtab *symtab; /* We own a ref. */ - upb_inttable layouts; -}; +/** upb_map *******************************************************************/ -upb_msgfactory *upb_msgfactory_new(const upb_symtab *symtab) { - upb_msgfactory *ret = upb_gmalloc(sizeof(*ret)); +upb_map *upb_map_new(upb_arena *a, upb_fieldtype_t key_type, + upb_fieldtype_t value_type) { + return _upb_map_new(a, _upb_fieldtype_to_mapsize[key_type], + _upb_fieldtype_to_mapsize[value_type]); +} - ret->symtab = symtab; - upb_inttable_init(&ret->layouts, UPB_CTYPE_PTR); +size_t upb_map_size(const upb_map *map) { + return _upb_map_size(map); +} - return ret; +bool upb_map_get(const upb_map *map, upb_msgval key, upb_msgval *val) { + return _upb_map_get(map, &key, map->key_size, val, map->val_size); } -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); - } +bool upb_map_set(upb_map *map, upb_msgval key, upb_msgval val, + upb_arena *arena) { + return _upb_map_set(map, &key, map->key_size, &val, map->val_size, arena); +} - upb_inttable_uninit(&f->layouts); - upb_gfree(f); +bool upb_map_delete(upb_map *map, upb_msgval key) { + return _upb_map_delete(map, &key, map->key_size); } -const upb_symtab *upb_msgfactory_symtab(const upb_msgfactory *f) { - return f->symtab; +bool upb_mapiter_next(const upb_map *map, size_t *iter) { + return _upb_map_next(map, iter); } -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)); +/* Returns the key and value for this entry of the map. */ +upb_msgval upb_mapiter_key(const upb_map *map, size_t iter) { + upb_strtable_iter i; + upb_msgval ret; + i.t = &map->table; + i.index = iter; + _upb_map_fromkey(upb_strtable_iter_key(&i), &ret, map->key_size); + return ret; +} - if (upb_inttable_lookupptr(&f->layouts, m, &v)) { - UPB_ASSERT(upb_value_getptr(v)); - return upb_value_getptr(v); - } else { - /* 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; - } +upb_msgval upb_mapiter_value(const upb_map *map, size_t iter) { + upb_strtable_iter i; + upb_msgval ret; + i.t = &map->table; + i.index = iter; + _upb_map_fromvalue(upb_strtable_iter_value(&i), &ret, map->val_size); + return ret; } + +/* void upb_mapiter_setvalue(upb_map *map, size_t iter, upb_msgval value); */ /* ** TODO(haberman): it's unclear whether a lot of the consistency checks should ** UPB_ASSERT() or return false. @@ -5088,7 +5543,8 @@ static upb_handlers *upb_handlers_new(const upb_msgdef *md, int extra; upb_handlers *h; - extra = sizeof(upb_handlers_tabent) * (upb_msgdef_selectorcount(md) - 1); + extra = + (int)(sizeof(upb_handlers_tabent) * (upb_msgdef_selectorcount(md) - 1)); h = upb_calloc(arena, sizeof(*h) + extra); if (!h) return NULL; @@ -5489,6 +5945,31 @@ bool upb_bufsrc_putbuf(const char *buf, size_t len, upb_bytessink sink) { } return ret; } + + +#ifdef UPB_MSVC_VSNPRINTF +/* Visual C++ earlier than 2015 doesn't have standard C99 snprintf and + * vsnprintf. To support them, missing functions are manually implemented + * using the existing secure functions. */ +int msvc_vsnprintf(char* s, size_t n, const char* format, va_list arg) { + if (!s) { + return _vscprintf(format, arg); + } + int ret = _vsnprintf_s(s, n, _TRUNCATE, format, arg); + if (ret < 0) { + ret = _vscprintf(format, arg); + } + return ret; +} + +int msvc_snprintf(char* s, size_t n, const char* format, ...) { + va_list arg; + va_start(arg, format); + int ret = msvc_vsnprintf(s, n, format, arg); + va_end(arg); + return ret; +} +#endif /* ** protobuf decoder bytecode compiler ** @@ -5644,7 +6125,9 @@ static void setofs(uint32_t *instruction, int32_t ofs) { UPB_ASSERT(getofs(*instruction) == ofs); /* Would fail in cases of overflow. */ } -static uint32_t pcofs(compiler *c) { return c->pc - c->group->bytecode; } +static uint32_t pcofs(compiler *c) { + return (uint32_t)(c->pc - c->group->bytecode); +} /* Defines a local label at the current PC location. All previous forward * references are updated to point to this location. The location is noted @@ -5658,7 +6141,7 @@ static void label(compiler *c, unsigned int label) { codep = (val == EMPTYLABEL) ? NULL : c->group->bytecode + val; while (codep) { int ofs = getofs(*codep); - setofs(codep, c->pc - codep - instruction_len(*codep)); + setofs(codep, (int32_t)(c->pc - codep - instruction_len(*codep))); codep = ofs ? codep + ofs : NULL; } c->fwd_labels[label] = EMPTYLABEL; @@ -5680,7 +6163,7 @@ static int32_t labelref(compiler *c, int label) { return 0; } else if (label < 0) { /* Backward local label. Relative to the next instruction. */ - uint32_t from = (c->pc + 1) - c->group->bytecode; + uint32_t from = (uint32_t)((c->pc + 1) - c->group->bytecode); return c->back_labels[-label] - from; } else { /* Forward local label: prepend to (possibly-empty) linked list. */ @@ -5714,7 +6197,7 @@ static void putop(compiler *c, int op, ...) { case OP_SETDISPATCH: { uintptr_t ptr = (uintptr_t)va_arg(ap, void*); put32(c, OP_SETDISPATCH); - put32(c, ptr); + put32(c, (uint32_t)ptr); if (sizeof(uintptr_t) > sizeof(uint32_t)) put32(c, (uint64_t)ptr >> 32); break; @@ -5773,7 +6256,7 @@ static void putop(compiler *c, int op, ...) { case OP_TAG2: { int label = va_arg(ap, int); uint64_t tag = va_arg(ap, uint64_t); - uint32_t instruction = op | (tag << 16); + uint32_t instruction = (uint32_t)(op | (tag << 16)); UPB_ASSERT(tag <= 0xffff); setofs(&instruction, labelref(c, label)); put32(c, instruction); @@ -5785,7 +6268,7 @@ static void putop(compiler *c, int op, ...) { uint32_t instruction = op | (upb_value_size(tag) << 16); setofs(&instruction, labelref(c, label)); put32(c, instruction); - put32(c, tag); + put32(c, (uint32_t)tag); put32(c, tag >> 32); break; } @@ -6398,11 +6881,11 @@ const upb_pbdecodermethod *upb_pbcodecache_get(upb_pbcodecache *c, } else { g = mgroup_new(h, c->lazy); ok = upb_inttable_insertptr(&c->groups, md, upb_value_constptr(g)); - UPB_ASSERT(ok); + UPB_ASSUME(ok); } ok = upb_inttable_lookupptr(&g->methods, h, &v); - UPB_ASSERT(ok); + UPB_ASSUME(ok); return upb_value_getptr(v); } /* @@ -6589,7 +7072,7 @@ static int32_t skip(upb_pbdecoder *d, size_t bytes) { UPB_ASSERT(d->skip == 0); if (bytes > delim_remaining(d)) { seterr(d, "Skipped value extended beyond enclosing submessage."); - return upb_pbdecoder_suspend(d); + return (int32_t)upb_pbdecoder_suspend(d); } else if (bufleft(d) >= bytes) { /* Skipped data is all in current buffer, and more is still available. */ advance(d, bytes); @@ -6602,7 +7085,7 @@ static int32_t skip(upb_pbdecoder *d, size_t bytes) { d->bufstart_ofs += (d->end - d->buf); d->residual_end = d->residual; switchtobuf(d, d->residual, d->residual_end); - return d->size_param + d->skip; + return (int32_t)(d->size_param + d->skip); } } @@ -6642,7 +7125,7 @@ int32_t upb_pbdecoder_resume(upb_pbdecoder *d, void *p, const char *buf, /* NULL buf is ok if its entire span is covered by the "skip" above, but * by this point we know that "skip" doesn't cover the buffer. */ seterr(d, "Passed NULL buffer over non-skippable region."); - return upb_pbdecoder_suspend(d); + return (int32_t)upb_pbdecoder_suspend(d); } if (d->residual_end > d->residual) { @@ -6752,9 +7235,9 @@ UPB_NOINLINE static int32_t getbytes_slow(upb_pbdecoder *d, void *buf, return DECODE_OK; } else if (d->data_end == d->delim_end) { seterr(d, "Submessage ended in the middle of a value or group"); - return upb_pbdecoder_suspend(d); + return (int32_t)upb_pbdecoder_suspend(d); } else { - return suspend_save(d); + return (int32_t)suspend_save(d); } } @@ -6810,7 +7293,7 @@ UPB_NOINLINE int32_t upb_pbdecoder_decode_varint_slow(upb_pbdecoder *d, } if(bitpos == 70 && (byte & 0x80)) { seterr(d, kUnterminatedVarint); - return upb_pbdecoder_suspend(d); + return (int32_t)upb_pbdecoder_suspend(d); } return DECODE_OK; } @@ -6827,7 +7310,7 @@ UPB_FORCEINLINE static int32_t decode_varint(upb_pbdecoder *d, uint64_t *u64) { upb_decoderet r = upb_vdecode_fast(d->ptr); if (r.p == NULL) { seterr(d, kUnterminatedVarint); - return upb_pbdecoder_suspend(d); + return (int32_t)upb_pbdecoder_suspend(d); } advance(d, r.p - d->ptr); *u64 = r.val; @@ -6851,9 +7334,9 @@ UPB_FORCEINLINE static int32_t decode_v32(upb_pbdecoder *d, uint32_t *u32) { * Right now the size_t -> int32_t can overflow and produce negative values. */ *u32 = 0; - return upb_pbdecoder_suspend(d); + return (int32_t)upb_pbdecoder_suspend(d); } - *u32 = u64; + *u32 = (uint32_t)u64; return DECODE_OK; } @@ -6929,7 +7412,7 @@ UPB_NOINLINE int32_t upb_pbdecoder_checktag_slow(upb_pbdecoder *d, UPB_ASSERT(ok < 0); return DECODE_OK; } else if (read < bytes && memcmp(&data, &expected, read) == 0) { - return suspend_save(d); + return (int32_t)suspend_save(d); } else { return DECODE_MISMATCH; } @@ -6949,7 +7432,7 @@ int32_t upb_pbdecoder_skipunknown(upb_pbdecoder *d, int32_t fieldnum, have_tag: if (fieldnum == 0) { seterr(d, "Saw invalid field number (0)"); - return upb_pbdecoder_suspend(d); + return (int32_t)upb_pbdecoder_suspend(d); } switch (wire_type) { @@ -6971,7 +7454,9 @@ have_tag: break; } case UPB_WIRE_TYPE_START_GROUP: - CHECK_SUSPEND(pushtagdelim(d, -fieldnum)); + if (!pushtagdelim(d, -fieldnum)) { + return (int32_t)upb_pbdecoder_suspend(d); + } break; case UPB_WIRE_TYPE_END_GROUP: if (fieldnum == -d->top->groupnum) { @@ -6980,12 +7465,12 @@ have_tag: return DECODE_ENDGROUP; } else { seterr(d, "Unmatched ENDGROUP tag."); - return upb_pbdecoder_suspend(d); + return (int32_t)upb_pbdecoder_suspend(d); } break; default: seterr(d, "Invalid wire type"); - return upb_pbdecoder_suspend(d); + return (int32_t)upb_pbdecoder_suspend(d); } if (d->top->groupnum >= 0) { @@ -7153,10 +7638,11 @@ size_t run_decoder_vm(upb_pbdecoder *d, const mgroup *group, CHECK_SUSPEND(upb_sink_startsubmsg(outer->sink, arg, &d->top->sink)); ) VMCASE(OP_ENDSUBMSG, - CHECK_SUSPEND(upb_sink_endsubmsg(d->top->sink, arg)); + upb_sink subsink = (d->top + 1)->sink; + CHECK_SUSPEND(upb_sink_endsubmsg(d->top->sink, subsink, arg)); ) VMCASE(OP_STARTSTR, - uint32_t len = delim_remaining(d); + uint32_t len = (uint32_t)delim_remaining(d); upb_pbdecoder_frame *outer = outer_frame(d); CHECK_SUSPEND(upb_sink_startstr(outer->sink, arg, len, &d->top->sink)); if (len == 0) { @@ -7164,7 +7650,7 @@ size_t run_decoder_vm(upb_pbdecoder *d, const mgroup *group, } ) VMCASE(OP_STRING, - uint32_t len = curbufleft(d); + uint32_t len = (uint32_t)curbufleft(d); size_t n = upb_sink_putstring(d->top->sink, arg, d->ptr, len, handle); if (n > len) { if (n > delim_remaining(d)) { @@ -7699,7 +8185,7 @@ static bool start_delim(upb_pb_encoder *e) { e->runbegin = e->ptr; } - *e->top = e->segptr - e->segbuf; + *e->top = (int)(e->segptr - e->segbuf); e->segptr->seglen = 0; e->segptr->msglen = 0; @@ -8819,7 +9305,7 @@ static upb_selector_t getsel_for_handlertype(upb_json_parser *p, upb_handlertype_t type) { upb_selector_t sel; bool ok = upb_handlers_getselector(p->top->f, type, &sel); - UPB_ASSERT(ok); + UPB_ASSUME(ok); return sel; } @@ -8844,7 +9330,7 @@ static void set_name_table(upb_json_parser *p, upb_jsonparser_frame *frame) { const upb_json_parsermethod *method; ok = upb_inttable_lookupptr(&cache->methods, frame->m, &v); - UPB_ASSERT(ok); + UPB_ASSUME(ok); method = upb_value_getconstptr(v); frame->name_table = &method->name_table; @@ -9398,7 +9884,7 @@ static bool parse_number_from_buffer(upb_json_parser *p, const char *buf, } else if (val > INT32_MAX || val < INT32_MIN) { return false; } else { - upb_sink_putint32(p->top->sink, parser_getsel(p), val); + upb_sink_putint32(p->top->sink, parser_getsel(p), (int32_t)val); return true; } } @@ -9409,7 +9895,7 @@ static bool parse_number_from_buffer(upb_json_parser *p, const char *buf, } else if (val > UINT32_MAX || errno == ERANGE) { return false; } else { - upb_sink_putuint32(p->top->sink, parser_getsel(p), val); + upb_sink_putuint32(p->top->sink, parser_getsel(p), (uint32_t)val); return true; } } @@ -9697,7 +10183,7 @@ static bool start_stringval(upb_json_parser *p) { } else if (upb_fielddef_type(p->top->f) != UPB_TYPE_BOOL && upb_fielddef_type(p->top->f) != UPB_TYPE_MESSAGE) { /* No need to push a frame -- numeric values in quotes remain in the - * current parser frame. These values must accumulate so we can convert + * current parser frame. These values must accmulate so we can convert * them all at once at the end. */ multipart_startaccum(p); return true; @@ -10117,14 +10603,18 @@ static void start_timestamp_zone(upb_json_parser *p, const char *ptr) { capture_begin(p, ptr); } +static int div_round_up2(int n, int d) { + return (n + d - 1) / d; +} + /* epoch_days(1970, 1, 1) == 1970-01-01 == 0. */ static int epoch_days(int year, int month, int day) { static const uint16_t month_yday[12] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334}; int febs_since_0 = month > 2 ? year + 1 : year; - int leap_days_since_0 = div_round_up(febs_since_0, 4) - - div_round_up(febs_since_0, 100) + - div_round_up(febs_since_0, 400); + int leap_days_since_0 = div_round_up2(febs_since_0, 4) - + div_round_up2(febs_since_0, 100) + + div_round_up2(febs_since_0, 400); int days_since_0 = 365 * year + month_yday[month - 1] + (day - 1) + leap_days_since_0; @@ -10445,8 +10935,8 @@ static void end_member(upb_json_parser *p) { /* send ENDSUBMSG in repeated-field-of-mapentries frame. */ p->top--; ok = upb_handlers_getselector(mapfield, UPB_HANDLER_ENDSUBMSG, &sel); - UPB_ASSERT(ok); - upb_sink_endsubmsg(p->top->sink, sel); + UPB_ASSUME(ok); + upb_sink_endsubmsg(p->top->sink, (p->top + 1)->sink, sel); } p->top->f = NULL; @@ -10560,7 +11050,7 @@ static void end_subobject(upb_json_parser *p) { p->top--; if (!is_unknown) { sel = getsel_for_handlertype(p, UPB_HANDLER_ENDSUBMSG); - upb_sink_endsubmsg(p->top->sink, sel); + upb_sink_endsubmsg(p->top->sink, (p->top + 1)->sink, sel); } } } @@ -10999,11 +11489,11 @@ static bool does_fieldmask_end(upb_json_parser *p) { * final state once, when the closing '"' is seen. */ -#line 2794 "upb/json/parser.rl" +#line 2780 "upb/json/parser.rl" -#line 2597 "upb/json/parser.c" +#line 2583 "upb/json/parser.c" static const char _json_actions[] = { 0, 1, 0, 1, 1, 1, 3, 1, 4, 1, 6, 1, 7, 1, 8, 1, @@ -11258,7 +11748,7 @@ static const int json_en_value_machine = 78; static const int json_en_main = 1; -#line 2797 "upb/json/parser.rl" +#line 2783 "upb/json/parser.rl" size_t parse(void *closure, const void *hd, const char *buf, size_t size, const upb_bufhandle *handle) { @@ -11281,7 +11771,7 @@ size_t parse(void *closure, const void *hd, const char *buf, size_t size, capture_resume(parser, buf); -#line 2875 "upb/json/parser.c" +#line 2861 "upb/json/parser.c" { int _klen; unsigned int _trans; @@ -11356,147 +11846,147 @@ _match: switch ( *_acts++ ) { case 1: -#line 2602 "upb/json/parser.rl" +#line 2588 "upb/json/parser.rl" { p--; {cs = stack[--top]; goto _again;} } break; case 2: -#line 2604 "upb/json/parser.rl" +#line 2590 "upb/json/parser.rl" { p--; {stack[top++] = cs; cs = 23;goto _again;} } break; case 3: -#line 2608 "upb/json/parser.rl" +#line 2594 "upb/json/parser.rl" { start_text(parser, p); } break; case 4: -#line 2609 "upb/json/parser.rl" +#line 2595 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_text(parser, p)); } break; case 5: -#line 2615 "upb/json/parser.rl" +#line 2601 "upb/json/parser.rl" { start_hex(parser); } break; case 6: -#line 2616 "upb/json/parser.rl" +#line 2602 "upb/json/parser.rl" { hexdigit(parser, p); } break; case 7: -#line 2617 "upb/json/parser.rl" +#line 2603 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_hex(parser)); } break; case 8: -#line 2623 "upb/json/parser.rl" +#line 2609 "upb/json/parser.rl" { CHECK_RETURN_TOP(escape(parser, p)); } break; case 9: -#line 2629 "upb/json/parser.rl" +#line 2615 "upb/json/parser.rl" { p--; {cs = stack[--top]; goto _again;} } break; case 10: -#line 2634 "upb/json/parser.rl" +#line 2620 "upb/json/parser.rl" { start_year(parser, p); } break; case 11: -#line 2635 "upb/json/parser.rl" +#line 2621 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_year(parser, p)); } break; case 12: -#line 2639 "upb/json/parser.rl" +#line 2625 "upb/json/parser.rl" { start_month(parser, p); } break; case 13: -#line 2640 "upb/json/parser.rl" +#line 2626 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_month(parser, p)); } break; case 14: -#line 2644 "upb/json/parser.rl" +#line 2630 "upb/json/parser.rl" { start_day(parser, p); } break; case 15: -#line 2645 "upb/json/parser.rl" +#line 2631 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_day(parser, p)); } break; case 16: -#line 2649 "upb/json/parser.rl" +#line 2635 "upb/json/parser.rl" { start_hour(parser, p); } break; case 17: -#line 2650 "upb/json/parser.rl" +#line 2636 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_hour(parser, p)); } break; case 18: -#line 2654 "upb/json/parser.rl" +#line 2640 "upb/json/parser.rl" { start_minute(parser, p); } break; case 19: -#line 2655 "upb/json/parser.rl" +#line 2641 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_minute(parser, p)); } break; case 20: -#line 2659 "upb/json/parser.rl" +#line 2645 "upb/json/parser.rl" { start_second(parser, p); } break; case 21: -#line 2660 "upb/json/parser.rl" +#line 2646 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_second(parser, p)); } break; case 22: -#line 2665 "upb/json/parser.rl" +#line 2651 "upb/json/parser.rl" { start_duration_base(parser, p); } break; case 23: -#line 2666 "upb/json/parser.rl" +#line 2652 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_duration_base(parser, p)); } break; case 24: -#line 2668 "upb/json/parser.rl" +#line 2654 "upb/json/parser.rl" { p--; {cs = stack[--top]; goto _again;} } break; case 25: -#line 2673 "upb/json/parser.rl" +#line 2659 "upb/json/parser.rl" { start_timestamp_base(parser); } break; case 26: -#line 2675 "upb/json/parser.rl" +#line 2661 "upb/json/parser.rl" { start_timestamp_fraction(parser, p); } break; case 27: -#line 2676 "upb/json/parser.rl" +#line 2662 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_timestamp_fraction(parser, p)); } break; case 28: -#line 2678 "upb/json/parser.rl" +#line 2664 "upb/json/parser.rl" { start_timestamp_zone(parser, p); } break; case 29: -#line 2679 "upb/json/parser.rl" +#line 2665 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_timestamp_zone(parser, p)); } break; case 30: -#line 2681 "upb/json/parser.rl" +#line 2667 "upb/json/parser.rl" { p--; {cs = stack[--top]; goto _again;} } break; case 31: -#line 2686 "upb/json/parser.rl" +#line 2672 "upb/json/parser.rl" { start_fieldmask_path_text(parser, p); } break; case 32: -#line 2687 "upb/json/parser.rl" +#line 2673 "upb/json/parser.rl" { end_fieldmask_path_text(parser, p); } break; case 33: -#line 2692 "upb/json/parser.rl" +#line 2678 "upb/json/parser.rl" { start_fieldmask_path(parser); } break; case 34: -#line 2693 "upb/json/parser.rl" +#line 2679 "upb/json/parser.rl" { end_fieldmask_path(parser); } break; case 35: -#line 2699 "upb/json/parser.rl" +#line 2685 "upb/json/parser.rl" { p--; {cs = stack[--top]; goto _again;} } break; case 36: -#line 2704 "upb/json/parser.rl" +#line 2690 "upb/json/parser.rl" { if (is_wellknown_msg(parser, UPB_WELLKNOWN_TIMESTAMP)) { {stack[top++] = cs; cs = 47;goto _again;} @@ -11510,11 +12000,11 @@ _match: } break; case 37: -#line 2717 "upb/json/parser.rl" +#line 2703 "upb/json/parser.rl" { p--; {stack[top++] = cs; cs = 78;goto _again;} } break; case 38: -#line 2722 "upb/json/parser.rl" +#line 2708 "upb/json/parser.rl" { if (is_wellknown_msg(parser, UPB_WELLKNOWN_ANY)) { start_any_member(parser, p); @@ -11524,11 +12014,11 @@ _match: } break; case 39: -#line 2729 "upb/json/parser.rl" +#line 2715 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_membername(parser)); } break; case 40: -#line 2732 "upb/json/parser.rl" +#line 2718 "upb/json/parser.rl" { if (is_wellknown_msg(parser, UPB_WELLKNOWN_ANY)) { end_any_member(parser, p); @@ -11538,7 +12028,7 @@ _match: } break; case 41: -#line 2743 "upb/json/parser.rl" +#line 2729 "upb/json/parser.rl" { if (is_wellknown_msg(parser, UPB_WELLKNOWN_ANY)) { start_any_object(parser, p); @@ -11548,7 +12038,7 @@ _match: } break; case 42: -#line 2752 "upb/json/parser.rl" +#line 2738 "upb/json/parser.rl" { if (is_wellknown_msg(parser, UPB_WELLKNOWN_ANY)) { CHECK_RETURN_TOP(end_any_object(parser, p)); @@ -11558,54 +12048,54 @@ _match: } break; case 43: -#line 2764 "upb/json/parser.rl" +#line 2750 "upb/json/parser.rl" { CHECK_RETURN_TOP(start_array(parser)); } break; case 44: -#line 2768 "upb/json/parser.rl" +#line 2754 "upb/json/parser.rl" { end_array(parser); } break; case 45: -#line 2773 "upb/json/parser.rl" +#line 2759 "upb/json/parser.rl" { CHECK_RETURN_TOP(start_number(parser, p)); } break; case 46: -#line 2774 "upb/json/parser.rl" +#line 2760 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_number(parser, p)); } break; case 47: -#line 2776 "upb/json/parser.rl" +#line 2762 "upb/json/parser.rl" { CHECK_RETURN_TOP(start_stringval(parser)); } break; case 48: -#line 2777 "upb/json/parser.rl" +#line 2763 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_stringval(parser)); } break; case 49: -#line 2779 "upb/json/parser.rl" +#line 2765 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_bool(parser, true)); } break; case 50: -#line 2781 "upb/json/parser.rl" +#line 2767 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_bool(parser, false)); } break; case 51: -#line 2783 "upb/json/parser.rl" +#line 2769 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_null(parser)); } break; case 52: -#line 2785 "upb/json/parser.rl" +#line 2771 "upb/json/parser.rl" { CHECK_RETURN_TOP(start_subobject_full(parser)); } break; case 53: -#line 2786 "upb/json/parser.rl" +#line 2772 "upb/json/parser.rl" { end_subobject_full(parser); } break; case 54: -#line 2791 "upb/json/parser.rl" +#line 2777 "upb/json/parser.rl" { p--; {cs = stack[--top]; goto _again;} } break; -#line 3199 "upb/json/parser.c" +#line 3185 "upb/json/parser.c" } } @@ -11622,32 +12112,32 @@ _again: while ( __nacts-- > 0 ) { switch ( *__acts++ ) { case 0: -#line 2600 "upb/json/parser.rl" +#line 2586 "upb/json/parser.rl" { p--; {cs = stack[--top]; if ( p == pe ) goto _test_eof; goto _again;} } break; case 46: -#line 2774 "upb/json/parser.rl" +#line 2760 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_number(parser, p)); } break; case 49: -#line 2779 "upb/json/parser.rl" +#line 2765 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_bool(parser, true)); } break; case 50: -#line 2781 "upb/json/parser.rl" +#line 2767 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_bool(parser, false)); } break; case 51: -#line 2783 "upb/json/parser.rl" +#line 2769 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_null(parser)); } break; case 53: -#line 2786 "upb/json/parser.rl" +#line 2772 "upb/json/parser.rl" { end_subobject_full(parser); } break; -#line 3241 "upb/json/parser.c" +#line 3227 "upb/json/parser.c" } } } @@ -11655,7 +12145,7 @@ goto _again;} } _out: {} } -#line 2819 "upb/json/parser.rl" +#line 2805 "upb/json/parser.rl" if (p != pe) { upb_status_seterrf(parser->status, "Parse error at '%.*s'\n", pe - p, p); @@ -11698,13 +12188,13 @@ static void json_parser_reset(upb_json_parser *p) { /* Emit Ragel initialization of the parser. */ -#line 3292 "upb/json/parser.c" +#line 3278 "upb/json/parser.c" { cs = json_start; top = 0; } -#line 2861 "upb/json/parser.rl" +#line 2847 "upb/json/parser.rl" p->current_state = cs; p->parser_top = top; accumulate_clear(p); @@ -11735,15 +12225,13 @@ static upb_json_parsermethod *parsermethod_new(upb_json_codecache *c, upb_msg_field_next(&i)) { const upb_fielddef *f = upb_msg_iter_field(&i); upb_value v = upb_value_constptr(f); - char *buf; + const char *name; /* Add an entry for the JSON name. */ - size_t len = upb_fielddef_getjsonname(f, NULL, 0); - buf = upb_malloc(alloc, len); - upb_fielddef_getjsonname(f, buf, len); - upb_strtable_insert3(&m->name_table, buf, strlen(buf), v, alloc); + name = upb_fielddef_jsonname(f); + upb_strtable_insert3(&m->name_table, name, strlen(name), v, alloc); - if (strcmp(buf, upb_fielddef_name(f)) != 0) { + if (strcmp(name, upb_fielddef_name(f)) != 0) { /* Since the JSON name is different from the regular field name, add an * entry for the raw name (compliant proto3 JSON parsers must accept * both). */ @@ -11869,6 +12357,7 @@ const upb_json_parsermethod *upb_json_codecache_get(upb_json_codecache *c, #include +#include #include #include #include @@ -11926,12 +12415,8 @@ strpc *newstrpc(upb_handlers *h, const upb_fielddef *f, ret->ptr = upb_gstrdup(upb_fielddef_name(f)); ret->len = strlen(ret->ptr); } else { - size_t len; - ret->len = upb_fielddef_getjsonname(f, NULL, 0); - ret->ptr = upb_gmalloc(ret->len); - len = upb_fielddef_getjsonname(f, ret->ptr, ret->len); - UPB_ASSERT(len == ret->len); - ret->len--; /* NULL */ + ret->ptr = upb_gstrdup(upb_fielddef_jsonname(f)); + ret->len = strlen(ret->ptr); } upb_handlers_addcleanup(h, ret, freestrpc); @@ -11950,7 +12435,7 @@ strpc *newstrpc_str(upb_handlers *h, const char * str) { /* ------------ JSON string printing: values, maps, arrays ------------------ */ static void print_data( - upb_json_printer *p, const char *buf, unsigned int len) { + upb_json_printer *p, const char *buf, size_t len) { /* TODO: Will need to change if we support pushback from the sink. */ size_t n = upb_bytessink_putbuf(p->output_, p->subc_, buf, len, NULL); UPB_ASSERT(n == len); @@ -11990,7 +12475,7 @@ UPB_INLINE const char* json_nice_escape(char c) { /* Write a properly escaped string chunk. The surrounding quotes are *not* * printed; this is so that the caller has the option of emitting the string * content in chunks. */ -static void putstring(upb_json_printer *p, const char *buf, unsigned int len) { +static void putstring(upb_json_printer *p, const char *buf, size_t len) { const char* unescaped_run = NULL; unsigned int i; for (i = 0; i < len; i++) { @@ -12070,28 +12555,26 @@ static size_t fmt_bool(bool val, char* buf, size_t length) { return n; } -static size_t fmt_int64_as_number(long long val, char* buf, size_t length) { - size_t n = _upb_snprintf(buf, length, "%lld", val); +static size_t fmt_int64_as_number(int64_t val, char* buf, size_t length) { + size_t n = _upb_snprintf(buf, length, "%" PRId64, val); CHKLENGTH(n > 0 && n < length); return n; } -static size_t fmt_uint64_as_number( - unsigned long long val, char* buf, size_t length) { - size_t n = _upb_snprintf(buf, length, "%llu", val); +static size_t fmt_uint64_as_number(uint64_t val, char* buf, size_t length) { + size_t n = _upb_snprintf(buf, length, "%" PRIu64, val); CHKLENGTH(n > 0 && n < length); return n; } -static size_t fmt_int64_as_string(long long val, char* buf, size_t length) { - size_t n = _upb_snprintf(buf, length, "\"%lld\"", val); +static size_t fmt_int64_as_string(int64_t val, char* buf, size_t length) { + size_t n = _upb_snprintf(buf, length, "\"%" PRId64 "\"", val); CHKLENGTH(n > 0 && n < length); return n; } -static size_t fmt_uint64_as_string( - unsigned long long val, char* buf, size_t length) { - size_t n = _upb_snprintf(buf, length, "\"%llu\"", val); +static size_t fmt_uint64_as_string(uint64_t val, char* buf, size_t length) { + size_t n = _upb_snprintf(buf, length, "\"%" PRIu64 "\"", val); CHKLENGTH(n > 0 && n < length); return n; } @@ -13268,8 +13751,9 @@ upb_handlercache *upb_json_printer_newcache(bool preserve_proto_fieldnames) { } /* See port_def.inc. This should #undef all macros #defined there. */ +#undef UPB_MAPTYPE_STRING #undef UPB_SIZE -#undef UPB_FIELD_AT +#undef UPB_PTR_AT #undef UPB_READ_ONEOF #undef UPB_WRITE_ONEOF #undef UPB_INLINE @@ -13279,6 +13763,7 @@ upb_handlercache *upb_json_printer_newcache(bool preserve_proto_fieldnames) { #undef UPB_MAX #undef UPB_MIN #undef UPB_UNUSED +#undef UPB_ASSUME #undef UPB_ASSERT #undef UPB_ASSERT_DEBUGVAR #undef UPB_UNREACHABLE diff --git a/ruby/ext/google/protobuf_c/upb.h b/ruby/ext/google/protobuf_c/upb.h index 24943eed90..a34637925b 100644 --- a/ruby/ext/google/protobuf_c/upb.h +++ b/ruby/ext/google/protobuf_c/upb.h @@ -21,9 +21,7 @@ * * This file is private and must not be included by users! */ -#ifndef UINTPTR_MAX -#error must include stdint.h first -#endif +#include #if UINTPTR_MAX == 0xffffffff #define UPB_SIZE(size32, size64) size32 @@ -31,17 +29,21 @@ #define UPB_SIZE(size32, size64) size64 #endif -#define UPB_FIELD_AT(msg, fieldtype, offset) \ - *(fieldtype*)((const char*)(msg) + offset) +/* If we always read/write as a consistent type to each address, this shouldn't + * violate aliasing. + */ +#define UPB_PTR_AT(msg, ofs, type) ((type*)((char*)(msg) + (ofs))) #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) \ + *UPB_PTR_AT(msg, case_offset, int) == case_val \ + ? *UPB_PTR_AT(msg, offset, fieldtype) \ : 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_PTR_AT(msg, case_offset, int) = case_val; \ + *UPB_PTR_AT(msg, offset, fieldtype) = value; + +#define UPB_MAPTYPE_STRING 0 /* UPB_INLINE: inline if possible, emit standalone code if required. */ #ifdef __cplusplus @@ -115,7 +117,7 @@ int msvc_vsnprintf(char* s, size_t n, const char* format, va_list arg); #ifdef __cplusplus #if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__) || \ (defined(_MSC_VER) && _MSC_VER >= 1900) -// C++11 is present +/* C++11 is present */ #else #error upb requires C++11 for C++ support #endif @@ -126,6 +128,18 @@ int msvc_vsnprintf(char* s, size_t n, const char* format, va_list arg); #define UPB_UNUSED(var) (void)var +/* UPB_ASSUME(): in release mode, we tell the compiler to assume this is true. + */ +#ifdef NDEBUG +#ifdef __GNUC__ +#define UPB_ASSUME(expr) if (!(expr)) __builtin_unreachable() +#else +#define UPB_ASSUME(expr) do {} if (false && (expr)) +#endif +#else +#define UPB_ASSUME(expr) assert(expr) +#endif + /* UPB_ASSERT(): in release mode, we use the expression without letting it be * evaluated. This prevents "unused variable" warnings. */ #ifdef NDEBUG @@ -152,6 +166,50 @@ int msvc_vsnprintf(char* s, size_t n, const char* format, va_list arg); #define UPB_INFINITY (1.0 / 0.0) #endif /* +** upb_decode: parsing into a upb_msg using a upb_msglayout. +*/ + +#ifndef UPB_DECODE_H_ +#define UPB_DECODE_H_ + +/* +** Our memory representation for parsing tables and messages themselves. +** Functions in this file are used by generated code and possibly reflection. +** +** The definitions in this file are internal to upb. +**/ + +#ifndef UPB_MSG_H_ +#define UPB_MSG_H_ + +#include +#include + +/* +** 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. ** ** This is a mixed C/C++ interface that offers a full API to both languages. @@ -361,6 +419,19 @@ typedef struct upb_arena upb_arena; extern "C" { #endif +typedef struct { + /* We implement the allocator interface. + * This must be the first member of upb_arena! */ + upb_alloc alloc; + + char *ptr, *end; +} _upb_arena_head; + +UPB_INLINE size_t _upb_arena_alignup(size_t size) { + const size_t maxalign = 16; + return ((size + maxalign - 1) / maxalign) * maxalign; +} + /* Creates an arena from the given initial block (if any -- n may be 0). * Additional blocks will be allocated from |alloc|. If |alloc| is NULL, this * is a fixed-size arena and cannot grow. */ @@ -368,18 +439,29 @@ upb_arena *upb_arena_init(void *mem, size_t n, upb_alloc *alloc); void upb_arena_free(upb_arena *a); bool upb_arena_addcleanup(upb_arena *a, void *ud, upb_cleanup_func *func); size_t upb_arena_bytesallocated(const upb_arena *a); +void *_upb_arena_slowmalloc(upb_arena *a, size_t size); UPB_INLINE upb_alloc *upb_arena_alloc(upb_arena *a) { return (upb_alloc*)a; } -/* Convenience wrappers around upb_alloc functions. */ - UPB_INLINE void *upb_arena_malloc(upb_arena *a, size_t size) { - return upb_malloc(upb_arena_alloc(a), size); + _upb_arena_head *h = (_upb_arena_head*)a; + size = _upb_arena_alignup(size); + if (UPB_LIKELY((size_t)(h->end - h->ptr) >= size)) { + void* ret = h->ptr; + h->ptr += size; + return ret; + } else { + return _upb_arena_slowmalloc(a, size); + } } UPB_INLINE void *upb_arena_realloc(upb_arena *a, void *ptr, size_t oldsize, size_t size) { - return upb_realloc(upb_arena_alloc(a), ptr, oldsize, size); + if (oldsize == 0) { + return upb_arena_malloc(a, size); + } else { + return upb_realloc(upb_arena_alloc(a), ptr, oldsize, size); + } } UPB_INLINE upb_arena *upb_arena_new(void) { @@ -470,14 +552,15 @@ typedef enum { UPB_TYPE_INT32 = 3, UPB_TYPE_UINT32 = 4, UPB_TYPE_ENUM = 5, /* Enum values are int32. */ - /* Types stored as pointers (probably 4 or 8 bytes). */ - UPB_TYPE_STRING = 6, - UPB_TYPE_BYTES = 7, - UPB_TYPE_MESSAGE = 8, + /* Types stored as void* (probably 4 or 8 bytes). */ + UPB_TYPE_MESSAGE = 6, /* Types stored as 8 bytes. */ - UPB_TYPE_DOUBLE = 9, - UPB_TYPE_INT64 = 10, - UPB_TYPE_UINT64 = 11 + UPB_TYPE_DOUBLE = 7, + UPB_TYPE_INT64 = 8, + UPB_TYPE_UINT64 = 9, + /* Types stored as upb_strview (2 * void*) (probably 8 or 16 bytes). */ + UPB_TYPE_STRING = 10, + UPB_TYPE_BYTES = 11 } upb_fieldtype_t; /* The repeated-ness of each field; this matches descriptor.proto. */ @@ -489,6 +572,7 @@ typedef enum { /* Descriptor types, as defined in descriptor.proto. */ typedef enum { + /* Old (long) names. TODO(haberman): remove */ UPB_DESCRIPTOR_TYPE_DOUBLE = 1, UPB_DESCRIPTOR_TYPE_FLOAT = 2, UPB_DESCRIPTOR_TYPE_INT64 = 3, @@ -506,145 +590,32 @@ typedef enum { UPB_DESCRIPTOR_TYPE_SFIXED32 = 15, UPB_DESCRIPTOR_TYPE_SFIXED64 = 16, UPB_DESCRIPTOR_TYPE_SINT32 = 17, - UPB_DESCRIPTOR_TYPE_SINT64 = 18 + UPB_DESCRIPTOR_TYPE_SINT64 = 18, + + UPB_DTYPE_DOUBLE = 1, + UPB_DTYPE_FLOAT = 2, + UPB_DTYPE_INT64 = 3, + UPB_DTYPE_UINT64 = 4, + UPB_DTYPE_INT32 = 5, + UPB_DTYPE_FIXED64 = 6, + UPB_DTYPE_FIXED32 = 7, + UPB_DTYPE_BOOL = 8, + UPB_DTYPE_STRING = 9, + UPB_DTYPE_GROUP = 10, + UPB_DTYPE_MESSAGE = 11, + UPB_DTYPE_BYTES = 12, + UPB_DTYPE_UINT32 = 13, + UPB_DTYPE_ENUM = 14, + UPB_DTYPE_SFIXED32 = 15, + UPB_DTYPE_SFIXED64 = 16, + UPB_DTYPE_SINT32 = 17, + UPB_DTYPE_SINT64 = 18 } upb_descriptortype_t; -extern const uint8_t upb_desctype_to_fieldtype[]; +#define UPB_MAP_BEGIN -1 #endif /* UPB_H_ */ -/* -** upb_decode: parsing into a upb_msg using a upb_msglayout. -*/ - -#ifndef UPB_DECODE_H_ -#define UPB_DECODE_H_ - -/* -** Data structures for message tables, used for parsing and serialization. -** This are much lighter-weight than full reflection, but they are do not -** have enough information to convert to text format, JSON, etc. -** -** The definitions in this file are internal to upb. -**/ - -#ifndef UPB_MSG_H_ -#define UPB_MSG_H_ - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -typedef void upb_msg; - -/** upb_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; - -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; - -/** Message internal representation *******************************************/ - -/* Our internal representation for repeated fields. */ -typedef struct { - void *data; /* Each element is element_size. */ - size_t len; /* Measured in elements. */ - size_t size; /* Measured in elements. */ -} upb_array; - -upb_msg *upb_msg_new(const upb_msglayout *l, upb_arena *a); -upb_msg *upb_msg_new(const upb_msglayout *l, upb_arena *a); - -void upb_msg_addunknown(upb_msg *msg, const char *data, size_t len, - upb_arena *arena); -const char *upb_msg_getunknown(const upb_msg *msg, size_t *len); - -upb_array *upb_array_new(upb_arena *a); - -#ifdef __cplusplus -} /* extern "C" */ -#endif - -#endif /* UPB_MSG_H_ */ - -#ifdef __cplusplus -extern "C" { -#endif - -bool upb_decode(const char *buf, size_t size, upb_msg *msg, - const upb_msglayout *l, upb_arena *arena); - -#ifdef __cplusplus -} /* extern "C" */ -#endif - -#endif /* UPB_DECODE_H_ */ -/* -** upb_encode: parsing into a upb_msg using a upb_msglayout. -*/ - -#ifndef UPB_ENCODE_H_ -#define UPB_ENCODE_H_ - - -#ifdef __cplusplus -extern "C" { -#endif - -char *upb_encode(const void *msg, const upb_msglayout *l, upb_arena *arena, - size_t *size); - -#ifdef __cplusplus -} /* extern "C" */ -#endif - -#endif /* UPB_ENCODE_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 @@ -673,19 +644,8 @@ typedef enum { typedef struct { uint64_t val; -#ifndef NDEBUG - /* In debug mode we carry the value type around also so we can check accesses - * to be sure the right member is being read. */ - upb_ctype_t ctype; -#endif } upb_value; -#ifdef NDEBUG -#define SET_TYPE(dest, val) UPB_UNUSED(val) -#else -#define SET_TYPE(dest, val) dest = val -#endif - /* Like strdup(), which isn't always available since it's not ANSI C. */ char *upb_strdup(const char *s, upb_alloc *a); /* Variant that works with a length-delimited rather than NULL-delimited string, @@ -696,15 +656,13 @@ UPB_INLINE char *upb_gstrdup(const char *s) { return upb_strdup(s, &upb_alloc_global); } -UPB_INLINE void _upb_value_setval(upb_value *v, uint64_t val, - upb_ctype_t ctype) { +UPB_INLINE void _upb_value_setval(upb_value *v, uint64_t val) { v->val = val; - SET_TYPE(v->ctype, ctype); } -UPB_INLINE upb_value _upb_value_val(uint64_t val, upb_ctype_t ctype) { +UPB_INLINE upb_value _upb_value_val(uint64_t val) { upb_value ret; - _upb_value_setval(&ret, val, ctype); + _upb_value_setval(&ret, val); return ret; } @@ -719,7 +677,6 @@ UPB_INLINE upb_value _upb_value_val(uint64_t val, upb_ctype_t ctype) { #define FUNCS(name, membername, type_t, converter, proto_type) \ UPB_INLINE void upb_value_set ## name(upb_value *val, type_t cval) { \ val->val = (converter)cval; \ - SET_TYPE(val->ctype, proto_type); \ } \ UPB_INLINE upb_value upb_value_ ## name(type_t val) { \ upb_value ret; \ @@ -727,7 +684,6 @@ UPB_INLINE upb_value _upb_value_val(uint64_t val, upb_ctype_t ctype) { return ret; \ } \ UPB_INLINE type_t upb_value_get ## name(upb_value val) { \ - UPB_ASSERT_DEBUGVAR(val.ctype == proto_type); \ return (type_t)(converter)val.val; \ } @@ -745,12 +701,10 @@ FUNCS(fptr, fptr, upb_func*, uintptr_t, UPB_CTYPE_FPTR) UPB_INLINE void upb_value_setfloat(upb_value *val, float cval) { memcpy(&val->val, &cval, sizeof(cval)); - SET_TYPE(val->ctype, UPB_CTYPE_FLOAT); } UPB_INLINE void upb_value_setdouble(upb_value *val, double cval) { memcpy(&val->val, &cval, sizeof(cval)); - SET_TYPE(val->ctype, UPB_CTYPE_DOUBLE); } UPB_INLINE upb_value upb_value_float(float cval) { @@ -794,7 +748,6 @@ typedef struct { #define UPB_TABVALUE_EMPTY_INIT {-1} - /* upb_table ******************************************************************/ typedef struct _upb_tabent { @@ -811,7 +764,6 @@ typedef struct _upb_tabent { typedef struct { size_t count; /* Number of entries in the hash part. */ size_t mask; /* Mask to turn hash value -> bucket. */ - upb_ctype_t ctype; /* Type of all values. */ uint8_t size_lg2; /* Size of the hashtable part is 2^size_lg2 entries. */ /* Hash table entries. @@ -821,17 +773,6 @@ typedef struct { * initialize const hash tables. Then we cast away const when we have to. */ const upb_tabent *entries; - -#ifndef NDEBUG - /* This table's allocator. We make the user pass it in to every relevant - * function and only use this to check it in debug mode. We do this solely - * to keep upb_table as small as possible. This might seem slightly paranoid - * but the plan is to use upb_table for all map fields and extension sets in - * a forthcoming message representation, so there could be a lot of these. - * If this turns out to be too annoying later, we can change it (since this - * is an internal-only header file). */ - upb_alloc *alloc; -#endif } upb_table; typedef struct { @@ -845,12 +786,6 @@ typedef struct { size_t array_count; /* Array part number of elements. */ } upb_inttable; -#define UPB_INTTABLE_INIT(count, mask, ctype, size_lg2, ent, a, asize, acount) \ - {UPB_TABLE_INIT(count, mask, ctype, size_lg2, ent), a, asize, acount} - -#define UPB_EMPTY_INTTABLE_INIT(ctype) \ - UPB_INTTABLE_INIT(0, 0, ctype, 0, NULL, NULL, 0, 0) - #define UPB_ARRAY_EMPTYENT -1 UPB_INLINE size_t upb_table_size(const upb_table *t) { @@ -919,6 +854,7 @@ upb_inttable *upb_inttable_pack(const upb_inttable *t, void *p, size_t *ofs, size_t size); upb_strtable *upb_strtable_pack(const upb_strtable *t, void *p, size_t *ofs, size_t size); +void upb_strtable_clear(upb_strtable *t); /* Inserts the given key into the hashtable with the given value. The key must * not already exist in the hash table. For string tables, the key must be @@ -1020,7 +956,7 @@ UPB_INLINE bool upb_inttable_lookup32(const upb_inttable *t, uint32_t key, if (key < t->array_size) { upb_tabval arrval = t->array[key]; if (upb_arrhas(arrval)) { - _upb_value_setval(v, arrval.val, t->t.ctype); + _upb_value_setval(v, arrval.val); return true; } else { return false; @@ -1030,7 +966,7 @@ UPB_INLINE bool upb_inttable_lookup32(const upb_inttable *t, uint32_t key, if (t->t.entries == NULL) return false; for (e = upb_getentry(&t->t, upb_inthash(key)); true; e = e->next) { if ((uint32_t)e->key == key) { - _upb_value_setval(v, e->val.val, t->t.ctype); + _upb_value_setval(v, e->val.val); return true; } if (e->next == NULL) return false; @@ -1084,8 +1020,7 @@ typedef struct { void upb_strtable_begin(upb_strtable_iter *i, const upb_strtable *t); void upb_strtable_next(upb_strtable_iter *i); bool upb_strtable_done(const upb_strtable_iter *i); -const char *upb_strtable_iter_key(const upb_strtable_iter *i); -size_t upb_strtable_iter_keylength(const upb_strtable_iter *i); +upb_strview upb_strtable_iter_key(const upb_strtable_iter *i); upb_value upb_strtable_iter_value(const upb_strtable_iter *i); void upb_strtable_iter_setdone(upb_strtable_iter *i); bool upb_strtable_iter_isequal(const upb_strtable_iter *i1, @@ -1109,6 +1044,10 @@ typedef struct { bool array_part; } upb_inttable_iter; +UPB_INLINE const upb_tabent *str_tabent(const upb_strtable_iter *i) { + return &i->t->t.entries[i->index]; +} + void upb_inttable_begin(upb_inttable_iter *i, const upb_inttable *t); void upb_inttable_next(upb_inttable_iter *i); bool upb_inttable_done(const upb_inttable_iter *i); @@ -1125,36 +1064,140 @@ bool upb_inttable_iter_isequal(const upb_inttable_iter *i1, #endif /* UPB_TABLE_H_ */ -/* 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. */ -#ifndef GOOGLE_PROTOBUF_DESCRIPTOR_PROTO_UPB_H_ -#define GOOGLE_PROTOBUF_DESCRIPTOR_PROTO_UPB_H_ -/* -** Functions for use by generated code. These are not public and users must -** not call them directly. -*/ +#ifdef __cplusplus +extern "C" { +#endif -#ifndef UPB_GENERATED_UTIL_H_ -#define UPB_GENERATED_UTIL_H_ +#define PTR_AT(msg, ofs, type) (type*)((const char*)msg + ofs) -#include +typedef void upb_msg; +/** upb_msglayout *************************************************************/ -#define PTR_AT(msg, ofs, type) (type*)((const char*)msg + ofs) +/* 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. */ + +/* These aren't real labels according to descriptor.proto, but in the table we + * use these for map/packed fields instead of UPB_LABEL_REPEATED. */ +enum { + _UPB_LABEL_MAP = 4, + _UPB_LABEL_PACKED = 7 /* Low 3 bits are common with UPB_LABEL_REPEATED. */ +}; + +typedef struct { + uint32_t number; + uint16_t offset; + int16_t presence; /* If >0, hasbit_index. If <0, -oneof_index. */ + uint16_t submsg_index; /* undefined if descriptortype != MESSAGE or GROUP. */ + uint8_t descriptortype; + uint8_t label; +} upb_msglayout_field; + +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_msg *******************************************************************/ + +/* Internal members of a upb_msg. We can change this without breaking binary + * compatibility. We put these before the user's data. The user's upb_msg* + * points after the upb_msg_internal. */ + +/* Used when a message is not extendable. */ +typedef struct { + char *unknown; + size_t unknown_len; + size_t unknown_size; +} upb_msg_internal; + +/* Used when a message is extendable. */ +typedef struct { + upb_inttable *extdict; + upb_msg_internal base; +} upb_msg_internal_withext; + +/* Maps upb_fieldtype_t -> memory size. */ +extern char _upb_fieldtype_to_size[12]; + +/* Creates a new messages with the given layout on the given arena. */ +upb_msg *_upb_msg_new(const upb_msglayout *l, upb_arena *a); + +/* Adds unknown data (serialized protobuf data) to the given message. The data + * is copied into the message instance. */ +bool _upb_msg_addunknown(upb_msg *msg, const char *data, size_t len, + upb_arena *arena); + +/* Returns a reference to the message's unknown data. */ +const char *upb_msg_getunknown(const upb_msg *msg, size_t *len); + +UPB_INLINE bool _upb_has_field(const void *msg, size_t idx) { + return (*PTR_AT(msg, idx / 8, const char) & (1 << (idx % 8))) != 0; +} + +UPB_INLINE bool _upb_sethas(const void *msg, size_t idx) { + return (*PTR_AT(msg, idx / 8, char)) |= (char)(1 << (idx % 8)); +} + +UPB_INLINE bool _upb_clearhas(const void *msg, size_t idx) { + return (*PTR_AT(msg, idx / 8, char)) &= (char)(~(1 << (idx % 8))); +} + +UPB_INLINE bool _upb_has_oneof_field(const void *msg, size_t case_ofs, int32_t num) { + return *PTR_AT(msg, case_ofs, int32_t) == num; +} + +UPB_INLINE bool _upb_has_submsg_nohasbit(const void *msg, size_t ofs) { + return *PTR_AT(msg, ofs, const void*) != NULL; +} + +UPB_INLINE bool _upb_isrepeated(const upb_msglayout_field *field) { + return (field->label & 3) == UPB_LABEL_REPEATED; +} + +/** upb_array *****************************************************************/ + +/* Our internal representation for repeated fields. */ +typedef struct { + uintptr_t data; /* Tagged ptr: low 3 bits of ptr are lg2(elem size). */ + size_t len; /* Measured in elements. */ + size_t size; /* Measured in elements. */ +} upb_array; + +UPB_INLINE const void *_upb_array_constptr(const upb_array *arr) { + return (void*)(arr->data & ~(uintptr_t)7); +} + +UPB_INLINE void *_upb_array_ptr(upb_array *arr) { + return (void*)_upb_array_constptr(arr); +} + +/* Creates a new array on the given arena. */ +upb_array *_upb_array_new(upb_arena *a, upb_fieldtype_t type); + +/* Resizes the capacity of the array to be at least min_size. */ +bool _upb_array_realloc(upb_array *arr, size_t min_size, upb_arena *arena); + +/* Fallback functions for when the accessors require a resize. */ +void *_upb_array_resize_fallback(upb_array **arr_ptr, size_t size, + upb_fieldtype_t type, upb_arena *arena); +bool _upb_array_append_fallback(upb_array **arr_ptr, const void *value, + upb_fieldtype_t type, upb_arena *arena); UPB_INLINE const void *_upb_array_accessor(const void *msg, size_t ofs, size_t *size) { const upb_array *arr = *PTR_AT(msg, ofs, const upb_array*); if (arr) { if (size) *size = arr->len; - return arr->data; + return _upb_array_constptr(arr); } else { if (size) *size = 0; return NULL; @@ -1166,78 +1209,295 @@ UPB_INLINE void *_upb_array_mutable_accessor(void *msg, size_t ofs, upb_array *arr = *PTR_AT(msg, ofs, upb_array*); if (arr) { if (size) *size = arr->len; - return arr->data; + return _upb_array_ptr(arr); } else { if (size) *size = 0; return NULL; } } -/* TODO(haberman): this is a mess. It will improve when upb_array no longer - * carries reflective state (type, elem_size). */ UPB_INLINE void *_upb_array_resize_accessor(void *msg, size_t ofs, size_t size, - size_t elem_size, upb_fieldtype_t type, upb_arena *arena) { - upb_array *arr = *PTR_AT(msg, ofs, upb_array*); - - if (!arr) { - arr = upb_array_new(arena); - if (!arr) return NULL; - *PTR_AT(msg, ofs, upb_array*) = arr; - } - - if (size > arr->size) { - size_t new_size = UPB_MAX(arr->size, 4); - size_t old_bytes = arr->size * elem_size; - size_t new_bytes; - while (new_size < size) new_size *= 2; - new_bytes = new_size * elem_size; - arr->data = upb_arena_realloc(arena, arr->data, old_bytes, new_bytes); - if (!arr->data) { - return NULL; - } - arr->size = new_size; + upb_array **arr_ptr = PTR_AT(msg, ofs, upb_array*); + upb_array *arr = *arr_ptr; + if (!arr || arr->size < size) { + return _upb_array_resize_fallback(arr_ptr, size, type, arena); } - arr->len = size; - return arr->data; + return _upb_array_ptr(arr); } + UPB_INLINE bool _upb_array_append_accessor(void *msg, size_t ofs, size_t elem_size, upb_fieldtype_t type, const void *value, upb_arena *arena) { - upb_array *arr = *PTR_AT(msg, ofs, upb_array*); - size_t i = arr ? arr->len : 0; - void *data = - _upb_array_resize_accessor(msg, ofs, i + 1, elem_size, type, arena); - if (!data) return false; - memcpy(PTR_AT(data, i * elem_size, char), value, elem_size); + upb_array **arr_ptr = PTR_AT(msg, ofs, upb_array*); + upb_array *arr = *arr_ptr; + void* ptr; + if (!arr || arr->len == arr->size) { + return _upb_array_append_fallback(arr_ptr, value, type, arena); + } + ptr = _upb_array_ptr(arr); + memcpy(PTR_AT(ptr, arr->len * elem_size, char), value, elem_size); + arr->len++; return true; } -UPB_INLINE bool _upb_has_field(const void *msg, size_t idx) { - return (*PTR_AT(msg, idx / 8, const char) & (1 << (idx % 8))) != 0; +/** upb_map *******************************************************************/ + +/* Right now we use strmaps for everything. We'll likely want to use + * integer-specific maps for integer-keyed maps.*/ +typedef struct { + /* Size of key and val, based on the map type. Strings are represented as '0' + * because they must be handled specially. */ + char key_size; + char val_size; + + upb_strtable table; +} upb_map; + +/* Map entries aren't actually stored, they are only used during parsing. For + * parsing, it helps a lot if all map entry messages have the same layout. + * The compiler and def.c must ensure that all map entries have this layout. */ +typedef struct { + upb_msg_internal internal; + union { + upb_strview str; /* For str/bytes. */ + upb_value val; /* For all other types. */ + } k; + union { + upb_strview str; /* For str/bytes. */ + upb_value val; /* For all other types. */ + } v; +} upb_map_entry; + +/* Creates a new map on the given arena with this key/value type. */ +upb_map *_upb_map_new(upb_arena *a, size_t key_size, size_t value_size); + +/* Converting between internal table representation and user values. + * + * _upb_map_tokey() and _upb_map_fromkey() are inverses. + * _upb_map_tovalue() and _upb_map_fromvalue() are inverses. + * + * These functions account for the fact that strings are treated differently + * from other types when stored in a map. + */ + +UPB_INLINE upb_strview _upb_map_tokey(const void *key, size_t size) { + if (size == UPB_MAPTYPE_STRING) { + return *(upb_strview*)key; + } else { + return upb_strview_make((const char*)key, size); + } } -UPB_INLINE bool _upb_sethas(const void *msg, size_t idx) { - return (*PTR_AT(msg, idx / 8, char)) |= (char)(1 << (idx % 8)); +UPB_INLINE void _upb_map_fromkey(upb_strview key, void* out, size_t size) { + if (size == UPB_MAPTYPE_STRING) { + memcpy(out, &key, sizeof(key)); + } else { + memcpy(out, key.data, size); + } } -UPB_INLINE bool _upb_clearhas(const void *msg, size_t idx) { - return (*PTR_AT(msg, idx / 8, char)) &= (char)(~(1 << (idx % 8))); +UPB_INLINE upb_value _upb_map_tovalue(const void *val, size_t size, + upb_arena *a) { + upb_value ret = {0}; + if (size == UPB_MAPTYPE_STRING) { + upb_strview *strp = (upb_strview*)upb_arena_malloc(a, sizeof(*strp)); + *strp = *(upb_strview*)val; + memcpy(&ret, &strp, sizeof(strp)); + } else { + memcpy(&ret, val, size); + } + return ret; } -UPB_INLINE bool _upb_has_oneof_field(const void *msg, size_t case_ofs, int32_t num) { - return *PTR_AT(msg, case_ofs, int32_t) == num; +UPB_INLINE void _upb_map_fromvalue(upb_value val, void* out, size_t size) { + if (size == UPB_MAPTYPE_STRING) { + const upb_strview *strp = (const upb_strview*)upb_value_getptr(val); + memcpy(out, strp, sizeof(upb_strview)); + } else { + memcpy(out, &val, size); + } +} + +/* Map operations, shared by reflection and generated code. */ + +UPB_INLINE size_t _upb_map_size(const upb_map *map) { + return map->table.t.count; +} + +UPB_INLINE bool _upb_map_get(const upb_map *map, const void *key, + size_t key_size, void *val, size_t val_size) { + upb_value tabval; + upb_strview k = _upb_map_tokey(key, key_size); + bool ret = upb_strtable_lookup2(&map->table, k.data, k.size, &tabval); + if (ret) { + _upb_map_fromvalue(tabval, val, val_size); + } + return ret; +} + +UPB_INLINE void* _upb_map_next(const upb_map *map, size_t *iter) { + upb_strtable_iter it; + it.t = &map->table; + it.index = *iter; + upb_strtable_next(&it); + if (upb_strtable_done(&it)) return NULL; + *iter = it.index; + return (void*)str_tabent(&it); +} + +UPB_INLINE bool _upb_map_set(upb_map *map, const void *key, size_t key_size, + void *val, size_t val_size, upb_arena *arena) { + upb_strview strkey = _upb_map_tokey(key, key_size); + upb_value tabval = _upb_map_tovalue(val, val_size, arena); + upb_alloc *a = upb_arena_alloc(arena); + + /* TODO(haberman): add overwrite operation to minimize number of lookups. */ + upb_strtable_remove3(&map->table, strkey.data, strkey.size, NULL, a); + return upb_strtable_insert3(&map->table, strkey.data, strkey.size, tabval, a); +} + +UPB_INLINE bool _upb_map_delete(upb_map *map, const void *key, size_t key_size) { + upb_strview k = _upb_map_tokey(key, key_size); + return upb_strtable_remove3(&map->table, k.data, k.size, NULL, NULL); +} + +UPB_INLINE void _upb_map_clear(upb_map *map) { + upb_strtable_clear(&map->table); +} + +/* Message map operations, these get the map from the message first. */ + +UPB_INLINE size_t _upb_msg_map_size(const upb_msg *msg, size_t ofs) { + upb_map *map = *UPB_PTR_AT(msg, ofs, upb_map *); + return map ? _upb_map_size(map) : 0; +} + +UPB_INLINE bool _upb_msg_map_get(const upb_msg *msg, size_t ofs, + const void *key, size_t key_size, void *val, + size_t val_size) { + upb_map *map = *UPB_PTR_AT(msg, ofs, upb_map *); + if (!map) return false; + return _upb_map_get(map, key, key_size, val, val_size); +} + +UPB_INLINE void *_upb_msg_map_next(const upb_msg *msg, size_t ofs, + size_t *iter) { + upb_map *map = *UPB_PTR_AT(msg, ofs, upb_map *); + if (!map) return NULL; + return _upb_map_next(map, iter); +} + +UPB_INLINE bool _upb_msg_map_set(upb_msg *msg, size_t ofs, const void *key, + size_t key_size, void *val, size_t val_size, + upb_arena *arena) { + upb_map **map = PTR_AT(msg, ofs, upb_map *); + if (!*map) { + *map = _upb_map_new(arena, key_size, val_size); + } + return _upb_map_set(*map, key, key_size, val, val_size, arena); +} + +UPB_INLINE bool _upb_msg_map_delete(upb_msg *msg, size_t ofs, const void *key, + size_t key_size) { + upb_map *map = *UPB_PTR_AT(msg, ofs, upb_map *); + if (!map) return false; + return _upb_map_delete(map, key, key_size); +} + +UPB_INLINE void _upb_msg_map_clear(upb_msg *msg, size_t ofs) { + upb_map *map = *UPB_PTR_AT(msg, ofs, upb_map *); + if (!map) return; + _upb_map_clear(map); +} + +/* Accessing map key/value from a pointer, used by generated code only. */ + +UPB_INLINE void _upb_msg_map_key(const void* msg, void* key, size_t size) { + const upb_tabent *ent = (const upb_tabent*)msg; + uint32_t u32len; + upb_strview k; + k.data = upb_tabstr(ent->key, &u32len); + k.size = u32len; + _upb_map_fromkey(k, key, size); +} + +UPB_INLINE void _upb_msg_map_value(const void* msg, void* val, size_t size) { + const upb_tabent *ent = (const upb_tabent*)msg; + upb_value v; + _upb_value_setval(&v, ent->val.val); + _upb_map_fromvalue(v, val, size); +} + +UPB_INLINE void _upb_msg_map_set_value(void* msg, const void* val, size_t size) { + upb_tabent *ent = (upb_tabent*)msg; + /* This is like _upb_map_tovalue() except the entry already exists so we can + * reuse the allocated upb_strview for string fields. */ + if (size == UPB_MAPTYPE_STRING) { + upb_strview *strp = (upb_strview*)ent->val.val; + memcpy(strp, val, sizeof(*strp)); + } else { + memcpy(&ent->val.val, val, size); + } } #undef PTR_AT +#ifdef __cplusplus +} /* extern "C" */ +#endif + + +#endif /* UPB_MSG_H_ */ + +#ifdef __cplusplus +extern "C" { +#endif + +bool upb_decode(const char *buf, size_t size, upb_msg *msg, + const upb_msglayout *l, upb_arena *arena); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* UPB_DECODE_H_ */ +/* +** upb_encode: parsing into a upb_msg using a upb_msglayout. +*/ + +#ifndef UPB_ENCODE_H_ +#define UPB_ENCODE_H_ + + +#ifdef __cplusplus +extern "C" { +#endif + +char *upb_encode(const void *msg, const upb_msglayout *l, upb_arena *arena, + size_t *size); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* UPB_ENCODE_H_ */ +/* 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. */ + +#ifndef GOOGLE_PROTOBUF_DESCRIPTOR_PROTO_UPB_H_ +#define GOOGLE_PROTOBUF_DESCRIPTOR_PROTO_UPB_H_ -#endif /* UPB_GENERATED_UTIL_H_ */ #ifdef __cplusplus @@ -1381,7 +1641,7 @@ typedef enum { /* google.protobuf.FileDescriptorSet */ UPB_INLINE google_protobuf_FileDescriptorSet *google_protobuf_FileDescriptorSet_new(upb_arena *arena) { - return (google_protobuf_FileDescriptorSet *)upb_msg_new(&google_protobuf_FileDescriptorSet_msginit, arena); + return (google_protobuf_FileDescriptorSet *)_upb_msg_new(&google_protobuf_FileDescriptorSet_msginit, arena); } UPB_INLINE google_protobuf_FileDescriptorSet *google_protobuf_FileDescriptorSet_parse(const char *buf, size_t size, upb_arena *arena) { @@ -1392,16 +1652,17 @@ UPB_INLINE char *google_protobuf_FileDescriptorSet_serialize(const google_protob return upb_encode(msg, &google_protobuf_FileDescriptorSet_msginit, arena, len); } +UPB_INLINE bool google_protobuf_FileDescriptorSet_has_file(const google_protobuf_FileDescriptorSet *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(0, 0)); } UPB_INLINE const google_protobuf_FileDescriptorProto* const* google_protobuf_FileDescriptorSet_file(const google_protobuf_FileDescriptorSet *msg, size_t *len) { return (const google_protobuf_FileDescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(0, 0), len); } UPB_INLINE google_protobuf_FileDescriptorProto** google_protobuf_FileDescriptorSet_mutable_file(google_protobuf_FileDescriptorSet *msg, size_t *len) { return (google_protobuf_FileDescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(0, 0), len); } UPB_INLINE google_protobuf_FileDescriptorProto** google_protobuf_FileDescriptorSet_resize_file(google_protobuf_FileDescriptorSet *msg, size_t len, upb_arena *arena) { - return (google_protobuf_FileDescriptorProto**)_upb_array_resize_accessor(msg, UPB_SIZE(0, 0), len, UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, arena); + return (google_protobuf_FileDescriptorProto**)_upb_array_resize_accessor(msg, UPB_SIZE(0, 0), len, UPB_TYPE_MESSAGE, arena); } UPB_INLINE struct google_protobuf_FileDescriptorProto* google_protobuf_FileDescriptorSet_add_file(google_protobuf_FileDescriptorSet *msg, upb_arena *arena) { - struct google_protobuf_FileDescriptorProto* sub = (struct google_protobuf_FileDescriptorProto*)upb_msg_new(&google_protobuf_FileDescriptorProto_msginit, arena); + struct google_protobuf_FileDescriptorProto* sub = (struct google_protobuf_FileDescriptorProto*)_upb_msg_new(&google_protobuf_FileDescriptorProto_msginit, arena); bool ok = _upb_array_append_accessor( msg, UPB_SIZE(0, 0), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena); if (!ok) return NULL; @@ -1411,7 +1672,7 @@ UPB_INLINE struct google_protobuf_FileDescriptorProto* google_protobuf_FileDescr /* google.protobuf.FileDescriptorProto */ UPB_INLINE google_protobuf_FileDescriptorProto *google_protobuf_FileDescriptorProto_new(upb_arena *arena) { - return (google_protobuf_FileDescriptorProto *)upb_msg_new(&google_protobuf_FileDescriptorProto_msginit, arena); + return (google_protobuf_FileDescriptorProto *)_upb_msg_new(&google_protobuf_FileDescriptorProto_msginit, arena); } UPB_INLINE google_protobuf_FileDescriptorProto *google_protobuf_FileDescriptorProto_parse(const char *buf, size_t size, upb_arena *arena) { @@ -1423,49 +1684,53 @@ UPB_INLINE char *google_protobuf_FileDescriptorProto_serialize(const google_prot } UPB_INLINE bool google_protobuf_FileDescriptorProto_has_name(const google_protobuf_FileDescriptorProto *msg) { return _upb_has_field(msg, 1); } -UPB_INLINE upb_strview google_protobuf_FileDescriptorProto_name(const google_protobuf_FileDescriptorProto *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(4, 8)); } +UPB_INLINE upb_strview google_protobuf_FileDescriptorProto_name(const google_protobuf_FileDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview); } UPB_INLINE bool google_protobuf_FileDescriptorProto_has_package(const google_protobuf_FileDescriptorProto *msg) { return _upb_has_field(msg, 2); } -UPB_INLINE upb_strview google_protobuf_FileDescriptorProto_package(const google_protobuf_FileDescriptorProto *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(12, 24)); } +UPB_INLINE upb_strview google_protobuf_FileDescriptorProto_package(const google_protobuf_FileDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(12, 24), upb_strview); } UPB_INLINE upb_strview const* google_protobuf_FileDescriptorProto_dependency(const google_protobuf_FileDescriptorProto *msg, size_t *len) { return (upb_strview const*)_upb_array_accessor(msg, UPB_SIZE(36, 72), len); } +UPB_INLINE bool google_protobuf_FileDescriptorProto_has_message_type(const google_protobuf_FileDescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(40, 80)); } UPB_INLINE const google_protobuf_DescriptorProto* const* google_protobuf_FileDescriptorProto_message_type(const google_protobuf_FileDescriptorProto *msg, size_t *len) { return (const google_protobuf_DescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(40, 80), len); } +UPB_INLINE bool google_protobuf_FileDescriptorProto_has_enum_type(const google_protobuf_FileDescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(44, 88)); } UPB_INLINE const google_protobuf_EnumDescriptorProto* const* google_protobuf_FileDescriptorProto_enum_type(const google_protobuf_FileDescriptorProto *msg, size_t *len) { return (const google_protobuf_EnumDescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(44, 88), len); } +UPB_INLINE bool google_protobuf_FileDescriptorProto_has_service(const google_protobuf_FileDescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(48, 96)); } UPB_INLINE const google_protobuf_ServiceDescriptorProto* const* google_protobuf_FileDescriptorProto_service(const google_protobuf_FileDescriptorProto *msg, size_t *len) { return (const google_protobuf_ServiceDescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(48, 96), len); } +UPB_INLINE bool google_protobuf_FileDescriptorProto_has_extension(const google_protobuf_FileDescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(52, 104)); } UPB_INLINE const google_protobuf_FieldDescriptorProto* const* google_protobuf_FileDescriptorProto_extension(const google_protobuf_FileDescriptorProto *msg, size_t *len) { return (const google_protobuf_FieldDescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(52, 104), len); } UPB_INLINE bool google_protobuf_FileDescriptorProto_has_options(const google_protobuf_FileDescriptorProto *msg) { return _upb_has_field(msg, 4); } -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(28, 56)); } +UPB_INLINE const google_protobuf_FileOptions* google_protobuf_FileDescriptorProto_options(const google_protobuf_FileDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(28, 56), const google_protobuf_FileOptions*); } UPB_INLINE bool google_protobuf_FileDescriptorProto_has_source_code_info(const google_protobuf_FileDescriptorProto *msg) { return _upb_has_field(msg, 5); } -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(32, 64)); } +UPB_INLINE const google_protobuf_SourceCodeInfo* google_protobuf_FileDescriptorProto_source_code_info(const google_protobuf_FileDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(32, 64), const google_protobuf_SourceCodeInfo*); } UPB_INLINE int32_t const* google_protobuf_FileDescriptorProto_public_dependency(const google_protobuf_FileDescriptorProto *msg, size_t *len) { return (int32_t const*)_upb_array_accessor(msg, UPB_SIZE(56, 112), len); } UPB_INLINE int32_t const* google_protobuf_FileDescriptorProto_weak_dependency(const google_protobuf_FileDescriptorProto *msg, size_t *len) { return (int32_t const*)_upb_array_accessor(msg, UPB_SIZE(60, 120), len); } UPB_INLINE bool google_protobuf_FileDescriptorProto_has_syntax(const google_protobuf_FileDescriptorProto *msg) { return _upb_has_field(msg, 3); } -UPB_INLINE upb_strview google_protobuf_FileDescriptorProto_syntax(const google_protobuf_FileDescriptorProto *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(20, 40)); } +UPB_INLINE upb_strview google_protobuf_FileDescriptorProto_syntax(const google_protobuf_FileDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(20, 40), upb_strview); } UPB_INLINE void google_protobuf_FileDescriptorProto_set_name(google_protobuf_FileDescriptorProto *msg, upb_strview value) { _upb_sethas(msg, 1); - UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(4, 8)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview) = value; } UPB_INLINE void google_protobuf_FileDescriptorProto_set_package(google_protobuf_FileDescriptorProto *msg, upb_strview value) { _upb_sethas(msg, 2); - UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(12, 24)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(12, 24), upb_strview) = value; } UPB_INLINE upb_strview* google_protobuf_FileDescriptorProto_mutable_dependency(google_protobuf_FileDescriptorProto *msg, size_t *len) { return (upb_strview*)_upb_array_mutable_accessor(msg, UPB_SIZE(36, 72), len); } UPB_INLINE upb_strview* google_protobuf_FileDescriptorProto_resize_dependency(google_protobuf_FileDescriptorProto *msg, size_t len, upb_arena *arena) { - return (upb_strview*)_upb_array_resize_accessor(msg, UPB_SIZE(36, 72), len, UPB_SIZE(8, 16), UPB_TYPE_STRING, arena); + return (upb_strview*)_upb_array_resize_accessor(msg, UPB_SIZE(36, 72), len, UPB_TYPE_STRING, arena); } UPB_INLINE bool google_protobuf_FileDescriptorProto_add_dependency(google_protobuf_FileDescriptorProto *msg, upb_strview val, upb_arena *arena) { - return _upb_array_append_accessor( - msg, UPB_SIZE(36, 72), UPB_SIZE(8, 16), UPB_TYPE_STRING, &val, arena); + return _upb_array_append_accessor(msg, UPB_SIZE(36, 72), UPB_SIZE(8, 16), UPB_TYPE_STRING, &val, + arena); } UPB_INLINE google_protobuf_DescriptorProto** google_protobuf_FileDescriptorProto_mutable_message_type(google_protobuf_FileDescriptorProto *msg, size_t *len) { return (google_protobuf_DescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(40, 80), len); } UPB_INLINE google_protobuf_DescriptorProto** google_protobuf_FileDescriptorProto_resize_message_type(google_protobuf_FileDescriptorProto *msg, size_t len, upb_arena *arena) { - return (google_protobuf_DescriptorProto**)_upb_array_resize_accessor(msg, UPB_SIZE(40, 80), len, UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, arena); + return (google_protobuf_DescriptorProto**)_upb_array_resize_accessor(msg, UPB_SIZE(40, 80), len, UPB_TYPE_MESSAGE, arena); } UPB_INLINE struct google_protobuf_DescriptorProto* google_protobuf_FileDescriptorProto_add_message_type(google_protobuf_FileDescriptorProto *msg, upb_arena *arena) { - struct google_protobuf_DescriptorProto* sub = (struct google_protobuf_DescriptorProto*)upb_msg_new(&google_protobuf_DescriptorProto_msginit, arena); + struct google_protobuf_DescriptorProto* sub = (struct google_protobuf_DescriptorProto*)_upb_msg_new(&google_protobuf_DescriptorProto_msginit, arena); bool ok = _upb_array_append_accessor( msg, UPB_SIZE(40, 80), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena); if (!ok) return NULL; @@ -1475,10 +1740,10 @@ UPB_INLINE google_protobuf_EnumDescriptorProto** google_protobuf_FileDescriptorP return (google_protobuf_EnumDescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(44, 88), len); } UPB_INLINE google_protobuf_EnumDescriptorProto** google_protobuf_FileDescriptorProto_resize_enum_type(google_protobuf_FileDescriptorProto *msg, size_t len, upb_arena *arena) { - return (google_protobuf_EnumDescriptorProto**)_upb_array_resize_accessor(msg, UPB_SIZE(44, 88), len, UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, arena); + return (google_protobuf_EnumDescriptorProto**)_upb_array_resize_accessor(msg, UPB_SIZE(44, 88), len, UPB_TYPE_MESSAGE, arena); } UPB_INLINE struct google_protobuf_EnumDescriptorProto* google_protobuf_FileDescriptorProto_add_enum_type(google_protobuf_FileDescriptorProto *msg, upb_arena *arena) { - struct google_protobuf_EnumDescriptorProto* sub = (struct google_protobuf_EnumDescriptorProto*)upb_msg_new(&google_protobuf_EnumDescriptorProto_msginit, arena); + struct google_protobuf_EnumDescriptorProto* sub = (struct google_protobuf_EnumDescriptorProto*)_upb_msg_new(&google_protobuf_EnumDescriptorProto_msginit, arena); bool ok = _upb_array_append_accessor( msg, UPB_SIZE(44, 88), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena); if (!ok) return NULL; @@ -1488,10 +1753,10 @@ UPB_INLINE google_protobuf_ServiceDescriptorProto** google_protobuf_FileDescript return (google_protobuf_ServiceDescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(48, 96), len); } UPB_INLINE google_protobuf_ServiceDescriptorProto** google_protobuf_FileDescriptorProto_resize_service(google_protobuf_FileDescriptorProto *msg, size_t len, upb_arena *arena) { - return (google_protobuf_ServiceDescriptorProto**)_upb_array_resize_accessor(msg, UPB_SIZE(48, 96), len, UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, arena); + return (google_protobuf_ServiceDescriptorProto**)_upb_array_resize_accessor(msg, UPB_SIZE(48, 96), len, UPB_TYPE_MESSAGE, arena); } UPB_INLINE struct google_protobuf_ServiceDescriptorProto* google_protobuf_FileDescriptorProto_add_service(google_protobuf_FileDescriptorProto *msg, upb_arena *arena) { - struct google_protobuf_ServiceDescriptorProto* sub = (struct google_protobuf_ServiceDescriptorProto*)upb_msg_new(&google_protobuf_ServiceDescriptorProto_msginit, arena); + struct google_protobuf_ServiceDescriptorProto* sub = (struct google_protobuf_ServiceDescriptorProto*)_upb_msg_new(&google_protobuf_ServiceDescriptorProto_msginit, arena); bool ok = _upb_array_append_accessor( msg, UPB_SIZE(48, 96), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena); if (!ok) return NULL; @@ -1501,10 +1766,10 @@ UPB_INLINE google_protobuf_FieldDescriptorProto** google_protobuf_FileDescriptor return (google_protobuf_FieldDescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(52, 104), len); } UPB_INLINE google_protobuf_FieldDescriptorProto** google_protobuf_FileDescriptorProto_resize_extension(google_protobuf_FileDescriptorProto *msg, size_t len, upb_arena *arena) { - return (google_protobuf_FieldDescriptorProto**)_upb_array_resize_accessor(msg, UPB_SIZE(52, 104), len, UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, arena); + return (google_protobuf_FieldDescriptorProto**)_upb_array_resize_accessor(msg, UPB_SIZE(52, 104), len, UPB_TYPE_MESSAGE, arena); } UPB_INLINE struct google_protobuf_FieldDescriptorProto* google_protobuf_FileDescriptorProto_add_extension(google_protobuf_FileDescriptorProto *msg, upb_arena *arena) { - struct google_protobuf_FieldDescriptorProto* sub = (struct google_protobuf_FieldDescriptorProto*)upb_msg_new(&google_protobuf_FieldDescriptorProto_msginit, arena); + struct google_protobuf_FieldDescriptorProto* sub = (struct google_protobuf_FieldDescriptorProto*)_upb_msg_new(&google_protobuf_FieldDescriptorProto_msginit, arena); bool ok = _upb_array_append_accessor( msg, UPB_SIZE(52, 104), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena); if (!ok) return NULL; @@ -1512,12 +1777,12 @@ UPB_INLINE struct google_protobuf_FieldDescriptorProto* google_protobuf_FileDesc } UPB_INLINE void google_protobuf_FileDescriptorProto_set_options(google_protobuf_FileDescriptorProto *msg, google_protobuf_FileOptions* value) { _upb_sethas(msg, 4); - UPB_FIELD_AT(msg, google_protobuf_FileOptions*, UPB_SIZE(28, 56)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(28, 56), google_protobuf_FileOptions*) = value; } UPB_INLINE struct google_protobuf_FileOptions* google_protobuf_FileDescriptorProto_mutable_options(google_protobuf_FileDescriptorProto *msg, upb_arena *arena) { struct google_protobuf_FileOptions* sub = (struct google_protobuf_FileOptions*)google_protobuf_FileDescriptorProto_options(msg); if (sub == NULL) { - sub = (struct google_protobuf_FileOptions*)upb_msg_new(&google_protobuf_FileOptions_msginit, arena); + sub = (struct google_protobuf_FileOptions*)_upb_msg_new(&google_protobuf_FileOptions_msginit, arena); if (!sub) return NULL; google_protobuf_FileDescriptorProto_set_options(msg, sub); } @@ -1525,12 +1790,12 @@ UPB_INLINE struct google_protobuf_FileOptions* google_protobuf_FileDescriptorPro } UPB_INLINE void google_protobuf_FileDescriptorProto_set_source_code_info(google_protobuf_FileDescriptorProto *msg, google_protobuf_SourceCodeInfo* value) { _upb_sethas(msg, 5); - UPB_FIELD_AT(msg, google_protobuf_SourceCodeInfo*, UPB_SIZE(32, 64)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(32, 64), google_protobuf_SourceCodeInfo*) = value; } UPB_INLINE struct google_protobuf_SourceCodeInfo* google_protobuf_FileDescriptorProto_mutable_source_code_info(google_protobuf_FileDescriptorProto *msg, upb_arena *arena) { struct google_protobuf_SourceCodeInfo* sub = (struct google_protobuf_SourceCodeInfo*)google_protobuf_FileDescriptorProto_source_code_info(msg); if (sub == NULL) { - sub = (struct google_protobuf_SourceCodeInfo*)upb_msg_new(&google_protobuf_SourceCodeInfo_msginit, arena); + sub = (struct google_protobuf_SourceCodeInfo*)_upb_msg_new(&google_protobuf_SourceCodeInfo_msginit, arena); if (!sub) return NULL; google_protobuf_FileDescriptorProto_set_source_code_info(msg, sub); } @@ -1540,31 +1805,31 @@ UPB_INLINE int32_t* google_protobuf_FileDescriptorProto_mutable_public_dependenc return (int32_t*)_upb_array_mutable_accessor(msg, UPB_SIZE(56, 112), len); } UPB_INLINE int32_t* google_protobuf_FileDescriptorProto_resize_public_dependency(google_protobuf_FileDescriptorProto *msg, size_t len, upb_arena *arena) { - return (int32_t*)_upb_array_resize_accessor(msg, UPB_SIZE(56, 112), len, UPB_SIZE(4, 4), UPB_TYPE_INT32, arena); + return (int32_t*)_upb_array_resize_accessor(msg, UPB_SIZE(56, 112), len, UPB_TYPE_INT32, arena); } UPB_INLINE bool google_protobuf_FileDescriptorProto_add_public_dependency(google_protobuf_FileDescriptorProto *msg, int32_t val, upb_arena *arena) { - return _upb_array_append_accessor( - msg, UPB_SIZE(56, 112), UPB_SIZE(4, 4), UPB_TYPE_INT32, &val, arena); + return _upb_array_append_accessor(msg, UPB_SIZE(56, 112), UPB_SIZE(4, 4), UPB_TYPE_INT32, &val, + arena); } UPB_INLINE int32_t* google_protobuf_FileDescriptorProto_mutable_weak_dependency(google_protobuf_FileDescriptorProto *msg, size_t *len) { return (int32_t*)_upb_array_mutable_accessor(msg, UPB_SIZE(60, 120), len); } UPB_INLINE int32_t* google_protobuf_FileDescriptorProto_resize_weak_dependency(google_protobuf_FileDescriptorProto *msg, size_t len, upb_arena *arena) { - return (int32_t*)_upb_array_resize_accessor(msg, UPB_SIZE(60, 120), len, UPB_SIZE(4, 4), UPB_TYPE_INT32, arena); + return (int32_t*)_upb_array_resize_accessor(msg, UPB_SIZE(60, 120), len, UPB_TYPE_INT32, arena); } UPB_INLINE bool google_protobuf_FileDescriptorProto_add_weak_dependency(google_protobuf_FileDescriptorProto *msg, int32_t val, upb_arena *arena) { - return _upb_array_append_accessor( - msg, UPB_SIZE(60, 120), UPB_SIZE(4, 4), UPB_TYPE_INT32, &val, arena); + return _upb_array_append_accessor(msg, UPB_SIZE(60, 120), UPB_SIZE(4, 4), UPB_TYPE_INT32, &val, + arena); } UPB_INLINE void google_protobuf_FileDescriptorProto_set_syntax(google_protobuf_FileDescriptorProto *msg, upb_strview value) { _upb_sethas(msg, 3); - UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(20, 40)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(20, 40), upb_strview) = value; } /* google.protobuf.DescriptorProto */ UPB_INLINE google_protobuf_DescriptorProto *google_protobuf_DescriptorProto_new(upb_arena *arena) { - return (google_protobuf_DescriptorProto *)upb_msg_new(&google_protobuf_DescriptorProto_msginit, arena); + return (google_protobuf_DescriptorProto *)_upb_msg_new(&google_protobuf_DescriptorProto_msginit, arena); } UPB_INLINE google_protobuf_DescriptorProto *google_protobuf_DescriptorProto_parse(const char *buf, size_t size, upb_arena *arena) { @@ -1576,30 +1841,37 @@ UPB_INLINE char *google_protobuf_DescriptorProto_serialize(const google_protobuf } UPB_INLINE bool google_protobuf_DescriptorProto_has_name(const google_protobuf_DescriptorProto *msg) { return _upb_has_field(msg, 1); } -UPB_INLINE upb_strview google_protobuf_DescriptorProto_name(const google_protobuf_DescriptorProto *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(4, 8)); } +UPB_INLINE upb_strview google_protobuf_DescriptorProto_name(const google_protobuf_DescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview); } +UPB_INLINE bool google_protobuf_DescriptorProto_has_field(const google_protobuf_DescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(16, 32)); } UPB_INLINE const google_protobuf_FieldDescriptorProto* const* google_protobuf_DescriptorProto_field(const google_protobuf_DescriptorProto *msg, size_t *len) { return (const google_protobuf_FieldDescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(16, 32), len); } +UPB_INLINE bool google_protobuf_DescriptorProto_has_nested_type(const google_protobuf_DescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(20, 40)); } UPB_INLINE const google_protobuf_DescriptorProto* const* google_protobuf_DescriptorProto_nested_type(const google_protobuf_DescriptorProto *msg, size_t *len) { return (const google_protobuf_DescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(20, 40), len); } +UPB_INLINE bool google_protobuf_DescriptorProto_has_enum_type(const google_protobuf_DescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(24, 48)); } UPB_INLINE const google_protobuf_EnumDescriptorProto* const* google_protobuf_DescriptorProto_enum_type(const google_protobuf_DescriptorProto *msg, size_t *len) { return (const google_protobuf_EnumDescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(24, 48), len); } +UPB_INLINE bool google_protobuf_DescriptorProto_has_extension_range(const google_protobuf_DescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(28, 56)); } UPB_INLINE const google_protobuf_DescriptorProto_ExtensionRange* const* google_protobuf_DescriptorProto_extension_range(const google_protobuf_DescriptorProto *msg, size_t *len) { return (const google_protobuf_DescriptorProto_ExtensionRange* const*)_upb_array_accessor(msg, UPB_SIZE(28, 56), len); } +UPB_INLINE bool google_protobuf_DescriptorProto_has_extension(const google_protobuf_DescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(32, 64)); } UPB_INLINE const google_protobuf_FieldDescriptorProto* const* google_protobuf_DescriptorProto_extension(const google_protobuf_DescriptorProto *msg, size_t *len) { return (const google_protobuf_FieldDescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(32, 64), len); } UPB_INLINE bool google_protobuf_DescriptorProto_has_options(const google_protobuf_DescriptorProto *msg) { return _upb_has_field(msg, 2); } -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(12, 24)); } +UPB_INLINE const google_protobuf_MessageOptions* google_protobuf_DescriptorProto_options(const google_protobuf_DescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(12, 24), const google_protobuf_MessageOptions*); } +UPB_INLINE bool google_protobuf_DescriptorProto_has_oneof_decl(const google_protobuf_DescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(36, 72)); } UPB_INLINE const google_protobuf_OneofDescriptorProto* const* google_protobuf_DescriptorProto_oneof_decl(const google_protobuf_DescriptorProto *msg, size_t *len) { return (const google_protobuf_OneofDescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(36, 72), len); } +UPB_INLINE bool google_protobuf_DescriptorProto_has_reserved_range(const google_protobuf_DescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(40, 80)); } UPB_INLINE const google_protobuf_DescriptorProto_ReservedRange* const* google_protobuf_DescriptorProto_reserved_range(const google_protobuf_DescriptorProto *msg, size_t *len) { return (const google_protobuf_DescriptorProto_ReservedRange* const*)_upb_array_accessor(msg, UPB_SIZE(40, 80), len); } UPB_INLINE upb_strview const* google_protobuf_DescriptorProto_reserved_name(const google_protobuf_DescriptorProto *msg, size_t *len) { return (upb_strview const*)_upb_array_accessor(msg, UPB_SIZE(44, 88), len); } UPB_INLINE void google_protobuf_DescriptorProto_set_name(google_protobuf_DescriptorProto *msg, upb_strview value) { _upb_sethas(msg, 1); - UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(4, 8)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview) = value; } UPB_INLINE google_protobuf_FieldDescriptorProto** google_protobuf_DescriptorProto_mutable_field(google_protobuf_DescriptorProto *msg, size_t *len) { return (google_protobuf_FieldDescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(16, 32), len); } UPB_INLINE google_protobuf_FieldDescriptorProto** google_protobuf_DescriptorProto_resize_field(google_protobuf_DescriptorProto *msg, size_t len, upb_arena *arena) { - return (google_protobuf_FieldDescriptorProto**)_upb_array_resize_accessor(msg, UPB_SIZE(16, 32), len, UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, arena); + return (google_protobuf_FieldDescriptorProto**)_upb_array_resize_accessor(msg, UPB_SIZE(16, 32), len, UPB_TYPE_MESSAGE, arena); } UPB_INLINE struct google_protobuf_FieldDescriptorProto* google_protobuf_DescriptorProto_add_field(google_protobuf_DescriptorProto *msg, upb_arena *arena) { - struct google_protobuf_FieldDescriptorProto* sub = (struct google_protobuf_FieldDescriptorProto*)upb_msg_new(&google_protobuf_FieldDescriptorProto_msginit, arena); + struct google_protobuf_FieldDescriptorProto* sub = (struct google_protobuf_FieldDescriptorProto*)_upb_msg_new(&google_protobuf_FieldDescriptorProto_msginit, arena); bool ok = _upb_array_append_accessor( msg, UPB_SIZE(16, 32), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena); if (!ok) return NULL; @@ -1609,10 +1881,10 @@ UPB_INLINE google_protobuf_DescriptorProto** google_protobuf_DescriptorProto_mut return (google_protobuf_DescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(20, 40), len); } UPB_INLINE google_protobuf_DescriptorProto** google_protobuf_DescriptorProto_resize_nested_type(google_protobuf_DescriptorProto *msg, size_t len, upb_arena *arena) { - return (google_protobuf_DescriptorProto**)_upb_array_resize_accessor(msg, UPB_SIZE(20, 40), len, UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, arena); + return (google_protobuf_DescriptorProto**)_upb_array_resize_accessor(msg, UPB_SIZE(20, 40), len, UPB_TYPE_MESSAGE, arena); } UPB_INLINE struct google_protobuf_DescriptorProto* google_protobuf_DescriptorProto_add_nested_type(google_protobuf_DescriptorProto *msg, upb_arena *arena) { - struct google_protobuf_DescriptorProto* sub = (struct google_protobuf_DescriptorProto*)upb_msg_new(&google_protobuf_DescriptorProto_msginit, arena); + struct google_protobuf_DescriptorProto* sub = (struct google_protobuf_DescriptorProto*)_upb_msg_new(&google_protobuf_DescriptorProto_msginit, arena); bool ok = _upb_array_append_accessor( msg, UPB_SIZE(20, 40), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena); if (!ok) return NULL; @@ -1622,10 +1894,10 @@ UPB_INLINE google_protobuf_EnumDescriptorProto** google_protobuf_DescriptorProto return (google_protobuf_EnumDescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(24, 48), len); } UPB_INLINE google_protobuf_EnumDescriptorProto** google_protobuf_DescriptorProto_resize_enum_type(google_protobuf_DescriptorProto *msg, size_t len, upb_arena *arena) { - return (google_protobuf_EnumDescriptorProto**)_upb_array_resize_accessor(msg, UPB_SIZE(24, 48), len, UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, arena); + return (google_protobuf_EnumDescriptorProto**)_upb_array_resize_accessor(msg, UPB_SIZE(24, 48), len, UPB_TYPE_MESSAGE, arena); } UPB_INLINE struct google_protobuf_EnumDescriptorProto* google_protobuf_DescriptorProto_add_enum_type(google_protobuf_DescriptorProto *msg, upb_arena *arena) { - struct google_protobuf_EnumDescriptorProto* sub = (struct google_protobuf_EnumDescriptorProto*)upb_msg_new(&google_protobuf_EnumDescriptorProto_msginit, arena); + struct google_protobuf_EnumDescriptorProto* sub = (struct google_protobuf_EnumDescriptorProto*)_upb_msg_new(&google_protobuf_EnumDescriptorProto_msginit, arena); bool ok = _upb_array_append_accessor( msg, UPB_SIZE(24, 48), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena); if (!ok) return NULL; @@ -1635,10 +1907,10 @@ UPB_INLINE google_protobuf_DescriptorProto_ExtensionRange** google_protobuf_Desc return (google_protobuf_DescriptorProto_ExtensionRange**)_upb_array_mutable_accessor(msg, UPB_SIZE(28, 56), len); } UPB_INLINE google_protobuf_DescriptorProto_ExtensionRange** google_protobuf_DescriptorProto_resize_extension_range(google_protobuf_DescriptorProto *msg, size_t len, upb_arena *arena) { - return (google_protobuf_DescriptorProto_ExtensionRange**)_upb_array_resize_accessor(msg, UPB_SIZE(28, 56), len, UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, arena); + return (google_protobuf_DescriptorProto_ExtensionRange**)_upb_array_resize_accessor(msg, UPB_SIZE(28, 56), len, UPB_TYPE_MESSAGE, arena); } UPB_INLINE struct google_protobuf_DescriptorProto_ExtensionRange* google_protobuf_DescriptorProto_add_extension_range(google_protobuf_DescriptorProto *msg, upb_arena *arena) { - struct google_protobuf_DescriptorProto_ExtensionRange* sub = (struct google_protobuf_DescriptorProto_ExtensionRange*)upb_msg_new(&google_protobuf_DescriptorProto_ExtensionRange_msginit, arena); + struct google_protobuf_DescriptorProto_ExtensionRange* sub = (struct google_protobuf_DescriptorProto_ExtensionRange*)_upb_msg_new(&google_protobuf_DescriptorProto_ExtensionRange_msginit, arena); bool ok = _upb_array_append_accessor( msg, UPB_SIZE(28, 56), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena); if (!ok) return NULL; @@ -1648,10 +1920,10 @@ UPB_INLINE google_protobuf_FieldDescriptorProto** google_protobuf_DescriptorProt return (google_protobuf_FieldDescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(32, 64), len); } UPB_INLINE google_protobuf_FieldDescriptorProto** google_protobuf_DescriptorProto_resize_extension(google_protobuf_DescriptorProto *msg, size_t len, upb_arena *arena) { - return (google_protobuf_FieldDescriptorProto**)_upb_array_resize_accessor(msg, UPB_SIZE(32, 64), len, UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, arena); + return (google_protobuf_FieldDescriptorProto**)_upb_array_resize_accessor(msg, UPB_SIZE(32, 64), len, UPB_TYPE_MESSAGE, arena); } UPB_INLINE struct google_protobuf_FieldDescriptorProto* google_protobuf_DescriptorProto_add_extension(google_protobuf_DescriptorProto *msg, upb_arena *arena) { - struct google_protobuf_FieldDescriptorProto* sub = (struct google_protobuf_FieldDescriptorProto*)upb_msg_new(&google_protobuf_FieldDescriptorProto_msginit, arena); + struct google_protobuf_FieldDescriptorProto* sub = (struct google_protobuf_FieldDescriptorProto*)_upb_msg_new(&google_protobuf_FieldDescriptorProto_msginit, arena); bool ok = _upb_array_append_accessor( msg, UPB_SIZE(32, 64), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena); if (!ok) return NULL; @@ -1659,12 +1931,12 @@ UPB_INLINE struct google_protobuf_FieldDescriptorProto* google_protobuf_Descript } UPB_INLINE void google_protobuf_DescriptorProto_set_options(google_protobuf_DescriptorProto *msg, google_protobuf_MessageOptions* value) { _upb_sethas(msg, 2); - UPB_FIELD_AT(msg, google_protobuf_MessageOptions*, UPB_SIZE(12, 24)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(12, 24), google_protobuf_MessageOptions*) = value; } UPB_INLINE struct google_protobuf_MessageOptions* google_protobuf_DescriptorProto_mutable_options(google_protobuf_DescriptorProto *msg, upb_arena *arena) { struct google_protobuf_MessageOptions* sub = (struct google_protobuf_MessageOptions*)google_protobuf_DescriptorProto_options(msg); if (sub == NULL) { - sub = (struct google_protobuf_MessageOptions*)upb_msg_new(&google_protobuf_MessageOptions_msginit, arena); + sub = (struct google_protobuf_MessageOptions*)_upb_msg_new(&google_protobuf_MessageOptions_msginit, arena); if (!sub) return NULL; google_protobuf_DescriptorProto_set_options(msg, sub); } @@ -1674,10 +1946,10 @@ UPB_INLINE google_protobuf_OneofDescriptorProto** google_protobuf_DescriptorProt return (google_protobuf_OneofDescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(36, 72), len); } UPB_INLINE google_protobuf_OneofDescriptorProto** google_protobuf_DescriptorProto_resize_oneof_decl(google_protobuf_DescriptorProto *msg, size_t len, upb_arena *arena) { - return (google_protobuf_OneofDescriptorProto**)_upb_array_resize_accessor(msg, UPB_SIZE(36, 72), len, UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, arena); + return (google_protobuf_OneofDescriptorProto**)_upb_array_resize_accessor(msg, UPB_SIZE(36, 72), len, UPB_TYPE_MESSAGE, arena); } UPB_INLINE struct google_protobuf_OneofDescriptorProto* google_protobuf_DescriptorProto_add_oneof_decl(google_protobuf_DescriptorProto *msg, upb_arena *arena) { - struct google_protobuf_OneofDescriptorProto* sub = (struct google_protobuf_OneofDescriptorProto*)upb_msg_new(&google_protobuf_OneofDescriptorProto_msginit, arena); + struct google_protobuf_OneofDescriptorProto* sub = (struct google_protobuf_OneofDescriptorProto*)_upb_msg_new(&google_protobuf_OneofDescriptorProto_msginit, arena); bool ok = _upb_array_append_accessor( msg, UPB_SIZE(36, 72), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena); if (!ok) return NULL; @@ -1687,10 +1959,10 @@ UPB_INLINE google_protobuf_DescriptorProto_ReservedRange** google_protobuf_Descr return (google_protobuf_DescriptorProto_ReservedRange**)_upb_array_mutable_accessor(msg, UPB_SIZE(40, 80), len); } UPB_INLINE google_protobuf_DescriptorProto_ReservedRange** google_protobuf_DescriptorProto_resize_reserved_range(google_protobuf_DescriptorProto *msg, size_t len, upb_arena *arena) { - return (google_protobuf_DescriptorProto_ReservedRange**)_upb_array_resize_accessor(msg, UPB_SIZE(40, 80), len, UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, arena); + return (google_protobuf_DescriptorProto_ReservedRange**)_upb_array_resize_accessor(msg, UPB_SIZE(40, 80), len, UPB_TYPE_MESSAGE, arena); } UPB_INLINE struct google_protobuf_DescriptorProto_ReservedRange* google_protobuf_DescriptorProto_add_reserved_range(google_protobuf_DescriptorProto *msg, upb_arena *arena) { - struct google_protobuf_DescriptorProto_ReservedRange* sub = (struct google_protobuf_DescriptorProto_ReservedRange*)upb_msg_new(&google_protobuf_DescriptorProto_ReservedRange_msginit, arena); + struct google_protobuf_DescriptorProto_ReservedRange* sub = (struct google_protobuf_DescriptorProto_ReservedRange*)_upb_msg_new(&google_protobuf_DescriptorProto_ReservedRange_msginit, arena); bool ok = _upb_array_append_accessor( msg, UPB_SIZE(40, 80), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena); if (!ok) return NULL; @@ -1700,17 +1972,17 @@ UPB_INLINE upb_strview* google_protobuf_DescriptorProto_mutable_reserved_name(go return (upb_strview*)_upb_array_mutable_accessor(msg, UPB_SIZE(44, 88), len); } UPB_INLINE upb_strview* google_protobuf_DescriptorProto_resize_reserved_name(google_protobuf_DescriptorProto *msg, size_t len, upb_arena *arena) { - return (upb_strview*)_upb_array_resize_accessor(msg, UPB_SIZE(44, 88), len, UPB_SIZE(8, 16), UPB_TYPE_STRING, arena); + return (upb_strview*)_upb_array_resize_accessor(msg, UPB_SIZE(44, 88), len, UPB_TYPE_STRING, arena); } UPB_INLINE bool google_protobuf_DescriptorProto_add_reserved_name(google_protobuf_DescriptorProto *msg, upb_strview val, upb_arena *arena) { - return _upb_array_append_accessor( - msg, UPB_SIZE(44, 88), UPB_SIZE(8, 16), UPB_TYPE_STRING, &val, arena); + return _upb_array_append_accessor(msg, UPB_SIZE(44, 88), UPB_SIZE(8, 16), UPB_TYPE_STRING, &val, + arena); } /* google.protobuf.DescriptorProto.ExtensionRange */ UPB_INLINE google_protobuf_DescriptorProto_ExtensionRange *google_protobuf_DescriptorProto_ExtensionRange_new(upb_arena *arena) { - return (google_protobuf_DescriptorProto_ExtensionRange *)upb_msg_new(&google_protobuf_DescriptorProto_ExtensionRange_msginit, arena); + return (google_protobuf_DescriptorProto_ExtensionRange *)_upb_msg_new(&google_protobuf_DescriptorProto_ExtensionRange_msginit, arena); } UPB_INLINE google_protobuf_DescriptorProto_ExtensionRange *google_protobuf_DescriptorProto_ExtensionRange_parse(const char *buf, size_t size, upb_arena *arena) { @@ -1722,28 +1994,28 @@ UPB_INLINE char *google_protobuf_DescriptorProto_ExtensionRange_serialize(const } UPB_INLINE bool google_protobuf_DescriptorProto_ExtensionRange_has_start(const google_protobuf_DescriptorProto_ExtensionRange *msg) { return _upb_has_field(msg, 1); } -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_start(const google_protobuf_DescriptorProto_ExtensionRange *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t); } UPB_INLINE bool google_protobuf_DescriptorProto_ExtensionRange_has_end(const google_protobuf_DescriptorProto_ExtensionRange *msg) { return _upb_has_field(msg, 2); } -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 int32_t google_protobuf_DescriptorProto_ExtensionRange_end(const google_protobuf_DescriptorProto_ExtensionRange *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t); } UPB_INLINE bool google_protobuf_DescriptorProto_ExtensionRange_has_options(const google_protobuf_DescriptorProto_ExtensionRange *msg) { return _upb_has_field(msg, 3); } -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 const google_protobuf_ExtensionRangeOptions* google_protobuf_DescriptorProto_ExtensionRange_options(const google_protobuf_DescriptorProto_ExtensionRange *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(12, 16), const google_protobuf_ExtensionRangeOptions*); } UPB_INLINE void google_protobuf_DescriptorProto_ExtensionRange_set_start(google_protobuf_DescriptorProto_ExtensionRange *msg, int32_t value) { _upb_sethas(msg, 1); - UPB_FIELD_AT(msg, int32_t, UPB_SIZE(4, 4)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t) = value; } UPB_INLINE void google_protobuf_DescriptorProto_ExtensionRange_set_end(google_protobuf_DescriptorProto_ExtensionRange *msg, int32_t value) { _upb_sethas(msg, 2); - UPB_FIELD_AT(msg, int32_t, UPB_SIZE(8, 8)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t) = value; } UPB_INLINE void google_protobuf_DescriptorProto_ExtensionRange_set_options(google_protobuf_DescriptorProto_ExtensionRange *msg, google_protobuf_ExtensionRangeOptions* value) { _upb_sethas(msg, 3); - UPB_FIELD_AT(msg, google_protobuf_ExtensionRangeOptions*, UPB_SIZE(12, 16)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(12, 16), google_protobuf_ExtensionRangeOptions*) = value; } UPB_INLINE struct google_protobuf_ExtensionRangeOptions* google_protobuf_DescriptorProto_ExtensionRange_mutable_options(google_protobuf_DescriptorProto_ExtensionRange *msg, upb_arena *arena) { struct google_protobuf_ExtensionRangeOptions* sub = (struct google_protobuf_ExtensionRangeOptions*)google_protobuf_DescriptorProto_ExtensionRange_options(msg); if (sub == NULL) { - sub = (struct google_protobuf_ExtensionRangeOptions*)upb_msg_new(&google_protobuf_ExtensionRangeOptions_msginit, arena); + sub = (struct google_protobuf_ExtensionRangeOptions*)_upb_msg_new(&google_protobuf_ExtensionRangeOptions_msginit, arena); if (!sub) return NULL; google_protobuf_DescriptorProto_ExtensionRange_set_options(msg, sub); } @@ -1753,7 +2025,7 @@ UPB_INLINE struct google_protobuf_ExtensionRangeOptions* google_protobuf_Descrip /* google.protobuf.DescriptorProto.ReservedRange */ UPB_INLINE google_protobuf_DescriptorProto_ReservedRange *google_protobuf_DescriptorProto_ReservedRange_new(upb_arena *arena) { - return (google_protobuf_DescriptorProto_ReservedRange *)upb_msg_new(&google_protobuf_DescriptorProto_ReservedRange_msginit, arena); + return (google_protobuf_DescriptorProto_ReservedRange *)_upb_msg_new(&google_protobuf_DescriptorProto_ReservedRange_msginit, arena); } UPB_INLINE google_protobuf_DescriptorProto_ReservedRange *google_protobuf_DescriptorProto_ReservedRange_parse(const char *buf, size_t size, upb_arena *arena) { @@ -1765,23 +2037,23 @@ UPB_INLINE char *google_protobuf_DescriptorProto_ReservedRange_serialize(const g } UPB_INLINE bool google_protobuf_DescriptorProto_ReservedRange_has_start(const google_protobuf_DescriptorProto_ReservedRange *msg) { return _upb_has_field(msg, 1); } -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_start(const google_protobuf_DescriptorProto_ReservedRange *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t); } UPB_INLINE bool google_protobuf_DescriptorProto_ReservedRange_has_end(const google_protobuf_DescriptorProto_ReservedRange *msg) { return _upb_has_field(msg, 2); } -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 int32_t google_protobuf_DescriptorProto_ReservedRange_end(const google_protobuf_DescriptorProto_ReservedRange *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t); } UPB_INLINE void google_protobuf_DescriptorProto_ReservedRange_set_start(google_protobuf_DescriptorProto_ReservedRange *msg, int32_t value) { _upb_sethas(msg, 1); - UPB_FIELD_AT(msg, int32_t, UPB_SIZE(4, 4)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t) = value; } UPB_INLINE void google_protobuf_DescriptorProto_ReservedRange_set_end(google_protobuf_DescriptorProto_ReservedRange *msg, int32_t value) { _upb_sethas(msg, 2); - UPB_FIELD_AT(msg, int32_t, UPB_SIZE(8, 8)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t) = value; } /* google.protobuf.ExtensionRangeOptions */ UPB_INLINE google_protobuf_ExtensionRangeOptions *google_protobuf_ExtensionRangeOptions_new(upb_arena *arena) { - return (google_protobuf_ExtensionRangeOptions *)upb_msg_new(&google_protobuf_ExtensionRangeOptions_msginit, arena); + return (google_protobuf_ExtensionRangeOptions *)_upb_msg_new(&google_protobuf_ExtensionRangeOptions_msginit, arena); } UPB_INLINE google_protobuf_ExtensionRangeOptions *google_protobuf_ExtensionRangeOptions_parse(const char *buf, size_t size, upb_arena *arena) { @@ -1792,16 +2064,17 @@ UPB_INLINE char *google_protobuf_ExtensionRangeOptions_serialize(const google_pr return upb_encode(msg, &google_protobuf_ExtensionRangeOptions_msginit, arena, len); } +UPB_INLINE bool google_protobuf_ExtensionRangeOptions_has_uninterpreted_option(const google_protobuf_ExtensionRangeOptions *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(0, 0)); } UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_ExtensionRangeOptions_uninterpreted_option(const google_protobuf_ExtensionRangeOptions *msg, size_t *len) { return (const google_protobuf_UninterpretedOption* const*)_upb_array_accessor(msg, UPB_SIZE(0, 0), len); } UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_ExtensionRangeOptions_mutable_uninterpreted_option(google_protobuf_ExtensionRangeOptions *msg, size_t *len) { return (google_protobuf_UninterpretedOption**)_upb_array_mutable_accessor(msg, UPB_SIZE(0, 0), len); } UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_ExtensionRangeOptions_resize_uninterpreted_option(google_protobuf_ExtensionRangeOptions *msg, size_t len, upb_arena *arena) { - return (google_protobuf_UninterpretedOption**)_upb_array_resize_accessor(msg, UPB_SIZE(0, 0), len, UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, arena); + return (google_protobuf_UninterpretedOption**)_upb_array_resize_accessor(msg, UPB_SIZE(0, 0), len, UPB_TYPE_MESSAGE, arena); } UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_ExtensionRangeOptions_add_uninterpreted_option(google_protobuf_ExtensionRangeOptions *msg, upb_arena *arena) { - struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)upb_msg_new(&google_protobuf_UninterpretedOption_msginit, arena); + struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)_upb_msg_new(&google_protobuf_UninterpretedOption_msginit, arena); bool ok = _upb_array_append_accessor( msg, UPB_SIZE(0, 0), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena); if (!ok) return NULL; @@ -1811,7 +2084,7 @@ UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_Extension /* google.protobuf.FieldDescriptorProto */ UPB_INLINE google_protobuf_FieldDescriptorProto *google_protobuf_FieldDescriptorProto_new(upb_arena *arena) { - return (google_protobuf_FieldDescriptorProto *)upb_msg_new(&google_protobuf_FieldDescriptorProto_msginit, arena); + return (google_protobuf_FieldDescriptorProto *)_upb_msg_new(&google_protobuf_FieldDescriptorProto_msginit, arena); } UPB_INLINE google_protobuf_FieldDescriptorProto *google_protobuf_FieldDescriptorProto_parse(const char *buf, size_t size, upb_arena *arena) { @@ -1822,63 +2095,65 @@ UPB_INLINE char *google_protobuf_FieldDescriptorProto_serialize(const google_pro return upb_encode(msg, &google_protobuf_FieldDescriptorProto_msginit, arena, len); } -UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_name(const google_protobuf_FieldDescriptorProto *msg) { return _upb_has_field(msg, 5); } -UPB_INLINE upb_strview google_protobuf_FieldDescriptorProto_name(const google_protobuf_FieldDescriptorProto *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(32, 32)); } -UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_extendee(const google_protobuf_FieldDescriptorProto *msg) { return _upb_has_field(msg, 6); } -UPB_INLINE upb_strview google_protobuf_FieldDescriptorProto_extendee(const google_protobuf_FieldDescriptorProto *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(40, 48)); } +UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_name(const google_protobuf_FieldDescriptorProto *msg) { return _upb_has_field(msg, 6); } +UPB_INLINE upb_strview google_protobuf_FieldDescriptorProto_name(const google_protobuf_FieldDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(36, 40), upb_strview); } +UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_extendee(const google_protobuf_FieldDescriptorProto *msg) { return _upb_has_field(msg, 7); } +UPB_INLINE upb_strview google_protobuf_FieldDescriptorProto_extendee(const google_protobuf_FieldDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(44, 56), upb_strview); } UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_number(const google_protobuf_FieldDescriptorProto *msg) { return _upb_has_field(msg, 3); } -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 int32_t google_protobuf_FieldDescriptorProto_number(const google_protobuf_FieldDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(24, 24), int32_t); } UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_label(const google_protobuf_FieldDescriptorProto *msg) { return _upb_has_field(msg, 1); } -UPB_INLINE int32_t google_protobuf_FieldDescriptorProto_label(const google_protobuf_FieldDescriptorProto *msg) { return UPB_FIELD_AT(msg, int32_t, UPB_SIZE(8, 8)); } +UPB_INLINE int32_t google_protobuf_FieldDescriptorProto_label(const google_protobuf_FieldDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t); } UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_type(const google_protobuf_FieldDescriptorProto *msg) { return _upb_has_field(msg, 2); } -UPB_INLINE int32_t google_protobuf_FieldDescriptorProto_type(const google_protobuf_FieldDescriptorProto *msg) { return UPB_FIELD_AT(msg, int32_t, UPB_SIZE(16, 16)); } -UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_type_name(const google_protobuf_FieldDescriptorProto *msg) { return _upb_has_field(msg, 7); } -UPB_INLINE upb_strview google_protobuf_FieldDescriptorProto_type_name(const google_protobuf_FieldDescriptorProto *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(48, 64)); } -UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_default_value(const google_protobuf_FieldDescriptorProto *msg) { return _upb_has_field(msg, 8); } -UPB_INLINE upb_strview google_protobuf_FieldDescriptorProto_default_value(const google_protobuf_FieldDescriptorProto *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(56, 80)); } -UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_options(const google_protobuf_FieldDescriptorProto *msg) { return _upb_has_field(msg, 10); } -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_type(const google_protobuf_FieldDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(16, 16), int32_t); } +UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_type_name(const google_protobuf_FieldDescriptorProto *msg) { return _upb_has_field(msg, 8); } +UPB_INLINE upb_strview google_protobuf_FieldDescriptorProto_type_name(const google_protobuf_FieldDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(52, 72), upb_strview); } +UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_default_value(const google_protobuf_FieldDescriptorProto *msg) { return _upb_has_field(msg, 9); } +UPB_INLINE upb_strview google_protobuf_FieldDescriptorProto_default_value(const google_protobuf_FieldDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(60, 88), upb_strview); } +UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_options(const google_protobuf_FieldDescriptorProto *msg) { return _upb_has_field(msg, 11); } +UPB_INLINE const google_protobuf_FieldOptions* google_protobuf_FieldDescriptorProto_options(const google_protobuf_FieldDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(76, 120), const google_protobuf_FieldOptions*); } UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_oneof_index(const google_protobuf_FieldDescriptorProto *msg) { return _upb_has_field(msg, 4); } -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 bool google_protobuf_FieldDescriptorProto_has_json_name(const google_protobuf_FieldDescriptorProto *msg) { return _upb_has_field(msg, 9); } -UPB_INLINE upb_strview google_protobuf_FieldDescriptorProto_json_name(const google_protobuf_FieldDescriptorProto *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(64, 96)); } +UPB_INLINE int32_t google_protobuf_FieldDescriptorProto_oneof_index(const google_protobuf_FieldDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(28, 28), int32_t); } +UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_json_name(const google_protobuf_FieldDescriptorProto *msg) { return _upb_has_field(msg, 10); } +UPB_INLINE upb_strview google_protobuf_FieldDescriptorProto_json_name(const google_protobuf_FieldDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(68, 104), upb_strview); } +UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_proto3_optional(const google_protobuf_FieldDescriptorProto *msg) { return _upb_has_field(msg, 5); } +UPB_INLINE bool google_protobuf_FieldDescriptorProto_proto3_optional(const google_protobuf_FieldDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(32, 32), bool); } UPB_INLINE void google_protobuf_FieldDescriptorProto_set_name(google_protobuf_FieldDescriptorProto *msg, upb_strview value) { - _upb_sethas(msg, 5); - UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(32, 32)) = value; + _upb_sethas(msg, 6); + *UPB_PTR_AT(msg, UPB_SIZE(36, 40), upb_strview) = value; } UPB_INLINE void google_protobuf_FieldDescriptorProto_set_extendee(google_protobuf_FieldDescriptorProto *msg, upb_strview value) { - _upb_sethas(msg, 6); - UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(40, 48)) = value; + _upb_sethas(msg, 7); + *UPB_PTR_AT(msg, UPB_SIZE(44, 56), upb_strview) = value; } UPB_INLINE void google_protobuf_FieldDescriptorProto_set_number(google_protobuf_FieldDescriptorProto *msg, int32_t value) { _upb_sethas(msg, 3); - UPB_FIELD_AT(msg, int32_t, UPB_SIZE(24, 24)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(24, 24), int32_t) = value; } UPB_INLINE void google_protobuf_FieldDescriptorProto_set_label(google_protobuf_FieldDescriptorProto *msg, int32_t value) { _upb_sethas(msg, 1); - UPB_FIELD_AT(msg, int32_t, UPB_SIZE(8, 8)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t) = value; } UPB_INLINE void google_protobuf_FieldDescriptorProto_set_type(google_protobuf_FieldDescriptorProto *msg, int32_t value) { _upb_sethas(msg, 2); - UPB_FIELD_AT(msg, int32_t, UPB_SIZE(16, 16)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(16, 16), int32_t) = value; } UPB_INLINE void google_protobuf_FieldDescriptorProto_set_type_name(google_protobuf_FieldDescriptorProto *msg, upb_strview value) { - _upb_sethas(msg, 7); - UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(48, 64)) = value; + _upb_sethas(msg, 8); + *UPB_PTR_AT(msg, UPB_SIZE(52, 72), upb_strview) = value; } UPB_INLINE void google_protobuf_FieldDescriptorProto_set_default_value(google_protobuf_FieldDescriptorProto *msg, upb_strview value) { - _upb_sethas(msg, 8); - UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(56, 80)) = value; + _upb_sethas(msg, 9); + *UPB_PTR_AT(msg, UPB_SIZE(60, 88), upb_strview) = value; } UPB_INLINE void google_protobuf_FieldDescriptorProto_set_options(google_protobuf_FieldDescriptorProto *msg, google_protobuf_FieldOptions* value) { - _upb_sethas(msg, 10); - UPB_FIELD_AT(msg, google_protobuf_FieldOptions*, UPB_SIZE(72, 112)) = value; + _upb_sethas(msg, 11); + *UPB_PTR_AT(msg, UPB_SIZE(76, 120), google_protobuf_FieldOptions*) = value; } UPB_INLINE struct google_protobuf_FieldOptions* google_protobuf_FieldDescriptorProto_mutable_options(google_protobuf_FieldDescriptorProto *msg, upb_arena *arena) { struct google_protobuf_FieldOptions* sub = (struct google_protobuf_FieldOptions*)google_protobuf_FieldDescriptorProto_options(msg); if (sub == NULL) { - sub = (struct google_protobuf_FieldOptions*)upb_msg_new(&google_protobuf_FieldOptions_msginit, arena); + sub = (struct google_protobuf_FieldOptions*)_upb_msg_new(&google_protobuf_FieldOptions_msginit, arena); if (!sub) return NULL; google_protobuf_FieldDescriptorProto_set_options(msg, sub); } @@ -1886,17 +2161,21 @@ UPB_INLINE struct google_protobuf_FieldOptions* google_protobuf_FieldDescriptorP } UPB_INLINE void google_protobuf_FieldDescriptorProto_set_oneof_index(google_protobuf_FieldDescriptorProto *msg, int32_t value) { _upb_sethas(msg, 4); - UPB_FIELD_AT(msg, int32_t, UPB_SIZE(28, 28)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(28, 28), int32_t) = value; } UPB_INLINE void google_protobuf_FieldDescriptorProto_set_json_name(google_protobuf_FieldDescriptorProto *msg, upb_strview value) { - _upb_sethas(msg, 9); - UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(64, 96)) = value; + _upb_sethas(msg, 10); + *UPB_PTR_AT(msg, UPB_SIZE(68, 104), upb_strview) = value; +} +UPB_INLINE void google_protobuf_FieldDescriptorProto_set_proto3_optional(google_protobuf_FieldDescriptorProto *msg, bool value) { + _upb_sethas(msg, 5); + *UPB_PTR_AT(msg, UPB_SIZE(32, 32), bool) = value; } /* google.protobuf.OneofDescriptorProto */ UPB_INLINE google_protobuf_OneofDescriptorProto *google_protobuf_OneofDescriptorProto_new(upb_arena *arena) { - return (google_protobuf_OneofDescriptorProto *)upb_msg_new(&google_protobuf_OneofDescriptorProto_msginit, arena); + return (google_protobuf_OneofDescriptorProto *)_upb_msg_new(&google_protobuf_OneofDescriptorProto_msginit, arena); } UPB_INLINE google_protobuf_OneofDescriptorProto *google_protobuf_OneofDescriptorProto_parse(const char *buf, size_t size, upb_arena *arena) { @@ -1908,22 +2187,22 @@ UPB_INLINE char *google_protobuf_OneofDescriptorProto_serialize(const google_pro } UPB_INLINE bool google_protobuf_OneofDescriptorProto_has_name(const google_protobuf_OneofDescriptorProto *msg) { return _upb_has_field(msg, 1); } -UPB_INLINE upb_strview google_protobuf_OneofDescriptorProto_name(const google_protobuf_OneofDescriptorProto *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(4, 8)); } +UPB_INLINE upb_strview google_protobuf_OneofDescriptorProto_name(const google_protobuf_OneofDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview); } UPB_INLINE bool google_protobuf_OneofDescriptorProto_has_options(const google_protobuf_OneofDescriptorProto *msg) { return _upb_has_field(msg, 2); } -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(12, 24)); } +UPB_INLINE const google_protobuf_OneofOptions* google_protobuf_OneofDescriptorProto_options(const google_protobuf_OneofDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(12, 24), const google_protobuf_OneofOptions*); } UPB_INLINE void google_protobuf_OneofDescriptorProto_set_name(google_protobuf_OneofDescriptorProto *msg, upb_strview value) { _upb_sethas(msg, 1); - UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(4, 8)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview) = value; } UPB_INLINE void google_protobuf_OneofDescriptorProto_set_options(google_protobuf_OneofDescriptorProto *msg, google_protobuf_OneofOptions* value) { _upb_sethas(msg, 2); - UPB_FIELD_AT(msg, google_protobuf_OneofOptions*, UPB_SIZE(12, 24)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(12, 24), google_protobuf_OneofOptions*) = value; } UPB_INLINE struct google_protobuf_OneofOptions* google_protobuf_OneofDescriptorProto_mutable_options(google_protobuf_OneofDescriptorProto *msg, upb_arena *arena) { struct google_protobuf_OneofOptions* sub = (struct google_protobuf_OneofOptions*)google_protobuf_OneofDescriptorProto_options(msg); if (sub == NULL) { - sub = (struct google_protobuf_OneofOptions*)upb_msg_new(&google_protobuf_OneofOptions_msginit, arena); + sub = (struct google_protobuf_OneofOptions*)_upb_msg_new(&google_protobuf_OneofOptions_msginit, arena); if (!sub) return NULL; google_protobuf_OneofDescriptorProto_set_options(msg, sub); } @@ -1933,7 +2212,7 @@ UPB_INLINE struct google_protobuf_OneofOptions* google_protobuf_OneofDescriptorP /* google.protobuf.EnumDescriptorProto */ UPB_INLINE google_protobuf_EnumDescriptorProto *google_protobuf_EnumDescriptorProto_new(upb_arena *arena) { - return (google_protobuf_EnumDescriptorProto *)upb_msg_new(&google_protobuf_EnumDescriptorProto_msginit, arena); + return (google_protobuf_EnumDescriptorProto *)_upb_msg_new(&google_protobuf_EnumDescriptorProto_msginit, arena); } UPB_INLINE google_protobuf_EnumDescriptorProto *google_protobuf_EnumDescriptorProto_parse(const char *buf, size_t size, upb_arena *arena) { @@ -1945,25 +2224,27 @@ UPB_INLINE char *google_protobuf_EnumDescriptorProto_serialize(const google_prot } UPB_INLINE bool google_protobuf_EnumDescriptorProto_has_name(const google_protobuf_EnumDescriptorProto *msg) { return _upb_has_field(msg, 1); } -UPB_INLINE upb_strview google_protobuf_EnumDescriptorProto_name(const google_protobuf_EnumDescriptorProto *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(4, 8)); } +UPB_INLINE upb_strview google_protobuf_EnumDescriptorProto_name(const google_protobuf_EnumDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview); } +UPB_INLINE bool google_protobuf_EnumDescriptorProto_has_value(const google_protobuf_EnumDescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(16, 32)); } UPB_INLINE const google_protobuf_EnumValueDescriptorProto* const* google_protobuf_EnumDescriptorProto_value(const google_protobuf_EnumDescriptorProto *msg, size_t *len) { return (const google_protobuf_EnumValueDescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(16, 32), len); } UPB_INLINE bool google_protobuf_EnumDescriptorProto_has_options(const google_protobuf_EnumDescriptorProto *msg) { return _upb_has_field(msg, 2); } -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(12, 24)); } +UPB_INLINE const google_protobuf_EnumOptions* google_protobuf_EnumDescriptorProto_options(const google_protobuf_EnumDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(12, 24), const google_protobuf_EnumOptions*); } +UPB_INLINE bool google_protobuf_EnumDescriptorProto_has_reserved_range(const google_protobuf_EnumDescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(20, 40)); } UPB_INLINE const google_protobuf_EnumDescriptorProto_EnumReservedRange* const* google_protobuf_EnumDescriptorProto_reserved_range(const google_protobuf_EnumDescriptorProto *msg, size_t *len) { return (const google_protobuf_EnumDescriptorProto_EnumReservedRange* const*)_upb_array_accessor(msg, UPB_SIZE(20, 40), len); } UPB_INLINE upb_strview const* google_protobuf_EnumDescriptorProto_reserved_name(const google_protobuf_EnumDescriptorProto *msg, size_t *len) { return (upb_strview const*)_upb_array_accessor(msg, UPB_SIZE(24, 48), len); } UPB_INLINE void google_protobuf_EnumDescriptorProto_set_name(google_protobuf_EnumDescriptorProto *msg, upb_strview value) { _upb_sethas(msg, 1); - UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(4, 8)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview) = value; } UPB_INLINE google_protobuf_EnumValueDescriptorProto** google_protobuf_EnumDescriptorProto_mutable_value(google_protobuf_EnumDescriptorProto *msg, size_t *len) { return (google_protobuf_EnumValueDescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(16, 32), len); } UPB_INLINE google_protobuf_EnumValueDescriptorProto** google_protobuf_EnumDescriptorProto_resize_value(google_protobuf_EnumDescriptorProto *msg, size_t len, upb_arena *arena) { - return (google_protobuf_EnumValueDescriptorProto**)_upb_array_resize_accessor(msg, UPB_SIZE(16, 32), len, UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, arena); + return (google_protobuf_EnumValueDescriptorProto**)_upb_array_resize_accessor(msg, UPB_SIZE(16, 32), len, UPB_TYPE_MESSAGE, arena); } UPB_INLINE struct google_protobuf_EnumValueDescriptorProto* google_protobuf_EnumDescriptorProto_add_value(google_protobuf_EnumDescriptorProto *msg, upb_arena *arena) { - struct google_protobuf_EnumValueDescriptorProto* sub = (struct google_protobuf_EnumValueDescriptorProto*)upb_msg_new(&google_protobuf_EnumValueDescriptorProto_msginit, arena); + struct google_protobuf_EnumValueDescriptorProto* sub = (struct google_protobuf_EnumValueDescriptorProto*)_upb_msg_new(&google_protobuf_EnumValueDescriptorProto_msginit, arena); bool ok = _upb_array_append_accessor( msg, UPB_SIZE(16, 32), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena); if (!ok) return NULL; @@ -1971,12 +2252,12 @@ UPB_INLINE struct google_protobuf_EnumValueDescriptorProto* google_protobuf_Enum } UPB_INLINE void google_protobuf_EnumDescriptorProto_set_options(google_protobuf_EnumDescriptorProto *msg, google_protobuf_EnumOptions* value) { _upb_sethas(msg, 2); - UPB_FIELD_AT(msg, google_protobuf_EnumOptions*, UPB_SIZE(12, 24)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(12, 24), google_protobuf_EnumOptions*) = value; } UPB_INLINE struct google_protobuf_EnumOptions* google_protobuf_EnumDescriptorProto_mutable_options(google_protobuf_EnumDescriptorProto *msg, upb_arena *arena) { struct google_protobuf_EnumOptions* sub = (struct google_protobuf_EnumOptions*)google_protobuf_EnumDescriptorProto_options(msg); if (sub == NULL) { - sub = (struct google_protobuf_EnumOptions*)upb_msg_new(&google_protobuf_EnumOptions_msginit, arena); + sub = (struct google_protobuf_EnumOptions*)_upb_msg_new(&google_protobuf_EnumOptions_msginit, arena); if (!sub) return NULL; google_protobuf_EnumDescriptorProto_set_options(msg, sub); } @@ -1986,10 +2267,10 @@ UPB_INLINE google_protobuf_EnumDescriptorProto_EnumReservedRange** google_protob return (google_protobuf_EnumDescriptorProto_EnumReservedRange**)_upb_array_mutable_accessor(msg, UPB_SIZE(20, 40), len); } UPB_INLINE google_protobuf_EnumDescriptorProto_EnumReservedRange** google_protobuf_EnumDescriptorProto_resize_reserved_range(google_protobuf_EnumDescriptorProto *msg, size_t len, upb_arena *arena) { - return (google_protobuf_EnumDescriptorProto_EnumReservedRange**)_upb_array_resize_accessor(msg, UPB_SIZE(20, 40), len, UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, arena); + return (google_protobuf_EnumDescriptorProto_EnumReservedRange**)_upb_array_resize_accessor(msg, UPB_SIZE(20, 40), len, UPB_TYPE_MESSAGE, arena); } UPB_INLINE struct google_protobuf_EnumDescriptorProto_EnumReservedRange* google_protobuf_EnumDescriptorProto_add_reserved_range(google_protobuf_EnumDescriptorProto *msg, upb_arena *arena) { - struct google_protobuf_EnumDescriptorProto_EnumReservedRange* sub = (struct google_protobuf_EnumDescriptorProto_EnumReservedRange*)upb_msg_new(&google_protobuf_EnumDescriptorProto_EnumReservedRange_msginit, arena); + struct google_protobuf_EnumDescriptorProto_EnumReservedRange* sub = (struct google_protobuf_EnumDescriptorProto_EnumReservedRange*)_upb_msg_new(&google_protobuf_EnumDescriptorProto_EnumReservedRange_msginit, arena); bool ok = _upb_array_append_accessor( msg, UPB_SIZE(20, 40), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena); if (!ok) return NULL; @@ -1999,17 +2280,17 @@ UPB_INLINE upb_strview* google_protobuf_EnumDescriptorProto_mutable_reserved_nam return (upb_strview*)_upb_array_mutable_accessor(msg, UPB_SIZE(24, 48), len); } UPB_INLINE upb_strview* google_protobuf_EnumDescriptorProto_resize_reserved_name(google_protobuf_EnumDescriptorProto *msg, size_t len, upb_arena *arena) { - return (upb_strview*)_upb_array_resize_accessor(msg, UPB_SIZE(24, 48), len, UPB_SIZE(8, 16), UPB_TYPE_STRING, arena); + return (upb_strview*)_upb_array_resize_accessor(msg, UPB_SIZE(24, 48), len, UPB_TYPE_STRING, arena); } UPB_INLINE bool google_protobuf_EnumDescriptorProto_add_reserved_name(google_protobuf_EnumDescriptorProto *msg, upb_strview val, upb_arena *arena) { - return _upb_array_append_accessor( - msg, UPB_SIZE(24, 48), UPB_SIZE(8, 16), UPB_TYPE_STRING, &val, arena); + return _upb_array_append_accessor(msg, UPB_SIZE(24, 48), UPB_SIZE(8, 16), UPB_TYPE_STRING, &val, + arena); } /* google.protobuf.EnumDescriptorProto.EnumReservedRange */ UPB_INLINE google_protobuf_EnumDescriptorProto_EnumReservedRange *google_protobuf_EnumDescriptorProto_EnumReservedRange_new(upb_arena *arena) { - return (google_protobuf_EnumDescriptorProto_EnumReservedRange *)upb_msg_new(&google_protobuf_EnumDescriptorProto_EnumReservedRange_msginit, arena); + return (google_protobuf_EnumDescriptorProto_EnumReservedRange *)_upb_msg_new(&google_protobuf_EnumDescriptorProto_EnumReservedRange_msginit, arena); } UPB_INLINE google_protobuf_EnumDescriptorProto_EnumReservedRange *google_protobuf_EnumDescriptorProto_EnumReservedRange_parse(const char *buf, size_t size, upb_arena *arena) { @@ -2021,23 +2302,23 @@ UPB_INLINE char *google_protobuf_EnumDescriptorProto_EnumReservedRange_serialize } UPB_INLINE bool google_protobuf_EnumDescriptorProto_EnumReservedRange_has_start(const google_protobuf_EnumDescriptorProto_EnumReservedRange *msg) { return _upb_has_field(msg, 1); } -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_start(const google_protobuf_EnumDescriptorProto_EnumReservedRange *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t); } UPB_INLINE bool google_protobuf_EnumDescriptorProto_EnumReservedRange_has_end(const google_protobuf_EnumDescriptorProto_EnumReservedRange *msg) { return _upb_has_field(msg, 2); } -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 int32_t google_protobuf_EnumDescriptorProto_EnumReservedRange_end(const google_protobuf_EnumDescriptorProto_EnumReservedRange *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t); } UPB_INLINE void google_protobuf_EnumDescriptorProto_EnumReservedRange_set_start(google_protobuf_EnumDescriptorProto_EnumReservedRange *msg, int32_t value) { _upb_sethas(msg, 1); - UPB_FIELD_AT(msg, int32_t, UPB_SIZE(4, 4)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t) = value; } UPB_INLINE void google_protobuf_EnumDescriptorProto_EnumReservedRange_set_end(google_protobuf_EnumDescriptorProto_EnumReservedRange *msg, int32_t value) { _upb_sethas(msg, 2); - UPB_FIELD_AT(msg, int32_t, UPB_SIZE(8, 8)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t) = value; } /* google.protobuf.EnumValueDescriptorProto */ UPB_INLINE google_protobuf_EnumValueDescriptorProto *google_protobuf_EnumValueDescriptorProto_new(upb_arena *arena) { - return (google_protobuf_EnumValueDescriptorProto *)upb_msg_new(&google_protobuf_EnumValueDescriptorProto_msginit, arena); + return (google_protobuf_EnumValueDescriptorProto *)_upb_msg_new(&google_protobuf_EnumValueDescriptorProto_msginit, arena); } UPB_INLINE google_protobuf_EnumValueDescriptorProto *google_protobuf_EnumValueDescriptorProto_parse(const char *buf, size_t size, upb_arena *arena) { @@ -2049,28 +2330,28 @@ UPB_INLINE char *google_protobuf_EnumValueDescriptorProto_serialize(const google } UPB_INLINE bool google_protobuf_EnumValueDescriptorProto_has_name(const google_protobuf_EnumValueDescriptorProto *msg) { return _upb_has_field(msg, 2); } -UPB_INLINE upb_strview google_protobuf_EnumValueDescriptorProto_name(const google_protobuf_EnumValueDescriptorProto *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(8, 8)); } +UPB_INLINE upb_strview google_protobuf_EnumValueDescriptorProto_name(const google_protobuf_EnumValueDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(8, 8), upb_strview); } UPB_INLINE bool google_protobuf_EnumValueDescriptorProto_has_number(const google_protobuf_EnumValueDescriptorProto *msg) { return _upb_has_field(msg, 1); } -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 int32_t google_protobuf_EnumValueDescriptorProto_number(const google_protobuf_EnumValueDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t); } UPB_INLINE bool google_protobuf_EnumValueDescriptorProto_has_options(const google_protobuf_EnumValueDescriptorProto *msg) { return _upb_has_field(msg, 3); } -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, 24)); } +UPB_INLINE const google_protobuf_EnumValueOptions* google_protobuf_EnumValueDescriptorProto_options(const google_protobuf_EnumValueDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(16, 24), const google_protobuf_EnumValueOptions*); } UPB_INLINE void google_protobuf_EnumValueDescriptorProto_set_name(google_protobuf_EnumValueDescriptorProto *msg, upb_strview value) { _upb_sethas(msg, 2); - UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(8, 8)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(8, 8), upb_strview) = value; } UPB_INLINE void google_protobuf_EnumValueDescriptorProto_set_number(google_protobuf_EnumValueDescriptorProto *msg, int32_t value) { _upb_sethas(msg, 1); - UPB_FIELD_AT(msg, int32_t, UPB_SIZE(4, 4)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t) = value; } UPB_INLINE void google_protobuf_EnumValueDescriptorProto_set_options(google_protobuf_EnumValueDescriptorProto *msg, google_protobuf_EnumValueOptions* value) { _upb_sethas(msg, 3); - UPB_FIELD_AT(msg, google_protobuf_EnumValueOptions*, UPB_SIZE(16, 24)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(16, 24), google_protobuf_EnumValueOptions*) = value; } UPB_INLINE struct google_protobuf_EnumValueOptions* google_protobuf_EnumValueDescriptorProto_mutable_options(google_protobuf_EnumValueDescriptorProto *msg, upb_arena *arena) { struct google_protobuf_EnumValueOptions* sub = (struct google_protobuf_EnumValueOptions*)google_protobuf_EnumValueDescriptorProto_options(msg); if (sub == NULL) { - sub = (struct google_protobuf_EnumValueOptions*)upb_msg_new(&google_protobuf_EnumValueOptions_msginit, arena); + sub = (struct google_protobuf_EnumValueOptions*)_upb_msg_new(&google_protobuf_EnumValueOptions_msginit, arena); if (!sub) return NULL; google_protobuf_EnumValueDescriptorProto_set_options(msg, sub); } @@ -2080,7 +2361,7 @@ UPB_INLINE struct google_protobuf_EnumValueOptions* google_protobuf_EnumValueDes /* google.protobuf.ServiceDescriptorProto */ UPB_INLINE google_protobuf_ServiceDescriptorProto *google_protobuf_ServiceDescriptorProto_new(upb_arena *arena) { - return (google_protobuf_ServiceDescriptorProto *)upb_msg_new(&google_protobuf_ServiceDescriptorProto_msginit, arena); + return (google_protobuf_ServiceDescriptorProto *)_upb_msg_new(&google_protobuf_ServiceDescriptorProto_msginit, arena); } UPB_INLINE google_protobuf_ServiceDescriptorProto *google_protobuf_ServiceDescriptorProto_parse(const char *buf, size_t size, upb_arena *arena) { @@ -2092,23 +2373,24 @@ UPB_INLINE char *google_protobuf_ServiceDescriptorProto_serialize(const google_p } UPB_INLINE bool google_protobuf_ServiceDescriptorProto_has_name(const google_protobuf_ServiceDescriptorProto *msg) { return _upb_has_field(msg, 1); } -UPB_INLINE upb_strview google_protobuf_ServiceDescriptorProto_name(const google_protobuf_ServiceDescriptorProto *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(4, 8)); } +UPB_INLINE upb_strview google_protobuf_ServiceDescriptorProto_name(const google_protobuf_ServiceDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview); } +UPB_INLINE bool google_protobuf_ServiceDescriptorProto_has_method(const google_protobuf_ServiceDescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(16, 32)); } UPB_INLINE const google_protobuf_MethodDescriptorProto* const* google_protobuf_ServiceDescriptorProto_method(const google_protobuf_ServiceDescriptorProto *msg, size_t *len) { return (const google_protobuf_MethodDescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(16, 32), len); } UPB_INLINE bool google_protobuf_ServiceDescriptorProto_has_options(const google_protobuf_ServiceDescriptorProto *msg) { return _upb_has_field(msg, 2); } -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(12, 24)); } +UPB_INLINE const google_protobuf_ServiceOptions* google_protobuf_ServiceDescriptorProto_options(const google_protobuf_ServiceDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(12, 24), const google_protobuf_ServiceOptions*); } UPB_INLINE void google_protobuf_ServiceDescriptorProto_set_name(google_protobuf_ServiceDescriptorProto *msg, upb_strview value) { _upb_sethas(msg, 1); - UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(4, 8)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview) = value; } UPB_INLINE google_protobuf_MethodDescriptorProto** google_protobuf_ServiceDescriptorProto_mutable_method(google_protobuf_ServiceDescriptorProto *msg, size_t *len) { return (google_protobuf_MethodDescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(16, 32), len); } UPB_INLINE google_protobuf_MethodDescriptorProto** google_protobuf_ServiceDescriptorProto_resize_method(google_protobuf_ServiceDescriptorProto *msg, size_t len, upb_arena *arena) { - return (google_protobuf_MethodDescriptorProto**)_upb_array_resize_accessor(msg, UPB_SIZE(16, 32), len, UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, arena); + return (google_protobuf_MethodDescriptorProto**)_upb_array_resize_accessor(msg, UPB_SIZE(16, 32), len, UPB_TYPE_MESSAGE, arena); } UPB_INLINE struct google_protobuf_MethodDescriptorProto* google_protobuf_ServiceDescriptorProto_add_method(google_protobuf_ServiceDescriptorProto *msg, upb_arena *arena) { - struct google_protobuf_MethodDescriptorProto* sub = (struct google_protobuf_MethodDescriptorProto*)upb_msg_new(&google_protobuf_MethodDescriptorProto_msginit, arena); + struct google_protobuf_MethodDescriptorProto* sub = (struct google_protobuf_MethodDescriptorProto*)_upb_msg_new(&google_protobuf_MethodDescriptorProto_msginit, arena); bool ok = _upb_array_append_accessor( msg, UPB_SIZE(16, 32), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena); if (!ok) return NULL; @@ -2116,12 +2398,12 @@ UPB_INLINE struct google_protobuf_MethodDescriptorProto* google_protobuf_Service } UPB_INLINE void google_protobuf_ServiceDescriptorProto_set_options(google_protobuf_ServiceDescriptorProto *msg, google_protobuf_ServiceOptions* value) { _upb_sethas(msg, 2); - UPB_FIELD_AT(msg, google_protobuf_ServiceOptions*, UPB_SIZE(12, 24)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(12, 24), google_protobuf_ServiceOptions*) = value; } UPB_INLINE struct google_protobuf_ServiceOptions* google_protobuf_ServiceDescriptorProto_mutable_options(google_protobuf_ServiceDescriptorProto *msg, upb_arena *arena) { struct google_protobuf_ServiceOptions* sub = (struct google_protobuf_ServiceOptions*)google_protobuf_ServiceDescriptorProto_options(msg); if (sub == NULL) { - sub = (struct google_protobuf_ServiceOptions*)upb_msg_new(&google_protobuf_ServiceOptions_msginit, arena); + sub = (struct google_protobuf_ServiceOptions*)_upb_msg_new(&google_protobuf_ServiceOptions_msginit, arena); if (!sub) return NULL; google_protobuf_ServiceDescriptorProto_set_options(msg, sub); } @@ -2131,7 +2413,7 @@ UPB_INLINE struct google_protobuf_ServiceOptions* google_protobuf_ServiceDescrip /* google.protobuf.MethodDescriptorProto */ UPB_INLINE google_protobuf_MethodDescriptorProto *google_protobuf_MethodDescriptorProto_new(upb_arena *arena) { - return (google_protobuf_MethodDescriptorProto *)upb_msg_new(&google_protobuf_MethodDescriptorProto_msginit, arena); + return (google_protobuf_MethodDescriptorProto *)_upb_msg_new(&google_protobuf_MethodDescriptorProto_msginit, arena); } UPB_INLINE google_protobuf_MethodDescriptorProto *google_protobuf_MethodDescriptorProto_parse(const char *buf, size_t size, upb_arena *arena) { @@ -2143,38 +2425,38 @@ UPB_INLINE char *google_protobuf_MethodDescriptorProto_serialize(const google_pr } UPB_INLINE bool google_protobuf_MethodDescriptorProto_has_name(const google_protobuf_MethodDescriptorProto *msg) { return _upb_has_field(msg, 3); } -UPB_INLINE upb_strview google_protobuf_MethodDescriptorProto_name(const google_protobuf_MethodDescriptorProto *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(4, 8)); } +UPB_INLINE upb_strview google_protobuf_MethodDescriptorProto_name(const google_protobuf_MethodDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview); } UPB_INLINE bool google_protobuf_MethodDescriptorProto_has_input_type(const google_protobuf_MethodDescriptorProto *msg) { return _upb_has_field(msg, 4); } -UPB_INLINE upb_strview google_protobuf_MethodDescriptorProto_input_type(const google_protobuf_MethodDescriptorProto *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(12, 24)); } +UPB_INLINE upb_strview google_protobuf_MethodDescriptorProto_input_type(const google_protobuf_MethodDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(12, 24), upb_strview); } UPB_INLINE bool google_protobuf_MethodDescriptorProto_has_output_type(const google_protobuf_MethodDescriptorProto *msg) { return _upb_has_field(msg, 5); } -UPB_INLINE upb_strview google_protobuf_MethodDescriptorProto_output_type(const google_protobuf_MethodDescriptorProto *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(20, 40)); } +UPB_INLINE upb_strview google_protobuf_MethodDescriptorProto_output_type(const google_protobuf_MethodDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(20, 40), upb_strview); } UPB_INLINE bool google_protobuf_MethodDescriptorProto_has_options(const google_protobuf_MethodDescriptorProto *msg) { return _upb_has_field(msg, 6); } -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(28, 56)); } +UPB_INLINE const google_protobuf_MethodOptions* google_protobuf_MethodDescriptorProto_options(const google_protobuf_MethodDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(28, 56), const google_protobuf_MethodOptions*); } UPB_INLINE bool google_protobuf_MethodDescriptorProto_has_client_streaming(const google_protobuf_MethodDescriptorProto *msg) { return _upb_has_field(msg, 1); } -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_client_streaming(const google_protobuf_MethodDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool); } UPB_INLINE bool google_protobuf_MethodDescriptorProto_has_server_streaming(const google_protobuf_MethodDescriptorProto *msg) { return _upb_has_field(msg, 2); } -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 bool google_protobuf_MethodDescriptorProto_server_streaming(const google_protobuf_MethodDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(2, 2), bool); } UPB_INLINE void google_protobuf_MethodDescriptorProto_set_name(google_protobuf_MethodDescriptorProto *msg, upb_strview value) { _upb_sethas(msg, 3); - UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(4, 8)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview) = value; } UPB_INLINE void google_protobuf_MethodDescriptorProto_set_input_type(google_protobuf_MethodDescriptorProto *msg, upb_strview value) { _upb_sethas(msg, 4); - UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(12, 24)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(12, 24), upb_strview) = value; } UPB_INLINE void google_protobuf_MethodDescriptorProto_set_output_type(google_protobuf_MethodDescriptorProto *msg, upb_strview value) { _upb_sethas(msg, 5); - UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(20, 40)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(20, 40), upb_strview) = value; } UPB_INLINE void google_protobuf_MethodDescriptorProto_set_options(google_protobuf_MethodDescriptorProto *msg, google_protobuf_MethodOptions* value) { _upb_sethas(msg, 6); - UPB_FIELD_AT(msg, google_protobuf_MethodOptions*, UPB_SIZE(28, 56)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(28, 56), google_protobuf_MethodOptions*) = value; } UPB_INLINE struct google_protobuf_MethodOptions* google_protobuf_MethodDescriptorProto_mutable_options(google_protobuf_MethodDescriptorProto *msg, upb_arena *arena) { struct google_protobuf_MethodOptions* sub = (struct google_protobuf_MethodOptions*)google_protobuf_MethodDescriptorProto_options(msg); if (sub == NULL) { - sub = (struct google_protobuf_MethodOptions*)upb_msg_new(&google_protobuf_MethodOptions_msginit, arena); + sub = (struct google_protobuf_MethodOptions*)_upb_msg_new(&google_protobuf_MethodOptions_msginit, arena); if (!sub) return NULL; google_protobuf_MethodDescriptorProto_set_options(msg, sub); } @@ -2182,17 +2464,17 @@ UPB_INLINE struct google_protobuf_MethodOptions* google_protobuf_MethodDescripto } UPB_INLINE void google_protobuf_MethodDescriptorProto_set_client_streaming(google_protobuf_MethodDescriptorProto *msg, bool value) { _upb_sethas(msg, 1); - UPB_FIELD_AT(msg, bool, UPB_SIZE(1, 1)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool) = value; } UPB_INLINE void google_protobuf_MethodDescriptorProto_set_server_streaming(google_protobuf_MethodDescriptorProto *msg, bool value) { _upb_sethas(msg, 2); - UPB_FIELD_AT(msg, bool, UPB_SIZE(2, 2)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(2, 2), bool) = value; } /* google.protobuf.FileOptions */ UPB_INLINE google_protobuf_FileOptions *google_protobuf_FileOptions_new(upb_arena *arena) { - return (google_protobuf_FileOptions *)upb_msg_new(&google_protobuf_FileOptions_msginit, arena); + return (google_protobuf_FileOptions *)_upb_msg_new(&google_protobuf_FileOptions_msginit, arena); } UPB_INLINE google_protobuf_FileOptions *google_protobuf_FileOptions_parse(const char *buf, size_t size, upb_arena *arena) { @@ -2204,135 +2486,136 @@ UPB_INLINE char *google_protobuf_FileOptions_serialize(const google_protobuf_Fil } UPB_INLINE bool google_protobuf_FileOptions_has_java_package(const google_protobuf_FileOptions *msg) { return _upb_has_field(msg, 11); } -UPB_INLINE upb_strview google_protobuf_FileOptions_java_package(const google_protobuf_FileOptions *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(28, 32)); } +UPB_INLINE upb_strview google_protobuf_FileOptions_java_package(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(28, 32), upb_strview); } UPB_INLINE bool google_protobuf_FileOptions_has_java_outer_classname(const google_protobuf_FileOptions *msg) { return _upb_has_field(msg, 12); } -UPB_INLINE upb_strview google_protobuf_FileOptions_java_outer_classname(const google_protobuf_FileOptions *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(36, 48)); } +UPB_INLINE upb_strview google_protobuf_FileOptions_java_outer_classname(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(36, 48), upb_strview); } UPB_INLINE bool google_protobuf_FileOptions_has_optimize_for(const google_protobuf_FileOptions *msg) { return _upb_has_field(msg, 1); } -UPB_INLINE int32_t google_protobuf_FileOptions_optimize_for(const google_protobuf_FileOptions *msg) { return UPB_FIELD_AT(msg, int32_t, UPB_SIZE(8, 8)); } +UPB_INLINE int32_t google_protobuf_FileOptions_optimize_for(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t); } UPB_INLINE bool google_protobuf_FileOptions_has_java_multiple_files(const google_protobuf_FileOptions *msg) { return _upb_has_field(msg, 2); } -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 bool google_protobuf_FileOptions_java_multiple_files(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(16, 16), bool); } UPB_INLINE bool google_protobuf_FileOptions_has_go_package(const google_protobuf_FileOptions *msg) { return _upb_has_field(msg, 13); } -UPB_INLINE upb_strview google_protobuf_FileOptions_go_package(const google_protobuf_FileOptions *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(44, 64)); } +UPB_INLINE upb_strview google_protobuf_FileOptions_go_package(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(44, 64), upb_strview); } UPB_INLINE bool google_protobuf_FileOptions_has_cc_generic_services(const google_protobuf_FileOptions *msg) { return _upb_has_field(msg, 3); } -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_cc_generic_services(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(17, 17), bool); } UPB_INLINE bool google_protobuf_FileOptions_has_java_generic_services(const google_protobuf_FileOptions *msg) { return _upb_has_field(msg, 4); } -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_java_generic_services(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(18, 18), bool); } UPB_INLINE bool google_protobuf_FileOptions_has_py_generic_services(const google_protobuf_FileOptions *msg) { return _upb_has_field(msg, 5); } -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_py_generic_services(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(19, 19), bool); } UPB_INLINE bool google_protobuf_FileOptions_has_java_generate_equals_and_hash(const google_protobuf_FileOptions *msg) { return _upb_has_field(msg, 6); } -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_java_generate_equals_and_hash(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(20, 20), bool); } UPB_INLINE bool google_protobuf_FileOptions_has_deprecated(const google_protobuf_FileOptions *msg) { return _upb_has_field(msg, 7); } -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_deprecated(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(21, 21), bool); } UPB_INLINE bool google_protobuf_FileOptions_has_java_string_check_utf8(const google_protobuf_FileOptions *msg) { return _upb_has_field(msg, 8); } -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_java_string_check_utf8(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(22, 22), bool); } UPB_INLINE bool google_protobuf_FileOptions_has_cc_enable_arenas(const google_protobuf_FileOptions *msg) { return _upb_has_field(msg, 9); } -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 bool google_protobuf_FileOptions_cc_enable_arenas(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(23, 23), bool); } UPB_INLINE bool google_protobuf_FileOptions_has_objc_class_prefix(const google_protobuf_FileOptions *msg) { return _upb_has_field(msg, 14); } -UPB_INLINE upb_strview google_protobuf_FileOptions_objc_class_prefix(const google_protobuf_FileOptions *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(52, 80)); } +UPB_INLINE upb_strview google_protobuf_FileOptions_objc_class_prefix(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(52, 80), upb_strview); } UPB_INLINE bool google_protobuf_FileOptions_has_csharp_namespace(const google_protobuf_FileOptions *msg) { return _upb_has_field(msg, 15); } -UPB_INLINE upb_strview google_protobuf_FileOptions_csharp_namespace(const google_protobuf_FileOptions *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(60, 96)); } +UPB_INLINE upb_strview google_protobuf_FileOptions_csharp_namespace(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(60, 96), upb_strview); } UPB_INLINE bool google_protobuf_FileOptions_has_swift_prefix(const google_protobuf_FileOptions *msg) { return _upb_has_field(msg, 16); } -UPB_INLINE upb_strview google_protobuf_FileOptions_swift_prefix(const google_protobuf_FileOptions *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(68, 112)); } +UPB_INLINE upb_strview google_protobuf_FileOptions_swift_prefix(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(68, 112), upb_strview); } UPB_INLINE bool google_protobuf_FileOptions_has_php_class_prefix(const google_protobuf_FileOptions *msg) { return _upb_has_field(msg, 17); } -UPB_INLINE upb_strview google_protobuf_FileOptions_php_class_prefix(const google_protobuf_FileOptions *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(76, 128)); } +UPB_INLINE upb_strview google_protobuf_FileOptions_php_class_prefix(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(76, 128), upb_strview); } UPB_INLINE bool google_protobuf_FileOptions_has_php_namespace(const google_protobuf_FileOptions *msg) { return _upb_has_field(msg, 18); } -UPB_INLINE upb_strview google_protobuf_FileOptions_php_namespace(const google_protobuf_FileOptions *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(84, 144)); } +UPB_INLINE upb_strview google_protobuf_FileOptions_php_namespace(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(84, 144), upb_strview); } UPB_INLINE bool google_protobuf_FileOptions_has_php_generic_services(const google_protobuf_FileOptions *msg) { return _upb_has_field(msg, 10); } -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 bool google_protobuf_FileOptions_php_generic_services(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(24, 24), bool); } UPB_INLINE bool google_protobuf_FileOptions_has_php_metadata_namespace(const google_protobuf_FileOptions *msg) { return _upb_has_field(msg, 19); } -UPB_INLINE upb_strview google_protobuf_FileOptions_php_metadata_namespace(const google_protobuf_FileOptions *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(92, 160)); } +UPB_INLINE upb_strview google_protobuf_FileOptions_php_metadata_namespace(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(92, 160), upb_strview); } UPB_INLINE bool google_protobuf_FileOptions_has_ruby_package(const google_protobuf_FileOptions *msg) { return _upb_has_field(msg, 20); } -UPB_INLINE upb_strview google_protobuf_FileOptions_ruby_package(const google_protobuf_FileOptions *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(100, 176)); } +UPB_INLINE upb_strview google_protobuf_FileOptions_ruby_package(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(100, 176), upb_strview); } +UPB_INLINE bool google_protobuf_FileOptions_has_uninterpreted_option(const google_protobuf_FileOptions *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(108, 192)); } UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_FileOptions_uninterpreted_option(const google_protobuf_FileOptions *msg, size_t *len) { return (const google_protobuf_UninterpretedOption* const*)_upb_array_accessor(msg, UPB_SIZE(108, 192), len); } UPB_INLINE void google_protobuf_FileOptions_set_java_package(google_protobuf_FileOptions *msg, upb_strview value) { _upb_sethas(msg, 11); - UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(28, 32)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(28, 32), upb_strview) = value; } UPB_INLINE void google_protobuf_FileOptions_set_java_outer_classname(google_protobuf_FileOptions *msg, upb_strview value) { _upb_sethas(msg, 12); - UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(36, 48)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(36, 48), upb_strview) = value; } UPB_INLINE void google_protobuf_FileOptions_set_optimize_for(google_protobuf_FileOptions *msg, int32_t value) { _upb_sethas(msg, 1); - UPB_FIELD_AT(msg, int32_t, UPB_SIZE(8, 8)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t) = value; } UPB_INLINE void google_protobuf_FileOptions_set_java_multiple_files(google_protobuf_FileOptions *msg, bool value) { _upb_sethas(msg, 2); - UPB_FIELD_AT(msg, bool, UPB_SIZE(16, 16)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(16, 16), bool) = value; } UPB_INLINE void google_protobuf_FileOptions_set_go_package(google_protobuf_FileOptions *msg, upb_strview value) { _upb_sethas(msg, 13); - UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(44, 64)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(44, 64), upb_strview) = value; } UPB_INLINE void google_protobuf_FileOptions_set_cc_generic_services(google_protobuf_FileOptions *msg, bool value) { _upb_sethas(msg, 3); - UPB_FIELD_AT(msg, bool, UPB_SIZE(17, 17)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(17, 17), bool) = value; } UPB_INLINE void google_protobuf_FileOptions_set_java_generic_services(google_protobuf_FileOptions *msg, bool value) { _upb_sethas(msg, 4); - UPB_FIELD_AT(msg, bool, UPB_SIZE(18, 18)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(18, 18), bool) = value; } UPB_INLINE void google_protobuf_FileOptions_set_py_generic_services(google_protobuf_FileOptions *msg, bool value) { _upb_sethas(msg, 5); - UPB_FIELD_AT(msg, bool, UPB_SIZE(19, 19)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(19, 19), bool) = value; } UPB_INLINE void google_protobuf_FileOptions_set_java_generate_equals_and_hash(google_protobuf_FileOptions *msg, bool value) { _upb_sethas(msg, 6); - UPB_FIELD_AT(msg, bool, UPB_SIZE(20, 20)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(20, 20), bool) = value; } UPB_INLINE void google_protobuf_FileOptions_set_deprecated(google_protobuf_FileOptions *msg, bool value) { _upb_sethas(msg, 7); - UPB_FIELD_AT(msg, bool, UPB_SIZE(21, 21)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(21, 21), bool) = value; } UPB_INLINE void google_protobuf_FileOptions_set_java_string_check_utf8(google_protobuf_FileOptions *msg, bool value) { _upb_sethas(msg, 8); - UPB_FIELD_AT(msg, bool, UPB_SIZE(22, 22)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(22, 22), bool) = value; } UPB_INLINE void google_protobuf_FileOptions_set_cc_enable_arenas(google_protobuf_FileOptions *msg, bool value) { _upb_sethas(msg, 9); - UPB_FIELD_AT(msg, bool, UPB_SIZE(23, 23)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(23, 23), bool) = value; } UPB_INLINE void google_protobuf_FileOptions_set_objc_class_prefix(google_protobuf_FileOptions *msg, upb_strview value) { _upb_sethas(msg, 14); - UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(52, 80)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(52, 80), upb_strview) = value; } UPB_INLINE void google_protobuf_FileOptions_set_csharp_namespace(google_protobuf_FileOptions *msg, upb_strview value) { _upb_sethas(msg, 15); - UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(60, 96)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(60, 96), upb_strview) = value; } UPB_INLINE void google_protobuf_FileOptions_set_swift_prefix(google_protobuf_FileOptions *msg, upb_strview value) { _upb_sethas(msg, 16); - UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(68, 112)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(68, 112), upb_strview) = value; } UPB_INLINE void google_protobuf_FileOptions_set_php_class_prefix(google_protobuf_FileOptions *msg, upb_strview value) { _upb_sethas(msg, 17); - UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(76, 128)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(76, 128), upb_strview) = value; } UPB_INLINE void google_protobuf_FileOptions_set_php_namespace(google_protobuf_FileOptions *msg, upb_strview value) { _upb_sethas(msg, 18); - UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(84, 144)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(84, 144), upb_strview) = value; } UPB_INLINE void google_protobuf_FileOptions_set_php_generic_services(google_protobuf_FileOptions *msg, bool value) { _upb_sethas(msg, 10); - UPB_FIELD_AT(msg, bool, UPB_SIZE(24, 24)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(24, 24), bool) = value; } UPB_INLINE void google_protobuf_FileOptions_set_php_metadata_namespace(google_protobuf_FileOptions *msg, upb_strview value) { _upb_sethas(msg, 19); - UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(92, 160)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(92, 160), upb_strview) = value; } UPB_INLINE void google_protobuf_FileOptions_set_ruby_package(google_protobuf_FileOptions *msg, upb_strview value) { _upb_sethas(msg, 20); - UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(100, 176)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(100, 176), upb_strview) = value; } UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_FileOptions_mutable_uninterpreted_option(google_protobuf_FileOptions *msg, size_t *len) { return (google_protobuf_UninterpretedOption**)_upb_array_mutable_accessor(msg, UPB_SIZE(108, 192), len); } UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_FileOptions_resize_uninterpreted_option(google_protobuf_FileOptions *msg, size_t len, upb_arena *arena) { - return (google_protobuf_UninterpretedOption**)_upb_array_resize_accessor(msg, UPB_SIZE(108, 192), len, UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, arena); + return (google_protobuf_UninterpretedOption**)_upb_array_resize_accessor(msg, UPB_SIZE(108, 192), len, UPB_TYPE_MESSAGE, arena); } UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_FileOptions_add_uninterpreted_option(google_protobuf_FileOptions *msg, upb_arena *arena) { - struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)upb_msg_new(&google_protobuf_UninterpretedOption_msginit, arena); + struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)_upb_msg_new(&google_protobuf_UninterpretedOption_msginit, arena); bool ok = _upb_array_append_accessor( msg, UPB_SIZE(108, 192), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena); if (!ok) return NULL; @@ -2342,7 +2625,7 @@ UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_FileOptio /* google.protobuf.MessageOptions */ UPB_INLINE google_protobuf_MessageOptions *google_protobuf_MessageOptions_new(upb_arena *arena) { - return (google_protobuf_MessageOptions *)upb_msg_new(&google_protobuf_MessageOptions_msginit, arena); + return (google_protobuf_MessageOptions *)_upb_msg_new(&google_protobuf_MessageOptions_msginit, arena); } UPB_INLINE google_protobuf_MessageOptions *google_protobuf_MessageOptions_parse(const char *buf, size_t size, upb_arena *arena) { @@ -2354,39 +2637,40 @@ UPB_INLINE char *google_protobuf_MessageOptions_serialize(const google_protobuf_ } UPB_INLINE bool google_protobuf_MessageOptions_has_message_set_wire_format(const google_protobuf_MessageOptions *msg) { return _upb_has_field(msg, 1); } -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_message_set_wire_format(const google_protobuf_MessageOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool); } UPB_INLINE bool google_protobuf_MessageOptions_has_no_standard_descriptor_accessor(const google_protobuf_MessageOptions *msg) { return _upb_has_field(msg, 2); } -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_no_standard_descriptor_accessor(const google_protobuf_MessageOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(2, 2), bool); } UPB_INLINE bool google_protobuf_MessageOptions_has_deprecated(const google_protobuf_MessageOptions *msg) { return _upb_has_field(msg, 3); } -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_deprecated(const google_protobuf_MessageOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(3, 3), bool); } UPB_INLINE bool google_protobuf_MessageOptions_has_map_entry(const google_protobuf_MessageOptions *msg) { return _upb_has_field(msg, 4); } -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 bool google_protobuf_MessageOptions_map_entry(const google_protobuf_MessageOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 4), bool); } +UPB_INLINE bool google_protobuf_MessageOptions_has_uninterpreted_option(const google_protobuf_MessageOptions *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(8, 8)); } UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_MessageOptions_uninterpreted_option(const google_protobuf_MessageOptions *msg, size_t *len) { return (const google_protobuf_UninterpretedOption* const*)_upb_array_accessor(msg, UPB_SIZE(8, 8), len); } UPB_INLINE void google_protobuf_MessageOptions_set_message_set_wire_format(google_protobuf_MessageOptions *msg, bool value) { _upb_sethas(msg, 1); - UPB_FIELD_AT(msg, bool, UPB_SIZE(1, 1)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool) = value; } UPB_INLINE void google_protobuf_MessageOptions_set_no_standard_descriptor_accessor(google_protobuf_MessageOptions *msg, bool value) { _upb_sethas(msg, 2); - UPB_FIELD_AT(msg, bool, UPB_SIZE(2, 2)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(2, 2), bool) = value; } UPB_INLINE void google_protobuf_MessageOptions_set_deprecated(google_protobuf_MessageOptions *msg, bool value) { _upb_sethas(msg, 3); - UPB_FIELD_AT(msg, bool, UPB_SIZE(3, 3)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(3, 3), bool) = value; } UPB_INLINE void google_protobuf_MessageOptions_set_map_entry(google_protobuf_MessageOptions *msg, bool value) { _upb_sethas(msg, 4); - UPB_FIELD_AT(msg, bool, UPB_SIZE(4, 4)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(4, 4), bool) = value; } UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_MessageOptions_mutable_uninterpreted_option(google_protobuf_MessageOptions *msg, size_t *len) { return (google_protobuf_UninterpretedOption**)_upb_array_mutable_accessor(msg, UPB_SIZE(8, 8), len); } UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_MessageOptions_resize_uninterpreted_option(google_protobuf_MessageOptions *msg, size_t len, upb_arena *arena) { - return (google_protobuf_UninterpretedOption**)_upb_array_resize_accessor(msg, UPB_SIZE(8, 8), len, UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, arena); + return (google_protobuf_UninterpretedOption**)_upb_array_resize_accessor(msg, UPB_SIZE(8, 8), len, UPB_TYPE_MESSAGE, arena); } UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_MessageOptions_add_uninterpreted_option(google_protobuf_MessageOptions *msg, upb_arena *arena) { - struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)upb_msg_new(&google_protobuf_UninterpretedOption_msginit, arena); + struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)_upb_msg_new(&google_protobuf_UninterpretedOption_msginit, arena); bool ok = _upb_array_append_accessor( msg, UPB_SIZE(8, 8), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena); if (!ok) return NULL; @@ -2396,7 +2680,7 @@ UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_MessageOp /* google.protobuf.FieldOptions */ UPB_INLINE google_protobuf_FieldOptions *google_protobuf_FieldOptions_new(upb_arena *arena) { - return (google_protobuf_FieldOptions *)upb_msg_new(&google_protobuf_FieldOptions_msginit, arena); + return (google_protobuf_FieldOptions *)_upb_msg_new(&google_protobuf_FieldOptions_msginit, arena); } UPB_INLINE google_protobuf_FieldOptions *google_protobuf_FieldOptions_parse(const char *buf, size_t size, upb_arena *arena) { @@ -2408,51 +2692,52 @@ UPB_INLINE char *google_protobuf_FieldOptions_serialize(const google_protobuf_Fi } UPB_INLINE bool google_protobuf_FieldOptions_has_ctype(const google_protobuf_FieldOptions *msg) { return _upb_has_field(msg, 1); } -UPB_INLINE int32_t google_protobuf_FieldOptions_ctype(const google_protobuf_FieldOptions *msg) { return UPB_FIELD_AT(msg, int32_t, UPB_SIZE(8, 8)); } +UPB_INLINE int32_t google_protobuf_FieldOptions_ctype(const google_protobuf_FieldOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t); } UPB_INLINE bool google_protobuf_FieldOptions_has_packed(const google_protobuf_FieldOptions *msg) { return _upb_has_field(msg, 3); } -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_packed(const google_protobuf_FieldOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(24, 24), bool); } UPB_INLINE bool google_protobuf_FieldOptions_has_deprecated(const google_protobuf_FieldOptions *msg) { return _upb_has_field(msg, 4); } -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_deprecated(const google_protobuf_FieldOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(25, 25), bool); } UPB_INLINE bool google_protobuf_FieldOptions_has_lazy(const google_protobuf_FieldOptions *msg) { return _upb_has_field(msg, 5); } -UPB_INLINE bool google_protobuf_FieldOptions_lazy(const google_protobuf_FieldOptions *msg) { return UPB_FIELD_AT(msg, bool, UPB_SIZE(26, 26)); } +UPB_INLINE bool google_protobuf_FieldOptions_lazy(const google_protobuf_FieldOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(26, 26), bool); } UPB_INLINE bool google_protobuf_FieldOptions_has_jstype(const google_protobuf_FieldOptions *msg) { return _upb_has_field(msg, 2); } -UPB_INLINE int32_t google_protobuf_FieldOptions_jstype(const google_protobuf_FieldOptions *msg) { return UPB_FIELD_AT(msg, int32_t, UPB_SIZE(16, 16)); } +UPB_INLINE int32_t google_protobuf_FieldOptions_jstype(const google_protobuf_FieldOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(16, 16), int32_t); } UPB_INLINE bool google_protobuf_FieldOptions_has_weak(const google_protobuf_FieldOptions *msg) { return _upb_has_field(msg, 6); } -UPB_INLINE bool google_protobuf_FieldOptions_weak(const google_protobuf_FieldOptions *msg) { return UPB_FIELD_AT(msg, bool, UPB_SIZE(27, 27)); } +UPB_INLINE bool google_protobuf_FieldOptions_weak(const google_protobuf_FieldOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(27, 27), bool); } +UPB_INLINE bool google_protobuf_FieldOptions_has_uninterpreted_option(const google_protobuf_FieldOptions *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(28, 32)); } UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_FieldOptions_uninterpreted_option(const google_protobuf_FieldOptions *msg, size_t *len) { return (const google_protobuf_UninterpretedOption* const*)_upb_array_accessor(msg, UPB_SIZE(28, 32), len); } UPB_INLINE void google_protobuf_FieldOptions_set_ctype(google_protobuf_FieldOptions *msg, int32_t value) { _upb_sethas(msg, 1); - UPB_FIELD_AT(msg, int32_t, UPB_SIZE(8, 8)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t) = value; } UPB_INLINE void google_protobuf_FieldOptions_set_packed(google_protobuf_FieldOptions *msg, bool value) { _upb_sethas(msg, 3); - UPB_FIELD_AT(msg, bool, UPB_SIZE(24, 24)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(24, 24), bool) = value; } UPB_INLINE void google_protobuf_FieldOptions_set_deprecated(google_protobuf_FieldOptions *msg, bool value) { _upb_sethas(msg, 4); - UPB_FIELD_AT(msg, bool, UPB_SIZE(25, 25)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(25, 25), bool) = value; } UPB_INLINE void google_protobuf_FieldOptions_set_lazy(google_protobuf_FieldOptions *msg, bool value) { _upb_sethas(msg, 5); - UPB_FIELD_AT(msg, bool, UPB_SIZE(26, 26)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(26, 26), bool) = value; } UPB_INLINE void google_protobuf_FieldOptions_set_jstype(google_protobuf_FieldOptions *msg, int32_t value) { _upb_sethas(msg, 2); - UPB_FIELD_AT(msg, int32_t, UPB_SIZE(16, 16)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(16, 16), int32_t) = value; } UPB_INLINE void google_protobuf_FieldOptions_set_weak(google_protobuf_FieldOptions *msg, bool value) { _upb_sethas(msg, 6); - UPB_FIELD_AT(msg, bool, UPB_SIZE(27, 27)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(27, 27), bool) = value; } UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_FieldOptions_mutable_uninterpreted_option(google_protobuf_FieldOptions *msg, size_t *len) { return (google_protobuf_UninterpretedOption**)_upb_array_mutable_accessor(msg, UPB_SIZE(28, 32), len); } UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_FieldOptions_resize_uninterpreted_option(google_protobuf_FieldOptions *msg, size_t len, upb_arena *arena) { - return (google_protobuf_UninterpretedOption**)_upb_array_resize_accessor(msg, UPB_SIZE(28, 32), len, UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, arena); + return (google_protobuf_UninterpretedOption**)_upb_array_resize_accessor(msg, UPB_SIZE(28, 32), len, UPB_TYPE_MESSAGE, arena); } UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_FieldOptions_add_uninterpreted_option(google_protobuf_FieldOptions *msg, upb_arena *arena) { - struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)upb_msg_new(&google_protobuf_UninterpretedOption_msginit, arena); + struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)_upb_msg_new(&google_protobuf_UninterpretedOption_msginit, arena); bool ok = _upb_array_append_accessor( msg, UPB_SIZE(28, 32), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena); if (!ok) return NULL; @@ -2462,7 +2747,7 @@ UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_FieldOpti /* google.protobuf.OneofOptions */ UPB_INLINE google_protobuf_OneofOptions *google_protobuf_OneofOptions_new(upb_arena *arena) { - return (google_protobuf_OneofOptions *)upb_msg_new(&google_protobuf_OneofOptions_msginit, arena); + return (google_protobuf_OneofOptions *)_upb_msg_new(&google_protobuf_OneofOptions_msginit, arena); } UPB_INLINE google_protobuf_OneofOptions *google_protobuf_OneofOptions_parse(const char *buf, size_t size, upb_arena *arena) { @@ -2473,16 +2758,17 @@ UPB_INLINE char *google_protobuf_OneofOptions_serialize(const google_protobuf_On return upb_encode(msg, &google_protobuf_OneofOptions_msginit, arena, len); } +UPB_INLINE bool google_protobuf_OneofOptions_has_uninterpreted_option(const google_protobuf_OneofOptions *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(0, 0)); } UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_OneofOptions_uninterpreted_option(const google_protobuf_OneofOptions *msg, size_t *len) { return (const google_protobuf_UninterpretedOption* const*)_upb_array_accessor(msg, UPB_SIZE(0, 0), len); } UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_OneofOptions_mutable_uninterpreted_option(google_protobuf_OneofOptions *msg, size_t *len) { return (google_protobuf_UninterpretedOption**)_upb_array_mutable_accessor(msg, UPB_SIZE(0, 0), len); } UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_OneofOptions_resize_uninterpreted_option(google_protobuf_OneofOptions *msg, size_t len, upb_arena *arena) { - return (google_protobuf_UninterpretedOption**)_upb_array_resize_accessor(msg, UPB_SIZE(0, 0), len, UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, arena); + return (google_protobuf_UninterpretedOption**)_upb_array_resize_accessor(msg, UPB_SIZE(0, 0), len, UPB_TYPE_MESSAGE, arena); } UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_OneofOptions_add_uninterpreted_option(google_protobuf_OneofOptions *msg, upb_arena *arena) { - struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)upb_msg_new(&google_protobuf_UninterpretedOption_msginit, arena); + struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)_upb_msg_new(&google_protobuf_UninterpretedOption_msginit, arena); bool ok = _upb_array_append_accessor( msg, UPB_SIZE(0, 0), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena); if (!ok) return NULL; @@ -2492,7 +2778,7 @@ UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_OneofOpti /* google.protobuf.EnumOptions */ UPB_INLINE google_protobuf_EnumOptions *google_protobuf_EnumOptions_new(upb_arena *arena) { - return (google_protobuf_EnumOptions *)upb_msg_new(&google_protobuf_EnumOptions_msginit, arena); + return (google_protobuf_EnumOptions *)_upb_msg_new(&google_protobuf_EnumOptions_msginit, arena); } UPB_INLINE google_protobuf_EnumOptions *google_protobuf_EnumOptions_parse(const char *buf, size_t size, upb_arena *arena) { @@ -2504,27 +2790,28 @@ UPB_INLINE char *google_protobuf_EnumOptions_serialize(const google_protobuf_Enu } UPB_INLINE bool google_protobuf_EnumOptions_has_allow_alias(const google_protobuf_EnumOptions *msg) { return _upb_has_field(msg, 1); } -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_allow_alias(const google_protobuf_EnumOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool); } UPB_INLINE bool google_protobuf_EnumOptions_has_deprecated(const google_protobuf_EnumOptions *msg) { return _upb_has_field(msg, 2); } -UPB_INLINE bool google_protobuf_EnumOptions_deprecated(const google_protobuf_EnumOptions *msg) { return UPB_FIELD_AT(msg, bool, UPB_SIZE(2, 2)); } +UPB_INLINE bool google_protobuf_EnumOptions_deprecated(const google_protobuf_EnumOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(2, 2), bool); } +UPB_INLINE bool google_protobuf_EnumOptions_has_uninterpreted_option(const google_protobuf_EnumOptions *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(4, 8)); } UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_EnumOptions_uninterpreted_option(const google_protobuf_EnumOptions *msg, size_t *len) { return (const google_protobuf_UninterpretedOption* const*)_upb_array_accessor(msg, UPB_SIZE(4, 8), len); } UPB_INLINE void google_protobuf_EnumOptions_set_allow_alias(google_protobuf_EnumOptions *msg, bool value) { _upb_sethas(msg, 1); - UPB_FIELD_AT(msg, bool, UPB_SIZE(1, 1)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool) = value; } UPB_INLINE void google_protobuf_EnumOptions_set_deprecated(google_protobuf_EnumOptions *msg, bool value) { _upb_sethas(msg, 2); - UPB_FIELD_AT(msg, bool, UPB_SIZE(2, 2)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(2, 2), bool) = value; } UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_EnumOptions_mutable_uninterpreted_option(google_protobuf_EnumOptions *msg, size_t *len) { return (google_protobuf_UninterpretedOption**)_upb_array_mutable_accessor(msg, UPB_SIZE(4, 8), len); } UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_EnumOptions_resize_uninterpreted_option(google_protobuf_EnumOptions *msg, size_t len, upb_arena *arena) { - return (google_protobuf_UninterpretedOption**)_upb_array_resize_accessor(msg, UPB_SIZE(4, 8), len, UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, arena); + return (google_protobuf_UninterpretedOption**)_upb_array_resize_accessor(msg, UPB_SIZE(4, 8), len, UPB_TYPE_MESSAGE, arena); } UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_EnumOptions_add_uninterpreted_option(google_protobuf_EnumOptions *msg, upb_arena *arena) { - struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)upb_msg_new(&google_protobuf_UninterpretedOption_msginit, arena); + struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)_upb_msg_new(&google_protobuf_UninterpretedOption_msginit, arena); bool ok = _upb_array_append_accessor( msg, UPB_SIZE(4, 8), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena); if (!ok) return NULL; @@ -2534,7 +2821,7 @@ UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_EnumOptio /* google.protobuf.EnumValueOptions */ UPB_INLINE google_protobuf_EnumValueOptions *google_protobuf_EnumValueOptions_new(upb_arena *arena) { - return (google_protobuf_EnumValueOptions *)upb_msg_new(&google_protobuf_EnumValueOptions_msginit, arena); + return (google_protobuf_EnumValueOptions *)_upb_msg_new(&google_protobuf_EnumValueOptions_msginit, arena); } UPB_INLINE google_protobuf_EnumValueOptions *google_protobuf_EnumValueOptions_parse(const char *buf, size_t size, upb_arena *arena) { @@ -2546,21 +2833,22 @@ UPB_INLINE char *google_protobuf_EnumValueOptions_serialize(const google_protobu } UPB_INLINE bool google_protobuf_EnumValueOptions_has_deprecated(const google_protobuf_EnumValueOptions *msg) { return _upb_has_field(msg, 1); } -UPB_INLINE bool google_protobuf_EnumValueOptions_deprecated(const google_protobuf_EnumValueOptions *msg) { return UPB_FIELD_AT(msg, bool, UPB_SIZE(1, 1)); } +UPB_INLINE bool google_protobuf_EnumValueOptions_deprecated(const google_protobuf_EnumValueOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool); } +UPB_INLINE bool google_protobuf_EnumValueOptions_has_uninterpreted_option(const google_protobuf_EnumValueOptions *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(4, 8)); } UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_EnumValueOptions_uninterpreted_option(const google_protobuf_EnumValueOptions *msg, size_t *len) { return (const google_protobuf_UninterpretedOption* const*)_upb_array_accessor(msg, UPB_SIZE(4, 8), len); } UPB_INLINE void google_protobuf_EnumValueOptions_set_deprecated(google_protobuf_EnumValueOptions *msg, bool value) { _upb_sethas(msg, 1); - UPB_FIELD_AT(msg, bool, UPB_SIZE(1, 1)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool) = value; } UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_EnumValueOptions_mutable_uninterpreted_option(google_protobuf_EnumValueOptions *msg, size_t *len) { return (google_protobuf_UninterpretedOption**)_upb_array_mutable_accessor(msg, UPB_SIZE(4, 8), len); } UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_EnumValueOptions_resize_uninterpreted_option(google_protobuf_EnumValueOptions *msg, size_t len, upb_arena *arena) { - return (google_protobuf_UninterpretedOption**)_upb_array_resize_accessor(msg, UPB_SIZE(4, 8), len, UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, arena); + return (google_protobuf_UninterpretedOption**)_upb_array_resize_accessor(msg, UPB_SIZE(4, 8), len, UPB_TYPE_MESSAGE, arena); } UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_EnumValueOptions_add_uninterpreted_option(google_protobuf_EnumValueOptions *msg, upb_arena *arena) { - struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)upb_msg_new(&google_protobuf_UninterpretedOption_msginit, arena); + struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)_upb_msg_new(&google_protobuf_UninterpretedOption_msginit, arena); bool ok = _upb_array_append_accessor( msg, UPB_SIZE(4, 8), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena); if (!ok) return NULL; @@ -2570,7 +2858,7 @@ UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_EnumValue /* google.protobuf.ServiceOptions */ UPB_INLINE google_protobuf_ServiceOptions *google_protobuf_ServiceOptions_new(upb_arena *arena) { - return (google_protobuf_ServiceOptions *)upb_msg_new(&google_protobuf_ServiceOptions_msginit, arena); + return (google_protobuf_ServiceOptions *)_upb_msg_new(&google_protobuf_ServiceOptions_msginit, arena); } UPB_INLINE google_protobuf_ServiceOptions *google_protobuf_ServiceOptions_parse(const char *buf, size_t size, upb_arena *arena) { @@ -2582,21 +2870,22 @@ UPB_INLINE char *google_protobuf_ServiceOptions_serialize(const google_protobuf_ } UPB_INLINE bool google_protobuf_ServiceOptions_has_deprecated(const google_protobuf_ServiceOptions *msg) { return _upb_has_field(msg, 1); } -UPB_INLINE bool google_protobuf_ServiceOptions_deprecated(const google_protobuf_ServiceOptions *msg) { return UPB_FIELD_AT(msg, bool, UPB_SIZE(1, 1)); } +UPB_INLINE bool google_protobuf_ServiceOptions_deprecated(const google_protobuf_ServiceOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool); } +UPB_INLINE bool google_protobuf_ServiceOptions_has_uninterpreted_option(const google_protobuf_ServiceOptions *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(4, 8)); } UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_ServiceOptions_uninterpreted_option(const google_protobuf_ServiceOptions *msg, size_t *len) { return (const google_protobuf_UninterpretedOption* const*)_upb_array_accessor(msg, UPB_SIZE(4, 8), len); } UPB_INLINE void google_protobuf_ServiceOptions_set_deprecated(google_protobuf_ServiceOptions *msg, bool value) { _upb_sethas(msg, 1); - UPB_FIELD_AT(msg, bool, UPB_SIZE(1, 1)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool) = value; } UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_ServiceOptions_mutable_uninterpreted_option(google_protobuf_ServiceOptions *msg, size_t *len) { return (google_protobuf_UninterpretedOption**)_upb_array_mutable_accessor(msg, UPB_SIZE(4, 8), len); } UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_ServiceOptions_resize_uninterpreted_option(google_protobuf_ServiceOptions *msg, size_t len, upb_arena *arena) { - return (google_protobuf_UninterpretedOption**)_upb_array_resize_accessor(msg, UPB_SIZE(4, 8), len, UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, arena); + return (google_protobuf_UninterpretedOption**)_upb_array_resize_accessor(msg, UPB_SIZE(4, 8), len, UPB_TYPE_MESSAGE, arena); } UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_ServiceOptions_add_uninterpreted_option(google_protobuf_ServiceOptions *msg, upb_arena *arena) { - struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)upb_msg_new(&google_protobuf_UninterpretedOption_msginit, arena); + struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)_upb_msg_new(&google_protobuf_UninterpretedOption_msginit, arena); bool ok = _upb_array_append_accessor( msg, UPB_SIZE(4, 8), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena); if (!ok) return NULL; @@ -2606,7 +2895,7 @@ UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_ServiceOp /* google.protobuf.MethodOptions */ UPB_INLINE google_protobuf_MethodOptions *google_protobuf_MethodOptions_new(upb_arena *arena) { - return (google_protobuf_MethodOptions *)upb_msg_new(&google_protobuf_MethodOptions_msginit, arena); + return (google_protobuf_MethodOptions *)_upb_msg_new(&google_protobuf_MethodOptions_msginit, arena); } UPB_INLINE google_protobuf_MethodOptions *google_protobuf_MethodOptions_parse(const char *buf, size_t size, upb_arena *arena) { @@ -2618,27 +2907,28 @@ UPB_INLINE char *google_protobuf_MethodOptions_serialize(const google_protobuf_M } UPB_INLINE bool google_protobuf_MethodOptions_has_deprecated(const google_protobuf_MethodOptions *msg) { return _upb_has_field(msg, 2); } -UPB_INLINE bool google_protobuf_MethodOptions_deprecated(const google_protobuf_MethodOptions *msg) { return UPB_FIELD_AT(msg, bool, UPB_SIZE(16, 16)); } +UPB_INLINE bool google_protobuf_MethodOptions_deprecated(const google_protobuf_MethodOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(16, 16), bool); } UPB_INLINE bool google_protobuf_MethodOptions_has_idempotency_level(const google_protobuf_MethodOptions *msg) { return _upb_has_field(msg, 1); } -UPB_INLINE int32_t google_protobuf_MethodOptions_idempotency_level(const google_protobuf_MethodOptions *msg) { return UPB_FIELD_AT(msg, int32_t, UPB_SIZE(8, 8)); } +UPB_INLINE int32_t google_protobuf_MethodOptions_idempotency_level(const google_protobuf_MethodOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t); } +UPB_INLINE bool google_protobuf_MethodOptions_has_uninterpreted_option(const google_protobuf_MethodOptions *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(20, 24)); } UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_MethodOptions_uninterpreted_option(const google_protobuf_MethodOptions *msg, size_t *len) { return (const google_protobuf_UninterpretedOption* const*)_upb_array_accessor(msg, UPB_SIZE(20, 24), len); } UPB_INLINE void google_protobuf_MethodOptions_set_deprecated(google_protobuf_MethodOptions *msg, bool value) { _upb_sethas(msg, 2); - UPB_FIELD_AT(msg, bool, UPB_SIZE(16, 16)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(16, 16), bool) = value; } UPB_INLINE void google_protobuf_MethodOptions_set_idempotency_level(google_protobuf_MethodOptions *msg, int32_t value) { _upb_sethas(msg, 1); - UPB_FIELD_AT(msg, int32_t, UPB_SIZE(8, 8)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t) = value; } UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_MethodOptions_mutable_uninterpreted_option(google_protobuf_MethodOptions *msg, size_t *len) { return (google_protobuf_UninterpretedOption**)_upb_array_mutable_accessor(msg, UPB_SIZE(20, 24), len); } UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_MethodOptions_resize_uninterpreted_option(google_protobuf_MethodOptions *msg, size_t len, upb_arena *arena) { - return (google_protobuf_UninterpretedOption**)_upb_array_resize_accessor(msg, UPB_SIZE(20, 24), len, UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, arena); + return (google_protobuf_UninterpretedOption**)_upb_array_resize_accessor(msg, UPB_SIZE(20, 24), len, UPB_TYPE_MESSAGE, arena); } UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_MethodOptions_add_uninterpreted_option(google_protobuf_MethodOptions *msg, upb_arena *arena) { - struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)upb_msg_new(&google_protobuf_UninterpretedOption_msginit, arena); + struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)_upb_msg_new(&google_protobuf_UninterpretedOption_msginit, arena); bool ok = _upb_array_append_accessor( msg, UPB_SIZE(20, 24), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena); if (!ok) return NULL; @@ -2648,7 +2938,7 @@ UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_MethodOpt /* google.protobuf.UninterpretedOption */ UPB_INLINE google_protobuf_UninterpretedOption *google_protobuf_UninterpretedOption_new(upb_arena *arena) { - return (google_protobuf_UninterpretedOption *)upb_msg_new(&google_protobuf_UninterpretedOption_msginit, arena); + return (google_protobuf_UninterpretedOption *)_upb_msg_new(&google_protobuf_UninterpretedOption_msginit, arena); } UPB_INLINE google_protobuf_UninterpretedOption *google_protobuf_UninterpretedOption_parse(const char *buf, size_t size, upb_arena *arena) { @@ -2659,28 +2949,29 @@ UPB_INLINE char *google_protobuf_UninterpretedOption_serialize(const google_prot return upb_encode(msg, &google_protobuf_UninterpretedOption_msginit, arena, len); } +UPB_INLINE bool google_protobuf_UninterpretedOption_has_name(const google_protobuf_UninterpretedOption *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(56, 80)); } UPB_INLINE const google_protobuf_UninterpretedOption_NamePart* const* google_protobuf_UninterpretedOption_name(const google_protobuf_UninterpretedOption *msg, size_t *len) { return (const google_protobuf_UninterpretedOption_NamePart* const*)_upb_array_accessor(msg, UPB_SIZE(56, 80), len); } UPB_INLINE bool google_protobuf_UninterpretedOption_has_identifier_value(const google_protobuf_UninterpretedOption *msg) { return _upb_has_field(msg, 4); } -UPB_INLINE upb_strview google_protobuf_UninterpretedOption_identifier_value(const google_protobuf_UninterpretedOption *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(32, 32)); } +UPB_INLINE upb_strview google_protobuf_UninterpretedOption_identifier_value(const google_protobuf_UninterpretedOption *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(32, 32), upb_strview); } UPB_INLINE bool google_protobuf_UninterpretedOption_has_positive_int_value(const google_protobuf_UninterpretedOption *msg) { return _upb_has_field(msg, 1); } -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 uint64_t google_protobuf_UninterpretedOption_positive_int_value(const google_protobuf_UninterpretedOption *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(8, 8), uint64_t); } UPB_INLINE bool google_protobuf_UninterpretedOption_has_negative_int_value(const google_protobuf_UninterpretedOption *msg) { return _upb_has_field(msg, 2); } -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 int64_t google_protobuf_UninterpretedOption_negative_int_value(const google_protobuf_UninterpretedOption *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(16, 16), int64_t); } UPB_INLINE bool google_protobuf_UninterpretedOption_has_double_value(const google_protobuf_UninterpretedOption *msg) { return _upb_has_field(msg, 3); } -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 double google_protobuf_UninterpretedOption_double_value(const google_protobuf_UninterpretedOption *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(24, 24), double); } UPB_INLINE bool google_protobuf_UninterpretedOption_has_string_value(const google_protobuf_UninterpretedOption *msg) { return _upb_has_field(msg, 5); } -UPB_INLINE upb_strview google_protobuf_UninterpretedOption_string_value(const google_protobuf_UninterpretedOption *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(40, 48)); } +UPB_INLINE upb_strview google_protobuf_UninterpretedOption_string_value(const google_protobuf_UninterpretedOption *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(40, 48), upb_strview); } UPB_INLINE bool google_protobuf_UninterpretedOption_has_aggregate_value(const google_protobuf_UninterpretedOption *msg) { return _upb_has_field(msg, 6); } -UPB_INLINE upb_strview google_protobuf_UninterpretedOption_aggregate_value(const google_protobuf_UninterpretedOption *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(48, 64)); } +UPB_INLINE upb_strview google_protobuf_UninterpretedOption_aggregate_value(const google_protobuf_UninterpretedOption *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(48, 64), upb_strview); } UPB_INLINE google_protobuf_UninterpretedOption_NamePart** google_protobuf_UninterpretedOption_mutable_name(google_protobuf_UninterpretedOption *msg, size_t *len) { return (google_protobuf_UninterpretedOption_NamePart**)_upb_array_mutable_accessor(msg, UPB_SIZE(56, 80), len); } UPB_INLINE google_protobuf_UninterpretedOption_NamePart** google_protobuf_UninterpretedOption_resize_name(google_protobuf_UninterpretedOption *msg, size_t len, upb_arena *arena) { - return (google_protobuf_UninterpretedOption_NamePart**)_upb_array_resize_accessor(msg, UPB_SIZE(56, 80), len, UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, arena); + return (google_protobuf_UninterpretedOption_NamePart**)_upb_array_resize_accessor(msg, UPB_SIZE(56, 80), len, UPB_TYPE_MESSAGE, arena); } UPB_INLINE struct google_protobuf_UninterpretedOption_NamePart* google_protobuf_UninterpretedOption_add_name(google_protobuf_UninterpretedOption *msg, upb_arena *arena) { - struct google_protobuf_UninterpretedOption_NamePart* sub = (struct google_protobuf_UninterpretedOption_NamePart*)upb_msg_new(&google_protobuf_UninterpretedOption_NamePart_msginit, arena); + struct google_protobuf_UninterpretedOption_NamePart* sub = (struct google_protobuf_UninterpretedOption_NamePart*)_upb_msg_new(&google_protobuf_UninterpretedOption_NamePart_msginit, arena); bool ok = _upb_array_append_accessor( msg, UPB_SIZE(56, 80), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena); if (!ok) return NULL; @@ -2688,33 +2979,33 @@ UPB_INLINE struct google_protobuf_UninterpretedOption_NamePart* google_protobuf_ } UPB_INLINE void google_protobuf_UninterpretedOption_set_identifier_value(google_protobuf_UninterpretedOption *msg, upb_strview value) { _upb_sethas(msg, 4); - UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(32, 32)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(32, 32), upb_strview) = value; } UPB_INLINE void google_protobuf_UninterpretedOption_set_positive_int_value(google_protobuf_UninterpretedOption *msg, uint64_t value) { _upb_sethas(msg, 1); - UPB_FIELD_AT(msg, uint64_t, UPB_SIZE(8, 8)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(8, 8), uint64_t) = value; } UPB_INLINE void google_protobuf_UninterpretedOption_set_negative_int_value(google_protobuf_UninterpretedOption *msg, int64_t value) { _upb_sethas(msg, 2); - UPB_FIELD_AT(msg, int64_t, UPB_SIZE(16, 16)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(16, 16), int64_t) = value; } UPB_INLINE void google_protobuf_UninterpretedOption_set_double_value(google_protobuf_UninterpretedOption *msg, double value) { _upb_sethas(msg, 3); - UPB_FIELD_AT(msg, double, UPB_SIZE(24, 24)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(24, 24), double) = value; } UPB_INLINE void google_protobuf_UninterpretedOption_set_string_value(google_protobuf_UninterpretedOption *msg, upb_strview value) { _upb_sethas(msg, 5); - UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(40, 48)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(40, 48), upb_strview) = value; } UPB_INLINE void google_protobuf_UninterpretedOption_set_aggregate_value(google_protobuf_UninterpretedOption *msg, upb_strview value) { _upb_sethas(msg, 6); - UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(48, 64)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(48, 64), upb_strview) = value; } /* google.protobuf.UninterpretedOption.NamePart */ UPB_INLINE google_protobuf_UninterpretedOption_NamePart *google_protobuf_UninterpretedOption_NamePart_new(upb_arena *arena) { - return (google_protobuf_UninterpretedOption_NamePart *)upb_msg_new(&google_protobuf_UninterpretedOption_NamePart_msginit, arena); + return (google_protobuf_UninterpretedOption_NamePart *)_upb_msg_new(&google_protobuf_UninterpretedOption_NamePart_msginit, arena); } UPB_INLINE google_protobuf_UninterpretedOption_NamePart *google_protobuf_UninterpretedOption_NamePart_parse(const char *buf, size_t size, upb_arena *arena) { @@ -2726,23 +3017,23 @@ UPB_INLINE char *google_protobuf_UninterpretedOption_NamePart_serialize(const go } UPB_INLINE bool google_protobuf_UninterpretedOption_NamePart_has_name_part(const google_protobuf_UninterpretedOption_NamePart *msg) { return _upb_has_field(msg, 2); } -UPB_INLINE upb_strview google_protobuf_UninterpretedOption_NamePart_name_part(const google_protobuf_UninterpretedOption_NamePart *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(4, 8)); } +UPB_INLINE upb_strview google_protobuf_UninterpretedOption_NamePart_name_part(const google_protobuf_UninterpretedOption_NamePart *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview); } UPB_INLINE bool google_protobuf_UninterpretedOption_NamePart_has_is_extension(const google_protobuf_UninterpretedOption_NamePart *msg) { return _upb_has_field(msg, 1); } -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 bool google_protobuf_UninterpretedOption_NamePart_is_extension(const google_protobuf_UninterpretedOption_NamePart *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool); } UPB_INLINE void google_protobuf_UninterpretedOption_NamePart_set_name_part(google_protobuf_UninterpretedOption_NamePart *msg, upb_strview value) { _upb_sethas(msg, 2); - UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(4, 8)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview) = value; } UPB_INLINE void google_protobuf_UninterpretedOption_NamePart_set_is_extension(google_protobuf_UninterpretedOption_NamePart *msg, bool value) { _upb_sethas(msg, 1); - UPB_FIELD_AT(msg, bool, UPB_SIZE(1, 1)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool) = value; } /* google.protobuf.SourceCodeInfo */ UPB_INLINE google_protobuf_SourceCodeInfo *google_protobuf_SourceCodeInfo_new(upb_arena *arena) { - return (google_protobuf_SourceCodeInfo *)upb_msg_new(&google_protobuf_SourceCodeInfo_msginit, arena); + return (google_protobuf_SourceCodeInfo *)_upb_msg_new(&google_protobuf_SourceCodeInfo_msginit, arena); } UPB_INLINE google_protobuf_SourceCodeInfo *google_protobuf_SourceCodeInfo_parse(const char *buf, size_t size, upb_arena *arena) { @@ -2753,16 +3044,17 @@ UPB_INLINE char *google_protobuf_SourceCodeInfo_serialize(const google_protobuf_ return upb_encode(msg, &google_protobuf_SourceCodeInfo_msginit, arena, len); } +UPB_INLINE bool google_protobuf_SourceCodeInfo_has_location(const google_protobuf_SourceCodeInfo *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(0, 0)); } UPB_INLINE const google_protobuf_SourceCodeInfo_Location* const* google_protobuf_SourceCodeInfo_location(const google_protobuf_SourceCodeInfo *msg, size_t *len) { return (const google_protobuf_SourceCodeInfo_Location* const*)_upb_array_accessor(msg, UPB_SIZE(0, 0), len); } UPB_INLINE google_protobuf_SourceCodeInfo_Location** google_protobuf_SourceCodeInfo_mutable_location(google_protobuf_SourceCodeInfo *msg, size_t *len) { return (google_protobuf_SourceCodeInfo_Location**)_upb_array_mutable_accessor(msg, UPB_SIZE(0, 0), len); } UPB_INLINE google_protobuf_SourceCodeInfo_Location** google_protobuf_SourceCodeInfo_resize_location(google_protobuf_SourceCodeInfo *msg, size_t len, upb_arena *arena) { - return (google_protobuf_SourceCodeInfo_Location**)_upb_array_resize_accessor(msg, UPB_SIZE(0, 0), len, UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, arena); + return (google_protobuf_SourceCodeInfo_Location**)_upb_array_resize_accessor(msg, UPB_SIZE(0, 0), len, UPB_TYPE_MESSAGE, arena); } UPB_INLINE struct google_protobuf_SourceCodeInfo_Location* google_protobuf_SourceCodeInfo_add_location(google_protobuf_SourceCodeInfo *msg, upb_arena *arena) { - struct google_protobuf_SourceCodeInfo_Location* sub = (struct google_protobuf_SourceCodeInfo_Location*)upb_msg_new(&google_protobuf_SourceCodeInfo_Location_msginit, arena); + struct google_protobuf_SourceCodeInfo_Location* sub = (struct google_protobuf_SourceCodeInfo_Location*)_upb_msg_new(&google_protobuf_SourceCodeInfo_Location_msginit, arena); bool ok = _upb_array_append_accessor( msg, UPB_SIZE(0, 0), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena); if (!ok) return NULL; @@ -2772,7 +3064,7 @@ UPB_INLINE struct google_protobuf_SourceCodeInfo_Location* google_protobuf_Sourc /* google.protobuf.SourceCodeInfo.Location */ UPB_INLINE google_protobuf_SourceCodeInfo_Location *google_protobuf_SourceCodeInfo_Location_new(upb_arena *arena) { - return (google_protobuf_SourceCodeInfo_Location *)upb_msg_new(&google_protobuf_SourceCodeInfo_Location_msginit, arena); + return (google_protobuf_SourceCodeInfo_Location *)_upb_msg_new(&google_protobuf_SourceCodeInfo_Location_msginit, arena); } UPB_INLINE google_protobuf_SourceCodeInfo_Location *google_protobuf_SourceCodeInfo_Location_parse(const char *buf, size_t size, upb_arena *arena) { @@ -2786,54 +3078,54 @@ UPB_INLINE char *google_protobuf_SourceCodeInfo_Location_serialize(const google_ UPB_INLINE int32_t const* google_protobuf_SourceCodeInfo_Location_path(const google_protobuf_SourceCodeInfo_Location *msg, size_t *len) { return (int32_t const*)_upb_array_accessor(msg, UPB_SIZE(20, 40), len); } UPB_INLINE int32_t const* google_protobuf_SourceCodeInfo_Location_span(const google_protobuf_SourceCodeInfo_Location *msg, size_t *len) { return (int32_t const*)_upb_array_accessor(msg, UPB_SIZE(24, 48), len); } UPB_INLINE bool google_protobuf_SourceCodeInfo_Location_has_leading_comments(const google_protobuf_SourceCodeInfo_Location *msg) { return _upb_has_field(msg, 1); } -UPB_INLINE upb_strview google_protobuf_SourceCodeInfo_Location_leading_comments(const google_protobuf_SourceCodeInfo_Location *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(4, 8)); } +UPB_INLINE upb_strview google_protobuf_SourceCodeInfo_Location_leading_comments(const google_protobuf_SourceCodeInfo_Location *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview); } UPB_INLINE bool google_protobuf_SourceCodeInfo_Location_has_trailing_comments(const google_protobuf_SourceCodeInfo_Location *msg) { return _upb_has_field(msg, 2); } -UPB_INLINE upb_strview google_protobuf_SourceCodeInfo_Location_trailing_comments(const google_protobuf_SourceCodeInfo_Location *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(12, 24)); } +UPB_INLINE upb_strview google_protobuf_SourceCodeInfo_Location_trailing_comments(const google_protobuf_SourceCodeInfo_Location *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(12, 24), upb_strview); } UPB_INLINE upb_strview const* google_protobuf_SourceCodeInfo_Location_leading_detached_comments(const google_protobuf_SourceCodeInfo_Location *msg, size_t *len) { return (upb_strview const*)_upb_array_accessor(msg, UPB_SIZE(28, 56), len); } UPB_INLINE int32_t* google_protobuf_SourceCodeInfo_Location_mutable_path(google_protobuf_SourceCodeInfo_Location *msg, size_t *len) { return (int32_t*)_upb_array_mutable_accessor(msg, UPB_SIZE(20, 40), len); } UPB_INLINE int32_t* google_protobuf_SourceCodeInfo_Location_resize_path(google_protobuf_SourceCodeInfo_Location *msg, size_t len, upb_arena *arena) { - return (int32_t*)_upb_array_resize_accessor(msg, UPB_SIZE(20, 40), len, UPB_SIZE(4, 4), UPB_TYPE_INT32, arena); + return (int32_t*)_upb_array_resize_accessor(msg, UPB_SIZE(20, 40), len, UPB_TYPE_INT32, arena); } UPB_INLINE bool google_protobuf_SourceCodeInfo_Location_add_path(google_protobuf_SourceCodeInfo_Location *msg, int32_t val, upb_arena *arena) { - return _upb_array_append_accessor( - msg, UPB_SIZE(20, 40), UPB_SIZE(4, 4), UPB_TYPE_INT32, &val, arena); + return _upb_array_append_accessor(msg, UPB_SIZE(20, 40), UPB_SIZE(4, 4), UPB_TYPE_INT32, &val, + arena); } UPB_INLINE int32_t* google_protobuf_SourceCodeInfo_Location_mutable_span(google_protobuf_SourceCodeInfo_Location *msg, size_t *len) { return (int32_t*)_upb_array_mutable_accessor(msg, UPB_SIZE(24, 48), len); } UPB_INLINE int32_t* google_protobuf_SourceCodeInfo_Location_resize_span(google_protobuf_SourceCodeInfo_Location *msg, size_t len, upb_arena *arena) { - return (int32_t*)_upb_array_resize_accessor(msg, UPB_SIZE(24, 48), len, UPB_SIZE(4, 4), UPB_TYPE_INT32, arena); + return (int32_t*)_upb_array_resize_accessor(msg, UPB_SIZE(24, 48), len, UPB_TYPE_INT32, arena); } UPB_INLINE bool google_protobuf_SourceCodeInfo_Location_add_span(google_protobuf_SourceCodeInfo_Location *msg, int32_t val, upb_arena *arena) { - return _upb_array_append_accessor( - msg, UPB_SIZE(24, 48), UPB_SIZE(4, 4), UPB_TYPE_INT32, &val, arena); + return _upb_array_append_accessor(msg, UPB_SIZE(24, 48), UPB_SIZE(4, 4), UPB_TYPE_INT32, &val, + arena); } UPB_INLINE void google_protobuf_SourceCodeInfo_Location_set_leading_comments(google_protobuf_SourceCodeInfo_Location *msg, upb_strview value) { _upb_sethas(msg, 1); - UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(4, 8)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview) = value; } UPB_INLINE void google_protobuf_SourceCodeInfo_Location_set_trailing_comments(google_protobuf_SourceCodeInfo_Location *msg, upb_strview value) { _upb_sethas(msg, 2); - UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(12, 24)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(12, 24), upb_strview) = value; } UPB_INLINE upb_strview* google_protobuf_SourceCodeInfo_Location_mutable_leading_detached_comments(google_protobuf_SourceCodeInfo_Location *msg, size_t *len) { return (upb_strview*)_upb_array_mutable_accessor(msg, UPB_SIZE(28, 56), len); } UPB_INLINE upb_strview* google_protobuf_SourceCodeInfo_Location_resize_leading_detached_comments(google_protobuf_SourceCodeInfo_Location *msg, size_t len, upb_arena *arena) { - return (upb_strview*)_upb_array_resize_accessor(msg, UPB_SIZE(28, 56), len, UPB_SIZE(8, 16), UPB_TYPE_STRING, arena); + return (upb_strview*)_upb_array_resize_accessor(msg, UPB_SIZE(28, 56), len, UPB_TYPE_STRING, arena); } UPB_INLINE bool google_protobuf_SourceCodeInfo_Location_add_leading_detached_comments(google_protobuf_SourceCodeInfo_Location *msg, upb_strview val, upb_arena *arena) { - return _upb_array_append_accessor( - msg, UPB_SIZE(28, 56), UPB_SIZE(8, 16), UPB_TYPE_STRING, &val, arena); + return _upb_array_append_accessor(msg, UPB_SIZE(28, 56), UPB_SIZE(8, 16), UPB_TYPE_STRING, &val, + arena); } /* google.protobuf.GeneratedCodeInfo */ UPB_INLINE google_protobuf_GeneratedCodeInfo *google_protobuf_GeneratedCodeInfo_new(upb_arena *arena) { - return (google_protobuf_GeneratedCodeInfo *)upb_msg_new(&google_protobuf_GeneratedCodeInfo_msginit, arena); + return (google_protobuf_GeneratedCodeInfo *)_upb_msg_new(&google_protobuf_GeneratedCodeInfo_msginit, arena); } UPB_INLINE google_protobuf_GeneratedCodeInfo *google_protobuf_GeneratedCodeInfo_parse(const char *buf, size_t size, upb_arena *arena) { @@ -2844,16 +3136,17 @@ UPB_INLINE char *google_protobuf_GeneratedCodeInfo_serialize(const google_protob return upb_encode(msg, &google_protobuf_GeneratedCodeInfo_msginit, arena, len); } +UPB_INLINE bool google_protobuf_GeneratedCodeInfo_has_annotation(const google_protobuf_GeneratedCodeInfo *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(0, 0)); } UPB_INLINE const google_protobuf_GeneratedCodeInfo_Annotation* const* google_protobuf_GeneratedCodeInfo_annotation(const google_protobuf_GeneratedCodeInfo *msg, size_t *len) { return (const google_protobuf_GeneratedCodeInfo_Annotation* const*)_upb_array_accessor(msg, UPB_SIZE(0, 0), len); } UPB_INLINE google_protobuf_GeneratedCodeInfo_Annotation** google_protobuf_GeneratedCodeInfo_mutable_annotation(google_protobuf_GeneratedCodeInfo *msg, size_t *len) { return (google_protobuf_GeneratedCodeInfo_Annotation**)_upb_array_mutable_accessor(msg, UPB_SIZE(0, 0), len); } UPB_INLINE google_protobuf_GeneratedCodeInfo_Annotation** google_protobuf_GeneratedCodeInfo_resize_annotation(google_protobuf_GeneratedCodeInfo *msg, size_t len, upb_arena *arena) { - return (google_protobuf_GeneratedCodeInfo_Annotation**)_upb_array_resize_accessor(msg, UPB_SIZE(0, 0), len, UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, arena); + return (google_protobuf_GeneratedCodeInfo_Annotation**)_upb_array_resize_accessor(msg, UPB_SIZE(0, 0), len, UPB_TYPE_MESSAGE, arena); } UPB_INLINE struct google_protobuf_GeneratedCodeInfo_Annotation* google_protobuf_GeneratedCodeInfo_add_annotation(google_protobuf_GeneratedCodeInfo *msg, upb_arena *arena) { - struct google_protobuf_GeneratedCodeInfo_Annotation* sub = (struct google_protobuf_GeneratedCodeInfo_Annotation*)upb_msg_new(&google_protobuf_GeneratedCodeInfo_Annotation_msginit, arena); + struct google_protobuf_GeneratedCodeInfo_Annotation* sub = (struct google_protobuf_GeneratedCodeInfo_Annotation*)_upb_msg_new(&google_protobuf_GeneratedCodeInfo_Annotation_msginit, arena); bool ok = _upb_array_append_accessor( msg, UPB_SIZE(0, 0), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena); if (!ok) return NULL; @@ -2863,7 +3156,7 @@ UPB_INLINE struct google_protobuf_GeneratedCodeInfo_Annotation* google_protobuf_ /* google.protobuf.GeneratedCodeInfo.Annotation */ UPB_INLINE google_protobuf_GeneratedCodeInfo_Annotation *google_protobuf_GeneratedCodeInfo_Annotation_new(upb_arena *arena) { - return (google_protobuf_GeneratedCodeInfo_Annotation *)upb_msg_new(&google_protobuf_GeneratedCodeInfo_Annotation_msginit, arena); + return (google_protobuf_GeneratedCodeInfo_Annotation *)_upb_msg_new(&google_protobuf_GeneratedCodeInfo_Annotation_msginit, arena); } UPB_INLINE google_protobuf_GeneratedCodeInfo_Annotation *google_protobuf_GeneratedCodeInfo_Annotation_parse(const char *buf, size_t size, upb_arena *arena) { @@ -2876,33 +3169,33 @@ UPB_INLINE char *google_protobuf_GeneratedCodeInfo_Annotation_serialize(const go UPB_INLINE int32_t const* google_protobuf_GeneratedCodeInfo_Annotation_path(const google_protobuf_GeneratedCodeInfo_Annotation *msg, size_t *len) { return (int32_t const*)_upb_array_accessor(msg, UPB_SIZE(20, 32), len); } UPB_INLINE bool google_protobuf_GeneratedCodeInfo_Annotation_has_source_file(const google_protobuf_GeneratedCodeInfo_Annotation *msg) { return _upb_has_field(msg, 3); } -UPB_INLINE upb_strview google_protobuf_GeneratedCodeInfo_Annotation_source_file(const google_protobuf_GeneratedCodeInfo_Annotation *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(12, 16)); } +UPB_INLINE upb_strview google_protobuf_GeneratedCodeInfo_Annotation_source_file(const google_protobuf_GeneratedCodeInfo_Annotation *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(12, 16), upb_strview); } UPB_INLINE bool google_protobuf_GeneratedCodeInfo_Annotation_has_begin(const google_protobuf_GeneratedCodeInfo_Annotation *msg) { return _upb_has_field(msg, 1); } -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_begin(const google_protobuf_GeneratedCodeInfo_Annotation *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t); } UPB_INLINE bool google_protobuf_GeneratedCodeInfo_Annotation_has_end(const google_protobuf_GeneratedCodeInfo_Annotation *msg) { return _upb_has_field(msg, 2); } -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 int32_t google_protobuf_GeneratedCodeInfo_Annotation_end(const google_protobuf_GeneratedCodeInfo_Annotation *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t); } UPB_INLINE int32_t* google_protobuf_GeneratedCodeInfo_Annotation_mutable_path(google_protobuf_GeneratedCodeInfo_Annotation *msg, size_t *len) { return (int32_t*)_upb_array_mutable_accessor(msg, UPB_SIZE(20, 32), len); } UPB_INLINE int32_t* google_protobuf_GeneratedCodeInfo_Annotation_resize_path(google_protobuf_GeneratedCodeInfo_Annotation *msg, size_t len, upb_arena *arena) { - return (int32_t*)_upb_array_resize_accessor(msg, UPB_SIZE(20, 32), len, UPB_SIZE(4, 4), UPB_TYPE_INT32, arena); + return (int32_t*)_upb_array_resize_accessor(msg, UPB_SIZE(20, 32), len, UPB_TYPE_INT32, arena); } UPB_INLINE bool google_protobuf_GeneratedCodeInfo_Annotation_add_path(google_protobuf_GeneratedCodeInfo_Annotation *msg, int32_t val, upb_arena *arena) { - return _upb_array_append_accessor( - msg, UPB_SIZE(20, 32), UPB_SIZE(4, 4), UPB_TYPE_INT32, &val, arena); + return _upb_array_append_accessor(msg, UPB_SIZE(20, 32), UPB_SIZE(4, 4), UPB_TYPE_INT32, &val, + arena); } UPB_INLINE void google_protobuf_GeneratedCodeInfo_Annotation_set_source_file(google_protobuf_GeneratedCodeInfo_Annotation *msg, upb_strview value) { _upb_sethas(msg, 3); - UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(12, 16)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(12, 16), upb_strview) = value; } UPB_INLINE void google_protobuf_GeneratedCodeInfo_Annotation_set_begin(google_protobuf_GeneratedCodeInfo_Annotation *msg, int32_t value) { _upb_sethas(msg, 1); - UPB_FIELD_AT(msg, int32_t, UPB_SIZE(4, 4)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t) = value; } UPB_INLINE void google_protobuf_GeneratedCodeInfo_Annotation_set_end(google_protobuf_GeneratedCodeInfo_Annotation *msg, int32_t value) { _upb_sethas(msg, 2); - UPB_FIELD_AT(msg, int32_t, UPB_SIZE(8, 8)) = value; + *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t) = value; } #ifdef __cplusplus @@ -3008,10 +3301,10 @@ upb_descriptortype_t upb_fielddef_descriptortype(const upb_fielddef *f); upb_label_t upb_fielddef_label(const upb_fielddef *f); uint32_t upb_fielddef_number(const upb_fielddef *f); const char *upb_fielddef_name(const upb_fielddef *f); +const char *upb_fielddef_jsonname(const upb_fielddef *f); bool upb_fielddef_isextension(const upb_fielddef *f); bool upb_fielddef_lazy(const upb_fielddef *f); bool upb_fielddef_packed(const upb_fielddef *f); -size_t upb_fielddef_getjsonname(const upb_fielddef *f, char *buf, size_t len); const upb_msgdef *upb_fielddef_containingtype(const upb_fielddef *f); const upb_oneofdef *upb_fielddef_containingoneof(const upb_fielddef *f); uint32_t upb_fielddef_index(const upb_fielddef *f); @@ -3032,6 +3325,7 @@ bool upb_fielddef_hassubdef(const upb_fielddef *f); bool upb_fielddef_haspresence(const upb_fielddef *f); const upb_msgdef *upb_fielddef_msgsubdef(const upb_fielddef *f); const upb_enumdef *upb_fielddef_enumsubdef(const upb_fielddef *f); +const upb_msglayout_field *upb_fielddef_layout(const upb_fielddef *f); /* Internal only. */ uint32_t upb_fielddef_selectorbase(const upb_fielddef *f); @@ -3059,32 +3353,10 @@ class upb::FieldDefPtr { Type type() const { return upb_fielddef_type(ptr_); } Label label() const { return upb_fielddef_label(ptr_); } const char* name() const { return upb_fielddef_name(ptr_); } + const char* json_name() const { return upb_fielddef_jsonname(ptr_); } uint32_t number() const { return upb_fielddef_number(ptr_); } bool is_extension() const { return upb_fielddef_isextension(ptr_); } - /* Copies the JSON name for this field into the given buffer. Returns the - * actual size of the JSON name, including the NULL terminator. If the - * return value is 0, the JSON name is unset. If the return value is - * greater than len, the JSON name was truncated. The buffer is always - * NULL-terminated if len > 0. - * - * The JSON name always defaults to a camelCased version of the regular - * name. However if the regular name is unset, the JSON name will be unset - * also. - */ - size_t GetJsonName(char *buf, size_t len) const { - return upb_fielddef_getjsonname(ptr_, buf, len); - } - - /* Convenience version of the above function which copies the JSON name - * into the given string, returning false if the name is not set. */ - template - bool GetJsonName(T* str) { - str->resize(GetJsonName(NULL, 0)); - GetJsonName(&(*str)[0], str->size()); - return str->size() > 0; - } - /* For UPB_TYPE_MESSAGE fields only where is_tag_delimited() == false, * indicates whether this field should have lazy parsing handlers that yield * the unparsed string for the submessage. @@ -3181,6 +3453,7 @@ const char *upb_oneofdef_name(const upb_oneofdef *o); const upb_msgdef *upb_oneofdef_containingtype(const upb_oneofdef *o); int upb_oneofdef_numfields(const upb_oneofdef *o); uint32_t upb_oneofdef_index(const upb_oneofdef *o); +bool upb_oneofdef_synthetic(const upb_oneofdef *o); /* Oneof lookups: * - ntof: look up a field by name. @@ -3334,6 +3607,8 @@ const upb_oneofdef *upb_msgdef_ntoo(const upb_msgdef *m, const char *name, size_t len); int upb_msgdef_numfields(const upb_msgdef *m); int upb_msgdef_numoneofs(const upb_msgdef *m); +const upb_msglayout *upb_msgdef_layout(const upb_msgdef *m); +const upb_fielddef *_upb_msgdef_field(const upb_msgdef *m, int i); UPB_INLINE const upb_oneofdef *upb_msgdef_ntooz(const upb_msgdef *m, const char *name) { @@ -3361,6 +3636,10 @@ UPB_INLINE bool upb_msgdef_lookupnamez(const upb_msgdef *m, const char *name, return upb_msgdef_lookupname(m, name, strlen(name), f, o); } +/* Returns a field by either JSON name or regular proto name. */ +const upb_fielddef *upb_msgdef_lookupjsonname(const upb_msgdef *m, + const char *name, size_t len); + /* Iteration over fields and oneofs. For example: * * upb_msg_field_iter i; @@ -3760,9 +4039,10 @@ const upb_filedef *upb_symtab_addfile( /* For generated code only: loads a generated descriptor. */ typedef struct upb_def_init { - struct upb_def_init **deps; + struct upb_def_init **deps; /* Dependencies of this file. */ + const upb_msglayout **layouts; /* Pre-order layouts of all messages. */ const char *filename; - upb_strview descriptor; + upb_strview descriptor; /* Serialized descriptor. */ } upb_def_init; bool _upb_symtab_loaddefinit(upb_symtab *s, const upb_def_init *init); @@ -3816,51 +4096,156 @@ UPB_INLINE const char* upb_safecstr(const std::string& str) { #endif /* UPB_DEF_H_ */ +#ifndef UPB_REFLECTION_H_ +#define UPB_REFLECTION_H_ -#ifndef UPB_MSGFACTORY_H_ -#define UPB_MSGFACTORY_H_ -/** upb_msgfactory ************************************************************/ -struct upb_msgfactory; -typedef struct upb_msgfactory upb_msgfactory; +typedef union { + bool bool_val; + float float_val; + double double_val; + int32_t int32_val; + int64_t int64_val; + uint32_t uint32_val; + uint64_t uint64_val; + const upb_map* map_val; + const upb_msg* msg_val; + const upb_array* array_val; + upb_strview str_val; +} upb_msgval; -#ifdef __cplusplus -extern "C" { -#endif +typedef union { + upb_map* map; + upb_msg* msg; + upb_array* array; +} upb_mutmsgval; + +/** upb_msg *******************************************************************/ + +/* Creates a new message of the given type in the given arena. */ +upb_msg *upb_msg_new(const upb_msgdef *m, upb_arena *a); + +/* Returns the value associated with this field. */ +upb_msgval upb_msg_get(const upb_msg *msg, const upb_fielddef *f); + +/* Returns a mutable pointer to a map, array, or submessage value. If the given + * arena is non-NULL this will construct a new object if it was not previously + * present. May not be called for primitive fields. */ +upb_mutmsgval upb_msg_mutable(upb_msg *msg, const upb_fielddef *f, upb_arena *a); + +/* May only be called for fields where upb_fielddef_haspresence(f) == true. */ +bool upb_msg_has(const upb_msg *msg, const upb_fielddef *f); + +/* Returns whether any field is set in the oneof. */ +bool upb_msg_hasoneof(const upb_msg *msg, const upb_oneofdef *o); + +/* Sets the given field to the given value. For a msg/array/map/string, the + * value must be in the same arena. */ +void upb_msg_set(upb_msg *msg, const upb_fielddef *f, upb_msgval val, + upb_arena *a); + +/* Clears any field presence and sets the value back to its default. */ +void upb_msg_clearfield(upb_msg *msg, const upb_fielddef *f); -/* 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. +/* Iterate over present fields. * - * These caches are all populated by upb_msgdef, and lazily created on demand. + * size_t iter = UPB_MSG_BEGIN; + * const upb_fielddef *f; + * upb_msgval val; + * while (upb_msg_next(msg, m, ext_pool, &f, &val, &iter)) { + * process_field(f, val); + * } + * + * If ext_pool is NULL, no extensions will be returned. If the given symtab + * returns extensions that don't match what is in this message, those extensions + * will be skipped. */ -/* 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); +#define UPB_MSG_BEGIN -1 +bool upb_msg_next(const upb_msg *msg, const upb_msgdef *m, + const upb_symtab *ext_pool, const upb_fielddef **f, + upb_msgval *val, size_t *iter); + +/* Adds unknown data (serialized protobuf data) to the given message. The data + * is copied into the message instance. */ +void upb_msg_addunknown(upb_msg *msg, const char *data, size_t len, + upb_arena *arena); + +/* Returns a reference to the message's unknown data. */ +const char *upb_msg_getunknown(const upb_msg *msg, size_t *len); -const upb_symtab *upb_msgfactory_symtab(const upb_msgfactory *f); +/** upb_array *****************************************************************/ -/* 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). +/* Creates a new array on the given arena that holds elements of this type. */ +upb_array *upb_array_new(upb_arena *a, upb_fieldtype_t type); + +/* Returns the size of the array. */ +size_t upb_array_size(const upb_array *arr); + +/* Returns the given element, which must be within the array's current size. */ +upb_msgval upb_array_get(const upb_array *arr, size_t i); + +/* Sets the given element, which must be within the array's current size. */ +void upb_array_set(upb_array *arr, size_t i, upb_msgval val); + +/* Appends an element to the array. Returns false on allocation failure. */ +bool upb_array_append(upb_array *array, upb_msgval val, upb_arena *arena); + +/* Changes the size of a vector. New elements are initialized to empty/0. + * Returns false on allocation failure. */ +bool upb_array_resize(upb_array *array, size_t size, upb_arena *arena); + +/** upb_map *******************************************************************/ + +/* Creates a new map on the given arena with the given key/value size. */ +upb_map *upb_map_new(upb_arena *a, upb_fieldtype_t key_type, + upb_fieldtype_t value_type); + +/* Returns the number of entries in the map. */ +size_t upb_map_size(const upb_map *map); + +/* Stores a value for the given key into |*val| (or the zero value if the key is + * not present). Returns whether the key was present. The |val| pointer may be + * NULL, in which case the function tests whether the given key is present. */ +bool upb_map_get(const upb_map *map, upb_msgval key, upb_msgval *val); + +/* Removes all entries in the map. */ +void upb_map_clear(upb_map *map); + +/* Sets the given key to the given value. Returns true if this was a new key in + * the map, or false if an existing key was replaced. */ +bool upb_map_set(upb_map *map, upb_msgval key, upb_msgval val, + upb_arena *arena); + +/* Deletes this key from the table. Returns true if the key was present. */ +bool upb_map_delete(upb_map *map, upb_msgval key); + +/* Map iteration: * - * The returned objects will live for as long as the msgfactory does. + * size_t iter = UPB_MAP_BEGIN; + * while (upb_mapiter_next(map, &iter)) { + * upb_msgval key = upb_mapiter_key(map, iter); + * upb_msgval val = upb_mapiter_value(map, iter); * - * 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); + * // If mutating is desired. + * upb_mapiter_setvalue(map, iter, value2); + * } + */ + +/* Advances to the next entry. Returns false if no more entries are present. */ +bool upb_mapiter_next(const upb_map *map, size_t *iter); + +/* Returns the key and value for this entry of the map. */ +upb_msgval upb_mapiter_key(const upb_map *map, size_t iter); +upb_msgval upb_mapiter_value(const upb_map *map, size_t iter); + +/* Sets the value for this entry. The iterator must not be done, and the + * iterator must not have been initialized const. */ +void upb_mapiter_setvalue(upb_map *map, size_t iter, upb_msgval value); -#ifdef __cplusplus -} /* extern "C" */ -#endif -#endif /* UPB_MSGFACTORY_H_ */ +#endif /* UPB_REFLECTION_H_ */ /* ** upb::Handlers (upb_handlers) ** @@ -5693,15 +6078,16 @@ UPB_INLINE bool upb_sink_startsubmsg(upb_sink s, upb_selector_t sel, return sub->closure ? true : false; } -UPB_INLINE bool upb_sink_endsubmsg(upb_sink s, upb_selector_t sel) { +UPB_INLINE bool upb_sink_endsubmsg(upb_sink s, upb_sink sub, + upb_selector_t sel) { typedef upb_endfield_handlerfunc func; func *endsubmsg; const void *hd; if (!s.handlers) return true; endsubmsg = (func*)upb_handlers_gethandler(s.handlers, sel, &hd); - if (!endsubmsg) return s.closure; - return endsubmsg(s.closure, hd); + if (!endsubmsg) return true; + return endsubmsg(sub.closure, hd); } #ifdef __cplusplus @@ -5867,8 +6253,8 @@ class upb::Sink { return ret; } - bool EndSubMessage(HandlersPtr::Selector s) { - return upb_sink_endsubmsg(sink_, s); + bool EndSubMessage(HandlersPtr::Selector s, Sink sub) { + return upb_sink_endsubmsg(sink_, sub.sink_, s); } /* For repeated fields of any type, the sequence of values must be wrapped in @@ -6368,7 +6754,7 @@ typedef struct { typedef struct { /* Space optimization note: we store two pointers here that the JIT * doesn't need at all; the upb_handlers* inside the sink and - * the dispatch table pointer. We can optimize so that the JIT uses + * the dispatch table pointer. We can optimze so that the JIT uses * smaller stack frames than the interpreter. The only thing we need * to guarantee is that the fallback routines can find end_ofs. */ upb_sink sink; @@ -6445,7 +6831,7 @@ struct upb_pbdecoder { char residual[UPB_DECODER_MAX_RESIDUAL_BYTES]; char *residual_end; - /* Bytes of data that should be discarded from the input before we start + /* Bytes of data that should be discarded from the input beore we start * parsing again. We set this when we internally determine that we can * safely skip the next N bytes, but this region extends past the current * user buffer. */ @@ -6567,21 +6953,22 @@ extern "C" { * descriptor type (upb_descriptortype_t). */ extern const uint8_t upb_pb_native_wire_types[]; -UPB_INLINE uint64_t byteswap64(uint64_t val) -{ - return ((((val) & 0xff00000000000000ull) >> 56) - | (((val) & 0x00ff000000000000ull) >> 40) - | (((val) & 0x0000ff0000000000ull) >> 24) - | (((val) & 0x000000ff00000000ull) >> 8) - | (((val) & 0x00000000ff000000ull) << 8) - | (((val) & 0x0000000000ff0000ull) << 24) - | (((val) & 0x000000000000ff00ull) << 40) - | (((val) & 0x00000000000000ffull) << 56)); +UPB_INLINE uint64_t byteswap64(uint64_t val) { + uint64_t byte = 0xff; + return (val & (byte << 56) >> 56) + | (val & (byte << 48) >> 40) + | (val & (byte << 40) >> 24) + | (val & (byte << 32) >> 8) + | (val & (byte << 24) << 8) + | (val & (byte << 16) << 24) + | (val & (byte << 8) << 40) + | (val & (byte << 0) << 56); } /* Zig-zag encoding/decoding **************************************************/ -UPB_INLINE int32_t upb_zzdec_32(uint32_t n) { +UPB_INLINE int32_t upb_zzdec_32(uint64_t _n) { + uint32_t n = (uint32_t)_n; return (n >> 1) ^ -(int32_t)(n & 1); } UPB_INLINE int64_t upb_zzdec_64(uint64_t n) { @@ -7064,8 +7451,9 @@ class upb::json::PrinterPtr { #endif /* UPB_JSON_TYPED_PRINTER_H_ */ /* See port_def.inc. This should #undef all macros #defined there. */ +#undef UPB_MAPTYPE_STRING #undef UPB_SIZE -#undef UPB_FIELD_AT +#undef UPB_PTR_AT #undef UPB_READ_ONEOF #undef UPB_WRITE_ONEOF #undef UPB_INLINE @@ -7075,6 +7463,7 @@ class upb::json::PrinterPtr { #undef UPB_MAX #undef UPB_MIN #undef UPB_UNUSED +#undef UPB_ASSUME #undef UPB_ASSERT #undef UPB_ASSERT_DEBUGVAR #undef UPB_UNREACHABLE diff --git a/ruby/tests/common_tests.rb b/ruby/tests/common_tests.rb index 7414aea8ae..67781467a1 100644 --- a/ruby/tests/common_tests.rb +++ b/ruby/tests/common_tests.rb @@ -1723,7 +1723,7 @@ module CommonTests m.duration = Rational(3, 2) assert_equal Google::Protobuf::Duration.new(seconds: 1, nanos: 500_000_000), m.duration - m.duration = BigDecimal.new("5") + m.duration = BigDecimal("5") assert_equal Google::Protobuf::Duration.new(seconds: 5, nanos: 0), m.duration m = proto_module::TimeMessage.new(duration: 1.1) From 24dda9e233dfdf7786e39bfb21035f2d61e8ab34 Mon Sep 17 00:00:00 2001 From: Thomas Van Lenten Date: Tue, 14 Apr 2020 11:23:09 -0400 Subject: [PATCH 06/38] Update the build/test script for newer Xcode 11 versions Apple stopped really supporting the 32bit simulators, so don't try running those any more. --- objectivec/DevTools/full_mac_build.sh | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/objectivec/DevTools/full_mac_build.sh b/objectivec/DevTools/full_mac_build.sh index 5584b0ae44..84ed8e9914 100755 --- a/objectivec/DevTools/full_mac_build.sh +++ b/objectivec/DevTools/full_mac_build.sh @@ -290,12 +290,9 @@ if [[ "${DO_XCODE_IOS_TESTS}" == "yes" ]] ; then ) ;; 11.*) + # Dropped 32bit as Apple doesn't seem support the simulators either. XCODEBUILD_TEST_BASE_IOS+=( - -destination "platform=iOS Simulator,name=iPhone 4s,OS=8.1" # 32bit -destination "platform=iOS Simulator,name=iPhone 8,OS=latest" # 64bit - # 10.x also seems to often fail running destinations in parallel (with - # 32bit one include atleast) - -disable-concurrent-destination-testing ) ;; * ) From 6f3bda22f40984eeacc2ce4602b9918dccb0fd09 Mon Sep 17 00:00:00 2001 From: Thomas Van Lenten Date: Mon, 13 Apr 2020 17:50:35 -0400 Subject: [PATCH 07/38] [ObjC] Fix some tests checking the wrong Message class. --- objectivec/Tests/GPBMessageTests+Runtime.m | 12 ++++++------ objectivec/Tests/GPBSwiftTests.swift | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/objectivec/Tests/GPBMessageTests+Runtime.m b/objectivec/Tests/GPBMessageTests+Runtime.m index 190ff514d2..aa5b0dbe75 100644 --- a/objectivec/Tests/GPBMessageTests+Runtime.m +++ b/objectivec/Tests/GPBMessageTests+Runtime.m @@ -252,7 +252,7 @@ // build the selector, i.e. - repeatedInt32Array_Count SEL countSel = NSSelectorFromString( [NSString stringWithFormat:@"repeated%@Array_Count", name]); - XCTAssertTrue([Message2 instancesRespondToSelector:countSel], @"field: %@", + XCTAssertTrue([Message3 instancesRespondToSelector:countSel], @"field: %@", name); } @@ -264,9 +264,9 @@ NSSelectorFromString([NSString stringWithFormat:@"hasOneof%@", name]); SEL setHasSel = NSSelectorFromString( [NSString stringWithFormat:@"setHasOneof%@:", name]); - XCTAssertFalse([Message2 instancesRespondToSelector:hasSel], @"field: %@", + XCTAssertFalse([Message3 instancesRespondToSelector:hasSel], @"field: %@", name); - XCTAssertFalse([Message2 instancesRespondToSelector:setHasSel], + XCTAssertFalse([Message3 instancesRespondToSelector:setHasSel], @"field: %@", name); } @@ -302,14 +302,14 @@ [NSString stringWithFormat:@"hasMap%@", name]); SEL setHasSel = NSSelectorFromString( [NSString stringWithFormat:@"setHasMap%@:", name]); - XCTAssertFalse([Message2 instancesRespondToSelector:hasSel], @"field: %@", + XCTAssertFalse([Message3 instancesRespondToSelector:hasSel], @"field: %@", name); - XCTAssertFalse([Message2 instancesRespondToSelector:setHasSel], + XCTAssertFalse([Message3 instancesRespondToSelector:setHasSel], @"field: %@", name); // build the selector, i.e. - mapInt32Int32Count SEL countSel = NSSelectorFromString( [NSString stringWithFormat:@"map%@_Count", name]); - XCTAssertTrue([Message2 instancesRespondToSelector:countSel], @"field: %@", + XCTAssertTrue([Message3 instancesRespondToSelector:countSel], @"field: %@", name); } } diff --git a/objectivec/Tests/GPBSwiftTests.swift b/objectivec/Tests/GPBSwiftTests.swift index cedf0e487e..03d7510680 100644 --- a/objectivec/Tests/GPBSwiftTests.swift +++ b/objectivec/Tests/GPBSwiftTests.swift @@ -355,7 +355,7 @@ class GPBBridgeTests: XCTestCase { msg.oneof = nil XCTAssertEqual(msg.oneof.optionalInt32, Int32(0)) // Default XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase.gpbUnsetOneOfCase) -} + } func testProto3OneOfSupport() { let msg = Message3() From 62832897c3cf14c93b91c412f7e64086cd272cb7 Mon Sep 17 00:00:00 2001 From: Elliotte Rusty Harold Date: Tue, 14 Apr 2020 11:50:01 -0400 Subject: [PATCH 08/38] deps: update Guava to 29.0 @rafi-kamal --- java/pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/java/pom.xml b/java/pom.xml index 2889f90117..d1928ec4f5 100644 --- a/java/pom.xml +++ b/java/pom.xml @@ -93,12 +93,12 @@ com.google.guava guava - 28.2-android + 29.0-android com.google.guava guava-testlib - 28.2-android + 29.0-android test From 95282469eb522d635b644fc136330f27ef627275 Mon Sep 17 00:00:00 2001 From: Thomas Van Lenten Date: Tue, 7 Apr 2020 14:43:13 -0400 Subject: [PATCH 09/38] [ObjC] Remove helper to avoid extra lookups. Skip the helper that fetches the desc again since these methods already collected it. --- objectivec/GPBUtilities.m | 55 ++++++++++++------------ objectivec/GPBUtilities_PackagePrivate.h | 5 --- 2 files changed, 28 insertions(+), 32 deletions(-) diff --git a/objectivec/GPBUtilities.m b/objectivec/GPBUtilities.m index bf1b926217..f7014519ac 100644 --- a/objectivec/GPBUtilities.m +++ b/objectivec/GPBUtilities.m @@ -267,17 +267,18 @@ void GPBClearMessageField(GPBMessage *self, GPBFieldDescriptor *field) { return; } + GPBMessageFieldDescription *fieldDesc = field->description_; if (GPBFieldStoresObject(field)) { // Object types are handled slightly differently, they need to be released. uint8_t *storage = (uint8_t *)self->messageStorage_; - id *typePtr = (id *)&storage[field->description_->offset]; + id *typePtr = (id *)&storage[fieldDesc->offset]; [*typePtr release]; *typePtr = nil; } else { // POD types just need to clear the has bit as the Get* method will // fetch the default when needed. } - GPBSetHasIvarField(self, field, NO); + GPBSetHasIvar(self, fieldDesc->hasIndex, fieldDesc->number, NO); } BOOL GPBGetHasIvar(GPBMessage *self, int32_t idx, uint32_t fieldNumber) { @@ -394,8 +395,8 @@ void GPBMaybeClearOneof(GPBMessage *self, GPBOneofDescriptor *oneof, //% TypeToString(GPBGetFieldDataType(field))); //%#endif //% GPBOneofDescriptor *oneof = field->containingOneof_; +//% GPBMessageFieldDescription *fieldDesc = field->description_; //% if (oneof) { -//% GPBMessageFieldDescription *fieldDesc = field->description_; //% GPBMaybeClearOneof(self, oneof, fieldDesc->hasIndex, fieldDesc->number); //% } //%#if defined(DEBUG) && DEBUG @@ -407,14 +408,14 @@ void GPBMaybeClearOneof(GPBMessage *self, GPBOneofDescriptor *oneof, //% if (self->messageStorage_ == NULL) return; //%#endif //% uint8_t *storage = (uint8_t *)self->messageStorage_; -//% TYPE *typePtr = (TYPE *)&storage[field->description_->offset]; +//% TYPE *typePtr = (TYPE *)&storage[fieldDesc->offset]; //% *typePtr = value; //% // proto2: any value counts as having been set; proto3, it //% // has to be a non zero value or be in a oneof. //% BOOL hasValue = ((syntax == GPBFileSyntaxProto2) //% || (value != (TYPE)0) //% || (field->containingOneof_ != NULL)); -//% GPBSetHasIvarField(self, field, hasValue); +//% GPBSetHasIvar(self, fieldDesc->hasIndex, fieldDesc->number, hasValue); //% GPBBecomeVisibleToAutocreator(self); //%} //% @@ -579,12 +580,12 @@ void GPBSetRetainedObjectIvarWithFieldInternal(GPBMessage *self, // valueData/valueMessage. } #endif // DEBUG + GPBMessageFieldDescription *fieldDesc = field->description_; if (!isMapOrArray) { // Non repeated/map can be in an oneof, clear any existing value from the // oneof. GPBOneofDescriptor *oneof = field->containingOneof_; if (oneof) { - GPBMessageFieldDescription *fieldDesc = field->description_; GPBMaybeClearOneof(self, oneof, fieldDesc->hasIndex, fieldDesc->number); } // Clear "has" if they are being set to nil. @@ -608,10 +609,10 @@ void GPBSetRetainedObjectIvarWithFieldInternal(GPBMessage *self, value = nil; } } - GPBSetHasIvarField(self, field, setHasValue); + GPBSetHasIvar(self, fieldDesc->hasIndex, fieldDesc->number, setHasValue); } uint8_t *storage = (uint8_t *)self->messageStorage_; - id *typePtr = (id *)&storage[field->description_->offset]; + id *typePtr = (id *)&storage[fieldDesc->offset]; id oldValue = *typePtr; @@ -800,7 +801,7 @@ void GPBSetBoolIvarWithFieldInternal(GPBMessage *self, BOOL hasValue = ((syntax == GPBFileSyntaxProto2) || (value != (BOOL)0) || (field->containingOneof_ != NULL)); - GPBSetHasIvarField(self, field, hasValue); + GPBSetHasIvar(self, fieldDesc->hasIndex, fieldDesc->number, hasValue); GPBBecomeVisibleToAutocreator(self); } @@ -849,8 +850,8 @@ void GPBSetInt32IvarWithFieldInternal(GPBMessage *self, TypeToString(GPBGetFieldDataType(field))); #endif GPBOneofDescriptor *oneof = field->containingOneof_; + GPBMessageFieldDescription *fieldDesc = field->description_; if (oneof) { - GPBMessageFieldDescription *fieldDesc = field->description_; GPBMaybeClearOneof(self, oneof, fieldDesc->hasIndex, fieldDesc->number); } #if defined(DEBUG) && DEBUG @@ -862,14 +863,14 @@ void GPBSetInt32IvarWithFieldInternal(GPBMessage *self, if (self->messageStorage_ == NULL) return; #endif uint8_t *storage = (uint8_t *)self->messageStorage_; - int32_t *typePtr = (int32_t *)&storage[field->description_->offset]; + int32_t *typePtr = (int32_t *)&storage[fieldDesc->offset]; *typePtr = value; // proto2: any value counts as having been set; proto3, it // has to be a non zero value or be in a oneof. BOOL hasValue = ((syntax == GPBFileSyntaxProto2) || (value != (int32_t)0) || (field->containingOneof_ != NULL)); - GPBSetHasIvarField(self, field, hasValue); + GPBSetHasIvar(self, fieldDesc->hasIndex, fieldDesc->number, hasValue); GPBBecomeVisibleToAutocreator(self); } @@ -919,8 +920,8 @@ void GPBSetUInt32IvarWithFieldInternal(GPBMessage *self, TypeToString(GPBGetFieldDataType(field))); #endif GPBOneofDescriptor *oneof = field->containingOneof_; + GPBMessageFieldDescription *fieldDesc = field->description_; if (oneof) { - GPBMessageFieldDescription *fieldDesc = field->description_; GPBMaybeClearOneof(self, oneof, fieldDesc->hasIndex, fieldDesc->number); } #if defined(DEBUG) && DEBUG @@ -932,14 +933,14 @@ void GPBSetUInt32IvarWithFieldInternal(GPBMessage *self, if (self->messageStorage_ == NULL) return; #endif uint8_t *storage = (uint8_t *)self->messageStorage_; - uint32_t *typePtr = (uint32_t *)&storage[field->description_->offset]; + uint32_t *typePtr = (uint32_t *)&storage[fieldDesc->offset]; *typePtr = value; // proto2: any value counts as having been set; proto3, it // has to be a non zero value or be in a oneof. BOOL hasValue = ((syntax == GPBFileSyntaxProto2) || (value != (uint32_t)0) || (field->containingOneof_ != NULL)); - GPBSetHasIvarField(self, field, hasValue); + GPBSetHasIvar(self, fieldDesc->hasIndex, fieldDesc->number, hasValue); GPBBecomeVisibleToAutocreator(self); } @@ -989,8 +990,8 @@ void GPBSetInt64IvarWithFieldInternal(GPBMessage *self, TypeToString(GPBGetFieldDataType(field))); #endif GPBOneofDescriptor *oneof = field->containingOneof_; + GPBMessageFieldDescription *fieldDesc = field->description_; if (oneof) { - GPBMessageFieldDescription *fieldDesc = field->description_; GPBMaybeClearOneof(self, oneof, fieldDesc->hasIndex, fieldDesc->number); } #if defined(DEBUG) && DEBUG @@ -1002,14 +1003,14 @@ void GPBSetInt64IvarWithFieldInternal(GPBMessage *self, if (self->messageStorage_ == NULL) return; #endif uint8_t *storage = (uint8_t *)self->messageStorage_; - int64_t *typePtr = (int64_t *)&storage[field->description_->offset]; + int64_t *typePtr = (int64_t *)&storage[fieldDesc->offset]; *typePtr = value; // proto2: any value counts as having been set; proto3, it // has to be a non zero value or be in a oneof. BOOL hasValue = ((syntax == GPBFileSyntaxProto2) || (value != (int64_t)0) || (field->containingOneof_ != NULL)); - GPBSetHasIvarField(self, field, hasValue); + GPBSetHasIvar(self, fieldDesc->hasIndex, fieldDesc->number, hasValue); GPBBecomeVisibleToAutocreator(self); } @@ -1059,8 +1060,8 @@ void GPBSetUInt64IvarWithFieldInternal(GPBMessage *self, TypeToString(GPBGetFieldDataType(field))); #endif GPBOneofDescriptor *oneof = field->containingOneof_; + GPBMessageFieldDescription *fieldDesc = field->description_; if (oneof) { - GPBMessageFieldDescription *fieldDesc = field->description_; GPBMaybeClearOneof(self, oneof, fieldDesc->hasIndex, fieldDesc->number); } #if defined(DEBUG) && DEBUG @@ -1072,14 +1073,14 @@ void GPBSetUInt64IvarWithFieldInternal(GPBMessage *self, if (self->messageStorage_ == NULL) return; #endif uint8_t *storage = (uint8_t *)self->messageStorage_; - uint64_t *typePtr = (uint64_t *)&storage[field->description_->offset]; + uint64_t *typePtr = (uint64_t *)&storage[fieldDesc->offset]; *typePtr = value; // proto2: any value counts as having been set; proto3, it // has to be a non zero value or be in a oneof. BOOL hasValue = ((syntax == GPBFileSyntaxProto2) || (value != (uint64_t)0) || (field->containingOneof_ != NULL)); - GPBSetHasIvarField(self, field, hasValue); + GPBSetHasIvar(self, fieldDesc->hasIndex, fieldDesc->number, hasValue); GPBBecomeVisibleToAutocreator(self); } @@ -1129,8 +1130,8 @@ void GPBSetFloatIvarWithFieldInternal(GPBMessage *self, TypeToString(GPBGetFieldDataType(field))); #endif GPBOneofDescriptor *oneof = field->containingOneof_; + GPBMessageFieldDescription *fieldDesc = field->description_; if (oneof) { - GPBMessageFieldDescription *fieldDesc = field->description_; GPBMaybeClearOneof(self, oneof, fieldDesc->hasIndex, fieldDesc->number); } #if defined(DEBUG) && DEBUG @@ -1142,14 +1143,14 @@ void GPBSetFloatIvarWithFieldInternal(GPBMessage *self, if (self->messageStorage_ == NULL) return; #endif uint8_t *storage = (uint8_t *)self->messageStorage_; - float *typePtr = (float *)&storage[field->description_->offset]; + float *typePtr = (float *)&storage[fieldDesc->offset]; *typePtr = value; // proto2: any value counts as having been set; proto3, it // has to be a non zero value or be in a oneof. BOOL hasValue = ((syntax == GPBFileSyntaxProto2) || (value != (float)0) || (field->containingOneof_ != NULL)); - GPBSetHasIvarField(self, field, hasValue); + GPBSetHasIvar(self, fieldDesc->hasIndex, fieldDesc->number, hasValue); GPBBecomeVisibleToAutocreator(self); } @@ -1199,8 +1200,8 @@ void GPBSetDoubleIvarWithFieldInternal(GPBMessage *self, TypeToString(GPBGetFieldDataType(field))); #endif GPBOneofDescriptor *oneof = field->containingOneof_; + GPBMessageFieldDescription *fieldDesc = field->description_; if (oneof) { - GPBMessageFieldDescription *fieldDesc = field->description_; GPBMaybeClearOneof(self, oneof, fieldDesc->hasIndex, fieldDesc->number); } #if defined(DEBUG) && DEBUG @@ -1212,14 +1213,14 @@ void GPBSetDoubleIvarWithFieldInternal(GPBMessage *self, if (self->messageStorage_ == NULL) return; #endif uint8_t *storage = (uint8_t *)self->messageStorage_; - double *typePtr = (double *)&storage[field->description_->offset]; + double *typePtr = (double *)&storage[fieldDesc->offset]; *typePtr = value; // proto2: any value counts as having been set; proto3, it // has to be a non zero value or be in a oneof. BOOL hasValue = ((syntax == GPBFileSyntaxProto2) || (value != (double)0) || (field->containingOneof_ != NULL)); - GPBSetHasIvarField(self, field, hasValue); + GPBSetHasIvar(self, fieldDesc->hasIndex, fieldDesc->number, hasValue); GPBBecomeVisibleToAutocreator(self); } diff --git a/objectivec/GPBUtilities_PackagePrivate.h b/objectivec/GPBUtilities_PackagePrivate.h index a20789632d..1638a8c219 100644 --- a/objectivec/GPBUtilities_PackagePrivate.h +++ b/objectivec/GPBUtilities_PackagePrivate.h @@ -206,11 +206,6 @@ GPBGetHasIvarField(GPBMessage *self, GPBFieldDescriptor *field) { GPBMessageFieldDescription *fieldDesc = field->description_; return GPBGetHasIvar(self, fieldDesc->hasIndex, fieldDesc->number); } -GPB_INLINE void GPBSetHasIvarField(GPBMessage *self, GPBFieldDescriptor *field, - BOOL value) { - GPBMessageFieldDescription *fieldDesc = field->description_; - GPBSetHasIvar(self, fieldDesc->hasIndex, fieldDesc->number, value); -} void GPBMaybeClearOneof(GPBMessage *self, GPBOneofDescriptor *oneof, int32_t oneofHasIndex, uint32_t fieldNumberNotToClear); From 7b8a241b575b756c4dd7a5aec7f7a60854d5f711 Mon Sep 17 00:00:00 2001 From: Thomas Van Lenten Date: Wed, 8 Apr 2020 13:14:38 -0400 Subject: [PATCH 10/38] [ObjC] Improve validation on public apis. --- objectivec/GPBUtilities.m | 208 ++++++++++++++++++++++++-------------- 1 file changed, 131 insertions(+), 77 deletions(-) diff --git a/objectivec/GPBUtilities.m b/objectivec/GPBUtilities.m index f7014519ac..7a1635f64a 100644 --- a/objectivec/GPBUtilities.m +++ b/objectivec/GPBUtilities.m @@ -357,6 +357,9 @@ void GPBMaybeClearOneof(GPBMessage *self, GPBOneofDescriptor *oneof, //%TYPE GPBGetMessage##NAME##Field(GPBMessage *self, //% TYPE$S NAME$S GPBFieldDescriptor *field) { //%#if defined(DEBUG) && DEBUG +//% NSCAssert([[self descriptor] fieldWithNumber:field.number] == field, +//% @"FieldDescriptor %@ doesn't appear to be for %@ messages.", +//% field.name, [self class]); //% NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), //% GPBDataType##NAME), //% @"Attempting to get value of TYPE from field %@ " @@ -378,15 +381,10 @@ void GPBMaybeClearOneof(GPBMessage *self, GPBOneofDescriptor *oneof, //% NAME$S GPBFieldDescriptor *field, //% NAME$S TYPE value) { //% if (self == nil || field == nil) return; -//% GPBFileSyntax syntax = [self descriptor].file.syntax; -//% GPBSet##NAME##IvarWithFieldInternal(self, field, value, syntax); -//%} -//% -//%void GPBSet##NAME##IvarWithFieldInternal(GPBMessage *self, -//% NAME$S GPBFieldDescriptor *field, -//% NAME$S TYPE value, -//% NAME$S GPBFileSyntax syntax) { //%#if defined(DEBUG) && DEBUG +//% NSCAssert([[self descriptor] fieldWithNumber:field.number] == field, +//% @"FieldDescriptor %@ doesn't appear to be for %@ messages.", +//% field.name, [self class]); //% NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), //% GPBDataType##NAME), //% @"Attempting to set field %@ of %@ which is of type %@ with " @@ -394,6 +392,14 @@ void GPBMaybeClearOneof(GPBMessage *self, GPBOneofDescriptor *oneof, //% [self class], field.name, //% TypeToString(GPBGetFieldDataType(field))); //%#endif +//% GPBFileSyntax syntax = [self descriptor].file.syntax; +//% GPBSet##NAME##IvarWithFieldInternal(self, field, value, syntax); +//%} +//% +//%void GPBSet##NAME##IvarWithFieldInternal(GPBMessage *self, +//% NAME$S GPBFieldDescriptor *field, +//% NAME$S TYPE value, +//% NAME$S GPBFileSyntax syntax) { //% GPBOneofDescriptor *oneof = field->containingOneof_; //% GPBMessageFieldDescription *fieldDesc = field->description_; //% if (oneof) { @@ -679,6 +685,16 @@ id GPBGetObjectIvarWithFieldNoAutocreate(GPBMessage *self, // Only exists for public api, no core code should use this. int32_t GPBGetMessageEnumField(GPBMessage *self, GPBFieldDescriptor *field) { + #if defined(DEBUG) && DEBUG + NSCAssert([[self descriptor] fieldWithNumber:field.number] == field, + @"FieldDescriptor %@ doesn't appear to be for %@ messages.", + field.name, [self class]); + NSCAssert(GPBGetFieldDataType(field) == GPBDataTypeEnum, + @"Attempting to get value of type Enum from field %@ " + @"of %@ which is of type %@.", + [self class], field.name, + TypeToString(GPBGetFieldDataType(field))); + #endif GPBFileSyntax syntax = [self descriptor].file.syntax; return GPBGetEnumIvarWithFieldInternal(self, field, syntax); } @@ -686,13 +702,6 @@ int32_t GPBGetMessageEnumField(GPBMessage *self, GPBFieldDescriptor *field) { int32_t GPBGetEnumIvarWithFieldInternal(GPBMessage *self, GPBFieldDescriptor *field, GPBFileSyntax syntax) { -#if defined(DEBUG) && DEBUG - NSCAssert(GPBGetFieldDataType(field) == GPBDataTypeEnum, - @"Attempting to get value of type Enum from field %@ " - @"of %@ which is of type %@.", - [self class], field.name, - TypeToString(GPBGetFieldDataType(field))); -#endif int32_t result = GPBGetMessageInt32Field(self, field); // If this is presevering unknown enums, make sure the value is valid before // returning it. @@ -706,6 +715,16 @@ int32_t GPBGetEnumIvarWithFieldInternal(GPBMessage *self, // Only exists for public api, no core code should use this. void GPBSetMessageEnumField(GPBMessage *self, GPBFieldDescriptor *field, int32_t value) { + #if defined(DEBUG) && DEBUG + NSCAssert([[self descriptor] fieldWithNumber:field.number] == field, + @"FieldDescriptor %@ doesn't appear to be for %@ messages.", + field.name, [self class]); + NSCAssert(GPBGetFieldDataType(field) == GPBDataTypeEnum, + @"Attempting to set field %@ of %@ which is of type %@ with " + @"value of type Enum.", + [self class], field.name, + TypeToString(GPBGetFieldDataType(field))); + #endif GPBFileSyntax syntax = [self descriptor].file.syntax; GPBSetInt32IvarWithFieldInternal(self, field, value, syntax); } @@ -713,13 +732,6 @@ void GPBSetMessageEnumField(GPBMessage *self, GPBFieldDescriptor *field, void GPBSetEnumIvarWithFieldInternal(GPBMessage *self, GPBFieldDescriptor *field, int32_t value, GPBFileSyntax syntax) { -#if defined(DEBUG) && DEBUG - NSCAssert(GPBGetFieldDataType(field) == GPBDataTypeEnum, - @"Attempting to set field %@ of %@ which is of type %@ with " - @"value of type Enum.", - [self class], field.name, - TypeToString(GPBGetFieldDataType(field))); -#endif // Don't allow in unknown values. Proto3 can use the Raw method. if (![field isValidEnumValue:value]) { [NSException raise:NSInvalidArgumentException @@ -746,6 +758,9 @@ void GPBSetMessageRawEnumField(GPBMessage *self, GPBFieldDescriptor *field, BOOL GPBGetMessageBoolField(GPBMessage *self, GPBFieldDescriptor *field) { #if defined(DEBUG) && DEBUG + NSCAssert([[self descriptor] fieldWithNumber:field.number] == field, + @"FieldDescriptor %@ doesn't appear to be for %@ messages.", + field.name, [self class]); NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), GPBDataTypeBool), @"Attempting to get value of type bool from field %@ " @"of %@ which is of type %@.", @@ -769,6 +784,16 @@ void GPBSetMessageBoolField(GPBMessage *self, GPBFieldDescriptor *field, BOOL value) { if (self == nil || field == nil) return; + #if defined(DEBUG) && DEBUG + NSCAssert([[self descriptor] fieldWithNumber:field.number] == field, + @"FieldDescriptor %@ doesn't appear to be for %@ messages.", + field.name, [self class]); + NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), GPBDataTypeBool), + @"Attempting to set field %@ of %@ which is of type %@ with " + @"value of type bool.", + [self class], field.name, + TypeToString(GPBGetFieldDataType(field))); + #endif GPBFileSyntax syntax = [self descriptor].file.syntax; GPBSetBoolIvarWithFieldInternal(self, field, value, syntax); } @@ -777,13 +802,6 @@ void GPBSetBoolIvarWithFieldInternal(GPBMessage *self, GPBFieldDescriptor *field, BOOL value, GPBFileSyntax syntax) { -#if defined(DEBUG) && DEBUG - NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), GPBDataTypeBool), - @"Attempting to set field %@ of %@ which is of type %@ with " - @"value of type bool.", - [self class], field.name, - TypeToString(GPBGetFieldDataType(field))); -#endif GPBMessageFieldDescription *fieldDesc = field->description_; GPBOneofDescriptor *oneof = field->containingOneof_; if (oneof) { @@ -812,6 +830,9 @@ void GPBSetBoolIvarWithFieldInternal(GPBMessage *self, int32_t GPBGetMessageInt32Field(GPBMessage *self, GPBFieldDescriptor *field) { #if defined(DEBUG) && DEBUG + NSCAssert([[self descriptor] fieldWithNumber:field.number] == field, + @"FieldDescriptor %@ doesn't appear to be for %@ messages.", + field.name, [self class]); NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), GPBDataTypeInt32), @"Attempting to get value of int32_t from field %@ " @@ -833,15 +854,10 @@ void GPBSetMessageInt32Field(GPBMessage *self, GPBFieldDescriptor *field, int32_t value) { if (self == nil || field == nil) return; - GPBFileSyntax syntax = [self descriptor].file.syntax; - GPBSetInt32IvarWithFieldInternal(self, field, value, syntax); -} - -void GPBSetInt32IvarWithFieldInternal(GPBMessage *self, - GPBFieldDescriptor *field, - int32_t value, - GPBFileSyntax syntax) { #if defined(DEBUG) && DEBUG + NSCAssert([[self descriptor] fieldWithNumber:field.number] == field, + @"FieldDescriptor %@ doesn't appear to be for %@ messages.", + field.name, [self class]); NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), GPBDataTypeInt32), @"Attempting to set field %@ of %@ which is of type %@ with " @@ -849,6 +865,14 @@ void GPBSetInt32IvarWithFieldInternal(GPBMessage *self, [self class], field.name, TypeToString(GPBGetFieldDataType(field))); #endif + GPBFileSyntax syntax = [self descriptor].file.syntax; + GPBSetInt32IvarWithFieldInternal(self, field, value, syntax); +} + +void GPBSetInt32IvarWithFieldInternal(GPBMessage *self, + GPBFieldDescriptor *field, + int32_t value, + GPBFileSyntax syntax) { GPBOneofDescriptor *oneof = field->containingOneof_; GPBMessageFieldDescription *fieldDesc = field->description_; if (oneof) { @@ -882,6 +906,9 @@ void GPBSetInt32IvarWithFieldInternal(GPBMessage *self, uint32_t GPBGetMessageUInt32Field(GPBMessage *self, GPBFieldDescriptor *field) { #if defined(DEBUG) && DEBUG + NSCAssert([[self descriptor] fieldWithNumber:field.number] == field, + @"FieldDescriptor %@ doesn't appear to be for %@ messages.", + field.name, [self class]); NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), GPBDataTypeUInt32), @"Attempting to get value of uint32_t from field %@ " @@ -903,15 +930,10 @@ void GPBSetMessageUInt32Field(GPBMessage *self, GPBFieldDescriptor *field, uint32_t value) { if (self == nil || field == nil) return; - GPBFileSyntax syntax = [self descriptor].file.syntax; - GPBSetUInt32IvarWithFieldInternal(self, field, value, syntax); -} - -void GPBSetUInt32IvarWithFieldInternal(GPBMessage *self, - GPBFieldDescriptor *field, - uint32_t value, - GPBFileSyntax syntax) { #if defined(DEBUG) && DEBUG + NSCAssert([[self descriptor] fieldWithNumber:field.number] == field, + @"FieldDescriptor %@ doesn't appear to be for %@ messages.", + field.name, [self class]); NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), GPBDataTypeUInt32), @"Attempting to set field %@ of %@ which is of type %@ with " @@ -919,6 +941,14 @@ void GPBSetUInt32IvarWithFieldInternal(GPBMessage *self, [self class], field.name, TypeToString(GPBGetFieldDataType(field))); #endif + GPBFileSyntax syntax = [self descriptor].file.syntax; + GPBSetUInt32IvarWithFieldInternal(self, field, value, syntax); +} + +void GPBSetUInt32IvarWithFieldInternal(GPBMessage *self, + GPBFieldDescriptor *field, + uint32_t value, + GPBFileSyntax syntax) { GPBOneofDescriptor *oneof = field->containingOneof_; GPBMessageFieldDescription *fieldDesc = field->description_; if (oneof) { @@ -952,6 +982,9 @@ void GPBSetUInt32IvarWithFieldInternal(GPBMessage *self, int64_t GPBGetMessageInt64Field(GPBMessage *self, GPBFieldDescriptor *field) { #if defined(DEBUG) && DEBUG + NSCAssert([[self descriptor] fieldWithNumber:field.number] == field, + @"FieldDescriptor %@ doesn't appear to be for %@ messages.", + field.name, [self class]); NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), GPBDataTypeInt64), @"Attempting to get value of int64_t from field %@ " @@ -973,15 +1006,10 @@ void GPBSetMessageInt64Field(GPBMessage *self, GPBFieldDescriptor *field, int64_t value) { if (self == nil || field == nil) return; - GPBFileSyntax syntax = [self descriptor].file.syntax; - GPBSetInt64IvarWithFieldInternal(self, field, value, syntax); -} - -void GPBSetInt64IvarWithFieldInternal(GPBMessage *self, - GPBFieldDescriptor *field, - int64_t value, - GPBFileSyntax syntax) { #if defined(DEBUG) && DEBUG + NSCAssert([[self descriptor] fieldWithNumber:field.number] == field, + @"FieldDescriptor %@ doesn't appear to be for %@ messages.", + field.name, [self class]); NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), GPBDataTypeInt64), @"Attempting to set field %@ of %@ which is of type %@ with " @@ -989,6 +1017,14 @@ void GPBSetInt64IvarWithFieldInternal(GPBMessage *self, [self class], field.name, TypeToString(GPBGetFieldDataType(field))); #endif + GPBFileSyntax syntax = [self descriptor].file.syntax; + GPBSetInt64IvarWithFieldInternal(self, field, value, syntax); +} + +void GPBSetInt64IvarWithFieldInternal(GPBMessage *self, + GPBFieldDescriptor *field, + int64_t value, + GPBFileSyntax syntax) { GPBOneofDescriptor *oneof = field->containingOneof_; GPBMessageFieldDescription *fieldDesc = field->description_; if (oneof) { @@ -1022,6 +1058,9 @@ void GPBSetInt64IvarWithFieldInternal(GPBMessage *self, uint64_t GPBGetMessageUInt64Field(GPBMessage *self, GPBFieldDescriptor *field) { #if defined(DEBUG) && DEBUG + NSCAssert([[self descriptor] fieldWithNumber:field.number] == field, + @"FieldDescriptor %@ doesn't appear to be for %@ messages.", + field.name, [self class]); NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), GPBDataTypeUInt64), @"Attempting to get value of uint64_t from field %@ " @@ -1043,15 +1082,10 @@ void GPBSetMessageUInt64Field(GPBMessage *self, GPBFieldDescriptor *field, uint64_t value) { if (self == nil || field == nil) return; - GPBFileSyntax syntax = [self descriptor].file.syntax; - GPBSetUInt64IvarWithFieldInternal(self, field, value, syntax); -} - -void GPBSetUInt64IvarWithFieldInternal(GPBMessage *self, - GPBFieldDescriptor *field, - uint64_t value, - GPBFileSyntax syntax) { #if defined(DEBUG) && DEBUG + NSCAssert([[self descriptor] fieldWithNumber:field.number] == field, + @"FieldDescriptor %@ doesn't appear to be for %@ messages.", + field.name, [self class]); NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), GPBDataTypeUInt64), @"Attempting to set field %@ of %@ which is of type %@ with " @@ -1059,6 +1093,14 @@ void GPBSetUInt64IvarWithFieldInternal(GPBMessage *self, [self class], field.name, TypeToString(GPBGetFieldDataType(field))); #endif + GPBFileSyntax syntax = [self descriptor].file.syntax; + GPBSetUInt64IvarWithFieldInternal(self, field, value, syntax); +} + +void GPBSetUInt64IvarWithFieldInternal(GPBMessage *self, + GPBFieldDescriptor *field, + uint64_t value, + GPBFileSyntax syntax) { GPBOneofDescriptor *oneof = field->containingOneof_; GPBMessageFieldDescription *fieldDesc = field->description_; if (oneof) { @@ -1092,6 +1134,9 @@ void GPBSetUInt64IvarWithFieldInternal(GPBMessage *self, float GPBGetMessageFloatField(GPBMessage *self, GPBFieldDescriptor *field) { #if defined(DEBUG) && DEBUG + NSCAssert([[self descriptor] fieldWithNumber:field.number] == field, + @"FieldDescriptor %@ doesn't appear to be for %@ messages.", + field.name, [self class]); NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), GPBDataTypeFloat), @"Attempting to get value of float from field %@ " @@ -1113,15 +1158,10 @@ void GPBSetMessageFloatField(GPBMessage *self, GPBFieldDescriptor *field, float value) { if (self == nil || field == nil) return; - GPBFileSyntax syntax = [self descriptor].file.syntax; - GPBSetFloatIvarWithFieldInternal(self, field, value, syntax); -} - -void GPBSetFloatIvarWithFieldInternal(GPBMessage *self, - GPBFieldDescriptor *field, - float value, - GPBFileSyntax syntax) { #if defined(DEBUG) && DEBUG + NSCAssert([[self descriptor] fieldWithNumber:field.number] == field, + @"FieldDescriptor %@ doesn't appear to be for %@ messages.", + field.name, [self class]); NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), GPBDataTypeFloat), @"Attempting to set field %@ of %@ which is of type %@ with " @@ -1129,6 +1169,14 @@ void GPBSetFloatIvarWithFieldInternal(GPBMessage *self, [self class], field.name, TypeToString(GPBGetFieldDataType(field))); #endif + GPBFileSyntax syntax = [self descriptor].file.syntax; + GPBSetFloatIvarWithFieldInternal(self, field, value, syntax); +} + +void GPBSetFloatIvarWithFieldInternal(GPBMessage *self, + GPBFieldDescriptor *field, + float value, + GPBFileSyntax syntax) { GPBOneofDescriptor *oneof = field->containingOneof_; GPBMessageFieldDescription *fieldDesc = field->description_; if (oneof) { @@ -1162,6 +1210,9 @@ void GPBSetFloatIvarWithFieldInternal(GPBMessage *self, double GPBGetMessageDoubleField(GPBMessage *self, GPBFieldDescriptor *field) { #if defined(DEBUG) && DEBUG + NSCAssert([[self descriptor] fieldWithNumber:field.number] == field, + @"FieldDescriptor %@ doesn't appear to be for %@ messages.", + field.name, [self class]); NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), GPBDataTypeDouble), @"Attempting to get value of double from field %@ " @@ -1183,15 +1234,10 @@ void GPBSetMessageDoubleField(GPBMessage *self, GPBFieldDescriptor *field, double value) { if (self == nil || field == nil) return; - GPBFileSyntax syntax = [self descriptor].file.syntax; - GPBSetDoubleIvarWithFieldInternal(self, field, value, syntax); -} - -void GPBSetDoubleIvarWithFieldInternal(GPBMessage *self, - GPBFieldDescriptor *field, - double value, - GPBFileSyntax syntax) { #if defined(DEBUG) && DEBUG + NSCAssert([[self descriptor] fieldWithNumber:field.number] == field, + @"FieldDescriptor %@ doesn't appear to be for %@ messages.", + field.name, [self class]); NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), GPBDataTypeDouble), @"Attempting to set field %@ of %@ which is of type %@ with " @@ -1199,6 +1245,14 @@ void GPBSetDoubleIvarWithFieldInternal(GPBMessage *self, [self class], field.name, TypeToString(GPBGetFieldDataType(field))); #endif + GPBFileSyntax syntax = [self descriptor].file.syntax; + GPBSetDoubleIvarWithFieldInternal(self, field, value, syntax); +} + +void GPBSetDoubleIvarWithFieldInternal(GPBMessage *self, + GPBFieldDescriptor *field, + double value, + GPBFileSyntax syntax) { GPBOneofDescriptor *oneof = field->containingOneof_; GPBMessageFieldDescription *fieldDesc = field->description_; if (oneof) { From 97f5f649a419279368fd10036dca48c6d8ed0f1f Mon Sep 17 00:00:00 2001 From: "Daniel G. Taylor" Date: Wed, 15 Apr 2020 22:00:28 -0700 Subject: [PATCH 11/38] docs: add python-betterproto Adds the `betterproto` Python module to the list of implementations. --- docs/third_party.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/third_party.md b/docs/third_party.md index 528dc6e220..11a6efb5b1 100644 --- a/docs/third_party.md +++ b/docs/third_party.md @@ -82,6 +82,7 @@ These are projects we know about implementing Protocol Buffers for other program * Prolog: http://www.swi-prolog.org/pldoc/package/protobufs.html * Python: https://github.com/google/protobuf (Google-official implementation) * Python: https://github.com/eigenein/protobuf +* Python: https://github.com/danielgtaylor/python-betterproto * R: http://cran.r-project.org/package=RProtoBuf * Ruby: http://code.google.com/p/ruby-protobuf/ * Ruby: http://github.com/mozy/ruby-protocol-buffers From 64f6c59ccb56497749e83792696e726169aa00fc Mon Sep 17 00:00:00 2001 From: Masaki Hara Date: Fri, 17 Apr 2020 15:31:47 +0900 Subject: [PATCH 12/38] Build extensions for Ruby 2.7 (#7027) * Build extensions for Ruby 2.7 * Try installing bundler 2.x * Try bumping rake-compiler-dock * Use standard RCD images * Avoid 'rake cross native' with rake-compiler-dock * Use Ruby 2.5 for building Ruby <= 2.6 * Use rake-compiler 1.1.0 * Specify target * Don't update Ruby test image for now --- .../release/ruby_rake_compiler/Dockerfile | 3 -- kokoro/release/ruby/linux/prepare_build.sh | 6 ---- kokoro/release/ruby/linux/ruby/ruby_build.sh | 1 + .../ruby/macos/ruby/ruby_build_environment.sh | 29 +++++++++++++++---- ruby/Rakefile | 9 ++++-- ruby/google-protobuf.gemspec | 4 +-- 6 files changed, 34 insertions(+), 18 deletions(-) delete mode 100644 kokoro/linux/dockerfile/release/ruby_rake_compiler/Dockerfile diff --git a/kokoro/linux/dockerfile/release/ruby_rake_compiler/Dockerfile b/kokoro/linux/dockerfile/release/ruby_rake_compiler/Dockerfile deleted file mode 100644 index 866b289343..0000000000 --- a/kokoro/linux/dockerfile/release/ruby_rake_compiler/Dockerfile +++ /dev/null @@ -1,3 +0,0 @@ -FROM grpctesting/rake-compiler-dock_53c22085d091183c528303791e7771359f699bcf - -RUN /bin/bash -l -c "gem update --system '2.7.9' && gem install bundler" diff --git a/kokoro/release/ruby/linux/prepare_build.sh b/kokoro/release/ruby/linux/prepare_build.sh index f2257c3c75..91d186898c 100755 --- a/kokoro/release/ruby/linux/prepare_build.sh +++ b/kokoro/release/ruby/linux/prepare_build.sh @@ -7,12 +7,6 @@ echo 'DOCKER_OPTS="${DOCKER_OPTS} --graph=/tmpfs/docker"' | sudo tee --append /e echo 'DOCKER_OPTS="${DOCKER_OPTS} --registry-mirror=https://mirror.gcr.io"' | sudo tee --append /etc/default/docker sudo service docker restart -# Download Docker images from DockerHub -DOCKERHUB_ORGANIZATION=protobuftesting -DOCKERFILE_DIR=kokoro/linux/dockerfile/release/ruby_rake_compiler -DOCKERFILE_PREFIX=$(basename $DOCKERFILE_DIR) -export RAKE_COMPILER_DOCK_IMAGE=${DOCKERHUB_ORGANIZATION}/${DOCKERFILE_PREFIX}_$(sha1sum $DOCKERFILE_DIR/Dockerfile | cut -f1 -d\ ) - # All artifacts come here mkdir artifacts export ARTIFACT_DIR=$(pwd)/artifacts diff --git a/kokoro/release/ruby/linux/ruby/ruby_build.sh b/kokoro/release/ruby/linux/ruby/ruby_build.sh index 9fc42b13eb..95f1dea906 100755 --- a/kokoro/release/ruby/linux/ruby/ruby_build.sh +++ b/kokoro/release/ruby/linux/ruby/ruby_build.sh @@ -11,6 +11,7 @@ fi umask 0022 pushd ruby +gem install bundler -v 2.1.4 bundle install && bundle exec rake gem:native ls pkg mv pkg/* $ARTIFACT_DIR diff --git a/kokoro/release/ruby/macos/ruby/ruby_build_environment.sh b/kokoro/release/ruby/macos/ruby/ruby_build_environment.sh index 5776e3c349..a4bf9e051e 100755 --- a/kokoro/release/ruby/macos/ruby/ruby_build_environment.sh +++ b/kokoro/release/ruby/macos/ruby/ruby_build_environment.sh @@ -6,7 +6,11 @@ set +ex # rvm script is very verbose and exits with errorcode source $HOME/.rvm/scripts/rvm set -e # rvm commands are very verbose time rvm install 2.5.0 -rvm use 2.5.0 --default +rvm use 2.5.0 +gem install rake-compiler --no-document +gem install bundler --no-document +time rvm install 2.7.0 +rvm use 2.7.0 --default gem install rake-compiler --no-document gem install bundler --no-document rvm osx-ssl-certs status all @@ -17,13 +21,13 @@ rm -rf ~/.rake-compiler CROSS_RUBY=$(mktemp tmpfile.XXXXXXXX) -curl https://raw.githubusercontent.com/rake-compiler/rake-compiler/v1.0.3/tasks/bin/cross-ruby.rake > "$CROSS_RUBY" +curl https://raw.githubusercontent.com/rake-compiler/rake-compiler/v1.1.0/tasks/bin/cross-ruby.rake > "$CROSS_RUBY" # See https://github.com/grpc/grpc/issues/12161 for verconf.h patch details patch "$CROSS_RUBY" << EOF --- cross-ruby.rake 2018-04-10 11:32:16.000000000 -0700 +++ patched 2018-04-10 11:40:25.000000000 -0700 -@@ -133,8 +133,10 @@ +@@ -141,8 +141,10 @@ "--host=#{MINGW_HOST}", "--target=#{MINGW_TARGET}", "--build=#{RUBY_BUILD}", @@ -35,9 +39,9 @@ patch "$CROSS_RUBY" << EOF '--with-ext=' ] -@@ -151,6 +153,7 @@ +@@ -159,6 +161,7 @@ # make - file "#{USER_HOME}/builds/#{MINGW_HOST}/#{RUBY_CC_VERSION}/ruby.exe" => ["#{USER_HOME}/builds/#{MINGW_HOST}/#{RUBY_CC_VERSION}/Makefile"] do |t| + file "#{build_dir}/ruby.exe" => ["#{build_dir}/Makefile"] do |t| chdir File.dirname(t.prerequisites.first) do + sh "test -s verconf.h || rm -f verconf.h" # if verconf.h has size 0, make sure it gets re-built by make sh MAKE @@ -47,10 +51,25 @@ EOF MAKE="make -j8" +set +x # rvm commands are very verbose +rvm use 2.7.0 +set -x +ruby --version | grep 'ruby 2.7.0' +for v in 2.7.0 ; do + ccache -c + rake -f "$CROSS_RUBY" cross-ruby VERSION="$v" HOST=x86_64-darwin11 MAKE="$MAKE" +done +set +x +rvm use 2.5.0 +set -x +ruby --version | grep 'ruby 2.5.0' for v in 2.6.0 2.5.1 2.4.0 2.3.0 ; do ccache -c rake -f "$CROSS_RUBY" cross-ruby VERSION="$v" HOST=x86_64-darwin11 MAKE="$MAKE" done +set +x +rvm use 2.7.0 +set -x sed 's/x86_64-darwin-11/universal-darwin/' ~/.rake-compiler/config.yml > "$CROSS_RUBY" mv "$CROSS_RUBY" ~/.rake-compiler/config.yml diff --git a/ruby/Rakefile b/ruby/Rakefile index ad70e3107c..b0b803dd65 100644 --- a/ruby/Rakefile +++ b/ruby/Rakefile @@ -70,13 +70,18 @@ else task 'gem:windows' do require 'rake_compiler_dock' - RakeCompilerDock.sh "bundle && IN_DOCKER=true rake cross native gem RUBY_CC_VERSION=2.6.0:2.5.0:2.4.0:2.3.0" + ['x86-mingw32', 'x64-mingw32', 'x86_64-linux', 'x86-linux'].each do |plat| + RakeCompilerDock.sh <<-"EOT", platform: plat + bundle && \ + IN_DOCKER=true rake native:#{plat} pkg/#{spec.full_name}-#{plat}.gem RUBY_CC_VERSION=2.7.0:2.6.0:2.5.0:2.4.0:2.3.0 + EOT + end end if RUBY_PLATFORM =~ /darwin/ task 'gem:native' do system "rake genproto" - system "rake cross native gem RUBY_CC_VERSION=2.6.0:2.5.1:2.4.0:2.3.0" + system "rake cross native gem RUBY_CC_VERSION=2.7.0:2.6.0:2.5.1:2.4.0:2.3.0" end else task 'gem:native' => [:genproto, 'gem:windows'] diff --git a/ruby/google-protobuf.gemspec b/ruby/google-protobuf.gemspec index bf60b6ae9e..cd9af71b6e 100644 --- a/ruby/google-protobuf.gemspec +++ b/ruby/google-protobuf.gemspec @@ -17,13 +17,13 @@ Gem::Specification.new do |s| else s.files += Dir.glob('ext/**/*') s.extensions= ["ext/google/protobuf_c/extconf.rb"] - s.add_development_dependency "rake-compiler-dock", "~> 0.6.0" + s.add_development_dependency "rake-compiler-dock", ">= 1.0.1", "< 2.0" end s.test_files = ["tests/basic.rb", "tests/stress.rb", "tests/generated_code_test.rb"] s.required_ruby_version = '>= 2.3' - s.add_development_dependency "rake-compiler", "~> 0.9.5" + s.add_development_dependency "rake-compiler", "~> 1.1.0" s.add_development_dependency "test-unit", '~> 3.0', '>= 3.0.9' s.add_development_dependency "rubygems-tasks", "~> 0.2.4" end From 2c8364bcd199f4ce98892be10cafd7d3e537c0eb Mon Sep 17 00:00:00 2001 From: Eric Walker Date: Fri, 17 Apr 2020 13:20:38 -0400 Subject: [PATCH 13/38] Rails2.7 segfaults (#7091) * Add a test suite for ruby 2.7 * Call BigDecimal() instead of BigDecimal.new() BigDecimal.new was deprecated in ruby 2.6 * Switch FrozenError expectation to a matcher The error message for FrozenError changed to include more information about the mutated object. Switch from an exact match to an aproximate match (equal => match). This does not change the prefix. * We can safely ignore newest array methods from ruby 2.7 --- ruby/tests/common_tests.rb | 2 +- ruby/tests/repeated_field_test.rb | 1 + tests.sh | 4 ++++ 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/ruby/tests/common_tests.rb b/ruby/tests/common_tests.rb index 67781467a1..1f5013a529 100644 --- a/ruby/tests/common_tests.rb +++ b/ruby/tests/common_tests.rb @@ -1739,7 +1739,7 @@ module CommonTests m.freeze frozen_error = assert_raise(FrozenErrorType) { m.optional_int32 = 20 } - assert_equal "can't modify frozen #{proto_module}::TestMessage", frozen_error.message + assert_match "can't modify frozen #{proto_module}::TestMessage", frozen_error.message assert_equal 10, m.optional_int32 assert_equal true, m.frozen? diff --git a/ruby/tests/repeated_field_test.rb b/ruby/tests/repeated_field_test.rb index ced9de8381..6307447bc3 100755 --- a/ruby/tests/repeated_field_test.rb +++ b/ruby/tests/repeated_field_test.rb @@ -20,6 +20,7 @@ class RepeatedFieldTest < Test::Unit::TestCase :iter_for_each_with_index, :dimensions, :copy_data, :copy_data_simple, :nitems, :iter_for_reverse_each, :indexes, :append, :prepend] arr_methods -= [:union, :difference, :filter!] + arr_methods -= [:intersection, :deconstruct] # ruby 2.7 methods we can ignore arr_methods.each do |method_name| assert m.repeated_string.respond_to?(method_name) == true, "does not respond to #{method_name}" end diff --git a/tests.sh b/tests.sh index 9f485fee09..84fb0b124b 100755 --- a/tests.sh +++ b/tests.sh @@ -436,6 +436,10 @@ build_ruby26() { internal_build_cpp # For conformance tests. cd ruby && bash travis-test.sh ruby-2.6.0 && cd .. } +build_ruby27() { + internal_build_cpp # For conformance tests. + cd ruby && bash travis-test.sh ruby-2.7.0 && cd .. +} build_javascript() { internal_build_cpp From f15ac4091f96eb88f583eaa040ed16319104ebd2 Mon Sep 17 00:00:00 2001 From: Paul Yang Date: Sat, 18 Apr 2020 14:39:52 -0700 Subject: [PATCH 14/38] Drop 3.3, 3.4 and use single version docker images for all python tests (#7396) * Create a new docker image for python 3.6 The previous one cannot build, because python3.6 was removed from stretch. * Drop support for 3.3 and 3.4 Also update all docker file to be single version --- README.md | 2 +- .../linux/dockerfile/push_testing_images.sh | 2 +- .../linux/dockerfile/test/python27/Dockerfile | 23 +++++++++ .../linux/dockerfile/test/python35/Dockerfile | 23 +++++++++ .../linux/dockerfile/test/python36/Dockerfile | 23 +++++++++ .../linux/dockerfile/test/python37/Dockerfile | 23 +++++++++ .../linux/dockerfile/test/python38/Dockerfile | 23 +++++++++ .../dockerfile/test/python_jessie/Dockerfile | 39 --------------- .../dockerfile/test/python_stretch/Dockerfile | 49 ------------------- kokoro/linux/python27/build.sh | 2 +- kokoro/linux/python27_cpp/build.sh | 2 +- kokoro/linux/python33/build.sh | 18 ------- kokoro/linux/python33/continuous.cfg | 11 ----- kokoro/linux/python33/presubmit.cfg | 11 ----- kokoro/linux/python33_cpp/build.sh | 18 ------- kokoro/linux/python33_cpp/continuous.cfg | 11 ----- kokoro/linux/python33_cpp/presubmit.cfg | 11 ----- kokoro/linux/python34/build.sh | 18 ------- kokoro/linux/python34/continuous.cfg | 11 ----- kokoro/linux/python34/presubmit.cfg | 11 ----- kokoro/linux/python34_cpp/build.sh | 18 ------- kokoro/linux/python34_cpp/continuous.cfg | 11 ----- kokoro/linux/python34_cpp/presubmit.cfg | 11 ----- kokoro/linux/python35/build.sh | 2 +- kokoro/linux/python35_cpp/build.sh | 2 +- kokoro/linux/python36/build.sh | 2 +- kokoro/linux/python36_cpp/build.sh | 2 +- kokoro/linux/python37/build.sh | 2 +- kokoro/linux/python37_cpp/build.sh | 2 +- kokoro/linux/python38/build.sh | 2 +- kokoro/linux/python38_cpp/build.sh | 2 +- 31 files changed, 127 insertions(+), 260 deletions(-) create mode 100644 kokoro/linux/dockerfile/test/python27/Dockerfile create mode 100644 kokoro/linux/dockerfile/test/python35/Dockerfile create mode 100644 kokoro/linux/dockerfile/test/python36/Dockerfile create mode 100644 kokoro/linux/dockerfile/test/python37/Dockerfile create mode 100644 kokoro/linux/dockerfile/test/python38/Dockerfile delete mode 100644 kokoro/linux/dockerfile/test/python_jessie/Dockerfile delete mode 100644 kokoro/linux/dockerfile/test/python_stretch/Dockerfile delete mode 100755 kokoro/linux/python33/build.sh delete mode 100644 kokoro/linux/python33/continuous.cfg delete mode 100644 kokoro/linux/python33/presubmit.cfg delete mode 100755 kokoro/linux/python33_cpp/build.sh delete mode 100644 kokoro/linux/python33_cpp/continuous.cfg delete mode 100644 kokoro/linux/python33_cpp/presubmit.cfg delete mode 100755 kokoro/linux/python34/build.sh delete mode 100644 kokoro/linux/python34/continuous.cfg delete mode 100644 kokoro/linux/python34/presubmit.cfg delete mode 100755 kokoro/linux/python34_cpp/build.sh delete mode 100644 kokoro/linux/python34_cpp/continuous.cfg delete mode 100644 kokoro/linux/python34_cpp/presubmit.cfg diff --git a/README.md b/README.md index 0e5ae61e26..2f42c6c934 100644 --- a/README.md +++ b/README.md @@ -56,7 +56,7 @@ how to install protobuf runtime for that specific language: |--------------------------------------|-------------------------------------------------------------|--------|-------|---------| | C++ (include C++ runtime and protoc) | [src](src) | [![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-cpp_distcheck.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fcpp_distcheck%2Fcontinuous)
[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-bazel.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fbazel%2Fcontinuous)
[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-dist_install.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fdist_install%2Fcontinuous) | [![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/macos-cpp.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fmacos%2Fcpp%2Fcontinuous)
[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/macos-cpp_distcheck.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fmacos%2Fcpp_distcheck%2Fcontinuous) | [![Build status](https://ci.appveyor.com/api/projects/status/73ctee6ua4w2ruin?svg=true)](https://ci.appveyor.com/project/protobuf/protobuf) | | Java | [java](java) | [![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-java_compatibility.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fjava_compatibility%2Fcontinuous)
[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-java_jdk7.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fjava_jdk7%2Fcontinuous)
[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-java_oracle7.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fjava_oracle7%2Fcontinuous)
[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-java_linkage_monitor.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fjava_linkage_monitor%2Fcontinuous) | | | -| Python | [python](python) | [![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-python27.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fpython27%2Fcontinuous)
[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-python33.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fpython33%2Fcontinuous)
[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-python34.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fpython34%2Fcontinuous)
[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-python35.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fpython35%2Fcontinuous)
[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-python36.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fpython36%2Fcontinuous)
[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-python37.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fpython37%2Fcontinuous)
[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-python_compatibility.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fpython_compatibility%2Fcontinuous)
[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-python27_cpp.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fpython27_cpp%2Fcontinuous)
[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-python33_cpp.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fpython33_cpp%2Fcontinuous)
[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-python34_cpp.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fpython34_cpp%2Fcontinuous)
[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-python35_cpp.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fpython35_cpp%2Fcontinuous)
[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-python36_cpp.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fpython36_cpp%2Fcontinuous)
[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-python37_cpp.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fpython37_cpp%2Fcontinuous)
[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-python-release.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fpython_release%2Fcontinuous) | [![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/macos-python.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fmacos%2Fpython%2Fcontinuous)
[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/macos-python_cpp.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fmacos%2Fpython_cpp%2Fcontinuous)
[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/macos-python-release.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fmacos%2Fpython_release%2Fcontinuous) | [![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/windows-python-release.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fwindows%2Fpython_release%2Fcontinuous) | +| Python | [python](python) | [![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-python27.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fpython27%2Fcontinuous)
[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-python35.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fpython35%2Fcontinuous)
[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-python36.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fpython36%2Fcontinuous)
[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-python37.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fpython37%2Fcontinuous)
[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-python_compatibility.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fpython_compatibility%2Fcontinuous)
[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-python27_cpp.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fpython27_cpp%2Fcontinuous)
[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-python35_cpp.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fpython35_cpp%2Fcontinuous)
[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-python36_cpp.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fpython36_cpp%2Fcontinuous)
[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-python37_cpp.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fpython37_cpp%2Fcontinuous)
[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-python-release.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fpython_release%2Fcontinuous) | [![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/macos-python.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fmacos%2Fpython%2Fcontinuous)
[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/macos-python_cpp.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fmacos%2Fpython_cpp%2Fcontinuous)
[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/macos-python-release.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fmacos%2Fpython_release%2Fcontinuous) | [![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/windows-python-release.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fwindows%2Fpython_release%2Fcontinuous) | | Objective-C | [objectivec](objectivec) | | [![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/macos-objectivec_cocoapods_integration.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fmacos%2Fobjectivec_cocoapods_integration%2Fcontinuous)
[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/macos-objectivec_ios_debug.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fmacos%2Fobjectivec_ios_debug%2Fcontinuous)
[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/macos-objectivec_ios_release.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fmacos%2Fobjectivec_ios_release%2Fcontinuous)
[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/macos-objectivec_osx.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fmacos%2Fobjectivec_osx%2Fcontinuous) | | | C# | [csharp](csharp) | [![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-csharp.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fcsharp%2Fcontinuous) | | [![Build status](https://ci.appveyor.com/api/projects/status/73ctee6ua4w2ruin?svg=true)](https://ci.appveyor.com/project/protobuf/protobuf)
[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/windows-csharp-release.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fwindows%2Fcsharp_release%2Fcontinuous) | | JavaScript | [js](js) | [![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-javascript.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fjavascript%2Fcontinuous) | [![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/macos-javascript.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fmacos%2Fjavascript%2Fcontinuous) | | diff --git a/kokoro/linux/dockerfile/push_testing_images.sh b/kokoro/linux/dockerfile/push_testing_images.sh index 9a2983c829..2d82babba4 100755 --- a/kokoro/linux/dockerfile/push_testing_images.sh +++ b/kokoro/linux/dockerfile/push_testing_images.sh @@ -8,7 +8,7 @@ cd kokoro/linux/dockerfile DOCKERHUB_ORGANIZATION=protobuftesting -for DOCKERFILE_DIR in test/* release/* +for DOCKERFILE_DIR in test/* do # Generate image name based on Dockerfile checksum. That works well as long # as can count on dockerfiles being written in a way that changing the logical diff --git a/kokoro/linux/dockerfile/test/python27/Dockerfile b/kokoro/linux/dockerfile/test/python27/Dockerfile new file mode 100644 index 0000000000..e41e49a6e5 --- /dev/null +++ b/kokoro/linux/dockerfile/test/python27/Dockerfile @@ -0,0 +1,23 @@ +FROM python:2.7-buster + +# Install dependencies. We start with the basic ones require to build protoc +# and the C++ build +RUN apt-get update && apt-get install -y \ + autoconf \ + autotools-dev \ + build-essential \ + bzip2 \ + ccache \ + curl \ + gcc \ + git \ + libc6 \ + libc6-dbg \ + libc6-dev \ + libgtest-dev \ + libtool \ + make \ + parallel \ + time \ + wget \ + && apt-get clean diff --git a/kokoro/linux/dockerfile/test/python35/Dockerfile b/kokoro/linux/dockerfile/test/python35/Dockerfile new file mode 100644 index 0000000000..3ea4c9e188 --- /dev/null +++ b/kokoro/linux/dockerfile/test/python35/Dockerfile @@ -0,0 +1,23 @@ +FROM python:3.5-buster + +# Install dependencies. We start with the basic ones require to build protoc +# and the C++ build +RUN apt-get update && apt-get install -y \ + autoconf \ + autotools-dev \ + build-essential \ + bzip2 \ + ccache \ + curl \ + gcc \ + git \ + libc6 \ + libc6-dbg \ + libc6-dev \ + libgtest-dev \ + libtool \ + make \ + parallel \ + time \ + wget \ + && apt-get clean diff --git a/kokoro/linux/dockerfile/test/python36/Dockerfile b/kokoro/linux/dockerfile/test/python36/Dockerfile new file mode 100644 index 0000000000..436846065b --- /dev/null +++ b/kokoro/linux/dockerfile/test/python36/Dockerfile @@ -0,0 +1,23 @@ +FROM python:3.6-buster + +# Install dependencies. We start with the basic ones require to build protoc +# and the C++ build +RUN apt-get update && apt-get install -y \ + autoconf \ + autotools-dev \ + build-essential \ + bzip2 \ + ccache \ + curl \ + gcc \ + git \ + libc6 \ + libc6-dbg \ + libc6-dev \ + libgtest-dev \ + libtool \ + make \ + parallel \ + time \ + wget \ + && apt-get clean diff --git a/kokoro/linux/dockerfile/test/python37/Dockerfile b/kokoro/linux/dockerfile/test/python37/Dockerfile new file mode 100644 index 0000000000..c711eb86a5 --- /dev/null +++ b/kokoro/linux/dockerfile/test/python37/Dockerfile @@ -0,0 +1,23 @@ +FROM python:3.7-buster + +# Install dependencies. We start with the basic ones require to build protoc +# and the C++ build +RUN apt-get update && apt-get install -y \ + autoconf \ + autotools-dev \ + build-essential \ + bzip2 \ + ccache \ + curl \ + gcc \ + git \ + libc6 \ + libc6-dbg \ + libc6-dev \ + libgtest-dev \ + libtool \ + make \ + parallel \ + time \ + wget \ + && apt-get clean diff --git a/kokoro/linux/dockerfile/test/python38/Dockerfile b/kokoro/linux/dockerfile/test/python38/Dockerfile new file mode 100644 index 0000000000..48a7be5e05 --- /dev/null +++ b/kokoro/linux/dockerfile/test/python38/Dockerfile @@ -0,0 +1,23 @@ +FROM python:3.8-buster + +# Install dependencies. We start with the basic ones require to build protoc +# and the C++ build +RUN apt-get update && apt-get install -y \ + autoconf \ + autotools-dev \ + build-essential \ + bzip2 \ + ccache \ + curl \ + gcc \ + git \ + libc6 \ + libc6-dbg \ + libc6-dev \ + libgtest-dev \ + libtool \ + make \ + parallel \ + time \ + wget \ + && apt-get clean diff --git a/kokoro/linux/dockerfile/test/python_jessie/Dockerfile b/kokoro/linux/dockerfile/test/python_jessie/Dockerfile deleted file mode 100644 index b5a53a3e5f..0000000000 --- a/kokoro/linux/dockerfile/test/python_jessie/Dockerfile +++ /dev/null @@ -1,39 +0,0 @@ -FROM debian:jessie - -# Install dependencies. We start with the basic ones require to build protoc -# and the C++ build -RUN apt-get update && apt-get install -y \ - autoconf \ - autotools-dev \ - build-essential \ - bzip2 \ - ccache \ - curl \ - gcc \ - git \ - libc6 \ - libc6-dbg \ - libc6-dev \ - libgtest-dev \ - libtool \ - make \ - parallel \ - time \ - wget \ - && apt-get clean - -# Install python dependencies -RUN apt-get update && apt-get install -y \ - python-setuptools \ - python-all-dev \ - python3-all-dev \ - python-pip - -# Install Python packages from PyPI -RUN pip install --upgrade pip==10.0.1 -RUN pip install virtualenv -RUN pip install six==1.10.0 twisted==17.5.0 - -# Install pip and virtualenv for Python 3.4 -RUN curl https://bootstrap.pypa.io/get-pip.py | python3.4 -RUN python3.4 -m pip install virtualenv diff --git a/kokoro/linux/dockerfile/test/python_stretch/Dockerfile b/kokoro/linux/dockerfile/test/python_stretch/Dockerfile deleted file mode 100644 index 10790b9c3e..0000000000 --- a/kokoro/linux/dockerfile/test/python_stretch/Dockerfile +++ /dev/null @@ -1,49 +0,0 @@ -FROM debian:stretch - -# Install dependencies. We start with the basic ones require to build protoc -# and the C++ build -RUN apt-get update && apt-get install -y \ - autoconf \ - autotools-dev \ - build-essential \ - bzip2 \ - ccache \ - curl \ - gcc \ - git \ - libc6 \ - libc6-dbg \ - libc6-dev \ - libgtest-dev \ - libtool \ - make \ - parallel \ - time \ - wget \ - && apt-get clean - -# Install Python 2.7 -RUN apt-get update && apt-get install -y python2.7 python-all-dev -RUN curl https://bootstrap.pypa.io/get-pip.py | python2.7 - -# Install python dependencies -RUN apt-get update && apt-get install -y \ - python-setuptools \ - python-pip - -# Add Debian 'testing' repository -RUN echo 'deb http://ftp.de.debian.org/debian testing main' >> /etc/apt/sources.list -RUN echo 'APT::Default-Release "stable";' | tee -a /etc/apt/apt.conf.d/00local - -# Install Python3 -RUN apt-get update && apt-get -t testing install -y \ - python3.5 \ - python3.6 \ - python3.7 \ - python3.8 \ - python3-all-dev - -RUN curl https://bootstrap.pypa.io/get-pip.py | python3.5 -RUN curl https://bootstrap.pypa.io/get-pip.py | python3.6 -RUN curl https://bootstrap.pypa.io/get-pip.py | python3.7 -RUN curl https://bootstrap.pypa.io/get-pip.py | python3.8 diff --git a/kokoro/linux/python27/build.sh b/kokoro/linux/python27/build.sh index 8c40ba3604..41531a15ef 100755 --- a/kokoro/linux/python27/build.sh +++ b/kokoro/linux/python27/build.sh @@ -11,7 +11,7 @@ cd $(dirname $0)/../../.. export DOCKERHUB_ORGANIZATION=protobuftesting -export DOCKERFILE_DIR=kokoro/linux/dockerfile/test/python_jessie +export DOCKERFILE_DIR=kokoro/linux/dockerfile/test/python27 export DOCKER_RUN_SCRIPT=kokoro/linux/pull_request_in_docker.sh export OUTPUT_DIR=testoutput export TEST_SET="python27" diff --git a/kokoro/linux/python27_cpp/build.sh b/kokoro/linux/python27_cpp/build.sh index 2ff09a21fd..1a972ee9f2 100755 --- a/kokoro/linux/python27_cpp/build.sh +++ b/kokoro/linux/python27_cpp/build.sh @@ -11,7 +11,7 @@ cd $(dirname $0)/../../.. export DOCKERHUB_ORGANIZATION=protobuftesting -export DOCKERFILE_DIR=kokoro/linux/dockerfile/test/python_jessie +export DOCKERFILE_DIR=kokoro/linux/dockerfile/test/python27 export DOCKER_RUN_SCRIPT=kokoro/linux/pull_request_in_docker.sh export OUTPUT_DIR=testoutput export TEST_SET="python27_cpp" diff --git a/kokoro/linux/python33/build.sh b/kokoro/linux/python33/build.sh deleted file mode 100755 index 84a9acdb73..0000000000 --- a/kokoro/linux/python33/build.sh +++ /dev/null @@ -1,18 +0,0 @@ -#!/bin/bash -# -# This is the top-level script we give to Kokoro as the entry point for -# running the "pull request" project: -# -# This script selects a specific Dockerfile (for building a Docker image) and -# a script to run inside that image. Then we delegate to the general -# build_and_run_docker.sh script. - -# Change to repo root -cd $(dirname $0)/../../.. - -export DOCKERHUB_ORGANIZATION=protobuftesting -export DOCKERFILE_DIR=kokoro/linux/dockerfile/test/python_jessie -export DOCKER_RUN_SCRIPT=kokoro/linux/pull_request_in_docker.sh -export OUTPUT_DIR=testoutput -export TEST_SET="python33" -./kokoro/linux/build_and_run_docker.sh diff --git a/kokoro/linux/python33/continuous.cfg b/kokoro/linux/python33/continuous.cfg deleted file mode 100644 index e2fc4136f0..0000000000 --- a/kokoro/linux/python33/continuous.cfg +++ /dev/null @@ -1,11 +0,0 @@ -# Config file for running tests in Kokoro - -# Location of the build script in repository -build_file: "protobuf/kokoro/linux/python/build.sh" -timeout_mins: 120 - -action { - define_artifacts { - regex: "**/sponge_log.xml" - } -} diff --git a/kokoro/linux/python33/presubmit.cfg b/kokoro/linux/python33/presubmit.cfg deleted file mode 100644 index e2fc4136f0..0000000000 --- a/kokoro/linux/python33/presubmit.cfg +++ /dev/null @@ -1,11 +0,0 @@ -# Config file for running tests in Kokoro - -# Location of the build script in repository -build_file: "protobuf/kokoro/linux/python/build.sh" -timeout_mins: 120 - -action { - define_artifacts { - regex: "**/sponge_log.xml" - } -} diff --git a/kokoro/linux/python33_cpp/build.sh b/kokoro/linux/python33_cpp/build.sh deleted file mode 100755 index ad33e89d25..0000000000 --- a/kokoro/linux/python33_cpp/build.sh +++ /dev/null @@ -1,18 +0,0 @@ -#!/bin/bash -# -# This is the top-level script we give to Kokoro as the entry point for -# running the "pull request" project: -# -# This script selects a specific Dockerfile (for building a Docker image) and -# a script to run inside that image. Then we delegate to the general -# build_and_run_docker.sh script. - -# Change to repo root -cd $(dirname $0)/../../.. - -export DOCKERHUB_ORGANIZATION=protobuftesting -export DOCKERFILE_DIR=kokoro/linux/dockerfile/test/python_jessie -export DOCKER_RUN_SCRIPT=kokoro/linux/pull_request_in_docker.sh -export OUTPUT_DIR=testoutput -export TEST_SET="python33_cpp" -./kokoro/linux/build_and_run_docker.sh diff --git a/kokoro/linux/python33_cpp/continuous.cfg b/kokoro/linux/python33_cpp/continuous.cfg deleted file mode 100644 index b1b0e550ff..0000000000 --- a/kokoro/linux/python33_cpp/continuous.cfg +++ /dev/null @@ -1,11 +0,0 @@ -# Config file for running tests in Kokoro - -# Location of the build script in repository -build_file: "protobuf/kokoro/linux/python_cpp/build.sh" -timeout_mins: 120 - -action { - define_artifacts { - regex: "**/sponge_log.xml" - } -} diff --git a/kokoro/linux/python33_cpp/presubmit.cfg b/kokoro/linux/python33_cpp/presubmit.cfg deleted file mode 100644 index b1b0e550ff..0000000000 --- a/kokoro/linux/python33_cpp/presubmit.cfg +++ /dev/null @@ -1,11 +0,0 @@ -# Config file for running tests in Kokoro - -# Location of the build script in repository -build_file: "protobuf/kokoro/linux/python_cpp/build.sh" -timeout_mins: 120 - -action { - define_artifacts { - regex: "**/sponge_log.xml" - } -} diff --git a/kokoro/linux/python34/build.sh b/kokoro/linux/python34/build.sh deleted file mode 100755 index 25dfd5dfcd..0000000000 --- a/kokoro/linux/python34/build.sh +++ /dev/null @@ -1,18 +0,0 @@ -#!/bin/bash -# -# This is the top-level script we give to Kokoro as the entry point for -# running the "pull request" project: -# -# This script selects a specific Dockerfile (for building a Docker image) and -# a script to run inside that image. Then we delegate to the general -# build_and_run_docker.sh script. - -# Change to repo root -cd $(dirname $0)/../../.. - -export DOCKERHUB_ORGANIZATION=protobuftesting -export DOCKERFILE_DIR=kokoro/linux/dockerfile/test/python_jessie -export DOCKER_RUN_SCRIPT=kokoro/linux/pull_request_in_docker.sh -export OUTPUT_DIR=testoutput -export TEST_SET="python34" -./kokoro/linux/build_and_run_docker.sh diff --git a/kokoro/linux/python34/continuous.cfg b/kokoro/linux/python34/continuous.cfg deleted file mode 100644 index e2fc4136f0..0000000000 --- a/kokoro/linux/python34/continuous.cfg +++ /dev/null @@ -1,11 +0,0 @@ -# Config file for running tests in Kokoro - -# Location of the build script in repository -build_file: "protobuf/kokoro/linux/python/build.sh" -timeout_mins: 120 - -action { - define_artifacts { - regex: "**/sponge_log.xml" - } -} diff --git a/kokoro/linux/python34/presubmit.cfg b/kokoro/linux/python34/presubmit.cfg deleted file mode 100644 index e2fc4136f0..0000000000 --- a/kokoro/linux/python34/presubmit.cfg +++ /dev/null @@ -1,11 +0,0 @@ -# Config file for running tests in Kokoro - -# Location of the build script in repository -build_file: "protobuf/kokoro/linux/python/build.sh" -timeout_mins: 120 - -action { - define_artifacts { - regex: "**/sponge_log.xml" - } -} diff --git a/kokoro/linux/python34_cpp/build.sh b/kokoro/linux/python34_cpp/build.sh deleted file mode 100755 index e4590ffbad..0000000000 --- a/kokoro/linux/python34_cpp/build.sh +++ /dev/null @@ -1,18 +0,0 @@ -#!/bin/bash -# -# This is the top-level script we give to Kokoro as the entry point for -# running the "pull request" project: -# -# This script selects a specific Dockerfile (for building a Docker image) and -# a script to run inside that image. Then we delegate to the general -# build_and_run_docker.sh script. - -# Change to repo root -cd $(dirname $0)/../../.. - -export DOCKERHUB_ORGANIZATION=protobuftesting -export DOCKERFILE_DIR=kokoro/linux/dockerfile/test/python_jessie -export DOCKER_RUN_SCRIPT=kokoro/linux/pull_request_in_docker.sh -export OUTPUT_DIR=testoutput -export TEST_SET="python34_cpp" -./kokoro/linux/build_and_run_docker.sh diff --git a/kokoro/linux/python34_cpp/continuous.cfg b/kokoro/linux/python34_cpp/continuous.cfg deleted file mode 100644 index b1b0e550ff..0000000000 --- a/kokoro/linux/python34_cpp/continuous.cfg +++ /dev/null @@ -1,11 +0,0 @@ -# Config file for running tests in Kokoro - -# Location of the build script in repository -build_file: "protobuf/kokoro/linux/python_cpp/build.sh" -timeout_mins: 120 - -action { - define_artifacts { - regex: "**/sponge_log.xml" - } -} diff --git a/kokoro/linux/python34_cpp/presubmit.cfg b/kokoro/linux/python34_cpp/presubmit.cfg deleted file mode 100644 index b1b0e550ff..0000000000 --- a/kokoro/linux/python34_cpp/presubmit.cfg +++ /dev/null @@ -1,11 +0,0 @@ -# Config file for running tests in Kokoro - -# Location of the build script in repository -build_file: "protobuf/kokoro/linux/python_cpp/build.sh" -timeout_mins: 120 - -action { - define_artifacts { - regex: "**/sponge_log.xml" - } -} diff --git a/kokoro/linux/python35/build.sh b/kokoro/linux/python35/build.sh index f978e2ad11..66ea03f036 100755 --- a/kokoro/linux/python35/build.sh +++ b/kokoro/linux/python35/build.sh @@ -11,7 +11,7 @@ cd $(dirname $0)/../../.. export DOCKERHUB_ORGANIZATION=protobuftesting -export DOCKERFILE_DIR=kokoro/linux/dockerfile/test/python_stretch +export DOCKERFILE_DIR=kokoro/linux/dockerfile/test/python35 export DOCKER_RUN_SCRIPT=kokoro/linux/pull_request_in_docker.sh export OUTPUT_DIR=testoutput export TEST_SET="python35" diff --git a/kokoro/linux/python35_cpp/build.sh b/kokoro/linux/python35_cpp/build.sh index 2a79246d59..4d0dbd4986 100755 --- a/kokoro/linux/python35_cpp/build.sh +++ b/kokoro/linux/python35_cpp/build.sh @@ -11,7 +11,7 @@ cd $(dirname $0)/../../.. export DOCKERHUB_ORGANIZATION=protobuftesting -export DOCKERFILE_DIR=kokoro/linux/dockerfile/test/python_stretch +export DOCKERFILE_DIR=kokoro/linux/dockerfile/test/python35 export DOCKER_RUN_SCRIPT=kokoro/linux/pull_request_in_docker.sh export OUTPUT_DIR=testoutput export TEST_SET="python35_cpp" diff --git a/kokoro/linux/python36/build.sh b/kokoro/linux/python36/build.sh index 633145bcec..a483efc302 100755 --- a/kokoro/linux/python36/build.sh +++ b/kokoro/linux/python36/build.sh @@ -11,7 +11,7 @@ cd $(dirname $0)/../../.. export DOCKERHUB_ORGANIZATION=protobuftesting -export DOCKERFILE_DIR=kokoro/linux/dockerfile/test/python_stretch +export DOCKERFILE_DIR=kokoro/linux/dockerfile/test/python36 export DOCKER_RUN_SCRIPT=kokoro/linux/pull_request_in_docker.sh export OUTPUT_DIR=testoutput export TEST_SET="python36" diff --git a/kokoro/linux/python36_cpp/build.sh b/kokoro/linux/python36_cpp/build.sh index 8e120ff37c..eb71bda92c 100755 --- a/kokoro/linux/python36_cpp/build.sh +++ b/kokoro/linux/python36_cpp/build.sh @@ -11,7 +11,7 @@ cd $(dirname $0)/../../.. export DOCKERHUB_ORGANIZATION=protobuftesting -export DOCKERFILE_DIR=kokoro/linux/dockerfile/test/python_stretch +export DOCKERFILE_DIR=kokoro/linux/dockerfile/test/python36 export DOCKER_RUN_SCRIPT=kokoro/linux/pull_request_in_docker.sh export OUTPUT_DIR=testoutput export TEST_SET="python36_cpp" diff --git a/kokoro/linux/python37/build.sh b/kokoro/linux/python37/build.sh index 554aa09448..2117a271ce 100755 --- a/kokoro/linux/python37/build.sh +++ b/kokoro/linux/python37/build.sh @@ -11,7 +11,7 @@ cd $(dirname $0)/../../.. export DOCKERHUB_ORGANIZATION=protobuftesting -export DOCKERFILE_DIR=kokoro/linux/dockerfile/test/python_stretch +export DOCKERFILE_DIR=kokoro/linux/dockerfile/test/python37 export DOCKER_RUN_SCRIPT=kokoro/linux/pull_request_in_docker.sh export OUTPUT_DIR=testoutput export TEST_SET="python37" diff --git a/kokoro/linux/python37_cpp/build.sh b/kokoro/linux/python37_cpp/build.sh index 8fdc8f9339..3126b481e3 100755 --- a/kokoro/linux/python37_cpp/build.sh +++ b/kokoro/linux/python37_cpp/build.sh @@ -11,7 +11,7 @@ cd $(dirname $0)/../../.. export DOCKERHUB_ORGANIZATION=protobuftesting -export DOCKERFILE_DIR=kokoro/linux/dockerfile/test/python_stretch +export DOCKERFILE_DIR=kokoro/linux/dockerfile/test/python37 export DOCKER_RUN_SCRIPT=kokoro/linux/pull_request_in_docker.sh export OUTPUT_DIR=testoutput export TEST_SET="python37_cpp" diff --git a/kokoro/linux/python38/build.sh b/kokoro/linux/python38/build.sh index 9609939a48..299c7ba6f3 100755 --- a/kokoro/linux/python38/build.sh +++ b/kokoro/linux/python38/build.sh @@ -11,7 +11,7 @@ cd $(dirname $0)/../../.. export DOCKERHUB_ORGANIZATION=protobuftesting -export DOCKERFILE_DIR=kokoro/linux/dockerfile/test/python_stretch +export DOCKERFILE_DIR=kokoro/linux/dockerfile/test/python38 export DOCKER_RUN_SCRIPT=kokoro/linux/pull_request_in_docker.sh export OUTPUT_DIR=testoutput export TEST_SET="python38" diff --git a/kokoro/linux/python38_cpp/build.sh b/kokoro/linux/python38_cpp/build.sh index c5cd6eeb42..b43859b988 100755 --- a/kokoro/linux/python38_cpp/build.sh +++ b/kokoro/linux/python38_cpp/build.sh @@ -11,7 +11,7 @@ cd $(dirname $0)/../../.. export DOCKERHUB_ORGANIZATION=protobuftesting -export DOCKERFILE_DIR=kokoro/linux/dockerfile/test/python_stretch +export DOCKERFILE_DIR=kokoro/linux/dockerfile/test/python38 export DOCKER_RUN_SCRIPT=kokoro/linux/pull_request_in_docker.sh export OUTPUT_DIR=testoutput export TEST_SET="python38_cpp" From a8a400da5d99abb8bddbd21b46f712c45c2b6f78 Mon Sep 17 00:00:00 2001 From: Thomas Van Lenten Date: Mon, 20 Apr 2020 10:45:55 -0400 Subject: [PATCH 15/38] Move to constexpr. --- .../compiler/objectivec/objectivec_helpers.cc | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc b/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc index 638d7b70c9..df11689f61 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc +++ b/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc @@ -1301,14 +1301,14 @@ class DecodeDataBuilder { } private: - static const uint8 kAddUnderscore = 0x80; + static constexpr uint8 kAddUnderscore = 0x80; - static const uint8 kOpAsIs = 0x00; - static const uint8 kOpFirstUpper = 0x40; - static const uint8 kOpFirstLower = 0x20; - static const uint8 kOpAllUpper = 0x60; + static constexpr uint8 kOpAsIs = 0x00; + static constexpr uint8 kOpFirstUpper = 0x40; + static constexpr uint8 kOpFirstLower = 0x20; + static constexpr uint8 kOpAllUpper = 0x60; - static const int kMaxSegmentLen = 0x1f; + static constexpr int kMaxSegmentLen = 0x1f; void AddChar(const char desired) { ++segment_len_; From 18950451c7bfb1497f1deaf1c3868e79e332d80a Mon Sep 17 00:00:00 2001 From: Joshua Haberman Date: Mon, 20 Apr 2020 15:51:05 -0700 Subject: [PATCH 16/38] Ruby: assigning 'nil' to submessage should clear the field. (#7397) Previously if you assigned 'nil' to a submessage in proto2 the field would be set to 'nil' but would still have its hasbit set. This was a clear bug so I'm fixing it outright, even though it is an observable behavior change. --- ruby/ext/google/protobuf_c/message.c | 16 +++++++---- ruby/ext/google/protobuf_c/storage.c | 42 ++++++++++++++++++++-------- ruby/tests/basic_proto2.rb | 11 ++++++++ 3 files changed, 52 insertions(+), 17 deletions(-) diff --git a/ruby/ext/google/protobuf_c/message.c b/ruby/ext/google/protobuf_c/message.c index f57501cc65..db5d856d75 100644 --- a/ruby/ext/google/protobuf_c/message.c +++ b/ruby/ext/google/protobuf_c/message.c @@ -608,6 +608,12 @@ VALUE Message_to_h(VALUE _self) { VALUE hash; upb_msg_field_iter it; TypedData_Get_Struct(_self, MessageHeader, &Message_type, self); + // We currently have a few behaviors that are specific to proto2. + // This is unfortunate, we should key behaviors off field attributes (like + // whether a field has presence), not proto2 vs. proto3. We should see if we + // can change this without breaking users. + bool is_proto2 = + upb_msgdef_syntax(self->descriptor->msgdef) == UPB_SYNTAX_PROTO2; hash = rb_hash_new(); @@ -618,10 +624,9 @@ VALUE Message_to_h(VALUE _self) { VALUE msg_value; VALUE msg_key; - // For proto2, do not include fields which are not set. - if (upb_msgdef_syntax(self->descriptor->msgdef) == UPB_SYNTAX_PROTO2 && - field_contains_hasbit(self->descriptor->layout, field) && - !layout_has(self->descriptor->layout, Message_data(self), field)) { + // Do not include fields that are not present (oneof or optional fields). + if (is_proto2 && upb_fielddef_haspresence(field) && + !layout_has(self->descriptor->layout, Message_data(self), field)) { continue; } @@ -631,8 +636,7 @@ VALUE Message_to_h(VALUE _self) { msg_value = Map_to_h(msg_value); } else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) { msg_value = RepeatedField_to_ary(msg_value); - if (upb_msgdef_syntax(self->descriptor->msgdef) == UPB_SYNTAX_PROTO2 && - RARRAY_LEN(msg_value) == 0) { + if (is_proto2 && RARRAY_LEN(msg_value) == 0) { continue; } diff --git a/ruby/ext/google/protobuf_c/storage.c b/ruby/ext/google/protobuf_c/storage.c index 739c0a7765..56f9521669 100644 --- a/ruby/ext/google/protobuf_c/storage.c +++ b/ruby/ext/google/protobuf_c/storage.c @@ -517,7 +517,8 @@ void create_layout(Descriptor* desc) { !upb_msg_field_done(&it); upb_msg_field_next(&it)) { const upb_fielddef* field = upb_msg_iter_field(&it); - if (upb_fielddef_haspresence(field)) { + if (upb_fielddef_haspresence(field) && + !upb_fielddef_containingoneof(field)) { layout->fields[upb_fielddef_index(field)].hasbit = hasbit++; } else { layout->fields[upb_fielddef_index(field)].hasbit = @@ -724,11 +725,8 @@ static void slot_clear_hasbit(MessageLayout* layout, static bool slot_is_hasbit_set(MessageLayout* layout, const void* storage, const upb_fielddef* field) { + assert(field_contains_hasbit(layout, field)); size_t hasbit = layout->fields[upb_fielddef_index(field)].hasbit; - if (hasbit == MESSAGE_FIELD_NO_HASBIT) { - return false; - } - return DEREF_OFFSET( (uint8_t*)storage, hasbit / 8, char) & (1 << (hasbit % 8)); } @@ -736,8 +734,14 @@ static bool slot_is_hasbit_set(MessageLayout* layout, VALUE layout_has(MessageLayout* layout, const void* storage, const upb_fielddef* field) { - assert(field_contains_hasbit(layout, field)); - return slot_is_hasbit_set(layout, storage, field) ? Qtrue : Qfalse; + assert(upb_fielddef_haspresence(field)); + const upb_oneofdef* oneof = upb_fielddef_containingoneof(field); + if (oneof) { + uint32_t oneof_case = slot_read_oneof_case(layout, storage, oneof); + return oneof_case == upb_fielddef_number(field); + } else { + return slot_is_hasbit_set(layout, storage, field) ? Qtrue : Qfalse; + } } void layout_clear(MessageLayout* layout, @@ -953,7 +957,16 @@ void layout_set(MessageLayout* layout, if (layout->fields[upb_fielddef_index(field)].hasbit != MESSAGE_FIELD_NO_HASBIT) { - slot_set_hasbit(layout, storage, field); + if (val == Qnil) { + // No other field type has a hasbit and allows nil assignment. + if (upb_fielddef_type(field) != UPB_TYPE_MESSAGE) { + fprintf(stderr, "field: %s\n", upb_fielddef_fullname(field)); + } + assert(upb_fielddef_type(field) == UPB_TYPE_MESSAGE); + slot_clear_hasbit(layout, storage, field); + } else { + slot_set_hasbit(layout, storage, field); + } } } @@ -1095,9 +1108,16 @@ VALUE layout_eq(MessageLayout* layout, void* msg1, void* msg2) { return Qfalse; } } else { - if (slot_is_hasbit_set(layout, msg1, field) != - slot_is_hasbit_set(layout, msg2, field) || - !native_slot_eq(upb_fielddef_type(field), + if (field_contains_hasbit(layout, field) && + slot_is_hasbit_set(layout, msg1, field) != + slot_is_hasbit_set(layout, msg2, field)) { + // TODO(haberman): I don't think we should actually care about hasbits + // here: an unset default should be able to equal a set default. But we + // can address this later (will also have to make sure defaults are + // being properly set when hasbit is clear). + return Qfalse; + } + if (!native_slot_eq(upb_fielddef_type(field), field_type_class(layout, field), msg1_memory, msg2_memory)) { return Qfalse; diff --git a/ruby/tests/basic_proto2.rb b/ruby/tests/basic_proto2.rb index 4c7ddd55b9..986a31b229 100755 --- a/ruby/tests/basic_proto2.rb +++ b/ruby/tests/basic_proto2.rb @@ -197,6 +197,17 @@ module BasicTestProto2 assert !m.has_my_oneof? end + def test_assign_nil + m = TestMessageDefaults.new + m.optional_msg = TestMessage2.new(:foo => 42) + + assert_equal TestMessage2.new(:foo => 42), m.optional_msg + assert m.has_optional_msg? + m.optional_msg = nil + assert_equal nil, m.optional_msg + assert !m.has_optional_msg? + end + def test_initialization_map_errors e = assert_raise ArgumentError do TestMessage.new(:hello => "world") From c953182fa92f1633faa098d0aff514ed84454522 Mon Sep 17 00:00:00 2001 From: "David L. Jones" Date: Wed, 22 Apr 2020 21:41:12 -0700 Subject: [PATCH 17/38] Generate documentation for internal.container. (#7294) Since our (public) generated APIs document their use of repeated fields, we should probably document its API, too. This includes some changes to generate_docs.py to explicitly allow named modules, since the repeated field implementation lives in the "internal" tree. --- python/docs/generate_docs.py | 35 ++++++++++++++----- .../google/protobuf/internal/containers.rst | 21 +++++++++++ python/docs/index.rst | 1 + 3 files changed, 49 insertions(+), 8 deletions(-) create mode 100644 python/docs/google/protobuf/internal/containers.rst diff --git a/python/docs/generate_docs.py b/python/docs/generate_docs.py index 07debedd18..e024aaa479 100755 --- a/python/docs/generate_docs.py +++ b/python/docs/generate_docs.py @@ -67,12 +67,22 @@ DOCS_DIR = pathlib.Path(__file__).parent.resolve() PYTHON_DIR = DOCS_DIR.parent SOURCE_DIR = PYTHON_DIR / "google" / "protobuf" SOURCE_POSIX = SOURCE_DIR.as_posix() + +# Modules which are always included: +INCLUDED_MODULES = ( + "google.protobuf.internal.containers", +) + +# Packages to ignore, including all modules (unless in INCLUDED_MODULES): IGNORED_PACKAGES = ( "compiler", + "docs", "internal", "pyext", "util", ) + +# Ignored module stems in all packages (unless in INCLUDED_MODULES): IGNORED_MODULES = ( "any_test_pb2", "api_pb2", @@ -81,6 +91,7 @@ IGNORED_MODULES = ( "test_messages_proto3_pb2", "test_messages_proto2", ) + TOC_REGEX = re.compile( r"\.\. START REFTOC.*\.\. END REFTOC\.\n", flags=re.DOTALL, @@ -120,20 +131,28 @@ AUTOMODULE_TEMPLATE = """.. DO NOT EDIT, generated by generate_docs.py. def find_modules(): modules = [] for module_path in SOURCE_DIR.glob("**/*.py"): - package_posix = module_path.parent.as_posix() - if any(ignored in package_posix for ignored in IGNORED_PACKAGES): + # Determine the (dotted) relative package and module names. + package_path = module_path.parent.relative_to(PYTHON_DIR) + if package_path == SOURCE_DIR: + package_name = "" + module_name = module_path.stem + else: + package_name = package_path.as_posix().replace("/", ".") + module_name = package_name + "." + module_path.stem + + # Filter: first, accept anything in the whitelist; then, reject anything + # at package level, then module name level. + if any(include == module_name for include in INCLUDED_MODULES): + pass + elif any(ignored in package_name for ignored in IGNORED_PACKAGES): continue - if any(ignored in module_path.stem for ignored in IGNORED_MODULES): + elif any(ignored in module_path.stem for ignored in IGNORED_MODULES): continue - package_name = "google.protobuf{}".format( - package_posix[len(SOURCE_POSIX) :].replace("/", ".") - ) if module_path.name == "__init__.py": modules.append(package_name) else: - module_name = module_path.stem - modules.append("{}.{}".format(package_name, module_name)) + modules.append(module_name) return modules diff --git a/python/docs/google/protobuf/internal/containers.rst b/python/docs/google/protobuf/internal/containers.rst new file mode 100644 index 0000000000..c3b8e594a7 --- /dev/null +++ b/python/docs/google/protobuf/internal/containers.rst @@ -0,0 +1,21 @@ +.. DO NOT EDIT, generated by generate_docs.py. + +.. ifconfig:: build_env == 'readthedocs' + + .. warning:: + + You are reading the documentation for the `latest committed changes + `_ of + the `Protocol Buffers package for Python + `_. + Some features may not yet be released. Read the documentation for the + latest released package at `googleapis.dev + `_. + +google.protobuf.internal.containers +=================================== + +.. automodule:: google.protobuf.internal.containers + :members: + :inherited-members: + :undoc-members: diff --git a/python/docs/index.rst b/python/docs/index.rst index 57f7ce70ce..5535b398a9 100644 --- a/python/docs/index.rst +++ b/python/docs/index.rst @@ -38,6 +38,7 @@ Modules and Packages google/protobuf/duration_pb2 google/protobuf/empty_pb2 google/protobuf/field_mask_pb2 + google/protobuf/internal/containers google/protobuf/json_format google/protobuf/message google/protobuf/message_factory From 94afb8ab36032762210d2100b9a10f8cf1fdc856 Mon Sep 17 00:00:00 2001 From: "David L. Jones" Date: Thu, 23 Apr 2020 12:49:04 -0700 Subject: [PATCH 18/38] Add Ruby tests for oneof cases. (#7385) In Ruby, the oneof case returns a symbol with the name of the field that is set. These were not previously tested. --- ruby/tests/basic.rb | 1 + ruby/tests/basic_proto2.rb | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/ruby/tests/basic.rb b/ruby/tests/basic.rb index d1a66a6169..321b63fa6c 100755 --- a/ruby/tests/basic.rb +++ b/ruby/tests/basic.rb @@ -128,6 +128,7 @@ module BasicTest m.a = "foo" assert_equal "foo", m.a assert m.has_my_oneof? + assert_equal :a, m.my_oneof m.clear_a assert !m.has_my_oneof? diff --git a/ruby/tests/basic_proto2.rb b/ruby/tests/basic_proto2.rb index 986a31b229..2d30a08944 100755 --- a/ruby/tests/basic_proto2.rb +++ b/ruby/tests/basic_proto2.rb @@ -73,10 +73,11 @@ module BasicTestProto2 m = OneofMessage.new assert !m.has_my_oneof? m.a = "foo" + assert m.has_my_oneof? + assert_equal :a, m.my_oneof assert m.has_a? assert OneofMessage.descriptor.lookup('a').has?(m) assert_equal "foo", m.a - assert m.has_my_oneof? assert !m.has_b? assert !OneofMessage.descriptor.lookup('b').has?(m) assert !m.has_c? From 6b759688a1656e93da5776d94d018c85339c7b07 Mon Sep 17 00:00:00 2001 From: Joshua Haberman Date: Thu, 23 Apr 2020 12:54:25 -0700 Subject: [PATCH 19/38] Implemented proto3 presence for Ruby. (#7406) * WIP. * WIP. * Builds and runs. Tests need to be updated to test presence. * Ruby: proto3 presence is passing all tests. * Fixed a bug where empty messages has the wrong oneof count. --- ruby/Rakefile | 2 +- ruby/ext/google/protobuf_c/defs.c | 100 ++- ruby/ext/google/protobuf_c/encode_decode.c | 6 +- ruby/ext/google/protobuf_c/message.c | 19 +- ruby/ext/google/protobuf_c/protobuf.h | 1 + ruby/ext/google/protobuf_c/storage.c | 61 +- ruby/ext/google/protobuf_c/upb.c | 71 +- ruby/ext/google/protobuf_c/upb.h | 739 +----------------- ruby/tests/basic.rb | 113 +-- ruby/tests/basic_test.proto | 36 +- .../protobuf/compiler/ruby/ruby_generator.cc | 8 +- .../protobuf/compiler/ruby/ruby_generator.h | 11 +- 12 files changed, 336 insertions(+), 831 deletions(-) diff --git a/ruby/Rakefile b/ruby/Rakefile index b0b803dd65..2aa7743e20 100644 --- a/ruby/Rakefile +++ b/ruby/Rakefile @@ -124,7 +124,7 @@ file "tests/test_ruby_package_proto2.rb" => "tests/test_ruby_package_proto2.prot end file "tests/basic_test.rb" => "tests/basic_test.proto" do |file_task| - sh "../src/protoc -I../src -I. --ruby_out=. tests/basic_test.proto" + sh "../src/protoc --experimental_allow_proto3_optional -I../src -I. --ruby_out=. tests/basic_test.proto" end file "tests/basic_test_proto2.rb" => "tests/basic_test_proto2.proto" do |file_task| diff --git a/ruby/ext/google/protobuf_c/defs.c b/ruby/ext/google/protobuf_c/defs.c index babdfa9711..1a09cc5ffb 100644 --- a/ruby/ext/google/protobuf_c/defs.c +++ b/ruby/ext/google/protobuf_c/defs.c @@ -1100,7 +1100,7 @@ VALUE FieldDescriptor_get(VALUE _self, VALUE msg_rb) { * FieldDescriptor.has?(message) => boolean * * Returns whether the value is set on the given message. Raises an - * exception when calling with proto syntax 3. + * exception when calling for fields that do not have presence. */ VALUE FieldDescriptor_has(VALUE _self, VALUE msg_rb) { DEFINE_SELF(FieldDescriptor, self, _self); @@ -1434,6 +1434,7 @@ void MessageBuilderContext_register(VALUE module) { rb_define_method(klass, "initialize", MessageBuilderContext_initialize, 2); rb_define_method(klass, "optional", MessageBuilderContext_optional, -1); + rb_define_method(klass, "proto3_optional", MessageBuilderContext_proto3_optional, -1); rb_define_method(klass, "required", MessageBuilderContext_required, -1); rb_define_method(klass, "repeated", MessageBuilderContext_repeated, -1); rb_define_method(klass, "map", MessageBuilderContext_map, -1); @@ -1469,7 +1470,8 @@ VALUE MessageBuilderContext_initialize(VALUE _self, static void msgdef_add_field(VALUE msgbuilder_rb, upb_label_t label, VALUE name, VALUE type, VALUE number, VALUE type_class, - VALUE options, int oneof_index) { + VALUE options, int oneof_index, + bool proto3_optional) { DEFINE_SELF(MessageBuilderContext, self, msgbuilder_rb); FileBuilderContext* file_context = ruby_to_FileBuilderContext(self->file_builder); @@ -1489,6 +1491,10 @@ static void msgdef_add_field(VALUE msgbuilder_rb, upb_label_t label, VALUE name, google_protobuf_FieldDescriptorProto_set_type( field_proto, (int)ruby_to_descriptortype(type)); + if (proto3_optional) { + google_protobuf_FieldDescriptorProto_set_proto3_optional(field_proto, true); + } + if (type_class != Qnil) { Check_Type(type_class, T_STRING); @@ -1574,7 +1580,38 @@ VALUE MessageBuilderContext_optional(int argc, VALUE* argv, VALUE _self) { } msgdef_add_field(_self, UPB_LABEL_OPTIONAL, name, type, number, type_class, - options, -1); + options, -1, false); + + return Qnil; +} + +/* + * call-seq: + * MessageBuilderContext.proto3_optional(name, type, number, + * type_class = nil, options = nil) + * + * Defines a true proto3 optional field (that tracks presence) on this message + * type with the given type, tag number, and type class (for message and enum + * fields). The type must be a Ruby symbol (as accepted by + * FieldDescriptor#type=) and the type_class must be a string, if present (as + * accepted by FieldDescriptor#submsg_name=). + */ +VALUE MessageBuilderContext_proto3_optional(int argc, VALUE* argv, + VALUE _self) { + VALUE name, type, number; + VALUE type_class, options = Qnil; + + rb_scan_args(argc, argv, "32", &name, &type, &number, &type_class, &options); + + // Allow passing (name, type, number, options) or + // (name, type, number, type_class, options) + if (argc == 4 && RB_TYPE_P(type_class, T_HASH)) { + options = type_class; + type_class = Qnil; + } + + msgdef_add_field(_self, UPB_LABEL_OPTIONAL, name, type, number, type_class, + options, -1, true); return Qnil; } @@ -1607,7 +1644,7 @@ VALUE MessageBuilderContext_required(int argc, VALUE* argv, VALUE _self) { } msgdef_add_field(_self, UPB_LABEL_REQUIRED, name, type, number, type_class, - options, -1); + options, -1, false); return Qnil; } @@ -1633,7 +1670,7 @@ VALUE MessageBuilderContext_repeated(int argc, VALUE* argv, VALUE _self) { type_class = (argc > 3) ? argv[3] : Qnil; msgdef_add_field(_self, UPB_LABEL_REPEATED, name, type, number, type_class, - Qnil, -1); + Qnil, -1, false); return Qnil; } @@ -1758,6 +1795,56 @@ VALUE MessageBuilderContext_oneof(VALUE _self, VALUE name) { return Qnil; } +void MessageBuilderContext_add_synthetic_oneofs(VALUE _self) { + DEFINE_SELF(MessageBuilderContext, self, _self); + FileBuilderContext* file_context = + ruby_to_FileBuilderContext(self->file_builder); + size_t field_count, oneof_count; + google_protobuf_FieldDescriptorProto** fields = + google_protobuf_DescriptorProto_mutable_field(self->msg_proto, &field_count); + const google_protobuf_OneofDescriptorProto*const* oneofs = + google_protobuf_DescriptorProto_oneof_decl(self->msg_proto, &oneof_count); + VALUE names = rb_hash_new(); + VALUE underscore = rb_str_new2("_"); + size_t i; + + // We have to build a set of all names, to ensure that synthetic oneofs are + // not creating conflicts. + for (i = 0; i < field_count; i++) { + upb_strview name = google_protobuf_FieldDescriptorProto_name(fields[i]); + rb_hash_aset(names, rb_str_new(name.data, name.size), Qtrue); + } + for (i = 0; i < oneof_count; i++) { + upb_strview name = google_protobuf_OneofDescriptorProto_name(oneofs[i]); + rb_hash_aset(names, rb_str_new(name.data, name.size), Qtrue); + } + + for (i = 0; i < field_count; i++) { + google_protobuf_OneofDescriptorProto* oneof_proto; + VALUE oneof_name; + upb_strview field_name; + + if (!google_protobuf_FieldDescriptorProto_proto3_optional(fields[i])) { + continue; + } + + // Prepend '_' until we are no longer conflicting. + field_name = google_protobuf_FieldDescriptorProto_name(fields[i]); + oneof_name = rb_str_new(field_name.data, field_name.size); + while (rb_hash_lookup(names, oneof_name) != Qnil) { + oneof_name = rb_str_plus(underscore, oneof_name); + } + + rb_hash_aset(names, oneof_name, Qtrue); + google_protobuf_FieldDescriptorProto_set_oneof_index(fields[i], + oneof_count++); + oneof_proto = google_protobuf_DescriptorProto_add_oneof_decl( + self->msg_proto, file_context->arena); + google_protobuf_OneofDescriptorProto_set_name( + oneof_proto, FileBuilderContext_strdup(self->file_builder, oneof_name)); + } +} + // ----------------------------------------------------------------------------- // OneofBuilderContext. // ----------------------------------------------------------------------------- @@ -1829,7 +1916,7 @@ VALUE OneofBuilderContext_optional(int argc, VALUE* argv, VALUE _self) { rb_scan_args(argc, argv, "32", &name, &type, &number, &type_class, &options); msgdef_add_field(self->message_builder, UPB_LABEL_OPTIONAL, name, type, - number, type_class, options, self->oneof_index); + number, type_class, options, self->oneof_index, false); return Qnil; } @@ -2033,6 +2120,7 @@ VALUE FileBuilderContext_add_message(VALUE _self, VALUE name) { VALUE ctx = rb_class_new_instance(2, args, cMessageBuilderContext); VALUE block = rb_block_proc(); rb_funcall_with_block(ctx, rb_intern("instance_eval"), 0, NULL, block); + MessageBuilderContext_add_synthetic_oneofs(ctx); return Qnil; } diff --git a/ruby/ext/google/protobuf_c/encode_decode.c b/ruby/ext/google/protobuf_c/encode_decode.c index 4a1d724d8f..a58a5d2f84 100644 --- a/ruby/ext/google/protobuf_c/encode_decode.c +++ b/ruby/ext/google/protobuf_c/encode_decode.c @@ -933,7 +933,7 @@ void add_handlers_for_message(const void *closure, upb_handlers *h) { !upb_msg_field_done(&i); upb_msg_field_next(&i)) { const upb_fielddef *f = upb_msg_iter_field(&i); - const upb_oneofdef *oneof = upb_fielddef_containingoneof(f); + const upb_oneofdef* oneof = upb_fielddef_realcontainingoneof(f); size_t offset = get_field_offset(desc->layout, f); if (oneof) { @@ -1506,7 +1506,7 @@ static void putmsg(VALUE msg_rb, const Descriptor* desc, !upb_msg_field_done(&i); upb_msg_field_next(&i)) { upb_fielddef *f = upb_msg_iter_field(&i); - const upb_oneofdef *oneof = upb_fielddef_containingoneof(f); + const upb_oneofdef* oneof = upb_fielddef_realcontainingoneof(f); bool is_matching_oneof = false; uint32_t offset = desc->layout->fields[upb_fielddef_index(f)].offset + @@ -1714,7 +1714,7 @@ static void discard_unknown(VALUE msg_rb, const Descriptor* desc) { !upb_msg_field_done(&it); upb_msg_field_next(&it)) { upb_fielddef *f = upb_msg_iter_field(&it); - const upb_oneofdef *oneof = upb_fielddef_containingoneof(f); + const upb_oneofdef* oneof = upb_fielddef_realcontainingoneof(f); uint32_t offset = desc->layout->fields[upb_fielddef_index(f)].offset + sizeof(MessageHeader); diff --git a/ruby/ext/google/protobuf_c/message.c b/ruby/ext/google/protobuf_c/message.c index db5d856d75..0050506d3b 100644 --- a/ruby/ext/google/protobuf_c/message.c +++ b/ruby/ext/google/protobuf_c/message.c @@ -242,9 +242,14 @@ static int extract_method_call(VALUE method_name, MessageHeader* self, // Method calls like 'has_foo?' are not allowed if field "foo" does not have // a hasbit (e.g. repeated fields or non-message type fields for proto3 // syntax). - if (accessor_type == METHOD_PRESENCE && test_f != NULL && - !upb_fielddef_haspresence(test_f)) { - return METHOD_UNKNOWN; + if (accessor_type == METHOD_PRESENCE && test_f != NULL) { + if (!upb_fielddef_haspresence(test_f)) return METHOD_UNKNOWN; + + // TODO(haberman): remove this case, allow for proto3 oneofs. + if (upb_fielddef_realcontainingoneof(test_f) && + upb_filedef_syntax(upb_fielddef_file(test_f)) == UPB_SYNTAX_PROTO3) { + return METHOD_UNKNOWN; + } } *o = test_o; @@ -605,18 +610,18 @@ VALUE Message_inspect(VALUE _self) { */ VALUE Message_to_h(VALUE _self) { MessageHeader* self; - VALUE hash; + VALUE hash = rb_hash_new(); upb_msg_field_iter it; + bool is_proto2; TypedData_Get_Struct(_self, MessageHeader, &Message_type, self); + // We currently have a few behaviors that are specific to proto2. // This is unfortunate, we should key behaviors off field attributes (like // whether a field has presence), not proto2 vs. proto3. We should see if we // can change this without breaking users. - bool is_proto2 = + is_proto2 = upb_msgdef_syntax(self->descriptor->msgdef) == UPB_SYNTAX_PROTO2; - hash = rb_hash_new(); - for (upb_msg_field_begin(&it, self->descriptor->msgdef); !upb_msg_field_done(&it); upb_msg_field_next(&it)) { diff --git a/ruby/ext/google/protobuf_c/protobuf.h b/ruby/ext/google/protobuf_c/protobuf.h index ae9895c537..0ec78fc4fb 100644 --- a/ruby/ext/google/protobuf_c/protobuf.h +++ b/ruby/ext/google/protobuf_c/protobuf.h @@ -285,6 +285,7 @@ VALUE MessageBuilderContext_initialize(VALUE _self, VALUE _file_builder, VALUE name); VALUE MessageBuilderContext_optional(int argc, VALUE* argv, VALUE _self); +VALUE MessageBuilderContext_proto3_optional(int argc, VALUE* argv, VALUE _self); VALUE MessageBuilderContext_required(int argc, VALUE* argv, VALUE _self); VALUE MessageBuilderContext_repeated(int argc, VALUE* argv, VALUE _self); VALUE MessageBuilderContext_map(int argc, VALUE* argv, VALUE _self); diff --git a/ruby/ext/google/protobuf_c/storage.c b/ruby/ext/google/protobuf_c/storage.c index 56f9521669..a3805c96a3 100644 --- a/ruby/ext/google/protobuf_c/storage.c +++ b/ruby/ext/google/protobuf_c/storage.c @@ -496,11 +496,14 @@ void create_layout(Descriptor* desc) { const upb_msgdef *msgdef = desc->msgdef; MessageLayout* layout = ALLOC(MessageLayout); int nfields = upb_msgdef_numfields(msgdef); - int noneofs = upb_msgdef_numoneofs(msgdef); + int noneofs = upb_msgdef_numrealoneofs(msgdef); upb_msg_field_iter it; upb_msg_oneof_iter oit; size_t off = 0; size_t hasbit = 0; + int i; + + (void)i; layout->empty_template = NULL; layout->desc = desc; @@ -513,12 +516,22 @@ void create_layout(Descriptor* desc) { layout->oneofs = ALLOC_N(MessageOneof, noneofs); } +#ifndef NDEBUG + for (i = 0; i < nfields; i++) { + layout->fields[i].offset = -1; + } + + for (i = 0; i < noneofs; i++) { + layout->oneofs[i].offset = -1; + } +#endif + for (upb_msg_field_begin(&it, msgdef); !upb_msg_field_done(&it); upb_msg_field_next(&it)) { const upb_fielddef* field = upb_msg_iter_field(&it); if (upb_fielddef_haspresence(field) && - !upb_fielddef_containingoneof(field)) { + !upb_fielddef_realcontainingoneof(field)) { layout->fields[upb_fielddef_index(field)].hasbit = hasbit++; } else { layout->fields[upb_fielddef_index(field)].hasbit = @@ -541,7 +554,7 @@ void create_layout(Descriptor* desc) { !upb_msg_field_done(&it); upb_msg_field_next(&it)) { const upb_fielddef* field = upb_msg_iter_field(&it); - if (upb_fielddef_containingoneof(field) || !upb_fielddef_isseq(field) || + if (upb_fielddef_realcontainingoneof(field) || !upb_fielddef_isseq(field) || upb_fielddef_ismap(field)) { continue; } @@ -556,7 +569,7 @@ void create_layout(Descriptor* desc) { !upb_msg_field_done(&it); upb_msg_field_next(&it)) { const upb_fielddef* field = upb_msg_iter_field(&it); - if (upb_fielddef_containingoneof(field) || !upb_fielddef_isseq(field) || + if (upb_fielddef_realcontainingoneof(field) || !upb_fielddef_isseq(field) || !upb_fielddef_ismap(field)) { continue; } @@ -573,7 +586,7 @@ void create_layout(Descriptor* desc) { !upb_msg_field_done(&it); upb_msg_field_next(&it)) { const upb_fielddef* field = upb_msg_iter_field(&it); - if (upb_fielddef_containingoneof(field) || !is_value_field(field) || + if (upb_fielddef_realcontainingoneof(field) || !is_value_field(field) || upb_fielddef_isseq(field)) { continue; } @@ -590,7 +603,7 @@ void create_layout(Descriptor* desc) { const upb_fielddef* field = upb_msg_iter_field(&it); size_t field_size; - if (upb_fielddef_containingoneof(field) || is_value_field(field)) { + if (upb_fielddef_realcontainingoneof(field) || is_value_field(field)) { continue; } @@ -625,6 +638,10 @@ void create_layout(Descriptor* desc) { // Always allocate NATIVE_SLOT_MAX_SIZE bytes, but share the slot between // all fields. size_t field_size = NATIVE_SLOT_MAX_SIZE; + + if (upb_oneofdef_issynthetic(oneof)) continue; + assert(upb_oneofdef_index(oneof) < noneofs); + // Align the offset. off = align_up_to(off, field_size); // Assign all fields in the oneof this same offset. @@ -644,6 +661,8 @@ void create_layout(Descriptor* desc) { upb_msg_oneof_next(&oit)) { const upb_oneofdef* oneof = upb_msg_iter_oneof(&oit); size_t field_size = sizeof(uint32_t); + if (upb_oneofdef_issynthetic(oneof)) continue; + assert(upb_oneofdef_index(oneof) < noneofs); // Align the offset. off = (off + field_size - 1) & ~(field_size - 1); layout->oneofs[upb_oneofdef_index(oneof)].case_offset = off; @@ -653,6 +672,16 @@ void create_layout(Descriptor* desc) { layout->size = off; layout->msgdef = msgdef; +#ifndef NDEBUG + for (i = 0; i < nfields; i++) { + assert(layout->fields[i].offset != -1); + } + + for (i = 0; i < noneofs; i++) { + assert(layout->oneofs[i].offset != -1); + } +#endif + // Create the empty message template. layout->empty_template = ALLOC_N(char, layout->size); memset(layout->empty_template, 0, layout->size); @@ -725,8 +754,8 @@ static void slot_clear_hasbit(MessageLayout* layout, static bool slot_is_hasbit_set(MessageLayout* layout, const void* storage, const upb_fielddef* field) { - assert(field_contains_hasbit(layout, field)); size_t hasbit = layout->fields[upb_fielddef_index(field)].hasbit; + assert(field_contains_hasbit(layout, field)); return DEREF_OFFSET( (uint8_t*)storage, hasbit / 8, char) & (1 << (hasbit % 8)); } @@ -734,11 +763,11 @@ static bool slot_is_hasbit_set(MessageLayout* layout, VALUE layout_has(MessageLayout* layout, const void* storage, const upb_fielddef* field) { + const upb_oneofdef* oneof = upb_fielddef_realcontainingoneof(field); assert(upb_fielddef_haspresence(field)); - const upb_oneofdef* oneof = upb_fielddef_containingoneof(field); if (oneof) { uint32_t oneof_case = slot_read_oneof_case(layout, storage, oneof); - return oneof_case == upb_fielddef_number(field); + return oneof_case == upb_fielddef_number(field) ? Qtrue : Qfalse; } else { return slot_is_hasbit_set(layout, storage, field) ? Qtrue : Qfalse; } @@ -748,7 +777,7 @@ void layout_clear(MessageLayout* layout, const void* storage, const upb_fielddef* field) { void* memory = slot_memory(layout, storage, field); - const upb_oneofdef* oneof = upb_fielddef_containingoneof(field); + const upb_oneofdef* oneof = upb_fielddef_realcontainingoneof(field); if (field_contains_hasbit(layout, field)) { slot_clear_hasbit(layout, storage, field); @@ -841,7 +870,7 @@ VALUE layout_get(MessageLayout* layout, const void* storage, const upb_fielddef* field) { void* memory = slot_memory(layout, storage, field); - const upb_oneofdef* oneof = upb_fielddef_containingoneof(field); + const upb_oneofdef* oneof = upb_fielddef_realcontainingoneof(field); bool field_set; if (field_contains_hasbit(layout, field)) { field_set = slot_is_hasbit_set(layout, storage, field); @@ -914,7 +943,7 @@ void layout_set(MessageLayout* layout, const upb_fielddef* field, VALUE val) { void* memory = slot_memory(layout, storage, field); - const upb_oneofdef* oneof = upb_fielddef_containingoneof(field); + const upb_oneofdef* oneof = upb_fielddef_realcontainingoneof(field); if (oneof) { uint32_t* oneof_case = slot_oneof_case(layout, storage, oneof); @@ -985,7 +1014,7 @@ void layout_init(MessageLayout* layout, void* storage) { void layout_mark(MessageLayout* layout, void* storage) { VALUE* values = (VALUE*)CHARPTR_AT(storage, layout->value_offset); - int noneofs = upb_msgdef_numoneofs(layout->msgdef); + int noneofs = upb_msgdef_numrealoneofs(layout->msgdef); int i; for (i = 0; i < layout->value_count; i++) { @@ -1007,7 +1036,7 @@ void layout_dup(MessageLayout* layout, void* to, void* from) { !upb_msg_field_done(&it); upb_msg_field_next(&it)) { const upb_fielddef* field = upb_msg_iter_field(&it); - const upb_oneofdef* oneof = upb_fielddef_containingoneof(field); + const upb_oneofdef* oneof = upb_fielddef_realcontainingoneof(field); void* to_memory = slot_memory(layout, to, field); void* from_memory = slot_memory(layout, from, field); @@ -1041,7 +1070,7 @@ void layout_deep_copy(MessageLayout* layout, void* to, void* from) { !upb_msg_field_done(&it); upb_msg_field_next(&it)) { const upb_fielddef* field = upb_msg_iter_field(&it); - const upb_oneofdef* oneof = upb_fielddef_containingoneof(field); + const upb_oneofdef* oneof = upb_fielddef_realcontainingoneof(field); void* to_memory = slot_memory(layout, to, field); void* from_memory = slot_memory(layout, from, field); @@ -1081,7 +1110,7 @@ VALUE layout_eq(MessageLayout* layout, void* msg1, void* msg2) { !upb_msg_field_done(&it); upb_msg_field_next(&it)) { const upb_fielddef* field = upb_msg_iter_field(&it); - const upb_oneofdef* oneof = upb_fielddef_containingoneof(field); + const upb_oneofdef* oneof = upb_fielddef_realcontainingoneof(field); void* msg1_memory = slot_memory(layout, msg1, field); void* msg2_memory = slot_memory(layout, msg2, field); diff --git a/ruby/ext/google/protobuf_c/upb.c b/ruby/ext/google/protobuf_c/upb.c index ffa55fbb2a..61e86fcf10 100644 --- a/ruby/ext/google/protobuf_c/upb.c +++ b/ruby/ext/google/protobuf_c/upb.c @@ -3032,6 +3032,7 @@ struct upb_msgdef { const upb_oneofdef *oneofs; int field_count; int oneof_count; + int real_oneof_count; /* Is this a map-entry message? */ bool map_entry; @@ -3203,11 +3204,14 @@ static uint32_t upb_handlers_selectorcount(const upb_fielddef *f) { return ret; } +static void upb_status_setoom(upb_status *status) { + upb_status_seterrmsg(status, "out of memory"); +} + static bool assign_msg_indices(upb_msgdef *m, upb_status *s) { /* Sort fields. upb internally relies on UPB_TYPE_MESSAGE fields having the * lowest indexes, but we do not publicly guarantee this. */ upb_msg_field_iter j; - upb_msg_oneof_iter k; int i; uint32_t selector; int n = upb_msgdef_numfields(m); @@ -3248,14 +3252,38 @@ static bool assign_msg_indices(upb_msgdef *m, upb_status *s) { } m->selector_count = selector; - for(upb_msg_oneof_begin(&k, m), i = 0; - !upb_msg_oneof_done(&k); - upb_msg_oneof_next(&k), i++) { - upb_oneofdef *o = (upb_oneofdef*)upb_msg_iter_oneof(&k); - o->index = i; + upb_gfree(fields); + return true; +} + +static bool check_oneofs(upb_msgdef *m, upb_status *s) { + int i; + int first_synthetic = -1; + upb_oneofdef *mutable_oneofs = (upb_oneofdef*)m->oneofs; + + for (i = 0; i < m->oneof_count; i++) { + mutable_oneofs[i].index = i; + + if (upb_oneofdef_issynthetic(&mutable_oneofs[i])) { + if (first_synthetic == -1) { + first_synthetic = i; + } + } else { + if (first_synthetic != -1) { + upb_status_seterrf( + s, "Synthetic oneofs must be after all other oneofs: %s", + upb_oneofdef_name(&mutable_oneofs[i])); + return false; + } + } + } + + if (first_synthetic == -1) { + m->real_oneof_count = m->oneof_count; + } else { + m->real_oneof_count = first_synthetic; } - upb_gfree(fields); return true; } @@ -3440,6 +3468,10 @@ uint32_t upb_fielddef_selectorbase(const upb_fielddef *f) { return f->selector_base; } +const upb_filedef *upb_fielddef_file(const upb_fielddef *f) { + return f->file; +} + const upb_msgdef *upb_fielddef_containingtype(const upb_fielddef *f) { return f->msgdef; } @@ -3448,6 +3480,11 @@ const upb_oneofdef *upb_fielddef_containingoneof(const upb_fielddef *f) { return f->oneof; } +const upb_oneofdef *upb_fielddef_realcontainingoneof(const upb_fielddef *f) { + if (!f->oneof || upb_oneofdef_issynthetic(f->oneof)) return NULL; + return f->oneof; +} + static void chkdefaulttype(const upb_fielddef *f, int ctype) { UPB_UNUSED(f); UPB_UNUSED(ctype); @@ -3544,9 +3581,8 @@ bool upb_fielddef_hassubdef(const upb_fielddef *f) { bool upb_fielddef_haspresence(const upb_fielddef *f) { if (upb_fielddef_isseq(f)) return false; - if (upb_fielddef_issubmsg(f)) return true; - if (f->proto3_optional_) return true; - return f->file->syntax == UPB_SYNTAX_PROTO2; + return upb_fielddef_issubmsg(f) || upb_fielddef_containingoneof(f) || + f->file->syntax == UPB_SYNTAX_PROTO2; } static bool between(int32_t x, int32_t low, int32_t high) { @@ -3651,6 +3687,10 @@ int upb_msgdef_numoneofs(const upb_msgdef *m) { return m->oneof_count; } +int upb_msgdef_numrealoneofs(const upb_msgdef *m) { + return m->real_oneof_count; +} + const upb_msglayout *upb_msgdef_layout(const upb_msgdef *m) { return m->layout; } @@ -3749,7 +3789,7 @@ uint32_t upb_oneofdef_index(const upb_oneofdef *o) { return o->index; } -bool upb_oneofdef_synthetic(const upb_oneofdef *o) { +bool upb_oneofdef_issynthetic(const upb_oneofdef *o) { upb_inttable_iter iter; const upb_fielddef *f; upb_inttable_begin(&iter, &o->itof); @@ -3941,7 +3981,7 @@ static bool make_layout(const upb_symtab *symtab, const upb_msgdef *m) { submsgs[field->submsg_index] = subm->layout; } - if (upb_fielddef_haspresence(f) && !upb_fielddef_containingoneof(f)) { + if (upb_fielddef_haspresence(f) && !upb_fielddef_realcontainingoneof(f)) { /* We don't use hasbit 0, so that 0 can indicate "no presence" in the * table. This wastes one hasbit, but we don't worry about it for now. */ field->presence = ++hasbit; @@ -3960,7 +4000,7 @@ static bool make_layout(const upb_symtab *symtab, const upb_msgdef *m) { size_t field_size = upb_msg_fielddefsize(f); size_t index = upb_fielddef_index(f); - if (upb_fielddef_containingoneof(f)) { + if (upb_fielddef_realcontainingoneof(f)) { /* Oneofs are handled separately below. */ continue; } @@ -3975,6 +4015,8 @@ static bool make_layout(const upb_symtab *symtab, const upb_msgdef *m) { const upb_oneofdef* o = upb_msg_iter_oneof(&oit); upb_oneof_iter fit; + if (upb_oneofdef_issynthetic(o)) continue; + size_t case_size = sizeof(uint32_t); /* Could potentially optimize this. */ size_t field_size = 0; uint32_t case_offset; @@ -4587,6 +4629,7 @@ static bool create_msgdef(symtab_addctx *ctx, const char *prefix, } CHK(assign_msg_indices(m, ctx->status)); + CHK(check_oneofs(m, ctx->status)); assign_msg_wellknowntype(m); upb_inttable_compact2(&m->itof, ctx->alloc); @@ -9649,7 +9692,7 @@ static bool multipart_text(upb_json_parser *p, const char *buf, size_t len, /* Note: this invalidates the accumulate buffer! Call only after reading its * contents. */ static void multipart_end(upb_json_parser *p) { - UPB_ASSERT(p->multipart_state != MULTIPART_INACTIVE); + /* UPB_ASSERT(p->multipart_state != MULTIPART_INACTIVE); */ p->multipart_state = MULTIPART_INACTIVE; accumulate_clear(p); } diff --git a/ruby/ext/google/protobuf_c/upb.h b/ruby/ext/google/protobuf_c/upb.h index a34637925b..bdc20ebeef 100644 --- a/ruby/ext/google/protobuf_c/upb.h +++ b/ruby/ext/google/protobuf_c/upb.h @@ -211,9 +211,6 @@ int msvc_vsnprintf(char* s, size_t n, const char* format, va_list arg); #include /* ** This file contains shared definitions that are widely used across upb. -** -** 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_H_ @@ -226,23 +223,13 @@ int msvc_vsnprintf(char* s, size_t n, const char* format, va_list arg); #include #include + #ifdef __cplusplus -#include -namespace upb { -class Arena; -class Status; -template class InlinedArena; -} +extern "C" { #endif - /* upb_status *****************************************************************/ -/* upb_status represents a success or failure status and error message. - * It owns no resources and allocates no memory, so it should work - * even in OOM situations. */ - -/* The maximum length of an error message before it will get truncated. */ #define UPB_STATUS_MAX_MESSAGE 127 typedef struct { @@ -250,59 +237,15 @@ typedef struct { char msg[UPB_STATUS_MAX_MESSAGE]; /* Error message; NULL-terminated. */ } upb_status; -#ifdef __cplusplus -extern "C" { -#endif - const char *upb_status_errmsg(const upb_status *status); bool upb_ok(const upb_status *status); -/* Any of the functions that write to a status object allow status to be NULL, - * to support use cases where the function's caller does not care about the - * status message. */ +/* These are no-op if |status| is NULL. */ void upb_status_clear(upb_status *status); void upb_status_seterrmsg(upb_status *status, const char *msg); void upb_status_seterrf(upb_status *status, const char *fmt, ...); void upb_status_vseterrf(upb_status *status, const char *fmt, va_list args); -UPB_INLINE void upb_status_setoom(upb_status *status) { - upb_status_seterrmsg(status, "out of memory"); -} - -#ifdef __cplusplus -} /* extern "C" */ - -class upb::Status { - public: - Status() { upb_status_clear(&status_); } - - upb_status* ptr() { return &status_; } - - /* Returns true if there is no error. */ - bool ok() const { return upb_ok(&status_); } - - /* Guaranteed to be NULL-terminated. */ - const char *error_message() const { return upb_status_errmsg(&status_); } - - /* The error message will be truncated if it is longer than - * UPB_STATUS_MAX_MESSAGE-4. */ - void SetErrorMessage(const char *msg) { upb_status_seterrmsg(&status_, msg); } - void SetFormattedErrorMessage(const char *fmt, ...) { - va_list args; - va_start(args, fmt); - upb_status_vseterrf(&status_, fmt, args); - va_end(args); - } - - /* Resets the status to a successful state with no message. */ - void Clear() { upb_status_clear(&status_); } - - private: - upb_status status_; -}; - -#endif /* __cplusplus */ - /** upb_strview ************************************************************/ typedef struct { @@ -369,16 +312,8 @@ UPB_INLINE void upb_free(upb_alloc *alloc, void *ptr) { /* The global allocator used by upb. Uses the standard malloc()/free(). */ -#ifdef __cplusplus -extern "C" { -#endif - extern upb_alloc upb_alloc_global; -#ifdef __cplusplus -} /* extern "C" */ -#endif - /* Functions that hard-code the global malloc. * * We still get benefit because we can put custom logic into our global @@ -415,10 +350,6 @@ typedef void upb_cleanup_func(void *ud); struct upb_arena; typedef struct upb_arena upb_arena; -#ifdef __cplusplus -extern "C" { -#endif - typedef struct { /* We implement the allocator interface. * This must be the first member of upb_arena! */ @@ -468,64 +399,6 @@ UPB_INLINE upb_arena *upb_arena_new(void) { return upb_arena_init(NULL, 0, &upb_alloc_global); } -#ifdef __cplusplus -} /* extern "C" */ - -class upb::Arena { - public: - /* A simple arena with no initial memory block and the default allocator. */ - Arena() : ptr_(upb_arena_new(), upb_arena_free) {} - - upb_arena* ptr() { return ptr_.get(); } - - /* Allows this arena to be used as a generic allocator. - * - * The arena does not need free() calls so when using Arena as an allocator - * it is safe to skip them. However they are no-ops so there is no harm in - * calling free() either. */ - upb_alloc *allocator() { return upb_arena_alloc(ptr_.get()); } - - /* Add a cleanup function to run when the arena is destroyed. - * Returns false on out-of-memory. */ - bool AddCleanup(void *ud, upb_cleanup_func* func) { - return upb_arena_addcleanup(ptr_.get(), ud, func); - } - - /* Total number of bytes that have been allocated. It is undefined what - * Realloc() does to &arena_ counter. */ - size_t BytesAllocated() const { return upb_arena_bytesallocated(ptr_.get()); } - - private: - std::unique_ptr ptr_; -}; - -#endif - -/* upb::InlinedArena **********************************************************/ - -/* upb::InlinedArena seeds the arenas with a predefined amount of memory. No - * heap memory will be allocated until the initial block is exceeded. - * - * These types only exist in C++ */ - -#ifdef __cplusplus - -template class upb::InlinedArena : public upb::Arena { - public: - InlinedArena() : ptr_(upb_arena_new(&initial_block_, N, &upb_alloc_global)) {} - - upb_arena* ptr() { return ptr_.get(); } - - private: - InlinedArena(const InlinedArena*) = delete; - InlinedArena& operator=(const InlinedArena*) = delete; - - std::unique_ptr ptr_; - char initial_block_[N]; -}; - -#endif /* __cplusplus */ - /* Constants ******************************************************************/ /* Generic function type. */ @@ -545,20 +418,15 @@ typedef enum { * types defined in descriptor.proto, which gives INT32 and SINT32 separate * types (we distinguish the two with the "integer encoding" enum below). */ typedef enum { - /* Types stored in 1 byte. */ UPB_TYPE_BOOL = 1, - /* Types stored in 4 bytes. */ UPB_TYPE_FLOAT = 2, UPB_TYPE_INT32 = 3, UPB_TYPE_UINT32 = 4, UPB_TYPE_ENUM = 5, /* Enum values are int32. */ - /* Types stored as void* (probably 4 or 8 bytes). */ UPB_TYPE_MESSAGE = 6, - /* Types stored as 8 bytes. */ UPB_TYPE_DOUBLE = 7, UPB_TYPE_INT64 = 8, UPB_TYPE_UINT64 = 9, - /* Types stored as upb_strview (2 * void*) (probably 8 or 16 bytes). */ UPB_TYPE_STRING = 10, UPB_TYPE_BYTES = 11 } upb_fieldtype_t; @@ -615,6 +483,10 @@ typedef enum { #define UPB_MAP_BEGIN -1 +#ifdef __cplusplus +} /* extern "C" */ +#endif + #endif /* UPB_H_ */ @@ -3208,38 +3080,23 @@ UPB_INLINE void google_protobuf_GeneratedCodeInfo_Annotation_set_end(google_prot ** Defs are upb's internal representation of the constructs that can appear ** in a .proto file: ** -** - upb::MessageDefPtr (upb_msgdef): describes a "message" construct. -** - upb::FieldDefPtr (upb_fielddef): describes a message field. -** - upb::FileDefPtr (upb_filedef): describes a .proto file and its defs. -** - upb::EnumDefPtr (upb_enumdef): describes an enum. -** - upb::OneofDefPtr (upb_oneofdef): describes a oneof. +** - upb_msgdef: describes a "message" construct. +** - upb_fielddef: describes a message field. +** - upb_filedef: describes a .proto file and its defs. +** - upb_enumdef: describes an enum. +** - upb_oneofdef: describes a oneof. ** ** TODO: definitions of services. -** -** 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_ -#ifdef __cplusplus -#include -#include -#include -#include - -namespace upb { -class EnumDefPtr; -class FieldDefPtr; -class FileDefPtr; -class MessageDefPtr; -class OneofDefPtr; -class SymbolTable; -} -#endif +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ struct upb_enumdef; typedef struct upb_enumdef upb_enumdef; @@ -3291,10 +3148,6 @@ typedef enum { * protobuf wire format. */ #define UPB_MAX_FIELDNUMBER ((1 << 29) - 1) -#ifdef __cplusplus -extern "C" { -#endif - const char *upb_fielddef_fullname(const upb_fielddef *f); upb_fieldtype_t upb_fielddef_type(const upb_fielddef *f); upb_descriptortype_t upb_fielddef_descriptortype(const upb_fielddef *f); @@ -3305,8 +3158,10 @@ const char *upb_fielddef_jsonname(const upb_fielddef *f); bool upb_fielddef_isextension(const upb_fielddef *f); bool upb_fielddef_lazy(const upb_fielddef *f); bool upb_fielddef_packed(const upb_fielddef *f); +const upb_filedef *upb_fielddef_file(const upb_fielddef *f); const upb_msgdef *upb_fielddef_containingtype(const upb_fielddef *f); const upb_oneofdef *upb_fielddef_containingoneof(const upb_fielddef *f); +const upb_oneofdef *upb_fielddef_realcontainingoneof(const upb_fielddef *f); uint32_t upb_fielddef_index(const upb_fielddef *f); bool upb_fielddef_issubmsg(const upb_fielddef *f); bool upb_fielddef_isstring(const upb_fielddef *f); @@ -3330,130 +3185,15 @@ const upb_msglayout_field *upb_fielddef_layout(const upb_fielddef *f); /* Internal only. */ uint32_t upb_fielddef_selectorbase(const upb_fielddef *f); -#ifdef __cplusplus -} /* extern "C" */ - -/* A upb_fielddef describes a single field in a message. It is most often - * found as a part of a upb_msgdef, but can also stand alone to represent - * an extension. */ -class upb::FieldDefPtr { - public: - FieldDefPtr() : ptr_(nullptr) {} - explicit FieldDefPtr(const upb_fielddef *ptr) : ptr_(ptr) {} - - const upb_fielddef* ptr() const { return ptr_; } - explicit operator bool() const { return ptr_ != nullptr; } - - typedef upb_fieldtype_t Type; - typedef upb_label_t Label; - typedef upb_descriptortype_t DescriptorType; - - const char* full_name() const { return upb_fielddef_fullname(ptr_); } - - Type type() const { return upb_fielddef_type(ptr_); } - Label label() const { return upb_fielddef_label(ptr_); } - const char* name() const { return upb_fielddef_name(ptr_); } - const char* json_name() const { return upb_fielddef_jsonname(ptr_); } - uint32_t number() const { return upb_fielddef_number(ptr_); } - bool is_extension() const { return upb_fielddef_isextension(ptr_); } - - /* For UPB_TYPE_MESSAGE fields only where is_tag_delimited() == false, - * indicates whether this field should have lazy parsing handlers that yield - * the unparsed string for the submessage. - * - * TODO(haberman): I think we want to move this into a FieldOptions container - * when we add support for custom options (the FieldOptions struct will - * contain both regular FieldOptions like "lazy" *and* custom options). */ - bool lazy() const { return upb_fielddef_lazy(ptr_); } - - /* For non-string, non-submessage fields, this indicates whether binary - * protobufs are encoded in packed or non-packed format. - * - * TODO(haberman): see note above about putting options like this into a - * FieldOptions container. */ - bool packed() const { return upb_fielddef_packed(ptr_); } - - /* An integer that can be used as an index into an array of fields for - * whatever message this field belongs to. Guaranteed to be less than - * f->containing_type()->field_count(). May only be accessed once the def has - * been finalized. */ - uint32_t index() const { return upb_fielddef_index(ptr_); } - - /* The MessageDef to which this field belongs. - * - * If this field has been added to a MessageDef, that message can be retrieved - * directly (this is always the case for frozen FieldDefs). - * - * If the field has not yet been added to a MessageDef, you can set the name - * of the containing type symbolically instead. This is mostly useful for - * extensions, where the extension is declared separately from the message. */ - MessageDefPtr containing_type() const; - - /* The OneofDef to which this field belongs, or NULL if this field is not part - * of a oneof. */ - OneofDefPtr containing_oneof() const; - - /* The field's type according to the enum in descriptor.proto. This is not - * the same as UPB_TYPE_*, because it distinguishes between (for example) - * INT32 and SINT32, whereas our "type" enum does not. This return of - * descriptor_type() is a function of type(), integer_format(), and - * is_tag_delimited(). */ - DescriptorType descriptor_type() const { - return upb_fielddef_descriptortype(ptr_); - } - - /* Convenient field type tests. */ - bool IsSubMessage() const { return upb_fielddef_issubmsg(ptr_); } - bool IsString() const { return upb_fielddef_isstring(ptr_); } - bool IsSequence() const { return upb_fielddef_isseq(ptr_); } - bool IsPrimitive() const { return upb_fielddef_isprimitive(ptr_); } - bool IsMap() const { return upb_fielddef_ismap(ptr_); } - - /* Returns the non-string default value for this fielddef, which may either - * be something the client set explicitly or the "default default" (0 for - * numbers, empty for strings). The field's type indicates the type of the - * returned value, except for enum fields that are still mutable. - * - * Requires that the given function matches the field's current type. */ - int64_t default_int64() const { return upb_fielddef_defaultint64(ptr_); } - int32_t default_int32() const { return upb_fielddef_defaultint32(ptr_); } - uint64_t default_uint64() const { return upb_fielddef_defaultuint64(ptr_); } - uint32_t default_uint32() const { return upb_fielddef_defaultuint32(ptr_); } - bool default_bool() const { return upb_fielddef_defaultbool(ptr_); } - float default_float() const { return upb_fielddef_defaultfloat(ptr_); } - double default_double() const { return upb_fielddef_defaultdouble(ptr_); } - - /* The resulting string is always NULL-terminated. If non-NULL, the length - * will be stored in *len. */ - const char *default_string(size_t * len) const { - return upb_fielddef_defaultstr(ptr_, len); - } - - /* Returns the enum or submessage def for this field, if any. The field's - * type must match (ie. you may only call enum_subdef() for fields where - * type() == UPB_TYPE_ENUM). */ - EnumDefPtr enum_subdef() const; - MessageDefPtr message_subdef() const; - - private: - const upb_fielddef *ptr_; -}; - -#endif /* __cplusplus */ - /* upb_oneofdef ***************************************************************/ -#ifdef __cplusplus -extern "C" { -#endif - typedef upb_inttable_iter upb_oneof_iter; const char *upb_oneofdef_name(const upb_oneofdef *o); const upb_msgdef *upb_oneofdef_containingtype(const upb_oneofdef *o); int upb_oneofdef_numfields(const upb_oneofdef *o); uint32_t upb_oneofdef_index(const upb_oneofdef *o); -bool upb_oneofdef_synthetic(const upb_oneofdef *o); +bool upb_oneofdef_issynthetic(const upb_oneofdef *o); /* Oneof lookups: * - ntof: look up a field by name. @@ -3480,92 +3220,6 @@ void upb_oneof_iter_setdone(upb_oneof_iter *iter); bool upb_oneof_iter_isequal(const upb_oneof_iter *iter1, const upb_oneof_iter *iter2); -#ifdef __cplusplus -} /* extern "C" */ - -/* Class that represents a oneof. */ -class upb::OneofDefPtr { - public: - OneofDefPtr() : ptr_(nullptr) {} - explicit OneofDefPtr(const upb_oneofdef *ptr) : ptr_(ptr) {} - - const upb_oneofdef* ptr() const { return ptr_; } - explicit operator bool() { return ptr_ != nullptr; } - - /* Returns the MessageDef that owns this OneofDef. */ - MessageDefPtr containing_type() const; - - /* Returns the name of this oneof. This is the name used to look up the oneof - * by name once added to a message def. */ - const char* name() const { return upb_oneofdef_name(ptr_); } - - /* Returns the number of fields currently defined in the oneof. */ - int field_count() const { return upb_oneofdef_numfields(ptr_); } - - /* Looks up by name. */ - FieldDefPtr FindFieldByName(const char *name, size_t len) const { - return FieldDefPtr(upb_oneofdef_ntof(ptr_, name, len)); - } - FieldDefPtr FindFieldByName(const char* name) const { - return FieldDefPtr(upb_oneofdef_ntofz(ptr_, name)); - } - - template - FieldDefPtr FindFieldByName(const T& str) const { - return FindFieldByName(str.c_str(), str.size()); - } - - /* Looks up by tag number. */ - FieldDefPtr FindFieldByNumber(uint32_t num) const { - return FieldDefPtr(upb_oneofdef_itof(ptr_, num)); - } - - class const_iterator - : public std::iterator { - public: - void operator++() { upb_oneof_next(&iter_); } - - FieldDefPtr operator*() const { - return FieldDefPtr(upb_oneof_iter_field(&iter_)); - } - - bool operator!=(const const_iterator& other) const { - return !upb_oneof_iter_isequal(&iter_, &other.iter_); - } - - bool operator==(const const_iterator& other) const { - return upb_oneof_iter_isequal(&iter_, &other.iter_); - } - - private: - friend class OneofDefPtr; - - const_iterator() {} - explicit const_iterator(OneofDefPtr o) { - upb_oneof_begin(&iter_, o.ptr()); - } - static const_iterator end() { - const_iterator iter; - upb_oneof_iter_setdone(&iter.iter_); - return iter; - } - - upb_oneof_iter iter_; - }; - - const_iterator begin() const { return const_iterator(*this); } - const_iterator end() const { return const_iterator::end(); } - - private: - const upb_oneofdef *ptr_; -}; - -inline upb::OneofDefPtr upb::FieldDefPtr::containing_oneof() const { - return OneofDefPtr(upb_fielddef_containingoneof(ptr_)); -} - -#endif /* __cplusplus */ - /* upb_msgdef *****************************************************************/ typedef upb_inttable_iter upb_msg_field_iter; @@ -3587,26 +3241,21 @@ typedef upb_strtable_iter upb_msg_oneof_iter; #define UPB_TIMESTAMP_SECONDS 1 #define UPB_TIMESTAMP_NANOS 2 -#ifdef __cplusplus -extern "C" { -#endif - const char *upb_msgdef_fullname(const upb_msgdef *m); const upb_filedef *upb_msgdef_file(const upb_msgdef *m); const char *upb_msgdef_name(const upb_msgdef *m); +int upb_msgdef_numfields(const upb_msgdef *m); int upb_msgdef_numoneofs(const upb_msgdef *m); +int upb_msgdef_numrealoneofs(const upb_msgdef *m); upb_syntax_t upb_msgdef_syntax(const upb_msgdef *m); 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); const upb_fielddef *upb_msgdef_itof(const upb_msgdef *m, uint32_t i); const upb_fielddef *upb_msgdef_ntof(const upb_msgdef *m, const char *name, size_t len); const upb_oneofdef *upb_msgdef_ntoo(const upb_msgdef *m, const char *name, size_t len); -int upb_msgdef_numfields(const upb_msgdef *m); -int upb_msgdef_numoneofs(const upb_msgdef *m); const upb_msglayout *upb_msgdef_layout(const upb_msgdef *m); const upb_fielddef *_upb_msgdef_field(const upb_msgdef *m, int i); @@ -3671,194 +3320,6 @@ void upb_msg_oneof_iter_setdone(upb_msg_oneof_iter * iter); bool upb_msg_oneof_iter_isequal(const upb_msg_oneof_iter *iter1, const upb_msg_oneof_iter *iter2); -#ifdef __cplusplus -} /* extern "C" */ - -/* Structure that describes a single .proto message type. */ -class upb::MessageDefPtr { - public: - MessageDefPtr() : ptr_(nullptr) {} - explicit MessageDefPtr(const upb_msgdef *ptr) : ptr_(ptr) {} - - const upb_msgdef *ptr() const { return ptr_; } - explicit operator bool() const { return ptr_ != nullptr; } - - const char* full_name() const { return upb_msgdef_fullname(ptr_); } - const char* name() const { return upb_msgdef_name(ptr_); } - - /* The number of fields that belong to the MessageDef. */ - int field_count() const { return upb_msgdef_numfields(ptr_); } - - /* The number of oneofs that belong to the MessageDef. */ - int oneof_count() const { return upb_msgdef_numoneofs(ptr_); } - - upb_syntax_t syntax() const { return upb_msgdef_syntax(ptr_); } - - /* These return null pointers if the field is not found. */ - FieldDefPtr FindFieldByNumber(uint32_t number) const { - return FieldDefPtr(upb_msgdef_itof(ptr_, number)); - } - FieldDefPtr FindFieldByName(const char* name, size_t len) const { - return FieldDefPtr(upb_msgdef_ntof(ptr_, name, len)); - } - FieldDefPtr FindFieldByName(const char *name) const { - return FieldDefPtr(upb_msgdef_ntofz(ptr_, name)); - } - - template - FieldDefPtr FindFieldByName(const T& str) const { - return FindFieldByName(str.c_str(), str.size()); - } - - OneofDefPtr FindOneofByName(const char* name, size_t len) const { - return OneofDefPtr(upb_msgdef_ntoo(ptr_, name, len)); - } - - OneofDefPtr FindOneofByName(const char *name) const { - return OneofDefPtr(upb_msgdef_ntooz(ptr_, name)); - } - - template - OneofDefPtr FindOneofByName(const T &str) const { - return FindOneofByName(str.c_str(), str.size()); - } - - /* Is this message a map entry? */ - bool mapentry() const { return upb_msgdef_mapentry(ptr_); } - - /* Return the type of well known type message. UPB_WELLKNOWN_UNSPECIFIED for - * non-well-known message. */ - upb_wellknowntype_t wellknowntype() const { - return upb_msgdef_wellknowntype(ptr_); - } - - /* Whether is a number wrapper. */ - bool isnumberwrapper() const { return upb_msgdef_isnumberwrapper(ptr_); } - - /* Iteration over fields. The order is undefined. */ - class const_field_iterator - : public std::iterator { - public: - void operator++() { upb_msg_field_next(&iter_); } - - FieldDefPtr operator*() const { - return FieldDefPtr(upb_msg_iter_field(&iter_)); - } - - bool operator!=(const const_field_iterator &other) const { - return !upb_msg_field_iter_isequal(&iter_, &other.iter_); - } - - bool operator==(const const_field_iterator &other) const { - return upb_msg_field_iter_isequal(&iter_, &other.iter_); - } - - private: - friend class MessageDefPtr; - - explicit const_field_iterator() {} - - explicit const_field_iterator(MessageDefPtr msg) { - upb_msg_field_begin(&iter_, msg.ptr()); - } - - static const_field_iterator end() { - const_field_iterator iter; - upb_msg_field_iter_setdone(&iter.iter_); - return iter; - } - - upb_msg_field_iter iter_; - }; - - /* Iteration over oneofs. The order is undefined. */ - class const_oneof_iterator - : public std::iterator { - public: - - void operator++() { upb_msg_oneof_next(&iter_); } - - OneofDefPtr operator*() const { - return OneofDefPtr(upb_msg_iter_oneof(&iter_)); - } - - bool operator!=(const const_oneof_iterator& other) const { - return !upb_msg_oneof_iter_isequal(&iter_, &other.iter_); - } - - bool operator==(const const_oneof_iterator &other) const { - return upb_msg_oneof_iter_isequal(&iter_, &other.iter_); - } - - private: - friend class MessageDefPtr; - - const_oneof_iterator() {} - - explicit const_oneof_iterator(MessageDefPtr msg) { - upb_msg_oneof_begin(&iter_, msg.ptr()); - } - - static const_oneof_iterator end() { - const_oneof_iterator iter; - upb_msg_oneof_iter_setdone(&iter.iter_); - return iter; - } - - upb_msg_oneof_iter iter_; - }; - - class ConstFieldAccessor { - public: - explicit ConstFieldAccessor(const upb_msgdef* md) : md_(md) {} - const_field_iterator begin() { return MessageDefPtr(md_).field_begin(); } - const_field_iterator end() { return MessageDefPtr(md_).field_end(); } - private: - const upb_msgdef* md_; - }; - - class ConstOneofAccessor { - public: - explicit ConstOneofAccessor(const upb_msgdef* md) : md_(md) {} - const_oneof_iterator begin() { return MessageDefPtr(md_).oneof_begin(); } - const_oneof_iterator end() { return MessageDefPtr(md_).oneof_end(); } - private: - const upb_msgdef* md_; - }; - - const_field_iterator field_begin() const { - return const_field_iterator(*this); - } - - const_field_iterator field_end() const { return const_field_iterator::end(); } - - const_oneof_iterator oneof_begin() const { - return const_oneof_iterator(*this); - } - - const_oneof_iterator oneof_end() const { return const_oneof_iterator::end(); } - - ConstFieldAccessor fields() const { return ConstFieldAccessor(ptr()); } - ConstOneofAccessor oneofs() const { return ConstOneofAccessor(ptr()); } - - private: - const upb_msgdef* ptr_; -}; - -inline upb::MessageDefPtr upb::FieldDefPtr::message_subdef() const { - return MessageDefPtr(upb_fielddef_msgsubdef(ptr_)); -} - -inline upb::MessageDefPtr upb::FieldDefPtr::containing_type() const { - return MessageDefPtr(upb_fielddef_containingtype(ptr_)); -} - -inline upb::MessageDefPtr upb::OneofDefPtr::containing_type() const { - return MessageDefPtr(upb_oneofdef_containingtype(ptr_)); -} - -#endif /* __cplusplus */ - /* upb_enumdef ****************************************************************/ typedef upb_strtable_iter upb_enum_iter; @@ -3893,75 +3354,8 @@ bool upb_enum_done(upb_enum_iter *iter); const char *upb_enum_iter_name(upb_enum_iter *iter); int32_t upb_enum_iter_number(upb_enum_iter *iter); -#ifdef __cplusplus - -class upb::EnumDefPtr { - public: - EnumDefPtr() : ptr_(nullptr) {} - explicit EnumDefPtr(const upb_enumdef* ptr) : ptr_(ptr) {} - - const upb_enumdef* ptr() const { return ptr_; } - explicit operator bool() const { return ptr_ != nullptr; } - - const char* full_name() const { return upb_enumdef_fullname(ptr_); } - const char* name() const { return upb_enumdef_name(ptr_); } - - /* The value that is used as the default when no field default is specified. - * If not set explicitly, the first value that was added will be used. - * The default value must be a member of the enum. - * Requires that value_count() > 0. */ - int32_t default_value() const { return upb_enumdef_default(ptr_); } - - /* Returns the number of values currently defined in the enum. Note that - * multiple names can refer to the same number, so this may be greater than - * the total number of unique numbers. */ - int value_count() const { return upb_enumdef_numvals(ptr_); } - - /* Lookups from name to integer, returning true if found. */ - bool FindValueByName(const char *name, int32_t *num) const { - return upb_enumdef_ntoiz(ptr_, name, num); - } - - /* Finds the name corresponding to the given number, or NULL if none was - * found. If more than one name corresponds to this number, returns the - * first one that was added. */ - const char *FindValueByNumber(int32_t num) const { - return upb_enumdef_iton(ptr_, num); - } - - /* Iteration over name/value pairs. The order is undefined. - * Adding an enum val invalidates any iterators. - * - * TODO: make compatible with range-for, with elements as pairs? */ - class Iterator { - public: - explicit Iterator(EnumDefPtr e) { upb_enum_begin(&iter_, e.ptr()); } - - int32_t number() { return upb_enum_iter_number(&iter_); } - const char *name() { return upb_enum_iter_name(&iter_); } - bool Done() { return upb_enum_done(&iter_); } - void Next() { return upb_enum_next(&iter_); } - - private: - upb_enum_iter iter_; - }; - - private: - const upb_enumdef *ptr_; -}; - -inline upb::EnumDefPtr upb::FieldDefPtr::enum_subdef() const { - return EnumDefPtr(upb_fielddef_enumsubdef(ptr_)); -} - -#endif /* __cplusplus */ - /* upb_filedef ****************************************************************/ -#ifdef __cplusplus -extern "C" { -#endif - const char *upb_filedef_name(const upb_filedef *f); const char *upb_filedef_package(const upb_filedef *f); const char *upb_filedef_phpprefix(const upb_filedef *f); @@ -3974,57 +3368,8 @@ const upb_filedef *upb_filedef_dep(const upb_filedef *f, int i); const upb_msgdef *upb_filedef_msg(const upb_filedef *f, int i); const upb_enumdef *upb_filedef_enum(const upb_filedef *f, int i); -#ifdef __cplusplus -} /* extern "C" */ - -/* Class that represents a .proto file with some things defined in it. - * - * Many users won't care about FileDefs, but they are necessary if you want to - * read the values of file-level options. */ -class upb::FileDefPtr { - public: - explicit FileDefPtr(const upb_filedef *ptr) : ptr_(ptr) {} - - const upb_filedef* ptr() const { return ptr_; } - explicit operator bool() const { return ptr_ != nullptr; } - - /* Get/set name of the file (eg. "foo/bar.proto"). */ - const char* name() const { return upb_filedef_name(ptr_); } - - /* Package name for definitions inside the file (eg. "foo.bar"). */ - const char* package() const { return upb_filedef_package(ptr_); } - - /* Sets the php class prefix which is prepended to all php generated classes - * from this .proto. Default is empty. */ - const char* phpprefix() const { return upb_filedef_phpprefix(ptr_); } - - /* Use this option to change the namespace of php generated classes. Default - * is empty. When this option is empty, the package name will be used for - * determining the namespace. */ - const char* phpnamespace() const { return upb_filedef_phpnamespace(ptr_); } - - /* Syntax for the file. Defaults to proto2. */ - upb_syntax_t syntax() const { return upb_filedef_syntax(ptr_); } - - /* Get the list of dependencies from the file. These are returned in the - * order that they were added to the FileDefPtr. */ - int dependency_count() const { return upb_filedef_depcount(ptr_); } - const FileDefPtr dependency(int index) const { - return FileDefPtr(upb_filedef_dep(ptr_, index)); - } - - private: - const upb_filedef* ptr_; -}; - -#endif /* __cplusplus */ - /* upb_symtab *****************************************************************/ -#ifdef __cplusplus -extern "C" { -#endif - upb_symtab *upb_symtab_new(void); void upb_symtab_free(upb_symtab* s); const upb_msgdef *upb_symtab_lookupmsg(const upb_symtab *s, const char *sym); @@ -4047,53 +3392,11 @@ typedef struct upb_def_init { bool _upb_symtab_loaddefinit(upb_symtab *s, const upb_def_init *init); + #ifdef __cplusplus } /* extern "C" */ - -/* Non-const methods in upb::SymbolTable are NOT thread-safe. */ -class upb::SymbolTable { - public: - SymbolTable() : ptr_(upb_symtab_new(), upb_symtab_free) {} - explicit SymbolTable(upb_symtab* s) : ptr_(s, upb_symtab_free) {} - - const upb_symtab* ptr() const { return ptr_.get(); } - upb_symtab* ptr() { return ptr_.get(); } - - /* Finds an entry in the symbol table with this exact name. If not found, - * returns NULL. */ - MessageDefPtr LookupMessage(const char *sym) const { - return MessageDefPtr(upb_symtab_lookupmsg(ptr_.get(), sym)); - } - - EnumDefPtr LookupEnum(const char *sym) const { - return EnumDefPtr(upb_symtab_lookupenum(ptr_.get(), sym)); - } - - FileDefPtr LookupFile(const char *name) const { - return FileDefPtr(upb_symtab_lookupfile(ptr_.get(), name)); - } - - /* TODO: iteration? */ - - /* Adds the given serialized FileDescriptorProto to the pool. */ - FileDefPtr AddFile(const google_protobuf_FileDescriptorProto *file_proto, - Status *status) { - return FileDefPtr( - upb_symtab_addfile(ptr_.get(), file_proto, status->ptr())); - } - - private: - std::unique_ptr ptr_; -}; - -UPB_INLINE const char* upb_safecstr(const std::string& str) { - UPB_ASSERT(str.size() == std::strlen(str.c_str())); - return str.c_str(); -} - #endif /* __cplusplus */ - #endif /* UPB_DEF_H_ */ #ifndef UPB_REFLECTION_H_ diff --git a/ruby/tests/basic.rb b/ruby/tests/basic.rb index 321b63fa6c..687e1fb934 100755 --- a/ruby/tests/basic.rb +++ b/ruby/tests/basic.rb @@ -32,11 +32,11 @@ module BasicTest include CommonTests def test_has_field - m = TestMessage.new - assert !m.has_optional_msg? - m.optional_msg = TestMessage2.new - assert m.has_optional_msg? - assert TestMessage.descriptor.lookup('optional_msg').has?(m) + m = TestSingularFields.new + assert !m.has_singular_msg? + m.singular_msg = TestMessage2.new + assert m.has_singular_msg? + assert TestSingularFields.descriptor.lookup('singular_msg').has?(m) m = OneofMessage.new assert !m.has_my_oneof? @@ -45,32 +45,31 @@ module BasicTest assert_raise NoMethodError do m.has_a? end - assert_raise ArgumentError do - OneofMessage.descriptor.lookup('a').has?(m) - end + assert_true OneofMessage.descriptor.lookup('a').has?(m) - m = TestMessage.new + m = TestSingularFields.new assert_raise NoMethodError do - m.has_optional_int32? + m.has_singular_int32? end assert_raise ArgumentError do - TestMessage.descriptor.lookup('optional_int32').has?(m) + TestSingularFields.descriptor.lookup('singular_int32').has?(m) end assert_raise NoMethodError do - m.has_optional_string? + m.has_singular_string? end assert_raise ArgumentError do - TestMessage.descriptor.lookup('optional_string').has?(m) + TestSingularFields.descriptor.lookup('singular_string').has?(m) end assert_raise NoMethodError do - m.has_optional_bool? + m.has_singular_bool? end assert_raise ArgumentError do - TestMessage.descriptor.lookup('optional_bool').has?(m) + TestSingularFields.descriptor.lookup('singular_bool').has?(m) end + m = TestMessage.new assert_raise NoMethodError do m.has_repeated_msg? end @@ -79,40 +78,59 @@ module BasicTest end end + def test_no_presence + m = TestSingularFields.new + + # Explicitly setting to zero does not cause anything to be serialized. + m.singular_int32 = 0 + assert_equal "", TestSingularFields.encode(m) + + # Explicitly setting to a non-zero value *does* cause serialization. + m.singular_int32 = 1 + assert_not_equal "", TestSingularFields.encode(m) + + m.singular_int32 = 0 + assert_equal "", TestSingularFields.encode(m) + end + def test_set_clear_defaults - m = TestMessage.new + m = TestSingularFields.new + + m.singular_int32 = -42 + assert_equal -42, m.singular_int32 + m.clear_singular_int32 + assert_equal 0, m.singular_int32 + + m.singular_int32 = 50 + assert_equal 50, m.singular_int32 + TestSingularFields.descriptor.lookup('singular_int32').clear(m) + assert_equal 0, m.singular_int32 + + m.singular_string = "foo bar" + assert_equal "foo bar", m.singular_string + m.clear_singular_string + assert_equal "", m.singular_string + + m.singular_string = "foo" + assert_equal "foo", m.singular_string + TestSingularFields.descriptor.lookup('singular_string').clear(m) + assert_equal "", m.singular_string + + m.singular_msg = TestMessage2.new(:foo => 42) + assert_equal TestMessage2.new(:foo => 42), m.singular_msg + assert m.has_singular_msg? + m.clear_singular_msg + assert_equal nil, m.singular_msg + assert !m.has_singular_msg? + + m.singular_msg = TestMessage2.new(:foo => 42) + assert_equal TestMessage2.new(:foo => 42), m.singular_msg + TestSingularFields.descriptor.lookup('singular_msg').clear(m) + assert_equal nil, m.singular_msg + end - m.optional_int32 = -42 - assert_equal -42, m.optional_int32 - m.clear_optional_int32 - assert_equal 0, m.optional_int32 - - m.optional_int32 = 50 - assert_equal 50, m.optional_int32 - TestMessage.descriptor.lookup('optional_int32').clear(m) - assert_equal 0, m.optional_int32 - - m.optional_string = "foo bar" - assert_equal "foo bar", m.optional_string - m.clear_optional_string - assert_equal "", m.optional_string - - m.optional_string = "foo" - assert_equal "foo", m.optional_string - TestMessage.descriptor.lookup('optional_string').clear(m) - assert_equal "", m.optional_string - - m.optional_msg = TestMessage2.new(:foo => 42) - assert_equal TestMessage2.new(:foo => 42), m.optional_msg - assert m.has_optional_msg? - m.clear_optional_msg - assert_equal nil, m.optional_msg - assert !m.has_optional_msg? - - m.optional_msg = TestMessage2.new(:foo => 42) - assert_equal TestMessage2.new(:foo => 42), m.optional_msg - TestMessage.descriptor.lookup('optional_msg').clear(m) - assert_equal nil, m.optional_msg + def test_clear_repeated_fields + m = TestMessage.new m.repeated_int32.push(1) assert_equal [1], m.repeated_int32 @@ -144,7 +162,6 @@ module BasicTest assert !m.has_my_oneof? end - def test_initialization_map_errors e = assert_raise ArgumentError do TestMessage.new(:hello => "world") diff --git a/ruby/tests/basic_test.proto b/ruby/tests/basic_test.proto index a918540075..6086879d09 100644 --- a/ruby/tests/basic_test.proto +++ b/ruby/tests/basic_test.proto @@ -21,17 +21,17 @@ message Baz { } message TestMessage { - int32 optional_int32 = 1; - int64 optional_int64 = 2; - uint32 optional_uint32 = 3; - uint64 optional_uint64 = 4; - bool optional_bool = 5; - float optional_float = 6; - double optional_double = 7; - string optional_string = 8; - bytes optional_bytes = 9; - TestMessage2 optional_msg = 10; - TestEnum optional_enum = 11; + optional int32 optional_int32 = 1; + optional int64 optional_int64 = 2; + optional uint32 optional_uint32 = 3; + optional uint64 optional_uint64 = 4; + optional bool optional_bool = 5; + optional float optional_float = 6; + optional double optional_double = 7; + optional string optional_string = 8; + optional bytes optional_bytes = 9; + optional TestMessage2 optional_msg = 10; + optional TestEnum optional_enum = 11; repeated int32 repeated_int32 = 12; repeated int64 repeated_int64 = 13; @@ -46,6 +46,20 @@ message TestMessage { repeated TestEnum repeated_enum = 22; } +message TestSingularFields { + int32 singular_int32 = 1; + int64 singular_int64 = 2; + uint32 singular_uint32 = 3; + uint64 singular_uint64 = 4; + bool singular_bool = 5; + float singular_float = 6; + double singular_double = 7; + string singular_string = 8; + bytes singular_bytes = 9; + TestMessage2 singular_msg = 10; + TestEnum singular_enum = 11; +} + message TestMessage2 { int32 foo = 1; } diff --git a/src/google/protobuf/compiler/ruby/ruby_generator.cc b/src/google/protobuf/compiler/ruby/ruby_generator.cc index 8c0aed1c71..cf61d9995a 100644 --- a/src/google/protobuf/compiler/ruby/ruby_generator.cc +++ b/src/google/protobuf/compiler/ruby/ruby_generator.cc @@ -77,6 +77,10 @@ std::string GetOutputFilename(const std::string& proto_file) { } std::string LabelForField(const FieldDescriptor* field) { + if (field->has_optional_keyword() && + field->file()->syntax() == FileDescriptor::SYNTAX_PROTO3) { + return "proto3_optional"; + } switch (field->label()) { case FieldDescriptor::LABEL_OPTIONAL: return "optional"; case FieldDescriptor::LABEL_REQUIRED: return "required"; @@ -255,12 +259,12 @@ bool GenerateMessage(const Descriptor* message, io::Printer* printer, for (int i = 0; i < message->field_count(); i++) { const FieldDescriptor* field = message->field(i); - if (!field->containing_oneof()) { + if (!field->real_containing_oneof()) { GenerateField(field, printer); } } - for (int i = 0; i < message->oneof_decl_count(); i++) { + for (int i = 0; i < message->real_oneof_decl_count(); i++) { const OneofDescriptor* oneof = message->oneof_decl(i); GenerateOneof(oneof, printer); } diff --git a/src/google/protobuf/compiler/ruby/ruby_generator.h b/src/google/protobuf/compiler/ruby/ruby_generator.h index 731a81a52d..ea4f30a5c5 100644 --- a/src/google/protobuf/compiler/ruby/ruby_generator.h +++ b/src/google/protobuf/compiler/ruby/ruby_generator.h @@ -49,11 +49,12 @@ namespace ruby { // Ruby output, you can do so by registering an instance of this // CodeGenerator with the CommandLineInterface in your main() function. class PROTOC_EXPORT Generator : public CodeGenerator { - virtual bool Generate( - const FileDescriptor* file, - const string& parameter, - GeneratorContext* generator_context, - string* error) const; + bool Generate(const FileDescriptor* file, const string& parameter, + GeneratorContext* generator_context, + string* error) const override; + uint64 GetSupportedFeatures() const override { + return FEATURE_PROTO3_OPTIONAL; + } }; } // namespace ruby From e48c92952d9445309ad1e566ac5557af2ee09c87 Mon Sep 17 00:00:00 2001 From: "David L. Jones" Date: Thu, 23 Apr 2020 12:59:51 -0700 Subject: [PATCH 20/38] Add application note for explicit presence tracking. (#7390) This includes instructions for enabling explicit presence tracking in proto3, and also explains implicit presence. The language examples were written by inspection, and not individually tested. --- docs/field_presence.md | 476 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 476 insertions(+) create mode 100644 docs/field_presence.md diff --git a/docs/field_presence.md b/docs/field_presence.md new file mode 100644 index 0000000000..0491b820d6 --- /dev/null +++ b/docs/field_presence.md @@ -0,0 +1,476 @@ +# Application note: Field presence + +This application note explains the various presence tracking disciplies for protobuf fields. It also explains how to enable experimental support for explicit presence tracking for singular proto3 fields with basic types. + +## Background + +_Field presence_ is the notion of whether a protobuf field has a value. There are two different manifestations of presence for protobufs: _no presence_, where the generated message API stores field values (only), and _explicit presence_, where the API also stores whether or not a field has been set. + +Historically, proto2 has mostly followed _explicit presence_, while proto3 exposes only _no presence_ semantics. Singular proto3 fields of basic types (numeric, string, bytes, and enums) which are defined with the `optional` label have _explicit presence_, like proto2 (this is an experimental feature added as of release 3.12, and must be enabled by passing a flag to `protoc`). + +### Presence disciplines + +_Presence disciplines_ define the semantics for translating between the _API representation_ and the _serialized representation_. The _no presence_ discipline relies upon the field value itself to make decisions at (de)serialization time, while the _explicit presence_ discipline relies upon the explicit tracking state instead. + +### Presence in _tag-value stream_ (wire format) serialization + +The wire format is a stream of tagged, _self-delimiting_ values. By definition, the wire format represents a sequence of _present_ values. In other words, every value found within a serialization represents a _present_ field; furthermore, the serialization contains no information about not-present values. + +The generated API for a proto message includes (de)serialization definitions which translate between API types and a stream of definitionally _present_ (tag, value) pairs. This translation is designed to be forward- and backward-compatibile across changes to the message definition; however, this compatibility introduces some (perhaps surprising) considerations when deserializing wire-formatted messages: + +- When serializing, fields with _no presence_ are not serialized if they contain their default value. + - For numeric types, the default is 0. + - For enums, the default is the zero-valued enumerator. + - For strings, bytes, and repeated fields, the default is the zero-length value. + - For messages, the default is the language-specific null value. +- "Empty" length-delimited values (such as empty strings) can be validly represented in serialized values: the field is "present," in the sense that it appears in the wire format. However, if the generated API does not track presence, then these values may not be re-serialized; i.e., the empty field may be "not present" after a serialization round-trip. +- When deserializing, duplicate field values may be handled in different ways depending on the field definition. + - Duplicate `repeated` fields are typically appended to the field's API representation. (Note that serializing a _packed_ repeated field produces only one, length-delimited value in the tag stream.) + - Duplicate `optional` field values follow the rule that "the last one wins." +- `oneof` fields expose the API-level invariant that only one field is set at a time. However, the wire format may include multiple (tag, value) pairs which notionally belong to the `oneof`. Similar to `optional` fields, the generated API follows the "last one wins" rule. +- Out-of-range values are not returned for enum fields in generated proto2 APIs. However, out-of-range values may be stored as _unknown fields_ in the API, even though the wire-format tag was recognized. + +### Presence in _named-field mapping_ formats + +Protobufs can be represented in human-readable, textual forms. Two notable formats are TextFormat (the output format produced by generated message `DebugString` methods) and JSON. + +These formats have correctness requirements of their own, and are generally stricter than _tagged-value stream_ formats. However, TextFormat more closely mimics the semantics of the wire format, and does, in certain cases, provide similar semantics (for example, appending repeated name-value mappings to a repeated field). In particular, similar to the wire format, TextFormat only includes fields which are present. + +JSON is a much stricter format, however, and cannot validly represent some semantics of the wire format or TextFormat. + +- Notably, JSON _elements_ are semantically unordered, and each member must have a unique name. This is different from TextFormat rules for repeated fields. +- JSON may include fields that are "not present," unlike the _no presence_ discipline for other formats: + - JSON defines a `null` value, which may be used to represent a _defined but not-present field_. + - Repeated field values may be included in the formatted output, even if they are equal to the default (an empty list). +- Because JSON elements are unordered, there is no way to unambiguously interpret the "last one wins" rule. + - In most cases, this is fine: JSON elements must have unique names: repeated field values are not valid JSON, so they do not need to be resolved as they are for TextFormat. + - However, this means that it may not be possible to interpret `oneof` fields unambiguously: if multiple cases are present, they are unordered. + +In theory, JSON _can_ represent presence in a semantic-preserving fashion. In practice, however, presence correctness can vary depending upon implementation choices, especially if JSON was chosen as a means to interoperate with clients not using protobufs. + +### Presence in proto2 APIs + +This table outlines whether presence is tracked for fields in proto2 APIs (both for generated APIs and using dynamic reflection): + +Field type | Explicit Presence +-------------------------------------------- | ----------------- +Singular numeric (integer or floating point) | ✔️ +Singular enum | ✔️ +Singular string or bytes | ✔️ +Singular message | ✔️ +Repeated | +Oneofs | ✔️ +Maps | + +Singular fields (of all types) track presence explicitly in the generated API. The generated message interface includes methods to query presence of fields. For example, the field `foo` has a corresponding `has_foo` method. (The specific name follows the same language-specific naming convention as the field accessors.) These methods are sometimes referred to as "hazzers" within the protobuf implementation. + +Similar to singular fields, `oneof` fields explicitly track which one of the members, if any, contains a value. For example, consider this example `oneof`: + +``` +oneof foo { + int32 a = 1; + float b = 2; +} +``` + +Depending on the target language, the generated API would generally include several methods: + +- A hazzer for the oneof: `has_foo` +- A _oneof case_ method: `foo` +- Hazzers for the members: `has_a`, `has_b` +- Getters for the members: `a`, `b` + +Repeated fields and maps do not track presence: there is no distinction between an _empty_ and a _not-present_ repeated field. + +### Presence in proto3 APIs + +This table outlines whether presence is tracked for fields in proto3 APIs (both for generated APIs and using dynamic reflection): + +Field type | `optional` | Explicit Presence +-------------------------------------------- | ---------- | ----------------- +Singular numeric (integer or floating point) | No | +Singular enum | No | +Singular string or bytes | No | +Singular numeric (integer or floating point) | Yes | ✔️ +Singular enum | Yes | ✔️ +Singular string or bytes | Yes | ✔️ +Singular message | Yes | ✔️ +Singular message | No | ✔️ +Repeated | N/A | +Oneofs | N/A | ✔️ +Maps | N/A | + +Similar to proto2 APIs, proto3 does not track presence explicitly for repeated fields. Without the `optional` label, proto3 APIs do not track presence for basic types (numeric, string, bytes, and enums), either. (Note that `optional` for proto3 fields is only experimentally available as of release 3.12.) Oneof fields affirmatively expose presence, although the same set of hazzer methods may not generated as in proto2 APIs. + +Under the _no presence_ discipline, the default value is synonymous with "not present" for purposes of serialization. To notionally "clear" a field (so it won't be serialized), an API user would set it to the default value. + +The default value for enum-typed fields under _no presence_ is the corresponding 0-valued enumerator. Under proto3 syntax rules, all enum types are required to have an enumerator value which maps to 0. By convention, this is an `UNKNOWN` or similarly-named enumerator. If the zero value is notionally outside the domain of valid values for the application, this behavior can be thought of as tantamount to _explicit presence_. + +## Semantic differences + +The _no presence_ serialization discipline results in visible differences from the _explicit presence_ tracking discipline, when the default value is set. For a singular field with numeric, enum, or string type: + +- _No presence_ discipline: + - Default values are not serialized. + - Default values are _not_ merged-from. + - To "clear" a field, it is set to its default value. + - The default value may mean: + - the field was explicitly set to its default value, which is valid in the application-specific domain of values; + - the field was notionally "cleared" by setting its default; or + - the field was never set. +- _Explicit presence_ discipline: + - Explicitly set values are always serialized, including default values. + - Un-set fields are never merged-from. + - Explicitly set fields -- including default values -- _are_ merged-from. + - A generated `has_foo` method indicates whether or not the field `foo` has been set (and not cleared). + - A generated `clear_foo` method must be used to clear (i.e., un-set) the value. + +### Considerations for merging + +Under the _no presence_ rules, it is effectively impossible for a target field to merge-from its default value (using the protobuf's API merging functions). This is because default values are skipped, simliar to the _no presence_ serialization discipline. Merging only updates the target (merged-to) message using the non-skipped values from the update (merged-from) message. + +The difference in merging behavior has further implications for protocols which rely on partial "patch" updates. If field presence is not tracked, then an update patch alone cannot represent an update to the default value, because only non-default values are merged-from. + +Updating to set a default value in this case requires some external mechanism, such as `FieldMask`. However, if presence _is_ tracked, then all explicitly-set values -- even default values -- will be merged into the target. + +### Considerations for change-compatibility + +Changing a field between _explicit presence_ and _no presence_ is a binary-compatible change for serialized values in wire format. However, the serialized representation of the message may differ, depending on which version of the message definition was used for serialization. Specifically, when a "sender" explicitly sets a field to its default value: + +- The serialized value following _no presence_ discipline does not contain the default value, even though it was explicitly set. +- The serialized value following _explicit presence_ discipline contains every "present" field, even if it contains the default value. + +This change may or may not be safe, depending on the application's semantics. For example, consider two clients with different versions of a message definition. + +Client A uses this definition of the message, which follows the _explicit presence_ serialization discipline for field `foo`: + +``` +syntax = "proto3"; +message Msg { + optional int32 foo = 1; +} +``` + +Client B uses a definition of the same message, except that it follows the _no presence_ discipline: + +``` +syntax = "proto3"; +message Msg { + int32 foo = 1; +} +``` + +Now, consider a scenario where client A observes `foo`'s presence as the clients repeatedly exchange the "same" message by deserializing and reserializing: + +``` +// Client A: +Msg m_a; +m_a.set_foo(1); // non-default value +assert(m_a.has_foo()); // OK +Send(m_a.SerializeAsString()); // to client B + +// Client B: +Msg m_b; +m_b.ParseFromString(Receive()); // from client A +assert(m_b.foo() == 1); // OK +Send(m_b.SerializeAsString()); // to client A + +// Client A: +m_a.ParseFromString(Receive()); // from client B +assert(m_a.foo() == 1); // OK +assert(m_a.has_foo()); // OK +m_a.set_foo(0); // default value +Send(m_a.SerializeAsString()); // to client B + +// Client B: +Msg m_b; +m_b.ParseFromString(Receive()); // from client A +assert(m_b.foo() == 0); // OK +Send(m_b.SerializeAsString()); // to client A + +// Client A: +m_a.ParseFromString(Receive()); // from client B +assert(m_a.foo() == 0); // OK +assert(m_a.has_foo()); // FAIL +``` + +If client A depends on _explicit presence_ for `foo`, then a "round trip" through client B will be lossy from the perspective of client A. In the example, this is not a safe change: client A requires (by `assert`) that the field is present; even without any modifications through the API, that requirement fails in a value- and peer-dependent case. + +## How to enable _explicit presence_ in proto3 + +These are the general steps to use the experimental field tracking support for proto3: + +1. Add an `optional` field to a `.proto` file. +1. Run `protoc` (from release 3.12 or later) with an extra flag to recognize `optional` (i.e,. explicit presence) in proto3 files. +1. Use the generated "hazzer" methods and "clear" methods in application code, instead of comparing or setting default values. + +### `.proto` file changes + +This is an example of a proto3 message with fields which follow both _no presence_ and _explicit presence_ semantics: + +``` +syntax = "proto3"; +package example; + +message MyMessage { + // No presence: + int32 not_tracked = 1; + + // Explicit presence: + optional int32 tracked = 2; +} +``` + +### `protoc` invocation + +To enable presence tracking for proto3 messages, pass the `--experimental_allow_proto3_optional` flag to protoc. Without this flag, the `optional` label is an error in files using proto3 syntax. This flag is available in protobuf release 3.12 or later (or at HEAD, if you are reading this application note from Git). + +### Using the generated code + +The generated code for proto3 fields with _explicit presence_ (the `optional` label) will be the same as it would be in a proto2 file. + +This is the definition used in the "no presence" examples below: + +``` +syntax = "proto3"; +package example; +message Msg { + int32 foo = 1; +} +``` + +This is the definition used in the "explicit presence" examples below: + +``` +syntax = "proto3"; +package example; +message Msg { + optional int32 foo = 1; +} +``` + +In the examples, a function `GetProto` constructs and returns a message of type `Msg` with unspecified contents. + +#### C++ example + +No presence: + +``` +Msg m = GetProto(); +if (m.foo() != 0) { + // "Clear" the field: + m.set_foo(0); +} else { + // Default value: field may not have been present. + m.set_foo(1); +} +``` + +Explicit presence: + +``` +Msg m = GetProto(); +if (m.has_foo()) { + // Clear the field: + m.clear_foo(); +} else { + // Field is not present, so set it. + m.set_foo(1); +} +``` + +#### C# example + +No presence: + +``` +var m = GetProto(); +if (m.Foo != 0) { + // "Clear" the field: + m.Foo = 0; +} else { + // Default value: field may not have been present. + m.Foo = 1; +} +``` + +Explicit presence: + +``` +var m = GetProto(); +if (m.HasFoo) { + // Clear the field: + m.ClearFoo(); +} else { + // Field is not present, so set it. + m.Foo = 1; +} +``` + +#### Go example + +No presence: + +``` +m := GetProto() +if (m.GetFoo() != 0) { + // "Clear" the field: + m.Foo = 0; +} else { + // Default value: field may not have been present. + m.Foo = 1; +} +``` + +Explicit presence: + +``` +m := GetProto() +if (m.HasFoo()) { + // Clear the field: + m.Foo = nil +} else { + // Field is not present, so set it. + m.Foo = proto.Int32(1); +} +``` + +#### Java example + +These examples use a `Builder` to demonstrate clearing. Simply checking presence and getting values from a `Builder` follows the same API as the message type. + +No presence: + +``` +Msg.Builder m = GetProto().toBuilder(); +if (m.getFoo() != 0) { + // "Clear" the field: + m.setFoo(0); +} else { + // Default value: field may not have been present. + m.setFoo(1); +} +``` + +Explicit presence: + +``` +Msg.Builder m = GetProto().toBuilder(); +if (m.hasFoo()) { + // Clear the field: + m.clearFoo() +} else { + // Field is not present, so set it. + m.setFoo(1); +} +``` + +#### Python example + +No presence: + +``` +m = example.Msg() +if m.foo != 0: + // "Clear" the field: + m.foo = 0 +else: + // Default value: field may not have been present. + m.foo = 1 +``` + +Explicit presence: + +``` +m = example.Msg() +if m.HasField('foo'): + // Clear the field: + m.ClearField('foo') +else: + // Field is not present, so set it. + m.foo = 1 +``` + +#### Ruby example + +No presence: + +``` +m = Msg.new +if m.foo != 0 + // "Clear" the field: + m.foo = 0 +else + // Default value: field may not have been present. + m.foo = 1 +end +``` + +Explicit presence: + +``` +m = Msg.new +if m.has_foo? + // Clear the field: + m.clear_foo +else + // Field is not present, so set it. + m.foo = 1 +end +``` + +#### Javascript example + +No presence: + +``` +var m = new Msg(); +if (m.getFoo() != 0) { + // "Clear" the field: + m.setFoo(0); +} else { + // Default value: field may not have been present. + m.setFoo(1); +} +``` + +Explicit presence: + +``` +var m = new Msg(); +if (m.hasFoo()) { + // Clear the field: + m.clearFoo() +} else { + // Field is not present, so set it. + m.setFoo(1); +} +``` + +#### Objective C example + +No presence: + +``` +Msg *m = [[Msg alloc] init]; +if (m.foo != 0) { + // "Clear" the field: + m.foo = 0; +} else { + // Default value: field may not have been present. + m.foo = 1; +} +``` + +Explicit presence: + +``` +Msg *m = [[Msg alloc] init]; +if (m.hasFoo()) { + // Clear the field: + [m clearFoo]; +} else { + // Field is not present, so set it. + [m setFoo:1]; +} +``` From fda8544a596dd3049ed4e826edc63a515c690bfb Mon Sep 17 00:00:00 2001 From: Joshua Haberman Date: Thu, 23 Apr 2020 13:00:30 -0700 Subject: [PATCH 21/38] Howto doc for implementing proto3 presence in a code generator. (#7407) --- docs/implementing_proto3_presence.md | 274 +++++++++++++++++++++++++++ 1 file changed, 274 insertions(+) create mode 100644 docs/implementing_proto3_presence.md diff --git a/docs/implementing_proto3_presence.md b/docs/implementing_proto3_presence.md new file mode 100644 index 0000000000..585b7a2a93 --- /dev/null +++ b/docs/implementing_proto3_presence.md @@ -0,0 +1,274 @@ +# How To Implement Field Presence for Proto3 + +Protobuf release 3.12 adds experimental support for `optional` fields in +proto3. Proto3 optional fields track presence like in proto2. For background +information about what presence tracking means, please see +[docs/field_presence](field_presence.md). + +This document is targeted at developers who own or maintain protobuf code +generators. All code generators will need to be updated to support proto3 +optional fields. First-party code generators developed by Google are being +updated already. However third-party code generators will need to be updated +independently by their authors. This includes: + +- implementations of Protocol Buffers for other languges. +- alternate implementations of Protocol Buffers that target specialized use + cases. +- code generators that implement some utility code on top of protobuf generated + classes. + +While this document speaks in terms of "code generators", these same principles +apply to implementations that dynamically generate a protocol buffer API "on the +fly", directly from a descriptor, in languages that support this kind of usage. + +## Updating a Code Generator + +When a user adds an `optional` field to proto3, this is internally rewritten as +a one-field oneof, for backward-compatibility with reflection-based algorithms: + +```protobuf +syntax = "proto3"; + +message Foo { + // Experimental feature, not generally supported yet! + optional int32 foo = 1; + + // Internally rewritten to: + // oneof _foo { + // int32 foo = 1 [proto3_optional=true]; + // } + // + // We call _foo a "synthetic" oneof, since it was not created by the user. +} +``` + +As a result, the main two goals when updating a code generator are: + +1. Give `optional` fields like `foo` normal field presence, as described in + [docs/field_presence](field_presence.md) If your implementation already + supports proto2, a proto3 `optional` field should use exactly the same API + and internal implementation as proto2 `optional`. +2. Avoid generating any oneof-based accessors for the synthetic oneof. Its only + purpose is to make reflection-based algorithms work properly if they are + not aware of proto3 presence. The synthetic oneof should not appear anywhere + in the generated API. + +### Satisfying the Experimental Check + +If you try to run `protoc` on a file with proto3 `optional` fields, you will get +an error because the feature is still experimental: + +``` +$ cat test.proto +syntax = "proto3"; + +message Foo { + // Experimental feature, not generally supported yet! + optional int32 a = 1; +} +$ protoc --cpp_out=. test.proto +test.proto: This file contains proto3 optional fields, but --experimental_allow_proto3_optional was not set. +``` + +There are two options for getting around this error: + +1. Pass `--experimental_allow_proto3_optional` to protoc. +2. Make your filename (or a directory name) contain the string + `test_proto3_optional`. This indicates that the proto file is specifically + for testing proto3 optional support, so the check is suppressed. + +These options are demonstrated below: + +``` +# One option: +$ ./src/protoc test.proto --cpp_out=. --experimental_allow_proto3_optional + +# Another option: +$ cp test.proto test_proto3_optional.proto +$ ./src/protoc test_proto3_optional.proto --cpp_out=. +$ +``` + +### Signaling That Your Code Generator Supports Proto3 Optional + +If you now try to invoke your own code generator with the test proto, you will +run into a different error: + +``` +$ ./src/protoc test_proto3_optional.proto --my_codegen_out=. +test_proto3_optional.proto: is a proto3 file that contains optional fields, but +code generator --my_codegen_out hasn't been updated to support optional fields in +proto3. Please ask the owner of this code generator to support proto3 optional. +``` + +This check exists to make sure that code generators get a chance to update +before they are used with proto3 `optional` fields. Without this check an old +code generator might emit obsolete generated APIs (like accessors for a +synthetic oneof) and users could start depending on these. That would create +a legacy migration burden once a code generator actually implements the feature. + +To signal that your code generator supports `optional` fields in proto3, you +need to tell `protoc` what features you support. The method for doing this +depends on whether you are using the C++ +`google::protobuf::compiler::CodeGenerator` +framework or not. + +If you are using the CodeGenerator framework: + +```c++ +class MyCodeGenerator : public google::protobuf::compiler::CodeGenerator { + // Add this method. + uint64_t GetSupportedFeatures() const override { + // Indicate that this code generator supports proto3 optional fields. + // (Note: don't release your code generator with this flag set until you + // have actually added and tested your proto3 support!) + return FEATURE_PROTO3_OPTIONAL; + } +} +``` + +If you are generating code using raw `CodeGeneratorRequest` and +`CodeGeneratorResponse` messages from `plugin.proto`, the change will be very +similar: + +```c++ +void GenerateResponse() { + CodeGeneratorResponse response; + response.set_supported_features(CodeGeneratorResponse::FEATURE_PROTO3_OPTIONAL); + + // Generate code... +} +``` + +Once you have added this, you should now be able to successfully use your code +generator to generate a file containing proto3 optional fields: + +``` +$ ./src/protoc test_proto3_optional.proto --my_codegen_out=. +``` + +### Updating Your Code Generator + +Now to actually add support for proto3 optional to your code generator. The goal +is to recognize proto3 optional fields as optional, and suppress any output from +synthetic oneofs. + +If your code generator does not currently support proto2, you will need to +design an API and implementation for supporting presence in scalar fields. +Generally this means: + +- allocating a bit inside the generated class to represent whether a given field + is present or not. +- exposing a `has_foo()` method for each field to return the value of this bit. +- make the parser set this bit when a value is parsed from the wire. +- make the serializer test this bit to decide whether to serialize. + +If your code generator already supports proto2, then most of your work is +already done. All you need to do is make sure that proto3 optional fields have +exactly the same API and behave in exactly the same way as proto2 optional +fields. + +From experience updating several of Google's code generators, most of the +updates that are required fall into one of several patterns. Here we will show +the patterns in terms of the C++ CodeGenerator framework. If you are using +`CodeGeneratorRequest` and `CodeGeneratorReply` directly, you can translate the +C++ examples to your own language, referencing the C++ implementation of these +methods where required. + +#### To test whether a field should have presence + +Old: + +```c++ +bool MessageHasPresence(const google::protobuf::Descriptor* message) { + return message->file()->syntax() == + google::protobuf::FileDescriptor::SYNTAX_PROTO2; +} +``` + +New: + +```c++ +// Presence is no longer a property of a message, it's a property of individual +// fields. +bool FieldHasPresence(const google::protobuf::FieldDescriptor* field) { + return field->has_presence(); + // Note, the above will return true for fields in a oneof. + // If you want to filter out oneof fields, write this instead: + // return field->has_presence && !field->real_containing_oneof() +} +``` + +#### To test whether a field is a member of a oneof + +Old: + +```c++ +bool FieldIsInOneof(const google::protobuf::FielDescriptor* field) { + return field->containing_oneof() != nullptr; +} +``` + +New: + +```c++ +bool FieldIsInOneof(const google::protobuf::FielDescriptor* field) { + // real_containing_oneof() returns nullptr for synthetic oneofs. + return field->real_containing_oneof() != nullptr; +} +``` + +#### To iterate over all oneofs + +Old: + +```c++ +bool IterateOverOneofs(const google::protobuf::Descriptor* message) { + for (int i = 0; i < message->oneof_decl_count(); i++) { + const google::protobuf::OneofDescriptor* oneof = message->oneof(i); + // ... + } +} +``` + +New: + +```c++ +bool IterateOverOneofs(const google::protobuf::Descriptor* message) { + // Real oneofs are always first, and real_oneof_decl_count() will return the + // total number of oneofs, excluding synthetic oneofs. + for (int i = 0; i < message->real_oneof_decl_count(); i++) { + const google::protobuf::OneofDescriptor* oneof = message->oneof(i); + // ... + } +} +``` + +## Updating Reflection + +If your implementation supports protobuf reflection, there are a few changes +that you need to make: + +1. Reflection for synthetic oneofs should work properly. Even though synthetic + oneofs do not really exist in the message, you can still make reflection work + as if they did. In particular, you can make a method like + `Reflection::HasOneof()` or `Reflection::GetOneofFieldDescriptor()` look at + the hasbit to determine if the oneof is present or not. +2. Reflection for proto3 optional fields should work properly. For example, a + method like `Reflection::HasField()` should know to look for the hasbit for a + proto3 `optional` field. It should not be fooled by the synthetic oneof into + thinking that there is a `case` member for the oneof. + +Once you have updated reflection to work properly with proto3 `optional` and +synthetic oneofs, any code that *uses* your reflection interface should work +properly with no changes. This is the benefit of using synthetic oneofs. + +In particular, if you have a reflection-based implementation of protobuf text +format or JSON, it should properly support proto3 optional fields without any +changes to the code. The fields will look like they all belong to a one-field +oneof, and existing proto3 reflection code should know how to test presence for +fields in a oneof. + +So the best way to test your reflection changes is to try round-tripping a +message through text format, JSON, or some other reflection-based parser and +serializer, if you have one. From 7eddac7877b6983cdb23a082dcbe63efe3403b95 Mon Sep 17 00:00:00 2001 From: Joshua Haberman Date: Thu, 23 Apr 2020 14:33:53 -0700 Subject: [PATCH 22/38] Added some info about Reflection, and a note about timeline. (#7416) * Added some info about Reflection, and a note about timeline. * Fixed heading levels. * A bit more info. --- docs/implementing_proto3_presence.md | 80 +++++++++++++++++++++++++++- 1 file changed, 78 insertions(+), 2 deletions(-) diff --git a/docs/implementing_proto3_presence.md b/docs/implementing_proto3_presence.md index 585b7a2a93..08f9c51321 100644 --- a/docs/implementing_proto3_presence.md +++ b/docs/implementing_proto3_presence.md @@ -89,6 +89,13 @@ $ ./src/protoc test_proto3_optional.proto --cpp_out=. $ ``` +The experimental check will be removed in a future release, once we are ready +to make this feature generally available. Ideally this will happen for the 3.13 +release of protobuf, sometime in mid-2020, but there is not a specific date set +for this yet. Some of the timing will depend on feedback we get from the +community, so if you have questions or concerns please get in touch via a +GitHub issue. + ### Signaling That Your Code Generator Supports Proto3 Optional If you now try to invoke your own code generator with the test proto, you will @@ -246,8 +253,44 @@ bool IterateOverOneofs(const google::protobuf::Descriptor* message) { ## Updating Reflection -If your implementation supports protobuf reflection, there are a few changes -that you need to make: +If your implementation offers reflection, there are a few other changes to make: + +### API Changes + +The API for reflecting over fields and oneofs should make the following changes. +These match the changes implemented in C++ reflection. + +1. Add a `FieldDescriptor::has_presence()` method returning `bool` + (adjusted to your language's naming convention). This should return true + for all fields that have explicit presence, as documented in + [docs/field_presence](field_presence.md). In particular, this includes + fields in a oneof, proto2 scalar fields, and proto3 `optional` fields. + This accessor will allow users to query what fields have presence without + thinking about the difference between proto2 and proto3. +2. As a corollary of (1), please do *not* expose an accessor for the + `FieldDescriptorProto.proto3_optional` field. We want to avoid having + users implement any proto2/proto3-specific logic. Users should use the + `has_presence()` function instead. +3. You may also wish to add a `FieldDescriptor::has_optional_keyword()` method + returning `bool`, which indicates whether the `optional` keyword is present. + Message fields will always return `true` for `has_presence()`, so this method + can allow a user to know whether the user wrote `optional` or not. It can + occasionally be useful to have this information, even though it does not + change the presence semantics of the field. +4. If your reflection API may be used for a code generator, you may wish to + implement methods to help users tell the difference between real and + synthetic oneofs. In particular: + - `OneofDescriptor::is_synthetic()`: returns true if this is a synthetic + oneof. + - `FieldDescriptor::real_containing_oneof()`: like `containing_oneof()`, + but returns `nullptr` if the oneof is synthetic. + - `Descriptor::real_oneof_decl_count()`: like `oneof_decl_count()`, but + returns the number of real oneofs only. + +### Implementation Changes + +Proto3 `optional` fields and synthetic oneofs must work correctly when +reflected on. Specifically: 1. Reflection for synthetic oneofs should work properly. Even though synthetic oneofs do not really exist in the message, you can still make reflection work @@ -272,3 +315,36 @@ fields in a oneof. So the best way to test your reflection changes is to try round-tripping a message through text format, JSON, or some other reflection-based parser and serializer, if you have one. + +### Validating Descriptors + +If your reflection implementation supports loading descriptors at runtime, +you must verify that all synthetic oneofs are ordered after all "real" oneofs. + +Here is the code that implements this validation step in C++, for inspiration: + +```c++ + // Validation that runs for each message. + // Synthetic oneofs must be last. + int first_synthetic = -1; + for (int i = 0; i < message->oneof_decl_count(); i++) { + const OneofDescriptor* oneof = message->oneof_decl(i); + if (oneof->is_synthetic()) { + if (first_synthetic == -1) { + first_synthetic = i; + } + } else { + if (first_synthetic != -1) { + AddError(message->full_name(), proto.oneof_decl(i), + DescriptorPool::ErrorCollector::OTHER, + "Synthetic oneofs must be after all other oneofs"); + } + } + } + + if (first_synthetic == -1) { + message->real_oneof_decl_count_ = message->oneof_decl_count_; + } else { + message->real_oneof_decl_count_ = first_synthetic; + } +``` From 4c9613f226dcecd174a1233512632d41373217ef Mon Sep 17 00:00:00 2001 From: Jon Skeet Date: Wed, 15 Apr 2020 11:39:28 +0100 Subject: [PATCH 23/38] Register that the C# compiler supports proto3 presence. (It doesn't yet, but will in the next commits...) --- .../protobuf/compiler/csharp/csharp_generator.cc | 7 +++++++ .../protobuf/compiler/csharp/csharp_generator.h | 13 ++++++++----- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/src/google/protobuf/compiler/csharp/csharp_generator.cc b/src/google/protobuf/compiler/csharp/csharp_generator.cc index b335522032..c2170f17d1 100644 --- a/src/google/protobuf/compiler/csharp/csharp_generator.cc +++ b/src/google/protobuf/compiler/csharp/csharp_generator.cc @@ -48,6 +48,13 @@ namespace protobuf { namespace compiler { namespace csharp { +Generator::Generator() {} +Generator::~Generator() {} + +uint64 Generator::GetSupportedFeatures() const { + return CodeGenerator::Feature::FEATURE_PROTO3_OPTIONAL; +} + void GenerateFile(const FileDescriptor* file, io::Printer* printer, const Options* options) { ReflectionClassGenerator reflectionClassGenerator(file, options); diff --git a/src/google/protobuf/compiler/csharp/csharp_generator.h b/src/google/protobuf/compiler/csharp/csharp_generator.h index da72e0e776..76806db16c 100644 --- a/src/google/protobuf/compiler/csharp/csharp_generator.h +++ b/src/google/protobuf/compiler/csharp/csharp_generator.h @@ -50,11 +50,14 @@ namespace csharp { // CodeGenerator with the CommandLineInterface in your main() function. class PROTOC_EXPORT Generator : public CodeGenerator { public: - virtual bool Generate( - const FileDescriptor* file, - const string& parameter, - GeneratorContext* generator_context, - string* error) const; + Generator(); + ~Generator(); + bool Generate( + const FileDescriptor* file, + const string& parameter, + GeneratorContext* generator_context, + string* error) const override; + uint64 GetSupportedFeatures() const override; }; } // namespace csharp From 4dcafd12cb6b059a6af3ece3409c63f0b136e6b6 Mon Sep 17 00:00:00 2001 From: Jon Skeet Date: Wed, 15 Apr 2020 11:55:05 +0100 Subject: [PATCH 24/38] Support proto3 optional fields in the C# generator Most changes are: - Introducing new helpers of SupportsPresenceApi and RequiresPresenceBit. This allows calling code to be a lot clearer about what it's interested in. - Changing most previous IsProto2 calls to use one of the two new helper methods - Avoiding treating synthetic oneofs as regular ones - Some slight refactoring in csharp_primitive_field to avoid code duplication - Comments explaining what we want when, so the next maintainer doesn't need to do the detective work I did! This change deliberately doesn't modify the API surface of any existing code. The only change to previously-generated C# should be making presence bits more efficient in proto2. Once proto3 optional fields are supported, we can consider further changes to make the proto2 and proto3 generated API surface more consistent (e.g. adding presence API for message fields and oneofs). --- .../compiler/csharp/csharp_field_base.cc | 6 +- .../compiler/csharp/csharp_helpers.cc | 8 +- .../protobuf/compiler/csharp/csharp_helpers.h | 28 +++++ .../compiler/csharp/csharp_message.cc | 101 +++++++++--------- .../compiler/csharp/csharp_message_field.cc | 6 +- .../compiler/csharp/csharp_primitive_field.cc | 69 ++++++++---- .../compiler/csharp/csharp_wrapper_field.cc | 4 +- 7 files changed, 140 insertions(+), 82 deletions(-) diff --git a/src/google/protobuf/compiler/csharp/csharp_field_base.cc b/src/google/protobuf/compiler/csharp/csharp_field_base.cc index 454f4cb144..c69e24807b 100644 --- a/src/google/protobuf/compiler/csharp/csharp_field_base.cc +++ b/src/google/protobuf/compiler/csharp/csharp_field_base.cc @@ -96,13 +96,13 @@ void FieldGeneratorBase::SetCommonFieldVariables( (*variables)["default_value"] = default_value(); (*variables)["capitalized_type_name"] = capitalized_type_name(); (*variables)["number"] = number(); - if (has_default_value() && !IsProto2(descriptor_->file())) { + if (has_default_value() && !SupportsPresenceApi(descriptor_)) { (*variables)["name_def_message"] = (*variables)["name"] + "_ = " + (*variables)["default_value"]; } else { (*variables)["name_def_message"] = (*variables)["name"] + "_"; } - if (IsProto2(descriptor_->file())) { + if (SupportsPresenceApi(descriptor_)) { (*variables)["has_property_check"] = "Has" + (*variables)["property_name"]; (*variables)["other_has_property_check"] = "other.Has" + (*variables)["property_name"]; (*variables)["has_not_property_check"] = "!" + (*variables)["has_property_check"]; @@ -125,7 +125,7 @@ void FieldGeneratorBase::SetCommonFieldVariables( void FieldGeneratorBase::SetCommonOneofFieldVariables( std::map* variables) { (*variables)["oneof_name"] = oneof_name(); - if (IsProto2(descriptor_->file())) { + if (SupportsPresenceApi(descriptor_)) { (*variables)["has_property_check"] = "Has" + property_name(); } else { (*variables)["has_property_check"] = diff --git a/src/google/protobuf/compiler/csharp/csharp_helpers.cc b/src/google/protobuf/compiler/csharp/csharp_helpers.cc index 98aa246c28..c7a0d4fa98 100644 --- a/src/google/protobuf/compiler/csharp/csharp_helpers.cc +++ b/src/google/protobuf/compiler/csharp/csharp_helpers.cc @@ -515,13 +515,13 @@ FieldGeneratorBase* CreateFieldGenerator(const FieldDescriptor* descriptor, } } else { if (IsWrapperType(descriptor)) { - if (descriptor->containing_oneof()) { + if (descriptor->real_containing_oneof()) { return new WrapperOneofFieldGenerator(descriptor, presenceIndex, options); } else { return new WrapperFieldGenerator(descriptor, presenceIndex, options); } } else { - if (descriptor->containing_oneof()) { + if (descriptor->real_containing_oneof()) { return new MessageOneofFieldGenerator(descriptor, presenceIndex, options); } else { return new MessageFieldGenerator(descriptor, presenceIndex, options); @@ -532,7 +532,7 @@ FieldGeneratorBase* CreateFieldGenerator(const FieldDescriptor* descriptor, if (descriptor->is_repeated()) { return new RepeatedEnumFieldGenerator(descriptor, presenceIndex, options); } else { - if (descriptor->containing_oneof()) { + if (descriptor->real_containing_oneof()) { return new EnumOneofFieldGenerator(descriptor, presenceIndex, options); } else { return new EnumFieldGenerator(descriptor, presenceIndex, options); @@ -542,7 +542,7 @@ FieldGeneratorBase* CreateFieldGenerator(const FieldDescriptor* descriptor, if (descriptor->is_repeated()) { return new RepeatedPrimitiveFieldGenerator(descriptor, presenceIndex, options); } else { - if (descriptor->containing_oneof()) { + if (descriptor->real_containing_oneof()) { return new PrimitiveOneofFieldGenerator(descriptor, presenceIndex, options); } else { return new PrimitiveFieldGenerator(descriptor, presenceIndex, options); diff --git a/src/google/protobuf/compiler/csharp/csharp_helpers.h b/src/google/protobuf/compiler/csharp/csharp_helpers.h index 6354e9e6aa..d295bbe803 100644 --- a/src/google/protobuf/compiler/csharp/csharp_helpers.h +++ b/src/google/protobuf/compiler/csharp/csharp_helpers.h @@ -158,6 +158,34 @@ inline bool IsProto2(const FileDescriptor* descriptor) { return descriptor->syntax() == FileDescriptor::SYNTAX_PROTO2; } +inline bool SupportsPresenceApi(const FieldDescriptor* descriptor) { + // We don't use descriptor->is_singular_with_presence() as C# has slightly + // different behavior to other languages. + + if (IsProto2(descriptor->file())) { + // We generate Has/Clear for oneof fields in C#, as well as for messages. + // It's possible that we shouldn't, but stopping doing so would be a + // breaking change for proto2. Fortunately the decision is moot for + // onoeof in proto3: you can't use "optional" inside a oneof. + // Proto2: every singular field has presence. (Even fields in oneofs.) + return !descriptor->is_repeated(); + } else { + // Proto3: only for explictly-optional fields that aren't messages. + // (Repeated fields can never be explicitly optional, so we don't need + // to check for that.) Currently we can't get at proto3_optional directly, + // but we can use has_optional_keyword() as a surrogate check. + return descriptor->has_optional_keyword() && + descriptor->type() != FieldDescriptor::TYPE_MESSAGE; + } +} + +inline bool RequiresPresenceBit(const FieldDescriptor* descriptor) { + return SupportsPresenceApi(descriptor) && + !IsNullable(descriptor) && + !descriptor->is_extension() && + !descriptor->real_containing_oneof(); +} + } // namespace csharp } // namespace compiler } // namespace protobuf diff --git a/src/google/protobuf/compiler/csharp/csharp_message.cc b/src/google/protobuf/compiler/csharp/csharp_message.cc index 67f2892919..d71d2c41db 100644 --- a/src/google/protobuf/compiler/csharp/csharp_message.cc +++ b/src/google/protobuf/compiler/csharp/csharp_message.cc @@ -72,15 +72,13 @@ MessageGenerator::MessageGenerator(const Descriptor* descriptor, std::sort(fields_by_number_.begin(), fields_by_number_.end(), CompareFieldNumbers); - if (IsProto2(descriptor_->file())) { - int primitiveCount = 0; - for (int i = 0; i < descriptor_->field_count(); i++) { - const FieldDescriptor* field = descriptor_->field(i); - if (!IsNullable(field)) { - primitiveCount++; - if (has_bit_field_count_ == 0 || (primitiveCount % 32) == 0) { - has_bit_field_count_++; - } + int presence_bit_count = 0; + for (int i = 0; i < descriptor_->field_count(); i++) { + const FieldDescriptor* field = descriptor_->field(i); + if (RequiresPresenceBit(field)) { + presence_bit_count++; + if (has_bit_field_count_ == 0 || (presence_bit_count % 32) == 0) { + has_bit_field_count_++; } } } @@ -222,11 +220,12 @@ void MessageGenerator::Generate(io::Printer* printer) { printer->Print("\n"); } - // oneof properties - for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { - vars["name"] = UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), false); - vars["property_name"] = UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), true); - vars["original_name"] = descriptor_->oneof_decl(i)->name(); + // oneof properties (for real oneofs, which come before synthetic ones) + for (int i = 0; i < descriptor_->real_oneof_decl_count(); i++) { + const OneofDescriptor* oneof = descriptor_->oneof_decl(i); + vars["name"] = UnderscoresToCamelCase(oneof->name(), false); + vars["property_name"] = UnderscoresToCamelCase(oneof->name(), true); + vars["original_name"] = oneof->name(); printer->Print( vars, "private object $name$_;\n" @@ -234,8 +233,8 @@ void MessageGenerator::Generate(io::Printer* printer) { "public enum $property_name$OneofCase {\n"); printer->Indent(); printer->Print("None = 0,\n"); - for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) { - const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j); + for (int j = 0; j < oneof->field_count(); j++) { + const FieldDescriptor* field = oneof->field(j); printer->Print("$field_property_name$ = $index$,\n", "field_property_name", GetPropertyName(field), "index", StrCat(field->number())); @@ -382,23 +381,24 @@ void MessageGenerator::GenerateCloningCode(io::Printer* printer) { for (int i = 0; i < has_bit_field_count_; i++) { printer->Print("_hasBits$i$ = other._hasBits$i$;\n", "i", StrCat(i)); } - // Clone non-oneof fields first + // Clone non-oneof fields first (treating optional proto3 fields as non-oneof) for (int i = 0; i < descriptor_->field_count(); i++) { - if (!descriptor_->field(i)->containing_oneof()) { - std::unique_ptr generator( - CreateFieldGeneratorInternal(descriptor_->field(i))); - generator->GenerateCloningCode(printer); + const FieldDescriptor* field = descriptor_->field(i); + if (field->real_containing_oneof()) { + continue; } - } - // Clone just the right field for each oneof - for (int i = 0; i < descriptor_->oneof_decl_count(); ++i) { - vars["name"] = UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), false); - vars["property_name"] = UnderscoresToCamelCase( - descriptor_->oneof_decl(i)->name(), true); + std::unique_ptr generator(CreateFieldGeneratorInternal(field)); + generator->GenerateCloningCode(printer); + } + // Clone just the right field for each real oneof + for (int i = 0; i < descriptor_->real_oneof_decl_count(); ++i) { + const OneofDescriptor* oneof = descriptor_->oneof_decl(i); + vars["name"] = UnderscoresToCamelCase(oneof->name(), false); + vars["property_name"] = UnderscoresToCamelCase(oneof->name(), true); printer->Print(vars, "switch (other.$property_name$Case) {\n"); printer->Indent(); - for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) { - const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j); + for (int j = 0; j < oneof->field_count(); j++) { + const FieldDescriptor* field = oneof->field(j); std::unique_ptr generator(CreateFieldGeneratorInternal(field)); vars["field_property_name"] = GetPropertyName(field); printer->Print( @@ -461,9 +461,9 @@ void MessageGenerator::GenerateFrameworkMethods(io::Printer* printer) { CreateFieldGeneratorInternal(descriptor_->field(i))); generator->WriteEquals(printer); } - for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { - printer->Print("if ($property_name$Case != other.$property_name$Case) return false;\n", - "property_name", UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), true)); + for (int i = 0; i < descriptor_->real_oneof_decl_count(); i++) { + printer->Print("if ($property_name$Case != other.$property_name$Case) return false;\n", + "property_name", UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), true)); } if (has_extension_ranges_) { printer->Print( @@ -488,9 +488,9 @@ void MessageGenerator::GenerateFrameworkMethods(io::Printer* printer) { CreateFieldGeneratorInternal(descriptor_->field(i))); generator->WriteHash(printer); } - for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { - printer->Print("hash ^= (int) $name$Case_;\n", - "name", UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), false)); + for (int i = 0; i < descriptor_->real_oneof_decl_count(); i++) { + printer->Print("hash ^= (int) $name$Case_;\n", + "name", UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), false)); } if (has_extension_ranges_) { printer->Print( @@ -589,22 +589,24 @@ void MessageGenerator::GenerateMergingMethods(io::Printer* printer) { "if (other == null) {\n" " return;\n" "}\n"); - // Merge non-oneof fields + // Merge non-oneof fields, treating optional proto3 fields as normal fields for (int i = 0; i < descriptor_->field_count(); i++) { - if (!descriptor_->field(i)->containing_oneof()) { - std::unique_ptr generator( - CreateFieldGeneratorInternal(descriptor_->field(i))); - generator->GenerateMergingCode(printer); + const FieldDescriptor* field = descriptor_->field(i); + if (field->real_containing_oneof()) { + continue; } - } - // Merge oneof fields - for (int i = 0; i < descriptor_->oneof_decl_count(); ++i) { - vars["name"] = UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), false); - vars["property_name"] = UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), true); + std::unique_ptr generator(CreateFieldGeneratorInternal(field)); + generator->GenerateMergingCode(printer); + } + // Merge oneof fields (for non-synthetic oneofs) + for (int i = 0; i < descriptor_->real_oneof_decl_count(); ++i) { + const OneofDescriptor* oneof = descriptor_->oneof_decl(i); + vars["name"] = UnderscoresToCamelCase(oneof->name(), false); + vars["property_name"] = UnderscoresToCamelCase(oneof->name(), true); printer->Print(vars, "switch (other.$property_name$Case) {\n"); printer->Indent(); - for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) { - const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j); + for (int j = 0; j < oneof->field_count(); j++) { + const FieldDescriptor* field = oneof->field(j); vars["field_property_name"] = GetPropertyName(field); printer->Print( vars, @@ -698,8 +700,7 @@ void MessageGenerator::GenerateMergingMethods(io::Printer* printer) { // it's a waste of space to track presence for all values, so we only track them if they're not nullable int MessageGenerator::GetPresenceIndex(const FieldDescriptor* descriptor) { - if (IsNullable(descriptor) || !IsProto2(descriptor->file()) || - descriptor->is_extension()) { + if (!RequiresPresenceBit(descriptor)) { return -1; } @@ -709,7 +710,7 @@ int MessageGenerator::GetPresenceIndex(const FieldDescriptor* descriptor) { if (field == descriptor) { return index; } - if (!IsNullable(field)) { + if (RequiresPresenceBit(field)) { index++; } } diff --git a/src/google/protobuf/compiler/csharp/csharp_message_field.cc b/src/google/protobuf/compiler/csharp/csharp_message_field.cc index 4125798312..034fbd9242 100644 --- a/src/google/protobuf/compiler/csharp/csharp_message_field.cc +++ b/src/google/protobuf/compiler/csharp/csharp_message_field.cc @@ -53,7 +53,7 @@ MessageFieldGenerator::MessageFieldGenerator(const FieldDescriptor* descriptor, int presenceIndex, const Options *options) : FieldGeneratorBase(descriptor, presenceIndex, options) { - if (!IsProto2(descriptor_->file())) { + if (!SupportsPresenceApi(descriptor_)) { variables_["has_property_check"] = name() + "_ != null"; variables_["has_not_property_check"] = name() + "_ == null"; } @@ -77,7 +77,7 @@ void MessageFieldGenerator::GenerateMembers(io::Printer* printer) { " $name$_ = value;\n" " }\n" "}\n"); - if (IsProto2(descriptor_->file())) { + if (SupportsPresenceApi(descriptor_)) { printer->Print( variables_, "/// Gets whether the $descriptor_name$ field is set\n"); @@ -228,7 +228,7 @@ void MessageOneofFieldGenerator::GenerateMembers(io::Printer* printer) { " $oneof_name$Case_ = value == null ? $oneof_property_name$OneofCase.None : $oneof_property_name$OneofCase.$property_name$;\n" " }\n" "}\n"); - if (IsProto2(descriptor_->file())) { + if (SupportsPresenceApi(descriptor_)) { printer->Print( variables_, "/// Gets whether the \"$descriptor_name$\" field is set\n"); diff --git a/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc b/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc index eb7f70dda6..9df1dd6abd 100644 --- a/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc +++ b/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc @@ -53,7 +53,7 @@ PrimitiveFieldGenerator::PrimitiveFieldGenerator( // TODO(jonskeet): Make this cleaner... is_value_type = descriptor->type() != FieldDescriptor::TYPE_STRING && descriptor->type() != FieldDescriptor::TYPE_BYTES; - if (!is_value_type && !IsProto2(descriptor_->file())) { + if (!is_value_type && !SupportsPresenceApi(descriptor_)) { variables_["has_property_check"] = variables_["property_name"] + ".Length != 0"; variables_["other_has_property_check"] = "other." + variables_["property_name"] + ".Length != 0"; } @@ -63,42 +63,65 @@ PrimitiveFieldGenerator::~PrimitiveFieldGenerator() { } void PrimitiveFieldGenerator::GenerateMembers(io::Printer* printer) { - // TODO(jonskeet): Work out whether we want to prevent the fields from ever being - // null, or whether we just handle it, in the cases of bytes and string. - // (Basically, should null-handling code be in the getter or the setter?) + + // Note: in multiple places, this code assumes that all fields + // that support presence are either nullable, or use a presence field bit. + // Fields which are oneof members are not generated here; they're generated in PrimitiveOneofFieldGenerator below. + // Extensions are not generated here either. + + + // Proto2 allows different default values to be specified. These are retained + // via static fields. They don't particularly need to be, but we don't need + // to change that. In Proto3 the default value we don't generate these + // fields, just using the literal instead. if (IsProto2(descriptor_->file())) { + // Note: "private readonly static" isn't as idiomatic as + // "private static readonly", but changing this now would create a lot of + // churn in generated code with near-to-zero benefit. printer->Print( variables_, "private readonly static $type_name$ $property_name$DefaultValue = $default_value$;\n\n"); + variables_["default_value_access"] = + variables_["property_name"] + "DefaultValue"; + } else { + variables_["default_value_access"] = variables_["default_value"]; } + // Declare the field itself. printer->Print( variables_, "private $type_name$ $name_def_message$;\n"); WritePropertyDocComment(printer, descriptor_); AddPublicMemberAttributes(printer); - if (IsProto2(descriptor_->file())) { - if (presenceIndex_ == -1) { + + // Most of the work is done in the property: + // Declare the property itself (the same for all options) + printer->Print(variables_, "$access_level$ $type_name$ $property_name$ {\n"); + + // Specify the "getter", which may need to check for a presence field. + if (SupportsPresenceApi(descriptor_)) { + if (IsNullable(descriptor_)) { printer->Print( variables_, - "$access_level$ $type_name$ $property_name$ {\n" - " get { return $name$_ ?? $property_name$DefaultValue; }\n" - " set {\n"); + " get { return $name$_ ?? $default_value_access$; }\n"); } else { printer->Print( variables_, - "$access_level$ $type_name$ $property_name$ {\n" - " get { if ($has_field_check$) { return $name$_; } else { return $property_name$DefaultValue; } }\n" - " set {\n"); + // Note: it's possible that this could be rewritten as a + // conditional ?: expression, but there's no significant benefit + // to changing it. + " get { if ($has_field_check$) { return $name$_; } else { return $default_value_access$; } }\n"); } } else { printer->Print( variables_, - "$access_level$ $type_name$ $property_name$ {\n" - " get { return $name$_; }\n" - " set {\n"); + " get { return $name$_; }\n"); } + + // Specify the "setter", which may need to set a field bit as well as the + // value. + printer->Print(" set {\n"); if (presenceIndex_ != -1) { printer->Print( variables_, @@ -116,8 +139,11 @@ void PrimitiveFieldGenerator::GenerateMembers(io::Printer* printer) { printer->Print( " }\n" "}\n"); - if (IsProto2(descriptor_->file())) { - printer->Print(variables_, "/// Gets whether the \"$descriptor_name$\" field is set\n"); + + // The "HasFoo" property, where required. + if (SupportsPresenceApi(descriptor_)) { + printer->Print(variables_, + "/// Gets whether the \"$descriptor_name$\" field is set\n"); AddPublicMemberAttributes(printer); printer->Print( variables_, @@ -133,8 +159,11 @@ void PrimitiveFieldGenerator::GenerateMembers(io::Printer* printer) { "$has_field_check$; }\n}\n"); } } - if (IsProto2(descriptor_->file())) { - printer->Print(variables_, "/// Clears the value of the \"$descriptor_name$\" field\n"); + + // The "ClearFoo" method, where required. + if (SupportsPresenceApi(descriptor_)) { + printer->Print(variables_, + "/// Clears the value of the \"$descriptor_name$\" field\n"); AddPublicMemberAttributes(printer); printer->Print( variables_, @@ -270,7 +299,7 @@ void PrimitiveOneofFieldGenerator::GenerateMembers(io::Printer* printer) { " $oneof_name$Case_ = $oneof_property_name$OneofCase.$property_name$;\n" " }\n" "}\n"); - if (IsProto2(descriptor_->file())) { + if (SupportsPresenceApi(descriptor_)) { printer->Print( variables_, "/// Gets whether the \"$descriptor_name$\" field is set\n"); diff --git a/src/google/protobuf/compiler/csharp/csharp_wrapper_field.cc b/src/google/protobuf/compiler/csharp/csharp_wrapper_field.cc index add20ab9fe..2183d752c0 100644 --- a/src/google/protobuf/compiler/csharp/csharp_wrapper_field.cc +++ b/src/google/protobuf/compiler/csharp/csharp_wrapper_field.cc @@ -81,7 +81,7 @@ void WrapperFieldGenerator::GenerateMembers(io::Printer* printer) { " $name$_ = value;\n" " }\n" "}\n\n"); - if (IsProto2(descriptor_->file())) { + if (SupportsPresenceApi(descriptor_)) { printer->Print( variables_, "/// Gets whether the $descriptor_name$ field is set\n"); @@ -219,7 +219,7 @@ void WrapperOneofFieldGenerator::GenerateMembers(io::Printer* printer) { " $oneof_name$Case_ = value == null ? $oneof_property_name$OneofCase.None : $oneof_property_name$OneofCase.$property_name$;\n" " }\n" "}\n"); - if (IsProto2(descriptor_->file())) { + if (SupportsPresenceApi(descriptor_)) { printer->Print( variables_, "/// Gets whether the \"$descriptor_name$\" field is set\n"); From b0649a088a89b65f16b02428208e82afc92e808e Mon Sep 17 00:00:00 2001 From: Jon Skeet Date: Wed, 15 Apr 2020 11:57:38 +0100 Subject: [PATCH 25/38] Regenerate C# code with the new generator, adding unittest_proto3_optional.proto The changes in the existing proto2 code are solely around presence bits. The new generator allocated presence bits more efficiently. (Previously bits were sometimes allocated but never used.) --- csharp/generate_protos.sh | 3 +- .../TestMessagesProto2.cs | 144 +-- .../Unittest.cs | 12 +- .../UnittestProto3Optional.cs | 1072 +++++++++++++++++ csharp/src/Google.Protobuf.Test/testprotos.pb | Bin 328798 -> 334214 bytes 5 files changed, 1150 insertions(+), 81 deletions(-) create mode 100644 csharp/src/Google.Protobuf.Test.TestProtos/UnittestProto3Optional.cs diff --git a/csharp/generate_protos.sh b/csharp/generate_protos.sh index e6687c308e..0508584d7e 100755 --- a/csharp/generate_protos.sh +++ b/csharp/generate_protos.sh @@ -63,7 +63,8 @@ $PROTOC -Isrc -Icsharp/protos \ csharp/protos/unittest_issue6936_c.proto \ src/google/protobuf/unittest_well_known_types.proto \ src/google/protobuf/test_messages_proto3.proto \ - src/google/protobuf/test_messages_proto2.proto + src/google/protobuf/test_messages_proto2.proto \ + src/google/protobuf/unittest_proto3_optional.proto # AddressBook sample protos $PROTOC -Iexamples -Isrc --csharp_out=csharp/src/AddressBook \ diff --git a/csharp/src/Google.Protobuf.Test.TestProtos/TestMessagesProto2.cs b/csharp/src/Google.Protobuf.Test.TestProtos/TestMessagesProto2.cs index 350fb7cde7..1ba1275fb6 100644 --- a/csharp/src/Google.Protobuf.Test.TestProtos/TestMessagesProto2.cs +++ b/csharp/src/Google.Protobuf.Test.TestProtos/TestMessagesProto2.cs @@ -1872,21 +1872,21 @@ namespace ProtobufTestMessages.Proto2 { ///
[global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int Fieldname1 { - get { if ((_hasBits0 & 2097152) != 0) { return fieldname1_; } else { return Fieldname1DefaultValue; } } + get { if ((_hasBits0 & 32768) != 0) { return fieldname1_; } else { return Fieldname1DefaultValue; } } set { - _hasBits0 |= 2097152; + _hasBits0 |= 32768; fieldname1_ = value; } } /// Gets whether the "fieldname1" field is set [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public bool HasFieldname1 { - get { return (_hasBits0 & 2097152) != 0; } + get { return (_hasBits0 & 32768) != 0; } } /// Clears the value of the "fieldname1" field [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void ClearFieldname1() { - _hasBits0 &= ~2097152; + _hasBits0 &= ~32768; } /// Field number for the "field_name2" field. @@ -1896,21 +1896,21 @@ namespace ProtobufTestMessages.Proto2 { private int fieldName2_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int FieldName2 { - get { if ((_hasBits0 & 4194304) != 0) { return fieldName2_; } else { return FieldName2DefaultValue; } } + get { if ((_hasBits0 & 65536) != 0) { return fieldName2_; } else { return FieldName2DefaultValue; } } set { - _hasBits0 |= 4194304; + _hasBits0 |= 65536; fieldName2_ = value; } } /// Gets whether the "field_name2" field is set [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public bool HasFieldName2 { - get { return (_hasBits0 & 4194304) != 0; } + get { return (_hasBits0 & 65536) != 0; } } /// Clears the value of the "field_name2" field [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void ClearFieldName2() { - _hasBits0 &= ~4194304; + _hasBits0 &= ~65536; } /// Field number for the "_field_name3" field. @@ -1920,21 +1920,21 @@ namespace ProtobufTestMessages.Proto2 { private int FieldName3_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int FieldName3 { - get { if ((_hasBits0 & 8388608) != 0) { return FieldName3_; } else { return FieldName3DefaultValue; } } + get { if ((_hasBits0 & 131072) != 0) { return FieldName3_; } else { return FieldName3DefaultValue; } } set { - _hasBits0 |= 8388608; + _hasBits0 |= 131072; FieldName3_ = value; } } /// Gets whether the "_field_name3" field is set [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public bool HasFieldName3 { - get { return (_hasBits0 & 8388608) != 0; } + get { return (_hasBits0 & 131072) != 0; } } /// Clears the value of the "_field_name3" field [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void ClearFieldName3() { - _hasBits0 &= ~8388608; + _hasBits0 &= ~131072; } /// Field number for the "field__name4_" field. @@ -1944,21 +1944,21 @@ namespace ProtobufTestMessages.Proto2 { private int fieldName4_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int FieldName4 { - get { if ((_hasBits0 & 16777216) != 0) { return fieldName4_; } else { return FieldName4DefaultValue; } } + get { if ((_hasBits0 & 262144) != 0) { return fieldName4_; } else { return FieldName4DefaultValue; } } set { - _hasBits0 |= 16777216; + _hasBits0 |= 262144; fieldName4_ = value; } } /// Gets whether the "field__name4_" field is set [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public bool HasFieldName4 { - get { return (_hasBits0 & 16777216) != 0; } + get { return (_hasBits0 & 262144) != 0; } } /// Clears the value of the "field__name4_" field [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void ClearFieldName4() { - _hasBits0 &= ~16777216; + _hasBits0 &= ~262144; } /// Field number for the "field0name5" field. @@ -1968,21 +1968,21 @@ namespace ProtobufTestMessages.Proto2 { private int field0Name5_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int Field0Name5 { - get { if ((_hasBits0 & 33554432) != 0) { return field0Name5_; } else { return Field0Name5DefaultValue; } } + get { if ((_hasBits0 & 524288) != 0) { return field0Name5_; } else { return Field0Name5DefaultValue; } } set { - _hasBits0 |= 33554432; + _hasBits0 |= 524288; field0Name5_ = value; } } /// Gets whether the "field0name5" field is set [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public bool HasField0Name5 { - get { return (_hasBits0 & 33554432) != 0; } + get { return (_hasBits0 & 524288) != 0; } } /// Clears the value of the "field0name5" field [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void ClearField0Name5() { - _hasBits0 &= ~33554432; + _hasBits0 &= ~524288; } /// Field number for the "field_0_name6" field. @@ -1992,21 +1992,21 @@ namespace ProtobufTestMessages.Proto2 { private int field0Name6_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int Field0Name6 { - get { if ((_hasBits0 & 67108864) != 0) { return field0Name6_; } else { return Field0Name6DefaultValue; } } + get { if ((_hasBits0 & 1048576) != 0) { return field0Name6_; } else { return Field0Name6DefaultValue; } } set { - _hasBits0 |= 67108864; + _hasBits0 |= 1048576; field0Name6_ = value; } } /// Gets whether the "field_0_name6" field is set [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public bool HasField0Name6 { - get { return (_hasBits0 & 67108864) != 0; } + get { return (_hasBits0 & 1048576) != 0; } } /// Clears the value of the "field_0_name6" field [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void ClearField0Name6() { - _hasBits0 &= ~67108864; + _hasBits0 &= ~1048576; } /// Field number for the "fieldName7" field. @@ -2016,21 +2016,21 @@ namespace ProtobufTestMessages.Proto2 { private int fieldName7_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int FieldName7 { - get { if ((_hasBits0 & 134217728) != 0) { return fieldName7_; } else { return FieldName7DefaultValue; } } + get { if ((_hasBits0 & 2097152) != 0) { return fieldName7_; } else { return FieldName7DefaultValue; } } set { - _hasBits0 |= 134217728; + _hasBits0 |= 2097152; fieldName7_ = value; } } /// Gets whether the "fieldName7" field is set [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public bool HasFieldName7 { - get { return (_hasBits0 & 134217728) != 0; } + get { return (_hasBits0 & 2097152) != 0; } } /// Clears the value of the "fieldName7" field [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void ClearFieldName7() { - _hasBits0 &= ~134217728; + _hasBits0 &= ~2097152; } /// Field number for the "FieldName8" field. @@ -2040,21 +2040,21 @@ namespace ProtobufTestMessages.Proto2 { private int fieldName8_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int FieldName8 { - get { if ((_hasBits0 & 268435456) != 0) { return fieldName8_; } else { return FieldName8DefaultValue; } } + get { if ((_hasBits0 & 4194304) != 0) { return fieldName8_; } else { return FieldName8DefaultValue; } } set { - _hasBits0 |= 268435456; + _hasBits0 |= 4194304; fieldName8_ = value; } } /// Gets whether the "FieldName8" field is set [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public bool HasFieldName8 { - get { return (_hasBits0 & 268435456) != 0; } + get { return (_hasBits0 & 4194304) != 0; } } /// Clears the value of the "FieldName8" field [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void ClearFieldName8() { - _hasBits0 &= ~268435456; + _hasBits0 &= ~4194304; } /// Field number for the "field_Name9" field. @@ -2064,21 +2064,21 @@ namespace ProtobufTestMessages.Proto2 { private int fieldName9_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int FieldName9 { - get { if ((_hasBits0 & 536870912) != 0) { return fieldName9_; } else { return FieldName9DefaultValue; } } + get { if ((_hasBits0 & 8388608) != 0) { return fieldName9_; } else { return FieldName9DefaultValue; } } set { - _hasBits0 |= 536870912; + _hasBits0 |= 8388608; fieldName9_ = value; } } /// Gets whether the "field_Name9" field is set [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public bool HasFieldName9 { - get { return (_hasBits0 & 536870912) != 0; } + get { return (_hasBits0 & 8388608) != 0; } } /// Clears the value of the "field_Name9" field [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void ClearFieldName9() { - _hasBits0 &= ~536870912; + _hasBits0 &= ~8388608; } /// Field number for the "Field_Name10" field. @@ -2088,21 +2088,21 @@ namespace ProtobufTestMessages.Proto2 { private int fieldName10_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int FieldName10 { - get { if ((_hasBits0 & 1073741824) != 0) { return fieldName10_; } else { return FieldName10DefaultValue; } } + get { if ((_hasBits0 & 16777216) != 0) { return fieldName10_; } else { return FieldName10DefaultValue; } } set { - _hasBits0 |= 1073741824; + _hasBits0 |= 16777216; fieldName10_ = value; } } /// Gets whether the "Field_Name10" field is set [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public bool HasFieldName10 { - get { return (_hasBits0 & 1073741824) != 0; } + get { return (_hasBits0 & 16777216) != 0; } } /// Clears the value of the "Field_Name10" field [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void ClearFieldName10() { - _hasBits0 &= ~1073741824; + _hasBits0 &= ~16777216; } /// Field number for the "FIELD_NAME11" field. @@ -2112,21 +2112,21 @@ namespace ProtobufTestMessages.Proto2 { private int fIELDNAME11_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int FIELDNAME11 { - get { if ((_hasBits0 & -2147483648) != 0) { return fIELDNAME11_; } else { return FIELDNAME11DefaultValue; } } + get { if ((_hasBits0 & 33554432) != 0) { return fIELDNAME11_; } else { return FIELDNAME11DefaultValue; } } set { - _hasBits0 |= -2147483648; + _hasBits0 |= 33554432; fIELDNAME11_ = value; } } /// Gets whether the "FIELD_NAME11" field is set [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public bool HasFIELDNAME11 { - get { return (_hasBits0 & -2147483648) != 0; } + get { return (_hasBits0 & 33554432) != 0; } } /// Clears the value of the "FIELD_NAME11" field [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void ClearFIELDNAME11() { - _hasBits0 &= ~-2147483648; + _hasBits0 &= ~33554432; } /// Field number for the "FIELD_name12" field. @@ -2136,21 +2136,21 @@ namespace ProtobufTestMessages.Proto2 { private int fIELDName12_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int FIELDName12 { - get { if ((_hasBits1 & 1) != 0) { return fIELDName12_; } else { return FIELDName12DefaultValue; } } + get { if ((_hasBits0 & 67108864) != 0) { return fIELDName12_; } else { return FIELDName12DefaultValue; } } set { - _hasBits1 |= 1; + _hasBits0 |= 67108864; fIELDName12_ = value; } } /// Gets whether the "FIELD_name12" field is set [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public bool HasFIELDName12 { - get { return (_hasBits1 & 1) != 0; } + get { return (_hasBits0 & 67108864) != 0; } } /// Clears the value of the "FIELD_name12" field [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void ClearFIELDName12() { - _hasBits1 &= ~1; + _hasBits0 &= ~67108864; } /// Field number for the "__field_name13" field. @@ -2160,21 +2160,21 @@ namespace ProtobufTestMessages.Proto2 { private int FieldName13_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int FieldName13 { - get { if ((_hasBits1 & 2) != 0) { return FieldName13_; } else { return FieldName13DefaultValue; } } + get { if ((_hasBits0 & 134217728) != 0) { return FieldName13_; } else { return FieldName13DefaultValue; } } set { - _hasBits1 |= 2; + _hasBits0 |= 134217728; FieldName13_ = value; } } /// Gets whether the "__field_name13" field is set [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public bool HasFieldName13 { - get { return (_hasBits1 & 2) != 0; } + get { return (_hasBits0 & 134217728) != 0; } } /// Clears the value of the "__field_name13" field [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void ClearFieldName13() { - _hasBits1 &= ~2; + _hasBits0 &= ~134217728; } /// Field number for the "__Field_name14" field. @@ -2184,21 +2184,21 @@ namespace ProtobufTestMessages.Proto2 { private int FieldName14_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int FieldName14 { - get { if ((_hasBits1 & 4) != 0) { return FieldName14_; } else { return FieldName14DefaultValue; } } + get { if ((_hasBits0 & 268435456) != 0) { return FieldName14_; } else { return FieldName14DefaultValue; } } set { - _hasBits1 |= 4; + _hasBits0 |= 268435456; FieldName14_ = value; } } /// Gets whether the "__Field_name14" field is set [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public bool HasFieldName14 { - get { return (_hasBits1 & 4) != 0; } + get { return (_hasBits0 & 268435456) != 0; } } /// Clears the value of the "__Field_name14" field [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void ClearFieldName14() { - _hasBits1 &= ~4; + _hasBits0 &= ~268435456; } /// Field number for the "field__name15" field. @@ -2208,21 +2208,21 @@ namespace ProtobufTestMessages.Proto2 { private int fieldName15_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int FieldName15 { - get { if ((_hasBits1 & 8) != 0) { return fieldName15_; } else { return FieldName15DefaultValue; } } + get { if ((_hasBits0 & 536870912) != 0) { return fieldName15_; } else { return FieldName15DefaultValue; } } set { - _hasBits1 |= 8; + _hasBits0 |= 536870912; fieldName15_ = value; } } /// Gets whether the "field__name15" field is set [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public bool HasFieldName15 { - get { return (_hasBits1 & 8) != 0; } + get { return (_hasBits0 & 536870912) != 0; } } /// Clears the value of the "field__name15" field [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void ClearFieldName15() { - _hasBits1 &= ~8; + _hasBits0 &= ~536870912; } /// Field number for the "field__Name16" field. @@ -2232,21 +2232,21 @@ namespace ProtobufTestMessages.Proto2 { private int fieldName16_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int FieldName16 { - get { if ((_hasBits1 & 16) != 0) { return fieldName16_; } else { return FieldName16DefaultValue; } } + get { if ((_hasBits0 & 1073741824) != 0) { return fieldName16_; } else { return FieldName16DefaultValue; } } set { - _hasBits1 |= 16; + _hasBits0 |= 1073741824; fieldName16_ = value; } } /// Gets whether the "field__Name16" field is set [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public bool HasFieldName16 { - get { return (_hasBits1 & 16) != 0; } + get { return (_hasBits0 & 1073741824) != 0; } } /// Clears the value of the "field__Name16" field [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void ClearFieldName16() { - _hasBits1 &= ~16; + _hasBits0 &= ~1073741824; } /// Field number for the "field_name17__" field. @@ -2256,21 +2256,21 @@ namespace ProtobufTestMessages.Proto2 { private int fieldName17_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int FieldName17 { - get { if ((_hasBits1 & 32) != 0) { return fieldName17_; } else { return FieldName17DefaultValue; } } + get { if ((_hasBits0 & -2147483648) != 0) { return fieldName17_; } else { return FieldName17DefaultValue; } } set { - _hasBits1 |= 32; + _hasBits0 |= -2147483648; fieldName17_ = value; } } /// Gets whether the "field_name17__" field is set [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public bool HasFieldName17 { - get { return (_hasBits1 & 32) != 0; } + get { return (_hasBits0 & -2147483648) != 0; } } /// Clears the value of the "field_name17__" field [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void ClearFieldName17() { - _hasBits1 &= ~32; + _hasBits0 &= ~-2147483648; } /// Field number for the "Field_name18__" field. @@ -2280,21 +2280,21 @@ namespace ProtobufTestMessages.Proto2 { private int fieldName18_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int FieldName18 { - get { if ((_hasBits1 & 64) != 0) { return fieldName18_; } else { return FieldName18DefaultValue; } } + get { if ((_hasBits1 & 1) != 0) { return fieldName18_; } else { return FieldName18DefaultValue; } } set { - _hasBits1 |= 64; + _hasBits1 |= 1; fieldName18_ = value; } } /// Gets whether the "Field_name18__" field is set [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public bool HasFieldName18 { - get { return (_hasBits1 & 64) != 0; } + get { return (_hasBits1 & 1) != 0; } } /// Clears the value of the "Field_name18__" field [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void ClearFieldName18() { - _hasBits1 &= ~64; + _hasBits1 &= ~1; } private object oneofField_; diff --git a/csharp/src/Google.Protobuf.Test.TestProtos/Unittest.cs b/csharp/src/Google.Protobuf.Test.TestProtos/Unittest.cs index a35b6e0fe3..25fecb9b29 100644 --- a/csharp/src/Google.Protobuf.Test.TestProtos/Unittest.cs +++ b/csharp/src/Google.Protobuf.Test.TestProtos/Unittest.cs @@ -15521,7 +15521,6 @@ namespace Google.Protobuf.TestProtos.Proto2 { public sealed partial class TestOneof : pb::IMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestOneof()); private pb::UnknownFieldSet _unknownFields; - private int _hasBits0; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pb::MessageParser Parser { get { return _parser; } } @@ -15544,7 +15543,6 @@ namespace Google.Protobuf.TestProtos.Proto2 { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public TestOneof(TestOneof other) : this() { - _hasBits0 = other._hasBits0; switch (other.FooCase) { case FooOneofCase.FooInt: FooInt = other.FooInt; @@ -16934,21 +16932,21 @@ namespace Google.Protobuf.TestProtos.Proto2 { private int bazInt_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int BazInt { - get { if ((_hasBits0 & 16) != 0) { return bazInt_; } else { return BazIntDefaultValue; } } + get { if ((_hasBits0 & 1) != 0) { return bazInt_; } else { return BazIntDefaultValue; } } set { - _hasBits0 |= 16; + _hasBits0 |= 1; bazInt_ = value; } } /// Gets whether the "baz_int" field is set [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public bool HasBazInt { - get { return (_hasBits0 & 16) != 0; } + get { return (_hasBits0 & 1) != 0; } } /// Clears the value of the "baz_int" field [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void ClearBazInt() { - _hasBits0 &= ~16; + _hasBits0 &= ~1; } /// Field number for the "baz_string" field. @@ -17767,7 +17765,6 @@ namespace Google.Protobuf.TestProtos.Proto2 { public sealed partial class TestRequiredOneof : pb::IMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestRequiredOneof()); private pb::UnknownFieldSet _unknownFields; - private int _hasBits0; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pb::MessageParser Parser { get { return _parser; } } @@ -17790,7 +17787,6 @@ namespace Google.Protobuf.TestProtos.Proto2 { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public TestRequiredOneof(TestRequiredOneof other) : this() { - _hasBits0 = other._hasBits0; switch (other.FooCase) { case FooOneofCase.FooInt: FooInt = other.FooInt; diff --git a/csharp/src/Google.Protobuf.Test.TestProtos/UnittestProto3Optional.cs b/csharp/src/Google.Protobuf.Test.TestProtos/UnittestProto3Optional.cs new file mode 100644 index 0000000000..cbad5899e5 --- /dev/null +++ b/csharp/src/Google.Protobuf.Test.TestProtos/UnittestProto3Optional.cs @@ -0,0 +1,1072 @@ +// +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: google/protobuf/unittest_proto3_optional.proto +// +#pragma warning disable 1591, 0612, 3021 +#region Designer generated code + +using pb = global::Google.Protobuf; +using pbc = global::Google.Protobuf.Collections; +using pbr = global::Google.Protobuf.Reflection; +using scg = global::System.Collections.Generic; +namespace ProtobufUnittest { + + /// Holder for reflection information generated from google/protobuf/unittest_proto3_optional.proto + public static partial class UnittestProto3OptionalReflection { + + #region Descriptor + /// File descriptor for google/protobuf/unittest_proto3_optional.proto + public static pbr::FileDescriptor Descriptor { + get { return descriptor; } + } + private static pbr::FileDescriptor descriptor; + + static UnittestProto3OptionalReflection() { + byte[] descriptorData = global::System.Convert.FromBase64String( + string.Concat( + "Ci5nb29nbGUvcHJvdG9idWYvdW5pdHRlc3RfcHJvdG8zX29wdGlvbmFsLnBy", + "b3RvEhFwcm90b2J1Zl91bml0dGVzdCKBCgoSVGVzdFByb3RvM09wdGlvbmFs", + "EhsKDm9wdGlvbmFsX2ludDMyGAEgASgFSACIAQESGwoOb3B0aW9uYWxfaW50", + "NjQYAiABKANIAYgBARIcCg9vcHRpb25hbF91aW50MzIYAyABKA1IAogBARIc", + "Cg9vcHRpb25hbF91aW50NjQYBCABKARIA4gBARIcCg9vcHRpb25hbF9zaW50", + "MzIYBSABKBFIBIgBARIcCg9vcHRpb25hbF9zaW50NjQYBiABKBJIBYgBARId", + "ChBvcHRpb25hbF9maXhlZDMyGAcgASgHSAaIAQESHQoQb3B0aW9uYWxfZml4", + "ZWQ2NBgIIAEoBkgHiAEBEh4KEW9wdGlvbmFsX3NmaXhlZDMyGAkgASgPSAiI", + "AQESHgoRb3B0aW9uYWxfc2ZpeGVkNjQYCiABKBBICYgBARIbCg5vcHRpb25h", + "bF9mbG9hdBgLIAEoAkgKiAEBEhwKD29wdGlvbmFsX2RvdWJsZRgMIAEoAUgL", + "iAEBEhoKDW9wdGlvbmFsX2Jvb2wYDSABKAhIDIgBARIcCg9vcHRpb25hbF9z", + "dHJpbmcYDiABKAlIDYgBARIbCg5vcHRpb25hbF9ieXRlcxgPIAEoDEgOiAEB", + "Eh4KDW9wdGlvbmFsX2NvcmQYECABKAlCAggBSA+IAQESWQoXb3B0aW9uYWxf", + "bmVzdGVkX21lc3NhZ2UYEiABKAsyMy5wcm90b2J1Zl91bml0dGVzdC5UZXN0", + "UHJvdG8zT3B0aW9uYWwuTmVzdGVkTWVzc2FnZUgQiAEBElkKE2xhenlfbmVz", + "dGVkX21lc3NhZ2UYEyABKAsyMy5wcm90b2J1Zl91bml0dGVzdC5UZXN0UHJv", + "dG8zT3B0aW9uYWwuTmVzdGVkTWVzc2FnZUICKAFIEYgBARJTChRvcHRpb25h", + "bF9uZXN0ZWRfZW51bRgVIAEoDjIwLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RQ", + "cm90bzNPcHRpb25hbC5OZXN0ZWRFbnVtSBKIAQEaJwoNTmVzdGVkTWVzc2Fn", + "ZRIPCgJiYhgBIAEoBUgAiAEBQgUKA19iYiJKCgpOZXN0ZWRFbnVtEg8KC1VO", + "U1BFQ0lGSUVEEAASBwoDRk9PEAESBwoDQkFSEAISBwoDQkFaEAMSEAoDTkVH", + "EP///////////wFCEQoPX29wdGlvbmFsX2ludDMyQhEKD19vcHRpb25hbF9p", + "bnQ2NEISChBfb3B0aW9uYWxfdWludDMyQhIKEF9vcHRpb25hbF91aW50NjRC", + "EgoQX29wdGlvbmFsX3NpbnQzMkISChBfb3B0aW9uYWxfc2ludDY0QhMKEV9v", + "cHRpb25hbF9maXhlZDMyQhMKEV9vcHRpb25hbF9maXhlZDY0QhQKEl9vcHRp", + "b25hbF9zZml4ZWQzMkIUChJfb3B0aW9uYWxfc2ZpeGVkNjRCEQoPX29wdGlv", + "bmFsX2Zsb2F0QhIKEF9vcHRpb25hbF9kb3VibGVCEAoOX29wdGlvbmFsX2Jv", + "b2xCEgoQX29wdGlvbmFsX3N0cmluZ0IRCg9fb3B0aW9uYWxfYnl0ZXNCEAoO", + "X29wdGlvbmFsX2NvcmRCGgoYX29wdGlvbmFsX25lc3RlZF9tZXNzYWdlQhYK", + "FF9sYXp5X25lc3RlZF9tZXNzYWdlQhcKFV9vcHRpb25hbF9uZXN0ZWRfZW51", + "bUIlCiFjb20uZ29vZ2xlLnByb3RvYnVmLnRlc3RpbmcucHJvdG9QAWIGcHJv", + "dG8z")); + descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, + new pbr::FileDescriptor[] { }, + new pbr::GeneratedClrTypeInfo(null, null, new pbr::GeneratedClrTypeInfo[] { + new pbr::GeneratedClrTypeInfo(typeof(global::ProtobufUnittest.TestProto3Optional), global::ProtobufUnittest.TestProto3Optional.Parser, new[]{ "OptionalInt32", "OptionalInt64", "OptionalUint32", "OptionalUint64", "OptionalSint32", "OptionalSint64", "OptionalFixed32", "OptionalFixed64", "OptionalSfixed32", "OptionalSfixed64", "OptionalFloat", "OptionalDouble", "OptionalBool", "OptionalString", "OptionalBytes", "OptionalCord", "OptionalNestedMessage", "LazyNestedMessage", "OptionalNestedEnum" }, new[]{ "OptionalInt32", "OptionalInt64", "OptionalUint32", "OptionalUint64", "OptionalSint32", "OptionalSint64", "OptionalFixed32", "OptionalFixed64", "OptionalSfixed32", "OptionalSfixed64", "OptionalFloat", "OptionalDouble", "OptionalBool", "OptionalString", "OptionalBytes", "OptionalCord", "OptionalNestedMessage", "LazyNestedMessage", "OptionalNestedEnum" }, new[]{ typeof(global::ProtobufUnittest.TestProto3Optional.Types.NestedEnum) }, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::ProtobufUnittest.TestProto3Optional.Types.NestedMessage), global::ProtobufUnittest.TestProto3Optional.Types.NestedMessage.Parser, new[]{ "Bb" }, new[]{ "Bb" }, null, null, null)}) + })); + } + #endregion + + } + #region Messages + public sealed partial class TestProto3Optional : pb::IMessage { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestProto3Optional()); + private pb::UnknownFieldSet _unknownFields; + private int _hasBits0; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::ProtobufUnittest.UnittestProto3OptionalReflection.Descriptor.MessageTypes[0]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestProto3Optional() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestProto3Optional(TestProto3Optional other) : this() { + _hasBits0 = other._hasBits0; + optionalInt32_ = other.optionalInt32_; + optionalInt64_ = other.optionalInt64_; + optionalUint32_ = other.optionalUint32_; + optionalUint64_ = other.optionalUint64_; + optionalSint32_ = other.optionalSint32_; + optionalSint64_ = other.optionalSint64_; + optionalFixed32_ = other.optionalFixed32_; + optionalFixed64_ = other.optionalFixed64_; + optionalSfixed32_ = other.optionalSfixed32_; + optionalSfixed64_ = other.optionalSfixed64_; + optionalFloat_ = other.optionalFloat_; + optionalDouble_ = other.optionalDouble_; + optionalBool_ = other.optionalBool_; + optionalString_ = other.optionalString_; + optionalBytes_ = other.optionalBytes_; + optionalCord_ = other.optionalCord_; + optionalNestedMessage_ = other.optionalNestedMessage_ != null ? other.optionalNestedMessage_.Clone() : null; + lazyNestedMessage_ = other.lazyNestedMessage_ != null ? other.lazyNestedMessage_.Clone() : null; + optionalNestedEnum_ = other.optionalNestedEnum_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestProto3Optional Clone() { + return new TestProto3Optional(this); + } + + /// Field number for the "optional_int32" field. + public const int OptionalInt32FieldNumber = 1; + private int optionalInt32_; + /// + /// Singular + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int OptionalInt32 { + get { if ((_hasBits0 & 1) != 0) { return optionalInt32_; } else { return 0; } } + set { + _hasBits0 |= 1; + optionalInt32_ = value; + } + } + /// Gets whether the "optional_int32" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasOptionalInt32 { + get { return (_hasBits0 & 1) != 0; } + } + /// Clears the value of the "optional_int32" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearOptionalInt32() { + _hasBits0 &= ~1; + } + + /// Field number for the "optional_int64" field. + public const int OptionalInt64FieldNumber = 2; + private long optionalInt64_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public long OptionalInt64 { + get { if ((_hasBits0 & 2) != 0) { return optionalInt64_; } else { return 0L; } } + set { + _hasBits0 |= 2; + optionalInt64_ = value; + } + } + /// Gets whether the "optional_int64" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasOptionalInt64 { + get { return (_hasBits0 & 2) != 0; } + } + /// Clears the value of the "optional_int64" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearOptionalInt64() { + _hasBits0 &= ~2; + } + + /// Field number for the "optional_uint32" field. + public const int OptionalUint32FieldNumber = 3; + private uint optionalUint32_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public uint OptionalUint32 { + get { if ((_hasBits0 & 4) != 0) { return optionalUint32_; } else { return 0; } } + set { + _hasBits0 |= 4; + optionalUint32_ = value; + } + } + /// Gets whether the "optional_uint32" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasOptionalUint32 { + get { return (_hasBits0 & 4) != 0; } + } + /// Clears the value of the "optional_uint32" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearOptionalUint32() { + _hasBits0 &= ~4; + } + + /// Field number for the "optional_uint64" field. + public const int OptionalUint64FieldNumber = 4; + private ulong optionalUint64_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public ulong OptionalUint64 { + get { if ((_hasBits0 & 8) != 0) { return optionalUint64_; } else { return 0UL; } } + set { + _hasBits0 |= 8; + optionalUint64_ = value; + } + } + /// Gets whether the "optional_uint64" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasOptionalUint64 { + get { return (_hasBits0 & 8) != 0; } + } + /// Clears the value of the "optional_uint64" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearOptionalUint64() { + _hasBits0 &= ~8; + } + + /// Field number for the "optional_sint32" field. + public const int OptionalSint32FieldNumber = 5; + private int optionalSint32_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int OptionalSint32 { + get { if ((_hasBits0 & 16) != 0) { return optionalSint32_; } else { return 0; } } + set { + _hasBits0 |= 16; + optionalSint32_ = value; + } + } + /// Gets whether the "optional_sint32" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasOptionalSint32 { + get { return (_hasBits0 & 16) != 0; } + } + /// Clears the value of the "optional_sint32" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearOptionalSint32() { + _hasBits0 &= ~16; + } + + /// Field number for the "optional_sint64" field. + public const int OptionalSint64FieldNumber = 6; + private long optionalSint64_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public long OptionalSint64 { + get { if ((_hasBits0 & 32) != 0) { return optionalSint64_; } else { return 0L; } } + set { + _hasBits0 |= 32; + optionalSint64_ = value; + } + } + /// Gets whether the "optional_sint64" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasOptionalSint64 { + get { return (_hasBits0 & 32) != 0; } + } + /// Clears the value of the "optional_sint64" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearOptionalSint64() { + _hasBits0 &= ~32; + } + + /// Field number for the "optional_fixed32" field. + public const int OptionalFixed32FieldNumber = 7; + private uint optionalFixed32_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public uint OptionalFixed32 { + get { if ((_hasBits0 & 64) != 0) { return optionalFixed32_; } else { return 0; } } + set { + _hasBits0 |= 64; + optionalFixed32_ = value; + } + } + /// Gets whether the "optional_fixed32" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasOptionalFixed32 { + get { return (_hasBits0 & 64) != 0; } + } + /// Clears the value of the "optional_fixed32" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearOptionalFixed32() { + _hasBits0 &= ~64; + } + + /// Field number for the "optional_fixed64" field. + public const int OptionalFixed64FieldNumber = 8; + private ulong optionalFixed64_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public ulong OptionalFixed64 { + get { if ((_hasBits0 & 128) != 0) { return optionalFixed64_; } else { return 0UL; } } + set { + _hasBits0 |= 128; + optionalFixed64_ = value; + } + } + /// Gets whether the "optional_fixed64" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasOptionalFixed64 { + get { return (_hasBits0 & 128) != 0; } + } + /// Clears the value of the "optional_fixed64" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearOptionalFixed64() { + _hasBits0 &= ~128; + } + + /// Field number for the "optional_sfixed32" field. + public const int OptionalSfixed32FieldNumber = 9; + private int optionalSfixed32_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int OptionalSfixed32 { + get { if ((_hasBits0 & 256) != 0) { return optionalSfixed32_; } else { return 0; } } + set { + _hasBits0 |= 256; + optionalSfixed32_ = value; + } + } + /// Gets whether the "optional_sfixed32" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasOptionalSfixed32 { + get { return (_hasBits0 & 256) != 0; } + } + /// Clears the value of the "optional_sfixed32" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearOptionalSfixed32() { + _hasBits0 &= ~256; + } + + /// Field number for the "optional_sfixed64" field. + public const int OptionalSfixed64FieldNumber = 10; + private long optionalSfixed64_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public long OptionalSfixed64 { + get { if ((_hasBits0 & 512) != 0) { return optionalSfixed64_; } else { return 0L; } } + set { + _hasBits0 |= 512; + optionalSfixed64_ = value; + } + } + /// Gets whether the "optional_sfixed64" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasOptionalSfixed64 { + get { return (_hasBits0 & 512) != 0; } + } + /// Clears the value of the "optional_sfixed64" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearOptionalSfixed64() { + _hasBits0 &= ~512; + } + + /// Field number for the "optional_float" field. + public const int OptionalFloatFieldNumber = 11; + private float optionalFloat_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public float OptionalFloat { + get { if ((_hasBits0 & 1024) != 0) { return optionalFloat_; } else { return 0F; } } + set { + _hasBits0 |= 1024; + optionalFloat_ = value; + } + } + /// Gets whether the "optional_float" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasOptionalFloat { + get { return (_hasBits0 & 1024) != 0; } + } + /// Clears the value of the "optional_float" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearOptionalFloat() { + _hasBits0 &= ~1024; + } + + /// Field number for the "optional_double" field. + public const int OptionalDoubleFieldNumber = 12; + private double optionalDouble_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public double OptionalDouble { + get { if ((_hasBits0 & 2048) != 0) { return optionalDouble_; } else { return 0D; } } + set { + _hasBits0 |= 2048; + optionalDouble_ = value; + } + } + /// Gets whether the "optional_double" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasOptionalDouble { + get { return (_hasBits0 & 2048) != 0; } + } + /// Clears the value of the "optional_double" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearOptionalDouble() { + _hasBits0 &= ~2048; + } + + /// Field number for the "optional_bool" field. + public const int OptionalBoolFieldNumber = 13; + private bool optionalBool_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool OptionalBool { + get { if ((_hasBits0 & 4096) != 0) { return optionalBool_; } else { return false; } } + set { + _hasBits0 |= 4096; + optionalBool_ = value; + } + } + /// Gets whether the "optional_bool" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasOptionalBool { + get { return (_hasBits0 & 4096) != 0; } + } + /// Clears the value of the "optional_bool" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearOptionalBool() { + _hasBits0 &= ~4096; + } + + /// Field number for the "optional_string" field. + public const int OptionalStringFieldNumber = 14; + private string optionalString_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string OptionalString { + get { return optionalString_ ?? ""; } + set { + optionalString_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + /// Gets whether the "optional_string" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasOptionalString { + get { return optionalString_ != null; } + } + /// Clears the value of the "optional_string" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearOptionalString() { + optionalString_ = null; + } + + /// Field number for the "optional_bytes" field. + public const int OptionalBytesFieldNumber = 15; + private pb::ByteString optionalBytes_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pb::ByteString OptionalBytes { + get { return optionalBytes_ ?? pb::ByteString.Empty; } + set { + optionalBytes_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + /// Gets whether the "optional_bytes" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasOptionalBytes { + get { return optionalBytes_ != null; } + } + /// Clears the value of the "optional_bytes" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearOptionalBytes() { + optionalBytes_ = null; + } + + /// Field number for the "optional_cord" field. + public const int OptionalCordFieldNumber = 16; + private string optionalCord_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string OptionalCord { + get { return optionalCord_ ?? ""; } + set { + optionalCord_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + /// Gets whether the "optional_cord" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasOptionalCord { + get { return optionalCord_ != null; } + } + /// Clears the value of the "optional_cord" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearOptionalCord() { + optionalCord_ = null; + } + + /// Field number for the "optional_nested_message" field. + public const int OptionalNestedMessageFieldNumber = 18; + private global::ProtobufUnittest.TestProto3Optional.Types.NestedMessage optionalNestedMessage_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::ProtobufUnittest.TestProto3Optional.Types.NestedMessage OptionalNestedMessage { + get { return optionalNestedMessage_; } + set { + optionalNestedMessage_ = value; + } + } + + /// Field number for the "lazy_nested_message" field. + public const int LazyNestedMessageFieldNumber = 19; + private global::ProtobufUnittest.TestProto3Optional.Types.NestedMessage lazyNestedMessage_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::ProtobufUnittest.TestProto3Optional.Types.NestedMessage LazyNestedMessage { + get { return lazyNestedMessage_; } + set { + lazyNestedMessage_ = value; + } + } + + /// Field number for the "optional_nested_enum" field. + public const int OptionalNestedEnumFieldNumber = 21; + private global::ProtobufUnittest.TestProto3Optional.Types.NestedEnum optionalNestedEnum_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::ProtobufUnittest.TestProto3Optional.Types.NestedEnum OptionalNestedEnum { + get { if ((_hasBits0 & 8192) != 0) { return optionalNestedEnum_; } else { return global::ProtobufUnittest.TestProto3Optional.Types.NestedEnum.Unspecified; } } + set { + _hasBits0 |= 8192; + optionalNestedEnum_ = value; + } + } + /// Gets whether the "optional_nested_enum" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasOptionalNestedEnum { + get { return (_hasBits0 & 8192) != 0; } + } + /// Clears the value of the "optional_nested_enum" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearOptionalNestedEnum() { + _hasBits0 &= ~8192; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as TestProto3Optional); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(TestProto3Optional other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (OptionalInt32 != other.OptionalInt32) return false; + if (OptionalInt64 != other.OptionalInt64) return false; + if (OptionalUint32 != other.OptionalUint32) return false; + if (OptionalUint64 != other.OptionalUint64) return false; + if (OptionalSint32 != other.OptionalSint32) return false; + if (OptionalSint64 != other.OptionalSint64) return false; + if (OptionalFixed32 != other.OptionalFixed32) return false; + if (OptionalFixed64 != other.OptionalFixed64) return false; + if (OptionalSfixed32 != other.OptionalSfixed32) return false; + if (OptionalSfixed64 != other.OptionalSfixed64) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseSingleEqualityComparer.Equals(OptionalFloat, other.OptionalFloat)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(OptionalDouble, other.OptionalDouble)) return false; + if (OptionalBool != other.OptionalBool) return false; + if (OptionalString != other.OptionalString) return false; + if (OptionalBytes != other.OptionalBytes) return false; + if (OptionalCord != other.OptionalCord) return false; + if (!object.Equals(OptionalNestedMessage, other.OptionalNestedMessage)) return false; + if (!object.Equals(LazyNestedMessage, other.LazyNestedMessage)) return false; + if (OptionalNestedEnum != other.OptionalNestedEnum) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (HasOptionalInt32) hash ^= OptionalInt32.GetHashCode(); + if (HasOptionalInt64) hash ^= OptionalInt64.GetHashCode(); + if (HasOptionalUint32) hash ^= OptionalUint32.GetHashCode(); + if (HasOptionalUint64) hash ^= OptionalUint64.GetHashCode(); + if (HasOptionalSint32) hash ^= OptionalSint32.GetHashCode(); + if (HasOptionalSint64) hash ^= OptionalSint64.GetHashCode(); + if (HasOptionalFixed32) hash ^= OptionalFixed32.GetHashCode(); + if (HasOptionalFixed64) hash ^= OptionalFixed64.GetHashCode(); + if (HasOptionalSfixed32) hash ^= OptionalSfixed32.GetHashCode(); + if (HasOptionalSfixed64) hash ^= OptionalSfixed64.GetHashCode(); + if (HasOptionalFloat) hash ^= pbc::ProtobufEqualityComparers.BitwiseSingleEqualityComparer.GetHashCode(OptionalFloat); + if (HasOptionalDouble) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(OptionalDouble); + if (HasOptionalBool) hash ^= OptionalBool.GetHashCode(); + if (HasOptionalString) hash ^= OptionalString.GetHashCode(); + if (HasOptionalBytes) hash ^= OptionalBytes.GetHashCode(); + if (HasOptionalCord) hash ^= OptionalCord.GetHashCode(); + if (optionalNestedMessage_ != null) hash ^= OptionalNestedMessage.GetHashCode(); + if (lazyNestedMessage_ != null) hash ^= LazyNestedMessage.GetHashCode(); + if (HasOptionalNestedEnum) hash ^= OptionalNestedEnum.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + if (HasOptionalInt32) { + output.WriteRawTag(8); + output.WriteInt32(OptionalInt32); + } + if (HasOptionalInt64) { + output.WriteRawTag(16); + output.WriteInt64(OptionalInt64); + } + if (HasOptionalUint32) { + output.WriteRawTag(24); + output.WriteUInt32(OptionalUint32); + } + if (HasOptionalUint64) { + output.WriteRawTag(32); + output.WriteUInt64(OptionalUint64); + } + if (HasOptionalSint32) { + output.WriteRawTag(40); + output.WriteSInt32(OptionalSint32); + } + if (HasOptionalSint64) { + output.WriteRawTag(48); + output.WriteSInt64(OptionalSint64); + } + if (HasOptionalFixed32) { + output.WriteRawTag(61); + output.WriteFixed32(OptionalFixed32); + } + if (HasOptionalFixed64) { + output.WriteRawTag(65); + output.WriteFixed64(OptionalFixed64); + } + if (HasOptionalSfixed32) { + output.WriteRawTag(77); + output.WriteSFixed32(OptionalSfixed32); + } + if (HasOptionalSfixed64) { + output.WriteRawTag(81); + output.WriteSFixed64(OptionalSfixed64); + } + if (HasOptionalFloat) { + output.WriteRawTag(93); + output.WriteFloat(OptionalFloat); + } + if (HasOptionalDouble) { + output.WriteRawTag(97); + output.WriteDouble(OptionalDouble); + } + if (HasOptionalBool) { + output.WriteRawTag(104); + output.WriteBool(OptionalBool); + } + if (HasOptionalString) { + output.WriteRawTag(114); + output.WriteString(OptionalString); + } + if (HasOptionalBytes) { + output.WriteRawTag(122); + output.WriteBytes(OptionalBytes); + } + if (HasOptionalCord) { + output.WriteRawTag(130, 1); + output.WriteString(OptionalCord); + } + if (optionalNestedMessage_ != null) { + output.WriteRawTag(146, 1); + output.WriteMessage(OptionalNestedMessage); + } + if (lazyNestedMessage_ != null) { + output.WriteRawTag(154, 1); + output.WriteMessage(LazyNestedMessage); + } + if (HasOptionalNestedEnum) { + output.WriteRawTag(168, 1); + output.WriteEnum((int) OptionalNestedEnum); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (HasOptionalInt32) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(OptionalInt32); + } + if (HasOptionalInt64) { + size += 1 + pb::CodedOutputStream.ComputeInt64Size(OptionalInt64); + } + if (HasOptionalUint32) { + size += 1 + pb::CodedOutputStream.ComputeUInt32Size(OptionalUint32); + } + if (HasOptionalUint64) { + size += 1 + pb::CodedOutputStream.ComputeUInt64Size(OptionalUint64); + } + if (HasOptionalSint32) { + size += 1 + pb::CodedOutputStream.ComputeSInt32Size(OptionalSint32); + } + if (HasOptionalSint64) { + size += 1 + pb::CodedOutputStream.ComputeSInt64Size(OptionalSint64); + } + if (HasOptionalFixed32) { + size += 1 + 4; + } + if (HasOptionalFixed64) { + size += 1 + 8; + } + if (HasOptionalSfixed32) { + size += 1 + 4; + } + if (HasOptionalSfixed64) { + size += 1 + 8; + } + if (HasOptionalFloat) { + size += 1 + 4; + } + if (HasOptionalDouble) { + size += 1 + 8; + } + if (HasOptionalBool) { + size += 1 + 1; + } + if (HasOptionalString) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(OptionalString); + } + if (HasOptionalBytes) { + size += 1 + pb::CodedOutputStream.ComputeBytesSize(OptionalBytes); + } + if (HasOptionalCord) { + size += 2 + pb::CodedOutputStream.ComputeStringSize(OptionalCord); + } + if (optionalNestedMessage_ != null) { + size += 2 + pb::CodedOutputStream.ComputeMessageSize(OptionalNestedMessage); + } + if (lazyNestedMessage_ != null) { + size += 2 + pb::CodedOutputStream.ComputeMessageSize(LazyNestedMessage); + } + if (HasOptionalNestedEnum) { + size += 2 + pb::CodedOutputStream.ComputeEnumSize((int) OptionalNestedEnum); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(TestProto3Optional other) { + if (other == null) { + return; + } + if (other.HasOptionalInt32) { + OptionalInt32 = other.OptionalInt32; + } + if (other.HasOptionalInt64) { + OptionalInt64 = other.OptionalInt64; + } + if (other.HasOptionalUint32) { + OptionalUint32 = other.OptionalUint32; + } + if (other.HasOptionalUint64) { + OptionalUint64 = other.OptionalUint64; + } + if (other.HasOptionalSint32) { + OptionalSint32 = other.OptionalSint32; + } + if (other.HasOptionalSint64) { + OptionalSint64 = other.OptionalSint64; + } + if (other.HasOptionalFixed32) { + OptionalFixed32 = other.OptionalFixed32; + } + if (other.HasOptionalFixed64) { + OptionalFixed64 = other.OptionalFixed64; + } + if (other.HasOptionalSfixed32) { + OptionalSfixed32 = other.OptionalSfixed32; + } + if (other.HasOptionalSfixed64) { + OptionalSfixed64 = other.OptionalSfixed64; + } + if (other.HasOptionalFloat) { + OptionalFloat = other.OptionalFloat; + } + if (other.HasOptionalDouble) { + OptionalDouble = other.OptionalDouble; + } + if (other.HasOptionalBool) { + OptionalBool = other.OptionalBool; + } + if (other.HasOptionalString) { + OptionalString = other.OptionalString; + } + if (other.HasOptionalBytes) { + OptionalBytes = other.OptionalBytes; + } + if (other.HasOptionalCord) { + OptionalCord = other.OptionalCord; + } + if (other.optionalNestedMessage_ != null) { + if (optionalNestedMessage_ == null) { + OptionalNestedMessage = new global::ProtobufUnittest.TestProto3Optional.Types.NestedMessage(); + } + OptionalNestedMessage.MergeFrom(other.OptionalNestedMessage); + } + if (other.lazyNestedMessage_ != null) { + if (lazyNestedMessage_ == null) { + LazyNestedMessage = new global::ProtobufUnittest.TestProto3Optional.Types.NestedMessage(); + } + LazyNestedMessage.MergeFrom(other.LazyNestedMessage); + } + if (other.HasOptionalNestedEnum) { + OptionalNestedEnum = other.OptionalNestedEnum; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 8: { + OptionalInt32 = input.ReadInt32(); + break; + } + case 16: { + OptionalInt64 = input.ReadInt64(); + break; + } + case 24: { + OptionalUint32 = input.ReadUInt32(); + break; + } + case 32: { + OptionalUint64 = input.ReadUInt64(); + break; + } + case 40: { + OptionalSint32 = input.ReadSInt32(); + break; + } + case 48: { + OptionalSint64 = input.ReadSInt64(); + break; + } + case 61: { + OptionalFixed32 = input.ReadFixed32(); + break; + } + case 65: { + OptionalFixed64 = input.ReadFixed64(); + break; + } + case 77: { + OptionalSfixed32 = input.ReadSFixed32(); + break; + } + case 81: { + OptionalSfixed64 = input.ReadSFixed64(); + break; + } + case 93: { + OptionalFloat = input.ReadFloat(); + break; + } + case 97: { + OptionalDouble = input.ReadDouble(); + break; + } + case 104: { + OptionalBool = input.ReadBool(); + break; + } + case 114: { + OptionalString = input.ReadString(); + break; + } + case 122: { + OptionalBytes = input.ReadBytes(); + break; + } + case 130: { + OptionalCord = input.ReadString(); + break; + } + case 146: { + if (optionalNestedMessage_ == null) { + OptionalNestedMessage = new global::ProtobufUnittest.TestProto3Optional.Types.NestedMessage(); + } + input.ReadMessage(OptionalNestedMessage); + break; + } + case 154: { + if (lazyNestedMessage_ == null) { + LazyNestedMessage = new global::ProtobufUnittest.TestProto3Optional.Types.NestedMessage(); + } + input.ReadMessage(LazyNestedMessage); + break; + } + case 168: { + OptionalNestedEnum = (global::ProtobufUnittest.TestProto3Optional.Types.NestedEnum) input.ReadEnum(); + break; + } + } + } + } + + #region Nested types + /// Container for nested types declared in the TestProto3Optional message type. + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static partial class Types { + public enum NestedEnum { + [pbr::OriginalName("UNSPECIFIED")] Unspecified = 0, + [pbr::OriginalName("FOO")] Foo = 1, + [pbr::OriginalName("BAR")] Bar = 2, + [pbr::OriginalName("BAZ")] Baz = 3, + /// + /// Intentionally negative. + /// + [pbr::OriginalName("NEG")] Neg = -1, + } + + public sealed partial class NestedMessage : pb::IMessage { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new NestedMessage()); + private pb::UnknownFieldSet _unknownFields; + private int _hasBits0; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::ProtobufUnittest.TestProto3Optional.Descriptor.NestedTypes[0]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public NestedMessage() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public NestedMessage(NestedMessage other) : this() { + _hasBits0 = other._hasBits0; + bb_ = other.bb_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public NestedMessage Clone() { + return new NestedMessage(this); + } + + /// Field number for the "bb" field. + public const int BbFieldNumber = 1; + private int bb_; + /// + /// The field name "b" fails to compile in proto1 because it conflicts with + /// a local variable named "b" in one of the generated methods. Doh. + /// This file needs to compile in proto1 to test backwards-compatibility. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int Bb { + get { if ((_hasBits0 & 1) != 0) { return bb_; } else { return 0; } } + set { + _hasBits0 |= 1; + bb_ = value; + } + } + /// Gets whether the "bb" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasBb { + get { return (_hasBits0 & 1) != 0; } + } + /// Clears the value of the "bb" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearBb() { + _hasBits0 &= ~1; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as NestedMessage); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(NestedMessage other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (Bb != other.Bb) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (HasBb) hash ^= Bb.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + if (HasBb) { + output.WriteRawTag(8); + output.WriteInt32(Bb); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (HasBb) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(Bb); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(NestedMessage other) { + if (other == null) { + return; + } + if (other.HasBb) { + Bb = other.Bb; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 8: { + Bb = input.ReadInt32(); + break; + } + } + } + } + + } + + } + #endregion + + } + + #endregion + +} + +#endregion Designer generated code diff --git a/csharp/src/Google.Protobuf.Test/testprotos.pb b/csharp/src/Google.Protobuf.Test/testprotos.pb index 424d96900574455edba12e63e68a4f765023832e..1758578eb773eb9caffd2c6e5ccbca57f12109f6 100644 GIT binary patch delta 3108 zcmai$%WoT16vjPw#;@!5b(%OxxQa7xS5Gy2v@+a`!nYq_?TEuS7{l4=%XO7QY`S(Wy zAAdLS(V22a&eSvQd-uEA1pOjQbNj8A=V5JlIQ3JIvU`y4a{ug`j>xj+-I6vqXt=gQB4MN1o}GE5DA4Xa;hNH?(&k3TDkgyGqWh?=(# z9@Ka3Zgb{gS%d1mpxU`pX6s9g!SHQGMeg=qH+jk|KUE<6FUody)@(jiFbUe7#O+3F zr)^K-{7Y@9Yy`S3S6ZjFMxBcpD#u!_wOWltXhg~QjNn#KbfM$a#uUEdGYfSw+wJ3n z<~|p*=BK(gSTVxg`uaos*j8dsiTkbN-9!{6{5tU|Mx%0pNODC?F!5!RQS!rRyR9$(4+&UdX%)T1;kkd=nDi2b$`Yt#B^HNIfInT;x6 zFFi>URr9l7l%bkFNC&Df*$I7!UJ~URVqfa``Sfvm?SAXfxw>-V>dK)|8=Gz)+*LOJ zzDzw#yXxBf;oH~Mw>_OC^-;yg)RZel{gn8q{b(PKx)!ZNg{l0JQlhz-HtyO~@T_Vs zoR9mGG)Ohgr9w%Q8!93wK6pOay!p*<+HfaNs6Bq-!W8p?sEClCkG&!y zG?Gt^q7u)BG)Kl9NkPpy2~hx|$?Q0Cb+ z5rHy4Htw{7V1c9^Nd;sDVi0Dsc4`qN(!IqqNHe` zEXr13T#^tsAWO0pH`gS@4akxM>9~j+lqE^=Fm;(^oEP$dvMebcP?iHsXrL^|M@0n4 za{9V66)#g)B*Y8IiiCIpS&uTZw?O#>ABn0c8yo>+U8IEX&&X ztbNZR;@0$x^R`i@u9LjujH1H2tk8*K;nxERAtG;mcuGVlu|E5nLy0lfASFkNfnrEX z3=l&?Vt^RKH-!@rV{%$V=+l@fI(^1`+jv7`w&0XtOx+-&Izx#KS%RU&M&OczVJNXN RD83Db5*rhfHIMyY|6f)34`l!V delta 19 acmZqMEOM_yq@jheg{g(Pg=GtC918$T)CPS3 From bad9d753ae7da7f4ca6be84b2cd3f356fe416cbc Mon Sep 17 00:00:00 2001 From: Jon Skeet Date: Fri, 17 Apr 2020 07:45:26 +0100 Subject: [PATCH 26/38] Add unit tests for proto3 optional fields (This isn't as exhaustive as it might be, but the behavior is basically the same as proto2 optional fields.) --- .../Proto3OptionalTest.cs | 143 ++++++++++++++++++ 1 file changed, 143 insertions(+) create mode 100644 csharp/src/Google.Protobuf.Test/Proto3OptionalTest.cs diff --git a/csharp/src/Google.Protobuf.Test/Proto3OptionalTest.cs b/csharp/src/Google.Protobuf.Test/Proto3OptionalTest.cs new file mode 100644 index 0000000000..20c1846da4 --- /dev/null +++ b/csharp/src/Google.Protobuf.Test/Proto3OptionalTest.cs @@ -0,0 +1,143 @@ +#region Copyright notice and license +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#endregion + +using NUnit.Framework; +using ProtobufUnittest; +using System; +using System.IO; + +namespace Google.Protobuf.Test +{ + class Proto3OptionalTest + { + [Test] + public void OptionalInt32FieldLifecycle() + { + var message = new TestProto3Optional(); + Assert.IsFalse(message.HasOptionalInt32); + Assert.AreEqual(0, message.OptionalInt32); + + message.OptionalInt32 = 5; + Assert.IsTrue(message.HasOptionalInt32); + Assert.AreEqual(5, message.OptionalInt32); + + message.OptionalInt32 = 0; + Assert.IsTrue(message.HasOptionalInt32); + Assert.AreEqual(0, message.OptionalInt32); + + message.ClearOptionalInt32(); + Assert.IsFalse(message.HasOptionalInt32); + Assert.AreEqual(0, message.OptionalInt32); + } + + [Test] + public void OptionalStringFieldLifecycle() + { + var message = new TestProto3Optional(); + Assert.IsFalse(message.HasOptionalString); + Assert.AreEqual("", message.OptionalString); + + message.OptionalString = "x"; + Assert.IsTrue(message.HasOptionalString); + Assert.AreEqual("x", message.OptionalString); + + message.OptionalString = ""; + Assert.IsTrue(message.HasOptionalString); + Assert.AreEqual("", message.OptionalString); + + message.ClearOptionalString(); + Assert.IsFalse(message.HasOptionalString); + Assert.AreEqual("", message.OptionalString); + + Assert.Throws(() => message.OptionalString = null); + } + + [Test] + public void Clone() + { + var original = new TestProto3Optional { OptionalInt64 = 0L }; + + var clone = original.Clone(); + Assert.False(clone.HasOptionalInt32); + Assert.AreEqual(0, clone.OptionalInt32); + Assert.True(clone.HasOptionalInt64); + Assert.AreEqual(0L, clone.OptionalInt64); + } + + [Test] + public void Serialization_NotSet() + { + var stream = new MemoryStream(); + var message = new TestProto3Optional(); + message.WriteTo(stream); + Assert.AreEqual(0, stream.Length); + } + + [Test] + public void Serialization_SetToDefault() + { + var stream = new MemoryStream(); + var message = new TestProto3Optional { OptionalInt32 = 0 }; + message.WriteTo(stream); + Assert.AreEqual(2, stream.Length); // Tag and value + } + + [Test] + public void Serialization_Roundtrip() + { + var original = new TestProto3Optional { OptionalInt64 = 0L, OptionalFixed32 = 5U }; + var stream = new MemoryStream(); + original.WriteTo(stream); + stream.Position = 0; + var deserialized = TestProto3Optional.Parser.ParseFrom(stream); + + Assert.AreEqual(0, deserialized.OptionalInt32); + Assert.IsFalse(deserialized.HasOptionalInt32); + + Assert.AreEqual(0L, deserialized.OptionalInt64); + Assert.IsTrue(deserialized.HasOptionalInt64); + + Assert.AreEqual(5U, deserialized.OptionalFixed32); + Assert.IsTrue(deserialized.HasOptionalFixed32); + } + + [Test] + public void Equality_IgnoresPresence() + { + var message1 = new TestProto3Optional { OptionalInt32 = 0 }; + var message2 = new TestProto3Optional(); + + Assert.IsTrue(message1.Equals(message2)); + message1.ClearOptionalInt32(); + } + } +} From 97737072f9f6552fd5fa2bc4ca085793a9b708dd Mon Sep 17 00:00:00 2001 From: Jon Skeet Date: Fri, 17 Apr 2020 08:36:46 +0100 Subject: [PATCH 27/38] Add reflection support for proto3 optional fields This is more involved than might be expected because the synthetic oneofs don't generate the properties we would usually expect to see. --- .../Reflection/DescriptorsTest.cs | 50 +++++++++++++++++++ .../Reflection/FieldAccessTest.cs | 37 ++++++++++++++ .../Reflection/FieldDescriptor.cs | 6 +++ .../Reflection/IFieldAccessor.cs | 3 +- .../Reflection/MessageDescriptor.cs | 24 +++++++++ .../Reflection/OneofAccessor.cs | 47 +++++++++-------- .../Reflection/OneofDescriptor.cs | 40 +++++++++++---- .../Reflection/SingleFieldAccessor.cs | 36 +++++++++---- 8 files changed, 202 insertions(+), 41 deletions(-) diff --git a/csharp/src/Google.Protobuf.Test/Reflection/DescriptorsTest.cs b/csharp/src/Google.Protobuf.Test/Reflection/DescriptorsTest.cs index 482db535e2..ebb8394d23 100644 --- a/csharp/src/Google.Protobuf.Test/Reflection/DescriptorsTest.cs +++ b/csharp/src/Google.Protobuf.Test/Reflection/DescriptorsTest.cs @@ -32,6 +32,7 @@ using Google.Protobuf.TestProtos; using NUnit.Framework; +using ProtobufUnittest; using System; using System.Collections.Generic; using System.Linq; @@ -247,6 +248,7 @@ namespace Google.Protobuf.Reflection FieldDescriptor enumField = testAllTypesDescriptor.FindDescriptor("single_nested_enum"); FieldDescriptor foreignMessageField = testAllTypesDescriptor.FindDescriptor("single_foreign_message"); FieldDescriptor importMessageField = testAllTypesDescriptor.FindDescriptor("single_import_message"); + FieldDescriptor fieldInOneof = testAllTypesDescriptor.FindDescriptor("oneof_string"); Assert.AreEqual("single_int32", primitiveField.Name); Assert.AreEqual("protobuf_unittest3.TestAllTypes.single_int32", @@ -268,6 +270,10 @@ namespace Google.Protobuf.Reflection Assert.AreEqual("single_import_message", importMessageField.Name); Assert.AreEqual(FieldType.Message, importMessageField.FieldType); Assert.AreEqual(importMessageDescriptor, importMessageField.MessageType); + + // For a field in a regular onoef, ContainingOneof and RealContainingOneof should be the same. + Assert.AreEqual("oneof_field", fieldInOneof.ContainingOneof.Name); + Assert.AreSame(fieldInOneof.ContainingOneof, fieldInOneof.RealContainingOneof); } [Test] @@ -318,6 +324,7 @@ namespace Google.Protobuf.Reflection public void OneofDescriptor() { OneofDescriptor descriptor = TestAllTypes.Descriptor.FindDescriptor("oneof_field"); + Assert.IsFalse(descriptor.IsSynthetic); Assert.AreEqual("oneof_field", descriptor.Name); Assert.AreEqual("protobuf_unittest3.TestAllTypes.oneof_field", descriptor.FullName); @@ -383,5 +390,48 @@ namespace Google.Protobuf.Reflection var importingDescriptor = TestProtos.OldGenerator.OldExtensions1Reflection.Descriptor; Assert.NotNull(importingDescriptor); } + + [Test] + public void Proto3OptionalDescriptors() + { + var descriptor = TestProto3Optional.Descriptor; + var field = descriptor.Fields[TestProto3Optional.OptionalInt32FieldNumber]; + Assert.NotNull(field.ContainingOneof); + Assert.IsTrue(field.ContainingOneof.IsSynthetic); + Assert.Null(field.RealContainingOneof); + } + + + [Test] + public void SyntheticOneofReflection() + { + // Expect every oneof in TestProto3Optional to be synthetic + var proto3OptionalDescriptor = TestProto3Optional.Descriptor; + Assert.AreEqual(0, proto3OptionalDescriptor.RealOneofCount); + foreach (var oneof in proto3OptionalDescriptor.Oneofs) + { + Assert.True(oneof.IsSynthetic); + } + + // Expect no oneof in the original proto3 unit test file to be synthetic. + foreach (var descriptor in ProtobufTestMessages.Proto3.TestMessagesProto3Reflection.Descriptor.MessageTypes) + { + Assert.AreEqual(descriptor.Oneofs.Count, descriptor.RealOneofCount); + foreach (var oneof in descriptor.Oneofs) + { + Assert.False(oneof.IsSynthetic); + } + } + + // Expect no oneof in the original proto2 unit test file to be synthetic. + foreach (var descriptor in ProtobufTestMessages.Proto2.TestMessagesProto2Reflection.Descriptor.MessageTypes) + { + Assert.AreEqual(descriptor.Oneofs.Count, descriptor.RealOneofCount); + foreach (var oneof in descriptor.Oneofs) + { + Assert.False(oneof.IsSynthetic); + } + } + } } } diff --git a/csharp/src/Google.Protobuf.Test/Reflection/FieldAccessTest.cs b/csharp/src/Google.Protobuf.Test/Reflection/FieldAccessTest.cs index 9651ec30d8..0d4034c5b1 100644 --- a/csharp/src/Google.Protobuf.Test/Reflection/FieldAccessTest.cs +++ b/csharp/src/Google.Protobuf.Test/Reflection/FieldAccessTest.cs @@ -38,6 +38,7 @@ using System.Collections; using System.Collections.Generic; using static Google.Protobuf.TestProtos.Proto2.UnittestExtensions; +using ProtobufUnittest; namespace Google.Protobuf.Reflection { @@ -104,6 +105,21 @@ namespace Google.Protobuf.Reflection Assert.Throws(() => fields[TestProtos.TestAllTypes.SingleBoolFieldNumber].Accessor.HasValue(message)); } + [Test] + public void HasValue_Proto3Optional() + { + IMessage message = new TestProto3Optional + { + OptionalInt32 = 0, + LazyNestedMessage = new TestProto3Optional.Types.NestedMessage() + }; + var fields = message.Descriptor.Fields; + Assert.IsFalse(fields[TestProto3Optional.OptionalInt64FieldNumber].Accessor.HasValue(message)); + Assert.IsFalse(fields[TestProto3Optional.OptionalNestedMessageFieldNumber].Accessor.HasValue(message)); + Assert.IsTrue(fields[TestProto3Optional.LazyNestedMessageFieldNumber].Accessor.HasValue(message)); + Assert.IsTrue(fields[TestProto3Optional.OptionalInt32FieldNumber].Accessor.HasValue(message)); + } + [Test] public void HasValue() { @@ -225,6 +241,27 @@ namespace Google.Protobuf.Reflection Assert.AreEqual(0, mapMessage.MapStringString.Count); } + [Test] + public void Clear_Proto3Optional() + { + TestProto3Optional message = new TestProto3Optional + { + OptionalInt32 = 0, + OptionalNestedMessage = new TestProto3Optional.Types.NestedMessage() + }; + var primitiveField = TestProto3Optional.Descriptor.Fields[TestProto3Optional.OptionalInt32FieldNumber]; + var messageField = TestProto3Optional.Descriptor.Fields[TestProto3Optional.OptionalNestedMessageFieldNumber]; + + Assert.True(message.HasOptionalInt32); + Assert.NotNull(message.OptionalNestedMessage); + + primitiveField.Accessor.Clear(message); + messageField.Accessor.Clear(message); + + Assert.False(message.HasOptionalInt32); + Assert.Null(message.OptionalNestedMessage); + } + [Test] public void FieldDescriptor_ByName() { diff --git a/csharp/src/Google.Protobuf/Reflection/FieldDescriptor.cs b/csharp/src/Google.Protobuf/Reflection/FieldDescriptor.cs index ddd671aadb..69bab4f010 100644 --- a/csharp/src/Google.Protobuf/Reflection/FieldDescriptor.cs +++ b/csharp/src/Google.Protobuf/Reflection/FieldDescriptor.cs @@ -58,6 +58,12 @@ namespace Google.Protobuf.Reflection /// public OneofDescriptor ContainingOneof { get; } + /// + /// Returns the oneof containing this field if it's a "real" oneof, or null if either this + /// field is not part of a oneof, or the oneof is synthetic. + /// + public OneofDescriptor RealContainingOneof => ContainingOneof?.IsSynthetic == false ? ContainingOneof : null; + /// /// The effective JSON name for this field. This is usually the lower-camel-cased form of the field name, /// but can be overridden using the json_name option in the .proto file. diff --git a/csharp/src/Google.Protobuf/Reflection/IFieldAccessor.cs b/csharp/src/Google.Protobuf/Reflection/IFieldAccessor.cs index b48c4f9df5..d73427b73b 100644 --- a/csharp/src/Google.Protobuf/Reflection/IFieldAccessor.cs +++ b/csharp/src/Google.Protobuf/Reflection/IFieldAccessor.cs @@ -59,7 +59,8 @@ namespace Google.Protobuf.Reflection object GetValue(IMessage message); /// - /// Indicates whether the field in the specified message is set. For proto3 fields, this throws an + /// Indicates whether the field in the specified message is set. + /// For proto3 fields that aren't explicitly optional, this throws an /// bool HasValue(IMessage message); diff --git a/csharp/src/Google.Protobuf/Reflection/MessageDescriptor.cs b/csharp/src/Google.Protobuf/Reflection/MessageDescriptor.cs index eda1965c54..6217081fbc 100644 --- a/csharp/src/Google.Protobuf/Reflection/MessageDescriptor.cs +++ b/csharp/src/Google.Protobuf/Reflection/MessageDescriptor.cs @@ -80,6 +80,20 @@ namespace Google.Protobuf.Reflection (oneof, index) => new OneofDescriptor(oneof, file, this, index, generatedCodeInfo?.OneofNames[index])); + int syntheticOneofCount = 0; + foreach (var oneof in Oneofs) + { + if (oneof.IsSynthetic) + { + syntheticOneofCount++; + } + else if (syntheticOneofCount != 0) + { + throw new ArgumentException("All synthetic oneofs should come after real oneofs"); + } + } + RealOneofCount = Oneofs.Count - syntheticOneofCount; + NestedTypes = DescriptorUtil.ConvertAndMakeReadOnly( proto.NestedType, (type, index) => @@ -234,9 +248,19 @@ namespace Google.Protobuf.Reflection /// /// An unmodifiable list of the "oneof" field collections in this message type. + /// All "real" oneofs (where returns false) + /// come before synthetic ones. /// public IList Oneofs { get; } + /// + /// The number of real "oneof" descriptors in this message type. Every element in + /// with an index less than this will have a property value + /// of false; every element with an index greater than or equal to this will have a + /// property value of true. + /// + public int RealOneofCount { get; } + /// /// Finds a field by field name. /// diff --git a/csharp/src/Google.Protobuf/Reflection/OneofAccessor.cs b/csharp/src/Google.Protobuf/Reflection/OneofAccessor.cs index f4bf628a6f..4e040c17ea 100644 --- a/csharp/src/Google.Protobuf/Reflection/OneofAccessor.cs +++ b/csharp/src/Google.Protobuf/Reflection/OneofAccessor.cs @@ -43,19 +43,31 @@ namespace Google.Protobuf.Reflection { private readonly Func caseDelegate; private readonly Action clearDelegate; - private OneofDescriptor descriptor; - internal OneofAccessor(PropertyInfo caseProperty, MethodInfo clearMethod, OneofDescriptor descriptor) + private OneofAccessor(OneofDescriptor descriptor, Func caseDelegate, Action clearDelegate) { - if (!caseProperty.CanRead) - { - throw new ArgumentException("Cannot read from property"); - } - this.descriptor = descriptor; - caseDelegate = ReflectionUtil.CreateFuncIMessageInt32(caseProperty.GetGetMethod()); + Descriptor = descriptor; + this.caseDelegate = caseDelegate; + this.clearDelegate = clearDelegate; + } + + internal static OneofAccessor ForRegularOneof( + OneofDescriptor descriptor, + PropertyInfo caseProperty, + MethodInfo clearMethod) => + new OneofAccessor( + descriptor, + ReflectionUtil.CreateFuncIMessageInt32(caseProperty.GetGetMethod()), + ReflectionUtil.CreateActionIMessage(clearMethod)); - this.descriptor = descriptor; - clearDelegate = ReflectionUtil.CreateActionIMessage(clearMethod); + internal static OneofAccessor ForSyntheticOneof(OneofDescriptor descriptor) + { + // Note: descriptor.Fields will be null when this method is called, because we haven't + // cross-linked yet. But by the time the delgates are called by user code, all will be + // well. (That's why we capture the descriptor itself rather than a field.) + return new OneofAccessor(descriptor, + message => descriptor.Fields[0].Accessor.HasValue(message) ? descriptor.Fields[0].FieldNumber : 0, + message => descriptor.Fields[0].Accessor.Clear(message)); } /// @@ -64,15 +76,12 @@ namespace Google.Protobuf.Reflection /// /// The descriptor of the oneof. /// - public OneofDescriptor Descriptor { get { return descriptor; } } + public OneofDescriptor Descriptor { get; } /// /// Clears the oneof in the specified message. /// - public void Clear(IMessage message) - { - clearDelegate(message); - } + public void Clear(IMessage message) => clearDelegate(message); /// /// Indicates which field in the oneof is set for specified message @@ -80,11 +89,9 @@ namespace Google.Protobuf.Reflection public FieldDescriptor GetCaseFieldDescriptor(IMessage message) { int fieldNumber = caseDelegate(message); - if (fieldNumber > 0) - { - return descriptor.ContainingType.FindFieldByNumber(fieldNumber); - } - return null; + return fieldNumber > 0 + ? Descriptor.ContainingType.FindFieldByNumber(fieldNumber) + : null; } } } diff --git a/csharp/src/Google.Protobuf/Reflection/OneofDescriptor.cs b/csharp/src/Google.Protobuf/Reflection/OneofDescriptor.cs index 1e30b92ed6..7cceabd7c3 100644 --- a/csharp/src/Google.Protobuf/Reflection/OneofDescriptor.cs +++ b/csharp/src/Google.Protobuf/Reflection/OneofDescriptor.cs @@ -33,6 +33,7 @@ using System; using System.Collections.Generic; using System.Collections.ObjectModel; +using System.Linq; using Google.Protobuf.Collections; using Google.Protobuf.Compatibility; @@ -54,8 +55,13 @@ namespace Google.Protobuf.Reflection { this.proto = proto; containingType = parent; - file.DescriptorPool.AddSymbol(this); + + // It's useful to determine whether or not this is a synthetic oneof before cross-linking. That means + // diving into the proto directly rather than using FieldDescriptor, but that's okay. + var firstFieldInOneof = parent.Proto.Field.FirstOrDefault(fieldProto => fieldProto.OneofIndex == index); + IsSynthetic = firstFieldInOneof?.Proto3Optional ?? false; + accessor = CreateAccessor(clrName); } @@ -83,6 +89,12 @@ namespace Google.Protobuf.Reflection /// public IList Fields { get { return fields; } } + /// + /// Returns true if this oneof is a synthetic oneof containing a proto3 optional field; + /// false otherwise. + /// + public bool IsSynthetic { get; } + /// /// Gets an accessor for reflective access to the values associated with the oneof /// in a particular message. @@ -146,18 +158,28 @@ namespace Google.Protobuf.Reflection { return null; } - var caseProperty = containingType.ClrType.GetProperty(clrName + "Case"); - if (caseProperty == null) + if (IsSynthetic) { - throw new DescriptorValidationException(this, $"Property {clrName}Case not found in {containingType.ClrType}"); + return OneofAccessor.ForSyntheticOneof(this); } - var clearMethod = containingType.ClrType.GetMethod("Clear" + clrName); - if (clearMethod == null) + else { - throw new DescriptorValidationException(this, $"Method Clear{clrName} not found in {containingType.ClrType}"); + var caseProperty = containingType.ClrType.GetProperty(clrName + "Case"); + if (caseProperty == null) + { + throw new DescriptorValidationException(this, $"Property {clrName}Case not found in {containingType.ClrType}"); + } + if (!caseProperty.CanRead) + { + throw new ArgumentException($"Cannot read from property {clrName}Case in {containingType.ClrType}"); + } + var clearMethod = containingType.ClrType.GetMethod("Clear" + clrName); + if (clearMethod == null) + { + throw new DescriptorValidationException(this, $"Method Clear{clrName} not found in {containingType.ClrType}"); + } + return OneofAccessor.ForRegularOneof(this, caseProperty, clearMethod); } - - return new OneofAccessor(caseProperty, clearMethod, this); } } } diff --git a/csharp/src/Google.Protobuf/Reflection/SingleFieldAccessor.cs b/csharp/src/Google.Protobuf/Reflection/SingleFieldAccessor.cs index de10226511..ed844bc51d 100644 --- a/csharp/src/Google.Protobuf/Reflection/SingleFieldAccessor.cs +++ b/csharp/src/Google.Protobuf/Reflection/SingleFieldAccessor.cs @@ -57,10 +57,11 @@ namespace Google.Protobuf.Reflection throw new ArgumentException("Not all required properties/methods available"); } setValueDelegate = ReflectionUtil.CreateActionIMessageObject(property.GetSetMethod()); - if (descriptor.File.Syntax == Syntax.Proto3) + if (descriptor.File.Syntax == Syntax.Proto3 && !descriptor.Proto.Proto3Optional) { - hasDelegate = message => { - throw new InvalidOperationException("HasValue is not implemented for proto3 fields"); + hasDelegate = message => + { + throw new InvalidOperationException("HasValue is not implemented for non-optional proto3 fields"); }; var clrType = property.PropertyType; @@ -74,16 +75,29 @@ namespace Google.Protobuf.Reflection } else { - MethodInfo hasMethod = property.DeclaringType.GetRuntimeProperty("Has" + property.Name).GetMethod; - if (hasMethod == null) { - throw new ArgumentException("Not all required properties/methods are available"); + // For message fields, just compare with null and set to null. + // For primitive fields, use the Has/Clear methods. + + if (descriptor.FieldType == FieldType.Message) + { + hasDelegate = message => GetValue(message) != null; + clearDelegate = message => SetValue(message, null); } - hasDelegate = ReflectionUtil.CreateFuncIMessageBool(hasMethod); - MethodInfo clearMethod = property.DeclaringType.GetRuntimeMethod("Clear" + property.Name, ReflectionUtil.EmptyTypes); - if (clearMethod == null) { - throw new ArgumentException("Not all required properties/methods are available"); + else + { + MethodInfo hasMethod = property.DeclaringType.GetRuntimeProperty("Has" + property.Name).GetMethod; + if (hasMethod == null) + { + throw new ArgumentException("Not all required properties/methods are available"); + } + hasDelegate = ReflectionUtil.CreateFuncIMessageBool(hasMethod); + MethodInfo clearMethod = property.DeclaringType.GetRuntimeMethod("Clear" + property.Name, ReflectionUtil.EmptyTypes); + if (clearMethod == null) + { + throw new ArgumentException("Not all required properties/methods are available"); + } + clearDelegate = ReflectionUtil.CreateActionIMessage(clearMethod); } - clearDelegate = ReflectionUtil.CreateActionIMessage(clearMethod); } } From 81c9b85dee8a0b3a2714f974ff53b16b25e7caaf Mon Sep 17 00:00:00 2001 From: Jon Skeet Date: Fri, 24 Apr 2020 17:29:44 +0100 Subject: [PATCH 28/38] Add new files into Makefile.am --- Makefile.am | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Makefile.am b/Makefile.am index 090e5037b0..0c7476d129 100644 --- a/Makefile.am +++ b/Makefile.am @@ -122,6 +122,7 @@ csharp_EXTRA_DIST= \ csharp/src/Google.Protobuf.Test/JsonFormatterTest.cs \ csharp/src/Google.Protobuf.Test/JsonParserTest.cs \ csharp/src/Google.Protobuf.Test/JsonTokenizerTest.cs \ + csharp/src/Google.Protobuf.Test/Proto3OptionalTest.cs \ csharp/src/Google.Protobuf.Test/Reflection/CustomOptionsTest.cs \ csharp/src/Google.Protobuf.Test/Reflection/DescriptorDeclarationTest.cs \ csharp/src/Google.Protobuf.Test/Reflection/DescriptorsTest.cs \ @@ -148,6 +149,7 @@ csharp_EXTRA_DIST= \ csharp/src/Google.Protobuf.Test.TestProtos/UnittestImport.cs \ csharp/src/Google.Protobuf.Test.TestProtos/UnittestIssues.cs \ csharp/src/Google.Protobuf.Test.TestProtos/UnittestProto3.cs \ + csharp/src/Google.Protobuf.Test.TestProtos/UnittestProto3Optional.cs \ csharp/src/Google.Protobuf.Test.TestProtos/UnittestWellKnownTypes.cs \ csharp/src/Google.Protobuf.Test.TestProtos/Unittest.cs \ csharp/src/Google.Protobuf.Test/WellKnownTypes/AnyTest.cs \ From f494cb222d1b10a56273c07a3f5991b4b107958b Mon Sep 17 00:00:00 2001 From: Masaki Hara Date: Sat, 25 Apr 2020 01:50:27 +0900 Subject: [PATCH 29/38] Test in Ruby 2.7 (#7386) * Test in Ruby 2.7 * Turn off GC.stress for 'require' in Ruby 2.7 * Backport 2c8364b to compatibility_tests/v3.0.0 --- kokoro/linux/dockerfile/test/ruby/Dockerfile | 1 + kokoro/linux/ruby27/build.sh | 18 ++++++++++++++++++ kokoro/linux/ruby27/continuous.cfg | 11 +++++++++++ kokoro/linux/ruby27/presubmit.cfg | 11 +++++++++++ kokoro/macos/ruby27/build.sh | 11 +++++++++++ kokoro/macos/ruby27/continuous.cfg | 5 +++++ kokoro/macos/ruby27/presubmit.cfg | 5 +++++ .../v3.0.0/tests/repeated_field_test.rb | 1 + ruby/tests/gc_test.rb | 4 +++- ruby/travis-test.sh | 2 +- tests.sh | 1 + 11 files changed, 68 insertions(+), 2 deletions(-) create mode 100755 kokoro/linux/ruby27/build.sh create mode 100644 kokoro/linux/ruby27/continuous.cfg create mode 100644 kokoro/linux/ruby27/presubmit.cfg create mode 100755 kokoro/macos/ruby27/build.sh create mode 100644 kokoro/macos/ruby27/continuous.cfg create mode 100644 kokoro/macos/ruby27/presubmit.cfg diff --git a/kokoro/linux/dockerfile/test/ruby/Dockerfile b/kokoro/linux/dockerfile/test/ruby/Dockerfile index 41bfedeb33..9037da715f 100644 --- a/kokoro/linux/dockerfile/test/ruby/Dockerfile +++ b/kokoro/linux/dockerfile/test/ruby/Dockerfile @@ -32,6 +32,7 @@ RUN /bin/bash -l -c "rvm install 2.3.8" RUN /bin/bash -l -c "rvm install 2.4.5" RUN /bin/bash -l -c "rvm install 2.5.1" RUN /bin/bash -l -c "rvm install 2.6.0" +RUN /bin/bash -l -c "rvm install 2.7.0" RUN /bin/bash -l -c "echo 'gem: --no-ri --no-rdoc' > ~/.gemrc" RUN /bin/bash -l -c "echo 'export PATH=/usr/local/rvm/bin:$PATH' >> ~/.bashrc" diff --git a/kokoro/linux/ruby27/build.sh b/kokoro/linux/ruby27/build.sh new file mode 100755 index 0000000000..c38ee36e58 --- /dev/null +++ b/kokoro/linux/ruby27/build.sh @@ -0,0 +1,18 @@ +#!/bin/bash +# +# This is the top-level script we give to Kokoro as the entry point for +# running the "pull request" project: +# +# This script selects a specific Dockerfile (for building a Docker image) and +# a script to run inside that image. Then we delegate to the general +# build_and_run_docker.sh script. + +# Change to repo root +cd $(dirname $0)/../../.. + +export DOCKERHUB_ORGANIZATION=protobuftesting +export DOCKERFILE_DIR=kokoro/linux/dockerfile/test/ruby +export DOCKER_RUN_SCRIPT=kokoro/linux/pull_request_in_docker.sh +export OUTPUT_DIR=testoutput +export TEST_SET="ruby27" +./kokoro/linux/build_and_run_docker.sh diff --git a/kokoro/linux/ruby27/continuous.cfg b/kokoro/linux/ruby27/continuous.cfg new file mode 100644 index 0000000000..9cce8c90e1 --- /dev/null +++ b/kokoro/linux/ruby27/continuous.cfg @@ -0,0 +1,11 @@ +# Config file for running tests in Kokoro + +# Location of the build script in repository +build_file: "protobuf/kokoro/linux/ruby27/build.sh" +timeout_mins: 120 + +action { + define_artifacts { + regex: "**/sponge_log.xml" + } +} diff --git a/kokoro/linux/ruby27/presubmit.cfg b/kokoro/linux/ruby27/presubmit.cfg new file mode 100644 index 0000000000..9cce8c90e1 --- /dev/null +++ b/kokoro/linux/ruby27/presubmit.cfg @@ -0,0 +1,11 @@ +# Config file for running tests in Kokoro + +# Location of the build script in repository +build_file: "protobuf/kokoro/linux/ruby27/build.sh" +timeout_mins: 120 + +action { + define_artifacts { + regex: "**/sponge_log.xml" + } +} diff --git a/kokoro/macos/ruby27/build.sh b/kokoro/macos/ruby27/build.sh new file mode 100755 index 0000000000..16bcbd6cbd --- /dev/null +++ b/kokoro/macos/ruby27/build.sh @@ -0,0 +1,11 @@ +#!/bin/bash +# +# Build file to set up and run tests + +# Change to repo root +cd $(dirname $0)/../../.. + +# Prepare worker environment to run tests +source kokoro/macos/prepare_build_macos_rc + +./tests.sh ruby27 diff --git a/kokoro/macos/ruby27/continuous.cfg b/kokoro/macos/ruby27/continuous.cfg new file mode 100644 index 0000000000..b10b455da3 --- /dev/null +++ b/kokoro/macos/ruby27/continuous.cfg @@ -0,0 +1,5 @@ +# Config file for running tests in Kokoro + +# Location of the build script in repository +build_file: "protobuf/kokoro/macos/ruby27/build.sh" +timeout_mins: 1440 diff --git a/kokoro/macos/ruby27/presubmit.cfg b/kokoro/macos/ruby27/presubmit.cfg new file mode 100644 index 0000000000..b10b455da3 --- /dev/null +++ b/kokoro/macos/ruby27/presubmit.cfg @@ -0,0 +1,5 @@ +# Config file for running tests in Kokoro + +# Location of the build script in repository +build_file: "protobuf/kokoro/macos/ruby27/build.sh" +timeout_mins: 1440 diff --git a/ruby/compatibility_tests/v3.0.0/tests/repeated_field_test.rb b/ruby/compatibility_tests/v3.0.0/tests/repeated_field_test.rb index 4ebb731a83..b4a158f37c 100755 --- a/ruby/compatibility_tests/v3.0.0/tests/repeated_field_test.rb +++ b/ruby/compatibility_tests/v3.0.0/tests/repeated_field_test.rb @@ -20,6 +20,7 @@ class RepeatedFieldTest < Test::Unit::TestCase :iter_for_each_with_index, :dimensions, :copy_data, :copy_data_simple, :nitems, :iter_for_reverse_each, :indexes, :append, :prepend] arr_methods -= [:union, :difference, :filter!] + arr_methods -= [:intersection, :deconstruct] # ruby 2.7 methods we can ignore arr_methods.each do |method_name| assert m.repeated_string.respond_to?(method_name) == true, "does not respond to #{method_name}" end diff --git a/ruby/tests/gc_test.rb b/ruby/tests/gc_test.rb index 55b96289e8..6ef4e2e301 100755 --- a/ruby/tests/gc_test.rb +++ b/ruby/tests/gc_test.rb @@ -4,7 +4,9 @@ $LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__))) old_gc = GC.stress -GC.stress = 0x01 | 0x04 +# Ruby 2.7.0 - 2.7.1 has a GC bug in its parser, so turn off stress for now +# See https://bugs.ruby-lang.org/issues/16807 +GC.stress = 0x01 | 0x04 unless RUBY_VERSION.match?(/^2\.7\./) require 'generated_code_pb' require 'generated_code_proto2_pb' GC.stress = old_gc diff --git a/ruby/travis-test.sh b/ruby/travis-test.sh index 6dec0c906a..b39a6c5d12 100755 --- a/ruby/travis-test.sh +++ b/ruby/travis-test.sh @@ -16,7 +16,7 @@ test_version() { git clean -f && \ gem install bundler && bundle && \ rake test" - elif [ "$version" == "ruby-2.6.0" ] ; then + elif [ "$version" == "ruby-2.6.0" -o "$version" == "ruby-2.7.0" ] ; then bash --login -c \ "rvm install $version && rvm use $version && \ which ruby && \ diff --git a/tests.sh b/tests.sh index 84fb0b124b..faaec76f0a 100755 --- a/tests.sh +++ b/tests.sh @@ -919,6 +919,7 @@ Usage: $0 { cpp | ruby24 | ruby25 | ruby26 | + ruby27 | jruby | ruby_all | php5.5 | From 59f8dd5fafe44cb2aee5dd352361b3a540880a1c Mon Sep 17 00:00:00 2001 From: Thomas Van Lenten Date: Fri, 3 Apr 2020 17:08:53 -0400 Subject: [PATCH 30/38] [ObjC] Move over some custom logic to Descriptor provided info. FieldDescriptor::has_presence works as a replacement for the custom logic we had for FieldGenerator::WantsHasProperty(), and is already proto3 optional aware. --- .../compiler/objectivec/objectivec_field.cc | 21 ++++--------------- .../compiler/objectivec/objectivec_field.h | 4 +--- .../compiler/objectivec/objectivec_helpers.h | 4 ---- .../objectivec/objectivec_message_field.cc | 10 --------- .../objectivec/objectivec_message_field.h | 1 - 5 files changed, 5 insertions(+), 35 deletions(-) diff --git a/src/google/protobuf/compiler/objectivec/objectivec_field.cc b/src/google/protobuf/compiler/objectivec/objectivec_field.cc index 829f4258f9..574cf85e16 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_field.cc +++ b/src/google/protobuf/compiler/objectivec/objectivec_field.cc @@ -245,6 +245,10 @@ void FieldGenerator::SetOneofIndexBase(int index_base) { } } +bool FieldGenerator::WantsHasProperty(void) const { + return descriptor_->has_presence() && !descriptor_->real_containing_oneof(); +} + void FieldGenerator::FinishInitialization(void) { // If "property_type" wasn't set, make it "storage_type". if ((variables_.find("property_type") == variables_.end()) && @@ -289,18 +293,6 @@ void SingleFieldGenerator::GeneratePropertyImplementation( } } -bool SingleFieldGenerator::WantsHasProperty(void) const { - if (descriptor_->containing_oneof() != NULL) { - // If in a oneof, it uses the oneofcase instead of a has bit. - return false; - } - if (HasFieldPresence(descriptor_->file())) { - // In proto1/proto2, every field has a has_$name$() method. - return true; - } - return false; -} - bool SingleFieldGenerator::RuntimeUsesHasBit(void) const { if (descriptor_->containing_oneof() != NULL) { // The oneof tracks what is set instead. @@ -402,11 +394,6 @@ void RepeatedFieldGenerator::GeneratePropertyDeclaration( printer->Print("\n"); } -bool RepeatedFieldGenerator::WantsHasProperty(void) const { - // Consumer check the array size/existence rather than a has bit. - return false; -} - bool RepeatedFieldGenerator::RuntimeUsesHasBit(void) const { return false; // The array having anything is what is used. } diff --git a/src/google/protobuf/compiler/objectivec/objectivec_field.h b/src/google/protobuf/compiler/objectivec/objectivec_field.h index 68c470a50b..2ebe55b2fc 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_field.h +++ b/src/google/protobuf/compiler/objectivec/objectivec_field.h @@ -96,7 +96,7 @@ class FieldGenerator { FieldGenerator(const FieldDescriptor* descriptor, const Options& options); virtual void FinishInitialization(void); - virtual bool WantsHasProperty(void) const = 0; + bool WantsHasProperty(void) const; const FieldDescriptor* descriptor_; std::map variables_; @@ -119,7 +119,6 @@ class SingleFieldGenerator : public FieldGenerator { protected: SingleFieldGenerator(const FieldDescriptor* descriptor, const Options& options); - virtual bool WantsHasProperty(void) const; }; // Subclass with common support for when the field ends up as an ObjC Object. @@ -156,7 +155,6 @@ class RepeatedFieldGenerator : public ObjCObjFieldGenerator { RepeatedFieldGenerator(const FieldDescriptor* descriptor, const Options& options); virtual void FinishInitialization(void); - virtual bool WantsHasProperty(void) const; }; // Convenience class which constructs FieldGenerators for a Descriptor. diff --git a/src/google/protobuf/compiler/objectivec/objectivec_helpers.h b/src/google/protobuf/compiler/objectivec/objectivec_helpers.h index c6a2c7733b..5f91f4e4ed 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_helpers.h +++ b/src/google/protobuf/compiler/objectivec/objectivec_helpers.h @@ -126,10 +126,6 @@ string PROTOC_EXPORT ObjCClass(const string& class_name); // be refrerred to by ObjCClass. string PROTOC_EXPORT ObjCClassDeclaration(const string& class_name); -inline bool HasFieldPresence(const FileDescriptor* file) { - return file->syntax() != FileDescriptor::SYNTAX_PROTO3; -} - inline bool HasPreservingUnknownEnumSemantics(const FileDescriptor* file) { return file->syntax() == FileDescriptor::SYNTAX_PROTO3; } diff --git a/src/google/protobuf/compiler/objectivec/objectivec_message_field.cc b/src/google/protobuf/compiler/objectivec/objectivec_message_field.cc index 2730e7591d..7bf33f4c12 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_message_field.cc +++ b/src/google/protobuf/compiler/objectivec/objectivec_message_field.cc @@ -77,16 +77,6 @@ void MessageFieldGenerator::DetermineObjectiveCClassDefinitions( fwd_decls->insert(ObjCClassDeclaration(variable("storage_type"))); } -bool MessageFieldGenerator::WantsHasProperty(void) const { - if (descriptor_->containing_oneof() != NULL) { - // If in a oneof, it uses the oneofcase instead of a has bit. - return false; - } - // In both proto2 & proto3, message fields have a has* property to tell - // when it is a non default value. - return true; -} - RepeatedMessageFieldGenerator::RepeatedMessageFieldGenerator( const FieldDescriptor* descriptor, const Options& options) : RepeatedFieldGenerator(descriptor, options) { diff --git a/src/google/protobuf/compiler/objectivec/objectivec_message_field.h b/src/google/protobuf/compiler/objectivec/objectivec_message_field.h index 692f94c026..a53c4a540c 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_message_field.h +++ b/src/google/protobuf/compiler/objectivec/objectivec_message_field.h @@ -52,7 +52,6 @@ class MessageFieldGenerator : public ObjCObjFieldGenerator { MessageFieldGenerator& operator=(const MessageFieldGenerator&) = delete; virtual ~MessageFieldGenerator(); - virtual bool WantsHasProperty(void) const; public: virtual void DetermineForwardDeclarations(std::set* fwd_decls) const; From e9b0c9265984bec7c7bce69dc6ac2dbd015a62f9 Mon Sep 17 00:00:00 2001 From: Thomas Van Lenten Date: Mon, 6 Apr 2020 16:17:55 -0400 Subject: [PATCH 31/38] [ObjC] Update oneof generation for proto3 optional. - Don't make an OneofGenerator for synthetic oneofs. - Update the field calculations that determine if hasbits are needed to know about synthetic oneofs and ignore them. --- objectivec/GPBStruct.pbobjc.m | 2 +- .../protobuf/compiler/objectivec/objectivec_field.cc | 9 +++++---- .../compiler/objectivec/objectivec_message.cc | 11 ++++++----- .../protobuf/compiler/objectivec/objectivec_oneof.cc | 2 +- 4 files changed, 13 insertions(+), 11 deletions(-) diff --git a/objectivec/GPBStruct.pbobjc.m b/objectivec/GPBStruct.pbobjc.m index dbdcbe1df0..b43e9cd906 100644 --- a/objectivec/GPBStruct.pbobjc.m +++ b/objectivec/GPBStruct.pbobjc.m @@ -256,7 +256,7 @@ void SetGPBValue_NullValue_RawValue(GPBValue *message, int32_t value) { } void GPBValue_ClearKindOneOfCase(GPBValue *message) { - GPBDescriptor *descriptor = [message descriptor]; + GPBDescriptor *descriptor = [GPBValue descriptor]; GPBOneofDescriptor *oneof = [descriptor.oneofs objectAtIndex:0]; GPBMaybeClearOneof(message, oneof, -1, 0); } diff --git a/src/google/protobuf/compiler/objectivec/objectivec_field.cc b/src/google/protobuf/compiler/objectivec/objectivec_field.cc index 574cf85e16..bc39d32d28 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_field.cc +++ b/src/google/protobuf/compiler/objectivec/objectivec_field.cc @@ -238,8 +238,9 @@ void FieldGenerator::SetExtraRuntimeHasBitsBase(int index_base) { } void FieldGenerator::SetOneofIndexBase(int index_base) { - if (descriptor_->containing_oneof() != NULL) { - int index = descriptor_->containing_oneof()->index() + index_base; + const OneofDescriptor *oneof = descriptor_->real_containing_oneof(); + if (oneof != NULL) { + int index = oneof->index() + index_base; // Flip the sign to mark it as a oneof. variables_["has_index"] = StrCat(-index); } @@ -294,7 +295,7 @@ void SingleFieldGenerator::GeneratePropertyImplementation( } bool SingleFieldGenerator::RuntimeUsesHasBit(void) const { - if (descriptor_->containing_oneof() != NULL) { + if (descriptor_->real_containing_oneof()) { // The oneof tracks what is set instead. return false; } @@ -395,7 +396,7 @@ void RepeatedFieldGenerator::GeneratePropertyDeclaration( } bool RepeatedFieldGenerator::RuntimeUsesHasBit(void) const { - return false; // The array having anything is what is used. + return false; // The array (or map/dict) having anything is what is used. } FieldGeneratorMap::FieldGeneratorMap(const Descriptor* descriptor, diff --git a/src/google/protobuf/compiler/objectivec/objectivec_message.cc b/src/google/protobuf/compiler/objectivec/objectivec_message.cc index b5d8128a99..f2287f6711 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_message.cc +++ b/src/google/protobuf/compiler/objectivec/objectivec_message.cc @@ -185,7 +185,7 @@ MessageGenerator::MessageGenerator(const string& root_classname, new ExtensionGenerator(class_name_, descriptor_->extension(i))); } - for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { + for (int i = 0; i < descriptor_->real_oneof_decl_count(); i++) { OneofGenerator* generator = new OneofGenerator(descriptor_->oneof_decl(i)); oneof_generators_.emplace_back(generator); } @@ -339,11 +339,12 @@ void MessageGenerator::GenerateMessageHeader(io::Printer* printer) { "deprecated_attribute", deprecated_attribute_, "comments", message_comments); - std::vector seen_oneofs(descriptor_->oneof_decl_count(), 0); + std::vector seen_oneofs(oneof_generators_.size(), 0); for (int i = 0; i < descriptor_->field_count(); i++) { const FieldDescriptor* field = descriptor_->field(i); - if (field->containing_oneof() != NULL) { - const int oneof_index = field->containing_oneof()->index(); + const OneofDescriptor *oneof = field->real_containing_oneof(); + if (oneof) { + const int oneof_index = oneof->index(); if (!seen_oneofs[oneof_index]) { seen_oneofs[oneof_index] = 1; oneof_generators_[oneof_index]->GeneratePublicCasePropertyDeclaration( @@ -443,7 +444,7 @@ void MessageGenerator::GenerateSource(io::Printer* printer) { field_generators_.SetOneofIndexBase(sizeof_has_storage); // sizeof_has_storage needs enough bits for the single fields that aren't in // any oneof, and then one int32 for each oneof (to store the field number). - sizeof_has_storage += descriptor_->oneof_decl_count(); + sizeof_has_storage += oneof_generators_.size(); printer->Print( "\n" diff --git a/src/google/protobuf/compiler/objectivec/objectivec_oneof.cc b/src/google/protobuf/compiler/objectivec/objectivec_oneof.cc index 5b37c4e945..2dbfb71bbd 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_oneof.cc +++ b/src/google/protobuf/compiler/objectivec/objectivec_oneof.cc @@ -120,7 +120,7 @@ void OneofGenerator::GenerateClearFunctionImplementation(io::Printer* printer) { printer->Print( variables_, "void $owning_message_class$_Clear$capitalized_name$OneOfCase($owning_message_class$ *message) {\n" - " GPBDescriptor *descriptor = [message descriptor];\n" + " GPBDescriptor *descriptor = [$owning_message_class$ descriptor];\n" " GPBOneofDescriptor *oneof = [descriptor.oneofs objectAtIndex:$raw_index$];\n" " GPBMaybeClearOneof(message, oneof, $index$, 0);\n" "}\n"); From 8d224b4c48c7821a967abf274db44ac9bd5f4db9 Mon Sep 17 00:00:00 2001 From: Thomas Van Lenten Date: Wed, 8 Apr 2020 11:34:37 -0400 Subject: [PATCH 32/38] [ObjC] Runtime support for proto3 optional. - Add a Descriptor flag to capture if the field should clear on being zeroed. - Update the runtime to use the new clear on zero flag. - Add a flag on message initialization to indicate the sources were generated with/without this support so the runtime can backfill the flag for older generated sources. --- objectivec/GPBDescriptor.m | 40 ++++---- objectivec/GPBDescriptor_PackagePrivate.h | 19 ++-- objectivec/GPBUtilities.m | 106 ++++++++++------------ 3 files changed, 85 insertions(+), 80 deletions(-) diff --git a/objectivec/GPBDescriptor.m b/objectivec/GPBDescriptor.m index 130f1b96a8..bb178138aa 100644 --- a/objectivec/GPBDescriptor.m +++ b/objectivec/GPBDescriptor.m @@ -128,6 +128,8 @@ static NSArray *NewFieldsArrayForHasIndex(int hasIndex, (flags & GPBDescriptorInitializationFlag_FieldsWithDefault) != 0; BOOL usesClassRefs = (flags & GPBDescriptorInitializationFlag_UsesClassRefs) != 0; + BOOL proto3OptionalKnown = + (flags & GPBDescriptorInitializationFlag_Proto3OptionalKnown) != 0; void *desc; for (uint32_t i = 0; i < fieldCount; ++i) { @@ -146,6 +148,7 @@ static NSArray *NewFieldsArrayForHasIndex(int hasIndex, [[GPBFieldDescriptor alloc] initWithFieldDescription:desc includesDefault:fieldsIncludeDefault usesClassRefs:usesClassRefs + proto3OptionalKnown:proto3OptionalKnown syntax:syntax]; [fields addObject:fieldDescriptor]; [fieldDescriptor release]; @@ -488,6 +491,7 @@ uint32_t GPBFieldAlternateTag(GPBFieldDescriptor *self) { - (instancetype)initWithFieldDescription:(void *)description includesDefault:(BOOL)includesDefault usesClassRefs:(BOOL)usesClassRefs + proto3OptionalKnown:(BOOL)proto3OptionalKnown syntax:(GPBFileSyntax)syntax { if ((self = [super init])) { GPBMessageFieldDescription *coreDesc; @@ -504,20 +508,33 @@ uint32_t GPBFieldAlternateTag(GPBFieldDescriptor *self) { BOOL isMessage = GPBDataTypeIsMessage(dataType); BOOL isMapOrArray = GPBFieldIsMapOrArray(self); + // If proto3 optionals weren't know, compute the flag for the rest of the runtime. + if (!proto3OptionalKnown) { + // If it was... + // - proto3 syntax + // - not repeated/map + // - not in a oneof (negative has index) + // - not a message (the flag doesn't make sense for messages) + BOOL clearOnZero = ((syntax == GPBFileSyntaxProto3) && + !isMapOrArray && + (coreDesc->hasIndex >= 0) && + !isMessage); + if (clearOnZero) { + coreDesc->flags |= GPBFieldClearHasIvarOnZero; + } + } + if (isMapOrArray) { // map<>/repeated fields get a *Count property (inplace of a has*) to // support checking if there are any entries without triggering // autocreation. hasOrCountSel_ = SelFromStrings(NULL, coreDesc->name, "_Count", NO); } else { - // If there is a positive hasIndex, then: - // - All fields types for proto2 messages get has* selectors. - // - Only message fields for proto3 messages get has* selectors. - // Note: the positive check is to handle oneOfs, we can't check - // containingOneof_ because it isn't set until after initialization. + // Know it is a single field; it gets has/setHas selectors if... + // - not in a oneof (negative has index) + // - not clearing on zero if ((coreDesc->hasIndex >= 0) && - (coreDesc->hasIndex != GPBNoHasBit) && - ((syntax != GPBFileSyntaxProto3) || isMessage)) { + ((coreDesc->flags & GPBFieldClearHasIvarOnZero) == 0)) { hasOrCountSel_ = SelFromStrings("has", coreDesc->name, NULL, NO); setHasSel_ = SelFromStrings("setHas", coreDesc->name, NULL, YES); } @@ -567,15 +584,6 @@ uint32_t GPBFieldAlternateTag(GPBFieldDescriptor *self) { return self; } -- (instancetype)initWithFieldDescription:(void *)description - includesDefault:(BOOL)includesDefault - syntax:(GPBFileSyntax)syntax { - return [self initWithFieldDescription:description - includesDefault:includesDefault - usesClassRefs:NO - syntax:syntax]; -} - - (void)dealloc { if (description_->dataType == GPBDataTypeBytes && !(description_->flags & GPBFieldRepeated)) { diff --git a/objectivec/GPBDescriptor_PackagePrivate.h b/objectivec/GPBDescriptor_PackagePrivate.h index 09c1202a07..467504f16a 100644 --- a/objectivec/GPBDescriptor_PackagePrivate.h +++ b/objectivec/GPBDescriptor_PackagePrivate.h @@ -45,6 +45,10 @@ typedef NS_OPTIONS(uint16_t, GPBFieldFlags) { GPBFieldOptional = 1 << 3, GPBFieldHasDefaultValue = 1 << 4, + // Indicate that the field should "clear" when set to zero value. This is the + // proto3 non optional behavior for singular data (ints, data, string, enum) + // fields. + GPBFieldClearHasIvarOnZero = 1 << 5, // Indicates the field needs custom handling for the TextFormat name, if not // set, the name can be derived from the ObjC name. GPBFieldTextFormatNameCustom = 1 << 6, @@ -149,7 +153,13 @@ typedef NS_OPTIONS(uint32_t, GPBDescriptorInitializationFlags) { // This is used as a stopgap as we move from using class names to class // references. The runtime needs to support both until we allow a // breaking change in the runtime. - GPBDescriptorInitializationFlag_UsesClassRefs = 1 << 2, + GPBDescriptorInitializationFlag_UsesClassRefs = 1 << 2, + + // This flag is used to indicate that the generated sources already containg + // the `GPBFieldClearHasIvarOnZero` flag and it doesn't have to be computed + // at startup, this allows older generated code to still work with the + // current runtime library. + GPBDescriptorInitializationFlag_Proto3OptionalKnown = 1 << 3, }; @interface GPBDescriptor () { @@ -225,14 +235,9 @@ typedef NS_OPTIONS(uint32_t, GPBDescriptorInitializationFlags) { - (instancetype)initWithFieldDescription:(void *)description includesDefault:(BOOL)includesDefault usesClassRefs:(BOOL)usesClassRefs + proto3OptionalKnown:(BOOL)proto3OptionalKnown syntax:(GPBFileSyntax)syntax; -// Deprecated. Equivalent to calling above with `usesClassRefs = NO`. -- (instancetype)initWithFieldDescription:(void *)description - includesDefault:(BOOL)includesDefault - syntax:(GPBFileSyntax)syntax; - - @end @interface GPBEnumDescriptor () diff --git a/objectivec/GPBUtilities.m b/objectivec/GPBUtilities.m index 7a1635f64a..7b3bbda723 100644 --- a/objectivec/GPBUtilities.m +++ b/objectivec/GPBUtilities.m @@ -400,6 +400,7 @@ void GPBMaybeClearOneof(GPBMessage *self, GPBOneofDescriptor *oneof, //% NAME$S GPBFieldDescriptor *field, //% NAME$S TYPE value, //% NAME$S GPBFileSyntax syntax) { +//%#pragma unused(syntax) //% GPBOneofDescriptor *oneof = field->containingOneof_; //% GPBMessageFieldDescription *fieldDesc = field->description_; //% if (oneof) { @@ -416,11 +417,10 @@ void GPBMaybeClearOneof(GPBMessage *self, GPBOneofDescriptor *oneof, //% uint8_t *storage = (uint8_t *)self->messageStorage_; //% TYPE *typePtr = (TYPE *)&storage[fieldDesc->offset]; //% *typePtr = value; -//% // proto2: any value counts as having been set; proto3, it -//% // has to be a non zero value or be in a oneof. -//% BOOL hasValue = ((syntax == GPBFileSyntaxProto2) -//% || (value != (TYPE)0) -//% || (field->containingOneof_ != NULL)); +//% // If the value is zero, then we only count the field as "set" if the field +//% // shouldn't auto clear on zero. +//% BOOL hasValue = ((value != (TYPE)0) +//% || ((fieldDesc->flags & GPBFieldClearHasIvarOnZero) == 0)); //% GPBSetHasIvar(self, fieldDesc->hasIndex, fieldDesc->number, hasValue); //% GPBBecomeVisibleToAutocreator(self); //%} @@ -548,6 +548,7 @@ void GPBSetObjectIvarWithFieldInternal(GPBMessage *self, void GPBSetRetainedObjectIvarWithFieldInternal(GPBMessage *self, GPBFieldDescriptor *field, id value, GPBFileSyntax syntax) { +#pragma unused(syntax) NSCAssert(self->messageStorage_ != NULL, @"%@: All messages should have storage (from init)", [self class]); @@ -596,24 +597,15 @@ void GPBSetRetainedObjectIvarWithFieldInternal(GPBMessage *self, } // Clear "has" if they are being set to nil. BOOL setHasValue = (value != nil); - // Under proto3, Bytes & String fields get cleared by resetting them to - // their default (empty) values, so if they are set to something of length - // zero, they are being cleared. - if ((syntax == GPBFileSyntaxProto3) && !fieldIsMessage && + // If the field should clear on a "zero" value, then check if the string/data + // was zero length, and clear instead. + if (((fieldDesc->flags & GPBFieldClearHasIvarOnZero) != 0) && ([value length] == 0)) { - // Except, if the field was in a oneof, then it still gets recorded as - // having been set so the state of the oneof can be serialized back out. - if (!oneof) { - setHasValue = NO; - } - if (setHasValue) { - NSCAssert(value != nil, @"Should never be setting has for nil"); - } else { - // The value passed in was retained, it must be released since we - // aren't saving anything in the field. - [value release]; - value = nil; - } + setHasValue = NO; + // The value passed in was retained, it must be released since we + // aren't saving anything in the field. + [value release]; + value = nil; } GPBSetHasIvar(self, fieldDesc->hasIndex, fieldDesc->number, setHasValue); } @@ -802,6 +794,7 @@ void GPBSetBoolIvarWithFieldInternal(GPBMessage *self, GPBFieldDescriptor *field, BOOL value, GPBFileSyntax syntax) { +#pragma unused(syntax) GPBMessageFieldDescription *fieldDesc = field->description_; GPBOneofDescriptor *oneof = field->containingOneof_; if (oneof) { @@ -814,11 +807,10 @@ void GPBSetBoolIvarWithFieldInternal(GPBMessage *self, // the offset is never negative) GPBSetHasIvar(self, (int32_t)(fieldDesc->offset), fieldDesc->number, value); - // proto2: any value counts as having been set; proto3, it - // has to be a non zero value or be in a oneof. - BOOL hasValue = ((syntax == GPBFileSyntaxProto2) - || (value != (BOOL)0) - || (field->containingOneof_ != NULL)); + // If the value is zero, then we only count the field as "set" if the field + // shouldn't auto clear on zero. + BOOL hasValue = ((value != (BOOL)0) + || ((fieldDesc->flags & GPBFieldClearHasIvarOnZero) == 0)); GPBSetHasIvar(self, fieldDesc->hasIndex, fieldDesc->number, hasValue); GPBBecomeVisibleToAutocreator(self); } @@ -873,6 +865,7 @@ void GPBSetInt32IvarWithFieldInternal(GPBMessage *self, GPBFieldDescriptor *field, int32_t value, GPBFileSyntax syntax) { +#pragma unused(syntax) GPBOneofDescriptor *oneof = field->containingOneof_; GPBMessageFieldDescription *fieldDesc = field->description_; if (oneof) { @@ -889,11 +882,10 @@ void GPBSetInt32IvarWithFieldInternal(GPBMessage *self, uint8_t *storage = (uint8_t *)self->messageStorage_; int32_t *typePtr = (int32_t *)&storage[fieldDesc->offset]; *typePtr = value; - // proto2: any value counts as having been set; proto3, it - // has to be a non zero value or be in a oneof. - BOOL hasValue = ((syntax == GPBFileSyntaxProto2) - || (value != (int32_t)0) - || (field->containingOneof_ != NULL)); + // If the value is zero, then we only count the field as "set" if the field + // shouldn't auto clear on zero. + BOOL hasValue = ((value != (int32_t)0) + || ((fieldDesc->flags & GPBFieldClearHasIvarOnZero) == 0)); GPBSetHasIvar(self, fieldDesc->hasIndex, fieldDesc->number, hasValue); GPBBecomeVisibleToAutocreator(self); } @@ -949,6 +941,7 @@ void GPBSetUInt32IvarWithFieldInternal(GPBMessage *self, GPBFieldDescriptor *field, uint32_t value, GPBFileSyntax syntax) { +#pragma unused(syntax) GPBOneofDescriptor *oneof = field->containingOneof_; GPBMessageFieldDescription *fieldDesc = field->description_; if (oneof) { @@ -965,11 +958,10 @@ void GPBSetUInt32IvarWithFieldInternal(GPBMessage *self, uint8_t *storage = (uint8_t *)self->messageStorage_; uint32_t *typePtr = (uint32_t *)&storage[fieldDesc->offset]; *typePtr = value; - // proto2: any value counts as having been set; proto3, it - // has to be a non zero value or be in a oneof. - BOOL hasValue = ((syntax == GPBFileSyntaxProto2) - || (value != (uint32_t)0) - || (field->containingOneof_ != NULL)); + // If the value is zero, then we only count the field as "set" if the field + // shouldn't auto clear on zero. + BOOL hasValue = ((value != (uint32_t)0) + || ((fieldDesc->flags & GPBFieldClearHasIvarOnZero) == 0)); GPBSetHasIvar(self, fieldDesc->hasIndex, fieldDesc->number, hasValue); GPBBecomeVisibleToAutocreator(self); } @@ -1025,6 +1017,7 @@ void GPBSetInt64IvarWithFieldInternal(GPBMessage *self, GPBFieldDescriptor *field, int64_t value, GPBFileSyntax syntax) { +#pragma unused(syntax) GPBOneofDescriptor *oneof = field->containingOneof_; GPBMessageFieldDescription *fieldDesc = field->description_; if (oneof) { @@ -1041,11 +1034,10 @@ void GPBSetInt64IvarWithFieldInternal(GPBMessage *self, uint8_t *storage = (uint8_t *)self->messageStorage_; int64_t *typePtr = (int64_t *)&storage[fieldDesc->offset]; *typePtr = value; - // proto2: any value counts as having been set; proto3, it - // has to be a non zero value or be in a oneof. - BOOL hasValue = ((syntax == GPBFileSyntaxProto2) - || (value != (int64_t)0) - || (field->containingOneof_ != NULL)); + // If the value is zero, then we only count the field as "set" if the field + // shouldn't auto clear on zero. + BOOL hasValue = ((value != (int64_t)0) + || ((fieldDesc->flags & GPBFieldClearHasIvarOnZero) == 0)); GPBSetHasIvar(self, fieldDesc->hasIndex, fieldDesc->number, hasValue); GPBBecomeVisibleToAutocreator(self); } @@ -1101,6 +1093,7 @@ void GPBSetUInt64IvarWithFieldInternal(GPBMessage *self, GPBFieldDescriptor *field, uint64_t value, GPBFileSyntax syntax) { +#pragma unused(syntax) GPBOneofDescriptor *oneof = field->containingOneof_; GPBMessageFieldDescription *fieldDesc = field->description_; if (oneof) { @@ -1117,11 +1110,10 @@ void GPBSetUInt64IvarWithFieldInternal(GPBMessage *self, uint8_t *storage = (uint8_t *)self->messageStorage_; uint64_t *typePtr = (uint64_t *)&storage[fieldDesc->offset]; *typePtr = value; - // proto2: any value counts as having been set; proto3, it - // has to be a non zero value or be in a oneof. - BOOL hasValue = ((syntax == GPBFileSyntaxProto2) - || (value != (uint64_t)0) - || (field->containingOneof_ != NULL)); + // If the value is zero, then we only count the field as "set" if the field + // shouldn't auto clear on zero. + BOOL hasValue = ((value != (uint64_t)0) + || ((fieldDesc->flags & GPBFieldClearHasIvarOnZero) == 0)); GPBSetHasIvar(self, fieldDesc->hasIndex, fieldDesc->number, hasValue); GPBBecomeVisibleToAutocreator(self); } @@ -1177,6 +1169,7 @@ void GPBSetFloatIvarWithFieldInternal(GPBMessage *self, GPBFieldDescriptor *field, float value, GPBFileSyntax syntax) { +#pragma unused(syntax) GPBOneofDescriptor *oneof = field->containingOneof_; GPBMessageFieldDescription *fieldDesc = field->description_; if (oneof) { @@ -1193,11 +1186,10 @@ void GPBSetFloatIvarWithFieldInternal(GPBMessage *self, uint8_t *storage = (uint8_t *)self->messageStorage_; float *typePtr = (float *)&storage[fieldDesc->offset]; *typePtr = value; - // proto2: any value counts as having been set; proto3, it - // has to be a non zero value or be in a oneof. - BOOL hasValue = ((syntax == GPBFileSyntaxProto2) - || (value != (float)0) - || (field->containingOneof_ != NULL)); + // If the value is zero, then we only count the field as "set" if the field + // shouldn't auto clear on zero. + BOOL hasValue = ((value != (float)0) + || ((fieldDesc->flags & GPBFieldClearHasIvarOnZero) == 0)); GPBSetHasIvar(self, fieldDesc->hasIndex, fieldDesc->number, hasValue); GPBBecomeVisibleToAutocreator(self); } @@ -1253,6 +1245,7 @@ void GPBSetDoubleIvarWithFieldInternal(GPBMessage *self, GPBFieldDescriptor *field, double value, GPBFileSyntax syntax) { +#pragma unused(syntax) GPBOneofDescriptor *oneof = field->containingOneof_; GPBMessageFieldDescription *fieldDesc = field->description_; if (oneof) { @@ -1269,11 +1262,10 @@ void GPBSetDoubleIvarWithFieldInternal(GPBMessage *self, uint8_t *storage = (uint8_t *)self->messageStorage_; double *typePtr = (double *)&storage[fieldDesc->offset]; *typePtr = value; - // proto2: any value counts as having been set; proto3, it - // has to be a non zero value or be in a oneof. - BOOL hasValue = ((syntax == GPBFileSyntaxProto2) - || (value != (double)0) - || (field->containingOneof_ != NULL)); + // If the value is zero, then we only count the field as "set" if the field + // shouldn't auto clear on zero. + BOOL hasValue = ((value != (double)0) + || ((fieldDesc->flags & GPBFieldClearHasIvarOnZero) == 0)); GPBSetHasIvar(self, fieldDesc->hasIndex, fieldDesc->number, hasValue); GPBBecomeVisibleToAutocreator(self); } From e1e5b8af7916f5a93d16b577a7c0b02ca9192f17 Mon Sep 17 00:00:00 2001 From: Thomas Van Lenten Date: Fri, 10 Apr 2020 15:55:32 -0400 Subject: [PATCH 33/38] [ObjC] Update some library internals to not pass syntax versions. - With the new flags, the syntax isn't needed, so don't pass it. - To keep library binary compatibility, rename the helpers since one "Internal" method was called from generated code. Keep a shim with the old signature to support those generated sources. --- objectivec/GPBMessage.m | 116 ++++++++---------- objectivec/GPBUtilities.m | 147 ++++++++++------------- objectivec/GPBUtilities_PackagePrivate.h | 94 +++++++-------- 3 files changed, 151 insertions(+), 206 deletions(-) diff --git a/objectivec/GPBMessage.m b/objectivec/GPBMessage.m index 973c18b423..140c6a29de 100644 --- a/objectivec/GPBMessage.m +++ b/objectivec/GPBMessage.m @@ -99,15 +99,13 @@ static id CreateArrayForField(GPBFieldDescriptor *field, GPBMessage *autocreator) __attribute__((ns_returns_retained)); static id GetOrCreateArrayIvarWithField(GPBMessage *self, - GPBFieldDescriptor *field, - GPBFileSyntax syntax); + GPBFieldDescriptor *field); static id GetArrayIvarWithField(GPBMessage *self, GPBFieldDescriptor *field); static id CreateMapForField(GPBFieldDescriptor *field, GPBMessage *autocreator) __attribute__((ns_returns_retained)); static id GetOrCreateMapIvarWithField(GPBMessage *self, - GPBFieldDescriptor *field, - GPBFileSyntax syntax); + GPBFieldDescriptor *field); static id GetMapIvarWithField(GPBMessage *self, GPBFieldDescriptor *field); static NSMutableDictionary *CloneExtensionMap(NSDictionary *extensionMap, NSZone *zone) @@ -560,10 +558,10 @@ static id CreateMapForField(GPBFieldDescriptor *field, #if !defined(__clang_analyzer__) // These functions are blocked from the analyzer because the analyzer sees the -// GPBSetRetainedObjectIvarWithFieldInternal() call as consuming the array/map, +// GPBSetRetainedObjectIvarWithFieldPrivate() call as consuming the array/map, // so use of the array/map after the call returns is flagged as a use after // free. -// But GPBSetRetainedObjectIvarWithFieldInternal() is "consuming" the retain +// But GPBSetRetainedObjectIvarWithFieldPrivate() is "consuming" the retain // count be holding onto the object (it is transferring it), the object is // still valid after returning from the call. The other way to avoid this // would be to add a -retain/-autorelease, but that would force every @@ -571,14 +569,13 @@ static id CreateMapForField(GPBFieldDescriptor *field, // and performance hit. static id GetOrCreateArrayIvarWithField(GPBMessage *self, - GPBFieldDescriptor *field, - GPBFileSyntax syntax) { + GPBFieldDescriptor *field) { id array = GPBGetObjectIvarWithFieldNoAutocreate(self, field); if (!array) { // No lock needed, this is called from places expecting to mutate // so no threading protection is needed. array = CreateArrayForField(field, nil); - GPBSetRetainedObjectIvarWithFieldInternal(self, field, array, syntax); + GPBSetRetainedObjectIvarWithFieldPrivate(self, field, array); } return array; } @@ -602,14 +599,13 @@ static id GetArrayIvarWithField(GPBMessage *self, GPBFieldDescriptor *field) { } static id GetOrCreateMapIvarWithField(GPBMessage *self, - GPBFieldDescriptor *field, - GPBFileSyntax syntax) { + GPBFieldDescriptor *field) { id dict = GPBGetObjectIvarWithFieldNoAutocreate(self, field); if (!dict) { // No lock needed, this is called from places expecting to mutate // so no threading protection is needed. dict = CreateMapForField(field, nil); - GPBSetRetainedObjectIvarWithFieldInternal(self, field, dict, syntax); + GPBSetRetainedObjectIvarWithFieldPrivate(self, field, dict); } return dict; } @@ -668,9 +664,8 @@ void GPBBecomeVisibleToAutocreator(GPBMessage *self) { // This will recursively make all parent messages visible until it reaches a // super-creator that's visible. if (self->autocreatorField_) { - GPBFileSyntax syntax = [self->autocreator_ descriptor].file.syntax; - GPBSetObjectIvarWithFieldInternal(self->autocreator_, - self->autocreatorField_, self, syntax); + GPBSetObjectIvarWithFieldPrivate(self->autocreator_, + self->autocreatorField_, self); } else { [self->autocreator_ setExtension:self->autocreatorExtension_ value:self]; } @@ -936,8 +931,6 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) { // Copy all the storage... memcpy(message->messageStorage_, messageStorage_, descriptor->storageSize_); - GPBFileSyntax syntax = descriptor.file.syntax; - // Loop over the fields doing fixup... for (GPBFieldDescriptor *field in descriptor->fields_) { if (GPBFieldIsMapOrArray(field)) { @@ -1005,8 +998,7 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) { // We retain here because the memcpy picked up the pointer value and // the next call to SetRetainedObject... will release the current value. [value retain]; - GPBSetRetainedObjectIvarWithFieldInternal(message, field, newValue, - syntax); + GPBSetRetainedObjectIvarWithFieldPrivate(message, field, newValue); } } else if (GPBFieldDataTypeIsMessage(field)) { // For object types, if we have a value, copy it. If we don't, @@ -1018,8 +1010,7 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) { // We retain here because the memcpy picked up the pointer value and // the next call to SetRetainedObject... will release the current value. [value retain]; - GPBSetRetainedObjectIvarWithFieldInternal(message, field, newValue, - syntax); + GPBSetRetainedObjectIvarWithFieldPrivate(message, field, newValue); } else { uint8_t *storage = (uint8_t *)message->messageStorage_; id *typePtr = (id *)&storage[field->description_->offset]; @@ -1033,8 +1024,7 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) { // We retain here because the memcpy picked up the pointer value and // the next call to SetRetainedObject... will release the current value. [value retain]; - GPBSetRetainedObjectIvarWithFieldInternal(message, field, newValue, - syntax); + GPBSetRetainedObjectIvarWithFieldPrivate(message, field, newValue); } else { // memcpy took care of the rest of the primitive fields if they were set. } @@ -2161,13 +2151,13 @@ static void MergeSingleFieldFromCodedInputStream( #define CASE_SINGLE_POD(NAME, TYPE, FUNC_TYPE) \ case GPBDataType##NAME: { \ TYPE val = GPBCodedInputStreamRead##NAME(&input->state_); \ - GPBSet##FUNC_TYPE##IvarWithFieldInternal(self, field, val, syntax); \ + GPBSet##FUNC_TYPE##IvarWithFieldPrivate(self, field, val); \ break; \ } #define CASE_SINGLE_OBJECT(NAME) \ case GPBDataType##NAME: { \ id val = GPBCodedInputStreamReadRetained##NAME(&input->state_); \ - GPBSetRetainedObjectIvarWithFieldInternal(self, field, val, syntax); \ + GPBSetRetainedObjectIvarWithFieldPrivate(self, field, val); \ break; \ } CASE_SINGLE_POD(Bool, BOOL, Bool) @@ -2198,7 +2188,7 @@ static void MergeSingleFieldFromCodedInputStream( } else { GPBMessage *message = [[field.msgClass alloc] init]; [input readMessage:message extensionRegistry:extensionRegistry]; - GPBSetRetainedObjectIvarWithFieldInternal(self, field, message, syntax); + GPBSetRetainedObjectIvarWithFieldPrivate(self, field, message); } break; } @@ -2217,7 +2207,7 @@ static void MergeSingleFieldFromCodedInputStream( [input readGroup:GPBFieldNumber(field) message:message extensionRegistry:extensionRegistry]; - GPBSetRetainedObjectIvarWithFieldInternal(self, field, message, syntax); + GPBSetRetainedObjectIvarWithFieldPrivate(self, field, message); } break; } @@ -2226,7 +2216,7 @@ static void MergeSingleFieldFromCodedInputStream( int32_t val = GPBCodedInputStreamReadEnum(&input->state_); if (GPBHasPreservingUnknownEnumSemantics(syntax) || [field isValidEnumValue:val]) { - GPBSetInt32IvarWithFieldInternal(self, field, val, syntax); + GPBSetInt32IvarWithFieldPrivate(self, field, val); } else { GPBUnknownFieldSet *unknownFields = GetOrMakeUnknownFields(self); [unknownFields mergeVarintField:GPBFieldNumber(field) value:val]; @@ -2240,7 +2230,7 @@ static void MergeRepeatedPackedFieldFromCodedInputStream( GPBCodedInputStream *input) { GPBDataType fieldDataType = GPBGetFieldDataType(field); GPBCodedInputStreamState *state = &input->state_; - id genericArray = GetOrCreateArrayIvarWithField(self, field, syntax); + id genericArray = GetOrCreateArrayIvarWithField(self, field); int32_t length = GPBCodedInputStreamReadInt32(state); size_t limit = GPBCodedInputStreamPushLimit(state, length); while (GPBCodedInputStreamBytesUntilLimit(state) > 0) { @@ -2293,7 +2283,7 @@ static void MergeRepeatedNotPackedFieldFromCodedInputStream( GPBMessage *self, GPBFieldDescriptor *field, GPBFileSyntax syntax, GPBCodedInputStream *input, GPBExtensionRegistry *extensionRegistry) { GPBCodedInputStreamState *state = &input->state_; - id genericArray = GetOrCreateArrayIvarWithField(self, field, syntax); + id genericArray = GetOrCreateArrayIvarWithField(self, field); switch (GPBGetFieldDataType(field)) { #define CASE_REPEATED_NOT_PACKED_POD(NAME, TYPE, ARRAY_TYPE) \ case GPBDataType##NAME: { \ @@ -2395,7 +2385,7 @@ static void MergeRepeatedNotPackedFieldFromCodedInputStream( } else { // fieldType == GPBFieldTypeMap // GPB*Dictionary or NSDictionary, exact type doesn't matter at this // point. - id map = GetOrCreateMapIvarWithField(self, fieldDescriptor, syntax); + id map = GetOrCreateMapIvarWithField(self, fieldDescriptor); [input readMapEntry:map extensionRegistry:extensionRegistry field:fieldDescriptor @@ -2469,7 +2459,6 @@ static void MergeRepeatedNotPackedFieldFromCodedInputStream( GPBBecomeVisibleToAutocreator(self); GPBDescriptor *descriptor = [[self class] descriptor]; - GPBFileSyntax syntax = descriptor.file.syntax; for (GPBFieldDescriptor *field in descriptor->fields_) { GPBFieldType fieldType = field.fieldType; @@ -2483,44 +2472,44 @@ static void MergeRepeatedNotPackedFieldFromCodedInputStream( GPBDataType fieldDataType = GPBGetFieldDataType(field); switch (fieldDataType) { case GPBDataTypeBool: - GPBSetBoolIvarWithFieldInternal( - self, field, GPBGetMessageBoolField(other, field), syntax); + GPBSetBoolIvarWithFieldPrivate( + self, field, GPBGetMessageBoolField(other, field)); break; case GPBDataTypeSFixed32: case GPBDataTypeEnum: case GPBDataTypeInt32: case GPBDataTypeSInt32: - GPBSetInt32IvarWithFieldInternal( - self, field, GPBGetMessageInt32Field(other, field), syntax); + GPBSetInt32IvarWithFieldPrivate( + self, field, GPBGetMessageInt32Field(other, field)); break; case GPBDataTypeFixed32: case GPBDataTypeUInt32: - GPBSetUInt32IvarWithFieldInternal( - self, field, GPBGetMessageUInt32Field(other, field), syntax); + GPBSetUInt32IvarWithFieldPrivate( + self, field, GPBGetMessageUInt32Field(other, field)); break; case GPBDataTypeSFixed64: case GPBDataTypeInt64: case GPBDataTypeSInt64: - GPBSetInt64IvarWithFieldInternal( - self, field, GPBGetMessageInt64Field(other, field), syntax); + GPBSetInt64IvarWithFieldPrivate( + self, field, GPBGetMessageInt64Field(other, field)); break; case GPBDataTypeFixed64: case GPBDataTypeUInt64: - GPBSetUInt64IvarWithFieldInternal( - self, field, GPBGetMessageUInt64Field(other, field), syntax); + GPBSetUInt64IvarWithFieldPrivate( + self, field, GPBGetMessageUInt64Field(other, field)); break; case GPBDataTypeFloat: - GPBSetFloatIvarWithFieldInternal( - self, field, GPBGetMessageFloatField(other, field), syntax); + GPBSetFloatIvarWithFieldPrivate( + self, field, GPBGetMessageFloatField(other, field)); break; case GPBDataTypeDouble: - GPBSetDoubleIvarWithFieldInternal( - self, field, GPBGetMessageDoubleField(other, field), syntax); + GPBSetDoubleIvarWithFieldPrivate( + self, field, GPBGetMessageDoubleField(other, field)); break; case GPBDataTypeBytes: case GPBDataTypeString: { id otherVal = GPBGetObjectIvarWithFieldNoAutocreate(other, field); - GPBSetObjectIvarWithFieldInternal(self, field, otherVal, syntax); + GPBSetObjectIvarWithFieldPrivate(self, field, otherVal); break; } case GPBDataTypeMessage: @@ -2532,8 +2521,7 @@ static void MergeRepeatedNotPackedFieldFromCodedInputStream( [message mergeFrom:otherVal]; } else { GPBMessage *message = [otherVal copy]; - GPBSetRetainedObjectIvarWithFieldInternal(self, field, message, - syntax); + GPBSetRetainedObjectIvarWithFieldPrivate(self, field, message); } break; } @@ -2547,17 +2535,17 @@ static void MergeRepeatedNotPackedFieldFromCodedInputStream( GPBDataType fieldDataType = field->description_->dataType; if (GPBDataTypeIsObject(fieldDataType)) { NSMutableArray *resultArray = - GetOrCreateArrayIvarWithField(self, field, syntax); + GetOrCreateArrayIvarWithField(self, field); [resultArray addObjectsFromArray:otherArray]; } else if (fieldDataType == GPBDataTypeEnum) { GPBEnumArray *resultArray = - GetOrCreateArrayIvarWithField(self, field, syntax); + GetOrCreateArrayIvarWithField(self, field); [resultArray addRawValuesFromArray:otherArray]; } else { // The array type doesn't matter, that all implement // -addValuesFromArray:. GPBInt32Array *resultArray = - GetOrCreateArrayIvarWithField(self, field, syntax); + GetOrCreateArrayIvarWithField(self, field); [resultArray addValuesFromArray:otherArray]; } } @@ -2571,19 +2559,19 @@ static void MergeRepeatedNotPackedFieldFromCodedInputStream( if (GPBDataTypeIsObject(keyDataType) && GPBDataTypeIsObject(valueDataType)) { NSMutableDictionary *resultDict = - GetOrCreateMapIvarWithField(self, field, syntax); + GetOrCreateMapIvarWithField(self, field); [resultDict addEntriesFromDictionary:otherDict]; } else if (valueDataType == GPBDataTypeEnum) { // The exact type doesn't matter, just need to know it is a // GPB*EnumDictionary. GPBInt32EnumDictionary *resultDict = - GetOrCreateMapIvarWithField(self, field, syntax); + GetOrCreateMapIvarWithField(self, field); [resultDict addRawEntriesFromDictionary:otherDict]; } else { // The exact type doesn't matter, they all implement // -addEntriesFromDictionary:. GPBInt32Int32Dictionary *resultDict = - GetOrCreateMapIvarWithField(self, field, syntax); + GetOrCreateMapIvarWithField(self, field); [resultDict addEntriesFromDictionary:otherDict]; } } @@ -3115,14 +3103,13 @@ static void ResolveIvarGet(__unsafe_unretained GPBFieldDescriptor *field, // See comment about __unsafe_unretained on ResolveIvarGet. static void ResolveIvarSet(__unsafe_unretained GPBFieldDescriptor *field, - GPBFileSyntax syntax, ResolveIvarAccessorMethodResult *result) { GPBDataType fieldDataType = GPBGetFieldDataType(field); switch (fieldDataType) { #define CASE_SET(NAME, TYPE, TRUE_NAME) \ case GPBDataType##NAME: { \ result->impToAdd = imp_implementationWithBlock(^(id obj, TYPE value) { \ - return GPBSet##TRUE_NAME##IvarWithFieldInternal(obj, field, value, syntax); \ + return GPBSet##TRUE_NAME##IvarWithFieldPrivate(obj, field, value); \ }); \ result->encodingSelector = @selector(set##NAME:); \ break; \ @@ -3130,7 +3117,7 @@ static void ResolveIvarSet(__unsafe_unretained GPBFieldDescriptor *field, #define CASE_SET_COPY(NAME) \ case GPBDataType##NAME: { \ result->impToAdd = imp_implementationWithBlock(^(id obj, id value) { \ - return GPBSetRetainedObjectIvarWithFieldInternal(obj, field, [value copy], syntax); \ + return GPBSetRetainedObjectIvarWithFieldPrivate(obj, field, [value copy]); \ }); \ result->encodingSelector = @selector(set##NAME:); \ break; \ @@ -3177,7 +3164,7 @@ static void ResolveIvarSet(__unsafe_unretained GPBFieldDescriptor *field, ResolveIvarGet(field, &result); break; } else if (sel == field->setSel_) { - ResolveIvarSet(field, descriptor.file.syntax, &result); + ResolveIvarSet(field, &result); break; } else if (sel == field->hasOrCountSel_) { int32_t index = GPBFieldHasIndex(field); @@ -3227,9 +3214,8 @@ static void ResolveIvarSet(__unsafe_unretained GPBFieldDescriptor *field, } else if (sel == field->setSel_) { // Local for syntax so the block can directly capture it and not the // full lookup. - const GPBFileSyntax syntax = descriptor.file.syntax; result.impToAdd = imp_implementationWithBlock(^(id obj, id value) { - GPBSetObjectIvarWithFieldInternal(obj, field, value, syntax); + GPBSetObjectIvarWithFieldPrivate(obj, field, value); }); result.encodingSelector = @selector(setArray:); break; @@ -3334,9 +3320,7 @@ id GPBGetMessageRepeatedField(GPBMessage *self, GPBFieldDescriptor *field) { [self class], field.name]; } #endif - GPBDescriptor *descriptor = [[self class] descriptor]; - GPBFileSyntax syntax = descriptor.file.syntax; - return GetOrCreateArrayIvarWithField(self, field, syntax); + return GetOrCreateArrayIvarWithField(self, field); } // Only exists for public api, no core code should use this. @@ -3348,9 +3332,7 @@ id GPBGetMessageMapField(GPBMessage *self, GPBFieldDescriptor *field) { [self class], field.name]; } #endif - GPBDescriptor *descriptor = [[self class] descriptor]; - GPBFileSyntax syntax = descriptor.file.syntax; - return GetOrCreateMapIvarWithField(self, field, syntax); + return GetOrCreateMapIvarWithField(self, field); } id GPBGetObjectIvarWithField(GPBMessage *self, GPBFieldDescriptor *field) { diff --git a/objectivec/GPBUtilities.m b/objectivec/GPBUtilities.m index 7b3bbda723..b89c03cbb3 100644 --- a/objectivec/GPBUtilities.m +++ b/objectivec/GPBUtilities.m @@ -392,15 +392,12 @@ void GPBMaybeClearOneof(GPBMessage *self, GPBOneofDescriptor *oneof, //% [self class], field.name, //% TypeToString(GPBGetFieldDataType(field))); //%#endif -//% GPBFileSyntax syntax = [self descriptor].file.syntax; -//% GPBSet##NAME##IvarWithFieldInternal(self, field, value, syntax); +//% GPBSet##NAME##IvarWithFieldPrivate(self, field, value); //%} //% -//%void GPBSet##NAME##IvarWithFieldInternal(GPBMessage *self, -//% NAME$S GPBFieldDescriptor *field, -//% NAME$S TYPE value, -//% NAME$S GPBFileSyntax syntax) { -//%#pragma unused(syntax) +//%void GPBSet##NAME##IvarWithFieldPrivate(GPBMessage *self, +//% NAME$S GPBFieldDescriptor *field, +//% NAME$S TYPE value) { //% GPBOneofDescriptor *oneof = field->containingOneof_; //% GPBMessageFieldDescription *fieldDesc = field->description_; //% if (oneof) { @@ -515,16 +512,14 @@ void GPBClearAutocreatedMessageIvarWithField(GPBMessage *self, static void GPBSetObjectIvarWithField(GPBMessage *self, GPBFieldDescriptor *field, id value) { if (self == nil || field == nil) return; - GPBFileSyntax syntax = [self descriptor].file.syntax; - GPBSetRetainedObjectIvarWithFieldInternal(self, field, [value retain], - syntax); + GPBSetRetainedObjectIvarWithFieldPrivate(self, field, [value retain]); } static void GPBSetCopyObjectIvarWithField(GPBMessage *self, GPBFieldDescriptor *field, id value); // GPBSetCopyObjectIvarWithField is blocked from the analyzer because it flags -// a leak for the -copy even though GPBSetRetainedObjectIvarWithFieldInternal +// a leak for the -copy even though GPBSetRetainedObjectIvarWithFieldPrivate // is marked as consuming the value. Note: For some reason this doesn't happen // with the -retain in GPBSetObjectIvarWithField. #if !defined(__clang_analyzer__) @@ -532,23 +527,18 @@ static void GPBSetCopyObjectIvarWithField(GPBMessage *self, static void GPBSetCopyObjectIvarWithField(GPBMessage *self, GPBFieldDescriptor *field, id value) { if (self == nil || field == nil) return; - GPBFileSyntax syntax = [self descriptor].file.syntax; - GPBSetRetainedObjectIvarWithFieldInternal(self, field, [value copy], - syntax); + GPBSetRetainedObjectIvarWithFieldPrivate(self, field, [value copy]); } #endif // !defined(__clang_analyzer__) -void GPBSetObjectIvarWithFieldInternal(GPBMessage *self, - GPBFieldDescriptor *field, id value, - GPBFileSyntax syntax) { - GPBSetRetainedObjectIvarWithFieldInternal(self, field, [value retain], - syntax); +void GPBSetObjectIvarWithFieldPrivate(GPBMessage *self, + GPBFieldDescriptor *field, id value) { + GPBSetRetainedObjectIvarWithFieldPrivate(self, field, [value retain]); } -void GPBSetRetainedObjectIvarWithFieldInternal(GPBMessage *self, - GPBFieldDescriptor *field, - id value, GPBFileSyntax syntax) { -#pragma unused(syntax) +void GPBSetRetainedObjectIvarWithFieldPrivate(GPBMessage *self, + GPBFieldDescriptor *field, + id value) { NSCAssert(self->messageStorage_ != NULL, @"%@: All messages should have storage (from init)", [self class]); @@ -687,16 +677,12 @@ int32_t GPBGetMessageEnumField(GPBMessage *self, GPBFieldDescriptor *field) { [self class], field.name, TypeToString(GPBGetFieldDataType(field))); #endif - GPBFileSyntax syntax = [self descriptor].file.syntax; - return GPBGetEnumIvarWithFieldInternal(self, field, syntax); -} -int32_t GPBGetEnumIvarWithFieldInternal(GPBMessage *self, - GPBFieldDescriptor *field, - GPBFileSyntax syntax) { int32_t result = GPBGetMessageInt32Field(self, field); // If this is presevering unknown enums, make sure the value is valid before // returning it. + + GPBFileSyntax syntax = [self descriptor].file.syntax; if (GPBHasPreservingUnknownEnumSemantics(syntax) && ![field isValidEnumValue:result]) { result = kGPBUnrecognizedEnumeratorValue; @@ -717,20 +703,18 @@ void GPBSetMessageEnumField(GPBMessage *self, GPBFieldDescriptor *field, [self class], field.name, TypeToString(GPBGetFieldDataType(field))); #endif - GPBFileSyntax syntax = [self descriptor].file.syntax; - GPBSetInt32IvarWithFieldInternal(self, field, value, syntax); + GPBSetEnumIvarWithFieldPrivate(self, field, value); } -void GPBSetEnumIvarWithFieldInternal(GPBMessage *self, - GPBFieldDescriptor *field, int32_t value, - GPBFileSyntax syntax) { +void GPBSetEnumIvarWithFieldPrivate(GPBMessage *self, + GPBFieldDescriptor *field, int32_t value) { // Don't allow in unknown values. Proto3 can use the Raw method. if (![field isValidEnumValue:value]) { [NSException raise:NSInvalidArgumentException format:@"%@.%@: Attempt to set an unknown enum value (%d)", [self class], field.name, value]; } - GPBSetInt32IvarWithFieldInternal(self, field, value, syntax); + GPBSetInt32IvarWithFieldPrivate(self, field, value); } // Only exists for public api, no core code should use this. @@ -743,8 +727,7 @@ int32_t GPBGetMessageRawEnumField(GPBMessage *self, // Only exists for public api, no core code should use this. void GPBSetMessageRawEnumField(GPBMessage *self, GPBFieldDescriptor *field, int32_t value) { - GPBFileSyntax syntax = [self descriptor].file.syntax; - GPBSetInt32IvarWithFieldInternal(self, field, value, syntax); + GPBSetInt32IvarWithFieldPrivate(self, field, value); } BOOL GPBGetMessageBoolField(GPBMessage *self, @@ -786,15 +769,12 @@ void GPBSetMessageBoolField(GPBMessage *self, [self class], field.name, TypeToString(GPBGetFieldDataType(field))); #endif - GPBFileSyntax syntax = [self descriptor].file.syntax; - GPBSetBoolIvarWithFieldInternal(self, field, value, syntax); + GPBSetBoolIvarWithFieldPrivate(self, field, value); } -void GPBSetBoolIvarWithFieldInternal(GPBMessage *self, - GPBFieldDescriptor *field, - BOOL value, - GPBFileSyntax syntax) { -#pragma unused(syntax) +void GPBSetBoolIvarWithFieldPrivate(GPBMessage *self, + GPBFieldDescriptor *field, + BOOL value) { GPBMessageFieldDescription *fieldDesc = field->description_; GPBOneofDescriptor *oneof = field->containingOneof_; if (oneof) { @@ -857,15 +837,12 @@ void GPBSetMessageInt32Field(GPBMessage *self, [self class], field.name, TypeToString(GPBGetFieldDataType(field))); #endif - GPBFileSyntax syntax = [self descriptor].file.syntax; - GPBSetInt32IvarWithFieldInternal(self, field, value, syntax); + GPBSetInt32IvarWithFieldPrivate(self, field, value); } -void GPBSetInt32IvarWithFieldInternal(GPBMessage *self, - GPBFieldDescriptor *field, - int32_t value, - GPBFileSyntax syntax) { -#pragma unused(syntax) +void GPBSetInt32IvarWithFieldPrivate(GPBMessage *self, + GPBFieldDescriptor *field, + int32_t value) { GPBOneofDescriptor *oneof = field->containingOneof_; GPBMessageFieldDescription *fieldDesc = field->description_; if (oneof) { @@ -933,15 +910,12 @@ void GPBSetMessageUInt32Field(GPBMessage *self, [self class], field.name, TypeToString(GPBGetFieldDataType(field))); #endif - GPBFileSyntax syntax = [self descriptor].file.syntax; - GPBSetUInt32IvarWithFieldInternal(self, field, value, syntax); + GPBSetUInt32IvarWithFieldPrivate(self, field, value); } -void GPBSetUInt32IvarWithFieldInternal(GPBMessage *self, - GPBFieldDescriptor *field, - uint32_t value, - GPBFileSyntax syntax) { -#pragma unused(syntax) +void GPBSetUInt32IvarWithFieldPrivate(GPBMessage *self, + GPBFieldDescriptor *field, + uint32_t value) { GPBOneofDescriptor *oneof = field->containingOneof_; GPBMessageFieldDescription *fieldDesc = field->description_; if (oneof) { @@ -1009,15 +983,12 @@ void GPBSetMessageInt64Field(GPBMessage *self, [self class], field.name, TypeToString(GPBGetFieldDataType(field))); #endif - GPBFileSyntax syntax = [self descriptor].file.syntax; - GPBSetInt64IvarWithFieldInternal(self, field, value, syntax); + GPBSetInt64IvarWithFieldPrivate(self, field, value); } -void GPBSetInt64IvarWithFieldInternal(GPBMessage *self, - GPBFieldDescriptor *field, - int64_t value, - GPBFileSyntax syntax) { -#pragma unused(syntax) +void GPBSetInt64IvarWithFieldPrivate(GPBMessage *self, + GPBFieldDescriptor *field, + int64_t value) { GPBOneofDescriptor *oneof = field->containingOneof_; GPBMessageFieldDescription *fieldDesc = field->description_; if (oneof) { @@ -1085,15 +1056,12 @@ void GPBSetMessageUInt64Field(GPBMessage *self, [self class], field.name, TypeToString(GPBGetFieldDataType(field))); #endif - GPBFileSyntax syntax = [self descriptor].file.syntax; - GPBSetUInt64IvarWithFieldInternal(self, field, value, syntax); + GPBSetUInt64IvarWithFieldPrivate(self, field, value); } -void GPBSetUInt64IvarWithFieldInternal(GPBMessage *self, - GPBFieldDescriptor *field, - uint64_t value, - GPBFileSyntax syntax) { -#pragma unused(syntax) +void GPBSetUInt64IvarWithFieldPrivate(GPBMessage *self, + GPBFieldDescriptor *field, + uint64_t value) { GPBOneofDescriptor *oneof = field->containingOneof_; GPBMessageFieldDescription *fieldDesc = field->description_; if (oneof) { @@ -1161,15 +1129,12 @@ void GPBSetMessageFloatField(GPBMessage *self, [self class], field.name, TypeToString(GPBGetFieldDataType(field))); #endif - GPBFileSyntax syntax = [self descriptor].file.syntax; - GPBSetFloatIvarWithFieldInternal(self, field, value, syntax); + GPBSetFloatIvarWithFieldPrivate(self, field, value); } -void GPBSetFloatIvarWithFieldInternal(GPBMessage *self, - GPBFieldDescriptor *field, - float value, - GPBFileSyntax syntax) { -#pragma unused(syntax) +void GPBSetFloatIvarWithFieldPrivate(GPBMessage *self, + GPBFieldDescriptor *field, + float value) { GPBOneofDescriptor *oneof = field->containingOneof_; GPBMessageFieldDescription *fieldDesc = field->description_; if (oneof) { @@ -1237,15 +1202,12 @@ void GPBSetMessageDoubleField(GPBMessage *self, [self class], field.name, TypeToString(GPBGetFieldDataType(field))); #endif - GPBFileSyntax syntax = [self descriptor].file.syntax; - GPBSetDoubleIvarWithFieldInternal(self, field, value, syntax); + GPBSetDoubleIvarWithFieldPrivate(self, field, value); } -void GPBSetDoubleIvarWithFieldInternal(GPBMessage *self, - GPBFieldDescriptor *field, - double value, - GPBFileSyntax syntax) { -#pragma unused(syntax) +void GPBSetDoubleIvarWithFieldPrivate(GPBMessage *self, + GPBFieldDescriptor *field, + double value) { GPBOneofDescriptor *oneof = field->containingOneof_; GPBMessageFieldDescription *fieldDesc = field->description_; if (oneof) { @@ -2261,6 +2223,19 @@ NSString *GPBDecodeTextFormatName(const uint8_t *decodeData, int32_t key, #pragma clang diagnostic pop +#pragma mark Legacy methods old generated code calls + +// Shim from the older generated code into the runtime. +void GPBSetInt32IvarWithFieldInternal(GPBMessage *self, + GPBFieldDescriptor *field, + int32_t value, + GPBFileSyntax syntax) { +#pragma unused(syntax) + GPBSetMessageInt32Field(self, field, value); +} + +#pragma mark Misc Helpers + BOOL GPBClassHasSel(Class aClass, SEL sel) { // NOTE: We have to use class_copyMethodList, all other runtime method // lookups actually also resolve the method implementation and this diff --git a/objectivec/GPBUtilities_PackagePrivate.h b/objectivec/GPBUtilities_PackagePrivate.h index 1638a8c219..280b6deb00 100644 --- a/objectivec/GPBUtilities_PackagePrivate.h +++ b/objectivec/GPBUtilities_PackagePrivate.h @@ -213,98 +213,79 @@ void GPBMaybeClearOneof(GPBMessage *self, GPBOneofDescriptor *oneof, #pragma clang diagnostic pop //%PDDM-DEFINE GPB_IVAR_SET_DECL(NAME, TYPE) -//%void GPBSet##NAME##IvarWithFieldInternal(GPBMessage *self, -//% NAME$S GPBFieldDescriptor *field, -//% NAME$S TYPE value, -//% NAME$S GPBFileSyntax syntax); +//%void GPBSet##NAME##IvarWithFieldPrivate(GPBMessage *self, +//% NAME$S GPBFieldDescriptor *field, +//% NAME$S TYPE value); //%PDDM-EXPAND GPB_IVAR_SET_DECL(Bool, BOOL) // This block of code is generated, do not edit it directly. // clang-format off -void GPBSetBoolIvarWithFieldInternal(GPBMessage *self, - GPBFieldDescriptor *field, - BOOL value, - GPBFileSyntax syntax); +void GPBSetBoolIvarWithFieldPrivate(GPBMessage *self, + GPBFieldDescriptor *field, + BOOL value); // clang-format on //%PDDM-EXPAND GPB_IVAR_SET_DECL(Int32, int32_t) // This block of code is generated, do not edit it directly. // clang-format off -void GPBSetInt32IvarWithFieldInternal(GPBMessage *self, - GPBFieldDescriptor *field, - int32_t value, - GPBFileSyntax syntax); +void GPBSetInt32IvarWithFieldPrivate(GPBMessage *self, + GPBFieldDescriptor *field, + int32_t value); // clang-format on //%PDDM-EXPAND GPB_IVAR_SET_DECL(UInt32, uint32_t) // This block of code is generated, do not edit it directly. // clang-format off -void GPBSetUInt32IvarWithFieldInternal(GPBMessage *self, - GPBFieldDescriptor *field, - uint32_t value, - GPBFileSyntax syntax); +void GPBSetUInt32IvarWithFieldPrivate(GPBMessage *self, + GPBFieldDescriptor *field, + uint32_t value); // clang-format on //%PDDM-EXPAND GPB_IVAR_SET_DECL(Int64, int64_t) // This block of code is generated, do not edit it directly. // clang-format off -void GPBSetInt64IvarWithFieldInternal(GPBMessage *self, - GPBFieldDescriptor *field, - int64_t value, - GPBFileSyntax syntax); +void GPBSetInt64IvarWithFieldPrivate(GPBMessage *self, + GPBFieldDescriptor *field, + int64_t value); // clang-format on //%PDDM-EXPAND GPB_IVAR_SET_DECL(UInt64, uint64_t) // This block of code is generated, do not edit it directly. // clang-format off -void GPBSetUInt64IvarWithFieldInternal(GPBMessage *self, - GPBFieldDescriptor *field, - uint64_t value, - GPBFileSyntax syntax); +void GPBSetUInt64IvarWithFieldPrivate(GPBMessage *self, + GPBFieldDescriptor *field, + uint64_t value); // clang-format on //%PDDM-EXPAND GPB_IVAR_SET_DECL(Float, float) // This block of code is generated, do not edit it directly. // clang-format off -void GPBSetFloatIvarWithFieldInternal(GPBMessage *self, - GPBFieldDescriptor *field, - float value, - GPBFileSyntax syntax); +void GPBSetFloatIvarWithFieldPrivate(GPBMessage *self, + GPBFieldDescriptor *field, + float value); // clang-format on //%PDDM-EXPAND GPB_IVAR_SET_DECL(Double, double) // This block of code is generated, do not edit it directly. // clang-format off -void GPBSetDoubleIvarWithFieldInternal(GPBMessage *self, - GPBFieldDescriptor *field, - double value, - GPBFileSyntax syntax); -// clang-format on -//%PDDM-EXPAND GPB_IVAR_SET_DECL(Enum, int32_t) -// This block of code is generated, do not edit it directly. -// clang-format off - -void GPBSetEnumIvarWithFieldInternal(GPBMessage *self, - GPBFieldDescriptor *field, - int32_t value, - GPBFileSyntax syntax); +void GPBSetDoubleIvarWithFieldPrivate(GPBMessage *self, + GPBFieldDescriptor *field, + double value); // clang-format on -//%PDDM-EXPAND-END (8 expansions) +//%PDDM-EXPAND-END (7 expansions) -int32_t GPBGetEnumIvarWithFieldInternal(GPBMessage *self, - GPBFieldDescriptor *field, - GPBFileSyntax syntax); +void GPBSetEnumIvarWithFieldPrivate(GPBMessage *self, + GPBFieldDescriptor *field, + int32_t value); id GPBGetObjectIvarWithField(GPBMessage *self, GPBFieldDescriptor *field); -void GPBSetObjectIvarWithFieldInternal(GPBMessage *self, - GPBFieldDescriptor *field, id value, - GPBFileSyntax syntax); -void GPBSetRetainedObjectIvarWithFieldInternal(GPBMessage *self, - GPBFieldDescriptor *field, - id __attribute__((ns_consumed)) - value, - GPBFileSyntax syntax); +void GPBSetObjectIvarWithFieldPrivate(GPBMessage *self, + GPBFieldDescriptor *field, id value); +void GPBSetRetainedObjectIvarWithFieldPrivate(GPBMessage *self, + GPBFieldDescriptor *field, + id __attribute__((ns_consumed)) + value); // GPBGetObjectIvarWithField will automatically create the field (message) if // it doesn't exist. GPBGetObjectIvarWithFieldNoAutocreate will return nil. @@ -331,6 +312,13 @@ const char *GPBMessageEncodingForSelector(SEL selector, BOOL instanceSel); NSString *GPBDecodeTextFormatName(const uint8_t *decodeData, int32_t key, NSString *inputString); + +// Shim from the older generated code into the runtime. +void GPBSetInt32IvarWithFieldInternal(GPBMessage *self, + GPBFieldDescriptor *field, + int32_t value, + GPBFileSyntax syntax); + // A series of selectors that are used solely to get @encoding values // for them by the dynamic protobuf runtime code. See // GPBMessageEncodingForSelector for details. GPBRootObject conforms to From 3c8e959b6069e379210ee10751892c864cae2372 Mon Sep 17 00:00:00 2001 From: Thomas Van Lenten Date: Mon, 13 Apr 2020 10:49:16 -0400 Subject: [PATCH 34/38] [ObjC] Update oneof clearing internals. - Add/document an public api for clearing oneofs. - Move the current library internals to a new api and keep a shim for old generated code. --- objectivec/GPBUtilities.h | 10 ++++ objectivec/GPBUtilities.m | 59 ++++++++++++++++++------ objectivec/GPBUtilities_PackagePrivate.h | 7 ++- 3 files changed, 59 insertions(+), 17 deletions(-) diff --git a/objectivec/GPBUtilities.h b/objectivec/GPBUtilities.h index ef4f8552b9..828fd16297 100644 --- a/objectivec/GPBUtilities.h +++ b/objectivec/GPBUtilities.h @@ -34,6 +34,8 @@ #import "GPBMessage.h" #import "GPBRuntimeTypes.h" +@class GPBOneofDescriptor; + CF_EXTERN_C_BEGIN NS_ASSUME_NONNULL_BEGIN @@ -92,6 +94,14 @@ BOOL GPBMessageHasFieldSet(GPBMessage *self, GPBFieldDescriptor *field); **/ void GPBClearMessageField(GPBMessage *self, GPBFieldDescriptor *field); +/** + * Clears the given onoof field for the given message. + * + * @param self The message for which to clear the field. + * @param oneof The oneof to clear. + **/ +void GPBClearOneof(GPBMessage *self, GPBOneofDescriptor *oneof); + //%PDDM-EXPAND GPB_ACCESSORS() // This block of code is generated, do not edit it directly. // clang-format off diff --git a/objectivec/GPBUtilities.m b/objectivec/GPBUtilities.m index b89c03cbb3..ee79d00192 100644 --- a/objectivec/GPBUtilities.m +++ b/objectivec/GPBUtilities.m @@ -62,6 +62,12 @@ static GPBDataType BaseDataType(GPBDataType type) __attribute__ ((unused)); // Marked unused because currently only called from asserts/debug. static NSString *TypeToString(GPBDataType dataType) __attribute__ ((unused)); +// Helper for clearing oneofs. +static void GPBMaybeClearOneofPrivate(GPBMessage *self, + GPBOneofDescriptor *oneof, + int32_t oneofHasIndex, + uint32_t fieldNumberNotToClear); + NSData *GPBEmptyNSData(void) { static dispatch_once_t onceToken; static NSData *defaultNSData = nil; @@ -281,6 +287,16 @@ void GPBClearMessageField(GPBMessage *self, GPBFieldDescriptor *field) { GPBSetHasIvar(self, fieldDesc->hasIndex, fieldDesc->number, NO); } +void GPBClearOneof(GPBMessage *self, GPBOneofDescriptor *oneof) { + #if defined(DEBUG) && DEBUG + NSCAssert([[self descriptor] oneofWithName:oneof.name] == oneof, + @"OneofDescriptor %@ doesn't appear to be for %@ messages.", + oneof.name, [self class]); + #endif + GPBFieldDescriptor *firstField = oneof->fields_[0]; + GPBMaybeClearOneofPrivate(self, oneof, firstField->description_->hasIndex, 0); +} + BOOL GPBGetHasIvar(GPBMessage *self, int32_t idx, uint32_t fieldNumber) { NSCAssert(self->messageStorage_ != NULL, @"%@: All messages should have storage (from init)", @@ -325,8 +341,10 @@ void GPBSetHasIvar(GPBMessage *self, int32_t idx, uint32_t fieldNumber, } } -void GPBMaybeClearOneof(GPBMessage *self, GPBOneofDescriptor *oneof, - int32_t oneofHasIndex, uint32_t fieldNumberNotToClear) { +static void GPBMaybeClearOneofPrivate(GPBMessage *self, + GPBOneofDescriptor *oneof, + int32_t oneofHasIndex, + uint32_t fieldNumberNotToClear) { uint32_t fieldNumberSet = GPBGetHasOneof(self, oneofHasIndex); if ((fieldNumberSet == fieldNumberNotToClear) || (fieldNumberSet == 0)) { // Do nothing/nothing set in the oneof. @@ -401,7 +419,7 @@ void GPBMaybeClearOneof(GPBMessage *self, GPBOneofDescriptor *oneof, //% GPBOneofDescriptor *oneof = field->containingOneof_; //% GPBMessageFieldDescription *fieldDesc = field->description_; //% if (oneof) { -//% GPBMaybeClearOneof(self, oneof, fieldDesc->hasIndex, fieldDesc->number); +//% GPBMaybeClearOneofPrivate(self, oneof, fieldDesc->hasIndex, fieldDesc->number); //% } //%#if defined(DEBUG) && DEBUG //% NSCAssert(self->messageStorage_ != NULL, @@ -583,7 +601,7 @@ void GPBSetRetainedObjectIvarWithFieldPrivate(GPBMessage *self, // oneof. GPBOneofDescriptor *oneof = field->containingOneof_; if (oneof) { - GPBMaybeClearOneof(self, oneof, fieldDesc->hasIndex, fieldDesc->number); + GPBMaybeClearOneofPrivate(self, oneof, fieldDesc->hasIndex, fieldDesc->number); } // Clear "has" if they are being set to nil. BOOL setHasValue = (value != nil); @@ -778,7 +796,7 @@ void GPBSetBoolIvarWithFieldPrivate(GPBMessage *self, GPBMessageFieldDescription *fieldDesc = field->description_; GPBOneofDescriptor *oneof = field->containingOneof_; if (oneof) { - GPBMaybeClearOneof(self, oneof, fieldDesc->hasIndex, fieldDesc->number); + GPBMaybeClearOneofPrivate(self, oneof, fieldDesc->hasIndex, fieldDesc->number); } // Bools are stored in the has bits to avoid needing explicit space in the @@ -846,7 +864,7 @@ void GPBSetInt32IvarWithFieldPrivate(GPBMessage *self, GPBOneofDescriptor *oneof = field->containingOneof_; GPBMessageFieldDescription *fieldDesc = field->description_; if (oneof) { - GPBMaybeClearOneof(self, oneof, fieldDesc->hasIndex, fieldDesc->number); + GPBMaybeClearOneofPrivate(self, oneof, fieldDesc->hasIndex, fieldDesc->number); } #if defined(DEBUG) && DEBUG NSCAssert(self->messageStorage_ != NULL, @@ -919,7 +937,7 @@ void GPBSetUInt32IvarWithFieldPrivate(GPBMessage *self, GPBOneofDescriptor *oneof = field->containingOneof_; GPBMessageFieldDescription *fieldDesc = field->description_; if (oneof) { - GPBMaybeClearOneof(self, oneof, fieldDesc->hasIndex, fieldDesc->number); + GPBMaybeClearOneofPrivate(self, oneof, fieldDesc->hasIndex, fieldDesc->number); } #if defined(DEBUG) && DEBUG NSCAssert(self->messageStorage_ != NULL, @@ -992,7 +1010,7 @@ void GPBSetInt64IvarWithFieldPrivate(GPBMessage *self, GPBOneofDescriptor *oneof = field->containingOneof_; GPBMessageFieldDescription *fieldDesc = field->description_; if (oneof) { - GPBMaybeClearOneof(self, oneof, fieldDesc->hasIndex, fieldDesc->number); + GPBMaybeClearOneofPrivate(self, oneof, fieldDesc->hasIndex, fieldDesc->number); } #if defined(DEBUG) && DEBUG NSCAssert(self->messageStorage_ != NULL, @@ -1065,7 +1083,7 @@ void GPBSetUInt64IvarWithFieldPrivate(GPBMessage *self, GPBOneofDescriptor *oneof = field->containingOneof_; GPBMessageFieldDescription *fieldDesc = field->description_; if (oneof) { - GPBMaybeClearOneof(self, oneof, fieldDesc->hasIndex, fieldDesc->number); + GPBMaybeClearOneofPrivate(self, oneof, fieldDesc->hasIndex, fieldDesc->number); } #if defined(DEBUG) && DEBUG NSCAssert(self->messageStorage_ != NULL, @@ -1138,7 +1156,7 @@ void GPBSetFloatIvarWithFieldPrivate(GPBMessage *self, GPBOneofDescriptor *oneof = field->containingOneof_; GPBMessageFieldDescription *fieldDesc = field->description_; if (oneof) { - GPBMaybeClearOneof(self, oneof, fieldDesc->hasIndex, fieldDesc->number); + GPBMaybeClearOneofPrivate(self, oneof, fieldDesc->hasIndex, fieldDesc->number); } #if defined(DEBUG) && DEBUG NSCAssert(self->messageStorage_ != NULL, @@ -1211,7 +1229,7 @@ void GPBSetDoubleIvarWithFieldPrivate(GPBMessage *self, GPBOneofDescriptor *oneof = field->containingOneof_; GPBMessageFieldDescription *fieldDesc = field->description_; if (oneof) { - GPBMaybeClearOneof(self, oneof, fieldDesc->hasIndex, fieldDesc->number); + GPBMaybeClearOneofPrivate(self, oneof, fieldDesc->hasIndex, fieldDesc->number); } #if defined(DEBUG) && DEBUG NSCAssert(self->messageStorage_ != NULL, @@ -2221,8 +2239,6 @@ NSString *GPBDecodeTextFormatName(const uint8_t *decodeData, int32_t key, return result; } -#pragma clang diagnostic pop - #pragma mark Legacy methods old generated code calls // Shim from the older generated code into the runtime. @@ -2234,6 +2250,23 @@ void GPBSetInt32IvarWithFieldInternal(GPBMessage *self, GPBSetMessageInt32Field(self, field, value); } +void GPBMaybeClearOneof(GPBMessage *self, GPBOneofDescriptor *oneof, + int32_t oneofHasIndex, uint32_t fieldNumberNotToClear) { +#pragma unused(fieldNumberNotToClear) + #if defined(DEBUG) && DEBUG + NSCAssert([[self descriptor] oneofWithName:oneof.name] == oneof, + @"OneofDescriptor %@ doesn't appear to be for %@ messages.", + oneof.name, [self class]); + GPBFieldDescriptor *firstField = oneof->fields_[0]; + NSCAssert(firstField->description_->hasIndex == oneofHasIndex, + @"Internal error, oneofHasIndex (%d) doesn't match (%d).", + firstField->description_->hasIndex, oneofHasIndex); + #endif + GPBMaybeClearOneofPrivate(self, oneof, oneofHasIndex, 0); +} + +#pragma clang diagnostic pop + #pragma mark Misc Helpers BOOL GPBClassHasSel(Class aClass, SEL sel) { diff --git a/objectivec/GPBUtilities_PackagePrivate.h b/objectivec/GPBUtilities_PackagePrivate.h index 280b6deb00..9c29c39c0b 100644 --- a/objectivec/GPBUtilities_PackagePrivate.h +++ b/objectivec/GPBUtilities_PackagePrivate.h @@ -207,9 +207,6 @@ GPBGetHasIvarField(GPBMessage *self, GPBFieldDescriptor *field) { return GPBGetHasIvar(self, fieldDesc->hasIndex, fieldDesc->number); } -void GPBMaybeClearOneof(GPBMessage *self, GPBOneofDescriptor *oneof, - int32_t oneofHasIndex, uint32_t fieldNumberNotToClear); - #pragma clang diagnostic pop //%PDDM-DEFINE GPB_IVAR_SET_DECL(NAME, TYPE) @@ -313,11 +310,13 @@ NSString *GPBDecodeTextFormatName(const uint8_t *decodeData, int32_t key, NSString *inputString); -// Shim from the older generated code into the runtime. +// Shims from the older generated code into the runtime. void GPBSetInt32IvarWithFieldInternal(GPBMessage *self, GPBFieldDescriptor *field, int32_t value, GPBFileSyntax syntax); +void GPBMaybeClearOneof(GPBMessage *self, GPBOneofDescriptor *oneof, + int32_t oneofHasIndex, uint32_t fieldNumberNotToClear); // A series of selectors that are used solely to get @encoding values // for them by the dynamic protobuf runtime code. See From b0e2792842d5acb07bc11e2d5afbdc9d80a9fbdb Mon Sep 17 00:00:00 2001 From: Thomas Van Lenten Date: Mon, 13 Apr 2020 13:36:56 -0400 Subject: [PATCH 35/38] [ObjC] Generation changes around proto3 optional. - Bump the version marker in the generated code. - Set the flag to say clear on zero is known. - Set clear on zero for proto3 optional fields that aren't tagged as optional. - Also tweak the call from some C generated code to use different apis with better validation. - Mark the ObjC generator as supporting the proto3 optional feature. - Regenerate the WKTs to get the new flags. --- objectivec/GPBAny.pbobjc.h | 4 +- objectivec/GPBAny.pbobjc.m | 6 +- objectivec/GPBApi.pbobjc.h | 4 +- objectivec/GPBApi.pbobjc.m | 36 ++++++------ objectivec/GPBBootstrap.h | 2 +- objectivec/GPBDuration.pbobjc.h | 4 +- objectivec/GPBDuration.pbobjc.m | 6 +- objectivec/GPBEmpty.pbobjc.h | 4 +- objectivec/GPBEmpty.pbobjc.m | 2 +- objectivec/GPBFieldMask.pbobjc.h | 4 +- objectivec/GPBFieldMask.pbobjc.m | 2 +- objectivec/GPBSourceContext.pbobjc.h | 4 +- objectivec/GPBSourceContext.pbobjc.m | 4 +- objectivec/GPBStruct.pbobjc.h | 4 +- objectivec/GPBStruct.pbobjc.m | 12 ++-- objectivec/GPBTimestamp.pbobjc.h | 4 +- objectivec/GPBTimestamp.pbobjc.m | 6 +- objectivec/GPBType.pbobjc.h | 4 +- objectivec/GPBType.pbobjc.m | 58 +++++++++---------- objectivec/GPBWrappers.pbobjc.h | 4 +- objectivec/GPBWrappers.pbobjc.m | 36 ++++++------ .../objectivec/objectivec_enum_field.cc | 4 +- .../compiler/objectivec/objectivec_field.cc | 8 +++ .../compiler/objectivec/objectivec_file.cc | 2 +- .../objectivec/objectivec_generator.h | 10 +++- .../compiler/objectivec/objectivec_message.cc | 1 + .../compiler/objectivec/objectivec_oneof.cc | 2 +- 27 files changed, 125 insertions(+), 112 deletions(-) diff --git a/objectivec/GPBAny.pbobjc.h b/objectivec/GPBAny.pbobjc.h index 233cc270ea..288d552356 100644 --- a/objectivec/GPBAny.pbobjc.h +++ b/objectivec/GPBAny.pbobjc.h @@ -17,10 +17,10 @@ #import "GPBRootObject.h" #endif -#if GOOGLE_PROTOBUF_OBJC_VERSION < 30003 +#if GOOGLE_PROTOBUF_OBJC_VERSION < 30004 #error This file was generated by a newer version of protoc which is incompatible with your Protocol Buffer library sources. #endif -#if 30003 < GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION +#if 30004 < GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION #error This file was generated by an older version of protoc which is incompatible with your Protocol Buffer library sources. #endif diff --git a/objectivec/GPBAny.pbobjc.m b/objectivec/GPBAny.pbobjc.m index 06b892e233..a5143f15dc 100644 --- a/objectivec/GPBAny.pbobjc.m +++ b/objectivec/GPBAny.pbobjc.m @@ -72,7 +72,7 @@ typedef struct GPBAny__storage_ { .number = GPBAny_FieldNumber_TypeURL, .hasIndex = 0, .offset = (uint32_t)offsetof(GPBAny__storage_, typeURL), - .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldTextFormatNameCustom), + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldTextFormatNameCustom | GPBFieldClearHasIvarOnZero), .dataType = GPBDataTypeString, }, { @@ -81,7 +81,7 @@ typedef struct GPBAny__storage_ { .number = GPBAny_FieldNumber_Value, .hasIndex = 1, .offset = (uint32_t)offsetof(GPBAny__storage_, value), - .flags = GPBFieldOptional, + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero), .dataType = GPBDataTypeBytes, }, }; @@ -92,7 +92,7 @@ typedef struct GPBAny__storage_ { fields:fields fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) storageSize:sizeof(GPBAny__storage_) - flags:GPBDescriptorInitializationFlag_UsesClassRefs]; + flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)]; #if !GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS static const char *extraTextFormatInfo = "\001\001\004\241!!\000"; diff --git a/objectivec/GPBApi.pbobjc.h b/objectivec/GPBApi.pbobjc.h index c47a01c572..287c0516d0 100644 --- a/objectivec/GPBApi.pbobjc.h +++ b/objectivec/GPBApi.pbobjc.h @@ -17,10 +17,10 @@ #import "GPBRootObject.h" #endif -#if GOOGLE_PROTOBUF_OBJC_VERSION < 30003 +#if GOOGLE_PROTOBUF_OBJC_VERSION < 30004 #error This file was generated by a newer version of protoc which is incompatible with your Protocol Buffer library sources. #endif -#if 30003 < GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION +#if 30004 < GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION #error This file was generated by an older version of protoc which is incompatible with your Protocol Buffer library sources. #endif diff --git a/objectivec/GPBApi.pbobjc.m b/objectivec/GPBApi.pbobjc.m index bdd35bb765..5915ce1122 100644 --- a/objectivec/GPBApi.pbobjc.m +++ b/objectivec/GPBApi.pbobjc.m @@ -96,7 +96,7 @@ typedef struct GPBApi__storage_ { .number = GPBApi_FieldNumber_Name, .hasIndex = 0, .offset = (uint32_t)offsetof(GPBApi__storage_, name), - .flags = GPBFieldOptional, + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero), .dataType = GPBDataTypeString, }, { @@ -123,7 +123,7 @@ typedef struct GPBApi__storage_ { .number = GPBApi_FieldNumber_Version, .hasIndex = 1, .offset = (uint32_t)offsetof(GPBApi__storage_, version), - .flags = GPBFieldOptional, + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero), .dataType = GPBDataTypeString, }, { @@ -150,7 +150,7 @@ typedef struct GPBApi__storage_ { .number = GPBApi_FieldNumber_Syntax, .hasIndex = 3, .offset = (uint32_t)offsetof(GPBApi__storage_, syntax), - .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldHasEnumDescriptor), + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldHasEnumDescriptor | GPBFieldClearHasIvarOnZero), .dataType = GPBDataTypeEnum, }, }; @@ -161,7 +161,7 @@ typedef struct GPBApi__storage_ { fields:fields fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) storageSize:sizeof(GPBApi__storage_) - flags:GPBDescriptorInitializationFlag_UsesClassRefs]; + flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)]; #if defined(DEBUG) && DEBUG NSAssert(descriptor == nil, @"Startup recursed!"); #endif // DEBUG @@ -175,13 +175,13 @@ typedef struct GPBApi__storage_ { int32_t GPBApi_Syntax_RawValue(GPBApi *message) { GPBDescriptor *descriptor = [GPBApi descriptor]; GPBFieldDescriptor *field = [descriptor fieldWithNumber:GPBApi_FieldNumber_Syntax]; - return GPBGetMessageInt32Field(message, field); + return GPBGetMessageRawEnumField(message, field); } void SetGPBApi_Syntax_RawValue(GPBApi *message, int32_t value) { GPBDescriptor *descriptor = [GPBApi descriptor]; GPBFieldDescriptor *field = [descriptor fieldWithNumber:GPBApi_FieldNumber_Syntax]; - GPBSetInt32IvarWithFieldInternal(message, field, value, descriptor.file.syntax); + GPBSetMessageRawEnumField(message, field, value); } #pragma mark - GPBMethod @@ -217,7 +217,7 @@ typedef struct GPBMethod__storage_ { .number = GPBMethod_FieldNumber_Name, .hasIndex = 0, .offset = (uint32_t)offsetof(GPBMethod__storage_, name), - .flags = GPBFieldOptional, + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero), .dataType = GPBDataTypeString, }, { @@ -226,7 +226,7 @@ typedef struct GPBMethod__storage_ { .number = GPBMethod_FieldNumber_RequestTypeURL, .hasIndex = 1, .offset = (uint32_t)offsetof(GPBMethod__storage_, requestTypeURL), - .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldTextFormatNameCustom), + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldTextFormatNameCustom | GPBFieldClearHasIvarOnZero), .dataType = GPBDataTypeString, }, { @@ -235,7 +235,7 @@ typedef struct GPBMethod__storage_ { .number = GPBMethod_FieldNumber_RequestStreaming, .hasIndex = 2, .offset = 3, // Stored in _has_storage_ to save space. - .flags = GPBFieldOptional, + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero), .dataType = GPBDataTypeBool, }, { @@ -244,7 +244,7 @@ typedef struct GPBMethod__storage_ { .number = GPBMethod_FieldNumber_ResponseTypeURL, .hasIndex = 4, .offset = (uint32_t)offsetof(GPBMethod__storage_, responseTypeURL), - .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldTextFormatNameCustom), + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldTextFormatNameCustom | GPBFieldClearHasIvarOnZero), .dataType = GPBDataTypeString, }, { @@ -253,7 +253,7 @@ typedef struct GPBMethod__storage_ { .number = GPBMethod_FieldNumber_ResponseStreaming, .hasIndex = 5, .offset = 6, // Stored in _has_storage_ to save space. - .flags = GPBFieldOptional, + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero), .dataType = GPBDataTypeBool, }, { @@ -271,7 +271,7 @@ typedef struct GPBMethod__storage_ { .number = GPBMethod_FieldNumber_Syntax, .hasIndex = 7, .offset = (uint32_t)offsetof(GPBMethod__storage_, syntax), - .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldHasEnumDescriptor), + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldHasEnumDescriptor | GPBFieldClearHasIvarOnZero), .dataType = GPBDataTypeEnum, }, }; @@ -282,7 +282,7 @@ typedef struct GPBMethod__storage_ { fields:fields fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) storageSize:sizeof(GPBMethod__storage_) - flags:GPBDescriptorInitializationFlag_UsesClassRefs]; + flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)]; #if !GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS static const char *extraTextFormatInfo = "\002\002\007\244\241!!\000\004\010\244\241!!\000"; @@ -301,13 +301,13 @@ typedef struct GPBMethod__storage_ { int32_t GPBMethod_Syntax_RawValue(GPBMethod *message) { GPBDescriptor *descriptor = [GPBMethod descriptor]; GPBFieldDescriptor *field = [descriptor fieldWithNumber:GPBMethod_FieldNumber_Syntax]; - return GPBGetMessageInt32Field(message, field); + return GPBGetMessageRawEnumField(message, field); } void SetGPBMethod_Syntax_RawValue(GPBMethod *message, int32_t value) { GPBDescriptor *descriptor = [GPBMethod descriptor]; GPBFieldDescriptor *field = [descriptor fieldWithNumber:GPBMethod_FieldNumber_Syntax]; - GPBSetInt32IvarWithFieldInternal(message, field, value, descriptor.file.syntax); + GPBSetMessageRawEnumField(message, field, value); } #pragma mark - GPBMixin @@ -335,7 +335,7 @@ typedef struct GPBMixin__storage_ { .number = GPBMixin_FieldNumber_Name, .hasIndex = 0, .offset = (uint32_t)offsetof(GPBMixin__storage_, name), - .flags = GPBFieldOptional, + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero), .dataType = GPBDataTypeString, }, { @@ -344,7 +344,7 @@ typedef struct GPBMixin__storage_ { .number = GPBMixin_FieldNumber_Root, .hasIndex = 1, .offset = (uint32_t)offsetof(GPBMixin__storage_, root), - .flags = GPBFieldOptional, + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero), .dataType = GPBDataTypeString, }, }; @@ -355,7 +355,7 @@ typedef struct GPBMixin__storage_ { fields:fields fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) storageSize:sizeof(GPBMixin__storage_) - flags:GPBDescriptorInitializationFlag_UsesClassRefs]; + flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)]; #if defined(DEBUG) && DEBUG NSAssert(descriptor == nil, @"Startup recursed!"); #endif // DEBUG diff --git a/objectivec/GPBBootstrap.h b/objectivec/GPBBootstrap.h index 198ff9c71d..ea5986b8bf 100644 --- a/objectivec/GPBBootstrap.h +++ b/objectivec/GPBBootstrap.h @@ -132,7 +132,7 @@ // Current library runtime version. // - Gets bumped when the runtime makes changes to the interfaces between the // generated code and runtime (things added/removed, etc). -#define GOOGLE_PROTOBUF_OBJC_VERSION 30003 +#define GOOGLE_PROTOBUF_OBJC_VERSION 30004 // Minimum runtime version supported for compiling/running against. // - Gets changed when support for the older generated code is dropped. diff --git a/objectivec/GPBDuration.pbobjc.h b/objectivec/GPBDuration.pbobjc.h index 6ff27092cd..88527f520d 100644 --- a/objectivec/GPBDuration.pbobjc.h +++ b/objectivec/GPBDuration.pbobjc.h @@ -17,10 +17,10 @@ #import "GPBRootObject.h" #endif -#if GOOGLE_PROTOBUF_OBJC_VERSION < 30003 +#if GOOGLE_PROTOBUF_OBJC_VERSION < 30004 #error This file was generated by a newer version of protoc which is incompatible with your Protocol Buffer library sources. #endif -#if 30003 < GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION +#if 30004 < GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION #error This file was generated by an older version of protoc which is incompatible with your Protocol Buffer library sources. #endif diff --git a/objectivec/GPBDuration.pbobjc.m b/objectivec/GPBDuration.pbobjc.m index 465831e604..d3cc7e31ca 100644 --- a/objectivec/GPBDuration.pbobjc.m +++ b/objectivec/GPBDuration.pbobjc.m @@ -72,7 +72,7 @@ typedef struct GPBDuration__storage_ { .number = GPBDuration_FieldNumber_Seconds, .hasIndex = 0, .offset = (uint32_t)offsetof(GPBDuration__storage_, seconds), - .flags = GPBFieldOptional, + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero), .dataType = GPBDataTypeInt64, }, { @@ -81,7 +81,7 @@ typedef struct GPBDuration__storage_ { .number = GPBDuration_FieldNumber_Nanos, .hasIndex = 1, .offset = (uint32_t)offsetof(GPBDuration__storage_, nanos), - .flags = GPBFieldOptional, + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero), .dataType = GPBDataTypeInt32, }, }; @@ -92,7 +92,7 @@ typedef struct GPBDuration__storage_ { fields:fields fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) storageSize:sizeof(GPBDuration__storage_) - flags:GPBDescriptorInitializationFlag_UsesClassRefs]; + flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)]; #if defined(DEBUG) && DEBUG NSAssert(descriptor == nil, @"Startup recursed!"); #endif // DEBUG diff --git a/objectivec/GPBEmpty.pbobjc.h b/objectivec/GPBEmpty.pbobjc.h index 9673400376..45600ead86 100644 --- a/objectivec/GPBEmpty.pbobjc.h +++ b/objectivec/GPBEmpty.pbobjc.h @@ -17,10 +17,10 @@ #import "GPBRootObject.h" #endif -#if GOOGLE_PROTOBUF_OBJC_VERSION < 30003 +#if GOOGLE_PROTOBUF_OBJC_VERSION < 30004 #error This file was generated by a newer version of protoc which is incompatible with your Protocol Buffer library sources. #endif -#if 30003 < GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION +#if 30004 < GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION #error This file was generated by an older version of protoc which is incompatible with your Protocol Buffer library sources. #endif diff --git a/objectivec/GPBEmpty.pbobjc.m b/objectivec/GPBEmpty.pbobjc.m index 29aa389b3e..df3e398170 100644 --- a/objectivec/GPBEmpty.pbobjc.m +++ b/objectivec/GPBEmpty.pbobjc.m @@ -68,7 +68,7 @@ typedef struct GPBEmpty__storage_ { fields:NULL fieldCount:0 storageSize:sizeof(GPBEmpty__storage_) - flags:GPBDescriptorInitializationFlag_UsesClassRefs]; + flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)]; #if defined(DEBUG) && DEBUG NSAssert(descriptor == nil, @"Startup recursed!"); #endif // DEBUG diff --git a/objectivec/GPBFieldMask.pbobjc.h b/objectivec/GPBFieldMask.pbobjc.h index fa52ed0d3b..3028b775dc 100644 --- a/objectivec/GPBFieldMask.pbobjc.h +++ b/objectivec/GPBFieldMask.pbobjc.h @@ -17,10 +17,10 @@ #import "GPBRootObject.h" #endif -#if GOOGLE_PROTOBUF_OBJC_VERSION < 30003 +#if GOOGLE_PROTOBUF_OBJC_VERSION < 30004 #error This file was generated by a newer version of protoc which is incompatible with your Protocol Buffer library sources. #endif -#if 30003 < GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION +#if 30004 < GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION #error This file was generated by an older version of protoc which is incompatible with your Protocol Buffer library sources. #endif diff --git a/objectivec/GPBFieldMask.pbobjc.m b/objectivec/GPBFieldMask.pbobjc.m index 9f119fc164..3605f89d80 100644 --- a/objectivec/GPBFieldMask.pbobjc.m +++ b/objectivec/GPBFieldMask.pbobjc.m @@ -81,7 +81,7 @@ typedef struct GPBFieldMask__storage_ { fields:fields fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) storageSize:sizeof(GPBFieldMask__storage_) - flags:GPBDescriptorInitializationFlag_UsesClassRefs]; + flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)]; #if defined(DEBUG) && DEBUG NSAssert(descriptor == nil, @"Startup recursed!"); #endif // DEBUG diff --git a/objectivec/GPBSourceContext.pbobjc.h b/objectivec/GPBSourceContext.pbobjc.h index 90263b1070..7a103362b5 100644 --- a/objectivec/GPBSourceContext.pbobjc.h +++ b/objectivec/GPBSourceContext.pbobjc.h @@ -17,10 +17,10 @@ #import "GPBRootObject.h" #endif -#if GOOGLE_PROTOBUF_OBJC_VERSION < 30003 +#if GOOGLE_PROTOBUF_OBJC_VERSION < 30004 #error This file was generated by a newer version of protoc which is incompatible with your Protocol Buffer library sources. #endif -#if 30003 < GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION +#if 30004 < GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION #error This file was generated by an older version of protoc which is incompatible with your Protocol Buffer library sources. #endif diff --git a/objectivec/GPBSourceContext.pbobjc.m b/objectivec/GPBSourceContext.pbobjc.m index d37a4252a4..b3e6fa759c 100644 --- a/objectivec/GPBSourceContext.pbobjc.m +++ b/objectivec/GPBSourceContext.pbobjc.m @@ -70,7 +70,7 @@ typedef struct GPBSourceContext__storage_ { .number = GPBSourceContext_FieldNumber_FileName, .hasIndex = 0, .offset = (uint32_t)offsetof(GPBSourceContext__storage_, fileName), - .flags = GPBFieldOptional, + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero), .dataType = GPBDataTypeString, }, }; @@ -81,7 +81,7 @@ typedef struct GPBSourceContext__storage_ { fields:fields fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) storageSize:sizeof(GPBSourceContext__storage_) - flags:GPBDescriptorInitializationFlag_UsesClassRefs]; + flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)]; #if defined(DEBUG) && DEBUG NSAssert(descriptor == nil, @"Startup recursed!"); #endif // DEBUG diff --git a/objectivec/GPBStruct.pbobjc.h b/objectivec/GPBStruct.pbobjc.h index b465c3bee5..e36df3f1a3 100644 --- a/objectivec/GPBStruct.pbobjc.h +++ b/objectivec/GPBStruct.pbobjc.h @@ -17,10 +17,10 @@ #import "GPBRootObject.h" #endif -#if GOOGLE_PROTOBUF_OBJC_VERSION < 30003 +#if GOOGLE_PROTOBUF_OBJC_VERSION < 30004 #error This file was generated by a newer version of protoc which is incompatible with your Protocol Buffer library sources. #endif -#if 30003 < GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION +#if 30004 < GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION #error This file was generated by an older version of protoc which is incompatible with your Protocol Buffer library sources. #endif diff --git a/objectivec/GPBStruct.pbobjc.m b/objectivec/GPBStruct.pbobjc.m index b43e9cd906..554046a9fe 100644 --- a/objectivec/GPBStruct.pbobjc.m +++ b/objectivec/GPBStruct.pbobjc.m @@ -126,7 +126,7 @@ typedef struct GPBStruct__storage_ { fields:fields fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) storageSize:sizeof(GPBStruct__storage_) - flags:GPBDescriptorInitializationFlag_UsesClassRefs]; + flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)]; #if defined(DEBUG) && DEBUG NSAssert(descriptor == nil, @"Startup recursed!"); #endif // DEBUG @@ -226,7 +226,7 @@ typedef struct GPBValue__storage_ { fields:fields fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) storageSize:sizeof(GPBValue__storage_) - flags:GPBDescriptorInitializationFlag_UsesClassRefs]; + flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)]; static const char *oneofs[] = { "kind", }; @@ -246,19 +246,19 @@ typedef struct GPBValue__storage_ { int32_t GPBValue_NullValue_RawValue(GPBValue *message) { GPBDescriptor *descriptor = [GPBValue descriptor]; GPBFieldDescriptor *field = [descriptor fieldWithNumber:GPBValue_FieldNumber_NullValue]; - return GPBGetMessageInt32Field(message, field); + return GPBGetMessageRawEnumField(message, field); } void SetGPBValue_NullValue_RawValue(GPBValue *message, int32_t value) { GPBDescriptor *descriptor = [GPBValue descriptor]; GPBFieldDescriptor *field = [descriptor fieldWithNumber:GPBValue_FieldNumber_NullValue]; - GPBSetInt32IvarWithFieldInternal(message, field, value, descriptor.file.syntax); + GPBSetMessageRawEnumField(message, field, value); } void GPBValue_ClearKindOneOfCase(GPBValue *message) { GPBDescriptor *descriptor = [GPBValue descriptor]; GPBOneofDescriptor *oneof = [descriptor.oneofs objectAtIndex:0]; - GPBMaybeClearOneof(message, oneof, -1, 0); + GPBClearOneof(message, oneof); } #pragma mark - GPBListValue @@ -294,7 +294,7 @@ typedef struct GPBListValue__storage_ { fields:fields fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) storageSize:sizeof(GPBListValue__storage_) - flags:GPBDescriptorInitializationFlag_UsesClassRefs]; + flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)]; #if defined(DEBUG) && DEBUG NSAssert(descriptor == nil, @"Startup recursed!"); #endif // DEBUG diff --git a/objectivec/GPBTimestamp.pbobjc.h b/objectivec/GPBTimestamp.pbobjc.h index 1118c778b9..92f0bac886 100644 --- a/objectivec/GPBTimestamp.pbobjc.h +++ b/objectivec/GPBTimestamp.pbobjc.h @@ -17,10 +17,10 @@ #import "GPBRootObject.h" #endif -#if GOOGLE_PROTOBUF_OBJC_VERSION < 30003 +#if GOOGLE_PROTOBUF_OBJC_VERSION < 30004 #error This file was generated by a newer version of protoc which is incompatible with your Protocol Buffer library sources. #endif -#if 30003 < GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION +#if 30004 < GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION #error This file was generated by an older version of protoc which is incompatible with your Protocol Buffer library sources. #endif diff --git a/objectivec/GPBTimestamp.pbobjc.m b/objectivec/GPBTimestamp.pbobjc.m index 450d131b6c..736a75d19f 100644 --- a/objectivec/GPBTimestamp.pbobjc.m +++ b/objectivec/GPBTimestamp.pbobjc.m @@ -72,7 +72,7 @@ typedef struct GPBTimestamp__storage_ { .number = GPBTimestamp_FieldNumber_Seconds, .hasIndex = 0, .offset = (uint32_t)offsetof(GPBTimestamp__storage_, seconds), - .flags = GPBFieldOptional, + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero), .dataType = GPBDataTypeInt64, }, { @@ -81,7 +81,7 @@ typedef struct GPBTimestamp__storage_ { .number = GPBTimestamp_FieldNumber_Nanos, .hasIndex = 1, .offset = (uint32_t)offsetof(GPBTimestamp__storage_, nanos), - .flags = GPBFieldOptional, + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero), .dataType = GPBDataTypeInt32, }, }; @@ -92,7 +92,7 @@ typedef struct GPBTimestamp__storage_ { fields:fields fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) storageSize:sizeof(GPBTimestamp__storage_) - flags:GPBDescriptorInitializationFlag_UsesClassRefs]; + flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)]; #if defined(DEBUG) && DEBUG NSAssert(descriptor == nil, @"Startup recursed!"); #endif // DEBUG diff --git a/objectivec/GPBType.pbobjc.h b/objectivec/GPBType.pbobjc.h index 4b6cd9c521..747e15d455 100644 --- a/objectivec/GPBType.pbobjc.h +++ b/objectivec/GPBType.pbobjc.h @@ -17,10 +17,10 @@ #import "GPBRootObject.h" #endif -#if GOOGLE_PROTOBUF_OBJC_VERSION < 30003 +#if GOOGLE_PROTOBUF_OBJC_VERSION < 30004 #error This file was generated by a newer version of protoc which is incompatible with your Protocol Buffer library sources. #endif -#if 30003 < GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION +#if 30004 < GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION #error This file was generated by an older version of protoc which is incompatible with your Protocol Buffer library sources. #endif diff --git a/objectivec/GPBType.pbobjc.m b/objectivec/GPBType.pbobjc.m index 827270af5f..70dae31c68 100644 --- a/objectivec/GPBType.pbobjc.m +++ b/objectivec/GPBType.pbobjc.m @@ -132,7 +132,7 @@ typedef struct GPBType__storage_ { .number = GPBType_FieldNumber_Name, .hasIndex = 0, .offset = (uint32_t)offsetof(GPBType__storage_, name), - .flags = GPBFieldOptional, + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero), .dataType = GPBDataTypeString, }, { @@ -177,7 +177,7 @@ typedef struct GPBType__storage_ { .number = GPBType_FieldNumber_Syntax, .hasIndex = 2, .offset = (uint32_t)offsetof(GPBType__storage_, syntax), - .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldHasEnumDescriptor), + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldHasEnumDescriptor | GPBFieldClearHasIvarOnZero), .dataType = GPBDataTypeEnum, }, }; @@ -188,7 +188,7 @@ typedef struct GPBType__storage_ { fields:fields fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) storageSize:sizeof(GPBType__storage_) - flags:GPBDescriptorInitializationFlag_UsesClassRefs]; + flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)]; #if defined(DEBUG) && DEBUG NSAssert(descriptor == nil, @"Startup recursed!"); #endif // DEBUG @@ -202,13 +202,13 @@ typedef struct GPBType__storage_ { int32_t GPBType_Syntax_RawValue(GPBType *message) { GPBDescriptor *descriptor = [GPBType descriptor]; GPBFieldDescriptor *field = [descriptor fieldWithNumber:GPBType_FieldNumber_Syntax]; - return GPBGetMessageInt32Field(message, field); + return GPBGetMessageRawEnumField(message, field); } void SetGPBType_Syntax_RawValue(GPBType *message, int32_t value) { GPBDescriptor *descriptor = [GPBType descriptor]; GPBFieldDescriptor *field = [descriptor fieldWithNumber:GPBType_FieldNumber_Syntax]; - GPBSetInt32IvarWithFieldInternal(message, field, value, descriptor.file.syntax); + GPBSetMessageRawEnumField(message, field, value); } #pragma mark - GPBField @@ -251,7 +251,7 @@ typedef struct GPBField__storage_ { .number = GPBField_FieldNumber_Kind, .hasIndex = 0, .offset = (uint32_t)offsetof(GPBField__storage_, kind), - .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldHasEnumDescriptor), + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldHasEnumDescriptor | GPBFieldClearHasIvarOnZero), .dataType = GPBDataTypeEnum, }, { @@ -260,7 +260,7 @@ typedef struct GPBField__storage_ { .number = GPBField_FieldNumber_Cardinality, .hasIndex = 1, .offset = (uint32_t)offsetof(GPBField__storage_, cardinality), - .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldHasEnumDescriptor), + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldHasEnumDescriptor | GPBFieldClearHasIvarOnZero), .dataType = GPBDataTypeEnum, }, { @@ -269,7 +269,7 @@ typedef struct GPBField__storage_ { .number = GPBField_FieldNumber_Number, .hasIndex = 2, .offset = (uint32_t)offsetof(GPBField__storage_, number), - .flags = GPBFieldOptional, + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero), .dataType = GPBDataTypeInt32, }, { @@ -278,7 +278,7 @@ typedef struct GPBField__storage_ { .number = GPBField_FieldNumber_Name, .hasIndex = 3, .offset = (uint32_t)offsetof(GPBField__storage_, name), - .flags = GPBFieldOptional, + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero), .dataType = GPBDataTypeString, }, { @@ -287,7 +287,7 @@ typedef struct GPBField__storage_ { .number = GPBField_FieldNumber_TypeURL, .hasIndex = 4, .offset = (uint32_t)offsetof(GPBField__storage_, typeURL), - .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldTextFormatNameCustom), + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldTextFormatNameCustom | GPBFieldClearHasIvarOnZero), .dataType = GPBDataTypeString, }, { @@ -296,7 +296,7 @@ typedef struct GPBField__storage_ { .number = GPBField_FieldNumber_OneofIndex, .hasIndex = 5, .offset = (uint32_t)offsetof(GPBField__storage_, oneofIndex), - .flags = GPBFieldOptional, + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero), .dataType = GPBDataTypeInt32, }, { @@ -305,7 +305,7 @@ typedef struct GPBField__storage_ { .number = GPBField_FieldNumber_Packed, .hasIndex = 6, .offset = 7, // Stored in _has_storage_ to save space. - .flags = GPBFieldOptional, + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero), .dataType = GPBDataTypeBool, }, { @@ -323,7 +323,7 @@ typedef struct GPBField__storage_ { .number = GPBField_FieldNumber_JsonName, .hasIndex = 8, .offset = (uint32_t)offsetof(GPBField__storage_, jsonName), - .flags = GPBFieldOptional, + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero), .dataType = GPBDataTypeString, }, { @@ -332,7 +332,7 @@ typedef struct GPBField__storage_ { .number = GPBField_FieldNumber_DefaultValue, .hasIndex = 9, .offset = (uint32_t)offsetof(GPBField__storage_, defaultValue), - .flags = GPBFieldOptional, + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero), .dataType = GPBDataTypeString, }, }; @@ -343,7 +343,7 @@ typedef struct GPBField__storage_ { fields:fields fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) storageSize:sizeof(GPBField__storage_) - flags:GPBDescriptorInitializationFlag_UsesClassRefs]; + flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)]; #if !GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS static const char *extraTextFormatInfo = "\001\006\004\241!!\000"; @@ -362,25 +362,25 @@ typedef struct GPBField__storage_ { int32_t GPBField_Kind_RawValue(GPBField *message) { GPBDescriptor *descriptor = [GPBField descriptor]; GPBFieldDescriptor *field = [descriptor fieldWithNumber:GPBField_FieldNumber_Kind]; - return GPBGetMessageInt32Field(message, field); + return GPBGetMessageRawEnumField(message, field); } void SetGPBField_Kind_RawValue(GPBField *message, int32_t value) { GPBDescriptor *descriptor = [GPBField descriptor]; GPBFieldDescriptor *field = [descriptor fieldWithNumber:GPBField_FieldNumber_Kind]; - GPBSetInt32IvarWithFieldInternal(message, field, value, descriptor.file.syntax); + GPBSetMessageRawEnumField(message, field, value); } int32_t GPBField_Cardinality_RawValue(GPBField *message) { GPBDescriptor *descriptor = [GPBField descriptor]; GPBFieldDescriptor *field = [descriptor fieldWithNumber:GPBField_FieldNumber_Cardinality]; - return GPBGetMessageInt32Field(message, field); + return GPBGetMessageRawEnumField(message, field); } void SetGPBField_Cardinality_RawValue(GPBField *message, int32_t value) { GPBDescriptor *descriptor = [GPBField descriptor]; GPBFieldDescriptor *field = [descriptor fieldWithNumber:GPBField_FieldNumber_Cardinality]; - GPBSetInt32IvarWithFieldInternal(message, field, value, descriptor.file.syntax); + GPBSetMessageRawEnumField(message, field, value); } #pragma mark - Enum GPBField_Kind @@ -528,7 +528,7 @@ typedef struct GPBEnum__storage_ { .number = GPBEnum_FieldNumber_Name, .hasIndex = 0, .offset = (uint32_t)offsetof(GPBEnum__storage_, name), - .flags = GPBFieldOptional, + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero), .dataType = GPBDataTypeString, }, { @@ -564,7 +564,7 @@ typedef struct GPBEnum__storage_ { .number = GPBEnum_FieldNumber_Syntax, .hasIndex = 2, .offset = (uint32_t)offsetof(GPBEnum__storage_, syntax), - .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldHasEnumDescriptor), + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldHasEnumDescriptor | GPBFieldClearHasIvarOnZero), .dataType = GPBDataTypeEnum, }, }; @@ -575,7 +575,7 @@ typedef struct GPBEnum__storage_ { fields:fields fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) storageSize:sizeof(GPBEnum__storage_) - flags:GPBDescriptorInitializationFlag_UsesClassRefs]; + flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)]; #if defined(DEBUG) && DEBUG NSAssert(descriptor == nil, @"Startup recursed!"); #endif // DEBUG @@ -589,13 +589,13 @@ typedef struct GPBEnum__storage_ { int32_t GPBEnum_Syntax_RawValue(GPBEnum *message) { GPBDescriptor *descriptor = [GPBEnum descriptor]; GPBFieldDescriptor *field = [descriptor fieldWithNumber:GPBEnum_FieldNumber_Syntax]; - return GPBGetMessageInt32Field(message, field); + return GPBGetMessageRawEnumField(message, field); } void SetGPBEnum_Syntax_RawValue(GPBEnum *message, int32_t value) { GPBDescriptor *descriptor = [GPBEnum descriptor]; GPBFieldDescriptor *field = [descriptor fieldWithNumber:GPBEnum_FieldNumber_Syntax]; - GPBSetInt32IvarWithFieldInternal(message, field, value, descriptor.file.syntax); + GPBSetMessageRawEnumField(message, field, value); } #pragma mark - GPBEnumValue @@ -625,7 +625,7 @@ typedef struct GPBEnumValue__storage_ { .number = GPBEnumValue_FieldNumber_Name, .hasIndex = 0, .offset = (uint32_t)offsetof(GPBEnumValue__storage_, name), - .flags = GPBFieldOptional, + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero), .dataType = GPBDataTypeString, }, { @@ -634,7 +634,7 @@ typedef struct GPBEnumValue__storage_ { .number = GPBEnumValue_FieldNumber_Number, .hasIndex = 1, .offset = (uint32_t)offsetof(GPBEnumValue__storage_, number), - .flags = GPBFieldOptional, + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero), .dataType = GPBDataTypeInt32, }, { @@ -654,7 +654,7 @@ typedef struct GPBEnumValue__storage_ { fields:fields fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) storageSize:sizeof(GPBEnumValue__storage_) - flags:GPBDescriptorInitializationFlag_UsesClassRefs]; + flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)]; #if defined(DEBUG) && DEBUG NSAssert(descriptor == nil, @"Startup recursed!"); #endif // DEBUG @@ -690,7 +690,7 @@ typedef struct GPBOption__storage_ { .number = GPBOption_FieldNumber_Name, .hasIndex = 0, .offset = (uint32_t)offsetof(GPBOption__storage_, name), - .flags = GPBFieldOptional, + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero), .dataType = GPBDataTypeString, }, { @@ -710,7 +710,7 @@ typedef struct GPBOption__storage_ { fields:fields fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) storageSize:sizeof(GPBOption__storage_) - flags:GPBDescriptorInitializationFlag_UsesClassRefs]; + flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)]; #if defined(DEBUG) && DEBUG NSAssert(descriptor == nil, @"Startup recursed!"); #endif // DEBUG diff --git a/objectivec/GPBWrappers.pbobjc.h b/objectivec/GPBWrappers.pbobjc.h index cc377f2920..713bafc89b 100644 --- a/objectivec/GPBWrappers.pbobjc.h +++ b/objectivec/GPBWrappers.pbobjc.h @@ -17,10 +17,10 @@ #import "GPBRootObject.h" #endif -#if GOOGLE_PROTOBUF_OBJC_VERSION < 30003 +#if GOOGLE_PROTOBUF_OBJC_VERSION < 30004 #error This file was generated by a newer version of protoc which is incompatible with your Protocol Buffer library sources. #endif -#if 30003 < GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION +#if 30004 < GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION #error This file was generated by an older version of protoc which is incompatible with your Protocol Buffer library sources. #endif diff --git a/objectivec/GPBWrappers.pbobjc.m b/objectivec/GPBWrappers.pbobjc.m index 5de7a83a2f..32201d4d83 100644 --- a/objectivec/GPBWrappers.pbobjc.m +++ b/objectivec/GPBWrappers.pbobjc.m @@ -70,7 +70,7 @@ typedef struct GPBDoubleValue__storage_ { .number = GPBDoubleValue_FieldNumber_Value, .hasIndex = 0, .offset = (uint32_t)offsetof(GPBDoubleValue__storage_, value), - .flags = GPBFieldOptional, + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero), .dataType = GPBDataTypeDouble, }, }; @@ -81,7 +81,7 @@ typedef struct GPBDoubleValue__storage_ { fields:fields fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) storageSize:sizeof(GPBDoubleValue__storage_) - flags:GPBDescriptorInitializationFlag_UsesClassRefs]; + flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)]; #if defined(DEBUG) && DEBUG NSAssert(descriptor == nil, @"Startup recursed!"); #endif // DEBUG @@ -115,7 +115,7 @@ typedef struct GPBFloatValue__storage_ { .number = GPBFloatValue_FieldNumber_Value, .hasIndex = 0, .offset = (uint32_t)offsetof(GPBFloatValue__storage_, value), - .flags = GPBFieldOptional, + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero), .dataType = GPBDataTypeFloat, }, }; @@ -126,7 +126,7 @@ typedef struct GPBFloatValue__storage_ { fields:fields fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) storageSize:sizeof(GPBFloatValue__storage_) - flags:GPBDescriptorInitializationFlag_UsesClassRefs]; + flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)]; #if defined(DEBUG) && DEBUG NSAssert(descriptor == nil, @"Startup recursed!"); #endif // DEBUG @@ -160,7 +160,7 @@ typedef struct GPBInt64Value__storage_ { .number = GPBInt64Value_FieldNumber_Value, .hasIndex = 0, .offset = (uint32_t)offsetof(GPBInt64Value__storage_, value), - .flags = GPBFieldOptional, + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero), .dataType = GPBDataTypeInt64, }, }; @@ -171,7 +171,7 @@ typedef struct GPBInt64Value__storage_ { fields:fields fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) storageSize:sizeof(GPBInt64Value__storage_) - flags:GPBDescriptorInitializationFlag_UsesClassRefs]; + flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)]; #if defined(DEBUG) && DEBUG NSAssert(descriptor == nil, @"Startup recursed!"); #endif // DEBUG @@ -205,7 +205,7 @@ typedef struct GPBUInt64Value__storage_ { .number = GPBUInt64Value_FieldNumber_Value, .hasIndex = 0, .offset = (uint32_t)offsetof(GPBUInt64Value__storage_, value), - .flags = GPBFieldOptional, + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero), .dataType = GPBDataTypeUInt64, }, }; @@ -216,7 +216,7 @@ typedef struct GPBUInt64Value__storage_ { fields:fields fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) storageSize:sizeof(GPBUInt64Value__storage_) - flags:GPBDescriptorInitializationFlag_UsesClassRefs]; + flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)]; #if defined(DEBUG) && DEBUG NSAssert(descriptor == nil, @"Startup recursed!"); #endif // DEBUG @@ -250,7 +250,7 @@ typedef struct GPBInt32Value__storage_ { .number = GPBInt32Value_FieldNumber_Value, .hasIndex = 0, .offset = (uint32_t)offsetof(GPBInt32Value__storage_, value), - .flags = GPBFieldOptional, + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero), .dataType = GPBDataTypeInt32, }, }; @@ -261,7 +261,7 @@ typedef struct GPBInt32Value__storage_ { fields:fields fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) storageSize:sizeof(GPBInt32Value__storage_) - flags:GPBDescriptorInitializationFlag_UsesClassRefs]; + flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)]; #if defined(DEBUG) && DEBUG NSAssert(descriptor == nil, @"Startup recursed!"); #endif // DEBUG @@ -295,7 +295,7 @@ typedef struct GPBUInt32Value__storage_ { .number = GPBUInt32Value_FieldNumber_Value, .hasIndex = 0, .offset = (uint32_t)offsetof(GPBUInt32Value__storage_, value), - .flags = GPBFieldOptional, + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero), .dataType = GPBDataTypeUInt32, }, }; @@ -306,7 +306,7 @@ typedef struct GPBUInt32Value__storage_ { fields:fields fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) storageSize:sizeof(GPBUInt32Value__storage_) - flags:GPBDescriptorInitializationFlag_UsesClassRefs]; + flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)]; #if defined(DEBUG) && DEBUG NSAssert(descriptor == nil, @"Startup recursed!"); #endif // DEBUG @@ -339,7 +339,7 @@ typedef struct GPBBoolValue__storage_ { .number = GPBBoolValue_FieldNumber_Value, .hasIndex = 0, .offset = 1, // Stored in _has_storage_ to save space. - .flags = GPBFieldOptional, + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero), .dataType = GPBDataTypeBool, }, }; @@ -350,7 +350,7 @@ typedef struct GPBBoolValue__storage_ { fields:fields fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) storageSize:sizeof(GPBBoolValue__storage_) - flags:GPBDescriptorInitializationFlag_UsesClassRefs]; + flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)]; #if defined(DEBUG) && DEBUG NSAssert(descriptor == nil, @"Startup recursed!"); #endif // DEBUG @@ -384,7 +384,7 @@ typedef struct GPBStringValue__storage_ { .number = GPBStringValue_FieldNumber_Value, .hasIndex = 0, .offset = (uint32_t)offsetof(GPBStringValue__storage_, value), - .flags = GPBFieldOptional, + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero), .dataType = GPBDataTypeString, }, }; @@ -395,7 +395,7 @@ typedef struct GPBStringValue__storage_ { fields:fields fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) storageSize:sizeof(GPBStringValue__storage_) - flags:GPBDescriptorInitializationFlag_UsesClassRefs]; + flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)]; #if defined(DEBUG) && DEBUG NSAssert(descriptor == nil, @"Startup recursed!"); #endif // DEBUG @@ -429,7 +429,7 @@ typedef struct GPBBytesValue__storage_ { .number = GPBBytesValue_FieldNumber_Value, .hasIndex = 0, .offset = (uint32_t)offsetof(GPBBytesValue__storage_, value), - .flags = GPBFieldOptional, + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero), .dataType = GPBDataTypeBytes, }, }; @@ -440,7 +440,7 @@ typedef struct GPBBytesValue__storage_ { fields:fields fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) storageSize:sizeof(GPBBytesValue__storage_) - flags:GPBDescriptorInitializationFlag_UsesClassRefs]; + flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)]; #if defined(DEBUG) && DEBUG NSAssert(descriptor == nil, @"Startup recursed!"); #endif // DEBUG diff --git a/src/google/protobuf/compiler/objectivec/objectivec_enum_field.cc b/src/google/protobuf/compiler/objectivec/objectivec_enum_field.cc index 9890d0a140..3893801fa4 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_enum_field.cc +++ b/src/google/protobuf/compiler/objectivec/objectivec_enum_field.cc @@ -104,13 +104,13 @@ void EnumFieldGenerator::GenerateCFunctionImplementations( "int32_t $owning_message_class$_$capitalized_name$_RawValue($owning_message_class$ *message) {\n" " GPBDescriptor *descriptor = [$owning_message_class$ descriptor];\n" " GPBFieldDescriptor *field = [descriptor fieldWithNumber:$field_number_name$];\n" - " return GPBGetMessageInt32Field(message, field);\n" + " return GPBGetMessageRawEnumField(message, field);\n" "}\n" "\n" "void Set$owning_message_class$_$capitalized_name$_RawValue($owning_message_class$ *message, int32_t value) {\n" " GPBDescriptor *descriptor = [$owning_message_class$ descriptor];\n" " GPBFieldDescriptor *field = [descriptor fieldWithNumber:$field_number_name$];\n" - " GPBSetInt32IvarWithFieldInternal(message, field, value, descriptor.file.syntax);\n" + " GPBSetMessageRawEnumField(message, field, value);\n" "}\n" "\n"); } diff --git a/src/google/protobuf/compiler/objectivec/objectivec_field.cc b/src/google/protobuf/compiler/objectivec/objectivec_field.cc index bc39d32d28..e8360a515b 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_field.cc +++ b/src/google/protobuf/compiler/objectivec/objectivec_field.cc @@ -91,6 +91,14 @@ void SetCommonFieldVariables(const FieldDescriptor* descriptor, if (descriptor->type() == FieldDescriptor::TYPE_ENUM) { field_flags.push_back("GPBFieldHasEnumDescriptor"); } + // It will clear on a zero value if... + // - not repeated/map + // - doesn't have presence + bool clear_on_zero = + (!descriptor->is_repeated() && !descriptor->has_presence()); + if (clear_on_zero) { + field_flags.push_back("GPBFieldClearHasIvarOnZero"); + } (*variables)["fieldflags"] = BuildFlagsString(FLAGTYPE_FIELD, field_flags); diff --git a/src/google/protobuf/compiler/objectivec/objectivec_file.cc b/src/google/protobuf/compiler/objectivec/objectivec_file.cc index db58249ded..04733ca24c 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_file.cc +++ b/src/google/protobuf/compiler/objectivec/objectivec_file.cc @@ -52,7 +52,7 @@ namespace objectivec { namespace { // This is also found in GPBBootstrap.h, and needs to be kept in sync. -const int32 GOOGLE_PROTOBUF_OBJC_VERSION = 30003; +const int32 GOOGLE_PROTOBUF_OBJC_VERSION = 30004; const char* kHeaderExtension = ".pbobjc.h"; diff --git a/src/google/protobuf/compiler/objectivec/objectivec_generator.h b/src/google/protobuf/compiler/objectivec/objectivec_generator.h index d10efc20ef..b09e2b2d3f 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_generator.h +++ b/src/google/protobuf/compiler/objectivec/objectivec_generator.h @@ -57,15 +57,19 @@ class PROTOC_EXPORT ObjectiveCGenerator : public CodeGenerator { ObjectiveCGenerator& operator=(const ObjectiveCGenerator&) = delete; // implements CodeGenerator ---------------------------------------- - bool HasGenerateAll() const; + bool HasGenerateAll() const override; bool Generate(const FileDescriptor* file, const string& parameter, GeneratorContext* context, - string* error) const; + string* error) const override; bool GenerateAll(const std::vector& files, const string& parameter, GeneratorContext* context, - string* error) const; + string* error) const override; + + uint64 GetSupportedFeatures() const override { + return FEATURE_PROTO3_OPTIONAL; + } }; } // namespace objectivec diff --git a/src/google/protobuf/compiler/objectivec/objectivec_message.cc b/src/google/protobuf/compiler/objectivec/objectivec_message.cc index f2287f6711..0684021c2a 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_message.cc +++ b/src/google/protobuf/compiler/objectivec/objectivec_message.cc @@ -516,6 +516,7 @@ void MessageGenerator::GenerateSource(io::Printer* printer) { std::vector init_flags; init_flags.push_back("GPBDescriptorInitializationFlag_UsesClassRefs"); + init_flags.push_back("GPBDescriptorInitializationFlag_Proto3OptionalKnown"); if (need_defaults) { init_flags.push_back("GPBDescriptorInitializationFlag_FieldsWithDefault"); } diff --git a/src/google/protobuf/compiler/objectivec/objectivec_oneof.cc b/src/google/protobuf/compiler/objectivec/objectivec_oneof.cc index 2dbfb71bbd..badebf55b9 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_oneof.cc +++ b/src/google/protobuf/compiler/objectivec/objectivec_oneof.cc @@ -122,7 +122,7 @@ void OneofGenerator::GenerateClearFunctionImplementation(io::Printer* printer) { "void $owning_message_class$_Clear$capitalized_name$OneOfCase($owning_message_class$ *message) {\n" " GPBDescriptor *descriptor = [$owning_message_class$ descriptor];\n" " GPBOneofDescriptor *oneof = [descriptor.oneofs objectAtIndex:$raw_index$];\n" - " GPBMaybeClearOneof(message, oneof, $index$, 0);\n" + " GPBClearOneof(message, oneof);\n" "}\n"); } From 7b6016e343741df37a7811efc239d5b1cda10575 Mon Sep 17 00:00:00 2001 From: Thomas Van Lenten Date: Tue, 14 Apr 2020 11:03:14 -0400 Subject: [PATCH 36/38] [ObjC] Add tests for proto3 optional behaviors. --- objectivec/DevTools/compile_testing_protos.sh | 1 + objectivec/Tests/GPBMessageTests+Runtime.m | 260 +++++++++++++++ .../Tests/GPBMessageTests+Serialization.m | 311 ++++++++++++++++++ .../Tests/unittest_runtime_proto3.proto | 28 ++ 4 files changed, 600 insertions(+) diff --git a/objectivec/DevTools/compile_testing_protos.sh b/objectivec/DevTools/compile_testing_protos.sh index dc1d6d2e98..d04c5c522b 100755 --- a/objectivec/DevTools/compile_testing_protos.sh +++ b/objectivec/DevTools/compile_testing_protos.sh @@ -158,6 +158,7 @@ compile_protos() { --objc_out="${OUTPUT_DIR}/google/protobuf" \ --proto_path=src/google/protobuf/ \ --proto_path=src \ + --experimental_allow_proto3_optional \ "$@" } diff --git a/objectivec/Tests/GPBMessageTests+Runtime.m b/objectivec/Tests/GPBMessageTests+Runtime.m index aa5b0dbe75..1dac79754e 100644 --- a/objectivec/Tests/GPBMessageTests+Runtime.m +++ b/objectivec/Tests/GPBMessageTests+Runtime.m @@ -270,6 +270,23 @@ @"field: %@", name); } + // Single Optional fields + // - has*/setHas* thanks to the optional keyword in proto3, they exist + // for primitive types. + // - has*/setHas* valid for Message. + + for (NSString *name in names) { + // build the selector, i.e. - hasOptionalInt32/setHasOptionalInt32: + SEL hasSel = NSSelectorFromString( + [NSString stringWithFormat:@"hasOptional%@", name]); + SEL setHasSel = NSSelectorFromString( + [NSString stringWithFormat:@"setHasOptional%@:", name]); + XCTAssertTrue([Message3Optional instancesRespondToSelector:hasSel], @"field: %@", + name); + XCTAssertTrue([Message3Optional instancesRespondToSelector:setHasSel], + @"field: %@", name); + } + // map<> fields // - no has*/setHas* // - *Count @@ -1002,6 +1019,249 @@ //%PDDM-EXPAND-END PROTO3_TEST_HAS_FIELDS() } +- (void)testProto3SingleOptionalFieldHasBehavior { + // + // Setting to any value including the default (0) should result in true. + // + +//%PDDM-DEFINE PROTO3_TEST_OPTIONAL_HAS_FIELD(FIELD, NON_ZERO_VALUE, ZERO_VALUE) +//% { // optional##FIELD +//% Message3Optional *msg = [[Message3Optional alloc] init]; +//% XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_Optional##FIELD)); +//% msg.optional##FIELD = NON_ZERO_VALUE; +//% XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_Optional##FIELD)); +//% msg.hasOptional##FIELD = NO; +//% XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_Optional##FIELD)); +//% msg.optional##FIELD = ZERO_VALUE; +//% XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_Optional##FIELD)); +//% [msg release]; +//% } +//% +//%PDDM-DEFINE PROTO3_TEST_OPTIONAL_HAS_FIELDS() +//%PROTO3_TEST_OPTIONAL_HAS_FIELD(Int32, 1, 0) +//%PROTO3_TEST_OPTIONAL_HAS_FIELD(Int64, 1, 0) +//%PROTO3_TEST_OPTIONAL_HAS_FIELD(Uint32, 1, 0) +//%PROTO3_TEST_OPTIONAL_HAS_FIELD(Uint64, 1, 0) +//%PROTO3_TEST_OPTIONAL_HAS_FIELD(Sint32, 1, 0) +//%PROTO3_TEST_OPTIONAL_HAS_FIELD(Sint64, 1, 0) +//%PROTO3_TEST_OPTIONAL_HAS_FIELD(Fixed32, 1, 0) +//%PROTO3_TEST_OPTIONAL_HAS_FIELD(Fixed64, 1, 0) +//%PROTO3_TEST_OPTIONAL_HAS_FIELD(Sfixed32, 1, 0) +//%PROTO3_TEST_OPTIONAL_HAS_FIELD(Sfixed64, 1, 0) +//%PROTO3_TEST_OPTIONAL_HAS_FIELD(Float, 1.0f, 0.0f) +//%PROTO3_TEST_OPTIONAL_HAS_FIELD(Double, 1.0, 0.0) +//%PROTO3_TEST_OPTIONAL_HAS_FIELD(Bool, YES, NO) +//%PROTO3_TEST_OPTIONAL_HAS_FIELD(String, @"foo", @"") +//%PROTO3_TEST_OPTIONAL_HAS_FIELD(Bytes, [@"foo" dataUsingEncoding:NSUTF8StringEncoding], [NSData data]) +//% // +//% // Test doesn't apply to optionalMessage (no groups in proto3). +//% // +//% +//%PROTO3_TEST_OPTIONAL_HAS_FIELD(Enum, Message3Optional_Enum_Bar, Message3Optional_Enum_Foo) +//%PDDM-EXPAND PROTO3_TEST_OPTIONAL_HAS_FIELDS() +// This block of code is generated, do not edit it directly. +// clang-format off + + { // optionalInt32 + Message3Optional *msg = [[Message3Optional alloc] init]; + XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalInt32)); + msg.optionalInt32 = 1; + XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalInt32)); + msg.hasOptionalInt32 = NO; + XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalInt32)); + msg.optionalInt32 = 0; + XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalInt32)); + [msg release]; + } + + { // optionalInt64 + Message3Optional *msg = [[Message3Optional alloc] init]; + XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalInt64)); + msg.optionalInt64 = 1; + XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalInt64)); + msg.hasOptionalInt64 = NO; + XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalInt64)); + msg.optionalInt64 = 0; + XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalInt64)); + [msg release]; + } + + { // optionalUint32 + Message3Optional *msg = [[Message3Optional alloc] init]; + XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalUint32)); + msg.optionalUint32 = 1; + XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalUint32)); + msg.hasOptionalUint32 = NO; + XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalUint32)); + msg.optionalUint32 = 0; + XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalUint32)); + [msg release]; + } + + { // optionalUint64 + Message3Optional *msg = [[Message3Optional alloc] init]; + XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalUint64)); + msg.optionalUint64 = 1; + XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalUint64)); + msg.hasOptionalUint64 = NO; + XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalUint64)); + msg.optionalUint64 = 0; + XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalUint64)); + [msg release]; + } + + { // optionalSint32 + Message3Optional *msg = [[Message3Optional alloc] init]; + XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalSint32)); + msg.optionalSint32 = 1; + XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalSint32)); + msg.hasOptionalSint32 = NO; + XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalSint32)); + msg.optionalSint32 = 0; + XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalSint32)); + [msg release]; + } + + { // optionalSint64 + Message3Optional *msg = [[Message3Optional alloc] init]; + XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalSint64)); + msg.optionalSint64 = 1; + XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalSint64)); + msg.hasOptionalSint64 = NO; + XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalSint64)); + msg.optionalSint64 = 0; + XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalSint64)); + [msg release]; + } + + { // optionalFixed32 + Message3Optional *msg = [[Message3Optional alloc] init]; + XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalFixed32)); + msg.optionalFixed32 = 1; + XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalFixed32)); + msg.hasOptionalFixed32 = NO; + XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalFixed32)); + msg.optionalFixed32 = 0; + XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalFixed32)); + [msg release]; + } + + { // optionalFixed64 + Message3Optional *msg = [[Message3Optional alloc] init]; + XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalFixed64)); + msg.optionalFixed64 = 1; + XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalFixed64)); + msg.hasOptionalFixed64 = NO; + XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalFixed64)); + msg.optionalFixed64 = 0; + XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalFixed64)); + [msg release]; + } + + { // optionalSfixed32 + Message3Optional *msg = [[Message3Optional alloc] init]; + XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalSfixed32)); + msg.optionalSfixed32 = 1; + XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalSfixed32)); + msg.hasOptionalSfixed32 = NO; + XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalSfixed32)); + msg.optionalSfixed32 = 0; + XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalSfixed32)); + [msg release]; + } + + { // optionalSfixed64 + Message3Optional *msg = [[Message3Optional alloc] init]; + XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalSfixed64)); + msg.optionalSfixed64 = 1; + XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalSfixed64)); + msg.hasOptionalSfixed64 = NO; + XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalSfixed64)); + msg.optionalSfixed64 = 0; + XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalSfixed64)); + [msg release]; + } + + { // optionalFloat + Message3Optional *msg = [[Message3Optional alloc] init]; + XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalFloat)); + msg.optionalFloat = 1.0f; + XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalFloat)); + msg.hasOptionalFloat = NO; + XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalFloat)); + msg.optionalFloat = 0.0f; + XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalFloat)); + [msg release]; + } + + { // optionalDouble + Message3Optional *msg = [[Message3Optional alloc] init]; + XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalDouble)); + msg.optionalDouble = 1.0; + XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalDouble)); + msg.hasOptionalDouble = NO; + XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalDouble)); + msg.optionalDouble = 0.0; + XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalDouble)); + [msg release]; + } + + { // optionalBool + Message3Optional *msg = [[Message3Optional alloc] init]; + XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalBool)); + msg.optionalBool = YES; + XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalBool)); + msg.hasOptionalBool = NO; + XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalBool)); + msg.optionalBool = NO; + XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalBool)); + [msg release]; + } + + { // optionalString + Message3Optional *msg = [[Message3Optional alloc] init]; + XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalString)); + msg.optionalString = @"foo"; + XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalString)); + msg.hasOptionalString = NO; + XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalString)); + msg.optionalString = @""; + XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalString)); + [msg release]; + } + + { // optionalBytes + Message3Optional *msg = [[Message3Optional alloc] init]; + XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalBytes)); + msg.optionalBytes = [@"foo" dataUsingEncoding:NSUTF8StringEncoding]; + XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalBytes)); + msg.hasOptionalBytes = NO; + XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalBytes)); + msg.optionalBytes = [NSData data]; + XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalBytes)); + [msg release]; + } + + // + // Test doesn't apply to optionalMessage (no groups in proto3). + // + + { // optionalEnum + Message3Optional *msg = [[Message3Optional alloc] init]; + XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalEnum)); + msg.optionalEnum = Message3Optional_Enum_Bar; + XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalEnum)); + msg.hasOptionalEnum = NO; + XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalEnum)); + msg.optionalEnum = Message3Optional_Enum_Foo; + XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3Optional_FieldNumber_OptionalEnum)); + [msg release]; + } + +// clang-format on +//%PDDM-EXPAND-END PROTO3_TEST_OPTIONAL_HAS_FIELDS() +} + - (void)testAccessingProto2UnknownEnumValues { Message2 *msg = [[Message2 alloc] init]; diff --git a/objectivec/Tests/GPBMessageTests+Serialization.m b/objectivec/Tests/GPBMessageTests+Serialization.m index ef6e589e39..6f20797aee 100644 --- a/objectivec/Tests/GPBMessageTests+Serialization.m +++ b/objectivec/Tests/GPBMessageTests+Serialization.m @@ -109,6 +109,317 @@ [msg release]; } +- (void)testProto3SerializationHandlingOptionals { + // + // Proto3 optionals should be just like proto2, zero values also get serialized. + // + +//%PDDM-DEFINE PROTO3_TEST_SERIALIZE_OPTIONAL_FIELD(FIELD, ZERO_VALUE, EXPECTED_LEN) +//% { // optional##FIELD +//% Message3Optional *msg = [[Message3Optional alloc] init]; +//% NSData *data = [msg data]; +//% XCTAssertEqual([data length], 0U); +//% msg.optional##FIELD = ZERO_VALUE; +//% data = [msg data]; +//% XCTAssertEqual(data.length, EXPECTED_LEN); +//% NSError *err = nil; +//% Message3Optional *msg2 = [Message3Optional parseFromData:data error:&err]; +//% XCTAssertNotNil(msg2); +//% XCTAssertNil(err); +//% XCTAssertTrue(msg2.hasOptional##FIELD); +//% XCTAssertEqualObjects(msg, msg2); +//% [msg release]; +//% } +//% +//%PDDM-DEFINE PROTO3_TEST_SERIALIZE_OPTIONAL_FIELDS() +//%PROTO3_TEST_SERIALIZE_OPTIONAL_FIELD(Int32, 0, 2) +//%PROTO3_TEST_SERIALIZE_OPTIONAL_FIELD(Int64, 0, 2) +//%PROTO3_TEST_SERIALIZE_OPTIONAL_FIELD(Uint32, 0, 2) +//%PROTO3_TEST_SERIALIZE_OPTIONAL_FIELD(Uint64, 0, 2) +//%PROTO3_TEST_SERIALIZE_OPTIONAL_FIELD(Sint32, 0, 2) +//%PROTO3_TEST_SERIALIZE_OPTIONAL_FIELD(Sint64, 0, 2) +//%PROTO3_TEST_SERIALIZE_OPTIONAL_FIELD(Fixed32, 0, 5) +//%PROTO3_TEST_SERIALIZE_OPTIONAL_FIELD(Fixed64, 0, 9) +//%PROTO3_TEST_SERIALIZE_OPTIONAL_FIELD(Sfixed32, 0, 5) +//%PROTO3_TEST_SERIALIZE_OPTIONAL_FIELD(Sfixed64, 0, 9) +//%PROTO3_TEST_SERIALIZE_OPTIONAL_FIELD(Float, 0.0f, 5) +//%PROTO3_TEST_SERIALIZE_OPTIONAL_FIELD(Double, 0.0, 9) +//%PROTO3_TEST_SERIALIZE_OPTIONAL_FIELD(Bool, NO, 2) +//%PROTO3_TEST_SERIALIZE_OPTIONAL_FIELD(String, @"", 2) +//%PROTO3_TEST_SERIALIZE_OPTIONAL_FIELD(Bytes, [NSData data], 2) +//% // +//% // Test doesn't apply to optionalMessage (no groups in proto3). +//% // +//% +//%PROTO3_TEST_SERIALIZE_OPTIONAL_FIELD(Enum, Message3Optional_Enum_Foo, 3) +//%PDDM-EXPAND PROTO3_TEST_SERIALIZE_OPTIONAL_FIELDS() +// This block of code is generated, do not edit it directly. +// clang-format off + + { // optionalInt32 + Message3Optional *msg = [[Message3Optional alloc] init]; + NSData *data = [msg data]; + XCTAssertEqual([data length], 0U); + msg.optionalInt32 = 0; + data = [msg data]; + XCTAssertEqual(data.length, 2); + NSError *err = nil; + Message3Optional *msg2 = [Message3Optional parseFromData:data error:&err]; + XCTAssertNotNil(msg2); + XCTAssertNil(err); + XCTAssertTrue(msg2.hasOptionalInt32); + XCTAssertEqualObjects(msg, msg2); + [msg release]; + } + + { // optionalInt64 + Message3Optional *msg = [[Message3Optional alloc] init]; + NSData *data = [msg data]; + XCTAssertEqual([data length], 0U); + msg.optionalInt64 = 0; + data = [msg data]; + XCTAssertEqual(data.length, 2); + NSError *err = nil; + Message3Optional *msg2 = [Message3Optional parseFromData:data error:&err]; + XCTAssertNotNil(msg2); + XCTAssertNil(err); + XCTAssertTrue(msg2.hasOptionalInt64); + XCTAssertEqualObjects(msg, msg2); + [msg release]; + } + + { // optionalUint32 + Message3Optional *msg = [[Message3Optional alloc] init]; + NSData *data = [msg data]; + XCTAssertEqual([data length], 0U); + msg.optionalUint32 = 0; + data = [msg data]; + XCTAssertEqual(data.length, 2); + NSError *err = nil; + Message3Optional *msg2 = [Message3Optional parseFromData:data error:&err]; + XCTAssertNotNil(msg2); + XCTAssertNil(err); + XCTAssertTrue(msg2.hasOptionalUint32); + XCTAssertEqualObjects(msg, msg2); + [msg release]; + } + + { // optionalUint64 + Message3Optional *msg = [[Message3Optional alloc] init]; + NSData *data = [msg data]; + XCTAssertEqual([data length], 0U); + msg.optionalUint64 = 0; + data = [msg data]; + XCTAssertEqual(data.length, 2); + NSError *err = nil; + Message3Optional *msg2 = [Message3Optional parseFromData:data error:&err]; + XCTAssertNotNil(msg2); + XCTAssertNil(err); + XCTAssertTrue(msg2.hasOptionalUint64); + XCTAssertEqualObjects(msg, msg2); + [msg release]; + } + + { // optionalSint32 + Message3Optional *msg = [[Message3Optional alloc] init]; + NSData *data = [msg data]; + XCTAssertEqual([data length], 0U); + msg.optionalSint32 = 0; + data = [msg data]; + XCTAssertEqual(data.length, 2); + NSError *err = nil; + Message3Optional *msg2 = [Message3Optional parseFromData:data error:&err]; + XCTAssertNotNil(msg2); + XCTAssertNil(err); + XCTAssertTrue(msg2.hasOptionalSint32); + XCTAssertEqualObjects(msg, msg2); + [msg release]; + } + + { // optionalSint64 + Message3Optional *msg = [[Message3Optional alloc] init]; + NSData *data = [msg data]; + XCTAssertEqual([data length], 0U); + msg.optionalSint64 = 0; + data = [msg data]; + XCTAssertEqual(data.length, 2); + NSError *err = nil; + Message3Optional *msg2 = [Message3Optional parseFromData:data error:&err]; + XCTAssertNotNil(msg2); + XCTAssertNil(err); + XCTAssertTrue(msg2.hasOptionalSint64); + XCTAssertEqualObjects(msg, msg2); + [msg release]; + } + + { // optionalFixed32 + Message3Optional *msg = [[Message3Optional alloc] init]; + NSData *data = [msg data]; + XCTAssertEqual([data length], 0U); + msg.optionalFixed32 = 0; + data = [msg data]; + XCTAssertEqual(data.length, 5); + NSError *err = nil; + Message3Optional *msg2 = [Message3Optional parseFromData:data error:&err]; + XCTAssertNotNil(msg2); + XCTAssertNil(err); + XCTAssertTrue(msg2.hasOptionalFixed32); + XCTAssertEqualObjects(msg, msg2); + [msg release]; + } + + { // optionalFixed64 + Message3Optional *msg = [[Message3Optional alloc] init]; + NSData *data = [msg data]; + XCTAssertEqual([data length], 0U); + msg.optionalFixed64 = 0; + data = [msg data]; + XCTAssertEqual(data.length, 9); + NSError *err = nil; + Message3Optional *msg2 = [Message3Optional parseFromData:data error:&err]; + XCTAssertNotNil(msg2); + XCTAssertNil(err); + XCTAssertTrue(msg2.hasOptionalFixed64); + XCTAssertEqualObjects(msg, msg2); + [msg release]; + } + + { // optionalSfixed32 + Message3Optional *msg = [[Message3Optional alloc] init]; + NSData *data = [msg data]; + XCTAssertEqual([data length], 0U); + msg.optionalSfixed32 = 0; + data = [msg data]; + XCTAssertEqual(data.length, 5); + NSError *err = nil; + Message3Optional *msg2 = [Message3Optional parseFromData:data error:&err]; + XCTAssertNotNil(msg2); + XCTAssertNil(err); + XCTAssertTrue(msg2.hasOptionalSfixed32); + XCTAssertEqualObjects(msg, msg2); + [msg release]; + } + + { // optionalSfixed64 + Message3Optional *msg = [[Message3Optional alloc] init]; + NSData *data = [msg data]; + XCTAssertEqual([data length], 0U); + msg.optionalSfixed64 = 0; + data = [msg data]; + XCTAssertEqual(data.length, 9); + NSError *err = nil; + Message3Optional *msg2 = [Message3Optional parseFromData:data error:&err]; + XCTAssertNotNil(msg2); + XCTAssertNil(err); + XCTAssertTrue(msg2.hasOptionalSfixed64); + XCTAssertEqualObjects(msg, msg2); + [msg release]; + } + + { // optionalFloat + Message3Optional *msg = [[Message3Optional alloc] init]; + NSData *data = [msg data]; + XCTAssertEqual([data length], 0U); + msg.optionalFloat = 0.0f; + data = [msg data]; + XCTAssertEqual(data.length, 5); + NSError *err = nil; + Message3Optional *msg2 = [Message3Optional parseFromData:data error:&err]; + XCTAssertNotNil(msg2); + XCTAssertNil(err); + XCTAssertTrue(msg2.hasOptionalFloat); + XCTAssertEqualObjects(msg, msg2); + [msg release]; + } + + { // optionalDouble + Message3Optional *msg = [[Message3Optional alloc] init]; + NSData *data = [msg data]; + XCTAssertEqual([data length], 0U); + msg.optionalDouble = 0.0; + data = [msg data]; + XCTAssertEqual(data.length, 9); + NSError *err = nil; + Message3Optional *msg2 = [Message3Optional parseFromData:data error:&err]; + XCTAssertNotNil(msg2); + XCTAssertNil(err); + XCTAssertTrue(msg2.hasOptionalDouble); + XCTAssertEqualObjects(msg, msg2); + [msg release]; + } + + { // optionalBool + Message3Optional *msg = [[Message3Optional alloc] init]; + NSData *data = [msg data]; + XCTAssertEqual([data length], 0U); + msg.optionalBool = NO; + data = [msg data]; + XCTAssertEqual(data.length, 2); + NSError *err = nil; + Message3Optional *msg2 = [Message3Optional parseFromData:data error:&err]; + XCTAssertNotNil(msg2); + XCTAssertNil(err); + XCTAssertTrue(msg2.hasOptionalBool); + XCTAssertEqualObjects(msg, msg2); + [msg release]; + } + + { // optionalString + Message3Optional *msg = [[Message3Optional alloc] init]; + NSData *data = [msg data]; + XCTAssertEqual([data length], 0U); + msg.optionalString = @""; + data = [msg data]; + XCTAssertEqual(data.length, 2); + NSError *err = nil; + Message3Optional *msg2 = [Message3Optional parseFromData:data error:&err]; + XCTAssertNotNil(msg2); + XCTAssertNil(err); + XCTAssertTrue(msg2.hasOptionalString); + XCTAssertEqualObjects(msg, msg2); + [msg release]; + } + + { // optionalBytes + Message3Optional *msg = [[Message3Optional alloc] init]; + NSData *data = [msg data]; + XCTAssertEqual([data length], 0U); + msg.optionalBytes = [NSData data]; + data = [msg data]; + XCTAssertEqual(data.length, 2); + NSError *err = nil; + Message3Optional *msg2 = [Message3Optional parseFromData:data error:&err]; + XCTAssertNotNil(msg2); + XCTAssertNil(err); + XCTAssertTrue(msg2.hasOptionalBytes); + XCTAssertEqualObjects(msg, msg2); + [msg release]; + } + + // + // Test doesn't apply to optionalMessage (no groups in proto3). + // + + { // optionalEnum + Message3Optional *msg = [[Message3Optional alloc] init]; + NSData *data = [msg data]; + XCTAssertEqual([data length], 0U); + msg.optionalEnum = Message3Optional_Enum_Foo; + data = [msg data]; + XCTAssertEqual(data.length, 3); + NSError *err = nil; + Message3Optional *msg2 = [Message3Optional parseFromData:data error:&err]; + XCTAssertNotNil(msg2); + XCTAssertNil(err); + XCTAssertTrue(msg2.hasOptionalEnum); + XCTAssertEqualObjects(msg, msg2); + [msg release]; + } + +// clang-format on +//%PDDM-EXPAND-END PROTO3_TEST_SERIALIZE_OPTIONAL_FIELDS() +} + - (void)testProto2UnknownEnumToUnknownField { Message3 *orig = [[Message3 alloc] init]; diff --git a/objectivec/Tests/unittest_runtime_proto3.proto b/objectivec/Tests/unittest_runtime_proto3.proto index ad2e3620d3..c2ee5fb52f 100644 --- a/objectivec/Tests/unittest_runtime_proto3.proto +++ b/objectivec/Tests/unittest_runtime_proto3.proto @@ -119,3 +119,31 @@ message Message3 { map map_int32_enum = 87; map map_int32_message = 88; } + +message Message3Optional { + enum Enum { + FOO = 0; + BAR = 1; + BAZ = 2; + EXTRA_3 = 30; + } + + optional int32 optional_int32 = 1; + optional int64 optional_int64 = 2; + optional uint32 optional_uint32 = 3; + optional uint64 optional_uint64 = 4; + optional sint32 optional_sint32 = 5; + optional sint64 optional_sint64 = 6; + optional fixed32 optional_fixed32 = 7; + optional fixed64 optional_fixed64 = 8; + optional sfixed32 optional_sfixed32 = 9; + optional sfixed64 optional_sfixed64 = 10; + optional float optional_float = 11; + optional double optional_double = 12; + optional bool optional_bool = 13; + optional string optional_string = 14; + optional bytes optional_bytes = 15; + // No 'group' in proto3. + optional Message3 optional_message = 18; + optional Enum optional_enum = 19; +} From dddeed298bf84505f4d123a068f911025b351661 Mon Sep 17 00:00:00 2001 From: Thomas Van Lenten Date: Fri, 24 Apr 2020 13:40:59 -0400 Subject: [PATCH 37/38] [ObjC] Typos and comment improvements. --- objectivec/GPBDescriptor.m | 5 +++-- objectivec/GPBDescriptor_PackagePrivate.h | 4 ++-- objectivec/GPBUtilities.h | 2 +- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/objectivec/GPBDescriptor.m b/objectivec/GPBDescriptor.m index bb178138aa..c29b95539f 100644 --- a/objectivec/GPBDescriptor.m +++ b/objectivec/GPBDescriptor.m @@ -508,7 +508,8 @@ uint32_t GPBFieldAlternateTag(GPBFieldDescriptor *self) { BOOL isMessage = GPBDataTypeIsMessage(dataType); BOOL isMapOrArray = GPBFieldIsMapOrArray(self); - // If proto3 optionals weren't know, compute the flag for the rest of the runtime. + // If proto3 optionals weren't known (i.e. generated code from an + // older version), compute the flag for the rest of the runtime. if (!proto3OptionalKnown) { // If it was... // - proto3 syntax @@ -530,7 +531,7 @@ uint32_t GPBFieldAlternateTag(GPBFieldDescriptor *self) { // autocreation. hasOrCountSel_ = SelFromStrings(NULL, coreDesc->name, "_Count", NO); } else { - // Know it is a single field; it gets has/setHas selectors if... + // It is a single field; it gets has/setHas selectors if... // - not in a oneof (negative has index) // - not clearing on zero if ((coreDesc->hasIndex >= 0) && diff --git a/objectivec/GPBDescriptor_PackagePrivate.h b/objectivec/GPBDescriptor_PackagePrivate.h index 467504f16a..b3d673043c 100644 --- a/objectivec/GPBDescriptor_PackagePrivate.h +++ b/objectivec/GPBDescriptor_PackagePrivate.h @@ -155,9 +155,9 @@ typedef NS_OPTIONS(uint32_t, GPBDescriptorInitializationFlags) { // breaking change in the runtime. GPBDescriptorInitializationFlag_UsesClassRefs = 1 << 2, - // This flag is used to indicate that the generated sources already containg + // This flag is used to indicate that the generated sources already contain // the `GPBFieldClearHasIvarOnZero` flag and it doesn't have to be computed - // at startup, this allows older generated code to still work with the + // at startup. This allows older generated code to still work with the // current runtime library. GPBDescriptorInitializationFlag_Proto3OptionalKnown = 1 << 3, }; diff --git a/objectivec/GPBUtilities.h b/objectivec/GPBUtilities.h index 828fd16297..75759b2334 100644 --- a/objectivec/GPBUtilities.h +++ b/objectivec/GPBUtilities.h @@ -95,7 +95,7 @@ BOOL GPBMessageHasFieldSet(GPBMessage *self, GPBFieldDescriptor *field); void GPBClearMessageField(GPBMessage *self, GPBFieldDescriptor *field); /** - * Clears the given onoof field for the given message. + * Clears the given oneof field for the given message. * * @param self The message for which to clear the field. * @param oneof The oneof to clear. From 4059c61f27eb1b06c4ee979546a238be792df0a4 Mon Sep 17 00:00:00 2001 From: Greg Steuck Date: Mon, 27 Apr 2020 08:21:52 -0700 Subject: [PATCH 38/38] Typo in 'disciplines' (#7423) --- docs/field_presence.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/field_presence.md b/docs/field_presence.md index 0491b820d6..4ce778552b 100644 --- a/docs/field_presence.md +++ b/docs/field_presence.md @@ -1,6 +1,6 @@ # Application note: Field presence -This application note explains the various presence tracking disciplies for protobuf fields. It also explains how to enable experimental support for explicit presence tracking for singular proto3 fields with basic types. +This application note explains the various presence tracking disciplines for protobuf fields. It also explains how to enable experimental support for explicit presence tracking for singular proto3 fields with basic types. ## Background