google-protobuf 3.0.0.alpha.1.0

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.

@@ -0,0 +1,10 @@
1
+ #!/usr/bin/ruby
2
+
3
+ require 'mkmf'
4
+
5
+ $CFLAGS += " -O3 -std=c99 -Wno-unused-function -DNDEBUG "
6
+
7
+ $objs = ["protobuf.o", "defs.o", "storage.o", "message.o",
8
+ "repeated_field.o", "encode_decode.o", "upb.o"]
9
+
10
+ create_makefile("google/protobuf_c")
@@ -0,0 +1,463 @@
1
+ // Protocol Buffers - Google's data interchange format
2
+ // Copyright 2014 Google Inc. All rights reserved.
3
+ // https://developers.google.com/protocol-buffers/
4
+ //
5
+ // Redistribution and use in source and binary forms, with or without
6
+ // modification, are permitted provided that the following conditions are
7
+ // met:
8
+ //
9
+ // * Redistributions of source code must retain the above copyright
10
+ // notice, this list of conditions and the following disclaimer.
11
+ // * Redistributions in binary form must reproduce the above
12
+ // copyright notice, this list of conditions and the following disclaimer
13
+ // in the documentation and/or other materials provided with the
14
+ // distribution.
15
+ // * Neither the name of Google Inc. nor the names of its
16
+ // contributors may be used to endorse or promote products derived from
17
+ // this software without specific prior written permission.
18
+ //
19
+ // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20
+ // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21
+ // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22
+ // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23
+ // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24
+ // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25
+ // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26
+ // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27
+ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28
+ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29
+ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
+
31
+ #include "protobuf.h"
32
+
33
+ // -----------------------------------------------------------------------------
34
+ // Class/module creation from msgdefs and enumdefs, respectively.
35
+ // -----------------------------------------------------------------------------
36
+
37
+ void* Message_data(void* msg) {
38
+ return ((uint8_t *)msg) + sizeof(MessageHeader);
39
+ }
40
+
41
+ void Message_mark(void* _self) {
42
+ MessageHeader* self = (MessageHeader *)_self;
43
+ layout_mark(self->descriptor->layout, Message_data(self));
44
+ }
45
+
46
+ void Message_free(void* self) {
47
+ xfree(self);
48
+ }
49
+
50
+ rb_data_type_t Message_type = {
51
+ "Message",
52
+ { Message_mark, Message_free, NULL },
53
+ };
54
+
55
+ VALUE Message_alloc(VALUE klass) {
56
+ VALUE descriptor = rb_iv_get(klass, kDescriptorInstanceVar);
57
+ Descriptor* desc = ruby_to_Descriptor(descriptor);
58
+ MessageHeader* msg = (MessageHeader*)ALLOC_N(
59
+ uint8_t, sizeof(MessageHeader) + desc->layout->size);
60
+ memset(Message_data(msg), 0, desc->layout->size);
61
+
62
+ // We wrap first so that everything in the message object is GC-rooted in case
63
+ // a collection happens during object creation in layout_init().
64
+ VALUE ret = TypedData_Wrap_Struct(klass, &Message_type, msg);
65
+ msg->descriptor = desc;
66
+ rb_iv_set(ret, kDescriptorInstanceVar, descriptor);
67
+
68
+ layout_init(desc->layout, Message_data(msg));
69
+
70
+ return ret;
71
+ }
72
+
73
+ /*
74
+ * call-seq:
75
+ * Message.method_missing(*args)
76
+ *
77
+ * Provides accessors and setters for message fields according to their field
78
+ * names. For any field whose name does not conflict with a built-in method, an
79
+ * accessor is provided with the same name as the field, and a setter is
80
+ * provided with the name of the field plus the '=' suffix. Thus, given a
81
+ * message instance 'msg' with field 'foo', the following code is valid:
82
+ *
83
+ * msg.foo = 42
84
+ * puts msg.foo
85
+ */
86
+ VALUE Message_method_missing(int argc, VALUE* argv, VALUE _self) {
87
+ MessageHeader* self;
88
+ TypedData_Get_Struct(_self, MessageHeader, &Message_type, self);
89
+ if (argc < 1) {
90
+ rb_raise(rb_eArgError, "Expected method name as first argument.");
91
+ }
92
+ VALUE method_name = argv[0];
93
+ if (!SYMBOL_P(method_name)) {
94
+ rb_raise(rb_eArgError, "Expected symbol as method name.");
95
+ }
96
+ VALUE method_str = rb_id2str(SYM2ID(method_name));
97
+ char* name = RSTRING_PTR(method_str);
98
+ size_t name_len = RSTRING_LEN(method_str);
99
+ bool setter = false;
100
+
101
+ // Setters have names that end in '='.
102
+ if (name[name_len - 1] == '=') {
103
+ setter = true;
104
+ name_len--;
105
+ }
106
+
107
+ const upb_fielddef* f = upb_msgdef_ntof(self->descriptor->msgdef,
108
+ name, name_len);
109
+
110
+ if (f == NULL) {
111
+ rb_raise(rb_eArgError, "Unknown field");
112
+ }
113
+
114
+ if (setter) {
115
+ if (argc < 2) {
116
+ rb_raise(rb_eArgError, "No value provided to setter.");
117
+ }
118
+ layout_set(self->descriptor->layout, Message_data(self), f, argv[1]);
119
+ return Qnil;
120
+ } else {
121
+ return layout_get(self->descriptor->layout, Message_data(self), f);
122
+ }
123
+ }
124
+
125
+ int Message_initialize_kwarg(VALUE key, VALUE val, VALUE _self) {
126
+ MessageHeader* self;
127
+ TypedData_Get_Struct(_self, MessageHeader, &Message_type, self);
128
+
129
+ if (!SYMBOL_P(key)) {
130
+ rb_raise(rb_eArgError,
131
+ "Expected symbols as hash keys in initialization map.");
132
+ }
133
+
134
+ VALUE method_str = rb_id2str(SYM2ID(key));
135
+ char* name = RSTRING_PTR(method_str);
136
+ const upb_fielddef* f = upb_msgdef_ntofz(self->descriptor->msgdef, name);
137
+ if (f == NULL) {
138
+ rb_raise(rb_eArgError,
139
+ "Unknown field name in initialization map entry.");
140
+ }
141
+
142
+ if (upb_fielddef_label(f) == UPB_LABEL_REPEATED) {
143
+ if (TYPE(val) != T_ARRAY) {
144
+ rb_raise(rb_eArgError,
145
+ "Expected array as initializer value for repeated field.");
146
+ }
147
+ VALUE ary = layout_get(self->descriptor->layout, Message_data(self), f);
148
+ for (int i = 0; i < RARRAY_LEN(val); i++) {
149
+ RepeatedField_push(ary, rb_ary_entry(val, i));
150
+ }
151
+ } else {
152
+ layout_set(self->descriptor->layout, Message_data(self), f, val);
153
+ }
154
+ return 0;
155
+ }
156
+
157
+ /*
158
+ * call-seq:
159
+ * Message.new(kwargs) => new_message
160
+ *
161
+ * Creates a new instance of the given message class. Keyword arguments may be
162
+ * provided with keywords corresponding to field names.
163
+ *
164
+ * Note that no literal Message class exists. Only concrete classes per message
165
+ * type exist, as provided by the #msgclass method on Descriptors after they
166
+ * have been added to a pool. The method definitions described here on the
167
+ * Message class are provided on each concrete message class.
168
+ */
169
+ VALUE Message_initialize(int argc, VALUE* argv, VALUE _self) {
170
+ if (argc == 0) {
171
+ return Qnil;
172
+ }
173
+ if (argc != 1) {
174
+ rb_raise(rb_eArgError, "Expected 0 or 1 arguments.");
175
+ }
176
+ VALUE hash_args = argv[0];
177
+ if (TYPE(hash_args) != T_HASH) {
178
+ rb_raise(rb_eArgError, "Expected hash arguments.");
179
+ }
180
+
181
+ rb_hash_foreach(hash_args, Message_initialize_kwarg, _self);
182
+ return Qnil;
183
+ }
184
+
185
+ /*
186
+ * call-seq:
187
+ * Message.dup => new_message
188
+ *
189
+ * Performs a shallow copy of this message and returns the new copy.
190
+ */
191
+ VALUE Message_dup(VALUE _self) {
192
+ MessageHeader* self;
193
+ TypedData_Get_Struct(_self, MessageHeader, &Message_type, self);
194
+
195
+ VALUE new_msg = rb_class_new_instance(0, NULL, CLASS_OF(_self));
196
+ MessageHeader* new_msg_self;
197
+ TypedData_Get_Struct(new_msg, MessageHeader, &Message_type, new_msg_self);
198
+
199
+ layout_dup(self->descriptor->layout,
200
+ Message_data(new_msg_self),
201
+ Message_data(self));
202
+
203
+ return new_msg;
204
+ }
205
+
206
+ // Internal only; used by Google::Protobuf.deep_copy.
207
+ VALUE Message_deep_copy(VALUE _self) {
208
+ MessageHeader* self;
209
+ TypedData_Get_Struct(_self, MessageHeader, &Message_type, self);
210
+
211
+ VALUE new_msg = rb_class_new_instance(0, NULL, CLASS_OF(_self));
212
+ MessageHeader* new_msg_self;
213
+ TypedData_Get_Struct(new_msg, MessageHeader, &Message_type, new_msg_self);
214
+
215
+ layout_deep_copy(self->descriptor->layout,
216
+ Message_data(new_msg_self),
217
+ Message_data(self));
218
+
219
+ return new_msg;
220
+ }
221
+
222
+ /*
223
+ * call-seq:
224
+ * Message.==(other) => boolean
225
+ *
226
+ * Performs a deep comparison of this message with another. Messages are equal
227
+ * if they have the same type and if each field is equal according to the :==
228
+ * method's semantics (a more efficient comparison may actually be done if the
229
+ * field is of a primitive type).
230
+ */
231
+ VALUE Message_eq(VALUE _self, VALUE _other) {
232
+ MessageHeader* self;
233
+ TypedData_Get_Struct(_self, MessageHeader, &Message_type, self);
234
+
235
+ MessageHeader* other;
236
+ TypedData_Get_Struct(_other, MessageHeader, &Message_type, other);
237
+
238
+ if (self->descriptor != other->descriptor) {
239
+ return Qfalse;
240
+ }
241
+
242
+ return layout_eq(self->descriptor->layout,
243
+ Message_data(self),
244
+ Message_data(other));
245
+ }
246
+
247
+ /*
248
+ * call-seq:
249
+ * Message.hash => hash_value
250
+ *
251
+ * Returns a hash value that represents this message's field values.
252
+ */
253
+ VALUE Message_hash(VALUE _self) {
254
+ MessageHeader* self;
255
+ TypedData_Get_Struct(_self, MessageHeader, &Message_type, self);
256
+
257
+ return layout_hash(self->descriptor->layout, Message_data(self));
258
+ }
259
+
260
+ /*
261
+ * call-seq:
262
+ * Message.inspect => string
263
+ *
264
+ * Returns a human-readable string representing this message. It will be
265
+ * formatted as "<MessageType: field1: value1, field2: value2, ...>". Each
266
+ * field's value is represented according to its own #inspect method.
267
+ */
268
+ VALUE Message_inspect(VALUE _self) {
269
+ MessageHeader* self;
270
+ TypedData_Get_Struct(_self, MessageHeader, &Message_type, self);
271
+
272
+ VALUE str = rb_str_new2("<");
273
+ str = rb_str_append(str, rb_str_new2(rb_class2name(CLASS_OF(_self))));
274
+ str = rb_str_cat2(str, ": ");
275
+ str = rb_str_append(str, layout_inspect(
276
+ self->descriptor->layout, Message_data(self)));
277
+ str = rb_str_cat2(str, ">");
278
+ return str;
279
+ }
280
+
281
+ /*
282
+ * call-seq:
283
+ * Message.[](index) => value
284
+ *
285
+ * Accesses a field's value by field name. The provided field name should be a
286
+ * string.
287
+ */
288
+ VALUE Message_index(VALUE _self, VALUE field_name) {
289
+ MessageHeader* self;
290
+ TypedData_Get_Struct(_self, MessageHeader, &Message_type, self);
291
+ Check_Type(field_name, T_STRING);
292
+ const upb_fielddef* field =
293
+ upb_msgdef_ntofz(self->descriptor->msgdef, RSTRING_PTR(field_name));
294
+ if (field == NULL) {
295
+ return Qnil;
296
+ }
297
+ return layout_get(self->descriptor->layout, Message_data(self), field);
298
+ }
299
+
300
+ /*
301
+ * call-seq:
302
+ * Message.[]=(index, value)
303
+ *
304
+ * Sets a field's value by field name. The provided field name should be a
305
+ * string.
306
+ */
307
+ VALUE Message_index_set(VALUE _self, VALUE field_name, VALUE value) {
308
+ MessageHeader* self;
309
+ TypedData_Get_Struct(_self, MessageHeader, &Message_type, self);
310
+ Check_Type(field_name, T_STRING);
311
+ const upb_fielddef* field =
312
+ upb_msgdef_ntofz(self->descriptor->msgdef, RSTRING_PTR(field_name));
313
+ if (field == NULL) {
314
+ rb_raise(rb_eArgError, "Unknown field: %s", RSTRING_PTR(field_name));
315
+ }
316
+ layout_set(self->descriptor->layout, Message_data(self), field, value);
317
+ return Qnil;
318
+ }
319
+
320
+ /*
321
+ * call-seq:
322
+ * Message.descriptor => descriptor
323
+ *
324
+ * Class method that returns the Descriptor instance corresponding to this
325
+ * message class's type.
326
+ */
327
+ VALUE Message_descriptor(VALUE klass) {
328
+ return rb_iv_get(klass, kDescriptorInstanceVar);
329
+ }
330
+
331
+ VALUE build_class_from_descriptor(Descriptor* desc) {
332
+ if (desc->layout == NULL) {
333
+ desc->layout = create_layout(desc->msgdef);
334
+ }
335
+ if (desc->fill_method == NULL) {
336
+ desc->fill_method = new_fillmsg_decodermethod(desc, &desc->fill_method);
337
+ }
338
+
339
+ const char* name = upb_msgdef_fullname(desc->msgdef);
340
+ if (name == NULL) {
341
+ rb_raise(rb_eRuntimeError, "Descriptor does not have assigned name.");
342
+ }
343
+
344
+ VALUE klass = rb_define_class_id(
345
+ // Docs say this parameter is ignored. User will assign return value to
346
+ // their own toplevel constant class name.
347
+ rb_intern("Message"),
348
+ rb_cObject);
349
+ rb_iv_set(klass, kDescriptorInstanceVar, get_def_obj(desc->msgdef));
350
+ rb_define_alloc_func(klass, Message_alloc);
351
+ rb_define_method(klass, "method_missing",
352
+ Message_method_missing, -1);
353
+ rb_define_method(klass, "initialize", Message_initialize, -1);
354
+ rb_define_method(klass, "dup", Message_dup, 0);
355
+ // Also define #clone so that we don't inherit Object#clone.
356
+ rb_define_method(klass, "clone", Message_dup, 0);
357
+ rb_define_method(klass, "==", Message_eq, 1);
358
+ rb_define_method(klass, "hash", Message_hash, 0);
359
+ rb_define_method(klass, "inspect", Message_inspect, 0);
360
+ rb_define_method(klass, "[]", Message_index, 1);
361
+ rb_define_method(klass, "[]=", Message_index_set, 2);
362
+ rb_define_singleton_method(klass, "decode", Message_decode, 1);
363
+ rb_define_singleton_method(klass, "encode", Message_encode, 1);
364
+ rb_define_singleton_method(klass, "decode_json", Message_decode_json, 1);
365
+ rb_define_singleton_method(klass, "encode_json", Message_encode_json, 1);
366
+ rb_define_singleton_method(klass, "descriptor", Message_descriptor, 0);
367
+ return klass;
368
+ }
369
+
370
+ /*
371
+ * call-seq:
372
+ * Enum.lookup(number) => name
373
+ *
374
+ * This module method, provided on each generated enum module, looks up an enum
375
+ * value by number and returns its name as a Ruby symbol, or nil if not found.
376
+ */
377
+ VALUE enum_lookup(VALUE self, VALUE number) {
378
+ int32_t num = NUM2INT(number);
379
+ VALUE desc = rb_iv_get(self, kDescriptorInstanceVar);
380
+ EnumDescriptor* enumdesc = ruby_to_EnumDescriptor(desc);
381
+
382
+ const char* name = upb_enumdef_iton(enumdesc->enumdef, num);
383
+ if (name == NULL) {
384
+ return Qnil;
385
+ } else {
386
+ return ID2SYM(rb_intern(name));
387
+ }
388
+ }
389
+
390
+ /*
391
+ * call-seq:
392
+ * Enum.resolve(name) => number
393
+ *
394
+ * This module method, provided on each generated enum module, looks up an enum
395
+ * value by name (as a Ruby symbol) and returns its name, or nil if not found.
396
+ */
397
+ VALUE enum_resolve(VALUE self, VALUE sym) {
398
+ const char* name = rb_id2name(SYM2ID(sym));
399
+ VALUE desc = rb_iv_get(self, kDescriptorInstanceVar);
400
+ EnumDescriptor* enumdesc = ruby_to_EnumDescriptor(desc);
401
+
402
+ int32_t num = 0;
403
+ bool found = upb_enumdef_ntoiz(enumdesc->enumdef, name, &num);
404
+ if (!found) {
405
+ return Qnil;
406
+ } else {
407
+ return INT2NUM(num);
408
+ }
409
+ }
410
+
411
+ /*
412
+ * call-seq:
413
+ * Enum.descriptor
414
+ *
415
+ * This module method, provided on each generated enum module, returns the
416
+ * EnumDescriptor corresponding to this enum type.
417
+ */
418
+ VALUE enum_descriptor(VALUE self) {
419
+ return rb_iv_get(self, kDescriptorInstanceVar);
420
+ }
421
+
422
+ VALUE build_module_from_enumdesc(EnumDescriptor* enumdesc) {
423
+ VALUE mod = rb_define_module_id(
424
+ rb_intern(upb_enumdef_fullname(enumdesc->enumdef)));
425
+
426
+ upb_enum_iter it;
427
+ for (upb_enum_begin(&it, enumdesc->enumdef);
428
+ !upb_enum_done(&it);
429
+ upb_enum_next(&it)) {
430
+ const char* name = upb_enum_iter_name(&it);
431
+ int32_t value = upb_enum_iter_number(&it);
432
+ if (name[0] < 'A' || name[0] > 'Z') {
433
+ rb_raise(rb_eTypeError,
434
+ "Enum value '%s' does not start with an uppercase letter "
435
+ "as is required for Ruby constants.",
436
+ name);
437
+ }
438
+ rb_define_const(mod, name, INT2NUM(value));
439
+ }
440
+
441
+ rb_define_singleton_method(mod, "lookup", enum_lookup, 1);
442
+ rb_define_singleton_method(mod, "resolve", enum_resolve, 1);
443
+ rb_define_singleton_method(mod, "descriptor", enum_descriptor, 0);
444
+ rb_iv_set(mod, kDescriptorInstanceVar, get_def_obj(enumdesc->enumdef));
445
+
446
+ return mod;
447
+ }
448
+
449
+ /*
450
+ * call-seq:
451
+ * Google::Protobuf.deep_copy(obj) => copy_of_obj
452
+ *
453
+ * Performs a deep copy of either a RepeatedField instance or a message object,
454
+ * recursively copying its members.
455
+ */
456
+ VALUE Google_Protobuf_deep_copy(VALUE self, VALUE obj) {
457
+ VALUE klass = CLASS_OF(obj);
458
+ if (klass == cRepeatedField) {
459
+ return RepeatedField_deep_copy(obj);
460
+ } else {
461
+ return Message_deep_copy(obj);
462
+ }
463
+ }