google-protobuf 3.23.3 → 4.31.1
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 +60 -86
- data/ext/google/protobuf_c/convert.h +3 -28
- data/ext/google/protobuf_c/defs.c +702 -60
- data/ext/google/protobuf_c/defs.h +3 -28
- data/ext/google/protobuf_c/extconf.rb +20 -3
- data/ext/google/protobuf_c/glue.c +135 -0
- data/ext/google/protobuf_c/map.c +91 -47
- data/ext/google/protobuf_c/map.h +12 -30
- data/ext/google/protobuf_c/message.c +158 -166
- data/ext/google/protobuf_c/message.h +11 -33
- data/ext/google/protobuf_c/protobuf.c +62 -187
- data/ext/google/protobuf_c/protobuf.h +21 -39
- data/ext/google/protobuf_c/repeated_field.c +72 -38
- data/ext/google/protobuf_c/repeated_field.h +11 -29
- data/ext/google/protobuf_c/ruby-upb.c +15568 -11237
- data/ext/google/protobuf_c/ruby-upb.h +10632 -6097
- data/ext/google/protobuf_c/shared_convert.c +69 -0
- data/ext/google/protobuf_c/shared_convert.h +26 -0
- data/ext/google/protobuf_c/shared_message.c +37 -0
- data/ext/google/protobuf_c/shared_message.h +21 -0
- data/ext/google/protobuf_c/third_party/utf8_range/utf8_range.c +207 -0
- data/ext/google/protobuf_c/third_party/utf8_range/utf8_range.h +9 -8
- data/ext/google/protobuf_c/third_party/utf8_range/utf8_range_neon.inc +117 -0
- data/ext/google/protobuf_c/third_party/utf8_range/utf8_range_sse.inc +272 -0
- data/ext/google/protobuf_c/wrap_memcpy.c +3 -26
- data/lib/google/protobuf/any_pb.rb +2 -23
- data/lib/google/protobuf/api_pb.rb +2 -25
- data/lib/google/protobuf/descriptor_pb.rb +19 -24
- data/lib/google/protobuf/duration_pb.rb +2 -23
- data/lib/google/protobuf/empty_pb.rb +2 -23
- data/lib/google/protobuf/ffi/descriptor.rb +175 -0
- data/lib/google/protobuf/ffi/descriptor_pool.rb +79 -0
- data/lib/google/protobuf/ffi/enum_descriptor.rb +183 -0
- data/lib/google/protobuf/ffi/ffi.rb +214 -0
- data/lib/google/protobuf/ffi/field_descriptor.rb +346 -0
- data/lib/google/protobuf/ffi/file_descriptor.rb +85 -0
- data/lib/google/protobuf/ffi/internal/arena.rb +60 -0
- data/lib/google/protobuf/ffi/internal/convert.rb +292 -0
- data/lib/google/protobuf/ffi/internal/pointer_helper.rb +36 -0
- data/lib/google/protobuf/ffi/internal/type_safety.rb +25 -0
- data/lib/google/protobuf/ffi/map.rb +433 -0
- data/lib/google/protobuf/ffi/message.rb +783 -0
- data/lib/google/protobuf/ffi/method_descriptor.rb +124 -0
- data/lib/google/protobuf/ffi/object_cache.rb +30 -0
- data/lib/google/protobuf/ffi/oneof_descriptor.rb +107 -0
- data/lib/google/protobuf/ffi/repeated_field.rb +411 -0
- data/lib/google/protobuf/ffi/service_descriptor.rb +117 -0
- data/lib/google/protobuf/field_mask_pb.rb +2 -23
- data/lib/google/protobuf/internal/object_cache.rb +99 -0
- data/lib/google/protobuf/message_exts.rb +7 -26
- data/lib/google/protobuf/plugin_pb.rb +3 -25
- data/lib/google/protobuf/repeated_field.rb +7 -31
- data/lib/google/protobuf/source_context_pb.rb +2 -23
- data/lib/google/protobuf/struct_pb.rb +2 -23
- data/lib/google/protobuf/timestamp_pb.rb +2 -23
- data/lib/google/protobuf/type_pb.rb +2 -25
- data/lib/google/protobuf/well_known_types.rb +5 -34
- data/lib/google/protobuf/wrappers_pb.rb +2 -23
- data/lib/google/protobuf.rb +27 -45
- data/lib/google/protobuf_ffi.rb +52 -0
- data/lib/google/protobuf_native.rb +19 -0
- data/lib/google/tasks/ffi.rake +100 -0
- metadata +99 -16
- data/ext/google/protobuf_c/third_party/utf8_range/naive.c +0 -92
- data/ext/google/protobuf_c/third_party/utf8_range/range2-neon.c +0 -157
- data/ext/google/protobuf_c/third_party/utf8_range/range2-sse.c +0 -170
- data/lib/google/protobuf/descriptor_dsl.rb +0 -465
@@ -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,6 +12,7 @@
|
|
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;
|
40
18
|
static VALUE cAbstractMessage = Qnil;
|
@@ -66,9 +44,11 @@ static void Message_mark(void* _self) {
|
|
66
44
|
rb_gc_mark(self->arena);
|
67
45
|
}
|
68
46
|
|
47
|
+
static size_t Message_memsize(const void* _self) { return sizeof(Message); }
|
48
|
+
|
69
49
|
static rb_data_type_t Message_type = {
|
70
50
|
"Google::Protobuf::Message",
|
71
|
-
{Message_mark, RUBY_DEFAULT_FREE,
|
51
|
+
{Message_mark, RUBY_DEFAULT_FREE, Message_memsize},
|
72
52
|
.flags = RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
|
73
53
|
};
|
74
54
|
|
@@ -100,15 +80,19 @@ const upb_Message* Message_Get(VALUE msg_rb, const upb_MessageDef** m) {
|
|
100
80
|
}
|
101
81
|
|
102
82
|
upb_Message* Message_GetMutable(VALUE msg_rb, const upb_MessageDef** m) {
|
103
|
-
|
104
|
-
|
83
|
+
const upb_Message* upb_msg = Message_Get(msg_rb, m);
|
84
|
+
Protobuf_CheckNotFrozen(msg_rb, upb_Message_IsFrozen(upb_msg));
|
85
|
+
return (upb_Message*)upb_msg;
|
105
86
|
}
|
106
87
|
|
107
|
-
void Message_InitPtr(VALUE self_, upb_Message* msg, VALUE arena) {
|
88
|
+
void Message_InitPtr(VALUE self_, const upb_Message* msg, VALUE arena) {
|
89
|
+
PBRUBY_ASSERT(arena != Qnil);
|
108
90
|
Message* self = ruby_to_Message(self_);
|
109
91
|
self->msg = msg;
|
110
92
|
RB_OBJ_WRITE(self_, &self->arena, arena);
|
111
|
-
|
93
|
+
VALUE stored = ObjectCache_TryAdd(msg, self_);
|
94
|
+
(void)stored;
|
95
|
+
PBRUBY_ASSERT(stored == self_);
|
112
96
|
}
|
113
97
|
|
114
98
|
VALUE Message_GetArena(VALUE msg_rb) {
|
@@ -123,7 +107,7 @@ void Message_CheckClass(VALUE klass) {
|
|
123
107
|
}
|
124
108
|
}
|
125
109
|
|
126
|
-
VALUE Message_GetRubyWrapper(upb_Message* msg, const upb_MessageDef* m,
|
110
|
+
VALUE Message_GetRubyWrapper(const upb_Message* msg, const upb_MessageDef* m,
|
127
111
|
VALUE arena) {
|
128
112
|
if (msg == NULL) return Qnil;
|
129
113
|
|
@@ -134,7 +118,6 @@ VALUE Message_GetRubyWrapper(upb_Message* msg, const upb_MessageDef* m,
|
|
134
118
|
val = Message_alloc(klass);
|
135
119
|
Message_InitPtr(val, msg, arena);
|
136
120
|
}
|
137
|
-
|
138
121
|
return val;
|
139
122
|
}
|
140
123
|
|
@@ -266,7 +249,7 @@ static int extract_method_call(VALUE method_name, Message* self,
|
|
266
249
|
static VALUE Message_oneof_accessor(VALUE _self, const upb_OneofDef* o,
|
267
250
|
int accessor_type) {
|
268
251
|
Message* self = ruby_to_Message(_self);
|
269
|
-
const upb_FieldDef* oneof_field =
|
252
|
+
const upb_FieldDef* oneof_field = upb_Message_WhichOneofByDef(self->msg, o);
|
270
253
|
|
271
254
|
switch (accessor_type) {
|
272
255
|
case METHOD_PRESENCE:
|
@@ -306,13 +289,42 @@ static void Message_setfield(upb_Message* msg, const upb_FieldDef* f, VALUE val,
|
|
306
289
|
upb_Message_SetFieldByDef(msg, f, msgval, arena);
|
307
290
|
}
|
308
291
|
|
292
|
+
VALUE Message_getfield_frozen(const upb_Message* msg, const upb_FieldDef* f,
|
293
|
+
VALUE arena) {
|
294
|
+
upb_MessageValue msgval = upb_Message_GetFieldByDef(msg, f);
|
295
|
+
if (upb_FieldDef_IsMap(f)) {
|
296
|
+
if (msgval.map_val == NULL) {
|
297
|
+
return Map_EmptyFrozen(f);
|
298
|
+
}
|
299
|
+
const upb_FieldDef* key_f = map_field_key(f);
|
300
|
+
const upb_FieldDef* val_f = map_field_value(f);
|
301
|
+
upb_CType key_type = upb_FieldDef_CType(key_f);
|
302
|
+
TypeInfo value_type_info = TypeInfo_get(val_f);
|
303
|
+
return Map_GetRubyWrapper(msgval.map_val, key_type, value_type_info, arena);
|
304
|
+
}
|
305
|
+
if (upb_FieldDef_IsRepeated(f)) {
|
306
|
+
if (msgval.array_val == NULL) {
|
307
|
+
return RepeatedField_EmptyFrozen(f);
|
308
|
+
}
|
309
|
+
return RepeatedField_GetRubyWrapper(msgval.array_val, TypeInfo_get(f),
|
310
|
+
arena);
|
311
|
+
}
|
312
|
+
VALUE ret;
|
313
|
+
if (upb_FieldDef_IsSubMessage(f)) {
|
314
|
+
const upb_MessageDef* m = upb_FieldDef_MessageSubDef(f);
|
315
|
+
ret = Message_GetRubyWrapper(msgval.msg_val, m, arena);
|
316
|
+
} else {
|
317
|
+
ret = Convert_UpbToRuby(msgval, TypeInfo_get(f), Qnil);
|
318
|
+
}
|
319
|
+
return ret;
|
320
|
+
}
|
321
|
+
|
309
322
|
VALUE Message_getfield(VALUE _self, const upb_FieldDef* f) {
|
310
323
|
Message* self = ruby_to_Message(_self);
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
upb_Message* msg = (upb_Message*)self->msg;
|
324
|
+
if (upb_Message_IsFrozen(self->msg)) {
|
325
|
+
return Message_getfield_frozen(self->msg, f, self->arena);
|
326
|
+
}
|
327
|
+
upb_Message* msg = Message_GetMutable(_self, NULL);
|
316
328
|
upb_Arena* arena = Arena_get(self->arena);
|
317
329
|
if (upb_FieldDef_IsMap(f)) {
|
318
330
|
upb_Map* map = upb_Message_Mutable(msg, f, arena).map;
|
@@ -325,12 +337,12 @@ VALUE Message_getfield(VALUE _self, const upb_FieldDef* f) {
|
|
325
337
|
upb_Array* arr = upb_Message_Mutable(msg, f, arena).array;
|
326
338
|
return RepeatedField_GetRubyWrapper(arr, TypeInfo_get(f), self->arena);
|
327
339
|
} else if (upb_FieldDef_IsSubMessage(f)) {
|
328
|
-
if (!upb_Message_HasFieldByDef(
|
340
|
+
if (!upb_Message_HasFieldByDef(msg, f)) return Qnil;
|
329
341
|
upb_Message* submsg = upb_Message_Mutable(msg, f, arena).msg;
|
330
342
|
const upb_MessageDef* m = upb_FieldDef_MessageSubDef(f);
|
331
343
|
return Message_GetRubyWrapper(submsg, m, self->arena);
|
332
344
|
} else {
|
333
|
-
upb_MessageValue msgval = upb_Message_GetFieldByDef(
|
345
|
+
upb_MessageValue msgval = upb_Message_GetFieldByDef(msg, f);
|
334
346
|
return Convert_UpbToRuby(msgval, TypeInfo_get(f), self->arena);
|
335
347
|
}
|
336
348
|
}
|
@@ -350,7 +362,8 @@ static VALUE Message_field_accessor(VALUE _self, const upb_FieldDef* f,
|
|
350
362
|
if (!upb_FieldDef_HasPresence(f)) {
|
351
363
|
rb_raise(rb_eRuntimeError, "Field does not have presence.");
|
352
364
|
}
|
353
|
-
return upb_Message_HasFieldByDef(Message_Get(_self, NULL), f)
|
365
|
+
return upb_Message_HasFieldByDef(Message_Get(_self, NULL), f) ? Qtrue
|
366
|
+
: Qfalse;
|
354
367
|
case METHOD_WRAPPER_GETTER: {
|
355
368
|
Message* self = ruby_to_Message(_self);
|
356
369
|
if (upb_Message_HasFieldByDef(self->msg, f)) {
|
@@ -385,7 +398,7 @@ static VALUE Message_field_accessor(VALUE _self, const upb_FieldDef* f,
|
|
385
398
|
upb_MessageValue msgval =
|
386
399
|
upb_Message_GetFieldByDef(Message_Get(_self, NULL), f);
|
387
400
|
|
388
|
-
if (
|
401
|
+
if (upb_FieldDef_IsRepeated(f)) {
|
389
402
|
// Map repeated fields to a new type with ints
|
390
403
|
VALUE arr = rb_ary_new();
|
391
404
|
size_t i, n = upb_Array_Size(msgval.array_val);
|
@@ -454,7 +467,6 @@ static VALUE Message_method_missing(int argc, VALUE* argv, VALUE _self) {
|
|
454
467
|
if (argc != 2) {
|
455
468
|
rb_raise(rb_eArgError, "Expected 2 arguments, received %d", argc);
|
456
469
|
}
|
457
|
-
rb_check_frozen(_self);
|
458
470
|
break;
|
459
471
|
default:
|
460
472
|
if (argc != 1) {
|
@@ -508,7 +520,8 @@ static int Map_initialize_kwarg(VALUE key, VALUE val, VALUE _self) {
|
|
508
520
|
k = Convert_RubyToUpb(key, "", map_init->key_type, NULL);
|
509
521
|
|
510
522
|
if (map_init->val_type.type == kUpb_CType_Message && TYPE(val) == T_HASH) {
|
511
|
-
upb_MiniTable* t =
|
523
|
+
const upb_MiniTable* t =
|
524
|
+
upb_MessageDef_MiniTable(map_init->val_type.def.msgdef);
|
512
525
|
upb_Message* msg = upb_Message_New(t, map_init->arena);
|
513
526
|
Message_InitFromValue(msg, map_init->val_type.def.msgdef, val,
|
514
527
|
map_init->arena);
|
@@ -539,7 +552,7 @@ static upb_MessageValue MessageValue_FromValue(VALUE val, TypeInfo info,
|
|
539
552
|
upb_Arena* arena) {
|
540
553
|
if (info.type == kUpb_CType_Message) {
|
541
554
|
upb_MessageValue msgval;
|
542
|
-
upb_MiniTable* t = upb_MessageDef_MiniTable(info.def.msgdef);
|
555
|
+
const upb_MiniTable* t = upb_MessageDef_MiniTable(info.def.msgdef);
|
543
556
|
upb_Message* msg = upb_Message_New(t, arena);
|
544
557
|
Message_InitFromValue(msg, info.def.msgdef, val, arena);
|
545
558
|
msgval.msg_val = msg;
|
@@ -579,7 +592,7 @@ static void Message_InitFieldFromValue(upb_Message* msg, const upb_FieldDef* f,
|
|
579
592
|
if (upb_FieldDef_IsMap(f)) {
|
580
593
|
upb_Map* map = upb_Message_Mutable(msg, f, arena).map;
|
581
594
|
Map_InitFromValue(map, f, val, arena);
|
582
|
-
} else if (
|
595
|
+
} else if (upb_FieldDef_IsRepeated(f)) {
|
583
596
|
upb_Array* arr = upb_Message_Mutable(msg, f, arena).array;
|
584
597
|
RepeatedField_InitFromValue(arr, f, val, arena);
|
585
598
|
} else if (upb_FieldDef_IsSubMessage(f)) {
|
@@ -655,7 +668,7 @@ static VALUE Message_initialize(int argc, VALUE* argv, VALUE _self) {
|
|
655
668
|
Message* self = ruby_to_Message(_self);
|
656
669
|
VALUE arena_rb = Arena_new();
|
657
670
|
upb_Arena* arena = Arena_get(arena_rb);
|
658
|
-
upb_MiniTable* t = upb_MessageDef_MiniTable(self->msgdef);
|
671
|
+
const upb_MiniTable* t = upb_MessageDef_MiniTable(self->msgdef);
|
659
672
|
upb_Message* msg = upb_Message_New(t, arena);
|
660
673
|
|
661
674
|
Message_InitPtr(_self, msg, arena_rb);
|
@@ -680,44 +693,12 @@ static VALUE Message_dup(VALUE _self) {
|
|
680
693
|
Message* self = ruby_to_Message(_self);
|
681
694
|
VALUE new_msg = rb_class_new_instance(0, NULL, CLASS_OF(_self));
|
682
695
|
Message* new_msg_self = ruby_to_Message(new_msg);
|
683
|
-
|
684
|
-
|
685
|
-
// TODO(copy unknown fields?)
|
686
|
-
// TODO(use official upb msg copy function)
|
687
|
-
memcpy((upb_Message*)new_msg_self->msg, self->msg, size);
|
696
|
+
const upb_MiniTable* m = upb_MessageDef_MiniTable(self->msgdef);
|
697
|
+
upb_Message_ShallowCopy((upb_Message*)new_msg_self->msg, self->msg, m);
|
688
698
|
Arena_fuse(self->arena, Arena_get(new_msg_self->arena));
|
689
699
|
return new_msg;
|
690
700
|
}
|
691
701
|
|
692
|
-
// Support function for Message_eq, and also used by other #eq functions.
|
693
|
-
bool Message_Equal(const upb_Message* m1, const upb_Message* m2,
|
694
|
-
const upb_MessageDef* m) {
|
695
|
-
if (m1 == m2) return true;
|
696
|
-
|
697
|
-
size_t size1, size2;
|
698
|
-
int encode_opts =
|
699
|
-
kUpb_EncodeOption_SkipUnknown | kUpb_EncodeOption_Deterministic;
|
700
|
-
upb_Arena* arena_tmp = upb_Arena_New();
|
701
|
-
const upb_MiniTable* layout = upb_MessageDef_MiniTable(m);
|
702
|
-
|
703
|
-
// Compare deterministically serialized payloads with no unknown fields.
|
704
|
-
char* data1;
|
705
|
-
char* data2;
|
706
|
-
upb_EncodeStatus status1 =
|
707
|
-
upb_Encode(m1, layout, encode_opts, arena_tmp, &data1, &size1);
|
708
|
-
upb_EncodeStatus status2 =
|
709
|
-
upb_Encode(m2, layout, encode_opts, arena_tmp, &data2, &size2);
|
710
|
-
|
711
|
-
if (status1 == kUpb_EncodeStatus_Ok && status2 == kUpb_EncodeStatus_Ok) {
|
712
|
-
bool ret = (size1 == size2) && (memcmp(data1, data2, size1) == 0);
|
713
|
-
upb_Arena_Free(arena_tmp);
|
714
|
-
return ret;
|
715
|
-
} else {
|
716
|
-
upb_Arena_Free(arena_tmp);
|
717
|
-
rb_raise(cParseError, "Error comparing messages");
|
718
|
-
}
|
719
|
-
}
|
720
|
-
|
721
702
|
/*
|
722
703
|
* call-seq:
|
723
704
|
* Message.==(other) => boolean
|
@@ -734,28 +715,22 @@ static VALUE Message_eq(VALUE _self, VALUE _other) {
|
|
734
715
|
Message* other = ruby_to_Message(_other);
|
735
716
|
assert(self->msgdef == other->msgdef);
|
736
717
|
|
737
|
-
|
718
|
+
const upb_MiniTable* m = upb_MessageDef_MiniTable(self->msgdef);
|
719
|
+
const int options = 0;
|
720
|
+
return upb_Message_IsEqual(self->msg, other->msg, m, options) ? Qtrue
|
721
|
+
: Qfalse;
|
738
722
|
}
|
739
723
|
|
740
724
|
uint64_t Message_Hash(const upb_Message* msg, const upb_MessageDef* m,
|
741
725
|
uint64_t seed) {
|
742
|
-
|
743
|
-
|
744
|
-
|
745
|
-
|
746
|
-
|
747
|
-
upb_EncodeStatus status = upb_Encode(
|
748
|
-
msg, upb_MessageDef_MiniTable(m),
|
749
|
-
kUpb_EncodeOption_SkipUnknown | kUpb_EncodeOption_Deterministic, arena,
|
750
|
-
&data, &size);
|
751
|
-
|
752
|
-
if (status == kUpb_EncodeStatus_Ok) {
|
753
|
-
uint64_t ret = _upb_Hash(data, size, seed);
|
754
|
-
upb_Arena_Free(arena);
|
755
|
-
return ret;
|
726
|
+
upb_Status status;
|
727
|
+
upb_Status_Clear(&status);
|
728
|
+
uint64_t return_value = shared_Message_Hash(msg, m, seed, &status);
|
729
|
+
if (upb_Status_IsOk(&status)) {
|
730
|
+
return return_value;
|
756
731
|
} else {
|
757
|
-
|
758
|
-
|
732
|
+
rb_raise(cParseError, "Message_Hash(): %s",
|
733
|
+
upb_Status_ErrorMessage(&status));
|
759
734
|
}
|
760
735
|
}
|
761
736
|
|
@@ -812,58 +787,34 @@ static VALUE Message_CreateHash(const upb_Message* msg,
|
|
812
787
|
if (!msg) return Qnil;
|
813
788
|
|
814
789
|
VALUE hash = rb_hash_new();
|
815
|
-
|
816
|
-
|
817
|
-
|
818
|
-
|
819
|
-
// This is unfortunate, we should key behaviors off field attributes (like
|
820
|
-
// whether a field has presence), not proto2 vs. proto3. We should see if we
|
821
|
-
// can change this without breaking users.
|
822
|
-
is_proto2 = upb_MessageDef_Syntax(m) == kUpb_Syntax_Proto2;
|
823
|
-
|
824
|
-
for (int i = 0; i < n; i++) {
|
825
|
-
const upb_FieldDef* field = upb_MessageDef_Field(m, i);
|
826
|
-
TypeInfo type_info = TypeInfo_get(field);
|
827
|
-
upb_MessageValue msgval;
|
828
|
-
VALUE msg_value;
|
829
|
-
VALUE msg_key;
|
830
|
-
|
831
|
-
if (!is_proto2 && upb_FieldDef_IsSubMessage(field) &&
|
832
|
-
!upb_FieldDef_IsRepeated(field) &&
|
833
|
-
!upb_Message_HasFieldByDef(msg, field)) {
|
834
|
-
// TODO: Legacy behavior, remove when we fix the is_proto2 differences.
|
835
|
-
msg_key = ID2SYM(rb_intern(upb_FieldDef_Name(field)));
|
836
|
-
rb_hash_aset(hash, msg_key, Qnil);
|
837
|
-
continue;
|
838
|
-
}
|
790
|
+
size_t iter = kUpb_Message_Begin;
|
791
|
+
const upb_DefPool* pool = upb_FileDef_Pool(upb_MessageDef_File(m));
|
792
|
+
const upb_FieldDef* field;
|
793
|
+
upb_MessageValue val;
|
839
794
|
|
840
|
-
|
841
|
-
if (
|
842
|
-
|
795
|
+
while (upb_Message_Next(msg, m, pool, &field, &val, &iter)) {
|
796
|
+
if (upb_FieldDef_IsExtension(field)) {
|
797
|
+
// TODO: allow extensions once we have decided what naming scheme the
|
798
|
+
// symbol should use. eg. :"[pkg.ext]"
|
843
799
|
continue;
|
844
800
|
}
|
845
801
|
|
846
|
-
|
847
|
-
|
848
|
-
|
849
|
-
// Proto2 omits empty map/repeated filds also.
|
802
|
+
TypeInfo type_info = TypeInfo_get(field);
|
803
|
+
VALUE msg_value;
|
850
804
|
|
851
805
|
if (upb_FieldDef_IsMap(field)) {
|
852
806
|
const upb_MessageDef* entry_m = upb_FieldDef_MessageSubDef(field);
|
853
807
|
const upb_FieldDef* key_f = upb_MessageDef_FindFieldByNumber(entry_m, 1);
|
854
808
|
const upb_FieldDef* val_f = upb_MessageDef_FindFieldByNumber(entry_m, 2);
|
855
809
|
upb_CType key_type = upb_FieldDef_CType(key_f);
|
856
|
-
msg_value = Map_CreateHash(
|
810
|
+
msg_value = Map_CreateHash(val.map_val, key_type, TypeInfo_get(val_f));
|
857
811
|
} else if (upb_FieldDef_IsRepeated(field)) {
|
858
|
-
|
859
|
-
(!msgval.array_val || upb_Array_Size(msgval.array_val) == 0)) {
|
860
|
-
continue;
|
861
|
-
}
|
862
|
-
msg_value = RepeatedField_CreateArray(msgval.array_val, type_info);
|
812
|
+
msg_value = RepeatedField_CreateArray(val.array_val, type_info);
|
863
813
|
} else {
|
864
|
-
msg_value = Scalar_CreateHash(
|
814
|
+
msg_value = Scalar_CreateHash(val, type_info);
|
865
815
|
}
|
866
816
|
|
817
|
+
VALUE msg_key = ID2SYM(rb_intern(upb_FieldDef_Name(field)));
|
867
818
|
rb_hash_aset(hash, msg_key, msg_value);
|
868
819
|
}
|
869
820
|
|
@@ -889,19 +840,44 @@ static VALUE Message_to_h(VALUE _self) {
|
|
889
840
|
return Message_CreateHash(self->msg, self->msgdef);
|
890
841
|
}
|
891
842
|
|
843
|
+
/*
|
844
|
+
* call-seq:
|
845
|
+
* Message.frozen? => bool
|
846
|
+
*
|
847
|
+
* Returns true if the message is frozen in either Ruby or the underlying
|
848
|
+
* representation. Freezes the Ruby message object if it is not already frozen
|
849
|
+
* in Ruby but it is frozen in the underlying representation.
|
850
|
+
*/
|
851
|
+
VALUE Message_frozen(VALUE _self) {
|
852
|
+
Message* self = ruby_to_Message(_self);
|
853
|
+
if (!upb_Message_IsFrozen(self->msg)) {
|
854
|
+
PBRUBY_ASSERT(!RB_OBJ_FROZEN(_self));
|
855
|
+
return Qfalse;
|
856
|
+
}
|
857
|
+
|
858
|
+
// Lazily freeze the Ruby wrapper.
|
859
|
+
if (!RB_OBJ_FROZEN(_self)) RB_OBJ_FREEZE(_self);
|
860
|
+
return Qtrue;
|
861
|
+
}
|
862
|
+
|
892
863
|
/*
|
893
864
|
* call-seq:
|
894
865
|
* Message.freeze => self
|
895
866
|
*
|
896
|
-
* Freezes the message object. We have to intercept this so we can
|
897
|
-
*
|
867
|
+
* Freezes the message object. We have to intercept this so we can freeze the
|
868
|
+
* underlying representation, not just the Ruby wrapper.
|
898
869
|
*/
|
899
|
-
|
870
|
+
VALUE Message_freeze(VALUE _self) {
|
900
871
|
Message* self = ruby_to_Message(_self);
|
901
|
-
if (
|
902
|
-
|
903
|
-
|
872
|
+
if (RB_OBJ_FROZEN(_self)) {
|
873
|
+
PBRUBY_ASSERT(upb_Message_IsFrozen(self->msg));
|
874
|
+
return _self;
|
875
|
+
}
|
876
|
+
if (!upb_Message_IsFrozen(self->msg)) {
|
877
|
+
upb_Message_Freeze(Message_GetMutable(_self, NULL),
|
878
|
+
upb_MessageDef_MiniTable(self->msgdef));
|
904
879
|
}
|
880
|
+
RB_OBJ_FREEZE(_self);
|
905
881
|
return _self;
|
906
882
|
}
|
907
883
|
|
@@ -957,7 +933,7 @@ static VALUE Message_index_set(VALUE _self, VALUE field_name, VALUE value) {
|
|
957
933
|
* MessageClass.decode(data, options) => message
|
958
934
|
*
|
959
935
|
* Decodes the given data (as a string containing bytes in protocol buffers wire
|
960
|
-
* format) under the
|
936
|
+
* format) under the interpretation given by this message class's definition
|
961
937
|
* and returns a message object with the corresponding field values.
|
962
938
|
* @param options [Hash] options for the decoder
|
963
939
|
* recursion_limit: set to maximum decoding depth for message (default is 64)
|
@@ -988,18 +964,27 @@ static VALUE Message_decode(int argc, VALUE* argv, VALUE klass) {
|
|
988
964
|
rb_raise(rb_eArgError, "Expected string for binary protobuf data.");
|
989
965
|
}
|
990
966
|
|
967
|
+
return Message_decode_bytes(RSTRING_LEN(data), RSTRING_PTR(data), options,
|
968
|
+
klass, /*freeze*/ false);
|
969
|
+
}
|
970
|
+
|
971
|
+
VALUE Message_decode_bytes(int size, const char* bytes, int options,
|
972
|
+
VALUE klass, bool freeze) {
|
991
973
|
VALUE msg_rb = initialize_rb_class_with_no_args(klass);
|
992
974
|
Message* msg = ruby_to_Message(msg_rb);
|
993
975
|
|
994
|
-
|
995
|
-
|
996
|
-
|
997
|
-
|
998
|
-
|
976
|
+
const upb_FileDef* file = upb_MessageDef_File(msg->msgdef);
|
977
|
+
const upb_ExtensionRegistry* extreg =
|
978
|
+
upb_DefPool_ExtensionRegistry(upb_FileDef_Pool(file));
|
979
|
+
upb_DecodeStatus status = upb_Decode(bytes, size, (upb_Message*)msg->msg,
|
980
|
+
upb_MessageDef_MiniTable(msg->msgdef),
|
981
|
+
extreg, options, Arena_get(msg->arena));
|
999
982
|
if (status != kUpb_DecodeStatus_Ok) {
|
1000
983
|
rb_raise(cParseError, "Error occurred during parsing");
|
1001
984
|
}
|
1002
|
-
|
985
|
+
if (freeze) {
|
986
|
+
Message_freeze(msg_rb);
|
987
|
+
}
|
1003
988
|
return msg_rb;
|
1004
989
|
}
|
1005
990
|
|
@@ -1020,9 +1005,6 @@ static VALUE Message_decode_json(int argc, VALUE* argv, VALUE klass) {
|
|
1020
1005
|
int options = 0;
|
1021
1006
|
upb_Status status;
|
1022
1007
|
|
1023
|
-
// TODO(haberman): use this message's pool instead.
|
1024
|
-
const upb_DefPool* symtab = DescriptorPool_GetSymtab(generated_pool);
|
1025
|
-
|
1026
1008
|
if (argc < 1 || argc > 2) {
|
1027
1009
|
rb_raise(rb_eArgError, "Expected 1 or 2 arguments.");
|
1028
1010
|
}
|
@@ -1043,7 +1025,7 @@ static VALUE Message_decode_json(int argc, VALUE* argv, VALUE klass) {
|
|
1043
1025
|
rb_raise(rb_eArgError, "Expected string for JSON data.");
|
1044
1026
|
}
|
1045
1027
|
|
1046
|
-
// TODO
|
1028
|
+
// TODO: Check and respect string encoding. If not UTF-8, we need to
|
1047
1029
|
// convert, because string handlers pass data directly to message string
|
1048
1030
|
// fields.
|
1049
1031
|
|
@@ -1056,11 +1038,19 @@ static VALUE Message_decode_json(int argc, VALUE* argv, VALUE klass) {
|
|
1056
1038
|
}
|
1057
1039
|
|
1058
1040
|
upb_Status_Clear(&status);
|
1059
|
-
|
1060
|
-
|
1061
|
-
|
1062
|
-
|
1063
|
-
|
1041
|
+
const upb_DefPool* pool = upb_FileDef_Pool(upb_MessageDef_File(msg->msgdef));
|
1042
|
+
|
1043
|
+
int result = upb_JsonDecodeDetectingNonconformance(
|
1044
|
+
RSTRING_PTR(data), RSTRING_LEN(data), (upb_Message*)msg->msg,
|
1045
|
+
msg->msgdef, pool, options, Arena_get(msg->arena), &status);
|
1046
|
+
|
1047
|
+
switch (result) {
|
1048
|
+
case kUpb_JsonDecodeResult_Ok:
|
1049
|
+
break;
|
1050
|
+
case kUpb_JsonDecodeResult_Error:
|
1051
|
+
rb_raise(cParseError, "Error occurred during parsing: %s",
|
1052
|
+
upb_Status_ErrorMessage(&status));
|
1053
|
+
break;
|
1064
1054
|
}
|
1065
1055
|
|
1066
1056
|
return msg_rb;
|
@@ -1136,9 +1126,6 @@ static VALUE Message_encode_json(int argc, VALUE* argv, VALUE klass) {
|
|
1136
1126
|
size_t size;
|
1137
1127
|
upb_Status status;
|
1138
1128
|
|
1139
|
-
// TODO(haberman): use this message's pool instead.
|
1140
|
-
const upb_DefPool* symtab = DescriptorPool_GetSymtab(generated_pool);
|
1141
|
-
|
1142
1129
|
if (argc < 1 || argc > 2) {
|
1143
1130
|
rb_raise(rb_eArgError, "Expected 1 or 2 arguments.");
|
1144
1131
|
}
|
@@ -1173,8 +1160,9 @@ static VALUE Message_encode_json(int argc, VALUE* argv, VALUE klass) {
|
|
1173
1160
|
}
|
1174
1161
|
|
1175
1162
|
upb_Status_Clear(&status);
|
1176
|
-
|
1177
|
-
|
1163
|
+
const upb_DefPool* pool = upb_FileDef_Pool(upb_MessageDef_File(msg->msgdef));
|
1164
|
+
size = upb_JsonEncode(msg->msg, msg->msgdef, pool, options, buf, sizeof(buf),
|
1165
|
+
&status);
|
1178
1166
|
|
1179
1167
|
if (!upb_Status_IsOk(&status)) {
|
1180
1168
|
rb_raise(cParseError, "Error occurred during encoding: %s",
|
@@ -1184,7 +1172,7 @@ static VALUE Message_encode_json(int argc, VALUE* argv, VALUE klass) {
|
|
1184
1172
|
VALUE ret;
|
1185
1173
|
if (size >= sizeof(buf)) {
|
1186
1174
|
char* buf2 = malloc(size + 1);
|
1187
|
-
upb_JsonEncode(msg->msg, msg->msgdef,
|
1175
|
+
upb_JsonEncode(msg->msg, msg->msgdef, pool, options, buf2, size + 1,
|
1188
1176
|
&status);
|
1189
1177
|
ret = rb_str_new(buf2, size);
|
1190
1178
|
free(buf2);
|
@@ -1317,9 +1305,12 @@ upb_Message* Message_deep_copy(const upb_Message* msg, const upb_MessageDef* m,
|
|
1317
1305
|
upb_Message* new_msg = upb_Message_New(layout, arena);
|
1318
1306
|
char* data;
|
1319
1307
|
|
1308
|
+
const upb_FileDef* file = upb_MessageDef_File(m);
|
1309
|
+
const upb_ExtensionRegistry* extreg =
|
1310
|
+
upb_DefPool_ExtensionRegistry(upb_FileDef_Pool(file));
|
1320
1311
|
if (upb_Encode(msg, layout, 0, tmp_arena, &data, &size) !=
|
1321
1312
|
kUpb_EncodeStatus_Ok ||
|
1322
|
-
upb_Decode(data, size, new_msg, layout,
|
1313
|
+
upb_Decode(data, size, new_msg, layout, extreg, 0, arena) !=
|
1323
1314
|
kUpb_DecodeStatus_Ok) {
|
1324
1315
|
upb_Arena_Free(tmp_arena);
|
1325
1316
|
rb_raise(cParseError, "Error occurred copying proto");
|
@@ -1407,6 +1398,7 @@ static void Message_define_class(VALUE klass) {
|
|
1407
1398
|
rb_define_method(klass, "==", Message_eq, 1);
|
1408
1399
|
rb_define_method(klass, "eql?", Message_eq, 1);
|
1409
1400
|
rb_define_method(klass, "freeze", Message_freeze, 0);
|
1401
|
+
rb_define_method(klass, "frozen?", Message_frozen, 0);
|
1410
1402
|
rb_define_method(klass, "hash", Message_hash, 0);
|
1411
1403
|
rb_define_method(klass, "to_h", Message_to_h, 0);
|
1412
1404
|
rb_define_method(klass, "inspect", Message_inspect, 0);
|
@@ -1,38 +1,13 @@
|
|
1
1
|
// Protocol Buffers - Google's data interchange format
|
2
2
|
// Copyright 2008 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
|
#ifndef RUBY_PROTOBUF_MESSAGE_H_
|
32
9
|
#define RUBY_PROTOBUF_MESSAGE_H_
|
33
10
|
|
34
|
-
#include <ruby/ruby.h>
|
35
|
-
|
36
11
|
#include "protobuf.h"
|
37
12
|
#include "ruby-upb.h"
|
38
13
|
|
@@ -61,7 +36,7 @@ const upb_Message* Message_GetUpbMessage(VALUE value, const upb_MessageDef* m,
|
|
61
36
|
|
62
37
|
// Gets or constructs a Ruby wrapper object for the given message. The wrapper
|
63
38
|
// object will reference |arena| and ensure that it outlives this object.
|
64
|
-
VALUE Message_GetRubyWrapper(upb_Message* msg, const upb_MessageDef* m,
|
39
|
+
VALUE Message_GetRubyWrapper(const upb_Message* msg, const upb_MessageDef* m,
|
65
40
|
VALUE arena);
|
66
41
|
|
67
42
|
// Gets the given field from this message.
|
@@ -79,10 +54,6 @@ uint64_t Message_Hash(const upb_Message* msg, const upb_MessageDef* m,
|
|
79
54
|
upb_Message* Message_deep_copy(const upb_Message* msg, const upb_MessageDef* m,
|
80
55
|
upb_Arena* arena);
|
81
56
|
|
82
|
-
// Returns true if these two messages are equal.
|
83
|
-
bool Message_Equal(const upb_Message* m1, const upb_Message* m2,
|
84
|
-
const upb_MessageDef* m);
|
85
|
-
|
86
57
|
// Checks that this Ruby object is a message, and raises an exception if not.
|
87
58
|
void Message_CheckClass(VALUE klass);
|
88
59
|
|
@@ -98,6 +69,13 @@ VALUE build_module_from_enumdesc(VALUE _enumdesc);
|
|
98
69
|
// module.
|
99
70
|
VALUE MessageOrEnum_GetDescriptor(VALUE klass);
|
100
71
|
|
72
|
+
// Decodes a Message from a byte sequence.
|
73
|
+
VALUE Message_decode_bytes(int size, const char* bytes, int options,
|
74
|
+
VALUE klass, bool freeze);
|
75
|
+
|
76
|
+
// Recursively freeze message
|
77
|
+
VALUE Message_freeze(VALUE _self);
|
78
|
+
|
101
79
|
// Call at startup to register all types in this module.
|
102
80
|
void Message_register(VALUE protobuf);
|
103
81
|
|