1 package com.google.protobuf.jruby; 2 3 import com.google.protobuf.CodedInputStream; 4 import com.google.protobuf.Descriptors.FieldDescriptor; 5 import com.google.protobuf.Descriptors.OneofDescriptor; 6 import java.util.ArrayList; 7 import java.util.Collection; 8 import java.util.List; 9 import java.util.Map; 10 import org.jruby.Ruby; 11 import org.jruby.RubyClass; 12 import org.jruby.RubyModule; 13 import org.jruby.RubyObject; 14 import org.jruby.anno.JRubyClass; 15 import org.jruby.anno.JRubyMethod; 16 import org.jruby.runtime.Block; 17 import org.jruby.runtime.ObjectAllocator; 18 import org.jruby.runtime.ThreadContext; 19 import org.jruby.runtime.builtin.IRubyObject; 20 21 @JRubyClass(name = "OneofDescriptor", include = "Enumerable") 22 public class RubyOneofDescriptor extends RubyObject { 23 createRubyOneofDescriptor(Ruby runtime)24 public static void createRubyOneofDescriptor(Ruby runtime) { 25 RubyModule protobuf = runtime.getClassFromPath("Google::Protobuf"); 26 RubyClass cRubyOneofDescriptor = 27 protobuf.defineClassUnder( 28 "OneofDescriptor", 29 runtime.getObject(), 30 new ObjectAllocator() { 31 @Override 32 public IRubyObject allocate(Ruby ruby, RubyClass rubyClass) { 33 return new RubyOneofDescriptor(ruby, rubyClass); 34 } 35 }); 36 cRubyOneofDescriptor.defineAnnotatedMethods(RubyOneofDescriptor.class); 37 cRubyOneofDescriptor.includeModule(runtime.getEnumerable()); 38 } 39 RubyOneofDescriptor(Ruby ruby, RubyClass rubyClass)40 public RubyOneofDescriptor(Ruby ruby, RubyClass rubyClass) { 41 super(ruby, rubyClass); 42 fields = new ArrayList<RubyFieldDescriptor>(); 43 } 44 45 /* 46 * call-seq: 47 * OneofDescriptor.name => name 48 * 49 * Returns the name of this oneof. 50 */ 51 @JRubyMethod(name = "name") getName(ThreadContext context)52 public IRubyObject getName(ThreadContext context) { 53 return name; 54 } 55 56 /* 57 * call-seq: 58 * OneofDescriptor.each(&block) => nil 59 * 60 * Iterates through fields in this oneof, yielding to the block on each one. 61 */ 62 @JRubyMethod each(ThreadContext context, Block block)63 public IRubyObject each(ThreadContext context, Block block) { 64 for (RubyFieldDescriptor field : fields) { 65 block.yieldSpecific(context, field); 66 } 67 return context.nil; 68 } 69 70 @JRubyMethod options(ThreadContext context)71 public IRubyObject options(ThreadContext context) { 72 RubyDescriptorPool pool = (RubyDescriptorPool) RubyDescriptorPool.generatedPool(null, null); 73 RubyDescriptor oneofOptionsDescriptor = 74 (RubyDescriptor) 75 pool.lookup(context, context.runtime.newString("google.protobuf.OneofOptions")); 76 RubyClass oneofOptionsClass = (RubyClass) oneofOptionsDescriptor.msgclass(context); 77 RubyMessage msg = (RubyMessage) oneofOptionsClass.newInstance(context, Block.NULL_BLOCK); 78 return msg.decodeBytes( 79 context, 80 msg, 81 CodedInputStream.newInstance( 82 descriptor.getOptions().toByteString().toByteArray()), /*freeze*/ 83 true); 84 } 85 getFields()86 protected Collection<RubyFieldDescriptor> getFields() { 87 return fields; 88 } 89 getDescriptor()90 protected OneofDescriptor getDescriptor() { 91 return descriptor; 92 } 93 setDescriptor( ThreadContext context, OneofDescriptor descriptor, Map<FieldDescriptor, RubyFieldDescriptor> fieldCache)94 protected void setDescriptor( 95 ThreadContext context, 96 OneofDescriptor descriptor, 97 Map<FieldDescriptor, RubyFieldDescriptor> fieldCache) { 98 this.descriptor = descriptor; 99 this.name = context.runtime.newString(descriptor.getName()); 100 101 for (FieldDescriptor fd : descriptor.getFields()) { 102 fields.add(fieldCache.get(fd)); 103 } 104 } 105 106 private IRubyObject name; 107 private List<RubyFieldDescriptor> fields; 108 private OneofDescriptor descriptor; 109 } 110