google-protobuf 3.17.0 → 3.23.3
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.
Potentially problematic release.
This version of google-protobuf might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/ext/google/protobuf_c/convert.c +128 -116
- data/ext/google/protobuf_c/convert.h +12 -9
- data/ext/google/protobuf_c/defs.c +235 -1529
- data/ext/google/protobuf_c/defs.h +19 -19
- data/ext/google/protobuf_c/extconf.rb +12 -6
- data/ext/google/protobuf_c/map.c +108 -110
- data/ext/google/protobuf_c/map.h +7 -7
- data/ext/google/protobuf_c/message.c +456 -343
- data/ext/google/protobuf_c/message.h +22 -19
- data/ext/google/protobuf_c/protobuf.c +78 -56
- data/ext/google/protobuf_c/protobuf.h +16 -9
- data/ext/google/protobuf_c/repeated_field.c +85 -85
- data/ext/google/protobuf_c/repeated_field.h +6 -5
- data/ext/google/protobuf_c/ruby-upb.c +11806 -6746
- data/ext/google/protobuf_c/ruby-upb.h +10860 -3532
- data/ext/google/protobuf_c/third_party/utf8_range/LICENSE +22 -0
- data/ext/google/protobuf_c/third_party/utf8_range/naive.c +92 -0
- data/ext/google/protobuf_c/third_party/utf8_range/range2-neon.c +157 -0
- data/ext/google/protobuf_c/third_party/utf8_range/range2-sse.c +170 -0
- data/ext/google/protobuf_c/third_party/utf8_range/utf8_range.h +21 -0
- data/ext/google/protobuf_c/wrap_memcpy.c +4 -3
- data/lib/google/protobuf/any_pb.rb +24 -5
- data/lib/google/protobuf/api_pb.rb +27 -23
- data/lib/google/protobuf/descriptor_dsl.rb +465 -0
- data/lib/google/protobuf/descriptor_pb.rb +75 -0
- data/lib/google/protobuf/duration_pb.rb +24 -5
- data/lib/google/protobuf/empty_pb.rb +24 -3
- data/lib/google/protobuf/field_mask_pb.rb +24 -4
- data/lib/google/protobuf/message_exts.rb +7 -2
- data/lib/google/protobuf/plugin_pb.rb +47 -0
- data/lib/google/protobuf/repeated_field.rb +15 -2
- data/lib/google/protobuf/source_context_pb.rb +24 -4
- data/lib/google/protobuf/struct_pb.rb +24 -20
- data/lib/google/protobuf/timestamp_pb.rb +24 -5
- data/lib/google/protobuf/type_pb.rb +27 -68
- data/lib/google/protobuf/well_known_types.rb +12 -2
- data/lib/google/protobuf/wrappers_pb.rb +24 -28
- data/lib/google/protobuf.rb +5 -73
- metadata +17 -36
- data/ext/google/protobuf_c/third_party/wyhash/wyhash.h +0 -145
- data/tests/basic.rb +0 -604
- data/tests/generated_code_test.rb +0 -23
- data/tests/stress.rb +0 -38
@@ -35,13 +35,13 @@
|
|
35
35
|
#include "map.h"
|
36
36
|
#include "protobuf.h"
|
37
37
|
#include "repeated_field.h"
|
38
|
-
#include "third_party/wyhash/wyhash.h"
|
39
38
|
|
40
39
|
static VALUE cParseError = Qnil;
|
40
|
+
static VALUE cAbstractMessage = Qnil;
|
41
41
|
static ID descriptor_instancevar_interned;
|
42
42
|
|
43
43
|
static VALUE initialize_rb_class_with_no_args(VALUE klass) {
|
44
|
-
|
44
|
+
return rb_funcall(klass, rb_intern("new"), 0);
|
45
45
|
}
|
46
46
|
|
47
47
|
VALUE MessageOrEnum_GetDescriptor(VALUE klass) {
|
@@ -53,20 +53,23 @@ VALUE MessageOrEnum_GetDescriptor(VALUE klass) {
|
|
53
53
|
// -----------------------------------------------------------------------------
|
54
54
|
|
55
55
|
typedef struct {
|
56
|
+
// IMPORTANT: WB_PROTECTED objects must only use the RB_OBJ_WRITE()
|
57
|
+
// macro to update VALUE references, as to trigger write barriers.
|
56
58
|
VALUE arena;
|
57
|
-
const
|
58
|
-
const
|
59
|
+
const upb_Message* msg; // Can get as mutable when non-frozen.
|
60
|
+
const upb_MessageDef*
|
61
|
+
msgdef; // kept alive by self.class.descriptor reference.
|
59
62
|
} Message;
|
60
63
|
|
61
64
|
static void Message_mark(void* _self) {
|
62
|
-
Message* self = (Message
|
65
|
+
Message* self = (Message*)_self;
|
63
66
|
rb_gc_mark(self->arena);
|
64
67
|
}
|
65
68
|
|
66
69
|
static rb_data_type_t Message_type = {
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
+
"Google::Protobuf::Message",
|
71
|
+
{Message_mark, RUBY_DEFAULT_FREE, NULL},
|
72
|
+
.flags = RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
|
70
73
|
};
|
71
74
|
|
72
75
|
static Message* ruby_to_Message(VALUE msg_rb) {
|
@@ -90,21 +93,21 @@ static VALUE Message_alloc(VALUE klass) {
|
|
90
93
|
return ret;
|
91
94
|
}
|
92
95
|
|
93
|
-
const
|
96
|
+
const upb_Message* Message_Get(VALUE msg_rb, const upb_MessageDef** m) {
|
94
97
|
Message* msg = ruby_to_Message(msg_rb);
|
95
98
|
if (m) *m = msg->msgdef;
|
96
99
|
return msg->msg;
|
97
100
|
}
|
98
101
|
|
99
|
-
|
102
|
+
upb_Message* Message_GetMutable(VALUE msg_rb, const upb_MessageDef** m) {
|
100
103
|
rb_check_frozen(msg_rb);
|
101
|
-
return (
|
104
|
+
return (upb_Message*)Message_Get(msg_rb, m);
|
102
105
|
}
|
103
106
|
|
104
|
-
void Message_InitPtr(VALUE self_,
|
107
|
+
void Message_InitPtr(VALUE self_, upb_Message* msg, VALUE arena) {
|
105
108
|
Message* self = ruby_to_Message(self_);
|
106
109
|
self->msg = msg;
|
107
|
-
self->arena
|
110
|
+
RB_OBJ_WRITE(self_, &self->arena, arena);
|
108
111
|
ObjectCache_Add(msg, self_);
|
109
112
|
}
|
110
113
|
|
@@ -120,7 +123,8 @@ void Message_CheckClass(VALUE klass) {
|
|
120
123
|
}
|
121
124
|
}
|
122
125
|
|
123
|
-
VALUE Message_GetRubyWrapper(
|
126
|
+
VALUE Message_GetRubyWrapper(upb_Message* msg, const upb_MessageDef* m,
|
127
|
+
VALUE arena) {
|
124
128
|
if (msg == NULL) return Qnil;
|
125
129
|
|
126
130
|
VALUE val = ObjectCache_Get(msg);
|
@@ -134,17 +138,18 @@ VALUE Message_GetRubyWrapper(upb_msg* msg, const upb_msgdef* m, VALUE arena) {
|
|
134
138
|
return val;
|
135
139
|
}
|
136
140
|
|
137
|
-
void Message_PrintMessage(StringBuilder* b, const
|
138
|
-
const
|
141
|
+
void Message_PrintMessage(StringBuilder* b, const upb_Message* msg,
|
142
|
+
const upb_MessageDef* m) {
|
139
143
|
bool first = true;
|
140
|
-
int n =
|
144
|
+
int n = upb_MessageDef_FieldCount(m);
|
141
145
|
VALUE klass = Descriptor_DefToClass(m);
|
142
146
|
StringBuilder_Printf(b, "<%s: ", rb_class2name(klass));
|
143
147
|
|
144
148
|
for (int i = 0; i < n; i++) {
|
145
|
-
const
|
149
|
+
const upb_FieldDef* field = upb_MessageDef_Field(m, i);
|
146
150
|
|
147
|
-
if (
|
151
|
+
if (upb_FieldDef_HasPresence(field) &&
|
152
|
+
!upb_Message_HasFieldByDef(msg, field)) {
|
148
153
|
continue;
|
149
154
|
}
|
150
155
|
|
@@ -154,17 +159,17 @@ void Message_PrintMessage(StringBuilder* b, const upb_msg* msg,
|
|
154
159
|
first = false;
|
155
160
|
}
|
156
161
|
|
157
|
-
|
162
|
+
upb_MessageValue msgval = upb_Message_GetFieldByDef(msg, field);
|
158
163
|
|
159
|
-
StringBuilder_Printf(b, "%s: ",
|
164
|
+
StringBuilder_Printf(b, "%s: ", upb_FieldDef_Name(field));
|
160
165
|
|
161
|
-
if (
|
162
|
-
const
|
163
|
-
const
|
164
|
-
const
|
166
|
+
if (upb_FieldDef_IsMap(field)) {
|
167
|
+
const upb_MessageDef* entry_m = upb_FieldDef_MessageSubDef(field);
|
168
|
+
const upb_FieldDef* key_f = upb_MessageDef_FindFieldByNumber(entry_m, 1);
|
169
|
+
const upb_FieldDef* val_f = upb_MessageDef_FindFieldByNumber(entry_m, 2);
|
165
170
|
TypeInfo val_info = TypeInfo_get(val_f);
|
166
|
-
Map_Inspect(b, msgval.map_val,
|
167
|
-
} else if (
|
171
|
+
Map_Inspect(b, msgval.map_val, upb_FieldDef_CType(key_f), val_info);
|
172
|
+
} else if (upb_FieldDef_IsRepeated(field)) {
|
168
173
|
RepeatedField_Inspect(b, msgval.array_val, TypeInfo_get(field));
|
169
174
|
} else {
|
170
175
|
StringBuilder_PrintMsgval(b, msgval, TypeInfo_get(field));
|
@@ -188,14 +193,31 @@ enum {
|
|
188
193
|
};
|
189
194
|
|
190
195
|
// Check if the field is a well known wrapper type
|
191
|
-
static bool IsWrapper(const
|
192
|
-
|
193
|
-
|
196
|
+
static bool IsWrapper(const upb_MessageDef* m) {
|
197
|
+
if (!m) return false;
|
198
|
+
switch (upb_MessageDef_WellKnownType(m)) {
|
199
|
+
case kUpb_WellKnown_DoubleValue:
|
200
|
+
case kUpb_WellKnown_FloatValue:
|
201
|
+
case kUpb_WellKnown_Int64Value:
|
202
|
+
case kUpb_WellKnown_UInt64Value:
|
203
|
+
case kUpb_WellKnown_Int32Value:
|
204
|
+
case kUpb_WellKnown_UInt32Value:
|
205
|
+
case kUpb_WellKnown_StringValue:
|
206
|
+
case kUpb_WellKnown_BytesValue:
|
207
|
+
case kUpb_WellKnown_BoolValue:
|
208
|
+
return true;
|
209
|
+
default:
|
210
|
+
return false;
|
211
|
+
}
|
212
|
+
}
|
213
|
+
|
214
|
+
static bool IsFieldWrapper(const upb_FieldDef* f) {
|
215
|
+
return IsWrapper(upb_FieldDef_MessageSubDef(f));
|
194
216
|
}
|
195
217
|
|
196
|
-
static bool Match(const
|
197
|
-
const
|
198
|
-
const char* suffix) {
|
218
|
+
static bool Match(const upb_MessageDef* m, const char* name,
|
219
|
+
const upb_FieldDef** f, const upb_OneofDef** o,
|
220
|
+
const char* prefix, const char* suffix) {
|
199
221
|
size_t sp = strlen(prefix);
|
200
222
|
size_t ss = strlen(suffix);
|
201
223
|
size_t sn = strlen(name);
|
@@ -207,12 +229,12 @@ static bool Match(const upb_msgdef* m, const char* name, const upb_fielddef** f,
|
|
207
229
|
return false;
|
208
230
|
}
|
209
231
|
|
210
|
-
return
|
232
|
+
return upb_MessageDef_FindByNameWithSize(m, name + sp, sn - sp - ss, f, o);
|
211
233
|
}
|
212
234
|
|
213
235
|
static int extract_method_call(VALUE method_name, Message* self,
|
214
|
-
const
|
215
|
-
const
|
236
|
+
const upb_FieldDef** f, const upb_OneofDef** o) {
|
237
|
+
const upb_MessageDef* m = self->msgdef;
|
216
238
|
const char* name;
|
217
239
|
|
218
240
|
Check_Type(method_name, T_SYMBOL);
|
@@ -222,156 +244,153 @@ static int extract_method_call(VALUE method_name, Message* self,
|
|
222
244
|
if (Match(m, name, f, o, "", "=")) return METHOD_SETTER;
|
223
245
|
if (Match(m, name, f, o, "clear_", "")) return METHOD_CLEAR;
|
224
246
|
if (Match(m, name, f, o, "has_", "?") &&
|
225
|
-
(*o || (*f &&
|
226
|
-
// Disallow oneof hazzers for proto3.
|
227
|
-
// TODO(haberman): remove this test when we are enabling oneof hazzers for
|
228
|
-
// proto3.
|
229
|
-
if (*f && !upb_fielddef_issubmsg(*f) &&
|
230
|
-
upb_fielddef_realcontainingoneof(*f) &&
|
231
|
-
upb_msgdef_syntax(upb_fielddef_containingtype(*f)) !=
|
232
|
-
UPB_SYNTAX_PROTO2) {
|
233
|
-
return METHOD_UNKNOWN;
|
234
|
-
}
|
247
|
+
(*o || (*f && upb_FieldDef_HasPresence(*f)))) {
|
235
248
|
return METHOD_PRESENCE;
|
236
249
|
}
|
237
|
-
if (Match(m, name, f, o, "", "_as_value") && *f &&
|
238
|
-
|
250
|
+
if (Match(m, name, f, o, "", "_as_value") && *f &&
|
251
|
+
!upb_FieldDef_IsRepeated(*f) && IsFieldWrapper(*f)) {
|
239
252
|
return METHOD_WRAPPER_GETTER;
|
240
253
|
}
|
241
|
-
if (Match(m, name, f, o, "", "_as_value=") && *f &&
|
242
|
-
|
254
|
+
if (Match(m, name, f, o, "", "_as_value=") && *f &&
|
255
|
+
!upb_FieldDef_IsRepeated(*f) && IsFieldWrapper(*f)) {
|
243
256
|
return METHOD_WRAPPER_SETTER;
|
244
257
|
}
|
245
258
|
if (Match(m, name, f, o, "", "_const") && *f &&
|
246
|
-
|
259
|
+
upb_FieldDef_CType(*f) == kUpb_CType_Enum) {
|
247
260
|
return METHOD_ENUM_GETTER;
|
248
261
|
}
|
249
262
|
|
250
263
|
return METHOD_UNKNOWN;
|
251
264
|
}
|
252
265
|
|
253
|
-
static VALUE Message_oneof_accessor(VALUE _self, const
|
266
|
+
static VALUE Message_oneof_accessor(VALUE _self, const upb_OneofDef* o,
|
254
267
|
int accessor_type) {
|
255
268
|
Message* self = ruby_to_Message(_self);
|
256
|
-
const
|
269
|
+
const upb_FieldDef* oneof_field = upb_Message_WhichOneof(self->msg, o);
|
257
270
|
|
258
271
|
switch (accessor_type) {
|
259
272
|
case METHOD_PRESENCE:
|
260
273
|
return oneof_field == NULL ? Qfalse : Qtrue;
|
261
274
|
case METHOD_CLEAR:
|
262
275
|
if (oneof_field != NULL) {
|
263
|
-
|
276
|
+
upb_Message_ClearFieldByDef(Message_GetMutable(_self, NULL),
|
277
|
+
oneof_field);
|
264
278
|
}
|
265
279
|
return Qnil;
|
266
280
|
case METHOD_GETTER:
|
267
281
|
return oneof_field == NULL
|
268
282
|
? Qnil
|
269
|
-
: ID2SYM(rb_intern(
|
283
|
+
: ID2SYM(rb_intern(upb_FieldDef_Name(oneof_field)));
|
270
284
|
case METHOD_SETTER:
|
271
285
|
rb_raise(rb_eRuntimeError, "Oneof accessors are read-only.");
|
272
286
|
}
|
273
287
|
rb_raise(rb_eRuntimeError, "Invalid access of oneof field.");
|
274
288
|
}
|
275
289
|
|
276
|
-
static void Message_setfield(
|
277
|
-
|
278
|
-
|
279
|
-
if (
|
280
|
-
msgval.map_val = Map_GetUpbMap(val, f);
|
281
|
-
} else if (
|
282
|
-
msgval.array_val = RepeatedField_GetUpbArray(val, f);
|
290
|
+
static void Message_setfield(upb_Message* msg, const upb_FieldDef* f, VALUE val,
|
291
|
+
upb_Arena* arena) {
|
292
|
+
upb_MessageValue msgval;
|
293
|
+
if (upb_FieldDef_IsMap(f)) {
|
294
|
+
msgval.map_val = Map_GetUpbMap(val, f, arena);
|
295
|
+
} else if (upb_FieldDef_IsRepeated(f)) {
|
296
|
+
msgval.array_val = RepeatedField_GetUpbArray(val, f, arena);
|
283
297
|
} else {
|
284
298
|
if (val == Qnil &&
|
285
|
-
(
|
286
|
-
|
299
|
+
(upb_FieldDef_IsSubMessage(f) || upb_FieldDef_RealContainingOneof(f))) {
|
300
|
+
upb_Message_ClearFieldByDef(msg, f);
|
287
301
|
return;
|
288
302
|
}
|
289
303
|
msgval =
|
290
|
-
Convert_RubyToUpb(val,
|
304
|
+
Convert_RubyToUpb(val, upb_FieldDef_Name(f), TypeInfo_get(f), arena);
|
291
305
|
}
|
292
|
-
|
306
|
+
upb_Message_SetFieldByDef(msg, f, msgval, arena);
|
293
307
|
}
|
294
308
|
|
295
|
-
VALUE Message_getfield(VALUE _self, const
|
309
|
+
VALUE Message_getfield(VALUE _self, const upb_FieldDef* f) {
|
296
310
|
Message* self = ruby_to_Message(_self);
|
297
|
-
// This is a special-case:
|
311
|
+
// This is a special-case: upb_Message_Mutable() for map & array are logically
|
298
312
|
// const (they will not change what is serialized) but physically
|
299
313
|
// non-const, as they do allocate a repeated field or map. The logical
|
300
314
|
// constness means it's ok to do even if the message is frozen.
|
301
|
-
|
302
|
-
|
303
|
-
if (
|
304
|
-
|
305
|
-
const
|
306
|
-
const
|
307
|
-
|
315
|
+
upb_Message* msg = (upb_Message*)self->msg;
|
316
|
+
upb_Arena* arena = Arena_get(self->arena);
|
317
|
+
if (upb_FieldDef_IsMap(f)) {
|
318
|
+
upb_Map* map = upb_Message_Mutable(msg, f, arena).map;
|
319
|
+
const upb_FieldDef* key_f = map_field_key(f);
|
320
|
+
const upb_FieldDef* val_f = map_field_value(f);
|
321
|
+
upb_CType key_type = upb_FieldDef_CType(key_f);
|
308
322
|
TypeInfo value_type_info = TypeInfo_get(val_f);
|
309
323
|
return Map_GetRubyWrapper(map, key_type, value_type_info, self->arena);
|
310
|
-
} else if (
|
311
|
-
|
324
|
+
} else if (upb_FieldDef_IsRepeated(f)) {
|
325
|
+
upb_Array* arr = upb_Message_Mutable(msg, f, arena).array;
|
312
326
|
return RepeatedField_GetRubyWrapper(arr, TypeInfo_get(f), self->arena);
|
313
|
-
} else if (
|
314
|
-
if (!
|
315
|
-
|
316
|
-
const
|
327
|
+
} else if (upb_FieldDef_IsSubMessage(f)) {
|
328
|
+
if (!upb_Message_HasFieldByDef(self->msg, f)) return Qnil;
|
329
|
+
upb_Message* submsg = upb_Message_Mutable(msg, f, arena).msg;
|
330
|
+
const upb_MessageDef* m = upb_FieldDef_MessageSubDef(f);
|
317
331
|
return Message_GetRubyWrapper(submsg, m, self->arena);
|
318
332
|
} else {
|
319
|
-
|
333
|
+
upb_MessageValue msgval = upb_Message_GetFieldByDef(self->msg, f);
|
320
334
|
return Convert_UpbToRuby(msgval, TypeInfo_get(f), self->arena);
|
321
335
|
}
|
322
336
|
}
|
323
337
|
|
324
|
-
static VALUE Message_field_accessor(VALUE _self, const
|
338
|
+
static VALUE Message_field_accessor(VALUE _self, const upb_FieldDef* f,
|
325
339
|
int accessor_type, int argc, VALUE* argv) {
|
326
|
-
|
340
|
+
upb_Arena* arena = Arena_get(Message_GetArena(_self));
|
327
341
|
|
328
342
|
switch (accessor_type) {
|
329
343
|
case METHOD_SETTER:
|
330
344
|
Message_setfield(Message_GetMutable(_self, NULL), f, argv[1], arena);
|
331
345
|
return Qnil;
|
332
346
|
case METHOD_CLEAR:
|
333
|
-
|
347
|
+
upb_Message_ClearFieldByDef(Message_GetMutable(_self, NULL), f);
|
334
348
|
return Qnil;
|
335
349
|
case METHOD_PRESENCE:
|
336
|
-
if (!
|
350
|
+
if (!upb_FieldDef_HasPresence(f)) {
|
337
351
|
rb_raise(rb_eRuntimeError, "Field does not have presence.");
|
338
352
|
}
|
339
|
-
return
|
353
|
+
return upb_Message_HasFieldByDef(Message_Get(_self, NULL), f);
|
340
354
|
case METHOD_WRAPPER_GETTER: {
|
341
355
|
Message* self = ruby_to_Message(_self);
|
342
|
-
if (
|
343
|
-
PBRUBY_ASSERT(
|
344
|
-
|
345
|
-
|
346
|
-
const
|
347
|
-
|
356
|
+
if (upb_Message_HasFieldByDef(self->msg, f)) {
|
357
|
+
PBRUBY_ASSERT(upb_FieldDef_IsSubMessage(f) &&
|
358
|
+
!upb_FieldDef_IsRepeated(f));
|
359
|
+
upb_MessageValue wrapper = upb_Message_GetFieldByDef(self->msg, f);
|
360
|
+
const upb_MessageDef* wrapper_m = upb_FieldDef_MessageSubDef(f);
|
361
|
+
const upb_FieldDef* value_f =
|
362
|
+
upb_MessageDef_FindFieldByNumber(wrapper_m, 1);
|
363
|
+
upb_MessageValue value =
|
364
|
+
upb_Message_GetFieldByDef(wrapper.msg_val, value_f);
|
348
365
|
return Convert_UpbToRuby(value, TypeInfo_get(value_f), self->arena);
|
349
366
|
} else {
|
350
367
|
return Qnil;
|
351
368
|
}
|
352
369
|
}
|
353
370
|
case METHOD_WRAPPER_SETTER: {
|
354
|
-
|
371
|
+
upb_Message* msg = Message_GetMutable(_self, NULL);
|
355
372
|
if (argv[1] == Qnil) {
|
356
|
-
|
373
|
+
upb_Message_ClearFieldByDef(msg, f);
|
357
374
|
} else {
|
358
|
-
const
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
375
|
+
const upb_FieldDef* val_f =
|
376
|
+
upb_MessageDef_FindFieldByNumber(upb_FieldDef_MessageSubDef(f), 1);
|
377
|
+
upb_MessageValue msgval = Convert_RubyToUpb(
|
378
|
+
argv[1], upb_FieldDef_Name(f), TypeInfo_get(val_f), arena);
|
379
|
+
upb_Message* wrapper = upb_Message_Mutable(msg, f, arena).msg;
|
380
|
+
upb_Message_SetFieldByDef(wrapper, val_f, msgval, arena);
|
363
381
|
}
|
364
382
|
return Qnil;
|
365
383
|
}
|
366
384
|
case METHOD_ENUM_GETTER: {
|
367
|
-
|
385
|
+
upb_MessageValue msgval =
|
386
|
+
upb_Message_GetFieldByDef(Message_Get(_self, NULL), f);
|
368
387
|
|
369
|
-
if (
|
388
|
+
if (upb_FieldDef_Label(f) == kUpb_Label_Repeated) {
|
370
389
|
// Map repeated fields to a new type with ints
|
371
390
|
VALUE arr = rb_ary_new();
|
372
|
-
size_t i, n =
|
391
|
+
size_t i, n = upb_Array_Size(msgval.array_val);
|
373
392
|
for (i = 0; i < n; i++) {
|
374
|
-
|
393
|
+
upb_MessageValue elem = upb_Array_Get(msgval.array_val, i);
|
375
394
|
rb_ary_push(arr, INT2NUM(elem.int32_val));
|
376
395
|
}
|
377
396
|
return arr;
|
@@ -416,8 +435,8 @@ static VALUE Message_field_accessor(VALUE _self, const upb_fielddef* f,
|
|
416
435
|
*/
|
417
436
|
static VALUE Message_method_missing(int argc, VALUE* argv, VALUE _self) {
|
418
437
|
Message* self = ruby_to_Message(_self);
|
419
|
-
const
|
420
|
-
const
|
438
|
+
const upb_OneofDef* o;
|
439
|
+
const upb_FieldDef* f;
|
421
440
|
int accessor_type;
|
422
441
|
|
423
442
|
if (argc < 1) {
|
@@ -454,8 +473,8 @@ static VALUE Message_method_missing(int argc, VALUE* argv, VALUE _self) {
|
|
454
473
|
|
455
474
|
static VALUE Message_respond_to_missing(int argc, VALUE* argv, VALUE _self) {
|
456
475
|
Message* self = ruby_to_Message(_self);
|
457
|
-
const
|
458
|
-
const
|
476
|
+
const upb_OneofDef* o;
|
477
|
+
const upb_FieldDef* f;
|
459
478
|
int accessor_type;
|
460
479
|
|
461
480
|
if (argc < 1) {
|
@@ -473,53 +492,55 @@ static VALUE Message_respond_to_missing(int argc, VALUE* argv, VALUE _self) {
|
|
473
492
|
}
|
474
493
|
}
|
475
494
|
|
476
|
-
void Message_InitFromValue(
|
477
|
-
|
495
|
+
void Message_InitFromValue(upb_Message* msg, const upb_MessageDef* m, VALUE val,
|
496
|
+
upb_Arena* arena);
|
478
497
|
|
479
498
|
typedef struct {
|
480
|
-
|
499
|
+
upb_Map* map;
|
481
500
|
TypeInfo key_type;
|
482
501
|
TypeInfo val_type;
|
483
|
-
|
502
|
+
upb_Arena* arena;
|
484
503
|
} MapInit;
|
485
504
|
|
486
505
|
static int Map_initialize_kwarg(VALUE key, VALUE val, VALUE _self) {
|
487
|
-
MapInit
|
488
|
-
|
506
|
+
MapInit* map_init = (MapInit*)_self;
|
507
|
+
upb_MessageValue k, v;
|
489
508
|
k = Convert_RubyToUpb(key, "", map_init->key_type, NULL);
|
490
509
|
|
491
|
-
if (map_init->val_type.type ==
|
492
|
-
|
510
|
+
if (map_init->val_type.type == kUpb_CType_Message && TYPE(val) == T_HASH) {
|
511
|
+
upb_MiniTable* t = upb_MessageDef_MiniTable(map_init->val_type.def.msgdef);
|
512
|
+
upb_Message* msg = upb_Message_New(t, map_init->arena);
|
493
513
|
Message_InitFromValue(msg, map_init->val_type.def.msgdef, val,
|
494
514
|
map_init->arena);
|
495
515
|
v.msg_val = msg;
|
496
516
|
} else {
|
497
517
|
v = Convert_RubyToUpb(val, "", map_init->val_type, map_init->arena);
|
498
518
|
}
|
499
|
-
|
519
|
+
upb_Map_Set(map_init->map, k, v, map_init->arena);
|
500
520
|
return ST_CONTINUE;
|
501
521
|
}
|
502
522
|
|
503
|
-
static void Map_InitFromValue(
|
504
|
-
|
505
|
-
const
|
506
|
-
const
|
507
|
-
const
|
523
|
+
static void Map_InitFromValue(upb_Map* map, const upb_FieldDef* f, VALUE val,
|
524
|
+
upb_Arena* arena) {
|
525
|
+
const upb_MessageDef* entry_m = upb_FieldDef_MessageSubDef(f);
|
526
|
+
const upb_FieldDef* key_f = upb_MessageDef_FindFieldByNumber(entry_m, 1);
|
527
|
+
const upb_FieldDef* val_f = upb_MessageDef_FindFieldByNumber(entry_m, 2);
|
508
528
|
if (TYPE(val) != T_HASH) {
|
509
529
|
rb_raise(rb_eArgError,
|
510
530
|
"Expected Hash object as initializer value for map field '%s' "
|
511
531
|
"(given %s).",
|
512
|
-
|
532
|
+
upb_FieldDef_Name(f), rb_class2name(CLASS_OF(val)));
|
513
533
|
}
|
514
534
|
MapInit map_init = {map, TypeInfo_get(key_f), TypeInfo_get(val_f), arena};
|
515
535
|
rb_hash_foreach(val, Map_initialize_kwarg, (VALUE)&map_init);
|
516
536
|
}
|
517
537
|
|
518
|
-
static
|
519
|
-
|
520
|
-
if (info.type ==
|
521
|
-
|
522
|
-
|
538
|
+
static upb_MessageValue MessageValue_FromValue(VALUE val, TypeInfo info,
|
539
|
+
upb_Arena* arena) {
|
540
|
+
if (info.type == kUpb_CType_Message) {
|
541
|
+
upb_MessageValue msgval;
|
542
|
+
upb_MiniTable* t = upb_MessageDef_MiniTable(info.def.msgdef);
|
543
|
+
upb_Message* msg = upb_Message_New(t, arena);
|
523
544
|
Message_InitFromValue(msg, info.def.msgdef, val, arena);
|
524
545
|
msgval.msg_val = msg;
|
525
546
|
return msgval;
|
@@ -528,61 +549,62 @@ static upb_msgval MessageValue_FromValue(VALUE val, TypeInfo info,
|
|
528
549
|
}
|
529
550
|
}
|
530
551
|
|
531
|
-
static void RepeatedField_InitFromValue(
|
532
|
-
VALUE val,
|
552
|
+
static void RepeatedField_InitFromValue(upb_Array* arr, const upb_FieldDef* f,
|
553
|
+
VALUE val, upb_Arena* arena) {
|
533
554
|
TypeInfo type_info = TypeInfo_get(f);
|
534
555
|
|
535
556
|
if (TYPE(val) != T_ARRAY) {
|
536
557
|
rb_raise(rb_eArgError,
|
537
|
-
"Expected array as initializer value for repeated field '%s'
|
538
|
-
|
558
|
+
"Expected array as initializer value for repeated field '%s' "
|
559
|
+
"(given %s).",
|
560
|
+
upb_FieldDef_Name(f), rb_class2name(CLASS_OF(val)));
|
539
561
|
}
|
540
562
|
|
541
563
|
for (int i = 0; i < RARRAY_LEN(val); i++) {
|
542
564
|
VALUE entry = rb_ary_entry(val, i);
|
543
|
-
|
544
|
-
if (
|
565
|
+
upb_MessageValue msgval;
|
566
|
+
if (upb_FieldDef_IsSubMessage(f) && TYPE(entry) == T_HASH) {
|
545
567
|
msgval = MessageValue_FromValue(entry, type_info, arena);
|
546
568
|
} else {
|
547
|
-
msgval = Convert_RubyToUpb(entry,
|
569
|
+
msgval = Convert_RubyToUpb(entry, upb_FieldDef_Name(f), type_info, arena);
|
548
570
|
}
|
549
|
-
|
571
|
+
upb_Array_Append(arr, msgval, arena);
|
550
572
|
}
|
551
573
|
}
|
552
574
|
|
553
|
-
static void Message_InitFieldFromValue(
|
554
|
-
VALUE val,
|
575
|
+
static void Message_InitFieldFromValue(upb_Message* msg, const upb_FieldDef* f,
|
576
|
+
VALUE val, upb_Arena* arena) {
|
555
577
|
if (TYPE(val) == T_NIL) return;
|
556
578
|
|
557
|
-
if (
|
558
|
-
|
579
|
+
if (upb_FieldDef_IsMap(f)) {
|
580
|
+
upb_Map* map = upb_Message_Mutable(msg, f, arena).map;
|
559
581
|
Map_InitFromValue(map, f, val, arena);
|
560
|
-
} else if (
|
561
|
-
|
582
|
+
} else if (upb_FieldDef_Label(f) == kUpb_Label_Repeated) {
|
583
|
+
upb_Array* arr = upb_Message_Mutable(msg, f, arena).array;
|
562
584
|
RepeatedField_InitFromValue(arr, f, val, arena);
|
563
|
-
} else if (
|
585
|
+
} else if (upb_FieldDef_IsSubMessage(f)) {
|
564
586
|
if (TYPE(val) == T_HASH) {
|
565
|
-
|
566
|
-
Message_InitFromValue(submsg,
|
587
|
+
upb_Message* submsg = upb_Message_Mutable(msg, f, arena).msg;
|
588
|
+
Message_InitFromValue(submsg, upb_FieldDef_MessageSubDef(f), val, arena);
|
567
589
|
} else {
|
568
590
|
Message_setfield(msg, f, val, arena);
|
569
591
|
}
|
570
592
|
} else {
|
571
|
-
|
572
|
-
Convert_RubyToUpb(val,
|
573
|
-
|
593
|
+
upb_MessageValue msgval =
|
594
|
+
Convert_RubyToUpb(val, upb_FieldDef_Name(f), TypeInfo_get(f), arena);
|
595
|
+
upb_Message_SetFieldByDef(msg, f, msgval, arena);
|
574
596
|
}
|
575
597
|
}
|
576
598
|
|
577
599
|
typedef struct {
|
578
|
-
|
579
|
-
const
|
580
|
-
|
600
|
+
upb_Message* msg;
|
601
|
+
const upb_MessageDef* msgdef;
|
602
|
+
upb_Arena* arena;
|
581
603
|
} MsgInit;
|
582
604
|
|
583
605
|
static int Message_initialize_kwarg(VALUE key, VALUE val, VALUE _self) {
|
584
|
-
MsgInit
|
585
|
-
const char
|
606
|
+
MsgInit* msg_init = (MsgInit*)_self;
|
607
|
+
const char* name;
|
586
608
|
|
587
609
|
if (TYPE(key) == T_STRING) {
|
588
610
|
name = RSTRING_PTR(key);
|
@@ -590,10 +612,12 @@ static int Message_initialize_kwarg(VALUE key, VALUE val, VALUE _self) {
|
|
590
612
|
name = RSTRING_PTR(rb_id2str(SYM2ID(key)));
|
591
613
|
} else {
|
592
614
|
rb_raise(rb_eArgError,
|
593
|
-
"Expected string or symbols as hash keys when initializing proto
|
615
|
+
"Expected string or symbols as hash keys when initializing proto "
|
616
|
+
"from hash.");
|
594
617
|
}
|
595
618
|
|
596
|
-
const
|
619
|
+
const upb_FieldDef* f =
|
620
|
+
upb_MessageDef_FindFieldByName(msg_init->msgdef, name);
|
597
621
|
|
598
622
|
if (f == NULL) {
|
599
623
|
rb_raise(rb_eArgError,
|
@@ -604,8 +628,8 @@ static int Message_initialize_kwarg(VALUE key, VALUE val, VALUE _self) {
|
|
604
628
|
return ST_CONTINUE;
|
605
629
|
}
|
606
630
|
|
607
|
-
void Message_InitFromValue(
|
608
|
-
|
631
|
+
void Message_InitFromValue(upb_Message* msg, const upb_MessageDef* m, VALUE val,
|
632
|
+
upb_Arena* arena) {
|
609
633
|
MsgInit msg_init = {msg, m, arena};
|
610
634
|
if (TYPE(val) == T_HASH) {
|
611
635
|
rb_hash_foreach(val, Message_initialize_kwarg, (VALUE)&msg_init);
|
@@ -630,8 +654,9 @@ void Message_InitFromValue(upb_msg* msg, const upb_msgdef* m, VALUE val,
|
|
630
654
|
static VALUE Message_initialize(int argc, VALUE* argv, VALUE _self) {
|
631
655
|
Message* self = ruby_to_Message(_self);
|
632
656
|
VALUE arena_rb = Arena_new();
|
633
|
-
|
634
|
-
|
657
|
+
upb_Arena* arena = Arena_get(arena_rb);
|
658
|
+
upb_MiniTable* t = upb_MessageDef_MiniTable(self->msgdef);
|
659
|
+
upb_Message* msg = upb_Message_New(t, arena);
|
635
660
|
|
636
661
|
Message_InitPtr(_self, msg, arena_rb);
|
637
662
|
|
@@ -641,7 +666,7 @@ static VALUE Message_initialize(int argc, VALUE* argv, VALUE _self) {
|
|
641
666
|
if (argc != 1) {
|
642
667
|
rb_raise(rb_eArgError, "Expected 0 or 1 arguments.");
|
643
668
|
}
|
644
|
-
Message_InitFromValue((
|
669
|
+
Message_InitFromValue((upb_Message*)self->msg, self->msgdef, argv[0], arena);
|
645
670
|
return Qnil;
|
646
671
|
}
|
647
672
|
|
@@ -655,34 +680,40 @@ static VALUE Message_dup(VALUE _self) {
|
|
655
680
|
Message* self = ruby_to_Message(_self);
|
656
681
|
VALUE new_msg = rb_class_new_instance(0, NULL, CLASS_OF(_self));
|
657
682
|
Message* new_msg_self = ruby_to_Message(new_msg);
|
658
|
-
size_t size =
|
683
|
+
size_t size = upb_MessageDef_MiniTable(self->msgdef)->size;
|
659
684
|
|
660
685
|
// TODO(copy unknown fields?)
|
661
686
|
// TODO(use official upb msg copy function)
|
662
|
-
memcpy((
|
663
|
-
|
687
|
+
memcpy((upb_Message*)new_msg_self->msg, self->msg, size);
|
688
|
+
Arena_fuse(self->arena, Arena_get(new_msg_self->arena));
|
664
689
|
return new_msg;
|
665
690
|
}
|
666
691
|
|
667
692
|
// Support function for Message_eq, and also used by other #eq functions.
|
668
|
-
bool Message_Equal(const
|
693
|
+
bool Message_Equal(const upb_Message* m1, const upb_Message* m2,
|
694
|
+
const upb_MessageDef* m) {
|
669
695
|
if (m1 == m2) return true;
|
670
696
|
|
671
697
|
size_t size1, size2;
|
672
|
-
int encode_opts =
|
673
|
-
|
674
|
-
|
698
|
+
int encode_opts =
|
699
|
+
kUpb_EncodeOption_SkipUnknown | kUpb_EncodeOption_Deterministic;
|
700
|
+
upb_Arena* arena_tmp = upb_Arena_New();
|
701
|
+
const upb_MiniTable* layout = upb_MessageDef_MiniTable(m);
|
675
702
|
|
676
703
|
// Compare deterministically serialized payloads with no unknown fields.
|
677
|
-
char
|
678
|
-
char
|
679
|
-
|
680
|
-
|
704
|
+
char* data1;
|
705
|
+
char* data2;
|
706
|
+
upb_EncodeStatus status1 =
|
707
|
+
upb_Encode(m1, layout, encode_opts, arena_tmp, &data1, &size1);
|
708
|
+
upb_EncodeStatus status2 =
|
709
|
+
upb_Encode(m2, layout, encode_opts, arena_tmp, &data2, &size2);
|
710
|
+
|
711
|
+
if (status1 == kUpb_EncodeStatus_Ok && status2 == kUpb_EncodeStatus_Ok) {
|
681
712
|
bool ret = (size1 == size2) && (memcmp(data1, data2, size1) == 0);
|
682
|
-
|
713
|
+
upb_Arena_Free(arena_tmp);
|
683
714
|
return ret;
|
684
715
|
} else {
|
685
|
-
|
716
|
+
upb_Arena_Free(arena_tmp);
|
686
717
|
rb_raise(cParseError, "Error comparing messages");
|
687
718
|
}
|
688
719
|
}
|
@@ -706,22 +737,24 @@ static VALUE Message_eq(VALUE _self, VALUE _other) {
|
|
706
737
|
return Message_Equal(self->msg, other->msg, self->msgdef) ? Qtrue : Qfalse;
|
707
738
|
}
|
708
739
|
|
709
|
-
uint64_t Message_Hash(const
|
710
|
-
|
711
|
-
|
740
|
+
uint64_t Message_Hash(const upb_Message* msg, const upb_MessageDef* m,
|
741
|
+
uint64_t seed) {
|
742
|
+
upb_Arena* arena = upb_Arena_New();
|
743
|
+
char* data;
|
712
744
|
size_t size;
|
713
745
|
|
714
746
|
// Hash a deterministically serialized payloads with no unknown fields.
|
715
|
-
|
716
|
-
|
717
|
-
|
718
|
-
|
719
|
-
|
720
|
-
|
721
|
-
|
747
|
+
upb_EncodeStatus status = upb_Encode(
|
748
|
+
msg, upb_MessageDef_MiniTable(m),
|
749
|
+
kUpb_EncodeOption_SkipUnknown | kUpb_EncodeOption_Deterministic, arena,
|
750
|
+
&data, &size);
|
751
|
+
|
752
|
+
if (status == kUpb_EncodeStatus_Ok) {
|
753
|
+
uint64_t ret = _upb_Hash(data, size, seed);
|
754
|
+
upb_Arena_Free(arena);
|
722
755
|
return ret;
|
723
756
|
} else {
|
724
|
-
|
757
|
+
upb_Arena_Free(arena);
|
725
758
|
rb_raise(cParseError, "Error calculating hash");
|
726
759
|
}
|
727
760
|
}
|
@@ -760,13 +793,13 @@ static VALUE Message_inspect(VALUE _self) {
|
|
760
793
|
|
761
794
|
// Support functions for Message_to_h //////////////////////////////////////////
|
762
795
|
|
763
|
-
static VALUE RepeatedField_CreateArray(const
|
796
|
+
static VALUE RepeatedField_CreateArray(const upb_Array* arr,
|
764
797
|
TypeInfo type_info) {
|
765
|
-
int size = arr ?
|
798
|
+
int size = arr ? upb_Array_Size(arr) : 0;
|
766
799
|
VALUE ary = rb_ary_new2(size);
|
767
800
|
|
768
801
|
for (int i = 0; i < size; i++) {
|
769
|
-
|
802
|
+
upb_MessageValue msgval = upb_Array_Get(arr, i);
|
770
803
|
VALUE val = Scalar_CreateHash(msgval, type_info);
|
771
804
|
rb_ary_push(ary, val);
|
772
805
|
}
|
@@ -774,46 +807,56 @@ static VALUE RepeatedField_CreateArray(const upb_array* arr,
|
|
774
807
|
return ary;
|
775
808
|
}
|
776
809
|
|
777
|
-
static VALUE Message_CreateHash(const
|
810
|
+
static VALUE Message_CreateHash(const upb_Message* msg,
|
811
|
+
const upb_MessageDef* m) {
|
778
812
|
if (!msg) return Qnil;
|
779
813
|
|
780
814
|
VALUE hash = rb_hash_new();
|
781
|
-
int n =
|
815
|
+
int n = upb_MessageDef_FieldCount(m);
|
782
816
|
bool is_proto2;
|
783
817
|
|
784
818
|
// We currently have a few behaviors that are specific to proto2.
|
785
819
|
// This is unfortunate, we should key behaviors off field attributes (like
|
786
820
|
// whether a field has presence), not proto2 vs. proto3. We should see if we
|
787
821
|
// can change this without breaking users.
|
788
|
-
is_proto2 =
|
822
|
+
is_proto2 = upb_MessageDef_Syntax(m) == kUpb_Syntax_Proto2;
|
789
823
|
|
790
824
|
for (int i = 0; i < n; i++) {
|
791
|
-
const
|
825
|
+
const upb_FieldDef* field = upb_MessageDef_Field(m, i);
|
792
826
|
TypeInfo type_info = TypeInfo_get(field);
|
793
|
-
|
827
|
+
upb_MessageValue msgval;
|
794
828
|
VALUE msg_value;
|
795
829
|
VALUE msg_key;
|
796
830
|
|
831
|
+
if (!is_proto2 && upb_FieldDef_IsSubMessage(field) &&
|
832
|
+
!upb_FieldDef_IsRepeated(field) &&
|
833
|
+
!upb_Message_HasFieldByDef(msg, field)) {
|
834
|
+
// TODO: Legacy behavior, remove when we fix the is_proto2 differences.
|
835
|
+
msg_key = ID2SYM(rb_intern(upb_FieldDef_Name(field)));
|
836
|
+
rb_hash_aset(hash, msg_key, Qnil);
|
837
|
+
continue;
|
838
|
+
}
|
839
|
+
|
797
840
|
// Do not include fields that are not present (oneof or optional fields).
|
798
|
-
if (is_proto2 &&
|
799
|
-
!
|
841
|
+
if (is_proto2 && upb_FieldDef_HasPresence(field) &&
|
842
|
+
!upb_Message_HasFieldByDef(msg, field)) {
|
800
843
|
continue;
|
801
844
|
}
|
802
845
|
|
803
|
-
msg_key = ID2SYM(rb_intern(
|
804
|
-
msgval =
|
846
|
+
msg_key = ID2SYM(rb_intern(upb_FieldDef_Name(field)));
|
847
|
+
msgval = upb_Message_GetFieldByDef(msg, field);
|
805
848
|
|
806
849
|
// Proto2 omits empty map/repeated filds also.
|
807
850
|
|
808
|
-
if (
|
809
|
-
const
|
810
|
-
const
|
811
|
-
const
|
812
|
-
|
851
|
+
if (upb_FieldDef_IsMap(field)) {
|
852
|
+
const upb_MessageDef* entry_m = upb_FieldDef_MessageSubDef(field);
|
853
|
+
const upb_FieldDef* key_f = upb_MessageDef_FindFieldByNumber(entry_m, 1);
|
854
|
+
const upb_FieldDef* val_f = upb_MessageDef_FindFieldByNumber(entry_m, 2);
|
855
|
+
upb_CType key_type = upb_FieldDef_CType(key_f);
|
813
856
|
msg_value = Map_CreateHash(msgval.map_val, key_type, TypeInfo_get(val_f));
|
814
|
-
} else if (
|
857
|
+
} else if (upb_FieldDef_IsRepeated(field)) {
|
815
858
|
if (is_proto2 &&
|
816
|
-
(!msgval.array_val ||
|
859
|
+
(!msgval.array_val || upb_Array_Size(msgval.array_val) == 0)) {
|
817
860
|
continue;
|
818
861
|
}
|
819
862
|
msg_value = RepeatedField_CreateArray(msgval.array_val, type_info);
|
@@ -827,8 +870,8 @@ static VALUE Message_CreateHash(const upb_msg *msg, const upb_msgdef *m) {
|
|
827
870
|
return hash;
|
828
871
|
}
|
829
872
|
|
830
|
-
VALUE Scalar_CreateHash(
|
831
|
-
if (type_info.type ==
|
873
|
+
VALUE Scalar_CreateHash(upb_MessageValue msgval, TypeInfo type_info) {
|
874
|
+
if (type_info.type == kUpb_CType_Message) {
|
832
875
|
return Message_CreateHash(msgval.msg_val, type_info.def.msgdef);
|
833
876
|
} else {
|
834
877
|
return Convert_UpbToRuby(msgval, type_info, Qnil);
|
@@ -871,10 +914,10 @@ static VALUE Message_freeze(VALUE _self) {
|
|
871
914
|
*/
|
872
915
|
static VALUE Message_index(VALUE _self, VALUE field_name) {
|
873
916
|
Message* self = ruby_to_Message(_self);
|
874
|
-
const
|
917
|
+
const upb_FieldDef* field;
|
875
918
|
|
876
919
|
Check_Type(field_name, T_STRING);
|
877
|
-
field =
|
920
|
+
field = upb_MessageDef_FindFieldByName(self->msgdef, RSTRING_PTR(field_name));
|
878
921
|
|
879
922
|
if (field == NULL) {
|
880
923
|
return Qnil;
|
@@ -892,32 +935,55 @@ static VALUE Message_index(VALUE _self, VALUE field_name) {
|
|
892
935
|
*/
|
893
936
|
static VALUE Message_index_set(VALUE _self, VALUE field_name, VALUE value) {
|
894
937
|
Message* self = ruby_to_Message(_self);
|
895
|
-
const
|
896
|
-
|
897
|
-
|
938
|
+
const upb_FieldDef* f;
|
939
|
+
upb_MessageValue val;
|
940
|
+
upb_Arena* arena = Arena_get(self->arena);
|
898
941
|
|
899
942
|
Check_Type(field_name, T_STRING);
|
900
|
-
f =
|
943
|
+
f = upb_MessageDef_FindFieldByName(self->msgdef, RSTRING_PTR(field_name));
|
901
944
|
|
902
945
|
if (f == NULL) {
|
903
946
|
rb_raise(rb_eArgError, "Unknown field: %s", RSTRING_PTR(field_name));
|
904
947
|
}
|
905
948
|
|
906
|
-
val = Convert_RubyToUpb(value,
|
907
|
-
|
949
|
+
val = Convert_RubyToUpb(value, upb_FieldDef_Name(f), TypeInfo_get(f), arena);
|
950
|
+
upb_Message_SetFieldByDef(Message_GetMutable(_self, NULL), f, val, arena);
|
908
951
|
|
909
952
|
return Qnil;
|
910
953
|
}
|
911
954
|
|
912
955
|
/*
|
913
956
|
* call-seq:
|
914
|
-
* MessageClass.decode(data) => message
|
957
|
+
* MessageClass.decode(data, options) => message
|
915
958
|
*
|
916
959
|
* Decodes the given data (as a string containing bytes in protocol buffers wire
|
917
960
|
* format) under the interpretration given by this message class's definition
|
918
961
|
* and returns a message object with the corresponding field values.
|
962
|
+
* @param options [Hash] options for the decoder
|
963
|
+
* recursion_limit: set to maximum decoding depth for message (default is 64)
|
919
964
|
*/
|
920
|
-
static VALUE Message_decode(VALUE
|
965
|
+
static VALUE Message_decode(int argc, VALUE* argv, VALUE klass) {
|
966
|
+
VALUE data = argv[0];
|
967
|
+
int options = 0;
|
968
|
+
|
969
|
+
if (argc < 1 || argc > 2) {
|
970
|
+
rb_raise(rb_eArgError, "Expected 1 or 2 arguments.");
|
971
|
+
}
|
972
|
+
|
973
|
+
if (argc == 2) {
|
974
|
+
VALUE hash_args = argv[1];
|
975
|
+
if (TYPE(hash_args) != T_HASH) {
|
976
|
+
rb_raise(rb_eArgError, "Expected hash arguments.");
|
977
|
+
}
|
978
|
+
|
979
|
+
VALUE depth =
|
980
|
+
rb_hash_lookup(hash_args, ID2SYM(rb_intern("recursion_limit")));
|
981
|
+
|
982
|
+
if (depth != Qnil && TYPE(depth) == T_FIXNUM) {
|
983
|
+
options |= upb_DecodeOptions_MaxDepth(FIX2INT(depth));
|
984
|
+
}
|
985
|
+
}
|
986
|
+
|
921
987
|
if (TYPE(data) != T_STRING) {
|
922
988
|
rb_raise(rb_eArgError, "Expected string for binary protobuf data.");
|
923
989
|
}
|
@@ -925,9 +991,12 @@ static VALUE Message_decode(VALUE klass, VALUE data) {
|
|
925
991
|
VALUE msg_rb = initialize_rb_class_with_no_args(klass);
|
926
992
|
Message* msg = ruby_to_Message(msg_rb);
|
927
993
|
|
928
|
-
|
929
|
-
|
930
|
-
|
994
|
+
upb_DecodeStatus status =
|
995
|
+
upb_Decode(RSTRING_PTR(data), RSTRING_LEN(data), (upb_Message*)msg->msg,
|
996
|
+
upb_MessageDef_MiniTable(msg->msgdef), NULL, options,
|
997
|
+
Arena_get(msg->arena));
|
998
|
+
|
999
|
+
if (status != kUpb_DecodeStatus_Ok) {
|
931
1000
|
rb_raise(cParseError, "Error occurred during parsing");
|
932
1001
|
}
|
933
1002
|
|
@@ -949,10 +1018,10 @@ static VALUE Message_decode(VALUE klass, VALUE data) {
|
|
949
1018
|
static VALUE Message_decode_json(int argc, VALUE* argv, VALUE klass) {
|
950
1019
|
VALUE data = argv[0];
|
951
1020
|
int options = 0;
|
952
|
-
|
1021
|
+
upb_Status status;
|
953
1022
|
|
954
1023
|
// TODO(haberman): use this message's pool instead.
|
955
|
-
const
|
1024
|
+
const upb_DefPool* symtab = DescriptorPool_GetSymtab(generated_pool);
|
956
1025
|
|
957
1026
|
if (argc < 1 || argc > 2) {
|
958
1027
|
rb_raise(rb_eArgError, "Expected 1 or 2 arguments.");
|
@@ -964,8 +1033,9 @@ static VALUE Message_decode_json(int argc, VALUE* argv, VALUE klass) {
|
|
964
1033
|
rb_raise(rb_eArgError, "Expected hash arguments.");
|
965
1034
|
}
|
966
1035
|
|
967
|
-
if (RTEST(rb_hash_lookup2(
|
968
|
-
|
1036
|
+
if (RTEST(rb_hash_lookup2(
|
1037
|
+
hash_args, ID2SYM(rb_intern("ignore_unknown_fields")), Qfalse))) {
|
1038
|
+
options |= upb_JsonDecode_IgnoreUnknown;
|
969
1039
|
}
|
970
1040
|
}
|
971
1041
|
|
@@ -981,16 +1051,16 @@ static VALUE Message_decode_json(int argc, VALUE* argv, VALUE klass) {
|
|
981
1051
|
Message* msg = ruby_to_Message(msg_rb);
|
982
1052
|
|
983
1053
|
// We don't allow users to decode a wrapper type directly.
|
984
|
-
if (
|
1054
|
+
if (IsWrapper(msg->msgdef)) {
|
985
1055
|
rb_raise(rb_eRuntimeError, "Cannot parse a wrapper directly.");
|
986
1056
|
}
|
987
1057
|
|
988
|
-
|
989
|
-
if (!
|
990
|
-
|
991
|
-
|
1058
|
+
upb_Status_Clear(&status);
|
1059
|
+
if (!upb_JsonDecode(RSTRING_PTR(data), RSTRING_LEN(data),
|
1060
|
+
(upb_Message*)msg->msg, msg->msgdef, symtab, options,
|
1061
|
+
Arena_get(msg->arena), &status)) {
|
992
1062
|
rb_raise(cParseError, "Error occurred during parsing: %s",
|
993
|
-
|
1063
|
+
upb_Status_ErrorMessage(&status));
|
994
1064
|
}
|
995
1065
|
|
996
1066
|
return msg_rb;
|
@@ -998,31 +1068,53 @@ static VALUE Message_decode_json(int argc, VALUE* argv, VALUE klass) {
|
|
998
1068
|
|
999
1069
|
/*
|
1000
1070
|
* call-seq:
|
1001
|
-
* MessageClass.encode(msg) => bytes
|
1071
|
+
* MessageClass.encode(msg, options) => bytes
|
1002
1072
|
*
|
1003
1073
|
* Encodes the given message object to its serialized form in protocol buffers
|
1004
1074
|
* wire format.
|
1075
|
+
* @param options [Hash] options for the encoder
|
1076
|
+
* recursion_limit: set to maximum encoding depth for message (default is 64)
|
1005
1077
|
*/
|
1006
|
-
static VALUE Message_encode(VALUE
|
1007
|
-
Message* msg = ruby_to_Message(
|
1008
|
-
|
1009
|
-
|
1078
|
+
static VALUE Message_encode(int argc, VALUE* argv, VALUE klass) {
|
1079
|
+
Message* msg = ruby_to_Message(argv[0]);
|
1080
|
+
int options = 0;
|
1081
|
+
char* data;
|
1010
1082
|
size_t size;
|
1011
1083
|
|
1012
|
-
if (CLASS_OF(
|
1084
|
+
if (CLASS_OF(argv[0]) != klass) {
|
1013
1085
|
rb_raise(rb_eArgError, "Message of wrong type.");
|
1014
1086
|
}
|
1015
1087
|
|
1016
|
-
|
1017
|
-
|
1088
|
+
if (argc < 1 || argc > 2) {
|
1089
|
+
rb_raise(rb_eArgError, "Expected 1 or 2 arguments.");
|
1090
|
+
}
|
1018
1091
|
|
1019
|
-
if (
|
1092
|
+
if (argc == 2) {
|
1093
|
+
VALUE hash_args = argv[1];
|
1094
|
+
if (TYPE(hash_args) != T_HASH) {
|
1095
|
+
rb_raise(rb_eArgError, "Expected hash arguments.");
|
1096
|
+
}
|
1097
|
+
VALUE depth =
|
1098
|
+
rb_hash_lookup(hash_args, ID2SYM(rb_intern("recursion_limit")));
|
1099
|
+
|
1100
|
+
if (depth != Qnil && TYPE(depth) == T_FIXNUM) {
|
1101
|
+
options |= upb_DecodeOptions_MaxDepth(FIX2INT(depth));
|
1102
|
+
}
|
1103
|
+
}
|
1104
|
+
|
1105
|
+
upb_Arena* arena = upb_Arena_New();
|
1106
|
+
|
1107
|
+
upb_EncodeStatus status =
|
1108
|
+
upb_Encode(msg->msg, upb_MessageDef_MiniTable(msg->msgdef), options,
|
1109
|
+
arena, &data, &size);
|
1110
|
+
|
1111
|
+
if (status == kUpb_EncodeStatus_Ok) {
|
1020
1112
|
VALUE ret = rb_str_new(data, size);
|
1021
1113
|
rb_enc_associate(ret, rb_ascii8bit_encoding());
|
1022
|
-
|
1114
|
+
upb_Arena_Free(arena);
|
1023
1115
|
return ret;
|
1024
1116
|
} else {
|
1025
|
-
|
1117
|
+
upb_Arena_Free(arena);
|
1026
1118
|
rb_raise(rb_eRuntimeError, "Exceeded maximum depth (possibly cycle)");
|
1027
1119
|
}
|
1028
1120
|
}
|
@@ -1033,18 +1125,19 @@ static VALUE Message_encode(VALUE klass, VALUE msg_rb) {
|
|
1033
1125
|
*
|
1034
1126
|
* Encodes the given message object into its serialized JSON representation.
|
1035
1127
|
* @param options [Hash] options for the decoder
|
1036
|
-
* preserve_proto_fieldnames: set true to use original fieldnames (default is
|
1037
|
-
*
|
1128
|
+
* preserve_proto_fieldnames: set true to use original fieldnames (default is
|
1129
|
+
* to camelCase) emit_defaults: set true to emit 0/false values (default is to
|
1130
|
+
* omit them)
|
1038
1131
|
*/
|
1039
1132
|
static VALUE Message_encode_json(int argc, VALUE* argv, VALUE klass) {
|
1040
1133
|
Message* msg = ruby_to_Message(argv[0]);
|
1041
1134
|
int options = 0;
|
1042
1135
|
char buf[1024];
|
1043
1136
|
size_t size;
|
1044
|
-
|
1137
|
+
upb_Status status;
|
1045
1138
|
|
1046
1139
|
// TODO(haberman): use this message's pool instead.
|
1047
|
-
const
|
1140
|
+
const upb_DefPool* symtab = DescriptorPool_GetSymtab(generated_pool);
|
1048
1141
|
|
1049
1142
|
if (argc < 1 || argc > 2) {
|
1050
1143
|
rb_raise(rb_eArgError, "Expected 1 or 2 arguments.");
|
@@ -1053,35 +1146,46 @@ static VALUE Message_encode_json(int argc, VALUE* argv, VALUE klass) {
|
|
1053
1146
|
if (argc == 2) {
|
1054
1147
|
VALUE hash_args = argv[1];
|
1055
1148
|
if (TYPE(hash_args) != T_HASH) {
|
1056
|
-
|
1149
|
+
if (RTEST(rb_funcall(hash_args, rb_intern("respond_to?"), 1,
|
1150
|
+
rb_str_new2("to_h")))) {
|
1151
|
+
hash_args = rb_funcall(hash_args, rb_intern("to_h"), 0);
|
1152
|
+
} else {
|
1153
|
+
rb_raise(rb_eArgError, "Expected hash arguments.");
|
1154
|
+
}
|
1057
1155
|
}
|
1058
1156
|
|
1059
1157
|
if (RTEST(rb_hash_lookup2(hash_args,
|
1060
1158
|
ID2SYM(rb_intern("preserve_proto_fieldnames")),
|
1061
1159
|
Qfalse))) {
|
1062
|
-
options |=
|
1160
|
+
options |= upb_JsonEncode_UseProtoNames;
|
1063
1161
|
}
|
1064
1162
|
|
1065
1163
|
if (RTEST(rb_hash_lookup2(hash_args, ID2SYM(rb_intern("emit_defaults")),
|
1066
1164
|
Qfalse))) {
|
1067
|
-
options |=
|
1165
|
+
options |= upb_JsonEncode_EmitDefaults;
|
1166
|
+
}
|
1167
|
+
|
1168
|
+
if (RTEST(rb_hash_lookup2(hash_args,
|
1169
|
+
ID2SYM(rb_intern("format_enums_as_integers")),
|
1170
|
+
Qfalse))) {
|
1171
|
+
options |= upb_JsonEncode_FormatEnumsAsIntegers;
|
1068
1172
|
}
|
1069
1173
|
}
|
1070
1174
|
|
1071
|
-
|
1072
|
-
size =
|
1073
|
-
|
1175
|
+
upb_Status_Clear(&status);
|
1176
|
+
size = upb_JsonEncode(msg->msg, msg->msgdef, symtab, options, buf,
|
1177
|
+
sizeof(buf), &status);
|
1074
1178
|
|
1075
|
-
if (!
|
1179
|
+
if (!upb_Status_IsOk(&status)) {
|
1076
1180
|
rb_raise(cParseError, "Error occurred during encoding: %s",
|
1077
|
-
|
1181
|
+
upb_Status_ErrorMessage(&status));
|
1078
1182
|
}
|
1079
1183
|
|
1080
1184
|
VALUE ret;
|
1081
1185
|
if (size >= sizeof(buf)) {
|
1082
1186
|
char* buf2 = malloc(size + 1);
|
1083
|
-
|
1084
|
-
|
1187
|
+
upb_JsonEncode(msg->msg, msg->msgdef, symtab, options, buf2, size + 1,
|
1188
|
+
&status);
|
1085
1189
|
ret = rb_str_new(buf2, size);
|
1086
1190
|
free(buf2);
|
1087
1191
|
} else {
|
@@ -1104,10 +1208,10 @@ static VALUE Message_descriptor(VALUE klass) {
|
|
1104
1208
|
}
|
1105
1209
|
|
1106
1210
|
VALUE build_class_from_descriptor(VALUE descriptor) {
|
1107
|
-
const char
|
1211
|
+
const char* name;
|
1108
1212
|
VALUE klass;
|
1109
1213
|
|
1110
|
-
name =
|
1214
|
+
name = upb_MessageDef_FullName(Descriptor_GetMsgDef(descriptor));
|
1111
1215
|
if (name == NULL) {
|
1112
1216
|
rb_raise(rb_eRuntimeError, "Descriptor does not have assigned name.");
|
1113
1217
|
}
|
@@ -1115,38 +1219,8 @@ VALUE build_class_from_descriptor(VALUE descriptor) {
|
|
1115
1219
|
klass = rb_define_class_id(
|
1116
1220
|
// Docs say this parameter is ignored. User will assign return value to
|
1117
1221
|
// their own toplevel constant class name.
|
1118
|
-
rb_intern("Message"),
|
1119
|
-
rb_cObject);
|
1222
|
+
rb_intern("Message"), cAbstractMessage);
|
1120
1223
|
rb_ivar_set(klass, descriptor_instancevar_interned, descriptor);
|
1121
|
-
rb_define_alloc_func(klass, Message_alloc);
|
1122
|
-
rb_require("google/protobuf/message_exts");
|
1123
|
-
rb_include_module(klass, rb_eval_string("::Google::Protobuf::MessageExts"));
|
1124
|
-
rb_extend_object(
|
1125
|
-
klass, rb_eval_string("::Google::Protobuf::MessageExts::ClassMethods"));
|
1126
|
-
|
1127
|
-
rb_define_method(klass, "method_missing",
|
1128
|
-
Message_method_missing, -1);
|
1129
|
-
rb_define_method(klass, "respond_to_missing?",
|
1130
|
-
Message_respond_to_missing, -1);
|
1131
|
-
rb_define_method(klass, "initialize", Message_initialize, -1);
|
1132
|
-
rb_define_method(klass, "dup", Message_dup, 0);
|
1133
|
-
// Also define #clone so that we don't inherit Object#clone.
|
1134
|
-
rb_define_method(klass, "clone", Message_dup, 0);
|
1135
|
-
rb_define_method(klass, "==", Message_eq, 1);
|
1136
|
-
rb_define_method(klass, "eql?", Message_eq, 1);
|
1137
|
-
rb_define_method(klass, "freeze", Message_freeze, 0);
|
1138
|
-
rb_define_method(klass, "hash", Message_hash, 0);
|
1139
|
-
rb_define_method(klass, "to_h", Message_to_h, 0);
|
1140
|
-
rb_define_method(klass, "inspect", Message_inspect, 0);
|
1141
|
-
rb_define_method(klass, "to_s", Message_inspect, 0);
|
1142
|
-
rb_define_method(klass, "[]", Message_index, 1);
|
1143
|
-
rb_define_method(klass, "[]=", Message_index_set, 2);
|
1144
|
-
rb_define_singleton_method(klass, "decode", Message_decode, 1);
|
1145
|
-
rb_define_singleton_method(klass, "encode", Message_encode, 1);
|
1146
|
-
rb_define_singleton_method(klass, "decode_json", Message_decode_json, -1);
|
1147
|
-
rb_define_singleton_method(klass, "encode_json", Message_encode_json, -1);
|
1148
|
-
rb_define_singleton_method(klass, "descriptor", Message_descriptor, 0);
|
1149
|
-
|
1150
1224
|
return klass;
|
1151
1225
|
}
|
1152
1226
|
|
@@ -1160,13 +1234,12 @@ VALUE build_class_from_descriptor(VALUE descriptor) {
|
|
1160
1234
|
static VALUE enum_lookup(VALUE self, VALUE number) {
|
1161
1235
|
int32_t num = NUM2INT(number);
|
1162
1236
|
VALUE desc = rb_ivar_get(self, descriptor_instancevar_interned);
|
1163
|
-
const
|
1164
|
-
|
1165
|
-
|
1166
|
-
|
1167
|
-
return Qnil;
|
1237
|
+
const upb_EnumDef* e = EnumDescriptor_GetEnumDef(desc);
|
1238
|
+
const upb_EnumValueDef* ev = upb_EnumDef_FindValueByNumber(e, num);
|
1239
|
+
if (ev) {
|
1240
|
+
return ID2SYM(rb_intern(upb_EnumValueDef_Name(ev)));
|
1168
1241
|
} else {
|
1169
|
-
return
|
1242
|
+
return Qnil;
|
1170
1243
|
}
|
1171
1244
|
}
|
1172
1245
|
|
@@ -1180,14 +1253,12 @@ static VALUE enum_lookup(VALUE self, VALUE number) {
|
|
1180
1253
|
static VALUE enum_resolve(VALUE self, VALUE sym) {
|
1181
1254
|
const char* name = rb_id2name(SYM2ID(sym));
|
1182
1255
|
VALUE desc = rb_ivar_get(self, descriptor_instancevar_interned);
|
1183
|
-
const
|
1184
|
-
|
1185
|
-
|
1186
|
-
|
1187
|
-
if (!found) {
|
1188
|
-
return Qnil;
|
1256
|
+
const upb_EnumDef* e = EnumDescriptor_GetEnumDef(desc);
|
1257
|
+
const upb_EnumValueDef* ev = upb_EnumDef_FindValueByName(e, name);
|
1258
|
+
if (ev) {
|
1259
|
+
return INT2NUM(upb_EnumValueDef_Number(ev));
|
1189
1260
|
} else {
|
1190
|
-
return
|
1261
|
+
return Qnil;
|
1191
1262
|
}
|
1192
1263
|
}
|
1193
1264
|
|
@@ -1203,21 +1274,28 @@ static VALUE enum_descriptor(VALUE self) {
|
|
1203
1274
|
}
|
1204
1275
|
|
1205
1276
|
VALUE build_module_from_enumdesc(VALUE _enumdesc) {
|
1206
|
-
const
|
1207
|
-
VALUE mod = rb_define_module_id(rb_intern(
|
1208
|
-
|
1209
|
-
|
1210
|
-
for (
|
1211
|
-
|
1212
|
-
|
1213
|
-
const char*
|
1214
|
-
|
1277
|
+
const upb_EnumDef* e = EnumDescriptor_GetEnumDef(_enumdesc);
|
1278
|
+
VALUE mod = rb_define_module_id(rb_intern(upb_EnumDef_FullName(e)));
|
1279
|
+
|
1280
|
+
int n = upb_EnumDef_ValueCount(e);
|
1281
|
+
for (int i = 0; i < n; i++) {
|
1282
|
+
const upb_EnumValueDef* ev = upb_EnumDef_Value(e, i);
|
1283
|
+
upb_Arena* arena = upb_Arena_New();
|
1284
|
+
const char* src_name = upb_EnumValueDef_Name(ev);
|
1285
|
+
char* name = upb_strdup2(src_name, strlen(src_name), arena);
|
1286
|
+
int32_t value = upb_EnumValueDef_Number(ev);
|
1215
1287
|
if (name[0] < 'A' || name[0] > 'Z') {
|
1216
|
-
|
1217
|
-
|
1218
|
-
|
1288
|
+
if (name[0] >= 'a' && name[0] <= 'z') {
|
1289
|
+
name[0] -= 32; // auto capitalize
|
1290
|
+
} else {
|
1291
|
+
rb_warn(
|
1292
|
+
"Enum value '%s' does not start with an uppercase letter "
|
1293
|
+
"as is required for Ruby constants.",
|
1294
|
+
name);
|
1295
|
+
}
|
1219
1296
|
}
|
1220
1297
|
rb_define_const(mod, name, INT2NUM(value));
|
1298
|
+
upb_Arena_Free(arena);
|
1221
1299
|
}
|
1222
1300
|
|
1223
1301
|
rb_define_singleton_method(mod, "lookup", enum_lookup, 1);
|
@@ -1228,94 +1306,129 @@ VALUE build_module_from_enumdesc(VALUE _enumdesc) {
|
|
1228
1306
|
return mod;
|
1229
1307
|
}
|
1230
1308
|
|
1231
|
-
// Internal
|
1232
|
-
|
1233
|
-
|
1309
|
+
// Internal to the library; used by Google::Protobuf.deep_copy.
|
1310
|
+
upb_Message* Message_deep_copy(const upb_Message* msg, const upb_MessageDef* m,
|
1311
|
+
upb_Arena* arena) {
|
1234
1312
|
// Serialize and parse.
|
1235
|
-
|
1236
|
-
const
|
1313
|
+
upb_Arena* tmp_arena = upb_Arena_New();
|
1314
|
+
const upb_MiniTable* layout = upb_MessageDef_MiniTable(m);
|
1237
1315
|
size_t size;
|
1238
1316
|
|
1239
|
-
|
1240
|
-
|
1317
|
+
upb_Message* new_msg = upb_Message_New(layout, arena);
|
1318
|
+
char* data;
|
1241
1319
|
|
1242
|
-
if (
|
1243
|
-
|
1320
|
+
if (upb_Encode(msg, layout, 0, tmp_arena, &data, &size) !=
|
1321
|
+
kUpb_EncodeStatus_Ok ||
|
1322
|
+
upb_Decode(data, size, new_msg, layout, NULL, 0, arena) !=
|
1323
|
+
kUpb_DecodeStatus_Ok) {
|
1324
|
+
upb_Arena_Free(tmp_arena);
|
1244
1325
|
rb_raise(cParseError, "Error occurred copying proto");
|
1245
1326
|
}
|
1246
1327
|
|
1247
|
-
|
1328
|
+
upb_Arena_Free(tmp_arena);
|
1248
1329
|
return new_msg;
|
1249
1330
|
}
|
1250
1331
|
|
1251
|
-
const
|
1252
|
-
|
1332
|
+
const upb_Message* Message_GetUpbMessage(VALUE value, const upb_MessageDef* m,
|
1333
|
+
const char* name, upb_Arena* arena) {
|
1253
1334
|
if (value == Qnil) {
|
1254
1335
|
rb_raise(cTypeError, "nil message not allowed here.");
|
1255
1336
|
}
|
1256
1337
|
|
1257
1338
|
VALUE klass = CLASS_OF(value);
|
1258
1339
|
VALUE desc_rb = rb_ivar_get(klass, descriptor_instancevar_interned);
|
1259
|
-
const
|
1340
|
+
const upb_MessageDef* val_m =
|
1260
1341
|
desc_rb == Qnil ? NULL : Descriptor_GetMsgDef(desc_rb);
|
1261
1342
|
|
1262
1343
|
if (val_m != m) {
|
1263
1344
|
// Check for possible implicit conversions
|
1264
1345
|
// TODO: hash conversion?
|
1265
1346
|
|
1266
|
-
switch (
|
1267
|
-
case
|
1347
|
+
switch (upb_MessageDef_WellKnownType(m)) {
|
1348
|
+
case kUpb_WellKnown_Timestamp: {
|
1268
1349
|
// Time -> Google::Protobuf::Timestamp
|
1269
|
-
|
1270
|
-
|
1350
|
+
const upb_MiniTable* t = upb_MessageDef_MiniTable(m);
|
1351
|
+
upb_Message* msg = upb_Message_New(t, arena);
|
1352
|
+
upb_MessageValue sec, nsec;
|
1271
1353
|
struct timespec time;
|
1272
|
-
const
|
1273
|
-
const
|
1354
|
+
const upb_FieldDef* sec_f = upb_MessageDef_FindFieldByNumber(m, 1);
|
1355
|
+
const upb_FieldDef* nsec_f = upb_MessageDef_FindFieldByNumber(m, 2);
|
1274
1356
|
|
1275
1357
|
if (!rb_obj_is_kind_of(value, rb_cTime)) goto badtype;
|
1276
1358
|
|
1277
1359
|
time = rb_time_timespec(value);
|
1278
1360
|
sec.int64_val = time.tv_sec;
|
1279
1361
|
nsec.int32_val = time.tv_nsec;
|
1280
|
-
|
1281
|
-
|
1362
|
+
upb_Message_SetFieldByDef(msg, sec_f, sec, arena);
|
1363
|
+
upb_Message_SetFieldByDef(msg, nsec_f, nsec, arena);
|
1282
1364
|
return msg;
|
1283
1365
|
}
|
1284
|
-
case
|
1366
|
+
case kUpb_WellKnown_Duration: {
|
1285
1367
|
// Numeric -> Google::Protobuf::Duration
|
1286
|
-
|
1287
|
-
|
1288
|
-
|
1289
|
-
const
|
1368
|
+
const upb_MiniTable* t = upb_MessageDef_MiniTable(m);
|
1369
|
+
upb_Message* msg = upb_Message_New(t, arena);
|
1370
|
+
upb_MessageValue sec, nsec;
|
1371
|
+
const upb_FieldDef* sec_f = upb_MessageDef_FindFieldByNumber(m, 1);
|
1372
|
+
const upb_FieldDef* nsec_f = upb_MessageDef_FindFieldByNumber(m, 2);
|
1290
1373
|
|
1291
1374
|
if (!rb_obj_is_kind_of(value, rb_cNumeric)) goto badtype;
|
1292
1375
|
|
1293
1376
|
sec.int64_val = NUM2LL(value);
|
1294
1377
|
nsec.int32_val = round((NUM2DBL(value) - NUM2LL(value)) * 1000000000);
|
1295
|
-
|
1296
|
-
|
1378
|
+
upb_Message_SetFieldByDef(msg, sec_f, sec, arena);
|
1379
|
+
upb_Message_SetFieldByDef(msg, nsec_f, nsec, arena);
|
1297
1380
|
return msg;
|
1298
1381
|
}
|
1299
1382
|
default:
|
1300
1383
|
badtype:
|
1301
1384
|
rb_raise(cTypeError,
|
1302
1385
|
"Invalid type %s to assign to submessage field '%s'.",
|
1303
|
-
|
1386
|
+
rb_class2name(CLASS_OF(value)), name);
|
1304
1387
|
}
|
1305
|
-
|
1306
1388
|
}
|
1307
1389
|
|
1308
1390
|
Message* self = ruby_to_Message(value);
|
1309
|
-
|
1391
|
+
Arena_fuse(self->arena, arena);
|
1310
1392
|
|
1311
1393
|
return self->msg;
|
1312
1394
|
}
|
1313
1395
|
|
1396
|
+
static void Message_define_class(VALUE klass) {
|
1397
|
+
rb_define_alloc_func(klass, Message_alloc);
|
1398
|
+
|
1399
|
+
rb_require("google/protobuf/message_exts");
|
1400
|
+
rb_define_method(klass, "method_missing", Message_method_missing, -1);
|
1401
|
+
rb_define_method(klass, "respond_to_missing?", Message_respond_to_missing,
|
1402
|
+
-1);
|
1403
|
+
rb_define_method(klass, "initialize", Message_initialize, -1);
|
1404
|
+
rb_define_method(klass, "dup", Message_dup, 0);
|
1405
|
+
// Also define #clone so that we don't inherit Object#clone.
|
1406
|
+
rb_define_method(klass, "clone", Message_dup, 0);
|
1407
|
+
rb_define_method(klass, "==", Message_eq, 1);
|
1408
|
+
rb_define_method(klass, "eql?", Message_eq, 1);
|
1409
|
+
rb_define_method(klass, "freeze", Message_freeze, 0);
|
1410
|
+
rb_define_method(klass, "hash", Message_hash, 0);
|
1411
|
+
rb_define_method(klass, "to_h", Message_to_h, 0);
|
1412
|
+
rb_define_method(klass, "inspect", Message_inspect, 0);
|
1413
|
+
rb_define_method(klass, "to_s", Message_inspect, 0);
|
1414
|
+
rb_define_method(klass, "[]", Message_index, 1);
|
1415
|
+
rb_define_method(klass, "[]=", Message_index_set, 2);
|
1416
|
+
rb_define_singleton_method(klass, "decode", Message_decode, -1);
|
1417
|
+
rb_define_singleton_method(klass, "encode", Message_encode, -1);
|
1418
|
+
rb_define_singleton_method(klass, "decode_json", Message_decode_json, -1);
|
1419
|
+
rb_define_singleton_method(klass, "encode_json", Message_encode_json, -1);
|
1420
|
+
rb_define_singleton_method(klass, "descriptor", Message_descriptor, 0);
|
1421
|
+
}
|
1422
|
+
|
1314
1423
|
void Message_register(VALUE protobuf) {
|
1315
1424
|
cParseError = rb_const_get(protobuf, rb_intern("ParseError"));
|
1425
|
+
cAbstractMessage =
|
1426
|
+
rb_define_class_under(protobuf, "AbstractMessage", rb_cObject);
|
1427
|
+
Message_define_class(cAbstractMessage);
|
1428
|
+
rb_gc_register_address(&cAbstractMessage);
|
1316
1429
|
|
1317
1430
|
// Ruby-interned string: "descriptor". We use this identifier to store an
|
1318
1431
|
// instance variable on message classes we create in order to link them back
|
1319
1432
|
// to their descriptors.
|
1320
|
-
descriptor_instancevar_interned = rb_intern("descriptor");
|
1433
|
+
descriptor_instancevar_interned = rb_intern("@descriptor");
|
1321
1434
|
}
|