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