google-protobuf 3.20.0 → 4.34.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 +961 -157
- data/ext/google/protobuf_c/defs.h +3 -28
- data/ext/google/protobuf_c/extconf.rb +21 -11
- data/ext/google/protobuf_c/glue.c +135 -0
- data/ext/google/protobuf_c/map.c +187 -121
- data/ext/google/protobuf_c/map.h +12 -30
- data/ext/google/protobuf_c/message.c +354 -294
- data/ext/google/protobuf_c/message.h +11 -33
- data/ext/google/protobuf_c/protobuf.c +65 -188
- data/ext/google/protobuf_c/protobuf.h +21 -41
- data/ext/google/protobuf_c/repeated_field.c +145 -74
- data/ext/google/protobuf_c/repeated_field.h +11 -29
- data/ext/google/protobuf_c/ruby-upb.c +15734 -8866
- data/ext/google/protobuf_c/ruby-upb.h +16769 -4511
- 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 +207 -0
- data/ext/google/protobuf_c/third_party/utf8_range/utf8_range.h +20 -7
- 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/lib/google/protobuf/any_pb.rb +6 -8
- data/lib/google/protobuf/api_pb.rb +6 -26
- data/lib/google/protobuf/descriptor_pb.rb +27 -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 +175 -0
- data/lib/google/protobuf/ffi/descriptor_pool.rb +83 -0
- data/lib/google/protobuf/ffi/enum_descriptor.rb +183 -0
- data/lib/google/protobuf/ffi/ffi.rb +213 -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 +6 -7
- data/lib/google/protobuf/internal/object_cache.rb +99 -0
- data/lib/google/protobuf/message_exts.rb +12 -26
- data/lib/google/protobuf/plugin_pb.rb +25 -0
- data/lib/google/protobuf/repeated_field.rb +22 -33
- 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 +52 -0
- data/lib/google/protobuf_native.rb +19 -0
- data/lib/google/tasks/ffi.rake +100 -0
- metadata +103 -32
- 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/ext/google/protobuf_c/wrap_memcpy.c +0 -52
- data/lib/google/protobuf/descriptor_dsl.rb +0 -465
- data/tests/basic.rb +0 -670
- 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,25 @@ 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) ? Qtrue
|
|
366
|
+
: Qfalse;
|
|
358
367
|
case METHOD_WRAPPER_GETTER: {
|
|
359
368
|
Message* self = ruby_to_Message(_self);
|
|
360
|
-
if (
|
|
369
|
+
if (upb_Message_HasFieldByDef(self->msg, f)) {
|
|
361
370
|
PBRUBY_ASSERT(upb_FieldDef_IsSubMessage(f) &&
|
|
362
371
|
!upb_FieldDef_IsRepeated(f));
|
|
363
|
-
upb_MessageValue wrapper =
|
|
372
|
+
upb_MessageValue wrapper = upb_Message_GetFieldByDef(self->msg, f);
|
|
364
373
|
const upb_MessageDef* wrapper_m = upb_FieldDef_MessageSubDef(f);
|
|
365
374
|
const upb_FieldDef* value_f =
|
|
366
375
|
upb_MessageDef_FindFieldByNumber(wrapper_m, 1);
|
|
367
|
-
upb_MessageValue value =
|
|
376
|
+
upb_MessageValue value =
|
|
377
|
+
upb_Message_GetFieldByDef(wrapper.msg_val, value_f);
|
|
368
378
|
return Convert_UpbToRuby(value, TypeInfo_get(value_f), self->arena);
|
|
369
379
|
} else {
|
|
370
380
|
return Qnil;
|
|
@@ -373,21 +383,22 @@ static VALUE Message_field_accessor(VALUE _self, const upb_FieldDef* f,
|
|
|
373
383
|
case METHOD_WRAPPER_SETTER: {
|
|
374
384
|
upb_Message* msg = Message_GetMutable(_self, NULL);
|
|
375
385
|
if (argv[1] == Qnil) {
|
|
376
|
-
|
|
386
|
+
upb_Message_ClearFieldByDef(msg, f);
|
|
377
387
|
} else {
|
|
378
388
|
const upb_FieldDef* val_f =
|
|
379
389
|
upb_MessageDef_FindFieldByNumber(upb_FieldDef_MessageSubDef(f), 1);
|
|
380
390
|
upb_MessageValue msgval = Convert_RubyToUpb(
|
|
381
391
|
argv[1], upb_FieldDef_Name(f), TypeInfo_get(val_f), arena);
|
|
382
392
|
upb_Message* wrapper = upb_Message_Mutable(msg, f, arena).msg;
|
|
383
|
-
|
|
393
|
+
upb_Message_SetFieldByDef(wrapper, val_f, msgval, arena);
|
|
384
394
|
}
|
|
385
395
|
return Qnil;
|
|
386
396
|
}
|
|
387
397
|
case METHOD_ENUM_GETTER: {
|
|
388
|
-
upb_MessageValue msgval =
|
|
398
|
+
upb_MessageValue msgval =
|
|
399
|
+
upb_Message_GetFieldByDef(Message_Get(_self, NULL), f);
|
|
389
400
|
|
|
390
|
-
if (
|
|
401
|
+
if (upb_FieldDef_IsRepeated(f)) {
|
|
391
402
|
// Map repeated fields to a new type with ints
|
|
392
403
|
VALUE arr = rb_ary_new();
|
|
393
404
|
size_t i, n = upb_Array_Size(msgval.array_val);
|
|
@@ -409,11 +420,10 @@ static VALUE Message_field_accessor(VALUE _self, const upb_FieldDef* f,
|
|
|
409
420
|
}
|
|
410
421
|
|
|
411
422
|
/*
|
|
412
|
-
*
|
|
413
|
-
* Message.method_missing(*args)
|
|
423
|
+
* ruby-doc: AbstractMessage
|
|
414
424
|
*
|
|
415
|
-
*
|
|
416
|
-
*
|
|
425
|
+
* The {AbstractMessage} class is the parent class for all Protobuf messages,
|
|
426
|
+
* and is generated from C code.
|
|
417
427
|
*
|
|
418
428
|
* For any field whose name does not conflict with a built-in method, an
|
|
419
429
|
* accessor is provided with the same name as the field, and a setter is
|
|
@@ -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;
|
|
@@ -580,7 +591,7 @@ static void Message_InitFieldFromValue(upb_Message* msg, const upb_FieldDef* f,
|
|
|
580
591
|
if (upb_FieldDef_IsMap(f)) {
|
|
581
592
|
upb_Map* map = upb_Message_Mutable(msg, f, arena).map;
|
|
582
593
|
Map_InitFromValue(map, f, val, arena);
|
|
583
|
-
} else if (
|
|
594
|
+
} else if (upb_FieldDef_IsRepeated(f)) {
|
|
584
595
|
upb_Array* arr = upb_Message_Mutable(msg, f, arena).array;
|
|
585
596
|
RepeatedField_InitFromValue(arr, f, val, arena);
|
|
586
597
|
} else if (upb_FieldDef_IsSubMessage(f)) {
|
|
@@ -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
|
|
|
@@ -641,22 +652,19 @@ void Message_InitFromValue(upb_Message* msg, const upb_MessageDef* m, VALUE val,
|
|
|
641
652
|
}
|
|
642
653
|
|
|
643
654
|
/*
|
|
644
|
-
*
|
|
645
|
-
* Message.new(kwargs) => new_message
|
|
655
|
+
* ruby-doc: AbstractMessage#initialize
|
|
646
656
|
*
|
|
647
657
|
* Creates a new instance of the given message class. Keyword arguments may be
|
|
648
658
|
* provided with keywords corresponding to field names.
|
|
649
659
|
*
|
|
650
|
-
*
|
|
651
|
-
* type exist, as provided by the #msgclass method on Descriptors after they
|
|
652
|
-
* have been added to a pool. The method definitions described here on the
|
|
653
|
-
* Message class are provided on each concrete message class.
|
|
660
|
+
* @param kwargs the list of field keys and values.
|
|
654
661
|
*/
|
|
655
662
|
static VALUE Message_initialize(int argc, VALUE* argv, VALUE _self) {
|
|
656
663
|
Message* self = ruby_to_Message(_self);
|
|
657
664
|
VALUE arena_rb = Arena_new();
|
|
658
665
|
upb_Arena* arena = Arena_get(arena_rb);
|
|
659
|
-
|
|
666
|
+
const upb_MiniTable* t = upb_MessageDef_MiniTable(self->msgdef);
|
|
667
|
+
upb_Message* msg = upb_Message_New(t, arena);
|
|
660
668
|
|
|
661
669
|
Message_InitPtr(_self, msg, arena_rb);
|
|
662
670
|
|
|
@@ -671,56 +679,32 @@ static VALUE Message_initialize(int argc, VALUE* argv, VALUE _self) {
|
|
|
671
679
|
}
|
|
672
680
|
|
|
673
681
|
/*
|
|
674
|
-
*
|
|
675
|
-
* Message.dup => new_message
|
|
682
|
+
* ruby-doc: AbstractMessage#dup
|
|
676
683
|
*
|
|
677
684
|
* Performs a shallow copy of this message and returns the new copy.
|
|
685
|
+
*
|
|
686
|
+
* @return [AbstractMessage]
|
|
678
687
|
*/
|
|
679
688
|
static VALUE Message_dup(VALUE _self) {
|
|
680
689
|
Message* self = ruby_to_Message(_self);
|
|
681
690
|
VALUE new_msg = rb_class_new_instance(0, NULL, CLASS_OF(_self));
|
|
682
691
|
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);
|
|
692
|
+
const upb_MiniTable* m = upb_MessageDef_MiniTable(self->msgdef);
|
|
693
|
+
upb_Message_ShallowCopy((upb_Message*)new_msg_self->msg, self->msg, m);
|
|
688
694
|
Arena_fuse(self->arena, Arena_get(new_msg_self->arena));
|
|
689
695
|
return new_msg;
|
|
690
696
|
}
|
|
691
697
|
|
|
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
698
|
/*
|
|
717
|
-
*
|
|
718
|
-
* Message.==(other) => boolean
|
|
699
|
+
* ruby-doc: AbstractMessage#==
|
|
719
700
|
*
|
|
720
701
|
* Performs a deep comparison of this message with another. Messages are equal
|
|
721
702
|
* if they have the same type and if each field is equal according to the :==
|
|
722
703
|
* method's semantics (a more efficient comparison may actually be done if the
|
|
723
704
|
* field is of a primitive type).
|
|
705
|
+
*
|
|
706
|
+
* @param other [AbstractMessage]
|
|
707
|
+
* @return [Boolean]
|
|
724
708
|
*/
|
|
725
709
|
static VALUE Message_eq(VALUE _self, VALUE _other) {
|
|
726
710
|
if (CLASS_OF(_self) != CLASS_OF(_other)) return Qfalse;
|
|
@@ -729,35 +713,31 @@ static VALUE Message_eq(VALUE _self, VALUE _other) {
|
|
|
729
713
|
Message* other = ruby_to_Message(_other);
|
|
730
714
|
assert(self->msgdef == other->msgdef);
|
|
731
715
|
|
|
732
|
-
|
|
716
|
+
const upb_MiniTable* m = upb_MessageDef_MiniTable(self->msgdef);
|
|
717
|
+
const int options = 0;
|
|
718
|
+
return upb_Message_IsEqual(self->msg, other->msg, m, options) ? Qtrue
|
|
719
|
+
: Qfalse;
|
|
733
720
|
}
|
|
734
721
|
|
|
735
722
|
uint64_t Message_Hash(const upb_Message* msg, const upb_MessageDef* m,
|
|
736
723
|
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;
|
|
724
|
+
upb_Status status;
|
|
725
|
+
upb_Status_Clear(&status);
|
|
726
|
+
uint64_t return_value = shared_Message_Hash(msg, m, seed, &status);
|
|
727
|
+
if (upb_Status_IsOk(&status)) {
|
|
728
|
+
return return_value;
|
|
750
729
|
} else {
|
|
751
|
-
|
|
752
|
-
|
|
730
|
+
rb_raise(cParseError, "Message_Hash(): %s",
|
|
731
|
+
upb_Status_ErrorMessage(&status));
|
|
753
732
|
}
|
|
754
733
|
}
|
|
755
734
|
|
|
756
735
|
/*
|
|
757
|
-
*
|
|
758
|
-
* Message.hash => hash_value
|
|
736
|
+
* ruby-doc: AbstractMessage#hash
|
|
759
737
|
*
|
|
760
738
|
* Returns a hash value that represents this message's field values.
|
|
739
|
+
*
|
|
740
|
+
* @return [Integer]
|
|
761
741
|
*/
|
|
762
742
|
static VALUE Message_hash(VALUE _self) {
|
|
763
743
|
Message* self = ruby_to_Message(_self);
|
|
@@ -768,12 +748,13 @@ static VALUE Message_hash(VALUE _self) {
|
|
|
768
748
|
}
|
|
769
749
|
|
|
770
750
|
/*
|
|
771
|
-
*
|
|
772
|
-
* Message.inspect => string
|
|
751
|
+
* ruby-doc: AbstractMessage#inspect
|
|
773
752
|
*
|
|
774
753
|
* Returns a human-readable string representing this message. It will be
|
|
775
754
|
* formatted as "<MessageType: field1: value1, field2: value2, ...>". Each
|
|
776
755
|
* field's value is represented according to its own #inspect method.
|
|
756
|
+
*
|
|
757
|
+
* @return [String]
|
|
777
758
|
*/
|
|
778
759
|
static VALUE Message_inspect(VALUE _self) {
|
|
779
760
|
Message* self = ruby_to_Message(_self);
|
|
@@ -806,57 +787,34 @@ static VALUE Message_CreateHash(const upb_Message* msg,
|
|
|
806
787
|
if (!msg) return Qnil;
|
|
807
788
|
|
|
808
789
|
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
|
-
}
|
|
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;
|
|
832
794
|
|
|
833
|
-
|
|
834
|
-
if (
|
|
835
|
-
|
|
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]"
|
|
836
799
|
continue;
|
|
837
800
|
}
|
|
838
801
|
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
// Proto2 omits empty map/repeated filds also.
|
|
802
|
+
TypeInfo type_info = TypeInfo_get(field);
|
|
803
|
+
VALUE msg_value;
|
|
843
804
|
|
|
844
805
|
if (upb_FieldDef_IsMap(field)) {
|
|
845
806
|
const upb_MessageDef* entry_m = upb_FieldDef_MessageSubDef(field);
|
|
846
807
|
const upb_FieldDef* key_f = upb_MessageDef_FindFieldByNumber(entry_m, 1);
|
|
847
808
|
const upb_FieldDef* val_f = upb_MessageDef_FindFieldByNumber(entry_m, 2);
|
|
848
809
|
upb_CType key_type = upb_FieldDef_CType(key_f);
|
|
849
|
-
msg_value = Map_CreateHash(
|
|
810
|
+
msg_value = Map_CreateHash(val.map_val, key_type, TypeInfo_get(val_f));
|
|
850
811
|
} 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);
|
|
812
|
+
msg_value = RepeatedField_CreateArray(val.array_val, type_info);
|
|
856
813
|
} else {
|
|
857
|
-
msg_value = Scalar_CreateHash(
|
|
814
|
+
msg_value = Scalar_CreateHash(val, type_info);
|
|
858
815
|
}
|
|
859
816
|
|
|
817
|
+
VALUE msg_key = ID2SYM(rb_intern(upb_FieldDef_Name(field)));
|
|
860
818
|
rb_hash_aset(hash, msg_key, msg_value);
|
|
861
819
|
}
|
|
862
820
|
|
|
@@ -872,10 +830,11 @@ VALUE Scalar_CreateHash(upb_MessageValue msgval, TypeInfo type_info) {
|
|
|
872
830
|
}
|
|
873
831
|
|
|
874
832
|
/*
|
|
875
|
-
*
|
|
876
|
-
* Message.to_h => {}
|
|
833
|
+
* ruby-doc: AbstractMessage#to_h
|
|
877
834
|
*
|
|
878
835
|
* Returns the message as a Ruby Hash object, with keys as symbols.
|
|
836
|
+
*
|
|
837
|
+
* @return [Hash]
|
|
879
838
|
*/
|
|
880
839
|
static VALUE Message_to_h(VALUE _self) {
|
|
881
840
|
Message* self = ruby_to_Message(_self);
|
|
@@ -883,27 +842,56 @@ static VALUE Message_to_h(VALUE _self) {
|
|
|
883
842
|
}
|
|
884
843
|
|
|
885
844
|
/*
|
|
886
|
-
*
|
|
887
|
-
*
|
|
845
|
+
* ruby-doc: AbstractMessage#frozen?
|
|
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
|
+
* @return [Boolean]
|
|
852
|
+
*/
|
|
853
|
+
VALUE Message_frozen(VALUE _self) {
|
|
854
|
+
Message* self = ruby_to_Message(_self);
|
|
855
|
+
if (!upb_Message_IsFrozen(self->msg)) {
|
|
856
|
+
PBRUBY_ASSERT(!RB_OBJ_FROZEN(_self));
|
|
857
|
+
return Qfalse;
|
|
858
|
+
}
|
|
859
|
+
|
|
860
|
+
// Lazily freeze the Ruby wrapper.
|
|
861
|
+
if (!RB_OBJ_FROZEN(_self)) RB_OBJ_FREEZE(_self);
|
|
862
|
+
return Qtrue;
|
|
863
|
+
}
|
|
864
|
+
|
|
865
|
+
/*
|
|
866
|
+
* ruby-doc: AbstractMessage#freeze
|
|
867
|
+
*
|
|
868
|
+
* Freezes the message object. We have to intercept this so we can freeze the
|
|
869
|
+
* underlying representation, not just the Ruby wrapper.
|
|
888
870
|
*
|
|
889
|
-
*
|
|
890
|
-
* Ruby object into memory so we don't forget it's frozen.
|
|
871
|
+
* @return [self]
|
|
891
872
|
*/
|
|
892
|
-
|
|
873
|
+
VALUE Message_freeze(VALUE _self) {
|
|
893
874
|
Message* self = ruby_to_Message(_self);
|
|
894
|
-
if (
|
|
895
|
-
|
|
896
|
-
|
|
875
|
+
if (RB_OBJ_FROZEN(_self)) {
|
|
876
|
+
PBRUBY_ASSERT(upb_Message_IsFrozen(self->msg));
|
|
877
|
+
return _self;
|
|
897
878
|
}
|
|
879
|
+
if (!upb_Message_IsFrozen(self->msg)) {
|
|
880
|
+
upb_Message_Freeze(Message_GetMutable(_self, NULL),
|
|
881
|
+
upb_MessageDef_MiniTable(self->msgdef));
|
|
882
|
+
}
|
|
883
|
+
RB_OBJ_FREEZE(_self);
|
|
898
884
|
return _self;
|
|
899
885
|
}
|
|
900
886
|
|
|
901
887
|
/*
|
|
902
|
-
*
|
|
903
|
-
* Message.[](index) => value
|
|
888
|
+
* ruby-doc: AbstractMessage#[]
|
|
904
889
|
*
|
|
905
890
|
* Accesses a field's value by field name. The provided field name should be a
|
|
906
891
|
* string.
|
|
892
|
+
*
|
|
893
|
+
* @param index [Integer]
|
|
894
|
+
* @return [Object]
|
|
907
895
|
*/
|
|
908
896
|
static VALUE Message_index(VALUE _self, VALUE field_name) {
|
|
909
897
|
Message* self = ruby_to_Message(_self);
|
|
@@ -920,11 +908,14 @@ static VALUE Message_index(VALUE _self, VALUE field_name) {
|
|
|
920
908
|
}
|
|
921
909
|
|
|
922
910
|
/*
|
|
923
|
-
*
|
|
924
|
-
* Message.[]=(index, value)
|
|
911
|
+
* ruby-doc: AbstractMessage#[]=
|
|
925
912
|
*
|
|
926
913
|
* Sets a field's value by field name. The provided field name should be a
|
|
927
914
|
* string.
|
|
915
|
+
*
|
|
916
|
+
* @param index [Integer]
|
|
917
|
+
* @param value [Object]
|
|
918
|
+
* @return [nil]
|
|
928
919
|
*/
|
|
929
920
|
static VALUE Message_index_set(VALUE _self, VALUE field_name, VALUE value) {
|
|
930
921
|
Message* self = ruby_to_Message(_self);
|
|
@@ -940,20 +931,22 @@ static VALUE Message_index_set(VALUE _self, VALUE field_name, VALUE value) {
|
|
|
940
931
|
}
|
|
941
932
|
|
|
942
933
|
val = Convert_RubyToUpb(value, upb_FieldDef_Name(f), TypeInfo_get(f), arena);
|
|
943
|
-
|
|
934
|
+
upb_Message_SetFieldByDef(Message_GetMutable(_self, NULL), f, val, arena);
|
|
944
935
|
|
|
945
936
|
return Qnil;
|
|
946
937
|
}
|
|
947
938
|
|
|
948
939
|
/*
|
|
949
|
-
*
|
|
950
|
-
* MessageClass.decode(data, options) => message
|
|
940
|
+
* ruby-doc: AbstractMessage.decode
|
|
951
941
|
*
|
|
952
942
|
* Decodes the given data (as a string containing bytes in protocol buffers wire
|
|
953
|
-
* format) under the
|
|
943
|
+
* format) under the interpretation given by this message class's definition
|
|
954
944
|
* and returns a message object with the corresponding field values.
|
|
955
|
-
* @param
|
|
956
|
-
*
|
|
945
|
+
* @param data [String]
|
|
946
|
+
* @param options [Hash]
|
|
947
|
+
* @option recursion_limit [Integer] set to maximum decoding depth for message
|
|
948
|
+
* (default is 64)
|
|
949
|
+
* @return [AbstractMessage]
|
|
957
950
|
*/
|
|
958
951
|
static VALUE Message_decode(int argc, VALUE* argv, VALUE klass) {
|
|
959
952
|
VALUE data = argv[0];
|
|
@@ -969,10 +962,11 @@ static VALUE Message_decode(int argc, VALUE* argv, VALUE klass) {
|
|
|
969
962
|
rb_raise(rb_eArgError, "Expected hash arguments.");
|
|
970
963
|
}
|
|
971
964
|
|
|
972
|
-
VALUE depth =
|
|
965
|
+
VALUE depth =
|
|
966
|
+
rb_hash_lookup(hash_args, ID2SYM(rb_intern("recursion_limit")));
|
|
973
967
|
|
|
974
968
|
if (depth != Qnil && TYPE(depth) == T_FIXNUM) {
|
|
975
|
-
options |=
|
|
969
|
+
options |= upb_DecodeOptions_MaxDepth(FIX2INT(depth));
|
|
976
970
|
}
|
|
977
971
|
}
|
|
978
972
|
|
|
@@ -980,40 +974,48 @@ static VALUE Message_decode(int argc, VALUE* argv, VALUE klass) {
|
|
|
980
974
|
rb_raise(rb_eArgError, "Expected string for binary protobuf data.");
|
|
981
975
|
}
|
|
982
976
|
|
|
977
|
+
return Message_decode_bytes(RSTRING_LEN(data), RSTRING_PTR(data), options,
|
|
978
|
+
klass, /*freeze*/ false);
|
|
979
|
+
}
|
|
980
|
+
|
|
981
|
+
VALUE Message_decode_bytes(int size, const char* bytes, int options,
|
|
982
|
+
VALUE klass, bool freeze) {
|
|
983
983
|
VALUE msg_rb = initialize_rb_class_with_no_args(klass);
|
|
984
984
|
Message* msg = ruby_to_Message(msg_rb);
|
|
985
985
|
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
986
|
+
const upb_FileDef* file = upb_MessageDef_File(msg->msgdef);
|
|
987
|
+
const upb_ExtensionRegistry* extreg =
|
|
988
|
+
upb_DefPool_ExtensionRegistry(upb_FileDef_Pool(file));
|
|
989
|
+
upb_DecodeStatus status = upb_Decode(bytes, size, (upb_Message*)msg->msg,
|
|
990
|
+
upb_MessageDef_MiniTable(msg->msgdef),
|
|
991
|
+
extreg, options, Arena_get(msg->arena));
|
|
990
992
|
if (status != kUpb_DecodeStatus_Ok) {
|
|
991
993
|
rb_raise(cParseError, "Error occurred during parsing");
|
|
992
994
|
}
|
|
993
|
-
|
|
995
|
+
if (freeze) {
|
|
996
|
+
Message_freeze(msg_rb);
|
|
997
|
+
}
|
|
994
998
|
return msg_rb;
|
|
995
999
|
}
|
|
996
1000
|
|
|
997
1001
|
/*
|
|
998
|
-
*
|
|
999
|
-
* MessageClass.decode_json(data, options = {}) => message
|
|
1002
|
+
* ruby-doc: AbstractMessage.decode_json
|
|
1000
1003
|
*
|
|
1001
1004
|
* Decodes the given data (as a string containing bytes in protocol buffers wire
|
|
1002
1005
|
* format) under the interpretration given by this message class's definition
|
|
1003
1006
|
* and returns a message object with the corresponding field values.
|
|
1004
1007
|
*
|
|
1005
|
-
*
|
|
1006
|
-
*
|
|
1007
|
-
*
|
|
1008
|
+
* @param data [String]
|
|
1009
|
+
* @param options [Hash]
|
|
1010
|
+
* @option ignore_unknown_fields [Boolean] set true to ignore unknown fields
|
|
1011
|
+
* (default is to raise an error)
|
|
1012
|
+
* @return [AbstractMessage]
|
|
1008
1013
|
*/
|
|
1009
1014
|
static VALUE Message_decode_json(int argc, VALUE* argv, VALUE klass) {
|
|
1010
1015
|
VALUE data = argv[0];
|
|
1011
1016
|
int options = 0;
|
|
1012
1017
|
upb_Status status;
|
|
1013
1018
|
|
|
1014
|
-
// TODO(haberman): use this message's pool instead.
|
|
1015
|
-
const upb_DefPool* symtab = DescriptorPool_GetSymtab(generated_pool);
|
|
1016
|
-
|
|
1017
1019
|
if (argc < 1 || argc > 2) {
|
|
1018
1020
|
rb_raise(rb_eArgError, "Expected 1 or 2 arguments.");
|
|
1019
1021
|
}
|
|
@@ -1034,7 +1036,7 @@ static VALUE Message_decode_json(int argc, VALUE* argv, VALUE klass) {
|
|
|
1034
1036
|
rb_raise(rb_eArgError, "Expected string for JSON data.");
|
|
1035
1037
|
}
|
|
1036
1038
|
|
|
1037
|
-
// TODO
|
|
1039
|
+
// TODO: Check and respect string encoding. If not UTF-8, we need to
|
|
1038
1040
|
// convert, because string handlers pass data directly to message string
|
|
1039
1041
|
// fields.
|
|
1040
1042
|
|
|
@@ -1047,29 +1049,40 @@ static VALUE Message_decode_json(int argc, VALUE* argv, VALUE klass) {
|
|
|
1047
1049
|
}
|
|
1048
1050
|
|
|
1049
1051
|
upb_Status_Clear(&status);
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1052
|
+
const upb_DefPool* pool = upb_FileDef_Pool(upb_MessageDef_File(msg->msgdef));
|
|
1053
|
+
|
|
1054
|
+
int result = upb_JsonDecodeDetectingNonconformance(
|
|
1055
|
+
RSTRING_PTR(data), RSTRING_LEN(data), (upb_Message*)msg->msg,
|
|
1056
|
+
msg->msgdef, pool, options, Arena_get(msg->arena), &status);
|
|
1057
|
+
|
|
1058
|
+
switch (result) {
|
|
1059
|
+
case kUpb_JsonDecodeResult_Ok:
|
|
1060
|
+
break;
|
|
1061
|
+
case kUpb_JsonDecodeResult_Error:
|
|
1062
|
+
rb_raise(cParseError, "Error occurred during parsing: %s",
|
|
1063
|
+
upb_Status_ErrorMessage(&status));
|
|
1064
|
+
break;
|
|
1055
1065
|
}
|
|
1056
1066
|
|
|
1057
1067
|
return msg_rb;
|
|
1058
1068
|
}
|
|
1059
1069
|
|
|
1060
1070
|
/*
|
|
1061
|
-
*
|
|
1062
|
-
* MessageClass.encode(msg, options) => bytes
|
|
1071
|
+
* ruby-doc: AbstractMessage.encode
|
|
1063
1072
|
*
|
|
1064
1073
|
* Encodes the given message object to its serialized form in protocol buffers
|
|
1065
1074
|
* wire format.
|
|
1066
|
-
*
|
|
1067
|
-
*
|
|
1075
|
+
*
|
|
1076
|
+
* @param msg [AbstractMessage]
|
|
1077
|
+
* @param options [Hash]
|
|
1078
|
+
* @option recursion_limit [Integer] set to maximum encoding depth for message
|
|
1079
|
+
* (default is 64)
|
|
1080
|
+
* @return [String]
|
|
1068
1081
|
*/
|
|
1069
1082
|
static VALUE Message_encode(int argc, VALUE* argv, VALUE klass) {
|
|
1070
1083
|
Message* msg = ruby_to_Message(argv[0]);
|
|
1071
1084
|
int options = 0;
|
|
1072
|
-
|
|
1085
|
+
char* data;
|
|
1073
1086
|
size_t size;
|
|
1074
1087
|
|
|
1075
1088
|
if (CLASS_OF(argv[0]) != klass) {
|
|
@@ -1085,19 +1098,21 @@ static VALUE Message_encode(int argc, VALUE* argv, VALUE klass) {
|
|
|
1085
1098
|
if (TYPE(hash_args) != T_HASH) {
|
|
1086
1099
|
rb_raise(rb_eArgError, "Expected hash arguments.");
|
|
1087
1100
|
}
|
|
1088
|
-
VALUE depth =
|
|
1101
|
+
VALUE depth =
|
|
1102
|
+
rb_hash_lookup(hash_args, ID2SYM(rb_intern("recursion_limit")));
|
|
1089
1103
|
|
|
1090
1104
|
if (depth != Qnil && TYPE(depth) == T_FIXNUM) {
|
|
1091
|
-
options |=
|
|
1105
|
+
options |= upb_DecodeOptions_MaxDepth(FIX2INT(depth));
|
|
1092
1106
|
}
|
|
1093
1107
|
}
|
|
1094
1108
|
|
|
1095
|
-
upb_Arena
|
|
1109
|
+
upb_Arena* arena = upb_Arena_New();
|
|
1096
1110
|
|
|
1097
|
-
|
|
1098
|
-
|
|
1111
|
+
upb_EncodeStatus status =
|
|
1112
|
+
upb_Encode(msg->msg, upb_MessageDef_MiniTable(msg->msgdef), options,
|
|
1113
|
+
arena, &data, &size);
|
|
1099
1114
|
|
|
1100
|
-
if (
|
|
1115
|
+
if (status == kUpb_EncodeStatus_Ok) {
|
|
1101
1116
|
VALUE ret = rb_str_new(data, size);
|
|
1102
1117
|
rb_enc_associate(ret, rb_ascii8bit_encoding());
|
|
1103
1118
|
upb_Arena_Free(arena);
|
|
@@ -1109,14 +1124,17 @@ static VALUE Message_encode(int argc, VALUE* argv, VALUE klass) {
|
|
|
1109
1124
|
}
|
|
1110
1125
|
|
|
1111
1126
|
/*
|
|
1112
|
-
*
|
|
1113
|
-
* MessageClass.encode_json(msg, options = {}) => json_string
|
|
1127
|
+
* ruby-doc: AbstractMessage.encode_json
|
|
1114
1128
|
*
|
|
1115
1129
|
* Encodes the given message object into its serialized JSON representation.
|
|
1116
|
-
*
|
|
1117
|
-
*
|
|
1118
|
-
*
|
|
1119
|
-
*
|
|
1130
|
+
*
|
|
1131
|
+
* @param msg [AbstractMessage]
|
|
1132
|
+
* @param options [Hash]
|
|
1133
|
+
* @option preserve_proto_fieldnames [Boolean] set true to use original
|
|
1134
|
+
* fieldnames (default is to camelCase)
|
|
1135
|
+
* @option emit_defaults [Boolean] set true to emit 0/false values (default is
|
|
1136
|
+
* to omit them)
|
|
1137
|
+
* @return [String]
|
|
1120
1138
|
*/
|
|
1121
1139
|
static VALUE Message_encode_json(int argc, VALUE* argv, VALUE klass) {
|
|
1122
1140
|
Message* msg = ruby_to_Message(argv[0]);
|
|
@@ -1125,9 +1143,6 @@ static VALUE Message_encode_json(int argc, VALUE* argv, VALUE klass) {
|
|
|
1125
1143
|
size_t size;
|
|
1126
1144
|
upb_Status status;
|
|
1127
1145
|
|
|
1128
|
-
// TODO(haberman): use this message's pool instead.
|
|
1129
|
-
const upb_DefPool* symtab = DescriptorPool_GetSymtab(generated_pool);
|
|
1130
|
-
|
|
1131
1146
|
if (argc < 1 || argc > 2) {
|
|
1132
1147
|
rb_raise(rb_eArgError, "Expected 1 or 2 arguments.");
|
|
1133
1148
|
}
|
|
@@ -1135,7 +1150,8 @@ static VALUE Message_encode_json(int argc, VALUE* argv, VALUE klass) {
|
|
|
1135
1150
|
if (argc == 2) {
|
|
1136
1151
|
VALUE hash_args = argv[1];
|
|
1137
1152
|
if (TYPE(hash_args) != T_HASH) {
|
|
1138
|
-
if (RTEST(rb_funcall(hash_args, rb_intern("respond_to?"), 1,
|
|
1153
|
+
if (RTEST(rb_funcall(hash_args, rb_intern("respond_to?"), 1,
|
|
1154
|
+
rb_str_new2("to_h")))) {
|
|
1139
1155
|
hash_args = rb_funcall(hash_args, rb_intern("to_h"), 0);
|
|
1140
1156
|
} else {
|
|
1141
1157
|
rb_raise(rb_eArgError, "Expected hash arguments.");
|
|
@@ -1152,11 +1168,18 @@ static VALUE Message_encode_json(int argc, VALUE* argv, VALUE klass) {
|
|
|
1152
1168
|
Qfalse))) {
|
|
1153
1169
|
options |= upb_JsonEncode_EmitDefaults;
|
|
1154
1170
|
}
|
|
1171
|
+
|
|
1172
|
+
if (RTEST(rb_hash_lookup2(hash_args,
|
|
1173
|
+
ID2SYM(rb_intern("format_enums_as_integers")),
|
|
1174
|
+
Qfalse))) {
|
|
1175
|
+
options |= upb_JsonEncode_FormatEnumsAsIntegers;
|
|
1176
|
+
}
|
|
1155
1177
|
}
|
|
1156
1178
|
|
|
1157
1179
|
upb_Status_Clear(&status);
|
|
1158
|
-
|
|
1159
|
-
|
|
1180
|
+
const upb_DefPool* pool = upb_FileDef_Pool(upb_MessageDef_File(msg->msgdef));
|
|
1181
|
+
size = upb_JsonEncode(msg->msg, msg->msgdef, pool, options, buf, sizeof(buf),
|
|
1182
|
+
&status);
|
|
1160
1183
|
|
|
1161
1184
|
if (!upb_Status_IsOk(&status)) {
|
|
1162
1185
|
rb_raise(cParseError, "Error occurred during encoding: %s",
|
|
@@ -1166,7 +1189,7 @@ static VALUE Message_encode_json(int argc, VALUE* argv, VALUE klass) {
|
|
|
1166
1189
|
VALUE ret;
|
|
1167
1190
|
if (size >= sizeof(buf)) {
|
|
1168
1191
|
char* buf2 = malloc(size + 1);
|
|
1169
|
-
upb_JsonEncode(msg->msg, msg->msgdef,
|
|
1192
|
+
upb_JsonEncode(msg->msg, msg->msgdef, pool, options, buf2, size + 1,
|
|
1170
1193
|
&status);
|
|
1171
1194
|
ret = rb_str_new(buf2, size);
|
|
1172
1195
|
free(buf2);
|
|
@@ -1179,11 +1202,12 @@ static VALUE Message_encode_json(int argc, VALUE* argv, VALUE klass) {
|
|
|
1179
1202
|
}
|
|
1180
1203
|
|
|
1181
1204
|
/*
|
|
1182
|
-
*
|
|
1183
|
-
* Message.descriptor => descriptor
|
|
1205
|
+
* ruby-doc: AbstractMessage.descriptor
|
|
1184
1206
|
*
|
|
1185
1207
|
* Class method that returns the Descriptor instance corresponding to this
|
|
1186
1208
|
* message class's type.
|
|
1209
|
+
*
|
|
1210
|
+
* @return [Descriptor]
|
|
1187
1211
|
*/
|
|
1188
1212
|
static VALUE Message_descriptor(VALUE klass) {
|
|
1189
1213
|
return rb_ivar_get(klass, descriptor_instancevar_interned);
|
|
@@ -1201,45 +1225,31 @@ VALUE build_class_from_descriptor(VALUE descriptor) {
|
|
|
1201
1225
|
klass = rb_define_class_id(
|
|
1202
1226
|
// Docs say this parameter is ignored. User will assign return value to
|
|
1203
1227
|
// their own toplevel constant class name.
|
|
1204
|
-
rb_intern("Message"),
|
|
1228
|
+
rb_intern("Message"), cAbstractMessage);
|
|
1205
1229
|
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
1230
|
return klass;
|
|
1235
1231
|
}
|
|
1236
1232
|
|
|
1233
|
+
/* ruby-doc: Enum
|
|
1234
|
+
*
|
|
1235
|
+
* There isn't really a concrete `Enum` module generated by Protobuf. Instead,
|
|
1236
|
+
* you can use this documentation as an indicator of methods that are defined on
|
|
1237
|
+
* each `Enum` module that is generated. E.g. if you have:
|
|
1238
|
+
*
|
|
1239
|
+
* enum my_enum_type
|
|
1240
|
+
*
|
|
1241
|
+
* in your Proto file and generate Ruby code, a module
|
|
1242
|
+
* called `MyEnumType` will be generated with the following methods available.
|
|
1243
|
+
*/
|
|
1244
|
+
|
|
1237
1245
|
/*
|
|
1238
|
-
*
|
|
1239
|
-
* Enum.lookup(number) => name
|
|
1246
|
+
* ruby-doc: Enum.lookup
|
|
1240
1247
|
*
|
|
1241
1248
|
* This module method, provided on each generated enum module, looks up an enum
|
|
1242
1249
|
* value by number and returns its name as a Ruby symbol, or nil if not found.
|
|
1250
|
+
*
|
|
1251
|
+
* @param number [Integer]
|
|
1252
|
+
* @return [String]
|
|
1243
1253
|
*/
|
|
1244
1254
|
static VALUE enum_lookup(VALUE self, VALUE number) {
|
|
1245
1255
|
int32_t num = NUM2INT(number);
|
|
@@ -1254,11 +1264,13 @@ static VALUE enum_lookup(VALUE self, VALUE number) {
|
|
|
1254
1264
|
}
|
|
1255
1265
|
|
|
1256
1266
|
/*
|
|
1257
|
-
*
|
|
1258
|
-
* Enum.resolve(name) => number
|
|
1267
|
+
* ruby-doc: Enum.resolve
|
|
1259
1268
|
*
|
|
1260
1269
|
* This module method, provided on each generated enum module, looks up an enum
|
|
1261
1270
|
* value by name (as a Ruby symbol) and returns its name, or nil if not found.
|
|
1271
|
+
*
|
|
1272
|
+
* @param name [String]
|
|
1273
|
+
* @return [Integer]
|
|
1262
1274
|
*/
|
|
1263
1275
|
static VALUE enum_resolve(VALUE self, VALUE sym) {
|
|
1264
1276
|
const char* name = rb_id2name(SYM2ID(sym));
|
|
@@ -1273,11 +1285,13 @@ static VALUE enum_resolve(VALUE self, VALUE sym) {
|
|
|
1273
1285
|
}
|
|
1274
1286
|
|
|
1275
1287
|
/*
|
|
1276
|
-
*
|
|
1277
|
-
* Enum.descriptor
|
|
1288
|
+
* ruby-doc: Enum.descriptor
|
|
1278
1289
|
*
|
|
1279
1290
|
* This module method, provided on each generated enum module, returns the
|
|
1280
|
-
* EnumDescriptor corresponding to this enum type.
|
|
1291
|
+
* {EnumDescriptor} corresponding to this enum type.
|
|
1292
|
+
*
|
|
1293
|
+
* @return [EnumDescriptor]
|
|
1294
|
+
*
|
|
1281
1295
|
*/
|
|
1282
1296
|
static VALUE enum_descriptor(VALUE self) {
|
|
1283
1297
|
return rb_ivar_get(self, descriptor_instancevar_interned);
|
|
@@ -1290,15 +1304,22 @@ VALUE build_module_from_enumdesc(VALUE _enumdesc) {
|
|
|
1290
1304
|
int n = upb_EnumDef_ValueCount(e);
|
|
1291
1305
|
for (int i = 0; i < n; i++) {
|
|
1292
1306
|
const upb_EnumValueDef* ev = upb_EnumDef_Value(e, i);
|
|
1293
|
-
|
|
1307
|
+
upb_Arena* arena = upb_Arena_New();
|
|
1308
|
+
const char* src_name = upb_EnumValueDef_Name(ev);
|
|
1309
|
+
char* name = upb_strdup2(src_name, strlen(src_name), arena);
|
|
1294
1310
|
int32_t value = upb_EnumValueDef_Number(ev);
|
|
1295
1311
|
if (name[0] < 'A' || name[0] > 'Z') {
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1312
|
+
if (name[0] >= 'a' && name[0] <= 'z') {
|
|
1313
|
+
name[0] -= 32; // auto capitalize
|
|
1314
|
+
} else {
|
|
1315
|
+
rb_warn(
|
|
1316
|
+
"Enum value '%s' does not start with an uppercase letter "
|
|
1317
|
+
"as is required for Ruby constants.",
|
|
1318
|
+
name);
|
|
1319
|
+
}
|
|
1300
1320
|
}
|
|
1301
1321
|
rb_define_const(mod, name, INT2NUM(value));
|
|
1322
|
+
upb_Arena_Free(arena);
|
|
1302
1323
|
}
|
|
1303
1324
|
|
|
1304
1325
|
rb_define_singleton_method(mod, "lookup", enum_lookup, 1);
|
|
@@ -1309,7 +1330,7 @@ VALUE build_module_from_enumdesc(VALUE _enumdesc) {
|
|
|
1309
1330
|
return mod;
|
|
1310
1331
|
}
|
|
1311
1332
|
|
|
1312
|
-
// Internal
|
|
1333
|
+
// Internal to the library; used by Google::Protobuf.deep_copy.
|
|
1313
1334
|
upb_Message* Message_deep_copy(const upb_Message* msg, const upb_MessageDef* m,
|
|
1314
1335
|
upb_Arena* arena) {
|
|
1315
1336
|
// Serialize and parse.
|
|
@@ -1317,11 +1338,16 @@ upb_Message* Message_deep_copy(const upb_Message* msg, const upb_MessageDef* m,
|
|
|
1317
1338
|
const upb_MiniTable* layout = upb_MessageDef_MiniTable(m);
|
|
1318
1339
|
size_t size;
|
|
1319
1340
|
|
|
1320
|
-
|
|
1321
|
-
|
|
1341
|
+
upb_Message* new_msg = upb_Message_New(layout, arena);
|
|
1342
|
+
char* data;
|
|
1322
1343
|
|
|
1323
|
-
|
|
1324
|
-
|
|
1344
|
+
const upb_FileDef* file = upb_MessageDef_File(m);
|
|
1345
|
+
const upb_ExtensionRegistry* extreg =
|
|
1346
|
+
upb_DefPool_ExtensionRegistry(upb_FileDef_Pool(file));
|
|
1347
|
+
if (upb_Encode(msg, layout, 0, tmp_arena, &data, &size) !=
|
|
1348
|
+
kUpb_EncodeStatus_Ok ||
|
|
1349
|
+
upb_Decode(data, size, new_msg, layout, extreg, 0, arena) !=
|
|
1350
|
+
kUpb_DecodeStatus_Ok) {
|
|
1325
1351
|
upb_Arena_Free(tmp_arena);
|
|
1326
1352
|
rb_raise(cParseError, "Error occurred copying proto");
|
|
1327
1353
|
}
|
|
@@ -1348,7 +1374,8 @@ const upb_Message* Message_GetUpbMessage(VALUE value, const upb_MessageDef* m,
|
|
|
1348
1374
|
switch (upb_MessageDef_WellKnownType(m)) {
|
|
1349
1375
|
case kUpb_WellKnown_Timestamp: {
|
|
1350
1376
|
// Time -> Google::Protobuf::Timestamp
|
|
1351
|
-
|
|
1377
|
+
const upb_MiniTable* t = upb_MessageDef_MiniTable(m);
|
|
1378
|
+
upb_Message* msg = upb_Message_New(t, arena);
|
|
1352
1379
|
upb_MessageValue sec, nsec;
|
|
1353
1380
|
struct timespec time;
|
|
1354
1381
|
const upb_FieldDef* sec_f = upb_MessageDef_FindFieldByNumber(m, 1);
|
|
@@ -1359,13 +1386,14 @@ const upb_Message* Message_GetUpbMessage(VALUE value, const upb_MessageDef* m,
|
|
|
1359
1386
|
time = rb_time_timespec(value);
|
|
1360
1387
|
sec.int64_val = time.tv_sec;
|
|
1361
1388
|
nsec.int32_val = time.tv_nsec;
|
|
1362
|
-
|
|
1363
|
-
|
|
1389
|
+
upb_Message_SetFieldByDef(msg, sec_f, sec, arena);
|
|
1390
|
+
upb_Message_SetFieldByDef(msg, nsec_f, nsec, arena);
|
|
1364
1391
|
return msg;
|
|
1365
1392
|
}
|
|
1366
1393
|
case kUpb_WellKnown_Duration: {
|
|
1367
1394
|
// Numeric -> Google::Protobuf::Duration
|
|
1368
|
-
|
|
1395
|
+
const upb_MiniTable* t = upb_MessageDef_MiniTable(m);
|
|
1396
|
+
upb_Message* msg = upb_Message_New(t, arena);
|
|
1369
1397
|
upb_MessageValue sec, nsec;
|
|
1370
1398
|
const upb_FieldDef* sec_f = upb_MessageDef_FindFieldByNumber(m, 1);
|
|
1371
1399
|
const upb_FieldDef* nsec_f = upb_MessageDef_FindFieldByNumber(m, 2);
|
|
@@ -1374,8 +1402,8 @@ const upb_Message* Message_GetUpbMessage(VALUE value, const upb_MessageDef* m,
|
|
|
1374
1402
|
|
|
1375
1403
|
sec.int64_val = NUM2LL(value);
|
|
1376
1404
|
nsec.int32_val = round((NUM2DBL(value) - NUM2LL(value)) * 1000000000);
|
|
1377
|
-
|
|
1378
|
-
|
|
1405
|
+
upb_Message_SetFieldByDef(msg, sec_f, sec, arena);
|
|
1406
|
+
upb_Message_SetFieldByDef(msg, nsec_f, nsec, arena);
|
|
1379
1407
|
return msg;
|
|
1380
1408
|
}
|
|
1381
1409
|
default:
|
|
@@ -1392,11 +1420,43 @@ const upb_Message* Message_GetUpbMessage(VALUE value, const upb_MessageDef* m,
|
|
|
1392
1420
|
return self->msg;
|
|
1393
1421
|
}
|
|
1394
1422
|
|
|
1423
|
+
static void Message_define_class(VALUE klass) {
|
|
1424
|
+
rb_define_alloc_func(klass, Message_alloc);
|
|
1425
|
+
|
|
1426
|
+
rb_require("google/protobuf/message_exts");
|
|
1427
|
+
rb_define_method(klass, "method_missing", Message_method_missing, -1);
|
|
1428
|
+
rb_define_method(klass, "respond_to_missing?", Message_respond_to_missing,
|
|
1429
|
+
-1);
|
|
1430
|
+
rb_define_method(klass, "initialize", Message_initialize, -1);
|
|
1431
|
+
rb_define_method(klass, "dup", Message_dup, 0);
|
|
1432
|
+
// Also define #clone so that we don't inherit Object#clone.
|
|
1433
|
+
rb_define_method(klass, "clone", Message_dup, 0);
|
|
1434
|
+
rb_define_method(klass, "==", Message_eq, 1);
|
|
1435
|
+
rb_define_method(klass, "eql?", Message_eq, 1);
|
|
1436
|
+
rb_define_method(klass, "freeze", Message_freeze, 0);
|
|
1437
|
+
rb_define_method(klass, "frozen?", Message_frozen, 0);
|
|
1438
|
+
rb_define_method(klass, "hash", Message_hash, 0);
|
|
1439
|
+
rb_define_method(klass, "to_h", Message_to_h, 0);
|
|
1440
|
+
rb_define_method(klass, "inspect", Message_inspect, 0);
|
|
1441
|
+
rb_define_method(klass, "to_s", Message_inspect, 0);
|
|
1442
|
+
rb_define_method(klass, "[]", Message_index, 1);
|
|
1443
|
+
rb_define_method(klass, "[]=", Message_index_set, 2);
|
|
1444
|
+
rb_define_singleton_method(klass, "decode", Message_decode, -1);
|
|
1445
|
+
rb_define_singleton_method(klass, "encode", Message_encode, -1);
|
|
1446
|
+
rb_define_singleton_method(klass, "decode_json", Message_decode_json, -1);
|
|
1447
|
+
rb_define_singleton_method(klass, "encode_json", Message_encode_json, -1);
|
|
1448
|
+
rb_define_singleton_method(klass, "descriptor", Message_descriptor, 0);
|
|
1449
|
+
}
|
|
1450
|
+
|
|
1395
1451
|
void Message_register(VALUE protobuf) {
|
|
1396
1452
|
cParseError = rb_const_get(protobuf, rb_intern("ParseError"));
|
|
1453
|
+
cAbstractMessage =
|
|
1454
|
+
rb_define_class_under(protobuf, "AbstractMessage", rb_cObject);
|
|
1455
|
+
Message_define_class(cAbstractMessage);
|
|
1456
|
+
rb_gc_register_address(&cAbstractMessage);
|
|
1397
1457
|
|
|
1398
1458
|
// Ruby-interned string: "descriptor". We use this identifier to store an
|
|
1399
1459
|
// instance variable on message classes we create in order to link them back
|
|
1400
1460
|
// to their descriptors.
|
|
1401
|
-
descriptor_instancevar_interned = rb_intern("descriptor");
|
|
1461
|
+
descriptor_instancevar_interned = rb_intern("@descriptor");
|
|
1402
1462
|
}
|