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