google-protobuf 3.21.2 → 4.29.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 +67 -86
- data/ext/google/protobuf_c/convert.h +3 -28
- data/ext/google/protobuf_c/defs.c +538 -77
- 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 +72 -0
- data/ext/google/protobuf_c/map.c +114 -85
- data/ext/google/protobuf_c/map.h +12 -30
- data/ext/google/protobuf_c/message.c +264 -238
- data/ext/google/protobuf_c/message.h +11 -33
- data/ext/google/protobuf_c/protobuf.c +63 -187
- data/ext/google/protobuf_c/protobuf.h +27 -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 +13783 -8236
- data/ext/google/protobuf_c/ruby-upb.h +14077 -4495
- 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/LICENSE +1 -0
- data/ext/google/protobuf_c/third_party/utf8_range/utf8_range.c +467 -0
- data/ext/google/protobuf_c/third_party/utf8_range/utf8_range.h +20 -7
- data/ext/google/protobuf_c/wrap_memcpy.c +3 -26
- data/lib/google/protobuf/any_pb.rb +6 -8
- data/lib/google/protobuf/api_pb.rb +6 -26
- data/lib/google/protobuf/descriptor_pb.rb +23 -226
- data/lib/google/protobuf/duration_pb.rb +6 -8
- data/lib/google/protobuf/empty_pb.rb +6 -6
- data/lib/google/protobuf/ffi/descriptor.rb +165 -0
- data/lib/google/protobuf/ffi/descriptor_pool.rb +77 -0
- data/lib/google/protobuf/ffi/enum_descriptor.rb +173 -0
- data/lib/google/protobuf/ffi/ffi.rb +215 -0
- data/lib/google/protobuf/ffi/field_descriptor.rb +330 -0
- data/lib/google/protobuf/ffi/file_descriptor.rb +49 -0
- data/lib/google/protobuf/ffi/internal/arena.rb +60 -0
- data/lib/google/protobuf/ffi/internal/convert.rb +296 -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 +433 -0
- data/lib/google/protobuf/ffi/message.rb +785 -0
- data/lib/google/protobuf/ffi/method_descriptor.rb +114 -0
- data/lib/google/protobuf/ffi/object_cache.rb +30 -0
- data/lib/google/protobuf/ffi/oneof_descriptor.rb +97 -0
- data/lib/google/protobuf/ffi/repeated_field.rb +411 -0
- data/lib/google/protobuf/ffi/service_descriptor.rb +107 -0
- data/lib/google/protobuf/field_mask_pb.rb +6 -7
- data/lib/google/protobuf/internal/object_cache.rb +99 -0
- data/lib/google/protobuf/message_exts.rb +8 -26
- data/lib/google/protobuf/plugin_pb.rb +25 -0
- data/lib/google/protobuf/repeated_field.rb +7 -31
- data/lib/google/protobuf/source_context_pb.rb +6 -7
- data/lib/google/protobuf/struct_pb.rb +6 -23
- data/lib/google/protobuf/timestamp_pb.rb +6 -8
- data/lib/google/protobuf/type_pb.rb +6 -71
- data/lib/google/protobuf/well_known_types.rb +5 -34
- data/lib/google/protobuf/wrappers_pb.rb +6 -31
- data/lib/google/protobuf.rb +27 -45
- data/lib/google/protobuf_ffi.rb +51 -0
- data/lib/google/protobuf_native.rb +19 -0
- data/lib/google/tasks/ffi.rake +100 -0
- metadata +92 -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
- 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*
|
@@ -63,10 +44,12 @@ static void Message_mark(void* _self) {
|
|
63
44
|
rb_gc_mark(self->arena);
|
64
45
|
}
|
65
46
|
|
47
|
+
static size_t Message_memsize(const void* _self) { return sizeof(Message); }
|
48
|
+
|
66
49
|
static rb_data_type_t Message_type = {
|
67
|
-
"Message",
|
68
|
-
{Message_mark, RUBY_DEFAULT_FREE,
|
69
|
-
.flags = RUBY_TYPED_FREE_IMMEDIATELY,
|
50
|
+
"Google::Protobuf::Message",
|
51
|
+
{Message_mark, RUBY_DEFAULT_FREE, Message_memsize},
|
52
|
+
.flags = RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
|
70
53
|
};
|
71
54
|
|
72
55
|
static Message* ruby_to_Message(VALUE msg_rb) {
|
@@ -97,15 +80,19 @@ const upb_Message* Message_Get(VALUE msg_rb, const upb_MessageDef** m) {
|
|
97
80
|
}
|
98
81
|
|
99
82
|
upb_Message* Message_GetMutable(VALUE msg_rb, const upb_MessageDef** m) {
|
100
|
-
|
101
|
-
|
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;
|
102
86
|
}
|
103
87
|
|
104
|
-
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);
|
105
90
|
Message* self = ruby_to_Message(self_);
|
106
91
|
self->msg = msg;
|
107
|
-
self->arena
|
108
|
-
|
92
|
+
RB_OBJ_WRITE(self_, &self->arena, arena);
|
93
|
+
VALUE stored = ObjectCache_TryAdd(msg, self_);
|
94
|
+
(void)stored;
|
95
|
+
PBRUBY_ASSERT(stored == self_);
|
109
96
|
}
|
110
97
|
|
111
98
|
VALUE Message_GetArena(VALUE msg_rb) {
|
@@ -120,7 +107,7 @@ void Message_CheckClass(VALUE klass) {
|
|
120
107
|
}
|
121
108
|
}
|
122
109
|
|
123
|
-
VALUE Message_GetRubyWrapper(upb_Message* msg, const upb_MessageDef* m,
|
110
|
+
VALUE Message_GetRubyWrapper(const upb_Message* msg, const upb_MessageDef* m,
|
124
111
|
VALUE arena) {
|
125
112
|
if (msg == NULL) return Qnil;
|
126
113
|
|
@@ -131,7 +118,6 @@ VALUE Message_GetRubyWrapper(upb_Message* msg, const upb_MessageDef* m,
|
|
131
118
|
val = Message_alloc(klass);
|
132
119
|
Message_InitPtr(val, msg, arena);
|
133
120
|
}
|
134
|
-
|
135
121
|
return val;
|
136
122
|
}
|
137
123
|
|
@@ -145,7 +131,8 @@ void Message_PrintMessage(StringBuilder* b, const upb_Message* msg,
|
|
145
131
|
for (int i = 0; i < n; i++) {
|
146
132
|
const upb_FieldDef* field = upb_MessageDef_Field(m, i);
|
147
133
|
|
148
|
-
if (upb_FieldDef_HasPresence(field) &&
|
134
|
+
if (upb_FieldDef_HasPresence(field) &&
|
135
|
+
!upb_Message_HasFieldByDef(msg, field)) {
|
149
136
|
continue;
|
150
137
|
}
|
151
138
|
|
@@ -155,7 +142,7 @@ void Message_PrintMessage(StringBuilder* b, const upb_Message* msg,
|
|
155
142
|
first = false;
|
156
143
|
}
|
157
144
|
|
158
|
-
upb_MessageValue msgval =
|
145
|
+
upb_MessageValue msgval = upb_Message_GetFieldByDef(msg, field);
|
159
146
|
|
160
147
|
StringBuilder_Printf(b, "%s: ", upb_FieldDef_Name(field));
|
161
148
|
|
@@ -241,15 +228,6 @@ static int extract_method_call(VALUE method_name, Message* self,
|
|
241
228
|
if (Match(m, name, f, o, "clear_", "")) return METHOD_CLEAR;
|
242
229
|
if (Match(m, name, f, o, "has_", "?") &&
|
243
230
|
(*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
231
|
return METHOD_PRESENCE;
|
254
232
|
}
|
255
233
|
if (Match(m, name, f, o, "", "_as_value") && *f &&
|
@@ -271,14 +249,15 @@ static int extract_method_call(VALUE method_name, Message* self,
|
|
271
249
|
static VALUE Message_oneof_accessor(VALUE _self, const upb_OneofDef* o,
|
272
250
|
int accessor_type) {
|
273
251
|
Message* self = ruby_to_Message(_self);
|
274
|
-
const upb_FieldDef* oneof_field =
|
252
|
+
const upb_FieldDef* oneof_field = upb_Message_WhichOneofByDef(self->msg, o);
|
275
253
|
|
276
254
|
switch (accessor_type) {
|
277
255
|
case METHOD_PRESENCE:
|
278
256
|
return oneof_field == NULL ? Qfalse : Qtrue;
|
279
257
|
case METHOD_CLEAR:
|
280
258
|
if (oneof_field != NULL) {
|
281
|
-
|
259
|
+
upb_Message_ClearFieldByDef(Message_GetMutable(_self, NULL),
|
260
|
+
oneof_field);
|
282
261
|
}
|
283
262
|
return Qnil;
|
284
263
|
case METHOD_GETTER:
|
@@ -301,22 +280,51 @@ static void Message_setfield(upb_Message* msg, const upb_FieldDef* f, VALUE val,
|
|
301
280
|
} else {
|
302
281
|
if (val == Qnil &&
|
303
282
|
(upb_FieldDef_IsSubMessage(f) || upb_FieldDef_RealContainingOneof(f))) {
|
304
|
-
|
283
|
+
upb_Message_ClearFieldByDef(msg, f);
|
305
284
|
return;
|
306
285
|
}
|
307
286
|
msgval =
|
308
287
|
Convert_RubyToUpb(val, upb_FieldDef_Name(f), TypeInfo_get(f), arena);
|
309
288
|
}
|
310
|
-
|
289
|
+
upb_Message_SetFieldByDef(msg, f, msgval, arena);
|
290
|
+
}
|
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;
|
311
320
|
}
|
312
321
|
|
313
322
|
VALUE Message_getfield(VALUE _self, const upb_FieldDef* f) {
|
314
323
|
Message* self = ruby_to_Message(_self);
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
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);
|
320
328
|
upb_Arena* arena = Arena_get(self->arena);
|
321
329
|
if (upb_FieldDef_IsMap(f)) {
|
322
330
|
upb_Map* map = upb_Message_Mutable(msg, f, arena).map;
|
@@ -329,12 +337,12 @@ VALUE Message_getfield(VALUE _self, const upb_FieldDef* f) {
|
|
329
337
|
upb_Array* arr = upb_Message_Mutable(msg, f, arena).array;
|
330
338
|
return RepeatedField_GetRubyWrapper(arr, TypeInfo_get(f), self->arena);
|
331
339
|
} else if (upb_FieldDef_IsSubMessage(f)) {
|
332
|
-
if (!
|
340
|
+
if (!upb_Message_HasFieldByDef(msg, f)) return Qnil;
|
333
341
|
upb_Message* submsg = upb_Message_Mutable(msg, f, arena).msg;
|
334
342
|
const upb_MessageDef* m = upb_FieldDef_MessageSubDef(f);
|
335
343
|
return Message_GetRubyWrapper(submsg, m, self->arena);
|
336
344
|
} else {
|
337
|
-
upb_MessageValue msgval =
|
345
|
+
upb_MessageValue msgval = upb_Message_GetFieldByDef(msg, f);
|
338
346
|
return Convert_UpbToRuby(msgval, TypeInfo_get(f), self->arena);
|
339
347
|
}
|
340
348
|
}
|
@@ -348,23 +356,24 @@ static VALUE Message_field_accessor(VALUE _self, const upb_FieldDef* f,
|
|
348
356
|
Message_setfield(Message_GetMutable(_self, NULL), f, argv[1], arena);
|
349
357
|
return Qnil;
|
350
358
|
case METHOD_CLEAR:
|
351
|
-
|
359
|
+
upb_Message_ClearFieldByDef(Message_GetMutable(_self, NULL), f);
|
352
360
|
return Qnil;
|
353
361
|
case METHOD_PRESENCE:
|
354
362
|
if (!upb_FieldDef_HasPresence(f)) {
|
355
363
|
rb_raise(rb_eRuntimeError, "Field does not have presence.");
|
356
364
|
}
|
357
|
-
return
|
365
|
+
return upb_Message_HasFieldByDef(Message_Get(_self, NULL), f);
|
358
366
|
case METHOD_WRAPPER_GETTER: {
|
359
367
|
Message* self = ruby_to_Message(_self);
|
360
|
-
if (
|
368
|
+
if (upb_Message_HasFieldByDef(self->msg, f)) {
|
361
369
|
PBRUBY_ASSERT(upb_FieldDef_IsSubMessage(f) &&
|
362
370
|
!upb_FieldDef_IsRepeated(f));
|
363
|
-
upb_MessageValue wrapper =
|
371
|
+
upb_MessageValue wrapper = upb_Message_GetFieldByDef(self->msg, f);
|
364
372
|
const upb_MessageDef* wrapper_m = upb_FieldDef_MessageSubDef(f);
|
365
373
|
const upb_FieldDef* value_f =
|
366
374
|
upb_MessageDef_FindFieldByNumber(wrapper_m, 1);
|
367
|
-
upb_MessageValue value =
|
375
|
+
upb_MessageValue value =
|
376
|
+
upb_Message_GetFieldByDef(wrapper.msg_val, value_f);
|
368
377
|
return Convert_UpbToRuby(value, TypeInfo_get(value_f), self->arena);
|
369
378
|
} else {
|
370
379
|
return Qnil;
|
@@ -373,19 +382,20 @@ static VALUE Message_field_accessor(VALUE _self, const upb_FieldDef* f,
|
|
373
382
|
case METHOD_WRAPPER_SETTER: {
|
374
383
|
upb_Message* msg = Message_GetMutable(_self, NULL);
|
375
384
|
if (argv[1] == Qnil) {
|
376
|
-
|
385
|
+
upb_Message_ClearFieldByDef(msg, f);
|
377
386
|
} else {
|
378
387
|
const upb_FieldDef* val_f =
|
379
388
|
upb_MessageDef_FindFieldByNumber(upb_FieldDef_MessageSubDef(f), 1);
|
380
389
|
upb_MessageValue msgval = Convert_RubyToUpb(
|
381
390
|
argv[1], upb_FieldDef_Name(f), TypeInfo_get(val_f), arena);
|
382
391
|
upb_Message* wrapper = upb_Message_Mutable(msg, f, arena).msg;
|
383
|
-
|
392
|
+
upb_Message_SetFieldByDef(wrapper, val_f, msgval, arena);
|
384
393
|
}
|
385
394
|
return Qnil;
|
386
395
|
}
|
387
396
|
case METHOD_ENUM_GETTER: {
|
388
|
-
upb_MessageValue msgval =
|
397
|
+
upb_MessageValue msgval =
|
398
|
+
upb_Message_GetFieldByDef(Message_Get(_self, NULL), f);
|
389
399
|
|
390
400
|
if (upb_FieldDef_Label(f) == kUpb_Label_Repeated) {
|
391
401
|
// Map repeated fields to a new type with ints
|
@@ -456,7 +466,6 @@ static VALUE Message_method_missing(int argc, VALUE* argv, VALUE _self) {
|
|
456
466
|
if (argc != 2) {
|
457
467
|
rb_raise(rb_eArgError, "Expected 2 arguments, received %d", argc);
|
458
468
|
}
|
459
|
-
rb_check_frozen(_self);
|
460
469
|
break;
|
461
470
|
default:
|
462
471
|
if (argc != 1) {
|
@@ -510,8 +519,9 @@ static int Map_initialize_kwarg(VALUE key, VALUE val, VALUE _self) {
|
|
510
519
|
k = Convert_RubyToUpb(key, "", map_init->key_type, NULL);
|
511
520
|
|
512
521
|
if (map_init->val_type.type == kUpb_CType_Message && TYPE(val) == T_HASH) {
|
513
|
-
|
514
|
-
|
522
|
+
const upb_MiniTable* t =
|
523
|
+
upb_MessageDef_MiniTable(map_init->val_type.def.msgdef);
|
524
|
+
upb_Message* msg = upb_Message_New(t, map_init->arena);
|
515
525
|
Message_InitFromValue(msg, map_init->val_type.def.msgdef, val,
|
516
526
|
map_init->arena);
|
517
527
|
v.msg_val = msg;
|
@@ -541,7 +551,8 @@ static upb_MessageValue MessageValue_FromValue(VALUE val, TypeInfo info,
|
|
541
551
|
upb_Arena* arena) {
|
542
552
|
if (info.type == kUpb_CType_Message) {
|
543
553
|
upb_MessageValue msgval;
|
544
|
-
|
554
|
+
const upb_MiniTable* t = upb_MessageDef_MiniTable(info.def.msgdef);
|
555
|
+
upb_Message* msg = upb_Message_New(t, arena);
|
545
556
|
Message_InitFromValue(msg, info.def.msgdef, val, arena);
|
546
557
|
msgval.msg_val = msg;
|
547
558
|
return msgval;
|
@@ -593,7 +604,7 @@ static void Message_InitFieldFromValue(upb_Message* msg, const upb_FieldDef* f,
|
|
593
604
|
} else {
|
594
605
|
upb_MessageValue msgval =
|
595
606
|
Convert_RubyToUpb(val, upb_FieldDef_Name(f), TypeInfo_get(f), arena);
|
596
|
-
|
607
|
+
upb_Message_SetFieldByDef(msg, f, msgval, arena);
|
597
608
|
}
|
598
609
|
}
|
599
610
|
|
@@ -656,7 +667,8 @@ static VALUE Message_initialize(int argc, VALUE* argv, VALUE _self) {
|
|
656
667
|
Message* self = ruby_to_Message(_self);
|
657
668
|
VALUE arena_rb = Arena_new();
|
658
669
|
upb_Arena* arena = Arena_get(arena_rb);
|
659
|
-
|
670
|
+
const upb_MiniTable* t = upb_MessageDef_MiniTable(self->msgdef);
|
671
|
+
upb_Message* msg = upb_Message_New(t, arena);
|
660
672
|
|
661
673
|
Message_InitPtr(_self, msg, arena_rb);
|
662
674
|
|
@@ -680,39 +692,12 @@ static VALUE Message_dup(VALUE _self) {
|
|
680
692
|
Message* self = ruby_to_Message(_self);
|
681
693
|
VALUE new_msg = rb_class_new_instance(0, NULL, CLASS_OF(_self));
|
682
694
|
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);
|
695
|
+
const upb_MiniTable* m = upb_MessageDef_MiniTable(self->msgdef);
|
696
|
+
upb_Message_ShallowCopy((upb_Message*)new_msg_self->msg, self->msg, m);
|
688
697
|
Arena_fuse(self->arena, Arena_get(new_msg_self->arena));
|
689
698
|
return new_msg;
|
690
699
|
}
|
691
700
|
|
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 = kUpb_Encode_SkipUnknown | kUpb_Encode_Deterministic;
|
699
|
-
upb_Arena* arena_tmp = upb_Arena_New();
|
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;
|
710
|
-
} else {
|
711
|
-
upb_Arena_Free(arena_tmp);
|
712
|
-
rb_raise(cParseError, "Error comparing messages");
|
713
|
-
}
|
714
|
-
}
|
715
|
-
|
716
701
|
/*
|
717
702
|
* call-seq:
|
718
703
|
* Message.==(other) => boolean
|
@@ -729,27 +714,22 @@ static VALUE Message_eq(VALUE _self, VALUE _other) {
|
|
729
714
|
Message* other = ruby_to_Message(_other);
|
730
715
|
assert(self->msgdef == other->msgdef);
|
731
716
|
|
732
|
-
|
717
|
+
const upb_MiniTable* m = upb_MessageDef_MiniTable(self->msgdef);
|
718
|
+
const int options = 0;
|
719
|
+
return upb_Message_IsEqual(self->msg, other->msg, m, options) ? Qtrue
|
720
|
+
: Qfalse;
|
733
721
|
}
|
734
722
|
|
735
723
|
uint64_t Message_Hash(const upb_Message* msg, const upb_MessageDef* m,
|
736
724
|
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;
|
725
|
+
upb_Status status;
|
726
|
+
upb_Status_Clear(&status);
|
727
|
+
uint64_t return_value = shared_Message_Hash(msg, m, seed, &status);
|
728
|
+
if (upb_Status_IsOk(&status)) {
|
729
|
+
return return_value;
|
750
730
|
} else {
|
751
|
-
|
752
|
-
|
731
|
+
rb_raise(cParseError, "Message_Hash(): %s",
|
732
|
+
upb_Status_ErrorMessage(&status));
|
753
733
|
}
|
754
734
|
}
|
755
735
|
|
@@ -806,57 +786,34 @@ static VALUE Message_CreateHash(const upb_Message* msg,
|
|
806
786
|
if (!msg) return Qnil;
|
807
787
|
|
808
788
|
VALUE hash = rb_hash_new();
|
809
|
-
|
810
|
-
|
811
|
-
|
812
|
-
|
813
|
-
// This is unfortunate, we should key behaviors off field attributes (like
|
814
|
-
// whether a field has presence), not proto2 vs. proto3. We should see if we
|
815
|
-
// can change this without breaking users.
|
816
|
-
is_proto2 = upb_MessageDef_Syntax(m) == kUpb_Syntax_Proto2;
|
817
|
-
|
818
|
-
for (int i = 0; i < n; i++) {
|
819
|
-
const upb_FieldDef* field = upb_MessageDef_Field(m, i);
|
820
|
-
TypeInfo type_info = TypeInfo_get(field);
|
821
|
-
upb_MessageValue msgval;
|
822
|
-
VALUE msg_value;
|
823
|
-
VALUE msg_key;
|
824
|
-
|
825
|
-
if (!is_proto2 && upb_FieldDef_IsSubMessage(field) &&
|
826
|
-
!upb_FieldDef_IsRepeated(field) && !upb_Message_Has(msg, field)) {
|
827
|
-
// TODO: Legacy behavior, remove when we fix the is_proto2 differences.
|
828
|
-
msg_key = ID2SYM(rb_intern(upb_FieldDef_Name(field)));
|
829
|
-
rb_hash_aset(hash, msg_key, Qnil);
|
830
|
-
continue;
|
831
|
-
}
|
789
|
+
size_t iter = kUpb_Message_Begin;
|
790
|
+
const upb_DefPool* pool = upb_FileDef_Pool(upb_MessageDef_File(m));
|
791
|
+
const upb_FieldDef* field;
|
792
|
+
upb_MessageValue val;
|
832
793
|
|
833
|
-
|
834
|
-
if (
|
835
|
-
|
794
|
+
while (upb_Message_Next(msg, m, pool, &field, &val, &iter)) {
|
795
|
+
if (upb_FieldDef_IsExtension(field)) {
|
796
|
+
// TODO: allow extensions once we have decided what naming scheme the
|
797
|
+
// symbol should use. eg. :"[pkg.ext]"
|
836
798
|
continue;
|
837
799
|
}
|
838
800
|
|
839
|
-
|
840
|
-
|
841
|
-
|
842
|
-
// Proto2 omits empty map/repeated filds also.
|
801
|
+
TypeInfo type_info = TypeInfo_get(field);
|
802
|
+
VALUE msg_value;
|
843
803
|
|
844
804
|
if (upb_FieldDef_IsMap(field)) {
|
845
805
|
const upb_MessageDef* entry_m = upb_FieldDef_MessageSubDef(field);
|
846
806
|
const upb_FieldDef* key_f = upb_MessageDef_FindFieldByNumber(entry_m, 1);
|
847
807
|
const upb_FieldDef* val_f = upb_MessageDef_FindFieldByNumber(entry_m, 2);
|
848
808
|
upb_CType key_type = upb_FieldDef_CType(key_f);
|
849
|
-
msg_value = Map_CreateHash(
|
809
|
+
msg_value = Map_CreateHash(val.map_val, key_type, TypeInfo_get(val_f));
|
850
810
|
} else if (upb_FieldDef_IsRepeated(field)) {
|
851
|
-
|
852
|
-
(!msgval.array_val || upb_Array_Size(msgval.array_val) == 0)) {
|
853
|
-
continue;
|
854
|
-
}
|
855
|
-
msg_value = RepeatedField_CreateArray(msgval.array_val, type_info);
|
811
|
+
msg_value = RepeatedField_CreateArray(val.array_val, type_info);
|
856
812
|
} else {
|
857
|
-
msg_value = Scalar_CreateHash(
|
813
|
+
msg_value = Scalar_CreateHash(val, type_info);
|
858
814
|
}
|
859
815
|
|
816
|
+
VALUE msg_key = ID2SYM(rb_intern(upb_FieldDef_Name(field)));
|
860
817
|
rb_hash_aset(hash, msg_key, msg_value);
|
861
818
|
}
|
862
819
|
|
@@ -882,19 +839,44 @@ static VALUE Message_to_h(VALUE _self) {
|
|
882
839
|
return Message_CreateHash(self->msg, self->msgdef);
|
883
840
|
}
|
884
841
|
|
842
|
+
/*
|
843
|
+
* call-seq:
|
844
|
+
* Message.frozen? => bool
|
845
|
+
*
|
846
|
+
* Returns true if the message is frozen in either Ruby or the underlying
|
847
|
+
* representation. Freezes the Ruby message object if it is not already frozen
|
848
|
+
* in Ruby but it is frozen in the underlying representation.
|
849
|
+
*/
|
850
|
+
VALUE Message_frozen(VALUE _self) {
|
851
|
+
Message* self = ruby_to_Message(_self);
|
852
|
+
if (!upb_Message_IsFrozen(self->msg)) {
|
853
|
+
PBRUBY_ASSERT(!RB_OBJ_FROZEN(_self));
|
854
|
+
return Qfalse;
|
855
|
+
}
|
856
|
+
|
857
|
+
// Lazily freeze the Ruby wrapper.
|
858
|
+
if (!RB_OBJ_FROZEN(_self)) RB_OBJ_FREEZE(_self);
|
859
|
+
return Qtrue;
|
860
|
+
}
|
861
|
+
|
885
862
|
/*
|
886
863
|
* call-seq:
|
887
864
|
* Message.freeze => self
|
888
865
|
*
|
889
|
-
* Freezes the message object. We have to intercept this so we can
|
890
|
-
*
|
866
|
+
* Freezes the message object. We have to intercept this so we can freeze the
|
867
|
+
* underlying representation, not just the Ruby wrapper.
|
891
868
|
*/
|
892
|
-
|
869
|
+
VALUE Message_freeze(VALUE _self) {
|
893
870
|
Message* self = ruby_to_Message(_self);
|
894
|
-
if (
|
895
|
-
|
896
|
-
|
871
|
+
if (RB_OBJ_FROZEN(_self)) {
|
872
|
+
PBRUBY_ASSERT(upb_Message_IsFrozen(self->msg));
|
873
|
+
return _self;
|
897
874
|
}
|
875
|
+
if (!upb_Message_IsFrozen(self->msg)) {
|
876
|
+
upb_Message_Freeze(Message_GetMutable(_self, NULL),
|
877
|
+
upb_MessageDef_MiniTable(self->msgdef));
|
878
|
+
}
|
879
|
+
RB_OBJ_FREEZE(_self);
|
898
880
|
return _self;
|
899
881
|
}
|
900
882
|
|
@@ -940,7 +922,7 @@ static VALUE Message_index_set(VALUE _self, VALUE field_name, VALUE value) {
|
|
940
922
|
}
|
941
923
|
|
942
924
|
val = Convert_RubyToUpb(value, upb_FieldDef_Name(f), TypeInfo_get(f), arena);
|
943
|
-
|
925
|
+
upb_Message_SetFieldByDef(Message_GetMutable(_self, NULL), f, val, arena);
|
944
926
|
|
945
927
|
return Qnil;
|
946
928
|
}
|
@@ -950,7 +932,7 @@ static VALUE Message_index_set(VALUE _self, VALUE field_name, VALUE value) {
|
|
950
932
|
* MessageClass.decode(data, options) => message
|
951
933
|
*
|
952
934
|
* Decodes the given data (as a string containing bytes in protocol buffers wire
|
953
|
-
* format) under the
|
935
|
+
* format) under the interpretation given by this message class's definition
|
954
936
|
* and returns a message object with the corresponding field values.
|
955
937
|
* @param options [Hash] options for the decoder
|
956
938
|
* recursion_limit: set to maximum decoding depth for message (default is 64)
|
@@ -969,10 +951,11 @@ static VALUE Message_decode(int argc, VALUE* argv, VALUE klass) {
|
|
969
951
|
rb_raise(rb_eArgError, "Expected hash arguments.");
|
970
952
|
}
|
971
953
|
|
972
|
-
VALUE depth =
|
954
|
+
VALUE depth =
|
955
|
+
rb_hash_lookup(hash_args, ID2SYM(rb_intern("recursion_limit")));
|
973
956
|
|
974
957
|
if (depth != Qnil && TYPE(depth) == T_FIXNUM) {
|
975
|
-
options |=
|
958
|
+
options |= upb_DecodeOptions_MaxDepth(FIX2INT(depth));
|
976
959
|
}
|
977
960
|
}
|
978
961
|
|
@@ -980,17 +963,27 @@ static VALUE Message_decode(int argc, VALUE* argv, VALUE klass) {
|
|
980
963
|
rb_raise(rb_eArgError, "Expected string for binary protobuf data.");
|
981
964
|
}
|
982
965
|
|
966
|
+
return Message_decode_bytes(RSTRING_LEN(data), RSTRING_PTR(data), options,
|
967
|
+
klass, /*freeze*/ false);
|
968
|
+
}
|
969
|
+
|
970
|
+
VALUE Message_decode_bytes(int size, const char* bytes, int options,
|
971
|
+
VALUE klass, bool freeze) {
|
983
972
|
VALUE msg_rb = initialize_rb_class_with_no_args(klass);
|
984
973
|
Message* msg = ruby_to_Message(msg_rb);
|
985
974
|
|
986
|
-
|
987
|
-
|
988
|
-
|
989
|
-
|
975
|
+
const upb_FileDef* file = upb_MessageDef_File(msg->msgdef);
|
976
|
+
const upb_ExtensionRegistry* extreg =
|
977
|
+
upb_DefPool_ExtensionRegistry(upb_FileDef_Pool(file));
|
978
|
+
upb_DecodeStatus status = upb_Decode(bytes, size, (upb_Message*)msg->msg,
|
979
|
+
upb_MessageDef_MiniTable(msg->msgdef),
|
980
|
+
extreg, options, Arena_get(msg->arena));
|
990
981
|
if (status != kUpb_DecodeStatus_Ok) {
|
991
982
|
rb_raise(cParseError, "Error occurred during parsing");
|
992
983
|
}
|
993
|
-
|
984
|
+
if (freeze) {
|
985
|
+
Message_freeze(msg_rb);
|
986
|
+
}
|
994
987
|
return msg_rb;
|
995
988
|
}
|
996
989
|
|
@@ -1011,9 +1004,6 @@ static VALUE Message_decode_json(int argc, VALUE* argv, VALUE klass) {
|
|
1011
1004
|
int options = 0;
|
1012
1005
|
upb_Status status;
|
1013
1006
|
|
1014
|
-
// TODO(haberman): use this message's pool instead.
|
1015
|
-
const upb_DefPool* symtab = DescriptorPool_GetSymtab(generated_pool);
|
1016
|
-
|
1017
1007
|
if (argc < 1 || argc > 2) {
|
1018
1008
|
rb_raise(rb_eArgError, "Expected 1 or 2 arguments.");
|
1019
1009
|
}
|
@@ -1034,7 +1024,7 @@ static VALUE Message_decode_json(int argc, VALUE* argv, VALUE klass) {
|
|
1034
1024
|
rb_raise(rb_eArgError, "Expected string for JSON data.");
|
1035
1025
|
}
|
1036
1026
|
|
1037
|
-
// TODO
|
1027
|
+
// TODO: Check and respect string encoding. If not UTF-8, we need to
|
1038
1028
|
// convert, because string handlers pass data directly to message string
|
1039
1029
|
// fields.
|
1040
1030
|
|
@@ -1047,11 +1037,22 @@ static VALUE Message_decode_json(int argc, VALUE* argv, VALUE klass) {
|
|
1047
1037
|
}
|
1048
1038
|
|
1049
1039
|
upb_Status_Clear(&status);
|
1050
|
-
|
1051
|
-
|
1052
|
-
|
1053
|
-
|
1054
|
-
|
1040
|
+
const upb_DefPool* pool = upb_FileDef_Pool(upb_MessageDef_File(msg->msgdef));
|
1041
|
+
|
1042
|
+
int result = upb_JsonDecodeDetectingNonconformance(
|
1043
|
+
RSTRING_PTR(data), RSTRING_LEN(data), (upb_Message*)msg->msg,
|
1044
|
+
msg->msgdef, pool, options, Arena_get(msg->arena), &status);
|
1045
|
+
|
1046
|
+
switch (result) {
|
1047
|
+
case kUpb_JsonDecodeResult_Ok:
|
1048
|
+
break;
|
1049
|
+
case kUpb_JsonDecodeResult_OkWithEmptyStringNumerics:
|
1050
|
+
rb_warn("%s", upb_Status_ErrorMessage(&status));
|
1051
|
+
break;
|
1052
|
+
case kUpb_JsonDecodeResult_Error:
|
1053
|
+
rb_raise(cParseError, "Error occurred during parsing: %s",
|
1054
|
+
upb_Status_ErrorMessage(&status));
|
1055
|
+
break;
|
1055
1056
|
}
|
1056
1057
|
|
1057
1058
|
return msg_rb;
|
@@ -1069,7 +1070,7 @@ static VALUE Message_decode_json(int argc, VALUE* argv, VALUE klass) {
|
|
1069
1070
|
static VALUE Message_encode(int argc, VALUE* argv, VALUE klass) {
|
1070
1071
|
Message* msg = ruby_to_Message(argv[0]);
|
1071
1072
|
int options = 0;
|
1072
|
-
|
1073
|
+
char* data;
|
1073
1074
|
size_t size;
|
1074
1075
|
|
1075
1076
|
if (CLASS_OF(argv[0]) != klass) {
|
@@ -1085,19 +1086,21 @@ static VALUE Message_encode(int argc, VALUE* argv, VALUE klass) {
|
|
1085
1086
|
if (TYPE(hash_args) != T_HASH) {
|
1086
1087
|
rb_raise(rb_eArgError, "Expected hash arguments.");
|
1087
1088
|
}
|
1088
|
-
VALUE depth =
|
1089
|
+
VALUE depth =
|
1090
|
+
rb_hash_lookup(hash_args, ID2SYM(rb_intern("recursion_limit")));
|
1089
1091
|
|
1090
1092
|
if (depth != Qnil && TYPE(depth) == T_FIXNUM) {
|
1091
|
-
options |=
|
1093
|
+
options |= upb_DecodeOptions_MaxDepth(FIX2INT(depth));
|
1092
1094
|
}
|
1093
1095
|
}
|
1094
1096
|
|
1095
|
-
upb_Arena
|
1097
|
+
upb_Arena* arena = upb_Arena_New();
|
1096
1098
|
|
1097
|
-
|
1098
|
-
|
1099
|
+
upb_EncodeStatus status =
|
1100
|
+
upb_Encode(msg->msg, upb_MessageDef_MiniTable(msg->msgdef), options,
|
1101
|
+
arena, &data, &size);
|
1099
1102
|
|
1100
|
-
if (
|
1103
|
+
if (status == kUpb_EncodeStatus_Ok) {
|
1101
1104
|
VALUE ret = rb_str_new(data, size);
|
1102
1105
|
rb_enc_associate(ret, rb_ascii8bit_encoding());
|
1103
1106
|
upb_Arena_Free(arena);
|
@@ -1125,9 +1128,6 @@ static VALUE Message_encode_json(int argc, VALUE* argv, VALUE klass) {
|
|
1125
1128
|
size_t size;
|
1126
1129
|
upb_Status status;
|
1127
1130
|
|
1128
|
-
// TODO(haberman): use this message's pool instead.
|
1129
|
-
const upb_DefPool* symtab = DescriptorPool_GetSymtab(generated_pool);
|
1130
|
-
|
1131
1131
|
if (argc < 1 || argc > 2) {
|
1132
1132
|
rb_raise(rb_eArgError, "Expected 1 or 2 arguments.");
|
1133
1133
|
}
|
@@ -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,11 +1153,18 @@ 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);
|
1158
|
-
|
1159
|
-
|
1165
|
+
const upb_DefPool* pool = upb_FileDef_Pool(upb_MessageDef_File(msg->msgdef));
|
1166
|
+
size = upb_JsonEncode(msg->msg, msg->msgdef, pool, options, buf, sizeof(buf),
|
1167
|
+
&status);
|
1160
1168
|
|
1161
1169
|
if (!upb_Status_IsOk(&status)) {
|
1162
1170
|
rb_raise(cParseError, "Error occurred during encoding: %s",
|
@@ -1166,7 +1174,7 @@ static VALUE Message_encode_json(int argc, VALUE* argv, VALUE klass) {
|
|
1166
1174
|
VALUE ret;
|
1167
1175
|
if (size >= sizeof(buf)) {
|
1168
1176
|
char* buf2 = malloc(size + 1);
|
1169
|
-
upb_JsonEncode(msg->msg, msg->msgdef,
|
1177
|
+
upb_JsonEncode(msg->msg, msg->msgdef, pool, options, buf2, size + 1,
|
1170
1178
|
&status);
|
1171
1179
|
ret = rb_str_new(buf2, size);
|
1172
1180
|
free(buf2);
|
@@ -1201,36 +1209,8 @@ VALUE build_class_from_descriptor(VALUE descriptor) {
|
|
1201
1209
|
klass = rb_define_class_id(
|
1202
1210
|
// Docs say this parameter is ignored. User will assign return value to
|
1203
1211
|
// their own toplevel constant class name.
|
1204
|
-
rb_intern("Message"),
|
1212
|
+
rb_intern("Message"), cAbstractMessage);
|
1205
1213
|
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
1214
|
return klass;
|
1235
1215
|
}
|
1236
1216
|
|
@@ -1290,15 +1270,22 @@ VALUE build_module_from_enumdesc(VALUE _enumdesc) {
|
|
1290
1270
|
int n = upb_EnumDef_ValueCount(e);
|
1291
1271
|
for (int i = 0; i < n; i++) {
|
1292
1272
|
const upb_EnumValueDef* ev = upb_EnumDef_Value(e, i);
|
1293
|
-
|
1273
|
+
upb_Arena* arena = upb_Arena_New();
|
1274
|
+
const char* src_name = upb_EnumValueDef_Name(ev);
|
1275
|
+
char* name = upb_strdup2(src_name, strlen(src_name), arena);
|
1294
1276
|
int32_t value = upb_EnumValueDef_Number(ev);
|
1295
1277
|
if (name[0] < 'A' || name[0] > 'Z') {
|
1296
|
-
|
1297
|
-
|
1298
|
-
|
1299
|
-
|
1278
|
+
if (name[0] >= 'a' && name[0] <= 'z') {
|
1279
|
+
name[0] -= 32; // auto capitalize
|
1280
|
+
} else {
|
1281
|
+
rb_warn(
|
1282
|
+
"Enum value '%s' does not start with an uppercase letter "
|
1283
|
+
"as is required for Ruby constants.",
|
1284
|
+
name);
|
1285
|
+
}
|
1300
1286
|
}
|
1301
1287
|
rb_define_const(mod, name, INT2NUM(value));
|
1288
|
+
upb_Arena_Free(arena);
|
1302
1289
|
}
|
1303
1290
|
|
1304
1291
|
rb_define_singleton_method(mod, "lookup", enum_lookup, 1);
|
@@ -1309,7 +1296,7 @@ VALUE build_module_from_enumdesc(VALUE _enumdesc) {
|
|
1309
1296
|
return mod;
|
1310
1297
|
}
|
1311
1298
|
|
1312
|
-
// Internal
|
1299
|
+
// Internal to the library; used by Google::Protobuf.deep_copy.
|
1313
1300
|
upb_Message* Message_deep_copy(const upb_Message* msg, const upb_MessageDef* m,
|
1314
1301
|
upb_Arena* arena) {
|
1315
1302
|
// Serialize and parse.
|
@@ -1317,11 +1304,16 @@ upb_Message* Message_deep_copy(const upb_Message* msg, const upb_MessageDef* m,
|
|
1317
1304
|
const upb_MiniTable* layout = upb_MessageDef_MiniTable(m);
|
1318
1305
|
size_t size;
|
1319
1306
|
|
1320
|
-
|
1321
|
-
|
1307
|
+
upb_Message* new_msg = upb_Message_New(layout, arena);
|
1308
|
+
char* data;
|
1322
1309
|
|
1323
|
-
|
1324
|
-
|
1310
|
+
const upb_FileDef* file = upb_MessageDef_File(m);
|
1311
|
+
const upb_ExtensionRegistry* extreg =
|
1312
|
+
upb_DefPool_ExtensionRegistry(upb_FileDef_Pool(file));
|
1313
|
+
if (upb_Encode(msg, layout, 0, tmp_arena, &data, &size) !=
|
1314
|
+
kUpb_EncodeStatus_Ok ||
|
1315
|
+
upb_Decode(data, size, new_msg, layout, extreg, 0, arena) !=
|
1316
|
+
kUpb_DecodeStatus_Ok) {
|
1325
1317
|
upb_Arena_Free(tmp_arena);
|
1326
1318
|
rb_raise(cParseError, "Error occurred copying proto");
|
1327
1319
|
}
|
@@ -1348,7 +1340,8 @@ const upb_Message* Message_GetUpbMessage(VALUE value, const upb_MessageDef* m,
|
|
1348
1340
|
switch (upb_MessageDef_WellKnownType(m)) {
|
1349
1341
|
case kUpb_WellKnown_Timestamp: {
|
1350
1342
|
// Time -> Google::Protobuf::Timestamp
|
1351
|
-
|
1343
|
+
const upb_MiniTable* t = upb_MessageDef_MiniTable(m);
|
1344
|
+
upb_Message* msg = upb_Message_New(t, arena);
|
1352
1345
|
upb_MessageValue sec, nsec;
|
1353
1346
|
struct timespec time;
|
1354
1347
|
const upb_FieldDef* sec_f = upb_MessageDef_FindFieldByNumber(m, 1);
|
@@ -1359,13 +1352,14 @@ const upb_Message* Message_GetUpbMessage(VALUE value, const upb_MessageDef* m,
|
|
1359
1352
|
time = rb_time_timespec(value);
|
1360
1353
|
sec.int64_val = time.tv_sec;
|
1361
1354
|
nsec.int32_val = time.tv_nsec;
|
1362
|
-
|
1363
|
-
|
1355
|
+
upb_Message_SetFieldByDef(msg, sec_f, sec, arena);
|
1356
|
+
upb_Message_SetFieldByDef(msg, nsec_f, nsec, arena);
|
1364
1357
|
return msg;
|
1365
1358
|
}
|
1366
1359
|
case kUpb_WellKnown_Duration: {
|
1367
1360
|
// Numeric -> Google::Protobuf::Duration
|
1368
|
-
|
1361
|
+
const upb_MiniTable* t = upb_MessageDef_MiniTable(m);
|
1362
|
+
upb_Message* msg = upb_Message_New(t, arena);
|
1369
1363
|
upb_MessageValue sec, nsec;
|
1370
1364
|
const upb_FieldDef* sec_f = upb_MessageDef_FindFieldByNumber(m, 1);
|
1371
1365
|
const upb_FieldDef* nsec_f = upb_MessageDef_FindFieldByNumber(m, 2);
|
@@ -1374,8 +1368,8 @@ const upb_Message* Message_GetUpbMessage(VALUE value, const upb_MessageDef* m,
|
|
1374
1368
|
|
1375
1369
|
sec.int64_val = NUM2LL(value);
|
1376
1370
|
nsec.int32_val = round((NUM2DBL(value) - NUM2LL(value)) * 1000000000);
|
1377
|
-
|
1378
|
-
|
1371
|
+
upb_Message_SetFieldByDef(msg, sec_f, sec, arena);
|
1372
|
+
upb_Message_SetFieldByDef(msg, nsec_f, nsec, arena);
|
1379
1373
|
return msg;
|
1380
1374
|
}
|
1381
1375
|
default:
|
@@ -1392,11 +1386,43 @@ const upb_Message* Message_GetUpbMessage(VALUE value, const upb_MessageDef* m,
|
|
1392
1386
|
return self->msg;
|
1393
1387
|
}
|
1394
1388
|
|
1389
|
+
static void Message_define_class(VALUE klass) {
|
1390
|
+
rb_define_alloc_func(klass, Message_alloc);
|
1391
|
+
|
1392
|
+
rb_require("google/protobuf/message_exts");
|
1393
|
+
rb_define_method(klass, "method_missing", Message_method_missing, -1);
|
1394
|
+
rb_define_method(klass, "respond_to_missing?", Message_respond_to_missing,
|
1395
|
+
-1);
|
1396
|
+
rb_define_method(klass, "initialize", Message_initialize, -1);
|
1397
|
+
rb_define_method(klass, "dup", Message_dup, 0);
|
1398
|
+
// Also define #clone so that we don't inherit Object#clone.
|
1399
|
+
rb_define_method(klass, "clone", Message_dup, 0);
|
1400
|
+
rb_define_method(klass, "==", Message_eq, 1);
|
1401
|
+
rb_define_method(klass, "eql?", Message_eq, 1);
|
1402
|
+
rb_define_method(klass, "freeze", Message_freeze, 0);
|
1403
|
+
rb_define_method(klass, "frozen?", Message_frozen, 0);
|
1404
|
+
rb_define_method(klass, "hash", Message_hash, 0);
|
1405
|
+
rb_define_method(klass, "to_h", Message_to_h, 0);
|
1406
|
+
rb_define_method(klass, "inspect", Message_inspect, 0);
|
1407
|
+
rb_define_method(klass, "to_s", Message_inspect, 0);
|
1408
|
+
rb_define_method(klass, "[]", Message_index, 1);
|
1409
|
+
rb_define_method(klass, "[]=", Message_index_set, 2);
|
1410
|
+
rb_define_singleton_method(klass, "decode", Message_decode, -1);
|
1411
|
+
rb_define_singleton_method(klass, "encode", Message_encode, -1);
|
1412
|
+
rb_define_singleton_method(klass, "decode_json", Message_decode_json, -1);
|
1413
|
+
rb_define_singleton_method(klass, "encode_json", Message_encode_json, -1);
|
1414
|
+
rb_define_singleton_method(klass, "descriptor", Message_descriptor, 0);
|
1415
|
+
}
|
1416
|
+
|
1395
1417
|
void Message_register(VALUE protobuf) {
|
1396
1418
|
cParseError = rb_const_get(protobuf, rb_intern("ParseError"));
|
1419
|
+
cAbstractMessage =
|
1420
|
+
rb_define_class_under(protobuf, "AbstractMessage", rb_cObject);
|
1421
|
+
Message_define_class(cAbstractMessage);
|
1422
|
+
rb_gc_register_address(&cAbstractMessage);
|
1397
1423
|
|
1398
1424
|
// Ruby-interned string: "descriptor". We use this identifier to store an
|
1399
1425
|
// instance variable on message classes we create in order to link them back
|
1400
1426
|
// to their descriptors.
|
1401
|
-
descriptor_instancevar_interned = rb_intern("descriptor");
|
1427
|
+
descriptor_instancevar_interned = rb_intern("@descriptor");
|
1402
1428
|
}
|