google-protobuf 3.21.10 → 3.25.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/ext/google/protobuf_c/Rakefile +3 -0
- data/ext/google/protobuf_c/convert.c +23 -70
- data/ext/google/protobuf_c/convert.h +3 -28
- data/ext/google/protobuf_c/defs.c +178 -55
- data/ext/google/protobuf_c/defs.h +3 -28
- data/ext/google/protobuf_c/extconf.rb +4 -4
- data/ext/google/protobuf_c/glue.c +56 -0
- data/ext/google/protobuf_c/map.c +54 -70
- data/ext/google/protobuf_c/map.h +6 -28
- data/ext/google/protobuf_c/message.c +178 -161
- data/ext/google/protobuf_c/message.h +10 -28
- data/ext/google/protobuf_c/protobuf.c +39 -176
- data/ext/google/protobuf_c/protobuf.h +24 -32
- data/ext/google/protobuf_c/repeated_field.c +28 -29
- data/ext/google/protobuf_c/repeated_field.h +6 -28
- data/ext/google/protobuf_c/ruby-upb.c +12326 -9027
- data/ext/google/protobuf_c/ruby-upb.h +11950 -4518
- data/ext/google/protobuf_c/shared_convert.c +64 -0
- data/ext/google/protobuf_c/shared_convert.h +26 -0
- data/ext/google/protobuf_c/shared_message.c +65 -0
- data/ext/google/protobuf_c/shared_message.h +25 -0
- data/ext/google/protobuf_c/third_party/utf8_range/LICENSE +1 -0
- data/ext/google/protobuf_c/third_party/utf8_range/naive.c +0 -0
- data/ext/google/protobuf_c/third_party/utf8_range/range2-neon.c +1 -1
- data/ext/google/protobuf_c/third_party/utf8_range/range2-sse.c +0 -0
- data/ext/google/protobuf_c/third_party/utf8_range/utf8_range.h +13 -1
- data/ext/google/protobuf_c/wrap_memcpy.c +3 -26
- data/lib/google/protobuf/any_pb.rb +24 -5
- data/lib/google/protobuf/api_pb.rb +26 -23
- data/lib/google/protobuf/descriptor_dsl.rb +0 -0
- data/lib/google/protobuf/descriptor_pb.rb +43 -226
- data/lib/google/protobuf/duration_pb.rb +24 -5
- data/lib/google/protobuf/empty_pb.rb +24 -3
- data/lib/google/protobuf/ffi/descriptor.rb +165 -0
- data/lib/google/protobuf/ffi/descriptor_pool.rb +75 -0
- data/lib/google/protobuf/ffi/enum_descriptor.rb +171 -0
- data/lib/google/protobuf/ffi/ffi.rb +213 -0
- data/lib/google/protobuf/ffi/field_descriptor.rb +319 -0
- data/lib/google/protobuf/ffi/file_descriptor.rb +59 -0
- data/lib/google/protobuf/ffi/internal/arena.rb +66 -0
- data/lib/google/protobuf/ffi/internal/convert.rb +305 -0
- data/lib/google/protobuf/ffi/internal/pointer_helper.rb +35 -0
- data/lib/google/protobuf/ffi/internal/type_safety.rb +25 -0
- data/lib/google/protobuf/ffi/map.rb +407 -0
- data/lib/google/protobuf/ffi/message.rb +662 -0
- data/lib/google/protobuf/ffi/object_cache.rb +30 -0
- data/lib/google/protobuf/ffi/oneof_descriptor.rb +95 -0
- data/lib/google/protobuf/ffi/repeated_field.rb +383 -0
- data/lib/google/protobuf/field_mask_pb.rb +24 -4
- data/lib/google/protobuf/message_exts.rb +8 -26
- data/lib/google/protobuf/object_cache.rb +97 -0
- data/lib/google/protobuf/plugin_pb.rb +47 -0
- data/lib/google/protobuf/repeated_field.rb +3 -26
- data/lib/google/protobuf/source_context_pb.rb +24 -4
- data/lib/google/protobuf/struct_pb.rb +24 -20
- data/lib/google/protobuf/timestamp_pb.rb +24 -5
- data/lib/google/protobuf/type_pb.rb +26 -68
- data/lib/google/protobuf/well_known_types.rb +5 -34
- data/lib/google/protobuf/wrappers_pb.rb +24 -28
- data/lib/google/protobuf.rb +27 -45
- data/lib/google/protobuf_ffi.rb +50 -0
- data/lib/google/protobuf_native.rb +20 -0
- data/lib/google/tasks/ffi.rake +102 -0
- metadata +75 -12
- data/tests/basic.rb +0 -739
- data/tests/generated_code_test.rb +0 -23
- data/tests/stress.rb +0 -38
@@ -1,32 +1,9 @@
|
|
1
1
|
// Protocol Buffers - Google's data interchange format
|
2
2
|
// Copyright 2014 Google Inc. All rights reserved.
|
3
|
-
// https://developers.google.com/protocol-buffers/
|
4
3
|
//
|
5
|
-
//
|
6
|
-
//
|
7
|
-
//
|
8
|
-
//
|
9
|
-
// * Redistributions of source code must retain the above copyright
|
10
|
-
// notice, this list of conditions and the following disclaimer.
|
11
|
-
// * Redistributions in binary form must reproduce the above
|
12
|
-
// copyright notice, this list of conditions and the following disclaimer
|
13
|
-
// in the documentation and/or other materials provided with the
|
14
|
-
// distribution.
|
15
|
-
// * Neither the name of Google Inc. nor the names of its
|
16
|
-
// contributors may be used to endorse or promote products derived from
|
17
|
-
// this software without specific prior written permission.
|
18
|
-
//
|
19
|
-
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
20
|
-
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
21
|
-
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
22
|
-
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
23
|
-
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
24
|
-
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
25
|
-
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
26
|
-
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
27
|
-
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
28
|
-
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
29
|
-
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
4
|
+
// Use of this source code is governed by a BSD-style
|
5
|
+
// license that can be found in the LICENSE file or at
|
6
|
+
// https://developers.google.com/open-source/licenses/bsd
|
30
7
|
|
31
8
|
#include "message.h"
|
32
9
|
|
@@ -35,8 +12,10 @@
|
|
35
12
|
#include "map.h"
|
36
13
|
#include "protobuf.h"
|
37
14
|
#include "repeated_field.h"
|
15
|
+
#include "shared_message.h"
|
38
16
|
|
39
17
|
static VALUE cParseError = Qnil;
|
18
|
+
static VALUE cAbstractMessage = Qnil;
|
40
19
|
static ID descriptor_instancevar_interned;
|
41
20
|
|
42
21
|
static VALUE initialize_rb_class_with_no_args(VALUE klass) {
|
@@ -52,6 +31,8 @@ VALUE MessageOrEnum_GetDescriptor(VALUE klass) {
|
|
52
31
|
// -----------------------------------------------------------------------------
|
53
32
|
|
54
33
|
typedef struct {
|
34
|
+
// IMPORTANT: WB_PROTECTED objects must only use the RB_OBJ_WRITE()
|
35
|
+
// macro to update VALUE references, as to trigger write barriers.
|
55
36
|
VALUE arena;
|
56
37
|
const upb_Message* msg; // Can get as mutable when non-frozen.
|
57
38
|
const upb_MessageDef*
|
@@ -64,9 +45,9 @@ static void Message_mark(void* _self) {
|
|
64
45
|
}
|
65
46
|
|
66
47
|
static rb_data_type_t Message_type = {
|
67
|
-
"Message",
|
48
|
+
"Google::Protobuf::Message",
|
68
49
|
{Message_mark, RUBY_DEFAULT_FREE, NULL},
|
69
|
-
.flags = RUBY_TYPED_FREE_IMMEDIATELY,
|
50
|
+
.flags = RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
|
70
51
|
};
|
71
52
|
|
72
53
|
static Message* ruby_to_Message(VALUE msg_rb) {
|
@@ -104,8 +85,10 @@ upb_Message* Message_GetMutable(VALUE msg_rb, const upb_MessageDef** m) {
|
|
104
85
|
void Message_InitPtr(VALUE self_, upb_Message* msg, VALUE arena) {
|
105
86
|
Message* self = ruby_to_Message(self_);
|
106
87
|
self->msg = msg;
|
107
|
-
self->arena
|
108
|
-
|
88
|
+
RB_OBJ_WRITE(self_, &self->arena, arena);
|
89
|
+
VALUE stored = ObjectCache_TryAdd(msg, self_);
|
90
|
+
(void)stored;
|
91
|
+
PBRUBY_ASSERT(stored == self_);
|
109
92
|
}
|
110
93
|
|
111
94
|
VALUE Message_GetArena(VALUE msg_rb) {
|
@@ -145,7 +128,8 @@ void Message_PrintMessage(StringBuilder* b, const upb_Message* msg,
|
|
145
128
|
for (int i = 0; i < n; i++) {
|
146
129
|
const upb_FieldDef* field = upb_MessageDef_Field(m, i);
|
147
130
|
|
148
|
-
if (upb_FieldDef_HasPresence(field) &&
|
131
|
+
if (upb_FieldDef_HasPresence(field) &&
|
132
|
+
!upb_Message_HasFieldByDef(msg, field)) {
|
149
133
|
continue;
|
150
134
|
}
|
151
135
|
|
@@ -155,7 +139,7 @@ void Message_PrintMessage(StringBuilder* b, const upb_Message* msg,
|
|
155
139
|
first = false;
|
156
140
|
}
|
157
141
|
|
158
|
-
upb_MessageValue msgval =
|
142
|
+
upb_MessageValue msgval = upb_Message_GetFieldByDef(msg, field);
|
159
143
|
|
160
144
|
StringBuilder_Printf(b, "%s: ", upb_FieldDef_Name(field));
|
161
145
|
|
@@ -241,15 +225,6 @@ static int extract_method_call(VALUE method_name, Message* self,
|
|
241
225
|
if (Match(m, name, f, o, "clear_", "")) return METHOD_CLEAR;
|
242
226
|
if (Match(m, name, f, o, "has_", "?") &&
|
243
227
|
(*o || (*f && upb_FieldDef_HasPresence(*f)))) {
|
244
|
-
// Disallow oneof hazzers for proto3.
|
245
|
-
// TODO(haberman): remove this test when we are enabling oneof hazzers for
|
246
|
-
// proto3.
|
247
|
-
if (*f && !upb_FieldDef_IsSubMessage(*f) &&
|
248
|
-
upb_FieldDef_RealContainingOneof(*f) &&
|
249
|
-
upb_MessageDef_Syntax(upb_FieldDef_ContainingType(*f)) !=
|
250
|
-
kUpb_Syntax_Proto2) {
|
251
|
-
return METHOD_UNKNOWN;
|
252
|
-
}
|
253
228
|
return METHOD_PRESENCE;
|
254
229
|
}
|
255
230
|
if (Match(m, name, f, o, "", "_as_value") && *f &&
|
@@ -278,7 +253,8 @@ static VALUE Message_oneof_accessor(VALUE _self, const upb_OneofDef* o,
|
|
278
253
|
return oneof_field == NULL ? Qfalse : Qtrue;
|
279
254
|
case METHOD_CLEAR:
|
280
255
|
if (oneof_field != NULL) {
|
281
|
-
|
256
|
+
upb_Message_ClearFieldByDef(Message_GetMutable(_self, NULL),
|
257
|
+
oneof_field);
|
282
258
|
}
|
283
259
|
return Qnil;
|
284
260
|
case METHOD_GETTER:
|
@@ -301,13 +277,13 @@ static void Message_setfield(upb_Message* msg, const upb_FieldDef* f, VALUE val,
|
|
301
277
|
} else {
|
302
278
|
if (val == Qnil &&
|
303
279
|
(upb_FieldDef_IsSubMessage(f) || upb_FieldDef_RealContainingOneof(f))) {
|
304
|
-
|
280
|
+
upb_Message_ClearFieldByDef(msg, f);
|
305
281
|
return;
|
306
282
|
}
|
307
283
|
msgval =
|
308
284
|
Convert_RubyToUpb(val, upb_FieldDef_Name(f), TypeInfo_get(f), arena);
|
309
285
|
}
|
310
|
-
|
286
|
+
upb_Message_SetFieldByDef(msg, f, msgval, arena);
|
311
287
|
}
|
312
288
|
|
313
289
|
VALUE Message_getfield(VALUE _self, const upb_FieldDef* f) {
|
@@ -329,12 +305,12 @@ VALUE Message_getfield(VALUE _self, const upb_FieldDef* f) {
|
|
329
305
|
upb_Array* arr = upb_Message_Mutable(msg, f, arena).array;
|
330
306
|
return RepeatedField_GetRubyWrapper(arr, TypeInfo_get(f), self->arena);
|
331
307
|
} else if (upb_FieldDef_IsSubMessage(f)) {
|
332
|
-
if (!
|
308
|
+
if (!upb_Message_HasFieldByDef(self->msg, f)) return Qnil;
|
333
309
|
upb_Message* submsg = upb_Message_Mutable(msg, f, arena).msg;
|
334
310
|
const upb_MessageDef* m = upb_FieldDef_MessageSubDef(f);
|
335
311
|
return Message_GetRubyWrapper(submsg, m, self->arena);
|
336
312
|
} else {
|
337
|
-
upb_MessageValue msgval =
|
313
|
+
upb_MessageValue msgval = upb_Message_GetFieldByDef(self->msg, f);
|
338
314
|
return Convert_UpbToRuby(msgval, TypeInfo_get(f), self->arena);
|
339
315
|
}
|
340
316
|
}
|
@@ -348,23 +324,24 @@ static VALUE Message_field_accessor(VALUE _self, const upb_FieldDef* f,
|
|
348
324
|
Message_setfield(Message_GetMutable(_self, NULL), f, argv[1], arena);
|
349
325
|
return Qnil;
|
350
326
|
case METHOD_CLEAR:
|
351
|
-
|
327
|
+
upb_Message_ClearFieldByDef(Message_GetMutable(_self, NULL), f);
|
352
328
|
return Qnil;
|
353
329
|
case METHOD_PRESENCE:
|
354
330
|
if (!upb_FieldDef_HasPresence(f)) {
|
355
331
|
rb_raise(rb_eRuntimeError, "Field does not have presence.");
|
356
332
|
}
|
357
|
-
return
|
333
|
+
return upb_Message_HasFieldByDef(Message_Get(_self, NULL), f);
|
358
334
|
case METHOD_WRAPPER_GETTER: {
|
359
335
|
Message* self = ruby_to_Message(_self);
|
360
|
-
if (
|
336
|
+
if (upb_Message_HasFieldByDef(self->msg, f)) {
|
361
337
|
PBRUBY_ASSERT(upb_FieldDef_IsSubMessage(f) &&
|
362
338
|
!upb_FieldDef_IsRepeated(f));
|
363
|
-
upb_MessageValue wrapper =
|
339
|
+
upb_MessageValue wrapper = upb_Message_GetFieldByDef(self->msg, f);
|
364
340
|
const upb_MessageDef* wrapper_m = upb_FieldDef_MessageSubDef(f);
|
365
341
|
const upb_FieldDef* value_f =
|
366
342
|
upb_MessageDef_FindFieldByNumber(wrapper_m, 1);
|
367
|
-
upb_MessageValue value =
|
343
|
+
upb_MessageValue value =
|
344
|
+
upb_Message_GetFieldByDef(wrapper.msg_val, value_f);
|
368
345
|
return Convert_UpbToRuby(value, TypeInfo_get(value_f), self->arena);
|
369
346
|
} else {
|
370
347
|
return Qnil;
|
@@ -373,19 +350,20 @@ static VALUE Message_field_accessor(VALUE _self, const upb_FieldDef* f,
|
|
373
350
|
case METHOD_WRAPPER_SETTER: {
|
374
351
|
upb_Message* msg = Message_GetMutable(_self, NULL);
|
375
352
|
if (argv[1] == Qnil) {
|
376
|
-
|
353
|
+
upb_Message_ClearFieldByDef(msg, f);
|
377
354
|
} else {
|
378
355
|
const upb_FieldDef* val_f =
|
379
356
|
upb_MessageDef_FindFieldByNumber(upb_FieldDef_MessageSubDef(f), 1);
|
380
357
|
upb_MessageValue msgval = Convert_RubyToUpb(
|
381
358
|
argv[1], upb_FieldDef_Name(f), TypeInfo_get(val_f), arena);
|
382
359
|
upb_Message* wrapper = upb_Message_Mutable(msg, f, arena).msg;
|
383
|
-
|
360
|
+
upb_Message_SetFieldByDef(wrapper, val_f, msgval, arena);
|
384
361
|
}
|
385
362
|
return Qnil;
|
386
363
|
}
|
387
364
|
case METHOD_ENUM_GETTER: {
|
388
|
-
upb_MessageValue msgval =
|
365
|
+
upb_MessageValue msgval =
|
366
|
+
upb_Message_GetFieldByDef(Message_Get(_self, NULL), f);
|
389
367
|
|
390
368
|
if (upb_FieldDef_Label(f) == kUpb_Label_Repeated) {
|
391
369
|
// Map repeated fields to a new type with ints
|
@@ -510,8 +488,8 @@ static int Map_initialize_kwarg(VALUE key, VALUE val, VALUE _self) {
|
|
510
488
|
k = Convert_RubyToUpb(key, "", map_init->key_type, NULL);
|
511
489
|
|
512
490
|
if (map_init->val_type.type == kUpb_CType_Message && TYPE(val) == T_HASH) {
|
513
|
-
|
514
|
-
|
491
|
+
upb_MiniTable* t = upb_MessageDef_MiniTable(map_init->val_type.def.msgdef);
|
492
|
+
upb_Message* msg = upb_Message_New(t, map_init->arena);
|
515
493
|
Message_InitFromValue(msg, map_init->val_type.def.msgdef, val,
|
516
494
|
map_init->arena);
|
517
495
|
v.msg_val = msg;
|
@@ -541,7 +519,8 @@ static upb_MessageValue MessageValue_FromValue(VALUE val, TypeInfo info,
|
|
541
519
|
upb_Arena* arena) {
|
542
520
|
if (info.type == kUpb_CType_Message) {
|
543
521
|
upb_MessageValue msgval;
|
544
|
-
|
522
|
+
upb_MiniTable* t = upb_MessageDef_MiniTable(info.def.msgdef);
|
523
|
+
upb_Message* msg = upb_Message_New(t, arena);
|
545
524
|
Message_InitFromValue(msg, info.def.msgdef, val, arena);
|
546
525
|
msgval.msg_val = msg;
|
547
526
|
return msgval;
|
@@ -593,7 +572,7 @@ static void Message_InitFieldFromValue(upb_Message* msg, const upb_FieldDef* f,
|
|
593
572
|
} else {
|
594
573
|
upb_MessageValue msgval =
|
595
574
|
Convert_RubyToUpb(val, upb_FieldDef_Name(f), TypeInfo_get(f), arena);
|
596
|
-
|
575
|
+
upb_Message_SetFieldByDef(msg, f, msgval, arena);
|
597
576
|
}
|
598
577
|
}
|
599
578
|
|
@@ -656,7 +635,8 @@ static VALUE Message_initialize(int argc, VALUE* argv, VALUE _self) {
|
|
656
635
|
Message* self = ruby_to_Message(_self);
|
657
636
|
VALUE arena_rb = Arena_new();
|
658
637
|
upb_Arena* arena = Arena_get(arena_rb);
|
659
|
-
|
638
|
+
upb_MiniTable* t = upb_MessageDef_MiniTable(self->msgdef);
|
639
|
+
upb_Message* msg = upb_Message_New(t, arena);
|
660
640
|
|
661
641
|
Message_InitPtr(_self, msg, arena_rb);
|
662
642
|
|
@@ -682,8 +662,8 @@ static VALUE Message_dup(VALUE _self) {
|
|
682
662
|
Message* new_msg_self = ruby_to_Message(new_msg);
|
683
663
|
size_t size = upb_MessageDef_MiniTable(self->msgdef)->size;
|
684
664
|
|
685
|
-
// TODO
|
686
|
-
// TODO
|
665
|
+
// TODO
|
666
|
+
// TODO
|
687
667
|
memcpy((upb_Message*)new_msg_self->msg, self->msg, size);
|
688
668
|
Arena_fuse(self->arena, Arena_get(new_msg_self->arena));
|
689
669
|
return new_msg;
|
@@ -692,24 +672,13 @@ static VALUE Message_dup(VALUE _self) {
|
|
692
672
|
// Support function for Message_eq, and also used by other #eq functions.
|
693
673
|
bool Message_Equal(const upb_Message* m1, const upb_Message* m2,
|
694
674
|
const upb_MessageDef* m) {
|
695
|
-
|
696
|
-
|
697
|
-
|
698
|
-
|
699
|
-
|
700
|
-
const upb_MiniTable* layout = upb_MessageDef_MiniTable(m);
|
701
|
-
|
702
|
-
// Compare deterministically serialized payloads with no unknown fields.
|
703
|
-
char* data1 = upb_Encode(m1, layout, encode_opts, arena_tmp, &size1);
|
704
|
-
char* data2 = upb_Encode(m2, layout, encode_opts, arena_tmp, &size2);
|
705
|
-
|
706
|
-
if (data1 && data2) {
|
707
|
-
bool ret = (size1 == size2) && (memcmp(data1, data2, size1) == 0);
|
708
|
-
upb_Arena_Free(arena_tmp);
|
709
|
-
return ret;
|
675
|
+
upb_Status status;
|
676
|
+
upb_Status_Clear(&status);
|
677
|
+
bool return_value = shared_Message_Equal(m1, m2, m, &status);
|
678
|
+
if (upb_Status_IsOk(&status)) {
|
679
|
+
return return_value;
|
710
680
|
} else {
|
711
|
-
|
712
|
-
rb_raise(cParseError, "Error comparing messages");
|
681
|
+
rb_raise(cParseError, upb_Status_ErrorMessage(&status));
|
713
682
|
}
|
714
683
|
}
|
715
684
|
|
@@ -734,22 +703,13 @@ static VALUE Message_eq(VALUE _self, VALUE _other) {
|
|
734
703
|
|
735
704
|
uint64_t Message_Hash(const upb_Message* msg, const upb_MessageDef* m,
|
736
705
|
uint64_t seed) {
|
737
|
-
|
738
|
-
|
739
|
-
|
740
|
-
|
741
|
-
|
742
|
-
data = upb_Encode(msg, upb_MessageDef_MiniTable(m),
|
743
|
-
kUpb_Encode_SkipUnknown | kUpb_Encode_Deterministic, arena,
|
744
|
-
&size);
|
745
|
-
|
746
|
-
if (data) {
|
747
|
-
uint64_t ret = _upb_Hash(data, size, seed);
|
748
|
-
upb_Arena_Free(arena);
|
749
|
-
return ret;
|
706
|
+
upb_Status status;
|
707
|
+
upb_Status_Clear(&status);
|
708
|
+
uint64_t return_value = shared_Message_Hash(msg, m, seed, &status);
|
709
|
+
if (upb_Status_IsOk(&status)) {
|
710
|
+
return return_value;
|
750
711
|
} else {
|
751
|
-
|
752
|
-
rb_raise(cParseError, "Error calculating hash");
|
712
|
+
rb_raise(cParseError, upb_Status_ErrorMessage(&status));
|
753
713
|
}
|
754
714
|
}
|
755
715
|
|
@@ -823,7 +783,8 @@ static VALUE Message_CreateHash(const upb_Message* msg,
|
|
823
783
|
VALUE msg_key;
|
824
784
|
|
825
785
|
if (!is_proto2 && upb_FieldDef_IsSubMessage(field) &&
|
826
|
-
!upb_FieldDef_IsRepeated(field) &&
|
786
|
+
!upb_FieldDef_IsRepeated(field) &&
|
787
|
+
!upb_Message_HasFieldByDef(msg, field)) {
|
827
788
|
// TODO: Legacy behavior, remove when we fix the is_proto2 differences.
|
828
789
|
msg_key = ID2SYM(rb_intern(upb_FieldDef_Name(field)));
|
829
790
|
rb_hash_aset(hash, msg_key, Qnil);
|
@@ -832,12 +793,12 @@ static VALUE Message_CreateHash(const upb_Message* msg,
|
|
832
793
|
|
833
794
|
// Do not include fields that are not present (oneof or optional fields).
|
834
795
|
if (is_proto2 && upb_FieldDef_HasPresence(field) &&
|
835
|
-
!
|
796
|
+
!upb_Message_HasFieldByDef(msg, field)) {
|
836
797
|
continue;
|
837
798
|
}
|
838
799
|
|
839
800
|
msg_key = ID2SYM(rb_intern(upb_FieldDef_Name(field)));
|
840
|
-
msgval =
|
801
|
+
msgval = upb_Message_GetFieldByDef(msg, field);
|
841
802
|
|
842
803
|
// Proto2 omits empty map/repeated filds also.
|
843
804
|
|
@@ -898,6 +859,32 @@ static VALUE Message_freeze(VALUE _self) {
|
|
898
859
|
return _self;
|
899
860
|
}
|
900
861
|
|
862
|
+
/*
|
863
|
+
* Deep freezes the message object recursively.
|
864
|
+
* Internal use only.
|
865
|
+
*/
|
866
|
+
VALUE Message_internal_deep_freeze(VALUE _self) {
|
867
|
+
Message* self = ruby_to_Message(_self);
|
868
|
+
Message_freeze(_self);
|
869
|
+
|
870
|
+
int n = upb_MessageDef_FieldCount(self->msgdef);
|
871
|
+
for (int i = 0; i < n; i++) {
|
872
|
+
const upb_FieldDef* f = upb_MessageDef_Field(self->msgdef, i);
|
873
|
+
VALUE field = Message_getfield(_self, f);
|
874
|
+
|
875
|
+
if (field != Qnil) {
|
876
|
+
if (upb_FieldDef_IsMap(f)) {
|
877
|
+
Map_internal_deep_freeze(field);
|
878
|
+
} else if (upb_FieldDef_IsRepeated(f)) {
|
879
|
+
RepeatedField_internal_deep_freeze(field);
|
880
|
+
} else if (upb_FieldDef_IsSubMessage(f)) {
|
881
|
+
Message_internal_deep_freeze(field);
|
882
|
+
}
|
883
|
+
}
|
884
|
+
}
|
885
|
+
return _self;
|
886
|
+
}
|
887
|
+
|
901
888
|
/*
|
902
889
|
* call-seq:
|
903
890
|
* Message.[](index) => value
|
@@ -940,7 +927,7 @@ static VALUE Message_index_set(VALUE _self, VALUE field_name, VALUE value) {
|
|
940
927
|
}
|
941
928
|
|
942
929
|
val = Convert_RubyToUpb(value, upb_FieldDef_Name(f), TypeInfo_get(f), arena);
|
943
|
-
|
930
|
+
upb_Message_SetFieldByDef(Message_GetMutable(_self, NULL), f, val, arena);
|
944
931
|
|
945
932
|
return Qnil;
|
946
933
|
}
|
@@ -950,7 +937,7 @@ static VALUE Message_index_set(VALUE _self, VALUE field_name, VALUE value) {
|
|
950
937
|
* MessageClass.decode(data, options) => message
|
951
938
|
*
|
952
939
|
* Decodes the given data (as a string containing bytes in protocol buffers wire
|
953
|
-
* format) under the
|
940
|
+
* format) under the interpretation given by this message class's definition
|
954
941
|
* and returns a message object with the corresponding field values.
|
955
942
|
* @param options [Hash] options for the decoder
|
956
943
|
* recursion_limit: set to maximum decoding depth for message (default is 64)
|
@@ -969,10 +956,11 @@ static VALUE Message_decode(int argc, VALUE* argv, VALUE klass) {
|
|
969
956
|
rb_raise(rb_eArgError, "Expected hash arguments.");
|
970
957
|
}
|
971
958
|
|
972
|
-
VALUE depth =
|
959
|
+
VALUE depth =
|
960
|
+
rb_hash_lookup(hash_args, ID2SYM(rb_intern("recursion_limit")));
|
973
961
|
|
974
962
|
if (depth != Qnil && TYPE(depth) == T_FIXNUM) {
|
975
|
-
options |=
|
963
|
+
options |= upb_DecodeOptions_MaxDepth(FIX2INT(depth));
|
976
964
|
}
|
977
965
|
}
|
978
966
|
|
@@ -980,17 +968,27 @@ static VALUE Message_decode(int argc, VALUE* argv, VALUE klass) {
|
|
980
968
|
rb_raise(rb_eArgError, "Expected string for binary protobuf data.");
|
981
969
|
}
|
982
970
|
|
971
|
+
return Message_decode_bytes(RSTRING_LEN(data), RSTRING_PTR(data), options,
|
972
|
+
klass, /*freeze*/ false);
|
973
|
+
}
|
974
|
+
|
975
|
+
VALUE Message_decode_bytes(int size, const char* bytes, int options,
|
976
|
+
VALUE klass, bool freeze) {
|
983
977
|
VALUE msg_rb = initialize_rb_class_with_no_args(klass);
|
984
978
|
Message* msg = ruby_to_Message(msg_rb);
|
985
979
|
|
986
|
-
|
987
|
-
|
988
|
-
|
989
|
-
|
980
|
+
const upb_FileDef* file = upb_MessageDef_File(msg->msgdef);
|
981
|
+
const upb_ExtensionRegistry* extreg =
|
982
|
+
upb_DefPool_ExtensionRegistry(upb_FileDef_Pool(file));
|
983
|
+
upb_DecodeStatus status = upb_Decode(bytes, size, (upb_Message*)msg->msg,
|
984
|
+
upb_MessageDef_MiniTable(msg->msgdef),
|
985
|
+
extreg, options, Arena_get(msg->arena));
|
990
986
|
if (status != kUpb_DecodeStatus_Ok) {
|
991
987
|
rb_raise(cParseError, "Error occurred during parsing");
|
992
988
|
}
|
993
|
-
|
989
|
+
if (freeze) {
|
990
|
+
Message_internal_deep_freeze(msg_rb);
|
991
|
+
}
|
994
992
|
return msg_rb;
|
995
993
|
}
|
996
994
|
|
@@ -1011,7 +1009,7 @@ static VALUE Message_decode_json(int argc, VALUE* argv, VALUE klass) {
|
|
1011
1009
|
int options = 0;
|
1012
1010
|
upb_Status status;
|
1013
1011
|
|
1014
|
-
// TODO
|
1012
|
+
// TODO: use this message's pool instead.
|
1015
1013
|
const upb_DefPool* symtab = DescriptorPool_GetSymtab(generated_pool);
|
1016
1014
|
|
1017
1015
|
if (argc < 1 || argc > 2) {
|
@@ -1034,7 +1032,7 @@ static VALUE Message_decode_json(int argc, VALUE* argv, VALUE klass) {
|
|
1034
1032
|
rb_raise(rb_eArgError, "Expected string for JSON data.");
|
1035
1033
|
}
|
1036
1034
|
|
1037
|
-
// TODO
|
1035
|
+
// TODO: Check and respect string encoding. If not UTF-8, we need to
|
1038
1036
|
// convert, because string handlers pass data directly to message string
|
1039
1037
|
// fields.
|
1040
1038
|
|
@@ -1069,7 +1067,7 @@ static VALUE Message_decode_json(int argc, VALUE* argv, VALUE klass) {
|
|
1069
1067
|
static VALUE Message_encode(int argc, VALUE* argv, VALUE klass) {
|
1070
1068
|
Message* msg = ruby_to_Message(argv[0]);
|
1071
1069
|
int options = 0;
|
1072
|
-
|
1070
|
+
char* data;
|
1073
1071
|
size_t size;
|
1074
1072
|
|
1075
1073
|
if (CLASS_OF(argv[0]) != klass) {
|
@@ -1085,19 +1083,21 @@ static VALUE Message_encode(int argc, VALUE* argv, VALUE klass) {
|
|
1085
1083
|
if (TYPE(hash_args) != T_HASH) {
|
1086
1084
|
rb_raise(rb_eArgError, "Expected hash arguments.");
|
1087
1085
|
}
|
1088
|
-
VALUE depth =
|
1086
|
+
VALUE depth =
|
1087
|
+
rb_hash_lookup(hash_args, ID2SYM(rb_intern("recursion_limit")));
|
1089
1088
|
|
1090
1089
|
if (depth != Qnil && TYPE(depth) == T_FIXNUM) {
|
1091
|
-
options |=
|
1090
|
+
options |= upb_DecodeOptions_MaxDepth(FIX2INT(depth));
|
1092
1091
|
}
|
1093
1092
|
}
|
1094
1093
|
|
1095
|
-
upb_Arena
|
1094
|
+
upb_Arena* arena = upb_Arena_New();
|
1096
1095
|
|
1097
|
-
|
1098
|
-
|
1096
|
+
upb_EncodeStatus status =
|
1097
|
+
upb_Encode(msg->msg, upb_MessageDef_MiniTable(msg->msgdef), options,
|
1098
|
+
arena, &data, &size);
|
1099
1099
|
|
1100
|
-
if (
|
1100
|
+
if (status == kUpb_EncodeStatus_Ok) {
|
1101
1101
|
VALUE ret = rb_str_new(data, size);
|
1102
1102
|
rb_enc_associate(ret, rb_ascii8bit_encoding());
|
1103
1103
|
upb_Arena_Free(arena);
|
@@ -1125,7 +1125,7 @@ static VALUE Message_encode_json(int argc, VALUE* argv, VALUE klass) {
|
|
1125
1125
|
size_t size;
|
1126
1126
|
upb_Status status;
|
1127
1127
|
|
1128
|
-
// TODO
|
1128
|
+
// TODO: use this message's pool instead.
|
1129
1129
|
const upb_DefPool* symtab = DescriptorPool_GetSymtab(generated_pool);
|
1130
1130
|
|
1131
1131
|
if (argc < 1 || argc > 2) {
|
@@ -1135,7 +1135,8 @@ static VALUE Message_encode_json(int argc, VALUE* argv, VALUE klass) {
|
|
1135
1135
|
if (argc == 2) {
|
1136
1136
|
VALUE hash_args = argv[1];
|
1137
1137
|
if (TYPE(hash_args) != T_HASH) {
|
1138
|
-
if (RTEST(rb_funcall(hash_args, rb_intern("respond_to?"), 1,
|
1138
|
+
if (RTEST(rb_funcall(hash_args, rb_intern("respond_to?"), 1,
|
1139
|
+
rb_str_new2("to_h")))) {
|
1139
1140
|
hash_args = rb_funcall(hash_args, rb_intern("to_h"), 0);
|
1140
1141
|
} else {
|
1141
1142
|
rb_raise(rb_eArgError, "Expected hash arguments.");
|
@@ -1152,6 +1153,12 @@ static VALUE Message_encode_json(int argc, VALUE* argv, VALUE klass) {
|
|
1152
1153
|
Qfalse))) {
|
1153
1154
|
options |= upb_JsonEncode_EmitDefaults;
|
1154
1155
|
}
|
1156
|
+
|
1157
|
+
if (RTEST(rb_hash_lookup2(hash_args,
|
1158
|
+
ID2SYM(rb_intern("format_enums_as_integers")),
|
1159
|
+
Qfalse))) {
|
1160
|
+
options |= upb_JsonEncode_FormatEnumsAsIntegers;
|
1161
|
+
}
|
1155
1162
|
}
|
1156
1163
|
|
1157
1164
|
upb_Status_Clear(&status);
|
@@ -1201,36 +1208,8 @@ VALUE build_class_from_descriptor(VALUE descriptor) {
|
|
1201
1208
|
klass = rb_define_class_id(
|
1202
1209
|
// Docs say this parameter is ignored. User will assign return value to
|
1203
1210
|
// their own toplevel constant class name.
|
1204
|
-
rb_intern("Message"),
|
1211
|
+
rb_intern("Message"), cAbstractMessage);
|
1205
1212
|
rb_ivar_set(klass, descriptor_instancevar_interned, descriptor);
|
1206
|
-
rb_define_alloc_func(klass, Message_alloc);
|
1207
|
-
rb_require("google/protobuf/message_exts");
|
1208
|
-
rb_include_module(klass, rb_eval_string("::Google::Protobuf::MessageExts"));
|
1209
|
-
rb_extend_object(
|
1210
|
-
klass, rb_eval_string("::Google::Protobuf::MessageExts::ClassMethods"));
|
1211
|
-
|
1212
|
-
rb_define_method(klass, "method_missing", Message_method_missing, -1);
|
1213
|
-
rb_define_method(klass, "respond_to_missing?", Message_respond_to_missing,
|
1214
|
-
-1);
|
1215
|
-
rb_define_method(klass, "initialize", Message_initialize, -1);
|
1216
|
-
rb_define_method(klass, "dup", Message_dup, 0);
|
1217
|
-
// Also define #clone so that we don't inherit Object#clone.
|
1218
|
-
rb_define_method(klass, "clone", Message_dup, 0);
|
1219
|
-
rb_define_method(klass, "==", Message_eq, 1);
|
1220
|
-
rb_define_method(klass, "eql?", Message_eq, 1);
|
1221
|
-
rb_define_method(klass, "freeze", Message_freeze, 0);
|
1222
|
-
rb_define_method(klass, "hash", Message_hash, 0);
|
1223
|
-
rb_define_method(klass, "to_h", Message_to_h, 0);
|
1224
|
-
rb_define_method(klass, "inspect", Message_inspect, 0);
|
1225
|
-
rb_define_method(klass, "to_s", Message_inspect, 0);
|
1226
|
-
rb_define_method(klass, "[]", Message_index, 1);
|
1227
|
-
rb_define_method(klass, "[]=", Message_index_set, 2);
|
1228
|
-
rb_define_singleton_method(klass, "decode", Message_decode, -1);
|
1229
|
-
rb_define_singleton_method(klass, "encode", Message_encode, -1);
|
1230
|
-
rb_define_singleton_method(klass, "decode_json", Message_decode_json, -1);
|
1231
|
-
rb_define_singleton_method(klass, "encode_json", Message_encode_json, -1);
|
1232
|
-
rb_define_singleton_method(klass, "descriptor", Message_descriptor, 0);
|
1233
|
-
|
1234
1213
|
return klass;
|
1235
1214
|
}
|
1236
1215
|
|
@@ -1296,12 +1275,12 @@ VALUE build_module_from_enumdesc(VALUE _enumdesc) {
|
|
1296
1275
|
int32_t value = upb_EnumValueDef_Number(ev);
|
1297
1276
|
if (name[0] < 'A' || name[0] > 'Z') {
|
1298
1277
|
if (name[0] >= 'a' && name[0] <= 'z') {
|
1299
|
-
name[0] -= 32;
|
1278
|
+
name[0] -= 32; // auto capitalize
|
1300
1279
|
} else {
|
1301
1280
|
rb_warn(
|
1302
|
-
|
1303
|
-
|
1304
|
-
|
1281
|
+
"Enum value '%s' does not start with an uppercase letter "
|
1282
|
+
"as is required for Ruby constants.",
|
1283
|
+
name);
|
1305
1284
|
}
|
1306
1285
|
}
|
1307
1286
|
rb_define_const(mod, name, INT2NUM(value));
|
@@ -1316,7 +1295,7 @@ VALUE build_module_from_enumdesc(VALUE _enumdesc) {
|
|
1316
1295
|
return mod;
|
1317
1296
|
}
|
1318
1297
|
|
1319
|
-
// Internal
|
1298
|
+
// Internal to the library; used by Google::Protobuf.deep_copy.
|
1320
1299
|
upb_Message* Message_deep_copy(const upb_Message* msg, const upb_MessageDef* m,
|
1321
1300
|
upb_Arena* arena) {
|
1322
1301
|
// Serialize and parse.
|
@@ -1324,11 +1303,16 @@ upb_Message* Message_deep_copy(const upb_Message* msg, const upb_MessageDef* m,
|
|
1324
1303
|
const upb_MiniTable* layout = upb_MessageDef_MiniTable(m);
|
1325
1304
|
size_t size;
|
1326
1305
|
|
1327
|
-
|
1328
|
-
|
1306
|
+
upb_Message* new_msg = upb_Message_New(layout, arena);
|
1307
|
+
char* data;
|
1329
1308
|
|
1330
|
-
|
1331
|
-
|
1309
|
+
const upb_FileDef* file = upb_MessageDef_File(m);
|
1310
|
+
const upb_ExtensionRegistry* extreg =
|
1311
|
+
upb_DefPool_ExtensionRegistry(upb_FileDef_Pool(file));
|
1312
|
+
if (upb_Encode(msg, layout, 0, tmp_arena, &data, &size) !=
|
1313
|
+
kUpb_EncodeStatus_Ok ||
|
1314
|
+
upb_Decode(data, size, new_msg, layout, extreg, 0, arena) !=
|
1315
|
+
kUpb_DecodeStatus_Ok) {
|
1332
1316
|
upb_Arena_Free(tmp_arena);
|
1333
1317
|
rb_raise(cParseError, "Error occurred copying proto");
|
1334
1318
|
}
|
@@ -1355,7 +1339,8 @@ const upb_Message* Message_GetUpbMessage(VALUE value, const upb_MessageDef* m,
|
|
1355
1339
|
switch (upb_MessageDef_WellKnownType(m)) {
|
1356
1340
|
case kUpb_WellKnown_Timestamp: {
|
1357
1341
|
// Time -> Google::Protobuf::Timestamp
|
1358
|
-
|
1342
|
+
const upb_MiniTable* t = upb_MessageDef_MiniTable(m);
|
1343
|
+
upb_Message* msg = upb_Message_New(t, arena);
|
1359
1344
|
upb_MessageValue sec, nsec;
|
1360
1345
|
struct timespec time;
|
1361
1346
|
const upb_FieldDef* sec_f = upb_MessageDef_FindFieldByNumber(m, 1);
|
@@ -1366,13 +1351,14 @@ const upb_Message* Message_GetUpbMessage(VALUE value, const upb_MessageDef* m,
|
|
1366
1351
|
time = rb_time_timespec(value);
|
1367
1352
|
sec.int64_val = time.tv_sec;
|
1368
1353
|
nsec.int32_val = time.tv_nsec;
|
1369
|
-
|
1370
|
-
|
1354
|
+
upb_Message_SetFieldByDef(msg, sec_f, sec, arena);
|
1355
|
+
upb_Message_SetFieldByDef(msg, nsec_f, nsec, arena);
|
1371
1356
|
return msg;
|
1372
1357
|
}
|
1373
1358
|
case kUpb_WellKnown_Duration: {
|
1374
1359
|
// Numeric -> Google::Protobuf::Duration
|
1375
|
-
|
1360
|
+
const upb_MiniTable* t = upb_MessageDef_MiniTable(m);
|
1361
|
+
upb_Message* msg = upb_Message_New(t, arena);
|
1376
1362
|
upb_MessageValue sec, nsec;
|
1377
1363
|
const upb_FieldDef* sec_f = upb_MessageDef_FindFieldByNumber(m, 1);
|
1378
1364
|
const upb_FieldDef* nsec_f = upb_MessageDef_FindFieldByNumber(m, 2);
|
@@ -1381,8 +1367,8 @@ const upb_Message* Message_GetUpbMessage(VALUE value, const upb_MessageDef* m,
|
|
1381
1367
|
|
1382
1368
|
sec.int64_val = NUM2LL(value);
|
1383
1369
|
nsec.int32_val = round((NUM2DBL(value) - NUM2LL(value)) * 1000000000);
|
1384
|
-
|
1385
|
-
|
1370
|
+
upb_Message_SetFieldByDef(msg, sec_f, sec, arena);
|
1371
|
+
upb_Message_SetFieldByDef(msg, nsec_f, nsec, arena);
|
1386
1372
|
return msg;
|
1387
1373
|
}
|
1388
1374
|
default:
|
@@ -1399,11 +1385,42 @@ const upb_Message* Message_GetUpbMessage(VALUE value, const upb_MessageDef* m,
|
|
1399
1385
|
return self->msg;
|
1400
1386
|
}
|
1401
1387
|
|
1388
|
+
static void Message_define_class(VALUE klass) {
|
1389
|
+
rb_define_alloc_func(klass, Message_alloc);
|
1390
|
+
|
1391
|
+
rb_require("google/protobuf/message_exts");
|
1392
|
+
rb_define_method(klass, "method_missing", Message_method_missing, -1);
|
1393
|
+
rb_define_method(klass, "respond_to_missing?", Message_respond_to_missing,
|
1394
|
+
-1);
|
1395
|
+
rb_define_method(klass, "initialize", Message_initialize, -1);
|
1396
|
+
rb_define_method(klass, "dup", Message_dup, 0);
|
1397
|
+
// Also define #clone so that we don't inherit Object#clone.
|
1398
|
+
rb_define_method(klass, "clone", Message_dup, 0);
|
1399
|
+
rb_define_method(klass, "==", Message_eq, 1);
|
1400
|
+
rb_define_method(klass, "eql?", Message_eq, 1);
|
1401
|
+
rb_define_method(klass, "freeze", Message_freeze, 0);
|
1402
|
+
rb_define_method(klass, "hash", Message_hash, 0);
|
1403
|
+
rb_define_method(klass, "to_h", Message_to_h, 0);
|
1404
|
+
rb_define_method(klass, "inspect", Message_inspect, 0);
|
1405
|
+
rb_define_method(klass, "to_s", Message_inspect, 0);
|
1406
|
+
rb_define_method(klass, "[]", Message_index, 1);
|
1407
|
+
rb_define_method(klass, "[]=", Message_index_set, 2);
|
1408
|
+
rb_define_singleton_method(klass, "decode", Message_decode, -1);
|
1409
|
+
rb_define_singleton_method(klass, "encode", Message_encode, -1);
|
1410
|
+
rb_define_singleton_method(klass, "decode_json", Message_decode_json, -1);
|
1411
|
+
rb_define_singleton_method(klass, "encode_json", Message_encode_json, -1);
|
1412
|
+
rb_define_singleton_method(klass, "descriptor", Message_descriptor, 0);
|
1413
|
+
}
|
1414
|
+
|
1402
1415
|
void Message_register(VALUE protobuf) {
|
1403
1416
|
cParseError = rb_const_get(protobuf, rb_intern("ParseError"));
|
1417
|
+
cAbstractMessage =
|
1418
|
+
rb_define_class_under(protobuf, "AbstractMessage", rb_cObject);
|
1419
|
+
Message_define_class(cAbstractMessage);
|
1420
|
+
rb_gc_register_address(&cAbstractMessage);
|
1404
1421
|
|
1405
1422
|
// Ruby-interned string: "descriptor". We use this identifier to store an
|
1406
1423
|
// instance variable on message classes we create in order to link them back
|
1407
1424
|
// to their descriptors.
|
1408
|
-
descriptor_instancevar_interned = rb_intern("descriptor");
|
1425
|
+
descriptor_instancevar_interned = rb_intern("@descriptor");
|
1409
1426
|
}
|