google-protobuf 3.19.1 → 4.30.2
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.
- checksums.yaml +4 -4
- data/ext/google/protobuf_c/Rakefile +3 -0
- data/ext/google/protobuf_c/convert.c +153 -166
- data/ext/google/protobuf_c/convert.h +15 -37
- data/ext/google/protobuf_c/defs.c +867 -251
- data/ext/google/protobuf_c/defs.h +22 -47
- data/ext/google/protobuf_c/extconf.rb +25 -5
- data/ext/google/protobuf_c/glue.c +135 -0
- data/ext/google/protobuf_c/map.c +182 -145
- data/ext/google/protobuf_c/map.h +16 -35
- data/ext/google/protobuf_c/message.c +534 -437
- data/ext/google/protobuf_c/message.h +30 -49
- data/ext/google/protobuf_c/protobuf.c +125 -238
- data/ext/google/protobuf_c/protobuf.h +40 -49
- data/ext/google/protobuf_c/repeated_field.c +152 -120
- data/ext/google/protobuf_c/repeated_field.h +16 -34
- data/ext/google/protobuf_c/ruby-upb.c +15827 -7228
- data/ext/google/protobuf_c/ruby-upb.h +15075 -3866
- data/ext/google/protobuf_c/shared_convert.c +69 -0
- data/ext/google/protobuf_c/shared_convert.h +26 -0
- data/ext/google/protobuf_c/shared_message.c +37 -0
- data/ext/google/protobuf_c/shared_message.h +21 -0
- data/ext/google/protobuf_c/third_party/utf8_range/LICENSE +22 -0
- data/ext/google/protobuf_c/third_party/utf8_range/utf8_range.c +207 -0
- data/ext/google/protobuf_c/third_party/utf8_range/utf8_range.h +22 -0
- data/ext/google/protobuf_c/third_party/utf8_range/utf8_range_neon.inc +117 -0
- data/ext/google/protobuf_c/third_party/utf8_range/utf8_range_sse.inc +272 -0
- data/ext/google/protobuf_c/wrap_memcpy.c +7 -29
- data/lib/google/protobuf/any_pb.rb +6 -8
- data/lib/google/protobuf/api_pb.rb +6 -26
- data/lib/google/protobuf/descriptor_pb.rb +24 -225
- data/lib/google/protobuf/duration_pb.rb +6 -8
- data/lib/google/protobuf/empty_pb.rb +6 -6
- data/lib/google/protobuf/ffi/descriptor.rb +175 -0
- data/lib/google/protobuf/ffi/descriptor_pool.rb +77 -0
- data/lib/google/protobuf/ffi/enum_descriptor.rb +183 -0
- data/lib/google/protobuf/ffi/ffi.rb +214 -0
- data/lib/google/protobuf/ffi/field_descriptor.rb +340 -0
- data/lib/google/protobuf/ffi/file_descriptor.rb +59 -0
- data/lib/google/protobuf/ffi/internal/arena.rb +60 -0
- data/lib/google/protobuf/ffi/internal/convert.rb +292 -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 +433 -0
- data/lib/google/protobuf/ffi/message.rb +783 -0
- data/lib/google/protobuf/ffi/method_descriptor.rb +124 -0
- data/lib/google/protobuf/ffi/object_cache.rb +30 -0
- data/lib/google/protobuf/ffi/oneof_descriptor.rb +107 -0
- data/lib/google/protobuf/ffi/repeated_field.rb +411 -0
- data/lib/google/protobuf/ffi/service_descriptor.rb +117 -0
- data/lib/google/protobuf/field_mask_pb.rb +6 -7
- data/lib/google/protobuf/internal/object_cache.rb +99 -0
- data/lib/google/protobuf/message_exts.rb +10 -28
- data/lib/google/protobuf/plugin_pb.rb +25 -0
- data/lib/google/protobuf/repeated_field.rb +22 -33
- data/lib/google/protobuf/source_context_pb.rb +6 -7
- data/lib/google/protobuf/struct_pb.rb +6 -23
- data/lib/google/protobuf/timestamp_pb.rb +6 -8
- data/lib/google/protobuf/type_pb.rb +6 -71
- data/lib/google/protobuf/well_known_types.rb +16 -40
- data/lib/google/protobuf/wrappers_pb.rb +6 -31
- data/lib/google/protobuf.rb +32 -50
- data/lib/google/protobuf_ffi.rb +52 -0
- data/lib/google/protobuf_native.rb +19 -0
- data/lib/google/tasks/ffi.rake +100 -0
- metadata +97 -20
- data/lib/google/protobuf/descriptor_dsl.rb +0 -458
- 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,25 @@ 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
|
|
47
|
+
static size_t Message_memsize(const void* _self) { return sizeof(Message); }
|
48
|
+
|
65
49
|
static rb_data_type_t Message_type = {
|
66
|
-
|
67
|
-
|
68
|
-
|
50
|
+
"Google::Protobuf::Message",
|
51
|
+
{Message_mark, RUBY_DEFAULT_FREE, Message_memsize},
|
52
|
+
.flags = RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
|
69
53
|
};
|
70
54
|
|
71
55
|
static Message* ruby_to_Message(VALUE msg_rb) {
|
@@ -89,22 +73,26 @@ static VALUE Message_alloc(VALUE klass) {
|
|
89
73
|
return ret;
|
90
74
|
}
|
91
75
|
|
92
|
-
const
|
76
|
+
const upb_Message* Message_Get(VALUE msg_rb, const upb_MessageDef** m) {
|
93
77
|
Message* msg = ruby_to_Message(msg_rb);
|
94
78
|
if (m) *m = msg->msgdef;
|
95
79
|
return msg->msg;
|
96
80
|
}
|
97
81
|
|
98
|
-
|
99
|
-
|
100
|
-
|
82
|
+
upb_Message* Message_GetMutable(VALUE msg_rb, const upb_MessageDef** m) {
|
83
|
+
const upb_Message* upb_msg = Message_Get(msg_rb, m);
|
84
|
+
Protobuf_CheckNotFrozen(msg_rb, upb_Message_IsFrozen(upb_msg));
|
85
|
+
return (upb_Message*)upb_msg;
|
101
86
|
}
|
102
87
|
|
103
|
-
void Message_InitPtr(VALUE self_,
|
88
|
+
void Message_InitPtr(VALUE self_, const upb_Message* msg, VALUE arena) {
|
89
|
+
PBRUBY_ASSERT(arena != Qnil);
|
104
90
|
Message* self = ruby_to_Message(self_);
|
105
91
|
self->msg = msg;
|
106
|
-
self->arena
|
107
|
-
|
92
|
+
RB_OBJ_WRITE(self_, &self->arena, arena);
|
93
|
+
VALUE stored = ObjectCache_TryAdd(msg, self_);
|
94
|
+
(void)stored;
|
95
|
+
PBRUBY_ASSERT(stored == self_);
|
108
96
|
}
|
109
97
|
|
110
98
|
VALUE Message_GetArena(VALUE msg_rb) {
|
@@ -119,7 +107,8 @@ void Message_CheckClass(VALUE klass) {
|
|
119
107
|
}
|
120
108
|
}
|
121
109
|
|
122
|
-
VALUE Message_GetRubyWrapper(
|
110
|
+
VALUE Message_GetRubyWrapper(const upb_Message* msg, const upb_MessageDef* m,
|
111
|
+
VALUE arena) {
|
123
112
|
if (msg == NULL) return Qnil;
|
124
113
|
|
125
114
|
VALUE val = ObjectCache_Get(msg);
|
@@ -129,21 +118,21 @@ VALUE Message_GetRubyWrapper(upb_msg* msg, const upb_msgdef* m, VALUE arena) {
|
|
129
118
|
val = Message_alloc(klass);
|
130
119
|
Message_InitPtr(val, msg, arena);
|
131
120
|
}
|
132
|
-
|
133
121
|
return val;
|
134
122
|
}
|
135
123
|
|
136
|
-
void Message_PrintMessage(StringBuilder* b, const
|
137
|
-
const
|
124
|
+
void Message_PrintMessage(StringBuilder* b, const upb_Message* msg,
|
125
|
+
const upb_MessageDef* m) {
|
138
126
|
bool first = true;
|
139
|
-
int n =
|
127
|
+
int n = upb_MessageDef_FieldCount(m);
|
140
128
|
VALUE klass = Descriptor_DefToClass(m);
|
141
129
|
StringBuilder_Printf(b, "<%s: ", rb_class2name(klass));
|
142
130
|
|
143
131
|
for (int i = 0; i < n; i++) {
|
144
|
-
const
|
132
|
+
const upb_FieldDef* field = upb_MessageDef_Field(m, i);
|
145
133
|
|
146
|
-
if (
|
134
|
+
if (upb_FieldDef_HasPresence(field) &&
|
135
|
+
!upb_Message_HasFieldByDef(msg, field)) {
|
147
136
|
continue;
|
148
137
|
}
|
149
138
|
|
@@ -153,17 +142,17 @@ void Message_PrintMessage(StringBuilder* b, const upb_msg* msg,
|
|
153
142
|
first = false;
|
154
143
|
}
|
155
144
|
|
156
|
-
|
145
|
+
upb_MessageValue msgval = upb_Message_GetFieldByDef(msg, field);
|
157
146
|
|
158
|
-
StringBuilder_Printf(b, "%s: ",
|
147
|
+
StringBuilder_Printf(b, "%s: ", upb_FieldDef_Name(field));
|
159
148
|
|
160
|
-
if (
|
161
|
-
const
|
162
|
-
const
|
163
|
-
const
|
149
|
+
if (upb_FieldDef_IsMap(field)) {
|
150
|
+
const upb_MessageDef* entry_m = upb_FieldDef_MessageSubDef(field);
|
151
|
+
const upb_FieldDef* key_f = upb_MessageDef_FindFieldByNumber(entry_m, 1);
|
152
|
+
const upb_FieldDef* val_f = upb_MessageDef_FindFieldByNumber(entry_m, 2);
|
164
153
|
TypeInfo val_info = TypeInfo_get(val_f);
|
165
|
-
Map_Inspect(b, msgval.map_val,
|
166
|
-
} else if (
|
154
|
+
Map_Inspect(b, msgval.map_val, upb_FieldDef_CType(key_f), val_info);
|
155
|
+
} else if (upb_FieldDef_IsRepeated(field)) {
|
167
156
|
RepeatedField_Inspect(b, msgval.array_val, TypeInfo_get(field));
|
168
157
|
} else {
|
169
158
|
StringBuilder_PrintMsgval(b, msgval, TypeInfo_get(field));
|
@@ -187,14 +176,31 @@ enum {
|
|
187
176
|
};
|
188
177
|
|
189
178
|
// Check if the field is a well known wrapper type
|
190
|
-
static bool IsWrapper(const
|
191
|
-
|
192
|
-
|
179
|
+
static bool IsWrapper(const upb_MessageDef* m) {
|
180
|
+
if (!m) return false;
|
181
|
+
switch (upb_MessageDef_WellKnownType(m)) {
|
182
|
+
case kUpb_WellKnown_DoubleValue:
|
183
|
+
case kUpb_WellKnown_FloatValue:
|
184
|
+
case kUpb_WellKnown_Int64Value:
|
185
|
+
case kUpb_WellKnown_UInt64Value:
|
186
|
+
case kUpb_WellKnown_Int32Value:
|
187
|
+
case kUpb_WellKnown_UInt32Value:
|
188
|
+
case kUpb_WellKnown_StringValue:
|
189
|
+
case kUpb_WellKnown_BytesValue:
|
190
|
+
case kUpb_WellKnown_BoolValue:
|
191
|
+
return true;
|
192
|
+
default:
|
193
|
+
return false;
|
194
|
+
}
|
193
195
|
}
|
194
196
|
|
195
|
-
static bool
|
196
|
-
|
197
|
-
|
197
|
+
static bool IsFieldWrapper(const upb_FieldDef* f) {
|
198
|
+
return IsWrapper(upb_FieldDef_MessageSubDef(f));
|
199
|
+
}
|
200
|
+
|
201
|
+
static bool Match(const upb_MessageDef* m, const char* name,
|
202
|
+
const upb_FieldDef** f, const upb_OneofDef** o,
|
203
|
+
const char* prefix, const char* suffix) {
|
198
204
|
size_t sp = strlen(prefix);
|
199
205
|
size_t ss = strlen(suffix);
|
200
206
|
size_t sn = strlen(name);
|
@@ -206,12 +212,12 @@ static bool Match(const upb_msgdef* m, const char* name, const upb_fielddef** f,
|
|
206
212
|
return false;
|
207
213
|
}
|
208
214
|
|
209
|
-
return
|
215
|
+
return upb_MessageDef_FindByNameWithSize(m, name + sp, sn - sp - ss, f, o);
|
210
216
|
}
|
211
217
|
|
212
218
|
static int extract_method_call(VALUE method_name, Message* self,
|
213
|
-
const
|
214
|
-
const
|
219
|
+
const upb_FieldDef** f, const upb_OneofDef** o) {
|
220
|
+
const upb_MessageDef* m = self->msgdef;
|
215
221
|
const char* name;
|
216
222
|
|
217
223
|
Check_Type(method_name, T_SYMBOL);
|
@@ -221,156 +227,183 @@ static int extract_method_call(VALUE method_name, Message* self,
|
|
221
227
|
if (Match(m, name, f, o, "", "=")) return METHOD_SETTER;
|
222
228
|
if (Match(m, name, f, o, "clear_", "")) return METHOD_CLEAR;
|
223
229
|
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
|
-
}
|
230
|
+
(*o || (*f && upb_FieldDef_HasPresence(*f)))) {
|
234
231
|
return METHOD_PRESENCE;
|
235
232
|
}
|
236
|
-
if (Match(m, name, f, o, "", "_as_value") && *f &&
|
237
|
-
|
233
|
+
if (Match(m, name, f, o, "", "_as_value") && *f &&
|
234
|
+
!upb_FieldDef_IsRepeated(*f) && IsFieldWrapper(*f)) {
|
238
235
|
return METHOD_WRAPPER_GETTER;
|
239
236
|
}
|
240
|
-
if (Match(m, name, f, o, "", "_as_value=") && *f &&
|
241
|
-
|
237
|
+
if (Match(m, name, f, o, "", "_as_value=") && *f &&
|
238
|
+
!upb_FieldDef_IsRepeated(*f) && IsFieldWrapper(*f)) {
|
242
239
|
return METHOD_WRAPPER_SETTER;
|
243
240
|
}
|
244
241
|
if (Match(m, name, f, o, "", "_const") && *f &&
|
245
|
-
|
242
|
+
upb_FieldDef_CType(*f) == kUpb_CType_Enum) {
|
246
243
|
return METHOD_ENUM_GETTER;
|
247
244
|
}
|
248
245
|
|
249
246
|
return METHOD_UNKNOWN;
|
250
247
|
}
|
251
248
|
|
252
|
-
static VALUE Message_oneof_accessor(VALUE _self, const
|
249
|
+
static VALUE Message_oneof_accessor(VALUE _self, const upb_OneofDef* o,
|
253
250
|
int accessor_type) {
|
254
251
|
Message* self = ruby_to_Message(_self);
|
255
|
-
const
|
252
|
+
const upb_FieldDef* oneof_field = upb_Message_WhichOneofByDef(self->msg, o);
|
256
253
|
|
257
254
|
switch (accessor_type) {
|
258
255
|
case METHOD_PRESENCE:
|
259
256
|
return oneof_field == NULL ? Qfalse : Qtrue;
|
260
257
|
case METHOD_CLEAR:
|
261
258
|
if (oneof_field != NULL) {
|
262
|
-
|
259
|
+
upb_Message_ClearFieldByDef(Message_GetMutable(_self, NULL),
|
260
|
+
oneof_field);
|
263
261
|
}
|
264
262
|
return Qnil;
|
265
263
|
case METHOD_GETTER:
|
266
264
|
return oneof_field == NULL
|
267
265
|
? Qnil
|
268
|
-
: ID2SYM(rb_intern(
|
266
|
+
: ID2SYM(rb_intern(upb_FieldDef_Name(oneof_field)));
|
269
267
|
case METHOD_SETTER:
|
270
268
|
rb_raise(rb_eRuntimeError, "Oneof accessors are read-only.");
|
271
269
|
}
|
272
270
|
rb_raise(rb_eRuntimeError, "Invalid access of oneof field.");
|
273
271
|
}
|
274
272
|
|
275
|
-
static void Message_setfield(
|
276
|
-
|
277
|
-
|
278
|
-
if (
|
273
|
+
static void Message_setfield(upb_Message* msg, const upb_FieldDef* f, VALUE val,
|
274
|
+
upb_Arena* arena) {
|
275
|
+
upb_MessageValue msgval;
|
276
|
+
if (upb_FieldDef_IsMap(f)) {
|
279
277
|
msgval.map_val = Map_GetUpbMap(val, f, arena);
|
280
|
-
} else if (
|
278
|
+
} else if (upb_FieldDef_IsRepeated(f)) {
|
281
279
|
msgval.array_val = RepeatedField_GetUpbArray(val, f, arena);
|
282
280
|
} else {
|
283
281
|
if (val == Qnil &&
|
284
|
-
(
|
285
|
-
|
282
|
+
(upb_FieldDef_IsSubMessage(f) || upb_FieldDef_RealContainingOneof(f))) {
|
283
|
+
upb_Message_ClearFieldByDef(msg, f);
|
286
284
|
return;
|
287
285
|
}
|
288
286
|
msgval =
|
289
|
-
Convert_RubyToUpb(val,
|
287
|
+
Convert_RubyToUpb(val, upb_FieldDef_Name(f), TypeInfo_get(f), arena);
|
290
288
|
}
|
291
|
-
|
289
|
+
upb_Message_SetFieldByDef(msg, f, msgval, arena);
|
292
290
|
}
|
293
291
|
|
294
|
-
VALUE
|
292
|
+
VALUE Message_getfield_frozen(const upb_Message* msg, const upb_FieldDef* f,
|
293
|
+
VALUE arena) {
|
294
|
+
upb_MessageValue msgval = upb_Message_GetFieldByDef(msg, f);
|
295
|
+
if (upb_FieldDef_IsMap(f)) {
|
296
|
+
if (msgval.map_val == NULL) {
|
297
|
+
return Map_EmptyFrozen(f);
|
298
|
+
}
|
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);
|
302
|
+
TypeInfo value_type_info = TypeInfo_get(val_f);
|
303
|
+
return Map_GetRubyWrapper(msgval.map_val, key_type, value_type_info, arena);
|
304
|
+
}
|
305
|
+
if (upb_FieldDef_IsRepeated(f)) {
|
306
|
+
if (msgval.array_val == NULL) {
|
307
|
+
return RepeatedField_EmptyFrozen(f);
|
308
|
+
}
|
309
|
+
return RepeatedField_GetRubyWrapper(msgval.array_val, TypeInfo_get(f),
|
310
|
+
arena);
|
311
|
+
}
|
312
|
+
VALUE ret;
|
313
|
+
if (upb_FieldDef_IsSubMessage(f)) {
|
314
|
+
const upb_MessageDef* m = upb_FieldDef_MessageSubDef(f);
|
315
|
+
ret = Message_GetRubyWrapper(msgval.msg_val, m, arena);
|
316
|
+
} else {
|
317
|
+
ret = Convert_UpbToRuby(msgval, TypeInfo_get(f), Qnil);
|
318
|
+
}
|
319
|
+
return ret;
|
320
|
+
}
|
321
|
+
|
322
|
+
VALUE Message_getfield(VALUE _self, const upb_FieldDef* f) {
|
295
323
|
Message* self = ruby_to_Message(_self);
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
const
|
305
|
-
|
306
|
-
upb_fieldtype_t key_type = upb_fielddef_type(key_f);
|
324
|
+
if (upb_Message_IsFrozen(self->msg)) {
|
325
|
+
return Message_getfield_frozen(self->msg, f, self->arena);
|
326
|
+
}
|
327
|
+
upb_Message* msg = Message_GetMutable(_self, NULL);
|
328
|
+
upb_Arena* arena = Arena_get(self->arena);
|
329
|
+
if (upb_FieldDef_IsMap(f)) {
|
330
|
+
upb_Map* map = upb_Message_Mutable(msg, f, arena).map;
|
331
|
+
const upb_FieldDef* key_f = map_field_key(f);
|
332
|
+
const upb_FieldDef* val_f = map_field_value(f);
|
333
|
+
upb_CType key_type = upb_FieldDef_CType(key_f);
|
307
334
|
TypeInfo value_type_info = TypeInfo_get(val_f);
|
308
335
|
return Map_GetRubyWrapper(map, key_type, value_type_info, self->arena);
|
309
|
-
} else if (
|
310
|
-
|
336
|
+
} else if (upb_FieldDef_IsRepeated(f)) {
|
337
|
+
upb_Array* arr = upb_Message_Mutable(msg, f, arena).array;
|
311
338
|
return RepeatedField_GetRubyWrapper(arr, TypeInfo_get(f), self->arena);
|
312
|
-
} else if (
|
313
|
-
if (!
|
314
|
-
|
315
|
-
const
|
339
|
+
} else if (upb_FieldDef_IsSubMessage(f)) {
|
340
|
+
if (!upb_Message_HasFieldByDef(msg, f)) return Qnil;
|
341
|
+
upb_Message* submsg = upb_Message_Mutable(msg, f, arena).msg;
|
342
|
+
const upb_MessageDef* m = upb_FieldDef_MessageSubDef(f);
|
316
343
|
return Message_GetRubyWrapper(submsg, m, self->arena);
|
317
344
|
} else {
|
318
|
-
|
345
|
+
upb_MessageValue msgval = upb_Message_GetFieldByDef(msg, f);
|
319
346
|
return Convert_UpbToRuby(msgval, TypeInfo_get(f), self->arena);
|
320
347
|
}
|
321
348
|
}
|
322
349
|
|
323
|
-
static VALUE Message_field_accessor(VALUE _self, const
|
350
|
+
static VALUE Message_field_accessor(VALUE _self, const upb_FieldDef* f,
|
324
351
|
int accessor_type, int argc, VALUE* argv) {
|
325
|
-
|
352
|
+
upb_Arena* arena = Arena_get(Message_GetArena(_self));
|
326
353
|
|
327
354
|
switch (accessor_type) {
|
328
355
|
case METHOD_SETTER:
|
329
356
|
Message_setfield(Message_GetMutable(_self, NULL), f, argv[1], arena);
|
330
357
|
return Qnil;
|
331
358
|
case METHOD_CLEAR:
|
332
|
-
|
359
|
+
upb_Message_ClearFieldByDef(Message_GetMutable(_self, NULL), f);
|
333
360
|
return Qnil;
|
334
361
|
case METHOD_PRESENCE:
|
335
|
-
if (!
|
362
|
+
if (!upb_FieldDef_HasPresence(f)) {
|
336
363
|
rb_raise(rb_eRuntimeError, "Field does not have presence.");
|
337
364
|
}
|
338
|
-
return
|
365
|
+
return upb_Message_HasFieldByDef(Message_Get(_self, NULL), f) ? Qtrue
|
366
|
+
: Qfalse;
|
339
367
|
case METHOD_WRAPPER_GETTER: {
|
340
368
|
Message* self = ruby_to_Message(_self);
|
341
|
-
if (
|
342
|
-
PBRUBY_ASSERT(
|
343
|
-
|
344
|
-
|
345
|
-
const
|
346
|
-
|
369
|
+
if (upb_Message_HasFieldByDef(self->msg, f)) {
|
370
|
+
PBRUBY_ASSERT(upb_FieldDef_IsSubMessage(f) &&
|
371
|
+
!upb_FieldDef_IsRepeated(f));
|
372
|
+
upb_MessageValue wrapper = upb_Message_GetFieldByDef(self->msg, f);
|
373
|
+
const upb_MessageDef* wrapper_m = upb_FieldDef_MessageSubDef(f);
|
374
|
+
const upb_FieldDef* value_f =
|
375
|
+
upb_MessageDef_FindFieldByNumber(wrapper_m, 1);
|
376
|
+
upb_MessageValue value =
|
377
|
+
upb_Message_GetFieldByDef(wrapper.msg_val, value_f);
|
347
378
|
return Convert_UpbToRuby(value, TypeInfo_get(value_f), self->arena);
|
348
379
|
} else {
|
349
380
|
return Qnil;
|
350
381
|
}
|
351
382
|
}
|
352
383
|
case METHOD_WRAPPER_SETTER: {
|
353
|
-
|
384
|
+
upb_Message* msg = Message_GetMutable(_self, NULL);
|
354
385
|
if (argv[1] == Qnil) {
|
355
|
-
|
386
|
+
upb_Message_ClearFieldByDef(msg, f);
|
356
387
|
} else {
|
357
|
-
const
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
388
|
+
const upb_FieldDef* val_f =
|
389
|
+
upb_MessageDef_FindFieldByNumber(upb_FieldDef_MessageSubDef(f), 1);
|
390
|
+
upb_MessageValue msgval = Convert_RubyToUpb(
|
391
|
+
argv[1], upb_FieldDef_Name(f), TypeInfo_get(val_f), arena);
|
392
|
+
upb_Message* wrapper = upb_Message_Mutable(msg, f, arena).msg;
|
393
|
+
upb_Message_SetFieldByDef(wrapper, val_f, msgval, arena);
|
362
394
|
}
|
363
395
|
return Qnil;
|
364
396
|
}
|
365
397
|
case METHOD_ENUM_GETTER: {
|
366
|
-
|
398
|
+
upb_MessageValue msgval =
|
399
|
+
upb_Message_GetFieldByDef(Message_Get(_self, NULL), f);
|
367
400
|
|
368
|
-
if (
|
401
|
+
if (upb_FieldDef_Label(f) == kUpb_Label_Repeated) {
|
369
402
|
// Map repeated fields to a new type with ints
|
370
403
|
VALUE arr = rb_ary_new();
|
371
|
-
size_t i, n =
|
404
|
+
size_t i, n = upb_Array_Size(msgval.array_val);
|
372
405
|
for (i = 0; i < n; i++) {
|
373
|
-
|
406
|
+
upb_MessageValue elem = upb_Array_Get(msgval.array_val, i);
|
374
407
|
rb_ary_push(arr, INT2NUM(elem.int32_val));
|
375
408
|
}
|
376
409
|
return arr;
|
@@ -415,8 +448,8 @@ static VALUE Message_field_accessor(VALUE _self, const upb_fielddef* f,
|
|
415
448
|
*/
|
416
449
|
static VALUE Message_method_missing(int argc, VALUE* argv, VALUE _self) {
|
417
450
|
Message* self = ruby_to_Message(_self);
|
418
|
-
const
|
419
|
-
const
|
451
|
+
const upb_OneofDef* o;
|
452
|
+
const upb_FieldDef* f;
|
420
453
|
int accessor_type;
|
421
454
|
|
422
455
|
if (argc < 1) {
|
@@ -434,7 +467,6 @@ static VALUE Message_method_missing(int argc, VALUE* argv, VALUE _self) {
|
|
434
467
|
if (argc != 2) {
|
435
468
|
rb_raise(rb_eArgError, "Expected 2 arguments, received %d", argc);
|
436
469
|
}
|
437
|
-
rb_check_frozen(_self);
|
438
470
|
break;
|
439
471
|
default:
|
440
472
|
if (argc != 1) {
|
@@ -453,8 +485,8 @@ static VALUE Message_method_missing(int argc, VALUE* argv, VALUE _self) {
|
|
453
485
|
|
454
486
|
static VALUE Message_respond_to_missing(int argc, VALUE* argv, VALUE _self) {
|
455
487
|
Message* self = ruby_to_Message(_self);
|
456
|
-
const
|
457
|
-
const
|
488
|
+
const upb_OneofDef* o;
|
489
|
+
const upb_FieldDef* f;
|
458
490
|
int accessor_type;
|
459
491
|
|
460
492
|
if (argc < 1) {
|
@@ -472,53 +504,56 @@ static VALUE Message_respond_to_missing(int argc, VALUE* argv, VALUE _self) {
|
|
472
504
|
}
|
473
505
|
}
|
474
506
|
|
475
|
-
void Message_InitFromValue(
|
476
|
-
|
507
|
+
void Message_InitFromValue(upb_Message* msg, const upb_MessageDef* m, VALUE val,
|
508
|
+
upb_Arena* arena);
|
477
509
|
|
478
510
|
typedef struct {
|
479
|
-
|
511
|
+
upb_Map* map;
|
480
512
|
TypeInfo key_type;
|
481
513
|
TypeInfo val_type;
|
482
|
-
|
514
|
+
upb_Arena* arena;
|
483
515
|
} MapInit;
|
484
516
|
|
485
517
|
static int Map_initialize_kwarg(VALUE key, VALUE val, VALUE _self) {
|
486
|
-
MapInit
|
487
|
-
|
518
|
+
MapInit* map_init = (MapInit*)_self;
|
519
|
+
upb_MessageValue k, v;
|
488
520
|
k = Convert_RubyToUpb(key, "", map_init->key_type, NULL);
|
489
521
|
|
490
|
-
if (map_init->val_type.type ==
|
491
|
-
|
522
|
+
if (map_init->val_type.type == kUpb_CType_Message && TYPE(val) == T_HASH) {
|
523
|
+
const upb_MiniTable* t =
|
524
|
+
upb_MessageDef_MiniTable(map_init->val_type.def.msgdef);
|
525
|
+
upb_Message* msg = upb_Message_New(t, map_init->arena);
|
492
526
|
Message_InitFromValue(msg, map_init->val_type.def.msgdef, val,
|
493
527
|
map_init->arena);
|
494
528
|
v.msg_val = msg;
|
495
529
|
} else {
|
496
530
|
v = Convert_RubyToUpb(val, "", map_init->val_type, map_init->arena);
|
497
531
|
}
|
498
|
-
|
532
|
+
upb_Map_Set(map_init->map, k, v, map_init->arena);
|
499
533
|
return ST_CONTINUE;
|
500
534
|
}
|
501
535
|
|
502
|
-
static void Map_InitFromValue(
|
503
|
-
|
504
|
-
const
|
505
|
-
const
|
506
|
-
const
|
536
|
+
static void Map_InitFromValue(upb_Map* map, const upb_FieldDef* f, VALUE val,
|
537
|
+
upb_Arena* arena) {
|
538
|
+
const upb_MessageDef* entry_m = upb_FieldDef_MessageSubDef(f);
|
539
|
+
const upb_FieldDef* key_f = upb_MessageDef_FindFieldByNumber(entry_m, 1);
|
540
|
+
const upb_FieldDef* val_f = upb_MessageDef_FindFieldByNumber(entry_m, 2);
|
507
541
|
if (TYPE(val) != T_HASH) {
|
508
542
|
rb_raise(rb_eArgError,
|
509
543
|
"Expected Hash object as initializer value for map field '%s' "
|
510
544
|
"(given %s).",
|
511
|
-
|
545
|
+
upb_FieldDef_Name(f), rb_class2name(CLASS_OF(val)));
|
512
546
|
}
|
513
547
|
MapInit map_init = {map, TypeInfo_get(key_f), TypeInfo_get(val_f), arena};
|
514
548
|
rb_hash_foreach(val, Map_initialize_kwarg, (VALUE)&map_init);
|
515
549
|
}
|
516
550
|
|
517
|
-
static
|
518
|
-
|
519
|
-
if (info.type ==
|
520
|
-
|
521
|
-
|
551
|
+
static upb_MessageValue MessageValue_FromValue(VALUE val, TypeInfo info,
|
552
|
+
upb_Arena* arena) {
|
553
|
+
if (info.type == kUpb_CType_Message) {
|
554
|
+
upb_MessageValue msgval;
|
555
|
+
const upb_MiniTable* t = upb_MessageDef_MiniTable(info.def.msgdef);
|
556
|
+
upb_Message* msg = upb_Message_New(t, arena);
|
522
557
|
Message_InitFromValue(msg, info.def.msgdef, val, arena);
|
523
558
|
msgval.msg_val = msg;
|
524
559
|
return msgval;
|
@@ -527,61 +562,62 @@ static upb_msgval MessageValue_FromValue(VALUE val, TypeInfo info,
|
|
527
562
|
}
|
528
563
|
}
|
529
564
|
|
530
|
-
static void RepeatedField_InitFromValue(
|
531
|
-
VALUE val,
|
565
|
+
static void RepeatedField_InitFromValue(upb_Array* arr, const upb_FieldDef* f,
|
566
|
+
VALUE val, upb_Arena* arena) {
|
532
567
|
TypeInfo type_info = TypeInfo_get(f);
|
533
568
|
|
534
569
|
if (TYPE(val) != T_ARRAY) {
|
535
570
|
rb_raise(rb_eArgError,
|
536
|
-
"Expected array as initializer value for repeated field '%s'
|
537
|
-
|
571
|
+
"Expected array as initializer value for repeated field '%s' "
|
572
|
+
"(given %s).",
|
573
|
+
upb_FieldDef_Name(f), rb_class2name(CLASS_OF(val)));
|
538
574
|
}
|
539
575
|
|
540
576
|
for (int i = 0; i < RARRAY_LEN(val); i++) {
|
541
577
|
VALUE entry = rb_ary_entry(val, i);
|
542
|
-
|
543
|
-
if (
|
578
|
+
upb_MessageValue msgval;
|
579
|
+
if (upb_FieldDef_IsSubMessage(f) && TYPE(entry) == T_HASH) {
|
544
580
|
msgval = MessageValue_FromValue(entry, type_info, arena);
|
545
581
|
} else {
|
546
|
-
msgval = Convert_RubyToUpb(entry,
|
582
|
+
msgval = Convert_RubyToUpb(entry, upb_FieldDef_Name(f), type_info, arena);
|
547
583
|
}
|
548
|
-
|
584
|
+
upb_Array_Append(arr, msgval, arena);
|
549
585
|
}
|
550
586
|
}
|
551
587
|
|
552
|
-
static void Message_InitFieldFromValue(
|
553
|
-
VALUE val,
|
588
|
+
static void Message_InitFieldFromValue(upb_Message* msg, const upb_FieldDef* f,
|
589
|
+
VALUE val, upb_Arena* arena) {
|
554
590
|
if (TYPE(val) == T_NIL) return;
|
555
591
|
|
556
|
-
if (
|
557
|
-
|
592
|
+
if (upb_FieldDef_IsMap(f)) {
|
593
|
+
upb_Map* map = upb_Message_Mutable(msg, f, arena).map;
|
558
594
|
Map_InitFromValue(map, f, val, arena);
|
559
|
-
} else if (
|
560
|
-
|
595
|
+
} else if (upb_FieldDef_Label(f) == kUpb_Label_Repeated) {
|
596
|
+
upb_Array* arr = upb_Message_Mutable(msg, f, arena).array;
|
561
597
|
RepeatedField_InitFromValue(arr, f, val, arena);
|
562
|
-
} else if (
|
598
|
+
} else if (upb_FieldDef_IsSubMessage(f)) {
|
563
599
|
if (TYPE(val) == T_HASH) {
|
564
|
-
|
565
|
-
Message_InitFromValue(submsg,
|
600
|
+
upb_Message* submsg = upb_Message_Mutable(msg, f, arena).msg;
|
601
|
+
Message_InitFromValue(submsg, upb_FieldDef_MessageSubDef(f), val, arena);
|
566
602
|
} else {
|
567
603
|
Message_setfield(msg, f, val, arena);
|
568
604
|
}
|
569
605
|
} else {
|
570
|
-
|
571
|
-
Convert_RubyToUpb(val,
|
572
|
-
|
606
|
+
upb_MessageValue msgval =
|
607
|
+
Convert_RubyToUpb(val, upb_FieldDef_Name(f), TypeInfo_get(f), arena);
|
608
|
+
upb_Message_SetFieldByDef(msg, f, msgval, arena);
|
573
609
|
}
|
574
610
|
}
|
575
611
|
|
576
612
|
typedef struct {
|
577
|
-
|
578
|
-
const
|
579
|
-
|
613
|
+
upb_Message* msg;
|
614
|
+
const upb_MessageDef* msgdef;
|
615
|
+
upb_Arena* arena;
|
580
616
|
} MsgInit;
|
581
617
|
|
582
618
|
static int Message_initialize_kwarg(VALUE key, VALUE val, VALUE _self) {
|
583
|
-
MsgInit
|
584
|
-
const char
|
619
|
+
MsgInit* msg_init = (MsgInit*)_self;
|
620
|
+
const char* name;
|
585
621
|
|
586
622
|
if (TYPE(key) == T_STRING) {
|
587
623
|
name = RSTRING_PTR(key);
|
@@ -589,10 +625,12 @@ static int Message_initialize_kwarg(VALUE key, VALUE val, VALUE _self) {
|
|
589
625
|
name = RSTRING_PTR(rb_id2str(SYM2ID(key)));
|
590
626
|
} else {
|
591
627
|
rb_raise(rb_eArgError,
|
592
|
-
"Expected string or symbols as hash keys when initializing proto
|
628
|
+
"Expected string or symbols as hash keys when initializing proto "
|
629
|
+
"from hash.");
|
593
630
|
}
|
594
631
|
|
595
|
-
const
|
632
|
+
const upb_FieldDef* f =
|
633
|
+
upb_MessageDef_FindFieldByName(msg_init->msgdef, name);
|
596
634
|
|
597
635
|
if (f == NULL) {
|
598
636
|
rb_raise(rb_eArgError,
|
@@ -603,8 +641,8 @@ static int Message_initialize_kwarg(VALUE key, VALUE val, VALUE _self) {
|
|
603
641
|
return ST_CONTINUE;
|
604
642
|
}
|
605
643
|
|
606
|
-
void Message_InitFromValue(
|
607
|
-
|
644
|
+
void Message_InitFromValue(upb_Message* msg, const upb_MessageDef* m, VALUE val,
|
645
|
+
upb_Arena* arena) {
|
608
646
|
MsgInit msg_init = {msg, m, arena};
|
609
647
|
if (TYPE(val) == T_HASH) {
|
610
648
|
rb_hash_foreach(val, Message_initialize_kwarg, (VALUE)&msg_init);
|
@@ -629,8 +667,9 @@ void Message_InitFromValue(upb_msg* msg, const upb_msgdef* m, VALUE val,
|
|
629
667
|
static VALUE Message_initialize(int argc, VALUE* argv, VALUE _self) {
|
630
668
|
Message* self = ruby_to_Message(_self);
|
631
669
|
VALUE arena_rb = Arena_new();
|
632
|
-
|
633
|
-
|
670
|
+
upb_Arena* arena = Arena_get(arena_rb);
|
671
|
+
const upb_MiniTable* t = upb_MessageDef_MiniTable(self->msgdef);
|
672
|
+
upb_Message* msg = upb_Message_New(t, arena);
|
634
673
|
|
635
674
|
Message_InitPtr(_self, msg, arena_rb);
|
636
675
|
|
@@ -640,7 +679,7 @@ static VALUE Message_initialize(int argc, VALUE* argv, VALUE _self) {
|
|
640
679
|
if (argc != 1) {
|
641
680
|
rb_raise(rb_eArgError, "Expected 0 or 1 arguments.");
|
642
681
|
}
|
643
|
-
Message_InitFromValue((
|
682
|
+
Message_InitFromValue((upb_Message*)self->msg, self->msgdef, argv[0], arena);
|
644
683
|
return Qnil;
|
645
684
|
}
|
646
685
|
|
@@ -654,38 +693,12 @@ static VALUE Message_dup(VALUE _self) {
|
|
654
693
|
Message* self = ruby_to_Message(_self);
|
655
694
|
VALUE new_msg = rb_class_new_instance(0, NULL, CLASS_OF(_self));
|
656
695
|
Message* new_msg_self = ruby_to_Message(new_msg);
|
657
|
-
|
658
|
-
|
659
|
-
// TODO(copy unknown fields?)
|
660
|
-
// TODO(use official upb msg copy function)
|
661
|
-
memcpy((upb_msg*)new_msg_self->msg, self->msg, size);
|
696
|
+
const upb_MiniTable* m = upb_MessageDef_MiniTable(self->msgdef);
|
697
|
+
upb_Message_ShallowCopy((upb_Message*)new_msg_self->msg, self->msg, m);
|
662
698
|
Arena_fuse(self->arena, Arena_get(new_msg_self->arena));
|
663
699
|
return new_msg;
|
664
700
|
}
|
665
701
|
|
666
|
-
// Support function for Message_eq, and also used by other #eq functions.
|
667
|
-
bool Message_Equal(const upb_msg *m1, const upb_msg *m2, const upb_msgdef *m) {
|
668
|
-
if (m1 == m2) return true;
|
669
|
-
|
670
|
-
size_t size1, size2;
|
671
|
-
int encode_opts = UPB_ENCODE_SKIPUNKNOWN | UPB_ENCODE_DETERMINISTIC;
|
672
|
-
upb_arena *arena_tmp = upb_arena_new();
|
673
|
-
const upb_msglayout *layout = upb_msgdef_layout(m);
|
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;
|
683
|
-
} else {
|
684
|
-
upb_arena_free(arena_tmp);
|
685
|
-
rb_raise(cParseError, "Error comparing messages");
|
686
|
-
}
|
687
|
-
}
|
688
|
-
|
689
702
|
/*
|
690
703
|
* call-seq:
|
691
704
|
* Message.==(other) => boolean
|
@@ -702,26 +715,22 @@ static VALUE Message_eq(VALUE _self, VALUE _other) {
|
|
702
715
|
Message* other = ruby_to_Message(_other);
|
703
716
|
assert(self->msgdef == other->msgdef);
|
704
717
|
|
705
|
-
|
718
|
+
const upb_MiniTable* m = upb_MessageDef_MiniTable(self->msgdef);
|
719
|
+
const int options = 0;
|
720
|
+
return upb_Message_IsEqual(self->msg, other->msg, m, options) ? Qtrue
|
721
|
+
: Qfalse;
|
706
722
|
}
|
707
723
|
|
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;
|
724
|
+
uint64_t Message_Hash(const upb_Message* msg, const upb_MessageDef* m,
|
725
|
+
uint64_t seed) {
|
726
|
+
upb_Status status;
|
727
|
+
upb_Status_Clear(&status);
|
728
|
+
uint64_t return_value = shared_Message_Hash(msg, m, seed, &status);
|
729
|
+
if (upb_Status_IsOk(&status)) {
|
730
|
+
return return_value;
|
722
731
|
} else {
|
723
|
-
|
724
|
-
|
732
|
+
rb_raise(cParseError, "Message_Hash(): %s",
|
733
|
+
upb_Status_ErrorMessage(&status));
|
725
734
|
}
|
726
735
|
}
|
727
736
|
|
@@ -759,13 +768,13 @@ static VALUE Message_inspect(VALUE _self) {
|
|
759
768
|
|
760
769
|
// Support functions for Message_to_h //////////////////////////////////////////
|
761
770
|
|
762
|
-
static VALUE RepeatedField_CreateArray(const
|
771
|
+
static VALUE RepeatedField_CreateArray(const upb_Array* arr,
|
763
772
|
TypeInfo type_info) {
|
764
|
-
int size = arr ?
|
773
|
+
int size = arr ? upb_Array_Size(arr) : 0;
|
765
774
|
VALUE ary = rb_ary_new2(size);
|
766
775
|
|
767
776
|
for (int i = 0; i < size; i++) {
|
768
|
-
|
777
|
+
upb_MessageValue msgval = upb_Array_Get(arr, i);
|
769
778
|
VALUE val = Scalar_CreateHash(msgval, type_info);
|
770
779
|
rb_ary_push(ary, val);
|
771
780
|
}
|
@@ -773,69 +782,47 @@ static VALUE RepeatedField_CreateArray(const upb_array* arr,
|
|
773
782
|
return ary;
|
774
783
|
}
|
775
784
|
|
776
|
-
static VALUE Message_CreateHash(const
|
785
|
+
static VALUE Message_CreateHash(const upb_Message* msg,
|
786
|
+
const upb_MessageDef* m) {
|
777
787
|
if (!msg) return Qnil;
|
778
788
|
|
779
789
|
VALUE hash = rb_hash_new();
|
780
|
-
|
781
|
-
|
782
|
-
|
783
|
-
|
784
|
-
|
785
|
-
|
786
|
-
|
787
|
-
|
788
|
-
|
789
|
-
for (int i = 0; i < n; i++) {
|
790
|
-
const upb_fielddef* field = upb_msgdef_field(m, i);
|
791
|
-
TypeInfo type_info = TypeInfo_get(field);
|
792
|
-
upb_msgval msgval;
|
793
|
-
VALUE msg_value;
|
794
|
-
VALUE msg_key;
|
795
|
-
|
796
|
-
if (!is_proto2 && upb_fielddef_issubmsg(field) &&
|
797
|
-
!upb_fielddef_isseq(field) && !upb_msg_has(msg, field)) {
|
798
|
-
// TODO: Legacy behavior, remove when we fix the is_proto2 differences.
|
799
|
-
msg_key = ID2SYM(rb_intern(upb_fielddef_name(field)));
|
800
|
-
rb_hash_aset(hash, msg_key, Qnil);
|
790
|
+
size_t iter = kUpb_Message_Begin;
|
791
|
+
const upb_DefPool* pool = upb_FileDef_Pool(upb_MessageDef_File(m));
|
792
|
+
const upb_FieldDef* field;
|
793
|
+
upb_MessageValue val;
|
794
|
+
|
795
|
+
while (upb_Message_Next(msg, m, pool, &field, &val, &iter)) {
|
796
|
+
if (upb_FieldDef_IsExtension(field)) {
|
797
|
+
// TODO: allow extensions once we have decided what naming scheme the
|
798
|
+
// symbol should use. eg. :"[pkg.ext]"
|
801
799
|
continue;
|
802
800
|
}
|
803
801
|
|
804
|
-
|
805
|
-
|
806
|
-
!upb_msg_has(msg, field)) {
|
807
|
-
continue;
|
808
|
-
}
|
802
|
+
TypeInfo type_info = TypeInfo_get(field);
|
803
|
+
VALUE msg_value;
|
809
804
|
|
810
|
-
|
811
|
-
|
812
|
-
|
813
|
-
|
814
|
-
|
815
|
-
|
816
|
-
|
817
|
-
|
818
|
-
const upb_fielddef *val_f = upb_msgdef_itof(entry_m, 2);
|
819
|
-
upb_fieldtype_t key_type = upb_fielddef_type(key_f);
|
820
|
-
msg_value = Map_CreateHash(msgval.map_val, key_type, TypeInfo_get(val_f));
|
821
|
-
} else if (upb_fielddef_isseq(field)) {
|
822
|
-
if (is_proto2 &&
|
823
|
-
(!msgval.array_val || upb_array_size(msgval.array_val) == 0)) {
|
824
|
-
continue;
|
825
|
-
}
|
826
|
-
msg_value = RepeatedField_CreateArray(msgval.array_val, type_info);
|
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);
|
810
|
+
msg_value = Map_CreateHash(val.map_val, key_type, TypeInfo_get(val_f));
|
811
|
+
} else if (upb_FieldDef_IsRepeated(field)) {
|
812
|
+
msg_value = RepeatedField_CreateArray(val.array_val, type_info);
|
827
813
|
} else {
|
828
|
-
msg_value = Scalar_CreateHash(
|
814
|
+
msg_value = Scalar_CreateHash(val, type_info);
|
829
815
|
}
|
830
816
|
|
817
|
+
VALUE msg_key = ID2SYM(rb_intern(upb_FieldDef_Name(field)));
|
831
818
|
rb_hash_aset(hash, msg_key, msg_value);
|
832
819
|
}
|
833
820
|
|
834
821
|
return hash;
|
835
822
|
}
|
836
823
|
|
837
|
-
VALUE Scalar_CreateHash(
|
838
|
-
if (type_info.type ==
|
824
|
+
VALUE Scalar_CreateHash(upb_MessageValue msgval, TypeInfo type_info) {
|
825
|
+
if (type_info.type == kUpb_CType_Message) {
|
839
826
|
return Message_CreateHash(msgval.msg_val, type_info.def.msgdef);
|
840
827
|
} else {
|
841
828
|
return Convert_UpbToRuby(msgval, type_info, Qnil);
|
@@ -853,19 +840,44 @@ static VALUE Message_to_h(VALUE _self) {
|
|
853
840
|
return Message_CreateHash(self->msg, self->msgdef);
|
854
841
|
}
|
855
842
|
|
843
|
+
/*
|
844
|
+
* call-seq:
|
845
|
+
* Message.frozen? => bool
|
846
|
+
*
|
847
|
+
* Returns true if the message is frozen in either Ruby or the underlying
|
848
|
+
* representation. Freezes the Ruby message object if it is not already frozen
|
849
|
+
* in Ruby but it is frozen in the underlying representation.
|
850
|
+
*/
|
851
|
+
VALUE Message_frozen(VALUE _self) {
|
852
|
+
Message* self = ruby_to_Message(_self);
|
853
|
+
if (!upb_Message_IsFrozen(self->msg)) {
|
854
|
+
PBRUBY_ASSERT(!RB_OBJ_FROZEN(_self));
|
855
|
+
return Qfalse;
|
856
|
+
}
|
857
|
+
|
858
|
+
// Lazily freeze the Ruby wrapper.
|
859
|
+
if (!RB_OBJ_FROZEN(_self)) RB_OBJ_FREEZE(_self);
|
860
|
+
return Qtrue;
|
861
|
+
}
|
862
|
+
|
856
863
|
/*
|
857
864
|
* call-seq:
|
858
865
|
* Message.freeze => self
|
859
866
|
*
|
860
|
-
* Freezes the message object. We have to intercept this so we can
|
861
|
-
*
|
867
|
+
* Freezes the message object. We have to intercept this so we can freeze the
|
868
|
+
* underlying representation, not just the Ruby wrapper.
|
862
869
|
*/
|
863
|
-
|
870
|
+
VALUE Message_freeze(VALUE _self) {
|
864
871
|
Message* self = ruby_to_Message(_self);
|
865
|
-
if (
|
866
|
-
|
867
|
-
|
872
|
+
if (RB_OBJ_FROZEN(_self)) {
|
873
|
+
PBRUBY_ASSERT(upb_Message_IsFrozen(self->msg));
|
874
|
+
return _self;
|
875
|
+
}
|
876
|
+
if (!upb_Message_IsFrozen(self->msg)) {
|
877
|
+
upb_Message_Freeze(Message_GetMutable(_self, NULL),
|
878
|
+
upb_MessageDef_MiniTable(self->msgdef));
|
868
879
|
}
|
880
|
+
RB_OBJ_FREEZE(_self);
|
869
881
|
return _self;
|
870
882
|
}
|
871
883
|
|
@@ -878,10 +890,10 @@ static VALUE Message_freeze(VALUE _self) {
|
|
878
890
|
*/
|
879
891
|
static VALUE Message_index(VALUE _self, VALUE field_name) {
|
880
892
|
Message* self = ruby_to_Message(_self);
|
881
|
-
const
|
893
|
+
const upb_FieldDef* field;
|
882
894
|
|
883
895
|
Check_Type(field_name, T_STRING);
|
884
|
-
field =
|
896
|
+
field = upb_MessageDef_FindFieldByName(self->msgdef, RSTRING_PTR(field_name));
|
885
897
|
|
886
898
|
if (field == NULL) {
|
887
899
|
return Qnil;
|
@@ -899,45 +911,80 @@ static VALUE Message_index(VALUE _self, VALUE field_name) {
|
|
899
911
|
*/
|
900
912
|
static VALUE Message_index_set(VALUE _self, VALUE field_name, VALUE value) {
|
901
913
|
Message* self = ruby_to_Message(_self);
|
902
|
-
const
|
903
|
-
|
904
|
-
|
914
|
+
const upb_FieldDef* f;
|
915
|
+
upb_MessageValue val;
|
916
|
+
upb_Arena* arena = Arena_get(self->arena);
|
905
917
|
|
906
918
|
Check_Type(field_name, T_STRING);
|
907
|
-
f =
|
919
|
+
f = upb_MessageDef_FindFieldByName(self->msgdef, RSTRING_PTR(field_name));
|
908
920
|
|
909
921
|
if (f == NULL) {
|
910
922
|
rb_raise(rb_eArgError, "Unknown field: %s", RSTRING_PTR(field_name));
|
911
923
|
}
|
912
924
|
|
913
|
-
val = Convert_RubyToUpb(value,
|
914
|
-
|
925
|
+
val = Convert_RubyToUpb(value, upb_FieldDef_Name(f), TypeInfo_get(f), arena);
|
926
|
+
upb_Message_SetFieldByDef(Message_GetMutable(_self, NULL), f, val, arena);
|
915
927
|
|
916
928
|
return Qnil;
|
917
929
|
}
|
918
930
|
|
919
931
|
/*
|
920
932
|
* call-seq:
|
921
|
-
* MessageClass.decode(data) => message
|
933
|
+
* MessageClass.decode(data, options) => message
|
922
934
|
*
|
923
935
|
* Decodes the given data (as a string containing bytes in protocol buffers wire
|
924
|
-
* format) under the
|
936
|
+
* format) under the interpretation given by this message class's definition
|
925
937
|
* and returns a message object with the corresponding field values.
|
938
|
+
* @param options [Hash] options for the decoder
|
939
|
+
* recursion_limit: set to maximum decoding depth for message (default is 64)
|
926
940
|
*/
|
927
|
-
static VALUE Message_decode(VALUE
|
941
|
+
static VALUE Message_decode(int argc, VALUE* argv, VALUE klass) {
|
942
|
+
VALUE data = argv[0];
|
943
|
+
int options = 0;
|
944
|
+
|
945
|
+
if (argc < 1 || argc > 2) {
|
946
|
+
rb_raise(rb_eArgError, "Expected 1 or 2 arguments.");
|
947
|
+
}
|
948
|
+
|
949
|
+
if (argc == 2) {
|
950
|
+
VALUE hash_args = argv[1];
|
951
|
+
if (TYPE(hash_args) != T_HASH) {
|
952
|
+
rb_raise(rb_eArgError, "Expected hash arguments.");
|
953
|
+
}
|
954
|
+
|
955
|
+
VALUE depth =
|
956
|
+
rb_hash_lookup(hash_args, ID2SYM(rb_intern("recursion_limit")));
|
957
|
+
|
958
|
+
if (depth != Qnil && TYPE(depth) == T_FIXNUM) {
|
959
|
+
options |= upb_DecodeOptions_MaxDepth(FIX2INT(depth));
|
960
|
+
}
|
961
|
+
}
|
962
|
+
|
928
963
|
if (TYPE(data) != T_STRING) {
|
929
964
|
rb_raise(rb_eArgError, "Expected string for binary protobuf data.");
|
930
965
|
}
|
931
966
|
|
967
|
+
return Message_decode_bytes(RSTRING_LEN(data), RSTRING_PTR(data), options,
|
968
|
+
klass, /*freeze*/ false);
|
969
|
+
}
|
970
|
+
|
971
|
+
VALUE Message_decode_bytes(int size, const char* bytes, int options,
|
972
|
+
VALUE klass, bool freeze) {
|
932
973
|
VALUE msg_rb = initialize_rb_class_with_no_args(klass);
|
933
974
|
Message* msg = ruby_to_Message(msg_rb);
|
934
975
|
|
935
|
-
|
936
|
-
|
937
|
-
|
976
|
+
const upb_FileDef* file = upb_MessageDef_File(msg->msgdef);
|
977
|
+
const upb_ExtensionRegistry* extreg =
|
978
|
+
upb_DefPool_ExtensionRegistry(upb_FileDef_Pool(file));
|
979
|
+
upb_DecodeStatus status = upb_Decode(bytes, size, (upb_Message*)msg->msg,
|
980
|
+
upb_MessageDef_MiniTable(msg->msgdef),
|
981
|
+
extreg, options, Arena_get(msg->arena));
|
982
|
+
if (status != kUpb_DecodeStatus_Ok) {
|
938
983
|
rb_raise(cParseError, "Error occurred during parsing");
|
939
984
|
}
|
940
|
-
|
985
|
+
if (freeze) {
|
986
|
+
Message_freeze(msg_rb);
|
987
|
+
}
|
941
988
|
return msg_rb;
|
942
989
|
}
|
943
990
|
|
@@ -956,10 +1003,7 @@ static VALUE Message_decode(VALUE klass, VALUE data) {
|
|
956
1003
|
static VALUE Message_decode_json(int argc, VALUE* argv, VALUE klass) {
|
957
1004
|
VALUE data = argv[0];
|
958
1005
|
int options = 0;
|
959
|
-
|
960
|
-
|
961
|
-
// TODO(haberman): use this message's pool instead.
|
962
|
-
const upb_symtab *symtab = DescriptorPool_GetSymtab(generated_pool);
|
1006
|
+
upb_Status status;
|
963
1007
|
|
964
1008
|
if (argc < 1 || argc > 2) {
|
965
1009
|
rb_raise(rb_eArgError, "Expected 1 or 2 arguments.");
|
@@ -971,8 +1015,9 @@ static VALUE Message_decode_json(int argc, VALUE* argv, VALUE klass) {
|
|
971
1015
|
rb_raise(rb_eArgError, "Expected hash arguments.");
|
972
1016
|
}
|
973
1017
|
|
974
|
-
if (RTEST(rb_hash_lookup2(
|
975
|
-
|
1018
|
+
if (RTEST(rb_hash_lookup2(
|
1019
|
+
hash_args, ID2SYM(rb_intern("ignore_unknown_fields")), Qfalse))) {
|
1020
|
+
options |= upb_JsonDecode_IgnoreUnknown;
|
976
1021
|
}
|
977
1022
|
}
|
978
1023
|
|
@@ -980,7 +1025,7 @@ static VALUE Message_decode_json(int argc, VALUE* argv, VALUE klass) {
|
|
980
1025
|
rb_raise(rb_eArgError, "Expected string for JSON data.");
|
981
1026
|
}
|
982
1027
|
|
983
|
-
// TODO
|
1028
|
+
// TODO: Check and respect string encoding. If not UTF-8, we need to
|
984
1029
|
// convert, because string handlers pass data directly to message string
|
985
1030
|
// fields.
|
986
1031
|
|
@@ -988,16 +1033,24 @@ static VALUE Message_decode_json(int argc, VALUE* argv, VALUE klass) {
|
|
988
1033
|
Message* msg = ruby_to_Message(msg_rb);
|
989
1034
|
|
990
1035
|
// We don't allow users to decode a wrapper type directly.
|
991
|
-
if (
|
1036
|
+
if (IsWrapper(msg->msgdef)) {
|
992
1037
|
rb_raise(rb_eRuntimeError, "Cannot parse a wrapper directly.");
|
993
1038
|
}
|
994
1039
|
|
995
|
-
|
996
|
-
|
997
|
-
|
998
|
-
|
999
|
-
|
1000
|
-
|
1040
|
+
upb_Status_Clear(&status);
|
1041
|
+
const upb_DefPool* pool = upb_FileDef_Pool(upb_MessageDef_File(msg->msgdef));
|
1042
|
+
|
1043
|
+
int result = upb_JsonDecodeDetectingNonconformance(
|
1044
|
+
RSTRING_PTR(data), RSTRING_LEN(data), (upb_Message*)msg->msg,
|
1045
|
+
msg->msgdef, pool, options, Arena_get(msg->arena), &status);
|
1046
|
+
|
1047
|
+
switch (result) {
|
1048
|
+
case kUpb_JsonDecodeResult_Ok:
|
1049
|
+
break;
|
1050
|
+
case kUpb_JsonDecodeResult_Error:
|
1051
|
+
rb_raise(cParseError, "Error occurred during parsing: %s",
|
1052
|
+
upb_Status_ErrorMessage(&status));
|
1053
|
+
break;
|
1001
1054
|
}
|
1002
1055
|
|
1003
1056
|
return msg_rb;
|
@@ -1005,32 +1058,53 @@ static VALUE Message_decode_json(int argc, VALUE* argv, VALUE klass) {
|
|
1005
1058
|
|
1006
1059
|
/*
|
1007
1060
|
* call-seq:
|
1008
|
-
* MessageClass.encode(msg) => bytes
|
1061
|
+
* MessageClass.encode(msg, options) => bytes
|
1009
1062
|
*
|
1010
1063
|
* Encodes the given message object to its serialized form in protocol buffers
|
1011
1064
|
* wire format.
|
1065
|
+
* @param options [Hash] options for the encoder
|
1066
|
+
* recursion_limit: set to maximum encoding depth for message (default is 64)
|
1012
1067
|
*/
|
1013
|
-
static VALUE Message_encode(VALUE
|
1014
|
-
Message* msg = ruby_to_Message(
|
1015
|
-
|
1068
|
+
static VALUE Message_encode(int argc, VALUE* argv, VALUE klass) {
|
1069
|
+
Message* msg = ruby_to_Message(argv[0]);
|
1070
|
+
int options = 0;
|
1071
|
+
char* data;
|
1016
1072
|
size_t size;
|
1017
1073
|
|
1018
|
-
if (CLASS_OF(
|
1074
|
+
if (CLASS_OF(argv[0]) != klass) {
|
1019
1075
|
rb_raise(rb_eArgError, "Message of wrong type.");
|
1020
1076
|
}
|
1021
1077
|
|
1022
|
-
|
1078
|
+
if (argc < 1 || argc > 2) {
|
1079
|
+
rb_raise(rb_eArgError, "Expected 1 or 2 arguments.");
|
1080
|
+
}
|
1023
1081
|
|
1024
|
-
|
1025
|
-
|
1082
|
+
if (argc == 2) {
|
1083
|
+
VALUE hash_args = argv[1];
|
1084
|
+
if (TYPE(hash_args) != T_HASH) {
|
1085
|
+
rb_raise(rb_eArgError, "Expected hash arguments.");
|
1086
|
+
}
|
1087
|
+
VALUE depth =
|
1088
|
+
rb_hash_lookup(hash_args, ID2SYM(rb_intern("recursion_limit")));
|
1089
|
+
|
1090
|
+
if (depth != Qnil && TYPE(depth) == T_FIXNUM) {
|
1091
|
+
options |= upb_DecodeOptions_MaxDepth(FIX2INT(depth));
|
1092
|
+
}
|
1093
|
+
}
|
1094
|
+
|
1095
|
+
upb_Arena* arena = upb_Arena_New();
|
1096
|
+
|
1097
|
+
upb_EncodeStatus status =
|
1098
|
+
upb_Encode(msg->msg, upb_MessageDef_MiniTable(msg->msgdef), options,
|
1099
|
+
arena, &data, &size);
|
1026
1100
|
|
1027
|
-
if (
|
1101
|
+
if (status == kUpb_EncodeStatus_Ok) {
|
1028
1102
|
VALUE ret = rb_str_new(data, size);
|
1029
1103
|
rb_enc_associate(ret, rb_ascii8bit_encoding());
|
1030
|
-
|
1104
|
+
upb_Arena_Free(arena);
|
1031
1105
|
return ret;
|
1032
1106
|
} else {
|
1033
|
-
|
1107
|
+
upb_Arena_Free(arena);
|
1034
1108
|
rb_raise(rb_eRuntimeError, "Exceeded maximum depth (possibly cycle)");
|
1035
1109
|
}
|
1036
1110
|
}
|
@@ -1041,18 +1115,16 @@ static VALUE Message_encode(VALUE klass, VALUE msg_rb) {
|
|
1041
1115
|
*
|
1042
1116
|
* Encodes the given message object into its serialized JSON representation.
|
1043
1117
|
* @param options [Hash] options for the decoder
|
1044
|
-
* preserve_proto_fieldnames: set true to use original fieldnames (default is
|
1045
|
-
*
|
1118
|
+
* preserve_proto_fieldnames: set true to use original fieldnames (default is
|
1119
|
+
* to camelCase) emit_defaults: set true to emit 0/false values (default is to
|
1120
|
+
* omit them)
|
1046
1121
|
*/
|
1047
1122
|
static VALUE Message_encode_json(int argc, VALUE* argv, VALUE klass) {
|
1048
1123
|
Message* msg = ruby_to_Message(argv[0]);
|
1049
1124
|
int options = 0;
|
1050
1125
|
char buf[1024];
|
1051
1126
|
size_t size;
|
1052
|
-
|
1053
|
-
|
1054
|
-
// TODO(haberman): use this message's pool instead.
|
1055
|
-
const upb_symtab *symtab = DescriptorPool_GetSymtab(generated_pool);
|
1127
|
+
upb_Status status;
|
1056
1128
|
|
1057
1129
|
if (argc < 1 || argc > 2) {
|
1058
1130
|
rb_raise(rb_eArgError, "Expected 1 or 2 arguments.");
|
@@ -1061,35 +1133,47 @@ static VALUE Message_encode_json(int argc, VALUE* argv, VALUE klass) {
|
|
1061
1133
|
if (argc == 2) {
|
1062
1134
|
VALUE hash_args = argv[1];
|
1063
1135
|
if (TYPE(hash_args) != T_HASH) {
|
1064
|
-
|
1136
|
+
if (RTEST(rb_funcall(hash_args, rb_intern("respond_to?"), 1,
|
1137
|
+
rb_str_new2("to_h")))) {
|
1138
|
+
hash_args = rb_funcall(hash_args, rb_intern("to_h"), 0);
|
1139
|
+
} else {
|
1140
|
+
rb_raise(rb_eArgError, "Expected hash arguments.");
|
1141
|
+
}
|
1065
1142
|
}
|
1066
1143
|
|
1067
1144
|
if (RTEST(rb_hash_lookup2(hash_args,
|
1068
1145
|
ID2SYM(rb_intern("preserve_proto_fieldnames")),
|
1069
1146
|
Qfalse))) {
|
1070
|
-
options |=
|
1147
|
+
options |= upb_JsonEncode_UseProtoNames;
|
1071
1148
|
}
|
1072
1149
|
|
1073
1150
|
if (RTEST(rb_hash_lookup2(hash_args, ID2SYM(rb_intern("emit_defaults")),
|
1074
1151
|
Qfalse))) {
|
1075
|
-
options |=
|
1152
|
+
options |= upb_JsonEncode_EmitDefaults;
|
1153
|
+
}
|
1154
|
+
|
1155
|
+
if (RTEST(rb_hash_lookup2(hash_args,
|
1156
|
+
ID2SYM(rb_intern("format_enums_as_integers")),
|
1157
|
+
Qfalse))) {
|
1158
|
+
options |= upb_JsonEncode_FormatEnumsAsIntegers;
|
1076
1159
|
}
|
1077
1160
|
}
|
1078
1161
|
|
1079
|
-
|
1080
|
-
|
1081
|
-
|
1162
|
+
upb_Status_Clear(&status);
|
1163
|
+
const upb_DefPool* pool = upb_FileDef_Pool(upb_MessageDef_File(msg->msgdef));
|
1164
|
+
size = upb_JsonEncode(msg->msg, msg->msgdef, pool, options, buf, sizeof(buf),
|
1165
|
+
&status);
|
1082
1166
|
|
1083
|
-
if (!
|
1167
|
+
if (!upb_Status_IsOk(&status)) {
|
1084
1168
|
rb_raise(cParseError, "Error occurred during encoding: %s",
|
1085
|
-
|
1169
|
+
upb_Status_ErrorMessage(&status));
|
1086
1170
|
}
|
1087
1171
|
|
1088
1172
|
VALUE ret;
|
1089
1173
|
if (size >= sizeof(buf)) {
|
1090
1174
|
char* buf2 = malloc(size + 1);
|
1091
|
-
|
1092
|
-
|
1175
|
+
upb_JsonEncode(msg->msg, msg->msgdef, pool, options, buf2, size + 1,
|
1176
|
+
&status);
|
1093
1177
|
ret = rb_str_new(buf2, size);
|
1094
1178
|
free(buf2);
|
1095
1179
|
} else {
|
@@ -1112,10 +1196,10 @@ static VALUE Message_descriptor(VALUE klass) {
|
|
1112
1196
|
}
|
1113
1197
|
|
1114
1198
|
VALUE build_class_from_descriptor(VALUE descriptor) {
|
1115
|
-
const char
|
1199
|
+
const char* name;
|
1116
1200
|
VALUE klass;
|
1117
1201
|
|
1118
|
-
name =
|
1202
|
+
name = upb_MessageDef_FullName(Descriptor_GetMsgDef(descriptor));
|
1119
1203
|
if (name == NULL) {
|
1120
1204
|
rb_raise(rb_eRuntimeError, "Descriptor does not have assigned name.");
|
1121
1205
|
}
|
@@ -1123,38 +1207,8 @@ VALUE build_class_from_descriptor(VALUE descriptor) {
|
|
1123
1207
|
klass = rb_define_class_id(
|
1124
1208
|
// Docs say this parameter is ignored. User will assign return value to
|
1125
1209
|
// their own toplevel constant class name.
|
1126
|
-
rb_intern("Message"),
|
1127
|
-
rb_cObject);
|
1210
|
+
rb_intern("Message"), cAbstractMessage);
|
1128
1211
|
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
1212
|
return klass;
|
1159
1213
|
}
|
1160
1214
|
|
@@ -1168,13 +1222,12 @@ VALUE build_class_from_descriptor(VALUE descriptor) {
|
|
1168
1222
|
static VALUE enum_lookup(VALUE self, VALUE number) {
|
1169
1223
|
int32_t num = NUM2INT(number);
|
1170
1224
|
VALUE desc = rb_ivar_get(self, descriptor_instancevar_interned);
|
1171
|
-
const
|
1172
|
-
|
1173
|
-
|
1174
|
-
|
1175
|
-
return Qnil;
|
1225
|
+
const upb_EnumDef* e = EnumDescriptor_GetEnumDef(desc);
|
1226
|
+
const upb_EnumValueDef* ev = upb_EnumDef_FindValueByNumber(e, num);
|
1227
|
+
if (ev) {
|
1228
|
+
return ID2SYM(rb_intern(upb_EnumValueDef_Name(ev)));
|
1176
1229
|
} else {
|
1177
|
-
return
|
1230
|
+
return Qnil;
|
1178
1231
|
}
|
1179
1232
|
}
|
1180
1233
|
|
@@ -1188,14 +1241,12 @@ static VALUE enum_lookup(VALUE self, VALUE number) {
|
|
1188
1241
|
static VALUE enum_resolve(VALUE self, VALUE sym) {
|
1189
1242
|
const char* name = rb_id2name(SYM2ID(sym));
|
1190
1243
|
VALUE desc = rb_ivar_get(self, descriptor_instancevar_interned);
|
1191
|
-
const
|
1192
|
-
|
1193
|
-
|
1194
|
-
|
1195
|
-
if (!found) {
|
1196
|
-
return Qnil;
|
1244
|
+
const upb_EnumDef* e = EnumDescriptor_GetEnumDef(desc);
|
1245
|
+
const upb_EnumValueDef* ev = upb_EnumDef_FindValueByName(e, name);
|
1246
|
+
if (ev) {
|
1247
|
+
return INT2NUM(upb_EnumValueDef_Number(ev));
|
1197
1248
|
} else {
|
1198
|
-
return
|
1249
|
+
return Qnil;
|
1199
1250
|
}
|
1200
1251
|
}
|
1201
1252
|
|
@@ -1211,21 +1262,28 @@ static VALUE enum_descriptor(VALUE self) {
|
|
1211
1262
|
}
|
1212
1263
|
|
1213
1264
|
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
|
-
|
1265
|
+
const upb_EnumDef* e = EnumDescriptor_GetEnumDef(_enumdesc);
|
1266
|
+
VALUE mod = rb_define_module_id(rb_intern(upb_EnumDef_FullName(e)));
|
1267
|
+
|
1268
|
+
int n = upb_EnumDef_ValueCount(e);
|
1269
|
+
for (int i = 0; i < n; i++) {
|
1270
|
+
const upb_EnumValueDef* ev = upb_EnumDef_Value(e, i);
|
1271
|
+
upb_Arena* arena = upb_Arena_New();
|
1272
|
+
const char* src_name = upb_EnumValueDef_Name(ev);
|
1273
|
+
char* name = upb_strdup2(src_name, strlen(src_name), arena);
|
1274
|
+
int32_t value = upb_EnumValueDef_Number(ev);
|
1223
1275
|
if (name[0] < 'A' || name[0] > 'Z') {
|
1224
|
-
|
1225
|
-
|
1226
|
-
|
1276
|
+
if (name[0] >= 'a' && name[0] <= 'z') {
|
1277
|
+
name[0] -= 32; // auto capitalize
|
1278
|
+
} else {
|
1279
|
+
rb_warn(
|
1280
|
+
"Enum value '%s' does not start with an uppercase letter "
|
1281
|
+
"as is required for Ruby constants.",
|
1282
|
+
name);
|
1283
|
+
}
|
1227
1284
|
}
|
1228
1285
|
rb_define_const(mod, name, INT2NUM(value));
|
1286
|
+
upb_Arena_Free(arena);
|
1229
1287
|
}
|
1230
1288
|
|
1231
1289
|
rb_define_singleton_method(mod, "lookup", enum_lookup, 1);
|
@@ -1236,81 +1294,88 @@ VALUE build_module_from_enumdesc(VALUE _enumdesc) {
|
|
1236
1294
|
return mod;
|
1237
1295
|
}
|
1238
1296
|
|
1239
|
-
// Internal
|
1240
|
-
|
1241
|
-
|
1297
|
+
// Internal to the library; used by Google::Protobuf.deep_copy.
|
1298
|
+
upb_Message* Message_deep_copy(const upb_Message* msg, const upb_MessageDef* m,
|
1299
|
+
upb_Arena* arena) {
|
1242
1300
|
// Serialize and parse.
|
1243
|
-
|
1244
|
-
const
|
1301
|
+
upb_Arena* tmp_arena = upb_Arena_New();
|
1302
|
+
const upb_MiniTable* layout = upb_MessageDef_MiniTable(m);
|
1245
1303
|
size_t size;
|
1246
1304
|
|
1247
|
-
|
1248
|
-
|
1249
|
-
|
1250
|
-
|
1251
|
-
|
1305
|
+
upb_Message* new_msg = upb_Message_New(layout, arena);
|
1306
|
+
char* data;
|
1307
|
+
|
1308
|
+
const upb_FileDef* file = upb_MessageDef_File(m);
|
1309
|
+
const upb_ExtensionRegistry* extreg =
|
1310
|
+
upb_DefPool_ExtensionRegistry(upb_FileDef_Pool(file));
|
1311
|
+
if (upb_Encode(msg, layout, 0, tmp_arena, &data, &size) !=
|
1312
|
+
kUpb_EncodeStatus_Ok ||
|
1313
|
+
upb_Decode(data, size, new_msg, layout, extreg, 0, arena) !=
|
1314
|
+
kUpb_DecodeStatus_Ok) {
|
1315
|
+
upb_Arena_Free(tmp_arena);
|
1252
1316
|
rb_raise(cParseError, "Error occurred copying proto");
|
1253
1317
|
}
|
1254
1318
|
|
1255
|
-
|
1319
|
+
upb_Arena_Free(tmp_arena);
|
1256
1320
|
return new_msg;
|
1257
1321
|
}
|
1258
1322
|
|
1259
|
-
const
|
1260
|
-
|
1323
|
+
const upb_Message* Message_GetUpbMessage(VALUE value, const upb_MessageDef* m,
|
1324
|
+
const char* name, upb_Arena* arena) {
|
1261
1325
|
if (value == Qnil) {
|
1262
1326
|
rb_raise(cTypeError, "nil message not allowed here.");
|
1263
1327
|
}
|
1264
1328
|
|
1265
1329
|
VALUE klass = CLASS_OF(value);
|
1266
1330
|
VALUE desc_rb = rb_ivar_get(klass, descriptor_instancevar_interned);
|
1267
|
-
const
|
1331
|
+
const upb_MessageDef* val_m =
|
1268
1332
|
desc_rb == Qnil ? NULL : Descriptor_GetMsgDef(desc_rb);
|
1269
1333
|
|
1270
1334
|
if (val_m != m) {
|
1271
1335
|
// Check for possible implicit conversions
|
1272
1336
|
// TODO: hash conversion?
|
1273
1337
|
|
1274
|
-
switch (
|
1275
|
-
case
|
1338
|
+
switch (upb_MessageDef_WellKnownType(m)) {
|
1339
|
+
case kUpb_WellKnown_Timestamp: {
|
1276
1340
|
// Time -> Google::Protobuf::Timestamp
|
1277
|
-
|
1278
|
-
|
1341
|
+
const upb_MiniTable* t = upb_MessageDef_MiniTable(m);
|
1342
|
+
upb_Message* msg = upb_Message_New(t, arena);
|
1343
|
+
upb_MessageValue sec, nsec;
|
1279
1344
|
struct timespec time;
|
1280
|
-
const
|
1281
|
-
const
|
1345
|
+
const upb_FieldDef* sec_f = upb_MessageDef_FindFieldByNumber(m, 1);
|
1346
|
+
const upb_FieldDef* nsec_f = upb_MessageDef_FindFieldByNumber(m, 2);
|
1282
1347
|
|
1283
1348
|
if (!rb_obj_is_kind_of(value, rb_cTime)) goto badtype;
|
1284
1349
|
|
1285
1350
|
time = rb_time_timespec(value);
|
1286
1351
|
sec.int64_val = time.tv_sec;
|
1287
1352
|
nsec.int32_val = time.tv_nsec;
|
1288
|
-
|
1289
|
-
|
1353
|
+
upb_Message_SetFieldByDef(msg, sec_f, sec, arena);
|
1354
|
+
upb_Message_SetFieldByDef(msg, nsec_f, nsec, arena);
|
1290
1355
|
return msg;
|
1291
1356
|
}
|
1292
|
-
case
|
1357
|
+
case kUpb_WellKnown_Duration: {
|
1293
1358
|
// Numeric -> Google::Protobuf::Duration
|
1294
|
-
|
1295
|
-
|
1296
|
-
|
1297
|
-
const
|
1359
|
+
const upb_MiniTable* t = upb_MessageDef_MiniTable(m);
|
1360
|
+
upb_Message* msg = upb_Message_New(t, arena);
|
1361
|
+
upb_MessageValue sec, nsec;
|
1362
|
+
const upb_FieldDef* sec_f = upb_MessageDef_FindFieldByNumber(m, 1);
|
1363
|
+
const upb_FieldDef* nsec_f = upb_MessageDef_FindFieldByNumber(m, 2);
|
1298
1364
|
|
1299
1365
|
if (!rb_obj_is_kind_of(value, rb_cNumeric)) goto badtype;
|
1300
1366
|
|
1301
1367
|
sec.int64_val = NUM2LL(value);
|
1302
1368
|
nsec.int32_val = round((NUM2DBL(value) - NUM2LL(value)) * 1000000000);
|
1303
|
-
|
1304
|
-
|
1369
|
+
upb_Message_SetFieldByDef(msg, sec_f, sec, arena);
|
1370
|
+
upb_Message_SetFieldByDef(msg, nsec_f, nsec, arena);
|
1305
1371
|
return msg;
|
1306
1372
|
}
|
1307
1373
|
default:
|
1308
1374
|
badtype:
|
1309
1375
|
rb_raise(cTypeError,
|
1310
1376
|
"Invalid type %s to assign to submessage field '%s'.",
|
1311
|
-
|
1377
|
+
rb_class2name(CLASS_OF(value)), name);
|
1312
1378
|
}
|
1313
|
-
|
1314
1379
|
}
|
1315
1380
|
|
1316
1381
|
Message* self = ruby_to_Message(value);
|
@@ -1319,11 +1384,43 @@ const upb_msg* Message_GetUpbMessage(VALUE value, const upb_msgdef* m,
|
|
1319
1384
|
return self->msg;
|
1320
1385
|
}
|
1321
1386
|
|
1387
|
+
static void Message_define_class(VALUE klass) {
|
1388
|
+
rb_define_alloc_func(klass, Message_alloc);
|
1389
|
+
|
1390
|
+
rb_require("google/protobuf/message_exts");
|
1391
|
+
rb_define_method(klass, "method_missing", Message_method_missing, -1);
|
1392
|
+
rb_define_method(klass, "respond_to_missing?", Message_respond_to_missing,
|
1393
|
+
-1);
|
1394
|
+
rb_define_method(klass, "initialize", Message_initialize, -1);
|
1395
|
+
rb_define_method(klass, "dup", Message_dup, 0);
|
1396
|
+
// Also define #clone so that we don't inherit Object#clone.
|
1397
|
+
rb_define_method(klass, "clone", Message_dup, 0);
|
1398
|
+
rb_define_method(klass, "==", Message_eq, 1);
|
1399
|
+
rb_define_method(klass, "eql?", Message_eq, 1);
|
1400
|
+
rb_define_method(klass, "freeze", Message_freeze, 0);
|
1401
|
+
rb_define_method(klass, "frozen?", Message_frozen, 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
|
}
|