3636import com .google .protobuf .Descriptors .Descriptor ;
3737import com .google .protobuf .Descriptors .DescriptorValidationException ;
3838import com .google .protobuf .Descriptors .EnumDescriptor ;
39+ import com .google .protobuf .Descriptors .FieldDescriptor ;
3940import com .google .protobuf .Descriptors .FileDescriptor ;
41+ import com .google .protobuf .ExtensionRegistry ;
4042import com .google .protobuf .InvalidProtocolBufferException ;
4143import java .util .ArrayList ;
4244import java .util .HashMap ;
@@ -70,6 +72,7 @@ public IRubyObject allocate(Ruby runtime, RubyClass klazz) {
7072 cDescriptorPool .newInstance (runtime .getCurrentContext (), Block .NULL_BLOCK );
7173 cDescriptor = (RubyClass ) runtime .getClassFromPath ("Google::Protobuf::Descriptor" );
7274 cEnumDescriptor = (RubyClass ) runtime .getClassFromPath ("Google::Protobuf::EnumDescriptor" );
75+ cFieldDescriptor = (RubyClass ) runtime .getClassFromPath ("Google::Protobuf::FieldDescriptor" );
7376 }
7477
7578 public RubyDescriptorPool (Ruby runtime , RubyClass klazz ) {
@@ -92,7 +95,7 @@ public IRubyObject build(ThreadContext context, Block block) {
9295 * call-seq:
9396 * DescriptorPool.lookup(name) => descriptor
9497 *
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
9699 * exists with the given name.
97100 *
98101 * This currently lazy loads the ruby descriptor objects as they are requested.
@@ -121,7 +124,8 @@ public static IRubyObject generatedPool(ThreadContext context, IRubyObject recv)
121124 public IRubyObject add_serialized_file (ThreadContext context , IRubyObject data ) {
122125 byte [] bin = data .convertToString ().getBytes ();
123126 try {
124- FileDescriptorProto .Builder builder = FileDescriptorProto .newBuilder ().mergeFrom (bin );
127+ FileDescriptorProto .Builder builder =
128+ FileDescriptorProto .newBuilder ().mergeFrom (bin , registry );
125129 registerFileDescriptor (context , builder );
126130 } catch (InvalidProtocolBufferException e ) {
127131 throw RaiseException .from (
@@ -150,6 +154,8 @@ protected void registerFileDescriptor(
150154 for (EnumDescriptor ed : fd .getEnumTypes ()) registerEnumDescriptor (context , ed , packageName );
151155 for (Descriptor message : fd .getMessageTypes ())
152156 registerDescriptor (context , message , packageName );
157+ for (FieldDescriptor fieldDescriptor : fd .getExtensions ())
158+ registerExtension (context , fieldDescriptor , packageName );
153159
154160 // Mark this as a loaded file
155161 fileDescriptors .add (fd );
@@ -170,6 +176,24 @@ private void registerDescriptor(ThreadContext context, Descriptor descriptor, St
170176 registerEnumDescriptor (context , ed , fullPath );
171177 for (Descriptor message : descriptor .getNestedTypes ())
172178 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 );
173197 }
174198
175199 private void registerEnumDescriptor (
@@ -188,8 +212,10 @@ private FileDescriptor[] existingFileDescriptors() {
188212
189213 private static RubyClass cDescriptor ;
190214 private static RubyClass cEnumDescriptor ;
215+ private static RubyClass cFieldDescriptor ;
191216 private static RubyDescriptorPool descriptorPool ;
192217
193218 private List <FileDescriptor > fileDescriptors ;
194219 private Map <IRubyObject , IRubyObject > symtab ;
220+ protected static final ExtensionRegistry registry = ExtensionRegistry .newInstance ();
195221}
0 commit comments