36
36
import com .google .protobuf .Descriptors .Descriptor ;
37
37
import com .google .protobuf .Descriptors .DescriptorValidationException ;
38
38
import com .google .protobuf .Descriptors .EnumDescriptor ;
39
+ import com .google .protobuf .Descriptors .FieldDescriptor ;
39
40
import com .google .protobuf .Descriptors .FileDescriptor ;
41
+ import com .google .protobuf .ExtensionRegistry ;
40
42
import com .google .protobuf .InvalidProtocolBufferException ;
41
43
import java .util .ArrayList ;
42
44
import java .util .HashMap ;
@@ -70,6 +72,7 @@ public IRubyObject allocate(Ruby runtime, RubyClass klazz) {
70
72
cDescriptorPool .newInstance (runtime .getCurrentContext (), Block .NULL_BLOCK );
71
73
cDescriptor = (RubyClass ) runtime .getClassFromPath ("Google::Protobuf::Descriptor" );
72
74
cEnumDescriptor = (RubyClass ) runtime .getClassFromPath ("Google::Protobuf::EnumDescriptor" );
75
+ cFieldDescriptor = (RubyClass ) runtime .getClassFromPath ("Google::Protobuf::FieldDescriptor" );
73
76
}
74
77
75
78
public RubyDescriptorPool (Ruby runtime , RubyClass klazz ) {
@@ -92,7 +95,7 @@ public IRubyObject build(ThreadContext context, Block block) {
92
95
* call-seq:
93
96
* DescriptorPool.lookup(name) => descriptor
94
97
*
95
- * Finds a Descriptor or EnumDescriptor by name and returns it, or nil if none
98
+ * Finds a Descriptor, EnumDescriptor or FieldDescriptor by name and returns it, or nil if none
96
99
* exists with the given name.
97
100
*
98
101
* This currently lazy loads the ruby descriptor objects as they are requested.
@@ -121,7 +124,8 @@ public static IRubyObject generatedPool(ThreadContext context, IRubyObject recv)
121
124
public IRubyObject add_serialized_file (ThreadContext context , IRubyObject data ) {
122
125
byte [] bin = data .convertToString ().getBytes ();
123
126
try {
124
- FileDescriptorProto .Builder builder = FileDescriptorProto .newBuilder ().mergeFrom (bin );
127
+ FileDescriptorProto .Builder builder =
128
+ FileDescriptorProto .newBuilder ().mergeFrom (bin , registry );
125
129
registerFileDescriptor (context , builder );
126
130
} catch (InvalidProtocolBufferException e ) {
127
131
throw RaiseException .from (
@@ -150,6 +154,8 @@ protected void registerFileDescriptor(
150
154
for (EnumDescriptor ed : fd .getEnumTypes ()) registerEnumDescriptor (context , ed , packageName );
151
155
for (Descriptor message : fd .getMessageTypes ())
152
156
registerDescriptor (context , message , packageName );
157
+ for (FieldDescriptor fieldDescriptor : fd .getExtensions ())
158
+ registerExtension (context , fieldDescriptor , packageName );
153
159
154
160
// Mark this as a loaded file
155
161
fileDescriptors .add (fd );
@@ -170,6 +176,24 @@ private void registerDescriptor(ThreadContext context, Descriptor descriptor, St
170
176
registerEnumDescriptor (context , ed , fullPath );
171
177
for (Descriptor message : descriptor .getNestedTypes ())
172
178
registerDescriptor (context , message , fullPath );
179
+ for (FieldDescriptor fieldDescriptor : descriptor .getExtensions ())
180
+ registerExtension (context , fieldDescriptor , fullPath );
181
+ }
182
+
183
+ private void registerExtension (
184
+ ThreadContext context , FieldDescriptor descriptor , String parentPath ) {
185
+ if (descriptor .getJavaType () == FieldDescriptor .JavaType .MESSAGE ) {
186
+ registry .add (descriptor , descriptor .toProto ());
187
+ } else {
188
+ registry .add (descriptor );
189
+ }
190
+ RubyString name = context .runtime .newString (parentPath + descriptor .getName ());
191
+ RubyFieldDescriptor des =
192
+ (RubyFieldDescriptor ) cFieldDescriptor .newInstance (context , Block .NULL_BLOCK );
193
+ des .setName (name );
194
+ des .setDescriptor (context , descriptor , this );
195
+ // For MessageSet extensions, there is the possibility of a name conflict. Prefer the Message.
196
+ symtab .putIfAbsent (name , des );
173
197
}
174
198
175
199
private void registerEnumDescriptor (
@@ -188,8 +212,10 @@ private FileDescriptor[] existingFileDescriptors() {
188
212
189
213
private static RubyClass cDescriptor ;
190
214
private static RubyClass cEnumDescriptor ;
215
+ private static RubyClass cFieldDescriptor ;
191
216
private static RubyDescriptorPool descriptorPool ;
192
217
193
218
private List <FileDescriptor > fileDescriptors ;
194
219
private Map <IRubyObject , IRubyObject > symtab ;
220
+ protected static final ExtensionRegistry registry = ExtensionRegistry .newInstance ();
195
221
}
0 commit comments