google-protobuf 3.19.0.rc.1-x86_64-darwin

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of google-protobuf might be problematic. Click here for more details.

Files changed (43) hide show
  1. checksums.yaml +7 -0
  2. data/ext/google/protobuf_c/convert.c +348 -0
  3. data/ext/google/protobuf_c/convert.h +72 -0
  4. data/ext/google/protobuf_c/defs.c +1284 -0
  5. data/ext/google/protobuf_c/defs.h +107 -0
  6. data/ext/google/protobuf_c/extconf.rb +20 -0
  7. data/ext/google/protobuf_c/map.c +694 -0
  8. data/ext/google/protobuf_c/map.h +67 -0
  9. data/ext/google/protobuf_c/message.c +1328 -0
  10. data/ext/google/protobuf_c/message.h +101 -0
  11. data/ext/google/protobuf_c/protobuf.c +470 -0
  12. data/ext/google/protobuf_c/protobuf.h +117 -0
  13. data/ext/google/protobuf_c/repeated_field.c +659 -0
  14. data/ext/google/protobuf_c/repeated_field.h +63 -0
  15. data/ext/google/protobuf_c/ruby-upb.c +9171 -0
  16. data/ext/google/protobuf_c/ruby-upb.h +4704 -0
  17. data/ext/google/protobuf_c/wrap_memcpy.c +51 -0
  18. data/lib/google/2.3/protobuf_c.bundle +0 -0
  19. data/lib/google/2.4/protobuf_c.bundle +0 -0
  20. data/lib/google/2.5/protobuf_c.bundle +0 -0
  21. data/lib/google/2.6/protobuf_c.bundle +0 -0
  22. data/lib/google/2.7/protobuf_c.bundle +0 -0
  23. data/lib/google/3.0/protobuf_c.bundle +0 -0
  24. data/lib/google/protobuf/any_pb.rb +19 -0
  25. data/lib/google/protobuf/api_pb.rb +41 -0
  26. data/lib/google/protobuf/descriptor_dsl.rb +458 -0
  27. data/lib/google/protobuf/descriptor_pb.rb +266 -0
  28. data/lib/google/protobuf/duration_pb.rb +19 -0
  29. data/lib/google/protobuf/empty_pb.rb +17 -0
  30. data/lib/google/protobuf/field_mask_pb.rb +18 -0
  31. data/lib/google/protobuf/message_exts.rb +53 -0
  32. data/lib/google/protobuf/repeated_field.rb +188 -0
  33. data/lib/google/protobuf/source_context_pb.rb +18 -0
  34. data/lib/google/protobuf/struct_pb.rb +37 -0
  35. data/lib/google/protobuf/timestamp_pb.rb +19 -0
  36. data/lib/google/protobuf/type_pb.rb +91 -0
  37. data/lib/google/protobuf/well_known_types.rb +235 -0
  38. data/lib/google/protobuf/wrappers_pb.rb +50 -0
  39. data/lib/google/protobuf.rb +79 -0
  40. data/tests/basic.rb +640 -0
  41. data/tests/generated_code_test.rb +23 -0
  42. data/tests/stress.rb +38 -0
  43. metadata +144 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 06dacd62e4180b65b74e88461b05a249d3a06fabbb125ca88c82b8091e7ed4e0
4
+ data.tar.gz: 75a3574b7230dff4bc66222c0adc09c9e432e54e513e5b96c0372c2886c9dbd2
5
+ SHA512:
6
+ metadata.gz: 64b6bcd828e0dbf9a7b6f53b5a21ce5dd5b99a6707e0790321581794c03291a8fa5ddbfb965144816c087d50a5a8d0c80296f5f09ad74bbe10581d789a67a6ed
7
+ data.tar.gz: 1209f279abb2a1dfe4ed1271bee3bc610c56b3f66a23ef7fe37bb8d66749492eb23e54c6e53844cedb87628e60bf8b477a317654e78feada15e95420ad10d6ad
@@ -0,0 +1,348 @@
1
+ // Protocol Buffers - Google's data interchange format
2
+ // Copyright 2008 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
+ // -----------------------------------------------------------------------------
32
+ // Ruby <-> upb data conversion functions.
33
+ //
34
+ // This file Also contains a few other assorted algorithms on upb_msgval.
35
+ //
36
+ // None of the algorithms in this file require any access to the internal
37
+ // representation of Ruby or upb objects.
38
+ // -----------------------------------------------------------------------------
39
+
40
+ #include "convert.h"
41
+
42
+ #include "message.h"
43
+ #include "protobuf.h"
44
+
45
+ static upb_strview Convert_StringData(VALUE str, upb_arena *arena) {
46
+ upb_strview ret;
47
+ if (arena) {
48
+ char *ptr = upb_arena_malloc(arena, RSTRING_LEN(str));
49
+ memcpy(ptr, RSTRING_PTR(str), RSTRING_LEN(str));
50
+ ret.data = ptr;
51
+ } else {
52
+ // Data is only needed temporarily (within map lookup).
53
+ ret.data = RSTRING_PTR(str);
54
+ }
55
+ ret.size = RSTRING_LEN(str);
56
+ return ret;
57
+ }
58
+
59
+ static bool is_ruby_num(VALUE value) {
60
+ return (TYPE(value) == T_FLOAT ||
61
+ TYPE(value) == T_FIXNUM ||
62
+ TYPE(value) == T_BIGNUM);
63
+ }
64
+
65
+ static void Convert_CheckInt(const char* name, upb_fieldtype_t type,
66
+ VALUE val) {
67
+ if (!is_ruby_num(val)) {
68
+ rb_raise(cTypeError,
69
+ "Expected number type for integral field '%s' (given %s).", name,
70
+ rb_class2name(CLASS_OF(val)));
71
+ }
72
+
73
+ // NUM2{INT,UINT,LL,ULL} macros do the appropriate range checks on upper
74
+ // bound; we just need to do precision checks (i.e., disallow rounding) and
75
+ // check for < 0 on unsigned types.
76
+ if (TYPE(val) == T_FLOAT) {
77
+ double dbl_val = NUM2DBL(val);
78
+ if (floor(dbl_val) != dbl_val) {
79
+ rb_raise(rb_eRangeError,
80
+ "Non-integral floating point value assigned to integer field "
81
+ "'%s' (given %s).",
82
+ name, rb_class2name(CLASS_OF(val)));
83
+ }
84
+ }
85
+ if (type == UPB_TYPE_UINT32 || type == UPB_TYPE_UINT64) {
86
+ if (NUM2DBL(val) < 0) {
87
+ rb_raise(
88
+ rb_eRangeError,
89
+ "Assigning negative value to unsigned integer field '%s' (given %s).",
90
+ name, rb_class2name(CLASS_OF(val)));
91
+ }
92
+ }
93
+ }
94
+
95
+ static int32_t Convert_ToEnum(VALUE value, const char* name,
96
+ const upb_enumdef* e) {
97
+ int32_t val;
98
+
99
+ switch (TYPE(value)) {
100
+ case T_FLOAT:
101
+ case T_FIXNUM:
102
+ case T_BIGNUM:
103
+ Convert_CheckInt(name, UPB_TYPE_INT32, value);
104
+ val = NUM2INT(value);
105
+ break;
106
+ case T_STRING:
107
+ if (!upb_enumdef_ntoi(e, RSTRING_PTR(value), RSTRING_LEN(value), &val)) {
108
+ goto unknownval;
109
+ }
110
+ break;
111
+ case T_SYMBOL:
112
+ if (!upb_enumdef_ntoiz(e, rb_id2name(SYM2ID(value)), &val)) {
113
+ goto unknownval;
114
+ }
115
+ break;
116
+ default:
117
+ rb_raise(cTypeError,
118
+ "Expected number or symbol type for enum field '%s'.", name);
119
+ }
120
+
121
+ return val;
122
+
123
+ unknownval:
124
+ rb_raise(rb_eRangeError, "Unknown symbol value for enum field '%s'.", name);
125
+ }
126
+
127
+ upb_msgval Convert_RubyToUpb(VALUE value, const char* name, TypeInfo type_info,
128
+ upb_arena* arena) {
129
+ upb_msgval ret;
130
+
131
+ switch (type_info.type) {
132
+ case UPB_TYPE_FLOAT:
133
+ if (!is_ruby_num(value)) {
134
+ rb_raise(cTypeError, "Expected number type for float field '%s' (given %s).",
135
+ name, rb_class2name(CLASS_OF(value)));
136
+ }
137
+ ret.float_val = NUM2DBL(value);
138
+ break;
139
+ case UPB_TYPE_DOUBLE:
140
+ if (!is_ruby_num(value)) {
141
+ rb_raise(cTypeError, "Expected number type for double field '%s' (given %s).",
142
+ name, rb_class2name(CLASS_OF(value)));
143
+ }
144
+ ret.double_val = NUM2DBL(value);
145
+ break;
146
+ case UPB_TYPE_BOOL: {
147
+ if (value == Qtrue) {
148
+ ret.bool_val = 1;
149
+ } else if (value == Qfalse) {
150
+ ret.bool_val = 0;
151
+ } else {
152
+ rb_raise(cTypeError, "Invalid argument for boolean field '%s' (given %s).",
153
+ name, rb_class2name(CLASS_OF(value)));
154
+ }
155
+ break;
156
+ }
157
+ case UPB_TYPE_STRING: {
158
+ VALUE utf8 = rb_enc_from_encoding(rb_utf8_encoding());
159
+ if (CLASS_OF(value) == rb_cSymbol) {
160
+ value = rb_funcall(value, rb_intern("to_s"), 0);
161
+ } else if (CLASS_OF(value) != rb_cString) {
162
+ rb_raise(cTypeError, "Invalid argument for string field '%s' (given %s).",
163
+ name, rb_class2name(CLASS_OF(value)));
164
+ }
165
+
166
+ if (rb_obj_encoding(value) != utf8) {
167
+ // Note: this will not duplicate underlying string data unless necessary.
168
+ value = rb_str_encode(value, utf8, 0, Qnil);
169
+
170
+ if (rb_enc_str_coderange(value) == ENC_CODERANGE_BROKEN) {
171
+ rb_raise(rb_eEncodingError, "String is invalid UTF-8");
172
+ }
173
+ }
174
+
175
+ ret.str_val = Convert_StringData(value, arena);
176
+ break;
177
+ }
178
+ case UPB_TYPE_BYTES: {
179
+ VALUE bytes = rb_enc_from_encoding(rb_ascii8bit_encoding());
180
+ if (CLASS_OF(value) != rb_cString) {
181
+ rb_raise(cTypeError, "Invalid argument for bytes field '%s' (given %s).",
182
+ name, rb_class2name(CLASS_OF(value)));
183
+ }
184
+
185
+ if (rb_obj_encoding(value) != bytes) {
186
+ // Note: this will not duplicate underlying string data unless necessary.
187
+ // TODO(haberman): is this really necessary to get raw bytes?
188
+ value = rb_str_encode(value, bytes, 0, Qnil);
189
+ }
190
+
191
+ ret.str_val = Convert_StringData(value, arena);
192
+ break;
193
+ }
194
+ case UPB_TYPE_MESSAGE:
195
+ ret.msg_val =
196
+ Message_GetUpbMessage(value, type_info.def.msgdef, name, arena);
197
+ break;
198
+ case UPB_TYPE_ENUM:
199
+ ret.int32_val = Convert_ToEnum(value, name, type_info.def.enumdef);
200
+ break;
201
+ case UPB_TYPE_INT32:
202
+ case UPB_TYPE_INT64:
203
+ case UPB_TYPE_UINT32:
204
+ case UPB_TYPE_UINT64:
205
+ Convert_CheckInt(name, type_info.type, value);
206
+ switch (type_info.type) {
207
+ case UPB_TYPE_INT32:
208
+ ret.int32_val = NUM2INT(value);
209
+ break;
210
+ case UPB_TYPE_INT64:
211
+ ret.int64_val = NUM2LL(value);
212
+ break;
213
+ case UPB_TYPE_UINT32:
214
+ ret.uint32_val = NUM2UINT(value);
215
+ break;
216
+ case UPB_TYPE_UINT64:
217
+ ret.uint64_val = NUM2ULL(value);
218
+ break;
219
+ default:
220
+ break;
221
+ }
222
+ break;
223
+ default:
224
+ break;
225
+ }
226
+
227
+ return ret;
228
+ }
229
+
230
+ VALUE Convert_UpbToRuby(upb_msgval upb_val, TypeInfo type_info, VALUE arena) {
231
+ switch (type_info.type) {
232
+ case UPB_TYPE_FLOAT:
233
+ return DBL2NUM(upb_val.float_val);
234
+ case UPB_TYPE_DOUBLE:
235
+ return DBL2NUM(upb_val.double_val);
236
+ case UPB_TYPE_BOOL:
237
+ return upb_val.bool_val ? Qtrue : Qfalse;
238
+ case UPB_TYPE_INT32:
239
+ return INT2NUM(upb_val.int32_val);
240
+ case UPB_TYPE_INT64:
241
+ return LL2NUM(upb_val.int64_val);
242
+ case UPB_TYPE_UINT32:
243
+ return UINT2NUM(upb_val.uint32_val);
244
+ case UPB_TYPE_UINT64:
245
+ return ULL2NUM(upb_val.int64_val);
246
+ case UPB_TYPE_ENUM: {
247
+ const char* name =
248
+ upb_enumdef_iton(type_info.def.enumdef, upb_val.int32_val);
249
+ if (name) {
250
+ return ID2SYM(rb_intern(name));
251
+ } else {
252
+ return INT2NUM(upb_val.int32_val);
253
+ }
254
+ }
255
+ case UPB_TYPE_STRING: {
256
+ VALUE str_rb = rb_str_new(upb_val.str_val.data, upb_val.str_val.size);
257
+ rb_enc_associate(str_rb, rb_utf8_encoding());
258
+ rb_obj_freeze(str_rb);
259
+ return str_rb;
260
+ }
261
+ case UPB_TYPE_BYTES: {
262
+ VALUE str_rb = rb_str_new(upb_val.str_val.data, upb_val.str_val.size);
263
+ rb_enc_associate(str_rb, rb_ascii8bit_encoding());
264
+ rb_obj_freeze(str_rb);
265
+ return str_rb;
266
+ }
267
+ case UPB_TYPE_MESSAGE:
268
+ return Message_GetRubyWrapper((upb_msg*)upb_val.msg_val,
269
+ type_info.def.msgdef, arena);
270
+ default:
271
+ rb_raise(rb_eRuntimeError, "Convert_UpbToRuby(): Unexpected type %d",
272
+ (int)type_info.type);
273
+ }
274
+ }
275
+
276
+ upb_msgval Msgval_DeepCopy(upb_msgval msgval, TypeInfo type_info,
277
+ upb_arena* arena) {
278
+ upb_msgval new_msgval;
279
+
280
+ switch (type_info.type) {
281
+ default:
282
+ memcpy(&new_msgval, &msgval, sizeof(msgval));
283
+ break;
284
+ case UPB_TYPE_STRING:
285
+ case UPB_TYPE_BYTES: {
286
+ size_t n = msgval.str_val.size;
287
+ char *mem = upb_arena_malloc(arena, n);
288
+ new_msgval.str_val.data = mem;
289
+ new_msgval.str_val.size = n;
290
+ memcpy(mem, msgval.str_val.data, n);
291
+ break;
292
+ }
293
+ case UPB_TYPE_MESSAGE:
294
+ new_msgval.msg_val =
295
+ Message_deep_copy(msgval.msg_val, type_info.def.msgdef, arena);
296
+ break;
297
+ }
298
+
299
+ return new_msgval;
300
+ }
301
+
302
+ bool Msgval_IsEqual(upb_msgval val1, upb_msgval val2, TypeInfo type_info) {
303
+ switch (type_info.type) {
304
+ case UPB_TYPE_BOOL:
305
+ return memcmp(&val1, &val2, 1) == 0;
306
+ case UPB_TYPE_FLOAT:
307
+ case UPB_TYPE_INT32:
308
+ case UPB_TYPE_UINT32:
309
+ case UPB_TYPE_ENUM:
310
+ return memcmp(&val1, &val2, 4) == 0;
311
+ case UPB_TYPE_DOUBLE:
312
+ case UPB_TYPE_INT64:
313
+ case UPB_TYPE_UINT64:
314
+ return memcmp(&val1, &val2, 8) == 0;
315
+ case UPB_TYPE_STRING:
316
+ case UPB_TYPE_BYTES:
317
+ return val1.str_val.size == val2.str_val.size &&
318
+ memcmp(val1.str_val.data, val2.str_val.data,
319
+ val1.str_val.size) == 0;
320
+ case UPB_TYPE_MESSAGE:
321
+ return Message_Equal(val1.msg_val, val2.msg_val, type_info.def.msgdef);
322
+ default:
323
+ rb_raise(rb_eRuntimeError, "Internal error, unexpected type");
324
+ }
325
+ }
326
+
327
+ uint64_t Msgval_GetHash(upb_msgval val, TypeInfo type_info, uint64_t seed) {
328
+ switch (type_info.type) {
329
+ case UPB_TYPE_BOOL:
330
+ return Wyhash(&val, 1, seed, kWyhashSalt);
331
+ case UPB_TYPE_FLOAT:
332
+ case UPB_TYPE_INT32:
333
+ case UPB_TYPE_UINT32:
334
+ case UPB_TYPE_ENUM:
335
+ return Wyhash(&val, 4, seed, kWyhashSalt);
336
+ case UPB_TYPE_DOUBLE:
337
+ case UPB_TYPE_INT64:
338
+ case UPB_TYPE_UINT64:
339
+ return Wyhash(&val, 8, seed, kWyhashSalt);
340
+ case UPB_TYPE_STRING:
341
+ case UPB_TYPE_BYTES:
342
+ return Wyhash(val.str_val.data, val.str_val.size, seed, kWyhashSalt);
343
+ case UPB_TYPE_MESSAGE:
344
+ return Message_Hash(val.msg_val, type_info.def.msgdef, seed);
345
+ default:
346
+ rb_raise(rb_eRuntimeError, "Internal error, unexpected type");
347
+ }
348
+ }
@@ -0,0 +1,72 @@
1
+ // Protocol Buffers - Google's data interchange format
2
+ // Copyright 2008 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
+ #ifndef RUBY_PROTOBUF_CONVERT_H_
32
+ #define RUBY_PROTOBUF_CONVERT_H_
33
+
34
+ #include <ruby/ruby.h>
35
+
36
+ #include "protobuf.h"
37
+ #include "ruby-upb.h"
38
+
39
+ // Converts |ruby_val| to a upb_msgval according to |type_info|.
40
+ //
41
+ // The |arena| parameter indicates the lifetime of the container where this
42
+ // value will be assigned. It is used as follows:
43
+ // - If type is string or bytes, the string data will be copied into |arena|.
44
+ // - If type is message, and we need to auto-construct a message due to implicit
45
+ // conversions (eg. Time -> Google::Protobuf::Timestamp), the new message
46
+ // will be created in |arena|.
47
+ // - If type is message and the Ruby value is a message instance, we will fuse
48
+ // the message's arena into |arena|, to ensure that this message outlives the
49
+ // container.
50
+ upb_msgval Convert_RubyToUpb(VALUE ruby_val, const char *name,
51
+ TypeInfo type_info, upb_arena *arena);
52
+
53
+ // Converts |upb_val| to a Ruby VALUE according to |type_info|. This may involve
54
+ // creating a Ruby wrapper object.
55
+ //
56
+ // The |arena| parameter indicates the arena that owns the lifetime of
57
+ // |upb_val|. Any Ruby wrapper object that is created will reference |arena|
58
+ // and ensure it outlives the wrapper.
59
+ VALUE Convert_UpbToRuby(upb_msgval upb_val, TypeInfo type_info, VALUE arena);
60
+
61
+ // Creates a deep copy of |msgval| in |arena|.
62
+ upb_msgval Msgval_DeepCopy(upb_msgval msgval, TypeInfo type_info,
63
+ upb_arena *arena);
64
+
65
+ // Returns true if |val1| and |val2| are equal. Their type is given by
66
+ // |type_info|.
67
+ bool Msgval_IsEqual(upb_msgval val1, upb_msgval val2, TypeInfo type_info);
68
+
69
+ // Returns a hash value for the given upb_msgval.
70
+ uint64_t Msgval_GetHash(upb_msgval val, TypeInfo type_info, uint64_t seed);
71
+
72
+ #endif // RUBY_PROTOBUF_CONVERT_H_