google-protobuf 3.19.1 → 3.25.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of google-protobuf might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/ext/google/protobuf_c/Rakefile +3 -0
- data/ext/google/protobuf_c/convert.c +121 -155
- data/ext/google/protobuf_c/convert.h +15 -37
- data/ext/google/protobuf_c/defs.c +362 -243
- data/ext/google/protobuf_c/defs.h +22 -47
- data/ext/google/protobuf_c/extconf.rb +13 -5
- data/ext/google/protobuf_c/glue.c +56 -0
- data/ext/google/protobuf_c/map.c +129 -137
- data/ext/google/protobuf_c/map.h +13 -36
- data/ext/google/protobuf_c/message.c +486 -389
- data/ext/google/protobuf_c/message.h +32 -47
- data/ext/google/protobuf_c/protobuf.c +101 -228
- data/ext/google/protobuf_c/protobuf.h +37 -42
- data/ext/google/protobuf_c/repeated_field.c +110 -113
- data/ext/google/protobuf_c/repeated_field.h +12 -34
- data/ext/google/protobuf_c/ruby-upb.c +12236 -6993
- data/ext/google/protobuf_c/ruby-upb.h +12127 -3787
- data/ext/google/protobuf_c/shared_convert.c +64 -0
- data/ext/google/protobuf_c/shared_convert.h +26 -0
- data/ext/google/protobuf_c/shared_message.c +65 -0
- data/ext/google/protobuf_c/shared_message.h +25 -0
- 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 +7 -29
- data/lib/google/protobuf/any_pb.rb +24 -5
- data/lib/google/protobuf/api_pb.rb +26 -23
- data/lib/google/protobuf/descriptor_dsl.rb +8 -1
- data/lib/google/protobuf/descriptor_pb.rb +43 -225
- data/lib/google/protobuf/duration_pb.rb +24 -5
- data/lib/google/protobuf/empty_pb.rb +24 -3
- data/lib/google/protobuf/ffi/descriptor.rb +165 -0
- data/lib/google/protobuf/ffi/descriptor_pool.rb +75 -0
- data/lib/google/protobuf/ffi/enum_descriptor.rb +171 -0
- data/lib/google/protobuf/ffi/ffi.rb +213 -0
- data/lib/google/protobuf/ffi/field_descriptor.rb +319 -0
- data/lib/google/protobuf/ffi/file_descriptor.rb +59 -0
- data/lib/google/protobuf/ffi/internal/arena.rb +66 -0
- data/lib/google/protobuf/ffi/internal/convert.rb +305 -0
- data/lib/google/protobuf/ffi/internal/pointer_helper.rb +35 -0
- data/lib/google/protobuf/ffi/internal/type_safety.rb +25 -0
- data/lib/google/protobuf/ffi/map.rb +407 -0
- data/lib/google/protobuf/ffi/message.rb +662 -0
- data/lib/google/protobuf/ffi/object_cache.rb +30 -0
- data/lib/google/protobuf/ffi/oneof_descriptor.rb +95 -0
- data/lib/google/protobuf/ffi/repeated_field.rb +383 -0
- data/lib/google/protobuf/field_mask_pb.rb +24 -4
- data/lib/google/protobuf/message_exts.rb +10 -28
- data/lib/google/protobuf/object_cache.rb +97 -0
- data/lib/google/protobuf/plugin_pb.rb +47 -0
- data/lib/google/protobuf/repeated_field.rb +18 -28
- data/lib/google/protobuf/source_context_pb.rb +24 -4
- data/lib/google/protobuf/struct_pb.rb +24 -20
- data/lib/google/protobuf/timestamp_pb.rb +24 -5
- data/lib/google/protobuf/type_pb.rb +26 -68
- data/lib/google/protobuf/well_known_types.rb +16 -40
- data/lib/google/protobuf/wrappers_pb.rb +24 -28
- data/lib/google/protobuf.rb +32 -50
- data/lib/google/protobuf_ffi.rb +50 -0
- data/lib/google/protobuf_native.rb +20 -0
- data/lib/google/tasks/ffi.rake +102 -0
- metadata +82 -20
- data/tests/basic.rb +0 -640
- data/tests/generated_code_test.rb +0 -23
- data/tests/stress.rb +0 -38
@@ -1,32 +1,9 @@
|
|
1
1
|
// Protocol Buffers - Google's data interchange format
|
2
2
|
// Copyright 2014 Google Inc. All rights reserved.
|
3
|
-
// https://developers.google.com/protocol-buffers/
|
4
3
|
//
|
5
|
-
//
|
6
|
-
//
|
7
|
-
//
|
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.
|
4
|
+
// Use of this source code is governed by a BSD-style
|
5
|
+
// license that can be found in the LICENSE file or at
|
6
|
+
// https://developers.google.com/open-source/licenses/bsd
|
30
7
|
|
31
8
|
#include "message.h"
|
32
9
|
|
@@ -35,12 +12,14 @@
|
|
35
12
|
#include "map.h"
|
36
13
|
#include "protobuf.h"
|
37
14
|
#include "repeated_field.h"
|
15
|
+
#include "shared_message.h"
|
38
16
|
|
39
17
|
static VALUE cParseError = Qnil;
|
18
|
+
static VALUE cAbstractMessage = Qnil;
|
40
19
|
static ID descriptor_instancevar_interned;
|
41
20
|
|
42
21
|
static VALUE initialize_rb_class_with_no_args(VALUE klass) {
|
43
|
-
|
22
|
+
return rb_funcall(klass, rb_intern("new"), 0);
|
44
23
|
}
|
45
24
|
|
46
25
|
VALUE MessageOrEnum_GetDescriptor(VALUE klass) {
|
@@ -52,20 +31,23 @@ VALUE MessageOrEnum_GetDescriptor(VALUE klass) {
|
|
52
31
|
// -----------------------------------------------------------------------------
|
53
32
|
|
54
33
|
typedef struct {
|
34
|
+
// IMPORTANT: WB_PROTECTED objects must only use the RB_OBJ_WRITE()
|
35
|
+
// macro to update VALUE references, as to trigger write barriers.
|
55
36
|
VALUE arena;
|
56
|
-
const
|
57
|
-
const
|
37
|
+
const upb_Message* msg; // Can get as mutable when non-frozen.
|
38
|
+
const upb_MessageDef*
|
39
|
+
msgdef; // kept alive by self.class.descriptor reference.
|
58
40
|
} Message;
|
59
41
|
|
60
42
|
static void Message_mark(void* _self) {
|
61
|
-
Message* self = (Message
|
43
|
+
Message* self = (Message*)_self;
|
62
44
|
rb_gc_mark(self->arena);
|
63
45
|
}
|
64
46
|
|
65
47
|
static rb_data_type_t Message_type = {
|
66
|
-
|
67
|
-
|
68
|
-
|
48
|
+
"Google::Protobuf::Message",
|
49
|
+
{Message_mark, RUBY_DEFAULT_FREE, NULL},
|
50
|
+
.flags = RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
|
69
51
|
};
|
70
52
|
|
71
53
|
static Message* ruby_to_Message(VALUE msg_rb) {
|
@@ -89,22 +71,24 @@ static VALUE Message_alloc(VALUE klass) {
|
|
89
71
|
return ret;
|
90
72
|
}
|
91
73
|
|
92
|
-
const
|
74
|
+
const upb_Message* Message_Get(VALUE msg_rb, const upb_MessageDef** m) {
|
93
75
|
Message* msg = ruby_to_Message(msg_rb);
|
94
76
|
if (m) *m = msg->msgdef;
|
95
77
|
return msg->msg;
|
96
78
|
}
|
97
79
|
|
98
|
-
|
80
|
+
upb_Message* Message_GetMutable(VALUE msg_rb, const upb_MessageDef** m) {
|
99
81
|
rb_check_frozen(msg_rb);
|
100
|
-
return (
|
82
|
+
return (upb_Message*)Message_Get(msg_rb, m);
|
101
83
|
}
|
102
84
|
|
103
|
-
void Message_InitPtr(VALUE self_,
|
85
|
+
void Message_InitPtr(VALUE self_, upb_Message* msg, VALUE arena) {
|
104
86
|
Message* self = ruby_to_Message(self_);
|
105
87
|
self->msg = msg;
|
106
|
-
self->arena
|
107
|
-
|
88
|
+
RB_OBJ_WRITE(self_, &self->arena, arena);
|
89
|
+
VALUE stored = ObjectCache_TryAdd(msg, self_);
|
90
|
+
(void)stored;
|
91
|
+
PBRUBY_ASSERT(stored == self_);
|
108
92
|
}
|
109
93
|
|
110
94
|
VALUE Message_GetArena(VALUE msg_rb) {
|
@@ -119,7 +103,8 @@ void Message_CheckClass(VALUE klass) {
|
|
119
103
|
}
|
120
104
|
}
|
121
105
|
|
122
|
-
VALUE Message_GetRubyWrapper(
|
106
|
+
VALUE Message_GetRubyWrapper(upb_Message* msg, const upb_MessageDef* m,
|
107
|
+
VALUE arena) {
|
123
108
|
if (msg == NULL) return Qnil;
|
124
109
|
|
125
110
|
VALUE val = ObjectCache_Get(msg);
|
@@ -133,17 +118,18 @@ VALUE Message_GetRubyWrapper(upb_msg* msg, const upb_msgdef* m, VALUE arena) {
|
|
133
118
|
return val;
|
134
119
|
}
|
135
120
|
|
136
|
-
void Message_PrintMessage(StringBuilder* b, const
|
137
|
-
const
|
121
|
+
void Message_PrintMessage(StringBuilder* b, const upb_Message* msg,
|
122
|
+
const upb_MessageDef* m) {
|
138
123
|
bool first = true;
|
139
|
-
int n =
|
124
|
+
int n = upb_MessageDef_FieldCount(m);
|
140
125
|
VALUE klass = Descriptor_DefToClass(m);
|
141
126
|
StringBuilder_Printf(b, "<%s: ", rb_class2name(klass));
|
142
127
|
|
143
128
|
for (int i = 0; i < n; i++) {
|
144
|
-
const
|
129
|
+
const upb_FieldDef* field = upb_MessageDef_Field(m, i);
|
145
130
|
|
146
|
-
if (
|
131
|
+
if (upb_FieldDef_HasPresence(field) &&
|
132
|
+
!upb_Message_HasFieldByDef(msg, field)) {
|
147
133
|
continue;
|
148
134
|
}
|
149
135
|
|
@@ -153,17 +139,17 @@ void Message_PrintMessage(StringBuilder* b, const upb_msg* msg,
|
|
153
139
|
first = false;
|
154
140
|
}
|
155
141
|
|
156
|
-
|
142
|
+
upb_MessageValue msgval = upb_Message_GetFieldByDef(msg, field);
|
157
143
|
|
158
|
-
StringBuilder_Printf(b, "%s: ",
|
144
|
+
StringBuilder_Printf(b, "%s: ", upb_FieldDef_Name(field));
|
159
145
|
|
160
|
-
if (
|
161
|
-
const
|
162
|
-
const
|
163
|
-
const
|
146
|
+
if (upb_FieldDef_IsMap(field)) {
|
147
|
+
const upb_MessageDef* entry_m = upb_FieldDef_MessageSubDef(field);
|
148
|
+
const upb_FieldDef* key_f = upb_MessageDef_FindFieldByNumber(entry_m, 1);
|
149
|
+
const upb_FieldDef* val_f = upb_MessageDef_FindFieldByNumber(entry_m, 2);
|
164
150
|
TypeInfo val_info = TypeInfo_get(val_f);
|
165
|
-
Map_Inspect(b, msgval.map_val,
|
166
|
-
} else if (
|
151
|
+
Map_Inspect(b, msgval.map_val, upb_FieldDef_CType(key_f), val_info);
|
152
|
+
} else if (upb_FieldDef_IsRepeated(field)) {
|
167
153
|
RepeatedField_Inspect(b, msgval.array_val, TypeInfo_get(field));
|
168
154
|
} else {
|
169
155
|
StringBuilder_PrintMsgval(b, msgval, TypeInfo_get(field));
|
@@ -187,14 +173,31 @@ enum {
|
|
187
173
|
};
|
188
174
|
|
189
175
|
// Check if the field is a well known wrapper type
|
190
|
-
static bool IsWrapper(const
|
191
|
-
|
192
|
-
|
176
|
+
static bool IsWrapper(const upb_MessageDef* m) {
|
177
|
+
if (!m) return false;
|
178
|
+
switch (upb_MessageDef_WellKnownType(m)) {
|
179
|
+
case kUpb_WellKnown_DoubleValue:
|
180
|
+
case kUpb_WellKnown_FloatValue:
|
181
|
+
case kUpb_WellKnown_Int64Value:
|
182
|
+
case kUpb_WellKnown_UInt64Value:
|
183
|
+
case kUpb_WellKnown_Int32Value:
|
184
|
+
case kUpb_WellKnown_UInt32Value:
|
185
|
+
case kUpb_WellKnown_StringValue:
|
186
|
+
case kUpb_WellKnown_BytesValue:
|
187
|
+
case kUpb_WellKnown_BoolValue:
|
188
|
+
return true;
|
189
|
+
default:
|
190
|
+
return false;
|
191
|
+
}
|
193
192
|
}
|
194
193
|
|
195
|
-
static bool
|
196
|
-
|
197
|
-
|
194
|
+
static bool IsFieldWrapper(const upb_FieldDef* f) {
|
195
|
+
return IsWrapper(upb_FieldDef_MessageSubDef(f));
|
196
|
+
}
|
197
|
+
|
198
|
+
static bool Match(const upb_MessageDef* m, const char* name,
|
199
|
+
const upb_FieldDef** f, const upb_OneofDef** o,
|
200
|
+
const char* prefix, const char* suffix) {
|
198
201
|
size_t sp = strlen(prefix);
|
199
202
|
size_t ss = strlen(suffix);
|
200
203
|
size_t sn = strlen(name);
|
@@ -206,12 +209,12 @@ static bool Match(const upb_msgdef* m, const char* name, const upb_fielddef** f,
|
|
206
209
|
return false;
|
207
210
|
}
|
208
211
|
|
209
|
-
return
|
212
|
+
return upb_MessageDef_FindByNameWithSize(m, name + sp, sn - sp - ss, f, o);
|
210
213
|
}
|
211
214
|
|
212
215
|
static int extract_method_call(VALUE method_name, Message* self,
|
213
|
-
const
|
214
|
-
const
|
216
|
+
const upb_FieldDef** f, const upb_OneofDef** o) {
|
217
|
+
const upb_MessageDef* m = self->msgdef;
|
215
218
|
const char* name;
|
216
219
|
|
217
220
|
Check_Type(method_name, T_SYMBOL);
|
@@ -221,156 +224,153 @@ static int extract_method_call(VALUE method_name, Message* self,
|
|
221
224
|
if (Match(m, name, f, o, "", "=")) return METHOD_SETTER;
|
222
225
|
if (Match(m, name, f, o, "clear_", "")) return METHOD_CLEAR;
|
223
226
|
if (Match(m, name, f, o, "has_", "?") &&
|
224
|
-
(*o || (*f &&
|
225
|
-
// Disallow oneof hazzers for proto3.
|
226
|
-
// TODO(haberman): remove this test when we are enabling oneof hazzers for
|
227
|
-
// proto3.
|
228
|
-
if (*f && !upb_fielddef_issubmsg(*f) &&
|
229
|
-
upb_fielddef_realcontainingoneof(*f) &&
|
230
|
-
upb_msgdef_syntax(upb_fielddef_containingtype(*f)) !=
|
231
|
-
UPB_SYNTAX_PROTO2) {
|
232
|
-
return METHOD_UNKNOWN;
|
233
|
-
}
|
227
|
+
(*o || (*f && upb_FieldDef_HasPresence(*f)))) {
|
234
228
|
return METHOD_PRESENCE;
|
235
229
|
}
|
236
|
-
if (Match(m, name, f, o, "", "_as_value") && *f &&
|
237
|
-
|
230
|
+
if (Match(m, name, f, o, "", "_as_value") && *f &&
|
231
|
+
!upb_FieldDef_IsRepeated(*f) && IsFieldWrapper(*f)) {
|
238
232
|
return METHOD_WRAPPER_GETTER;
|
239
233
|
}
|
240
|
-
if (Match(m, name, f, o, "", "_as_value=") && *f &&
|
241
|
-
|
234
|
+
if (Match(m, name, f, o, "", "_as_value=") && *f &&
|
235
|
+
!upb_FieldDef_IsRepeated(*f) && IsFieldWrapper(*f)) {
|
242
236
|
return METHOD_WRAPPER_SETTER;
|
243
237
|
}
|
244
238
|
if (Match(m, name, f, o, "", "_const") && *f &&
|
245
|
-
|
239
|
+
upb_FieldDef_CType(*f) == kUpb_CType_Enum) {
|
246
240
|
return METHOD_ENUM_GETTER;
|
247
241
|
}
|
248
242
|
|
249
243
|
return METHOD_UNKNOWN;
|
250
244
|
}
|
251
245
|
|
252
|
-
static VALUE Message_oneof_accessor(VALUE _self, const
|
246
|
+
static VALUE Message_oneof_accessor(VALUE _self, const upb_OneofDef* o,
|
253
247
|
int accessor_type) {
|
254
248
|
Message* self = ruby_to_Message(_self);
|
255
|
-
const
|
249
|
+
const upb_FieldDef* oneof_field = upb_Message_WhichOneof(self->msg, o);
|
256
250
|
|
257
251
|
switch (accessor_type) {
|
258
252
|
case METHOD_PRESENCE:
|
259
253
|
return oneof_field == NULL ? Qfalse : Qtrue;
|
260
254
|
case METHOD_CLEAR:
|
261
255
|
if (oneof_field != NULL) {
|
262
|
-
|
256
|
+
upb_Message_ClearFieldByDef(Message_GetMutable(_self, NULL),
|
257
|
+
oneof_field);
|
263
258
|
}
|
264
259
|
return Qnil;
|
265
260
|
case METHOD_GETTER:
|
266
261
|
return oneof_field == NULL
|
267
262
|
? Qnil
|
268
|
-
: ID2SYM(rb_intern(
|
263
|
+
: ID2SYM(rb_intern(upb_FieldDef_Name(oneof_field)));
|
269
264
|
case METHOD_SETTER:
|
270
265
|
rb_raise(rb_eRuntimeError, "Oneof accessors are read-only.");
|
271
266
|
}
|
272
267
|
rb_raise(rb_eRuntimeError, "Invalid access of oneof field.");
|
273
268
|
}
|
274
269
|
|
275
|
-
static void Message_setfield(
|
276
|
-
|
277
|
-
|
278
|
-
if (
|
270
|
+
static void Message_setfield(upb_Message* msg, const upb_FieldDef* f, VALUE val,
|
271
|
+
upb_Arena* arena) {
|
272
|
+
upb_MessageValue msgval;
|
273
|
+
if (upb_FieldDef_IsMap(f)) {
|
279
274
|
msgval.map_val = Map_GetUpbMap(val, f, arena);
|
280
|
-
} else if (
|
275
|
+
} else if (upb_FieldDef_IsRepeated(f)) {
|
281
276
|
msgval.array_val = RepeatedField_GetUpbArray(val, f, arena);
|
282
277
|
} else {
|
283
278
|
if (val == Qnil &&
|
284
|
-
(
|
285
|
-
|
279
|
+
(upb_FieldDef_IsSubMessage(f) || upb_FieldDef_RealContainingOneof(f))) {
|
280
|
+
upb_Message_ClearFieldByDef(msg, f);
|
286
281
|
return;
|
287
282
|
}
|
288
283
|
msgval =
|
289
|
-
Convert_RubyToUpb(val,
|
284
|
+
Convert_RubyToUpb(val, upb_FieldDef_Name(f), TypeInfo_get(f), arena);
|
290
285
|
}
|
291
|
-
|
286
|
+
upb_Message_SetFieldByDef(msg, f, msgval, arena);
|
292
287
|
}
|
293
288
|
|
294
|
-
VALUE Message_getfield(VALUE _self, const
|
289
|
+
VALUE Message_getfield(VALUE _self, const upb_FieldDef* f) {
|
295
290
|
Message* self = ruby_to_Message(_self);
|
296
|
-
// This is a special-case:
|
291
|
+
// This is a special-case: upb_Message_Mutable() for map & array are logically
|
297
292
|
// const (they will not change what is serialized) but physically
|
298
293
|
// non-const, as they do allocate a repeated field or map. The logical
|
299
294
|
// constness means it's ok to do even if the message is frozen.
|
300
|
-
|
301
|
-
|
302
|
-
if (
|
303
|
-
|
304
|
-
const
|
305
|
-
const
|
306
|
-
|
295
|
+
upb_Message* msg = (upb_Message*)self->msg;
|
296
|
+
upb_Arena* arena = Arena_get(self->arena);
|
297
|
+
if (upb_FieldDef_IsMap(f)) {
|
298
|
+
upb_Map* map = upb_Message_Mutable(msg, f, arena).map;
|
299
|
+
const upb_FieldDef* key_f = map_field_key(f);
|
300
|
+
const upb_FieldDef* val_f = map_field_value(f);
|
301
|
+
upb_CType key_type = upb_FieldDef_CType(key_f);
|
307
302
|
TypeInfo value_type_info = TypeInfo_get(val_f);
|
308
303
|
return Map_GetRubyWrapper(map, key_type, value_type_info, self->arena);
|
309
|
-
} else if (
|
310
|
-
|
304
|
+
} else if (upb_FieldDef_IsRepeated(f)) {
|
305
|
+
upb_Array* arr = upb_Message_Mutable(msg, f, arena).array;
|
311
306
|
return RepeatedField_GetRubyWrapper(arr, TypeInfo_get(f), self->arena);
|
312
|
-
} else if (
|
313
|
-
if (!
|
314
|
-
|
315
|
-
const
|
307
|
+
} else if (upb_FieldDef_IsSubMessage(f)) {
|
308
|
+
if (!upb_Message_HasFieldByDef(self->msg, f)) return Qnil;
|
309
|
+
upb_Message* submsg = upb_Message_Mutable(msg, f, arena).msg;
|
310
|
+
const upb_MessageDef* m = upb_FieldDef_MessageSubDef(f);
|
316
311
|
return Message_GetRubyWrapper(submsg, m, self->arena);
|
317
312
|
} else {
|
318
|
-
|
313
|
+
upb_MessageValue msgval = upb_Message_GetFieldByDef(self->msg, f);
|
319
314
|
return Convert_UpbToRuby(msgval, TypeInfo_get(f), self->arena);
|
320
315
|
}
|
321
316
|
}
|
322
317
|
|
323
|
-
static VALUE Message_field_accessor(VALUE _self, const
|
318
|
+
static VALUE Message_field_accessor(VALUE _self, const upb_FieldDef* f,
|
324
319
|
int accessor_type, int argc, VALUE* argv) {
|
325
|
-
|
320
|
+
upb_Arena* arena = Arena_get(Message_GetArena(_self));
|
326
321
|
|
327
322
|
switch (accessor_type) {
|
328
323
|
case METHOD_SETTER:
|
329
324
|
Message_setfield(Message_GetMutable(_self, NULL), f, argv[1], arena);
|
330
325
|
return Qnil;
|
331
326
|
case METHOD_CLEAR:
|
332
|
-
|
327
|
+
upb_Message_ClearFieldByDef(Message_GetMutable(_self, NULL), f);
|
333
328
|
return Qnil;
|
334
329
|
case METHOD_PRESENCE:
|
335
|
-
if (!
|
330
|
+
if (!upb_FieldDef_HasPresence(f)) {
|
336
331
|
rb_raise(rb_eRuntimeError, "Field does not have presence.");
|
337
332
|
}
|
338
|
-
return
|
333
|
+
return upb_Message_HasFieldByDef(Message_Get(_self, NULL), f);
|
339
334
|
case METHOD_WRAPPER_GETTER: {
|
340
335
|
Message* self = ruby_to_Message(_self);
|
341
|
-
if (
|
342
|
-
PBRUBY_ASSERT(
|
343
|
-
|
344
|
-
|
345
|
-
const
|
346
|
-
|
336
|
+
if (upb_Message_HasFieldByDef(self->msg, f)) {
|
337
|
+
PBRUBY_ASSERT(upb_FieldDef_IsSubMessage(f) &&
|
338
|
+
!upb_FieldDef_IsRepeated(f));
|
339
|
+
upb_MessageValue wrapper = upb_Message_GetFieldByDef(self->msg, f);
|
340
|
+
const upb_MessageDef* wrapper_m = upb_FieldDef_MessageSubDef(f);
|
341
|
+
const upb_FieldDef* value_f =
|
342
|
+
upb_MessageDef_FindFieldByNumber(wrapper_m, 1);
|
343
|
+
upb_MessageValue value =
|
344
|
+
upb_Message_GetFieldByDef(wrapper.msg_val, value_f);
|
347
345
|
return Convert_UpbToRuby(value, TypeInfo_get(value_f), self->arena);
|
348
346
|
} else {
|
349
347
|
return Qnil;
|
350
348
|
}
|
351
349
|
}
|
352
350
|
case METHOD_WRAPPER_SETTER: {
|
353
|
-
|
351
|
+
upb_Message* msg = Message_GetMutable(_self, NULL);
|
354
352
|
if (argv[1] == Qnil) {
|
355
|
-
|
353
|
+
upb_Message_ClearFieldByDef(msg, f);
|
356
354
|
} else {
|
357
|
-
const
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
355
|
+
const upb_FieldDef* val_f =
|
356
|
+
upb_MessageDef_FindFieldByNumber(upb_FieldDef_MessageSubDef(f), 1);
|
357
|
+
upb_MessageValue msgval = Convert_RubyToUpb(
|
358
|
+
argv[1], upb_FieldDef_Name(f), TypeInfo_get(val_f), arena);
|
359
|
+
upb_Message* wrapper = upb_Message_Mutable(msg, f, arena).msg;
|
360
|
+
upb_Message_SetFieldByDef(wrapper, val_f, msgval, arena);
|
362
361
|
}
|
363
362
|
return Qnil;
|
364
363
|
}
|
365
364
|
case METHOD_ENUM_GETTER: {
|
366
|
-
|
365
|
+
upb_MessageValue msgval =
|
366
|
+
upb_Message_GetFieldByDef(Message_Get(_self, NULL), f);
|
367
367
|
|
368
|
-
if (
|
368
|
+
if (upb_FieldDef_Label(f) == kUpb_Label_Repeated) {
|
369
369
|
// Map repeated fields to a new type with ints
|
370
370
|
VALUE arr = rb_ary_new();
|
371
|
-
size_t i, n =
|
371
|
+
size_t i, n = upb_Array_Size(msgval.array_val);
|
372
372
|
for (i = 0; i < n; i++) {
|
373
|
-
|
373
|
+
upb_MessageValue elem = upb_Array_Get(msgval.array_val, i);
|
374
374
|
rb_ary_push(arr, INT2NUM(elem.int32_val));
|
375
375
|
}
|
376
376
|
return arr;
|
@@ -415,8 +415,8 @@ static VALUE Message_field_accessor(VALUE _self, const upb_fielddef* f,
|
|
415
415
|
*/
|
416
416
|
static VALUE Message_method_missing(int argc, VALUE* argv, VALUE _self) {
|
417
417
|
Message* self = ruby_to_Message(_self);
|
418
|
-
const
|
419
|
-
const
|
418
|
+
const upb_OneofDef* o;
|
419
|
+
const upb_FieldDef* f;
|
420
420
|
int accessor_type;
|
421
421
|
|
422
422
|
if (argc < 1) {
|
@@ -453,8 +453,8 @@ static VALUE Message_method_missing(int argc, VALUE* argv, VALUE _self) {
|
|
453
453
|
|
454
454
|
static VALUE Message_respond_to_missing(int argc, VALUE* argv, VALUE _self) {
|
455
455
|
Message* self = ruby_to_Message(_self);
|
456
|
-
const
|
457
|
-
const
|
456
|
+
const upb_OneofDef* o;
|
457
|
+
const upb_FieldDef* f;
|
458
458
|
int accessor_type;
|
459
459
|
|
460
460
|
if (argc < 1) {
|
@@ -472,53 +472,55 @@ static VALUE Message_respond_to_missing(int argc, VALUE* argv, VALUE _self) {
|
|
472
472
|
}
|
473
473
|
}
|
474
474
|
|
475
|
-
void Message_InitFromValue(
|
476
|
-
|
475
|
+
void Message_InitFromValue(upb_Message* msg, const upb_MessageDef* m, VALUE val,
|
476
|
+
upb_Arena* arena);
|
477
477
|
|
478
478
|
typedef struct {
|
479
|
-
|
479
|
+
upb_Map* map;
|
480
480
|
TypeInfo key_type;
|
481
481
|
TypeInfo val_type;
|
482
|
-
|
482
|
+
upb_Arena* arena;
|
483
483
|
} MapInit;
|
484
484
|
|
485
485
|
static int Map_initialize_kwarg(VALUE key, VALUE val, VALUE _self) {
|
486
|
-
MapInit
|
487
|
-
|
486
|
+
MapInit* map_init = (MapInit*)_self;
|
487
|
+
upb_MessageValue k, v;
|
488
488
|
k = Convert_RubyToUpb(key, "", map_init->key_type, NULL);
|
489
489
|
|
490
|
-
if (map_init->val_type.type ==
|
491
|
-
|
490
|
+
if (map_init->val_type.type == kUpb_CType_Message && TYPE(val) == T_HASH) {
|
491
|
+
upb_MiniTable* t = upb_MessageDef_MiniTable(map_init->val_type.def.msgdef);
|
492
|
+
upb_Message* msg = upb_Message_New(t, map_init->arena);
|
492
493
|
Message_InitFromValue(msg, map_init->val_type.def.msgdef, val,
|
493
494
|
map_init->arena);
|
494
495
|
v.msg_val = msg;
|
495
496
|
} else {
|
496
497
|
v = Convert_RubyToUpb(val, "", map_init->val_type, map_init->arena);
|
497
498
|
}
|
498
|
-
|
499
|
+
upb_Map_Set(map_init->map, k, v, map_init->arena);
|
499
500
|
return ST_CONTINUE;
|
500
501
|
}
|
501
502
|
|
502
|
-
static void Map_InitFromValue(
|
503
|
-
|
504
|
-
const
|
505
|
-
const
|
506
|
-
const
|
503
|
+
static void Map_InitFromValue(upb_Map* map, const upb_FieldDef* f, VALUE val,
|
504
|
+
upb_Arena* arena) {
|
505
|
+
const upb_MessageDef* entry_m = upb_FieldDef_MessageSubDef(f);
|
506
|
+
const upb_FieldDef* key_f = upb_MessageDef_FindFieldByNumber(entry_m, 1);
|
507
|
+
const upb_FieldDef* val_f = upb_MessageDef_FindFieldByNumber(entry_m, 2);
|
507
508
|
if (TYPE(val) != T_HASH) {
|
508
509
|
rb_raise(rb_eArgError,
|
509
510
|
"Expected Hash object as initializer value for map field '%s' "
|
510
511
|
"(given %s).",
|
511
|
-
|
512
|
+
upb_FieldDef_Name(f), rb_class2name(CLASS_OF(val)));
|
512
513
|
}
|
513
514
|
MapInit map_init = {map, TypeInfo_get(key_f), TypeInfo_get(val_f), arena};
|
514
515
|
rb_hash_foreach(val, Map_initialize_kwarg, (VALUE)&map_init);
|
515
516
|
}
|
516
517
|
|
517
|
-
static
|
518
|
-
|
519
|
-
if (info.type ==
|
520
|
-
|
521
|
-
|
518
|
+
static upb_MessageValue MessageValue_FromValue(VALUE val, TypeInfo info,
|
519
|
+
upb_Arena* arena) {
|
520
|
+
if (info.type == kUpb_CType_Message) {
|
521
|
+
upb_MessageValue msgval;
|
522
|
+
upb_MiniTable* t = upb_MessageDef_MiniTable(info.def.msgdef);
|
523
|
+
upb_Message* msg = upb_Message_New(t, arena);
|
522
524
|
Message_InitFromValue(msg, info.def.msgdef, val, arena);
|
523
525
|
msgval.msg_val = msg;
|
524
526
|
return msgval;
|
@@ -527,61 +529,62 @@ static upb_msgval MessageValue_FromValue(VALUE val, TypeInfo info,
|
|
527
529
|
}
|
528
530
|
}
|
529
531
|
|
530
|
-
static void RepeatedField_InitFromValue(
|
531
|
-
VALUE val,
|
532
|
+
static void RepeatedField_InitFromValue(upb_Array* arr, const upb_FieldDef* f,
|
533
|
+
VALUE val, upb_Arena* arena) {
|
532
534
|
TypeInfo type_info = TypeInfo_get(f);
|
533
535
|
|
534
536
|
if (TYPE(val) != T_ARRAY) {
|
535
537
|
rb_raise(rb_eArgError,
|
536
|
-
"Expected array as initializer value for repeated field '%s'
|
537
|
-
|
538
|
+
"Expected array as initializer value for repeated field '%s' "
|
539
|
+
"(given %s).",
|
540
|
+
upb_FieldDef_Name(f), rb_class2name(CLASS_OF(val)));
|
538
541
|
}
|
539
542
|
|
540
543
|
for (int i = 0; i < RARRAY_LEN(val); i++) {
|
541
544
|
VALUE entry = rb_ary_entry(val, i);
|
542
|
-
|
543
|
-
if (
|
545
|
+
upb_MessageValue msgval;
|
546
|
+
if (upb_FieldDef_IsSubMessage(f) && TYPE(entry) == T_HASH) {
|
544
547
|
msgval = MessageValue_FromValue(entry, type_info, arena);
|
545
548
|
} else {
|
546
|
-
msgval = Convert_RubyToUpb(entry,
|
549
|
+
msgval = Convert_RubyToUpb(entry, upb_FieldDef_Name(f), type_info, arena);
|
547
550
|
}
|
548
|
-
|
551
|
+
upb_Array_Append(arr, msgval, arena);
|
549
552
|
}
|
550
553
|
}
|
551
554
|
|
552
|
-
static void Message_InitFieldFromValue(
|
553
|
-
VALUE val,
|
555
|
+
static void Message_InitFieldFromValue(upb_Message* msg, const upb_FieldDef* f,
|
556
|
+
VALUE val, upb_Arena* arena) {
|
554
557
|
if (TYPE(val) == T_NIL) return;
|
555
558
|
|
556
|
-
if (
|
557
|
-
|
559
|
+
if (upb_FieldDef_IsMap(f)) {
|
560
|
+
upb_Map* map = upb_Message_Mutable(msg, f, arena).map;
|
558
561
|
Map_InitFromValue(map, f, val, arena);
|
559
|
-
} else if (
|
560
|
-
|
562
|
+
} else if (upb_FieldDef_Label(f) == kUpb_Label_Repeated) {
|
563
|
+
upb_Array* arr = upb_Message_Mutable(msg, f, arena).array;
|
561
564
|
RepeatedField_InitFromValue(arr, f, val, arena);
|
562
|
-
} else if (
|
565
|
+
} else if (upb_FieldDef_IsSubMessage(f)) {
|
563
566
|
if (TYPE(val) == T_HASH) {
|
564
|
-
|
565
|
-
Message_InitFromValue(submsg,
|
567
|
+
upb_Message* submsg = upb_Message_Mutable(msg, f, arena).msg;
|
568
|
+
Message_InitFromValue(submsg, upb_FieldDef_MessageSubDef(f), val, arena);
|
566
569
|
} else {
|
567
570
|
Message_setfield(msg, f, val, arena);
|
568
571
|
}
|
569
572
|
} else {
|
570
|
-
|
571
|
-
Convert_RubyToUpb(val,
|
572
|
-
|
573
|
+
upb_MessageValue msgval =
|
574
|
+
Convert_RubyToUpb(val, upb_FieldDef_Name(f), TypeInfo_get(f), arena);
|
575
|
+
upb_Message_SetFieldByDef(msg, f, msgval, arena);
|
573
576
|
}
|
574
577
|
}
|
575
578
|
|
576
579
|
typedef struct {
|
577
|
-
|
578
|
-
const
|
579
|
-
|
580
|
+
upb_Message* msg;
|
581
|
+
const upb_MessageDef* msgdef;
|
582
|
+
upb_Arena* arena;
|
580
583
|
} MsgInit;
|
581
584
|
|
582
585
|
static int Message_initialize_kwarg(VALUE key, VALUE val, VALUE _self) {
|
583
|
-
MsgInit
|
584
|
-
const char
|
586
|
+
MsgInit* msg_init = (MsgInit*)_self;
|
587
|
+
const char* name;
|
585
588
|
|
586
589
|
if (TYPE(key) == T_STRING) {
|
587
590
|
name = RSTRING_PTR(key);
|
@@ -589,10 +592,12 @@ static int Message_initialize_kwarg(VALUE key, VALUE val, VALUE _self) {
|
|
589
592
|
name = RSTRING_PTR(rb_id2str(SYM2ID(key)));
|
590
593
|
} else {
|
591
594
|
rb_raise(rb_eArgError,
|
592
|
-
"Expected string or symbols as hash keys when initializing proto
|
595
|
+
"Expected string or symbols as hash keys when initializing proto "
|
596
|
+
"from hash.");
|
593
597
|
}
|
594
598
|
|
595
|
-
const
|
599
|
+
const upb_FieldDef* f =
|
600
|
+
upb_MessageDef_FindFieldByName(msg_init->msgdef, name);
|
596
601
|
|
597
602
|
if (f == NULL) {
|
598
603
|
rb_raise(rb_eArgError,
|
@@ -603,8 +608,8 @@ static int Message_initialize_kwarg(VALUE key, VALUE val, VALUE _self) {
|
|
603
608
|
return ST_CONTINUE;
|
604
609
|
}
|
605
610
|
|
606
|
-
void Message_InitFromValue(
|
607
|
-
|
611
|
+
void Message_InitFromValue(upb_Message* msg, const upb_MessageDef* m, VALUE val,
|
612
|
+
upb_Arena* arena) {
|
608
613
|
MsgInit msg_init = {msg, m, arena};
|
609
614
|
if (TYPE(val) == T_HASH) {
|
610
615
|
rb_hash_foreach(val, Message_initialize_kwarg, (VALUE)&msg_init);
|
@@ -629,8 +634,9 @@ void Message_InitFromValue(upb_msg* msg, const upb_msgdef* m, VALUE val,
|
|
629
634
|
static VALUE Message_initialize(int argc, VALUE* argv, VALUE _self) {
|
630
635
|
Message* self = ruby_to_Message(_self);
|
631
636
|
VALUE arena_rb = Arena_new();
|
632
|
-
|
633
|
-
|
637
|
+
upb_Arena* arena = Arena_get(arena_rb);
|
638
|
+
upb_MiniTable* t = upb_MessageDef_MiniTable(self->msgdef);
|
639
|
+
upb_Message* msg = upb_Message_New(t, arena);
|
634
640
|
|
635
641
|
Message_InitPtr(_self, msg, arena_rb);
|
636
642
|
|
@@ -640,7 +646,7 @@ static VALUE Message_initialize(int argc, VALUE* argv, VALUE _self) {
|
|
640
646
|
if (argc != 1) {
|
641
647
|
rb_raise(rb_eArgError, "Expected 0 or 1 arguments.");
|
642
648
|
}
|
643
|
-
Message_InitFromValue((
|
649
|
+
Message_InitFromValue((upb_Message*)self->msg, self->msgdef, argv[0], arena);
|
644
650
|
return Qnil;
|
645
651
|
}
|
646
652
|
|
@@ -654,35 +660,25 @@ static VALUE Message_dup(VALUE _self) {
|
|
654
660
|
Message* self = ruby_to_Message(_self);
|
655
661
|
VALUE new_msg = rb_class_new_instance(0, NULL, CLASS_OF(_self));
|
656
662
|
Message* new_msg_self = ruby_to_Message(new_msg);
|
657
|
-
size_t size =
|
663
|
+
size_t size = upb_MessageDef_MiniTable(self->msgdef)->size;
|
658
664
|
|
659
|
-
// TODO
|
660
|
-
// TODO
|
661
|
-
memcpy((
|
665
|
+
// TODO
|
666
|
+
// TODO
|
667
|
+
memcpy((upb_Message*)new_msg_self->msg, self->msg, size);
|
662
668
|
Arena_fuse(self->arena, Arena_get(new_msg_self->arena));
|
663
669
|
return new_msg;
|
664
670
|
}
|
665
671
|
|
666
672
|
// Support function for Message_eq, and also used by other #eq functions.
|
667
|
-
bool Message_Equal(const
|
668
|
-
|
669
|
-
|
670
|
-
|
671
|
-
|
672
|
-
|
673
|
-
|
674
|
-
|
675
|
-
// Compare deterministically serialized payloads with no unknown fields.
|
676
|
-
char *data1 = upb_encode_ex(m1, layout, encode_opts, arena_tmp, &size1);
|
677
|
-
char *data2 = upb_encode_ex(m2, layout, encode_opts, arena_tmp, &size2);
|
678
|
-
|
679
|
-
if (data1 && data2) {
|
680
|
-
bool ret = (size1 == size2) && (memcmp(data1, data2, size1) == 0);
|
681
|
-
upb_arena_free(arena_tmp);
|
682
|
-
return ret;
|
673
|
+
bool Message_Equal(const upb_Message* m1, const upb_Message* m2,
|
674
|
+
const upb_MessageDef* m) {
|
675
|
+
upb_Status status;
|
676
|
+
upb_Status_Clear(&status);
|
677
|
+
bool return_value = shared_Message_Equal(m1, m2, m, &status);
|
678
|
+
if (upb_Status_IsOk(&status)) {
|
679
|
+
return return_value;
|
683
680
|
} else {
|
684
|
-
|
685
|
-
rb_raise(cParseError, "Error comparing messages");
|
681
|
+
rb_raise(cParseError, upb_Status_ErrorMessage(&status));
|
686
682
|
}
|
687
683
|
}
|
688
684
|
|
@@ -705,23 +701,15 @@ static VALUE Message_eq(VALUE _self, VALUE _other) {
|
|
705
701
|
return Message_Equal(self->msg, other->msg, self->msgdef) ? Qtrue : Qfalse;
|
706
702
|
}
|
707
703
|
|
708
|
-
uint64_t Message_Hash(const
|
709
|
-
|
710
|
-
|
711
|
-
|
712
|
-
|
713
|
-
|
714
|
-
|
715
|
-
UPB_ENCODE_SKIPUNKNOWN | UPB_ENCODE_DETERMINISTIC, arena,
|
716
|
-
&size);
|
717
|
-
|
718
|
-
if (data) {
|
719
|
-
uint64_t ret = Wyhash(data, size, seed, kWyhashSalt);
|
720
|
-
upb_arena_free(arena);
|
721
|
-
return ret;
|
704
|
+
uint64_t Message_Hash(const upb_Message* msg, const upb_MessageDef* m,
|
705
|
+
uint64_t seed) {
|
706
|
+
upb_Status status;
|
707
|
+
upb_Status_Clear(&status);
|
708
|
+
uint64_t return_value = shared_Message_Hash(msg, m, seed, &status);
|
709
|
+
if (upb_Status_IsOk(&status)) {
|
710
|
+
return return_value;
|
722
711
|
} else {
|
723
|
-
|
724
|
-
rb_raise(cParseError, "Error calculating hash");
|
712
|
+
rb_raise(cParseError, upb_Status_ErrorMessage(&status));
|
725
713
|
}
|
726
714
|
}
|
727
715
|
|
@@ -759,13 +747,13 @@ static VALUE Message_inspect(VALUE _self) {
|
|
759
747
|
|
760
748
|
// Support functions for Message_to_h //////////////////////////////////////////
|
761
749
|
|
762
|
-
static VALUE RepeatedField_CreateArray(const
|
750
|
+
static VALUE RepeatedField_CreateArray(const upb_Array* arr,
|
763
751
|
TypeInfo type_info) {
|
764
|
-
int size = arr ?
|
752
|
+
int size = arr ? upb_Array_Size(arr) : 0;
|
765
753
|
VALUE ary = rb_ary_new2(size);
|
766
754
|
|
767
755
|
for (int i = 0; i < size; i++) {
|
768
|
-
|
756
|
+
upb_MessageValue msgval = upb_Array_Get(arr, i);
|
769
757
|
VALUE val = Scalar_CreateHash(msgval, type_info);
|
770
758
|
rb_ary_push(ary, val);
|
771
759
|
}
|
@@ -773,54 +761,56 @@ static VALUE RepeatedField_CreateArray(const upb_array* arr,
|
|
773
761
|
return ary;
|
774
762
|
}
|
775
763
|
|
776
|
-
static VALUE Message_CreateHash(const
|
764
|
+
static VALUE Message_CreateHash(const upb_Message* msg,
|
765
|
+
const upb_MessageDef* m) {
|
777
766
|
if (!msg) return Qnil;
|
778
767
|
|
779
768
|
VALUE hash = rb_hash_new();
|
780
|
-
int n =
|
769
|
+
int n = upb_MessageDef_FieldCount(m);
|
781
770
|
bool is_proto2;
|
782
771
|
|
783
772
|
// We currently have a few behaviors that are specific to proto2.
|
784
773
|
// This is unfortunate, we should key behaviors off field attributes (like
|
785
774
|
// whether a field has presence), not proto2 vs. proto3. We should see if we
|
786
775
|
// can change this without breaking users.
|
787
|
-
is_proto2 =
|
776
|
+
is_proto2 = upb_MessageDef_Syntax(m) == kUpb_Syntax_Proto2;
|
788
777
|
|
789
778
|
for (int i = 0; i < n; i++) {
|
790
|
-
const
|
779
|
+
const upb_FieldDef* field = upb_MessageDef_Field(m, i);
|
791
780
|
TypeInfo type_info = TypeInfo_get(field);
|
792
|
-
|
781
|
+
upb_MessageValue msgval;
|
793
782
|
VALUE msg_value;
|
794
783
|
VALUE msg_key;
|
795
784
|
|
796
|
-
if (!is_proto2 &&
|
797
|
-
!
|
785
|
+
if (!is_proto2 && upb_FieldDef_IsSubMessage(field) &&
|
786
|
+
!upb_FieldDef_IsRepeated(field) &&
|
787
|
+
!upb_Message_HasFieldByDef(msg, field)) {
|
798
788
|
// TODO: Legacy behavior, remove when we fix the is_proto2 differences.
|
799
|
-
msg_key = ID2SYM(rb_intern(
|
789
|
+
msg_key = ID2SYM(rb_intern(upb_FieldDef_Name(field)));
|
800
790
|
rb_hash_aset(hash, msg_key, Qnil);
|
801
791
|
continue;
|
802
792
|
}
|
803
793
|
|
804
794
|
// Do not include fields that are not present (oneof or optional fields).
|
805
|
-
if (is_proto2 &&
|
806
|
-
!
|
795
|
+
if (is_proto2 && upb_FieldDef_HasPresence(field) &&
|
796
|
+
!upb_Message_HasFieldByDef(msg, field)) {
|
807
797
|
continue;
|
808
798
|
}
|
809
799
|
|
810
|
-
msg_key = ID2SYM(rb_intern(
|
811
|
-
msgval =
|
800
|
+
msg_key = ID2SYM(rb_intern(upb_FieldDef_Name(field)));
|
801
|
+
msgval = upb_Message_GetFieldByDef(msg, field);
|
812
802
|
|
813
803
|
// Proto2 omits empty map/repeated filds also.
|
814
804
|
|
815
|
-
if (
|
816
|
-
const
|
817
|
-
const
|
818
|
-
const
|
819
|
-
|
805
|
+
if (upb_FieldDef_IsMap(field)) {
|
806
|
+
const upb_MessageDef* entry_m = upb_FieldDef_MessageSubDef(field);
|
807
|
+
const upb_FieldDef* key_f = upb_MessageDef_FindFieldByNumber(entry_m, 1);
|
808
|
+
const upb_FieldDef* val_f = upb_MessageDef_FindFieldByNumber(entry_m, 2);
|
809
|
+
upb_CType key_type = upb_FieldDef_CType(key_f);
|
820
810
|
msg_value = Map_CreateHash(msgval.map_val, key_type, TypeInfo_get(val_f));
|
821
|
-
} else if (
|
811
|
+
} else if (upb_FieldDef_IsRepeated(field)) {
|
822
812
|
if (is_proto2 &&
|
823
|
-
(!msgval.array_val ||
|
813
|
+
(!msgval.array_val || upb_Array_Size(msgval.array_val) == 0)) {
|
824
814
|
continue;
|
825
815
|
}
|
826
816
|
msg_value = RepeatedField_CreateArray(msgval.array_val, type_info);
|
@@ -834,8 +824,8 @@ static VALUE Message_CreateHash(const upb_msg *msg, const upb_msgdef *m) {
|
|
834
824
|
return hash;
|
835
825
|
}
|
836
826
|
|
837
|
-
VALUE Scalar_CreateHash(
|
838
|
-
if (type_info.type ==
|
827
|
+
VALUE Scalar_CreateHash(upb_MessageValue msgval, TypeInfo type_info) {
|
828
|
+
if (type_info.type == kUpb_CType_Message) {
|
839
829
|
return Message_CreateHash(msgval.msg_val, type_info.def.msgdef);
|
840
830
|
} else {
|
841
831
|
return Convert_UpbToRuby(msgval, type_info, Qnil);
|
@@ -869,6 +859,32 @@ static VALUE Message_freeze(VALUE _self) {
|
|
869
859
|
return _self;
|
870
860
|
}
|
871
861
|
|
862
|
+
/*
|
863
|
+
* Deep freezes the message object recursively.
|
864
|
+
* Internal use only.
|
865
|
+
*/
|
866
|
+
VALUE Message_internal_deep_freeze(VALUE _self) {
|
867
|
+
Message* self = ruby_to_Message(_self);
|
868
|
+
Message_freeze(_self);
|
869
|
+
|
870
|
+
int n = upb_MessageDef_FieldCount(self->msgdef);
|
871
|
+
for (int i = 0; i < n; i++) {
|
872
|
+
const upb_FieldDef* f = upb_MessageDef_Field(self->msgdef, i);
|
873
|
+
VALUE field = Message_getfield(_self, f);
|
874
|
+
|
875
|
+
if (field != Qnil) {
|
876
|
+
if (upb_FieldDef_IsMap(f)) {
|
877
|
+
Map_internal_deep_freeze(field);
|
878
|
+
} else if (upb_FieldDef_IsRepeated(f)) {
|
879
|
+
RepeatedField_internal_deep_freeze(field);
|
880
|
+
} else if (upb_FieldDef_IsSubMessage(f)) {
|
881
|
+
Message_internal_deep_freeze(field);
|
882
|
+
}
|
883
|
+
}
|
884
|
+
}
|
885
|
+
return _self;
|
886
|
+
}
|
887
|
+
|
872
888
|
/*
|
873
889
|
* call-seq:
|
874
890
|
* Message.[](index) => value
|
@@ -878,10 +894,10 @@ static VALUE Message_freeze(VALUE _self) {
|
|
878
894
|
*/
|
879
895
|
static VALUE Message_index(VALUE _self, VALUE field_name) {
|
880
896
|
Message* self = ruby_to_Message(_self);
|
881
|
-
const
|
897
|
+
const upb_FieldDef* field;
|
882
898
|
|
883
899
|
Check_Type(field_name, T_STRING);
|
884
|
-
field =
|
900
|
+
field = upb_MessageDef_FindFieldByName(self->msgdef, RSTRING_PTR(field_name));
|
885
901
|
|
886
902
|
if (field == NULL) {
|
887
903
|
return Qnil;
|
@@ -899,45 +915,80 @@ static VALUE Message_index(VALUE _self, VALUE field_name) {
|
|
899
915
|
*/
|
900
916
|
static VALUE Message_index_set(VALUE _self, VALUE field_name, VALUE value) {
|
901
917
|
Message* self = ruby_to_Message(_self);
|
902
|
-
const
|
903
|
-
|
904
|
-
|
918
|
+
const upb_FieldDef* f;
|
919
|
+
upb_MessageValue val;
|
920
|
+
upb_Arena* arena = Arena_get(self->arena);
|
905
921
|
|
906
922
|
Check_Type(field_name, T_STRING);
|
907
|
-
f =
|
923
|
+
f = upb_MessageDef_FindFieldByName(self->msgdef, RSTRING_PTR(field_name));
|
908
924
|
|
909
925
|
if (f == NULL) {
|
910
926
|
rb_raise(rb_eArgError, "Unknown field: %s", RSTRING_PTR(field_name));
|
911
927
|
}
|
912
928
|
|
913
|
-
val = Convert_RubyToUpb(value,
|
914
|
-
|
929
|
+
val = Convert_RubyToUpb(value, upb_FieldDef_Name(f), TypeInfo_get(f), arena);
|
930
|
+
upb_Message_SetFieldByDef(Message_GetMutable(_self, NULL), f, val, arena);
|
915
931
|
|
916
932
|
return Qnil;
|
917
933
|
}
|
918
934
|
|
919
935
|
/*
|
920
936
|
* call-seq:
|
921
|
-
* MessageClass.decode(data) => message
|
937
|
+
* MessageClass.decode(data, options) => message
|
922
938
|
*
|
923
939
|
* Decodes the given data (as a string containing bytes in protocol buffers wire
|
924
|
-
* format) under the
|
940
|
+
* format) under the interpretation given by this message class's definition
|
925
941
|
* and returns a message object with the corresponding field values.
|
942
|
+
* @param options [Hash] options for the decoder
|
943
|
+
* recursion_limit: set to maximum decoding depth for message (default is 64)
|
926
944
|
*/
|
927
|
-
static VALUE Message_decode(VALUE
|
945
|
+
static VALUE Message_decode(int argc, VALUE* argv, VALUE klass) {
|
946
|
+
VALUE data = argv[0];
|
947
|
+
int options = 0;
|
948
|
+
|
949
|
+
if (argc < 1 || argc > 2) {
|
950
|
+
rb_raise(rb_eArgError, "Expected 1 or 2 arguments.");
|
951
|
+
}
|
952
|
+
|
953
|
+
if (argc == 2) {
|
954
|
+
VALUE hash_args = argv[1];
|
955
|
+
if (TYPE(hash_args) != T_HASH) {
|
956
|
+
rb_raise(rb_eArgError, "Expected hash arguments.");
|
957
|
+
}
|
958
|
+
|
959
|
+
VALUE depth =
|
960
|
+
rb_hash_lookup(hash_args, ID2SYM(rb_intern("recursion_limit")));
|
961
|
+
|
962
|
+
if (depth != Qnil && TYPE(depth) == T_FIXNUM) {
|
963
|
+
options |= upb_DecodeOptions_MaxDepth(FIX2INT(depth));
|
964
|
+
}
|
965
|
+
}
|
966
|
+
|
928
967
|
if (TYPE(data) != T_STRING) {
|
929
968
|
rb_raise(rb_eArgError, "Expected string for binary protobuf data.");
|
930
969
|
}
|
931
970
|
|
971
|
+
return Message_decode_bytes(RSTRING_LEN(data), RSTRING_PTR(data), options,
|
972
|
+
klass, /*freeze*/ false);
|
973
|
+
}
|
974
|
+
|
975
|
+
VALUE Message_decode_bytes(int size, const char* bytes, int options,
|
976
|
+
VALUE klass, bool freeze) {
|
932
977
|
VALUE msg_rb = initialize_rb_class_with_no_args(klass);
|
933
978
|
Message* msg = ruby_to_Message(msg_rb);
|
934
979
|
|
935
|
-
|
936
|
-
|
937
|
-
|
980
|
+
const upb_FileDef* file = upb_MessageDef_File(msg->msgdef);
|
981
|
+
const upb_ExtensionRegistry* extreg =
|
982
|
+
upb_DefPool_ExtensionRegistry(upb_FileDef_Pool(file));
|
983
|
+
upb_DecodeStatus status = upb_Decode(bytes, size, (upb_Message*)msg->msg,
|
984
|
+
upb_MessageDef_MiniTable(msg->msgdef),
|
985
|
+
extreg, options, Arena_get(msg->arena));
|
986
|
+
if (status != kUpb_DecodeStatus_Ok) {
|
938
987
|
rb_raise(cParseError, "Error occurred during parsing");
|
939
988
|
}
|
940
|
-
|
989
|
+
if (freeze) {
|
990
|
+
Message_internal_deep_freeze(msg_rb);
|
991
|
+
}
|
941
992
|
return msg_rb;
|
942
993
|
}
|
943
994
|
|
@@ -956,10 +1007,10 @@ static VALUE Message_decode(VALUE klass, VALUE data) {
|
|
956
1007
|
static VALUE Message_decode_json(int argc, VALUE* argv, VALUE klass) {
|
957
1008
|
VALUE data = argv[0];
|
958
1009
|
int options = 0;
|
959
|
-
|
1010
|
+
upb_Status status;
|
960
1011
|
|
961
|
-
// TODO
|
962
|
-
const
|
1012
|
+
// TODO: use this message's pool instead.
|
1013
|
+
const upb_DefPool* symtab = DescriptorPool_GetSymtab(generated_pool);
|
963
1014
|
|
964
1015
|
if (argc < 1 || argc > 2) {
|
965
1016
|
rb_raise(rb_eArgError, "Expected 1 or 2 arguments.");
|
@@ -971,8 +1022,9 @@ static VALUE Message_decode_json(int argc, VALUE* argv, VALUE klass) {
|
|
971
1022
|
rb_raise(rb_eArgError, "Expected hash arguments.");
|
972
1023
|
}
|
973
1024
|
|
974
|
-
if (RTEST(rb_hash_lookup2(
|
975
|
-
|
1025
|
+
if (RTEST(rb_hash_lookup2(
|
1026
|
+
hash_args, ID2SYM(rb_intern("ignore_unknown_fields")), Qfalse))) {
|
1027
|
+
options |= upb_JsonDecode_IgnoreUnknown;
|
976
1028
|
}
|
977
1029
|
}
|
978
1030
|
|
@@ -980,7 +1032,7 @@ static VALUE Message_decode_json(int argc, VALUE* argv, VALUE klass) {
|
|
980
1032
|
rb_raise(rb_eArgError, "Expected string for JSON data.");
|
981
1033
|
}
|
982
1034
|
|
983
|
-
// TODO
|
1035
|
+
// TODO: Check and respect string encoding. If not UTF-8, we need to
|
984
1036
|
// convert, because string handlers pass data directly to message string
|
985
1037
|
// fields.
|
986
1038
|
|
@@ -988,16 +1040,16 @@ static VALUE Message_decode_json(int argc, VALUE* argv, VALUE klass) {
|
|
988
1040
|
Message* msg = ruby_to_Message(msg_rb);
|
989
1041
|
|
990
1042
|
// We don't allow users to decode a wrapper type directly.
|
991
|
-
if (
|
1043
|
+
if (IsWrapper(msg->msgdef)) {
|
992
1044
|
rb_raise(rb_eRuntimeError, "Cannot parse a wrapper directly.");
|
993
1045
|
}
|
994
1046
|
|
995
|
-
|
996
|
-
if (!
|
997
|
-
|
998
|
-
|
1047
|
+
upb_Status_Clear(&status);
|
1048
|
+
if (!upb_JsonDecode(RSTRING_PTR(data), RSTRING_LEN(data),
|
1049
|
+
(upb_Message*)msg->msg, msg->msgdef, symtab, options,
|
1050
|
+
Arena_get(msg->arena), &status)) {
|
999
1051
|
rb_raise(cParseError, "Error occurred during parsing: %s",
|
1000
|
-
|
1052
|
+
upb_Status_ErrorMessage(&status));
|
1001
1053
|
}
|
1002
1054
|
|
1003
1055
|
return msg_rb;
|
@@ -1005,32 +1057,53 @@ static VALUE Message_decode_json(int argc, VALUE* argv, VALUE klass) {
|
|
1005
1057
|
|
1006
1058
|
/*
|
1007
1059
|
* call-seq:
|
1008
|
-
* MessageClass.encode(msg) => bytes
|
1060
|
+
* MessageClass.encode(msg, options) => bytes
|
1009
1061
|
*
|
1010
1062
|
* Encodes the given message object to its serialized form in protocol buffers
|
1011
1063
|
* wire format.
|
1064
|
+
* @param options [Hash] options for the encoder
|
1065
|
+
* recursion_limit: set to maximum encoding depth for message (default is 64)
|
1012
1066
|
*/
|
1013
|
-
static VALUE Message_encode(VALUE
|
1014
|
-
Message* msg = ruby_to_Message(
|
1015
|
-
|
1067
|
+
static VALUE Message_encode(int argc, VALUE* argv, VALUE klass) {
|
1068
|
+
Message* msg = ruby_to_Message(argv[0]);
|
1069
|
+
int options = 0;
|
1070
|
+
char* data;
|
1016
1071
|
size_t size;
|
1017
1072
|
|
1018
|
-
if (CLASS_OF(
|
1073
|
+
if (CLASS_OF(argv[0]) != klass) {
|
1019
1074
|
rb_raise(rb_eArgError, "Message of wrong type.");
|
1020
1075
|
}
|
1021
1076
|
|
1022
|
-
|
1077
|
+
if (argc < 1 || argc > 2) {
|
1078
|
+
rb_raise(rb_eArgError, "Expected 1 or 2 arguments.");
|
1079
|
+
}
|
1080
|
+
|
1081
|
+
if (argc == 2) {
|
1082
|
+
VALUE hash_args = argv[1];
|
1083
|
+
if (TYPE(hash_args) != T_HASH) {
|
1084
|
+
rb_raise(rb_eArgError, "Expected hash arguments.");
|
1085
|
+
}
|
1086
|
+
VALUE depth =
|
1087
|
+
rb_hash_lookup(hash_args, ID2SYM(rb_intern("recursion_limit")));
|
1088
|
+
|
1089
|
+
if (depth != Qnil && TYPE(depth) == T_FIXNUM) {
|
1090
|
+
options |= upb_DecodeOptions_MaxDepth(FIX2INT(depth));
|
1091
|
+
}
|
1092
|
+
}
|
1093
|
+
|
1094
|
+
upb_Arena* arena = upb_Arena_New();
|
1023
1095
|
|
1024
|
-
|
1025
|
-
|
1096
|
+
upb_EncodeStatus status =
|
1097
|
+
upb_Encode(msg->msg, upb_MessageDef_MiniTable(msg->msgdef), options,
|
1098
|
+
arena, &data, &size);
|
1026
1099
|
|
1027
|
-
if (
|
1100
|
+
if (status == kUpb_EncodeStatus_Ok) {
|
1028
1101
|
VALUE ret = rb_str_new(data, size);
|
1029
1102
|
rb_enc_associate(ret, rb_ascii8bit_encoding());
|
1030
|
-
|
1103
|
+
upb_Arena_Free(arena);
|
1031
1104
|
return ret;
|
1032
1105
|
} else {
|
1033
|
-
|
1106
|
+
upb_Arena_Free(arena);
|
1034
1107
|
rb_raise(rb_eRuntimeError, "Exceeded maximum depth (possibly cycle)");
|
1035
1108
|
}
|
1036
1109
|
}
|
@@ -1041,18 +1114,19 @@ static VALUE Message_encode(VALUE klass, VALUE msg_rb) {
|
|
1041
1114
|
*
|
1042
1115
|
* Encodes the given message object into its serialized JSON representation.
|
1043
1116
|
* @param options [Hash] options for the decoder
|
1044
|
-
* preserve_proto_fieldnames: set true to use original fieldnames (default is
|
1045
|
-
*
|
1117
|
+
* preserve_proto_fieldnames: set true to use original fieldnames (default is
|
1118
|
+
* to camelCase) emit_defaults: set true to emit 0/false values (default is to
|
1119
|
+
* omit them)
|
1046
1120
|
*/
|
1047
1121
|
static VALUE Message_encode_json(int argc, VALUE* argv, VALUE klass) {
|
1048
1122
|
Message* msg = ruby_to_Message(argv[0]);
|
1049
1123
|
int options = 0;
|
1050
1124
|
char buf[1024];
|
1051
1125
|
size_t size;
|
1052
|
-
|
1126
|
+
upb_Status status;
|
1053
1127
|
|
1054
|
-
// TODO
|
1055
|
-
const
|
1128
|
+
// TODO: use this message's pool instead.
|
1129
|
+
const upb_DefPool* symtab = DescriptorPool_GetSymtab(generated_pool);
|
1056
1130
|
|
1057
1131
|
if (argc < 1 || argc > 2) {
|
1058
1132
|
rb_raise(rb_eArgError, "Expected 1 or 2 arguments.");
|
@@ -1061,35 +1135,46 @@ static VALUE Message_encode_json(int argc, VALUE* argv, VALUE klass) {
|
|
1061
1135
|
if (argc == 2) {
|
1062
1136
|
VALUE hash_args = argv[1];
|
1063
1137
|
if (TYPE(hash_args) != T_HASH) {
|
1064
|
-
|
1138
|
+
if (RTEST(rb_funcall(hash_args, rb_intern("respond_to?"), 1,
|
1139
|
+
rb_str_new2("to_h")))) {
|
1140
|
+
hash_args = rb_funcall(hash_args, rb_intern("to_h"), 0);
|
1141
|
+
} else {
|
1142
|
+
rb_raise(rb_eArgError, "Expected hash arguments.");
|
1143
|
+
}
|
1065
1144
|
}
|
1066
1145
|
|
1067
1146
|
if (RTEST(rb_hash_lookup2(hash_args,
|
1068
1147
|
ID2SYM(rb_intern("preserve_proto_fieldnames")),
|
1069
1148
|
Qfalse))) {
|
1070
|
-
options |=
|
1149
|
+
options |= upb_JsonEncode_UseProtoNames;
|
1071
1150
|
}
|
1072
1151
|
|
1073
1152
|
if (RTEST(rb_hash_lookup2(hash_args, ID2SYM(rb_intern("emit_defaults")),
|
1074
1153
|
Qfalse))) {
|
1075
|
-
options |=
|
1154
|
+
options |= upb_JsonEncode_EmitDefaults;
|
1155
|
+
}
|
1156
|
+
|
1157
|
+
if (RTEST(rb_hash_lookup2(hash_args,
|
1158
|
+
ID2SYM(rb_intern("format_enums_as_integers")),
|
1159
|
+
Qfalse))) {
|
1160
|
+
options |= upb_JsonEncode_FormatEnumsAsIntegers;
|
1076
1161
|
}
|
1077
1162
|
}
|
1078
1163
|
|
1079
|
-
|
1080
|
-
size =
|
1081
|
-
|
1164
|
+
upb_Status_Clear(&status);
|
1165
|
+
size = upb_JsonEncode(msg->msg, msg->msgdef, symtab, options, buf,
|
1166
|
+
sizeof(buf), &status);
|
1082
1167
|
|
1083
|
-
if (!
|
1168
|
+
if (!upb_Status_IsOk(&status)) {
|
1084
1169
|
rb_raise(cParseError, "Error occurred during encoding: %s",
|
1085
|
-
|
1170
|
+
upb_Status_ErrorMessage(&status));
|
1086
1171
|
}
|
1087
1172
|
|
1088
1173
|
VALUE ret;
|
1089
1174
|
if (size >= sizeof(buf)) {
|
1090
1175
|
char* buf2 = malloc(size + 1);
|
1091
|
-
|
1092
|
-
|
1176
|
+
upb_JsonEncode(msg->msg, msg->msgdef, symtab, options, buf2, size + 1,
|
1177
|
+
&status);
|
1093
1178
|
ret = rb_str_new(buf2, size);
|
1094
1179
|
free(buf2);
|
1095
1180
|
} else {
|
@@ -1112,10 +1197,10 @@ static VALUE Message_descriptor(VALUE klass) {
|
|
1112
1197
|
}
|
1113
1198
|
|
1114
1199
|
VALUE build_class_from_descriptor(VALUE descriptor) {
|
1115
|
-
const char
|
1200
|
+
const char* name;
|
1116
1201
|
VALUE klass;
|
1117
1202
|
|
1118
|
-
name =
|
1203
|
+
name = upb_MessageDef_FullName(Descriptor_GetMsgDef(descriptor));
|
1119
1204
|
if (name == NULL) {
|
1120
1205
|
rb_raise(rb_eRuntimeError, "Descriptor does not have assigned name.");
|
1121
1206
|
}
|
@@ -1123,38 +1208,8 @@ VALUE build_class_from_descriptor(VALUE descriptor) {
|
|
1123
1208
|
klass = rb_define_class_id(
|
1124
1209
|
// Docs say this parameter is ignored. User will assign return value to
|
1125
1210
|
// their own toplevel constant class name.
|
1126
|
-
rb_intern("Message"),
|
1127
|
-
rb_cObject);
|
1211
|
+
rb_intern("Message"), cAbstractMessage);
|
1128
1212
|
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
1213
|
return klass;
|
1159
1214
|
}
|
1160
1215
|
|
@@ -1168,13 +1223,12 @@ VALUE build_class_from_descriptor(VALUE descriptor) {
|
|
1168
1223
|
static VALUE enum_lookup(VALUE self, VALUE number) {
|
1169
1224
|
int32_t num = NUM2INT(number);
|
1170
1225
|
VALUE desc = rb_ivar_get(self, descriptor_instancevar_interned);
|
1171
|
-
const
|
1172
|
-
|
1173
|
-
|
1174
|
-
|
1175
|
-
return Qnil;
|
1226
|
+
const upb_EnumDef* e = EnumDescriptor_GetEnumDef(desc);
|
1227
|
+
const upb_EnumValueDef* ev = upb_EnumDef_FindValueByNumber(e, num);
|
1228
|
+
if (ev) {
|
1229
|
+
return ID2SYM(rb_intern(upb_EnumValueDef_Name(ev)));
|
1176
1230
|
} else {
|
1177
|
-
return
|
1231
|
+
return Qnil;
|
1178
1232
|
}
|
1179
1233
|
}
|
1180
1234
|
|
@@ -1188,14 +1242,12 @@ static VALUE enum_lookup(VALUE self, VALUE number) {
|
|
1188
1242
|
static VALUE enum_resolve(VALUE self, VALUE sym) {
|
1189
1243
|
const char* name = rb_id2name(SYM2ID(sym));
|
1190
1244
|
VALUE desc = rb_ivar_get(self, descriptor_instancevar_interned);
|
1191
|
-
const
|
1192
|
-
|
1193
|
-
|
1194
|
-
|
1195
|
-
if (!found) {
|
1196
|
-
return Qnil;
|
1245
|
+
const upb_EnumDef* e = EnumDescriptor_GetEnumDef(desc);
|
1246
|
+
const upb_EnumValueDef* ev = upb_EnumDef_FindValueByName(e, name);
|
1247
|
+
if (ev) {
|
1248
|
+
return INT2NUM(upb_EnumValueDef_Number(ev));
|
1197
1249
|
} else {
|
1198
|
-
return
|
1250
|
+
return Qnil;
|
1199
1251
|
}
|
1200
1252
|
}
|
1201
1253
|
|
@@ -1211,21 +1263,28 @@ static VALUE enum_descriptor(VALUE self) {
|
|
1211
1263
|
}
|
1212
1264
|
|
1213
1265
|
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
|
-
|
1266
|
+
const upb_EnumDef* e = EnumDescriptor_GetEnumDef(_enumdesc);
|
1267
|
+
VALUE mod = rb_define_module_id(rb_intern(upb_EnumDef_FullName(e)));
|
1268
|
+
|
1269
|
+
int n = upb_EnumDef_ValueCount(e);
|
1270
|
+
for (int i = 0; i < n; i++) {
|
1271
|
+
const upb_EnumValueDef* ev = upb_EnumDef_Value(e, i);
|
1272
|
+
upb_Arena* arena = upb_Arena_New();
|
1273
|
+
const char* src_name = upb_EnumValueDef_Name(ev);
|
1274
|
+
char* name = upb_strdup2(src_name, strlen(src_name), arena);
|
1275
|
+
int32_t value = upb_EnumValueDef_Number(ev);
|
1223
1276
|
if (name[0] < 'A' || name[0] > 'Z') {
|
1224
|
-
|
1225
|
-
|
1226
|
-
|
1277
|
+
if (name[0] >= 'a' && name[0] <= 'z') {
|
1278
|
+
name[0] -= 32; // auto capitalize
|
1279
|
+
} else {
|
1280
|
+
rb_warn(
|
1281
|
+
"Enum value '%s' does not start with an uppercase letter "
|
1282
|
+
"as is required for Ruby constants.",
|
1283
|
+
name);
|
1284
|
+
}
|
1227
1285
|
}
|
1228
1286
|
rb_define_const(mod, name, INT2NUM(value));
|
1287
|
+
upb_Arena_Free(arena);
|
1229
1288
|
}
|
1230
1289
|
|
1231
1290
|
rb_define_singleton_method(mod, "lookup", enum_lookup, 1);
|
@@ -1236,81 +1295,88 @@ VALUE build_module_from_enumdesc(VALUE _enumdesc) {
|
|
1236
1295
|
return mod;
|
1237
1296
|
}
|
1238
1297
|
|
1239
|
-
// Internal
|
1240
|
-
|
1241
|
-
|
1298
|
+
// Internal to the library; used by Google::Protobuf.deep_copy.
|
1299
|
+
upb_Message* Message_deep_copy(const upb_Message* msg, const upb_MessageDef* m,
|
1300
|
+
upb_Arena* arena) {
|
1242
1301
|
// Serialize and parse.
|
1243
|
-
|
1244
|
-
const
|
1302
|
+
upb_Arena* tmp_arena = upb_Arena_New();
|
1303
|
+
const upb_MiniTable* layout = upb_MessageDef_MiniTable(m);
|
1245
1304
|
size_t size;
|
1246
1305
|
|
1247
|
-
|
1248
|
-
|
1249
|
-
|
1250
|
-
|
1251
|
-
|
1306
|
+
upb_Message* new_msg = upb_Message_New(layout, arena);
|
1307
|
+
char* data;
|
1308
|
+
|
1309
|
+
const upb_FileDef* file = upb_MessageDef_File(m);
|
1310
|
+
const upb_ExtensionRegistry* extreg =
|
1311
|
+
upb_DefPool_ExtensionRegistry(upb_FileDef_Pool(file));
|
1312
|
+
if (upb_Encode(msg, layout, 0, tmp_arena, &data, &size) !=
|
1313
|
+
kUpb_EncodeStatus_Ok ||
|
1314
|
+
upb_Decode(data, size, new_msg, layout, extreg, 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
|
}
|