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