Merge pull request #9690 from JasonLunn/format_jruby_with_google-java-format

Run all JRuby source files through `google-java-format.`
pull/9697/head
Jason Lunn 3 years ago committed by GitHub
commit 3dee6efa54
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 334
      ruby/src/main/java/com/google/protobuf/jruby/RubyDescriptor.java
  2. 263
      ruby/src/main/java/com/google/protobuf/jruby/RubyDescriptorPool.java
  3. 70
      ruby/src/main/java/com/google/protobuf/jruby/RubyEnum.java
  4. 259
      ruby/src/main/java/com/google/protobuf/jruby/RubyEnumDescriptor.java
  5. 411
      ruby/src/main/java/com/google/protobuf/jruby/RubyFieldDescriptor.java
  6. 105
      ruby/src/main/java/com/google/protobuf/jruby/RubyFileDescriptor.java
  7. 805
      ruby/src/main/java/com/google/protobuf/jruby/RubyMap.java
  8. 2434
      ruby/src/main/java/com/google/protobuf/jruby/RubyMessage.java
  9. 118
      ruby/src/main/java/com/google/protobuf/jruby/RubyOneofDescriptor.java
  10. 69
      ruby/src/main/java/com/google/protobuf/jruby/RubyProtobuf.java
  11. 717
      ruby/src/main/java/com/google/protobuf/jruby/RubyRepeatedField.java
  12. 467
      ruby/src/main/java/com/google/protobuf/jruby/SentinelOuterClass.java
  13. 604
      ruby/src/main/java/com/google/protobuf/jruby/Utils.java
  14. 41
      ruby/src/main/java/google/ProtobufJavaService.java

@ -35,6 +35,8 @@ package com.google.protobuf.jruby;
import com.google.protobuf.Descriptors.Descriptor; import com.google.protobuf.Descriptors.Descriptor;
import com.google.protobuf.Descriptors.FieldDescriptor; import com.google.protobuf.Descriptors.FieldDescriptor;
import com.google.protobuf.Descriptors.OneofDescriptor; import com.google.protobuf.Descriptors.OneofDescriptor;
import java.util.HashMap;
import java.util.Map;
import org.jruby.*; import org.jruby.*;
import org.jruby.anno.JRubyClass; import org.jruby.anno.JRubyClass;
import org.jruby.anno.JRubyMethod; import org.jruby.anno.JRubyMethod;
@ -44,182 +46,186 @@ import org.jruby.runtime.ObjectAllocator;
import org.jruby.runtime.ThreadContext; import org.jruby.runtime.ThreadContext;
import org.jruby.runtime.builtin.IRubyObject; import org.jruby.runtime.builtin.IRubyObject;
import java.util.HashMap;
import java.util.Map;
@JRubyClass(name = "Descriptor", include = "Enumerable") @JRubyClass(name = "Descriptor", include = "Enumerable")
public class RubyDescriptor extends RubyObject { public class RubyDescriptor extends RubyObject {
public static void createRubyDescriptor(Ruby runtime) { public static void createRubyDescriptor(Ruby runtime) {
RubyModule protobuf = runtime.getClassFromPath("Google::Protobuf"); RubyModule protobuf = runtime.getClassFromPath("Google::Protobuf");
RubyClass cDescriptor = protobuf.defineClassUnder("Descriptor", runtime.getObject(), new ObjectAllocator() { RubyClass cDescriptor =
@Override protobuf.defineClassUnder(
public IRubyObject allocate(Ruby runtime, RubyClass klazz) { "Descriptor",
runtime.getObject(),
new ObjectAllocator() {
@Override
public IRubyObject allocate(Ruby runtime, RubyClass klazz) {
return new RubyDescriptor(runtime, klazz); return new RubyDescriptor(runtime, klazz);
} }
}); });
cDescriptor.includeModule(runtime.getEnumerable()); cDescriptor.includeModule(runtime.getEnumerable());
cDescriptor.defineAnnotatedMethods(RubyDescriptor.class); cDescriptor.defineAnnotatedMethods(RubyDescriptor.class);
cFieldDescriptor = (RubyClass) runtime.getClassFromPath("Google::Protobuf::FieldDescriptor"); cFieldDescriptor = (RubyClass) runtime.getClassFromPath("Google::Protobuf::FieldDescriptor");
cOneofDescriptor = (RubyClass) runtime.getClassFromPath("Google::Protobuf::OneofDescriptor"); cOneofDescriptor = (RubyClass) runtime.getClassFromPath("Google::Protobuf::OneofDescriptor");
}
public RubyDescriptor(Ruby runtime, RubyClass klazz) {
super(runtime, klazz);
}
/*
* call-seq:
* Descriptor.name => name
*
* Returns the name of this message type as a fully-qualified string (e.g.,
* My.Package.MessageType).
*/
@JRubyMethod(name = "name")
public IRubyObject getName(ThreadContext context) {
return name;
}
/*
* call-seq:
* Descriptor.lookup(name) => FieldDescriptor
*
* Returns the field descriptor for the field with the given name, if present,
* or nil if none.
*/
@JRubyMethod
public IRubyObject lookup(ThreadContext context, IRubyObject fieldName) {
return Helpers.nullToNil(fieldDescriptors.get(fieldName), context.nil);
}
/*
* call-seq:
* Descriptor.msgclass => message_klass
*
* Returns the Ruby class created for this message type. Valid only once the
* message type has been added to a pool.
*/
@JRubyMethod
public IRubyObject msgclass(ThreadContext context) {
return klazz;
}
/*
* call-seq:
* Descriptor.each(&block)
*
* Iterates over fields in this message type, yielding to the block on each one.
*/
@JRubyMethod
public IRubyObject each(ThreadContext context, Block block) {
for (Map.Entry<IRubyObject, RubyFieldDescriptor> entry : fieldDescriptors.entrySet()) {
block.yield(context, entry.getValue());
} }
return context.nil;
public RubyDescriptor(Ruby runtime, RubyClass klazz) { }
super(runtime, klazz);
/*
* call-seq:
* Descriptor.file_descriptor
*
* Returns the FileDescriptor object this message belongs to.
*/
@JRubyMethod(name = "file_descriptor")
public IRubyObject getFileDescriptor(ThreadContext context) {
return RubyFileDescriptor.getRubyFileDescriptor(context, descriptor);
}
/*
* call-seq:
* Descriptor.each_oneof(&block) => nil
*
* Invokes the given block for each oneof in this message type, passing the
* corresponding OneofDescriptor.
*/
@JRubyMethod(name = "each_oneof")
public IRubyObject eachOneof(ThreadContext context, Block block) {
for (RubyOneofDescriptor oneofDescriptor : oneofDescriptors.values()) {
block.yieldSpecific(context, oneofDescriptor);
} }
return context.nil;
/* }
* call-seq:
* Descriptor.name => name /*
* * call-seq:
* Returns the name of this message type as a fully-qualified string (e.g., * Descriptor.lookup_oneof(name) => OneofDescriptor
* My.Package.MessageType). *
*/ * Returns the oneof descriptor for the oneof with the given name, if present,
@JRubyMethod(name = "name") * or nil if none.
public IRubyObject getName(ThreadContext context) { */
return name; @JRubyMethod(name = "lookup_oneof")
public IRubyObject lookupOneof(ThreadContext context, IRubyObject name) {
return Helpers.nullToNil(oneofDescriptors.get(Utils.symToString(name)), context.nil);
}
protected FieldDescriptor getField(String name) {
return descriptor.findFieldByName(name);
}
protected void setDescriptor(
ThreadContext context, Descriptor descriptor, RubyDescriptorPool pool) {
Ruby runtime = context.runtime;
Map<FieldDescriptor, RubyFieldDescriptor> cache = new HashMap();
this.descriptor = descriptor;
// Populate the field caches
fieldDescriptors = new HashMap<IRubyObject, RubyFieldDescriptor>();
oneofDescriptors = new HashMap<IRubyObject, RubyOneofDescriptor>();
for (FieldDescriptor fieldDescriptor : descriptor.getFields()) {
RubyFieldDescriptor fd =
(RubyFieldDescriptor) cFieldDescriptor.newInstance(context, Block.NULL_BLOCK);
fd.setDescriptor(context, fieldDescriptor, pool);
fieldDescriptors.put(runtime.newString(fieldDescriptor.getName()), fd);
cache.put(fieldDescriptor, fd);
} }
/* for (OneofDescriptor oneofDescriptor : descriptor.getRealOneofs()) {
* call-seq: RubyOneofDescriptor ood =
* Descriptor.lookup(name) => FieldDescriptor (RubyOneofDescriptor) cOneofDescriptor.newInstance(context, Block.NULL_BLOCK);
* ood.setDescriptor(context, oneofDescriptor, cache);
* Returns the field descriptor for the field with the given name, if present, oneofDescriptors.put(runtime.newString(oneofDescriptor.getName()), ood);
* or nil if none.
*/
@JRubyMethod
public IRubyObject lookup(ThreadContext context, IRubyObject fieldName) {
return Helpers.nullToNil(fieldDescriptors.get(fieldName), context.nil);
} }
/* // Make sure our class is built
* call-seq: this.klazz = buildClassFromDescriptor(context);
* Descriptor.msgclass => message_klass }
*
* Returns the Ruby class created for this message type. Valid only once the
* message type has been added to a pool.
*/
@JRubyMethod
public IRubyObject msgclass(ThreadContext context) {
return klazz;
}
/* protected void setName(IRubyObject name) {
* call-seq: this.name = name;
* Descriptor.each(&block) }
*
* Iterates over fields in this message type, yielding to the block on each one.
*/
@JRubyMethod
public IRubyObject each(ThreadContext context, Block block) {
for (Map.Entry<IRubyObject, RubyFieldDescriptor> entry : fieldDescriptors.entrySet()) {
block.yield(context, entry.getValue());
}
return context.nil;
}
/* private RubyClass buildClassFromDescriptor(ThreadContext context) {
* call-seq: Ruby runtime = context.runtime;
* Descriptor.file_descriptor
*
* Returns the FileDescriptor object this message belongs to.
*/
@JRubyMethod(name = "file_descriptor")
public IRubyObject getFileDescriptor(ThreadContext context) {
return RubyFileDescriptor.getRubyFileDescriptor(context, descriptor);
}
/*
* call-seq:
* Descriptor.each_oneof(&block) => nil
*
* Invokes the given block for each oneof in this message type, passing the
* corresponding OneofDescriptor.
*/
@JRubyMethod(name = "each_oneof")
public IRubyObject eachOneof(ThreadContext context, Block block) {
for (RubyOneofDescriptor oneofDescriptor : oneofDescriptors.values()) {
block.yieldSpecific(context, oneofDescriptor);
}
return context.nil;
}
/* ObjectAllocator allocator =
* call-seq: new ObjectAllocator() {
* Descriptor.lookup_oneof(name) => OneofDescriptor @Override
* public IRubyObject allocate(Ruby runtime, RubyClass klazz) {
* Returns the oneof descriptor for the oneof with the given name, if present, return new RubyMessage(runtime, klazz, descriptor);
* or nil if none. }
*/
@JRubyMethod(name = "lookup_oneof")
public IRubyObject lookupOneof(ThreadContext context, IRubyObject name) {
return Helpers.nullToNil(oneofDescriptors.get(Utils.symToString(name)), context.nil);
}
protected FieldDescriptor getField(String name) {
return descriptor.findFieldByName(name);
}
protected void setDescriptor(ThreadContext context, Descriptor descriptor, RubyDescriptorPool pool) {
Ruby runtime = context.runtime;
Map<FieldDescriptor, RubyFieldDescriptor> cache = new HashMap();
this.descriptor = descriptor;
// Populate the field caches
fieldDescriptors = new HashMap<IRubyObject, RubyFieldDescriptor>();
oneofDescriptors = new HashMap<IRubyObject, RubyOneofDescriptor>();
for (FieldDescriptor fieldDescriptor : descriptor.getFields()) {
RubyFieldDescriptor fd = (RubyFieldDescriptor) cFieldDescriptor.newInstance(context, Block.NULL_BLOCK);
fd.setDescriptor(context, fieldDescriptor, pool);
fieldDescriptors.put(runtime.newString(fieldDescriptor.getName()), fd);
cache.put(fieldDescriptor, fd);
}
for (OneofDescriptor oneofDescriptor : descriptor.getRealOneofs()) {
RubyOneofDescriptor ood = (RubyOneofDescriptor) cOneofDescriptor.newInstance(context, Block.NULL_BLOCK);
ood.setDescriptor(context, oneofDescriptor, cache);
oneofDescriptors.put(runtime.newString(oneofDescriptor.getName()), ood);
}
// Make sure our class is built
this.klazz = buildClassFromDescriptor(context);
}
protected void setName(IRubyObject name) {
this.name = name;
}
private RubyClass buildClassFromDescriptor(ThreadContext context) {
Ruby runtime = context.runtime;
ObjectAllocator allocator = new ObjectAllocator() {
@Override
public IRubyObject allocate(Ruby runtime, RubyClass klazz) {
return new RubyMessage(runtime, klazz, descriptor);
}
}; };
// rb_define_class_id // rb_define_class_id
RubyClass klass = RubyClass.newClass(runtime, runtime.getObject()); RubyClass klass = RubyClass.newClass(runtime, runtime.getObject());
klass.setAllocator(allocator); klass.setAllocator(allocator);
klass.makeMetaClass(runtime.getObject().getMetaClass()); klass.makeMetaClass(runtime.getObject().getMetaClass());
klass.inherit(runtime.getObject()); klass.inherit(runtime.getObject());
RubyModule messageExts = runtime.getClassFromPath("Google::Protobuf::MessageExts"); RubyModule messageExts = runtime.getClassFromPath("Google::Protobuf::MessageExts");
klass.include(new IRubyObject[] {messageExts}); klass.include(new IRubyObject[] {messageExts});
klass.instance_variable_set(runtime.newString(Utils.DESCRIPTOR_INSTANCE_VAR), this); klass.instance_variable_set(runtime.newString(Utils.DESCRIPTOR_INSTANCE_VAR), this);
klass.defineAnnotatedMethods(RubyMessage.class); klass.defineAnnotatedMethods(RubyMessage.class);
// Workaround for https://github.com/jruby/jruby/issues/7154 // Workaround for https://github.com/jruby/jruby/issues/7154
klass.searchMethod("respond_to?").setIsBuiltin(false); klass.searchMethod("respond_to?").setIsBuiltin(false);
return klass; return klass;
} }
private static RubyClass cFieldDescriptor; private static RubyClass cFieldDescriptor;
private static RubyClass cOneofDescriptor; private static RubyClass cOneofDescriptor;
private Descriptor descriptor; private Descriptor descriptor;
private IRubyObject name; private IRubyObject name;
private Map<IRubyObject, RubyFieldDescriptor> fieldDescriptors; private Map<IRubyObject, RubyFieldDescriptor> fieldDescriptors;
private Map<IRubyObject, RubyOneofDescriptor> oneofDescriptors; private Map<IRubyObject, RubyOneofDescriptor> oneofDescriptors;
private RubyClass klazz; private RubyClass klazz;
} }

@ -38,6 +38,10 @@ import com.google.protobuf.Descriptors.DescriptorValidationException;
import com.google.protobuf.Descriptors.EnumDescriptor; import com.google.protobuf.Descriptors.EnumDescriptor;
import com.google.protobuf.Descriptors.FileDescriptor; import com.google.protobuf.Descriptors.FileDescriptor;
import com.google.protobuf.InvalidProtocolBufferException; import com.google.protobuf.InvalidProtocolBufferException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.jruby.*; import org.jruby.*;
import org.jruby.anno.JRubyClass; import org.jruby.anno.JRubyClass;
import org.jruby.anno.JRubyMethod; import org.jruby.anno.JRubyMethod;
@ -45,136 +49,147 @@ import org.jruby.exceptions.RaiseException;
import org.jruby.runtime.*; import org.jruby.runtime.*;
import org.jruby.runtime.builtin.IRubyObject; import org.jruby.runtime.builtin.IRubyObject;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@JRubyClass(name = "DescriptorPool") @JRubyClass(name = "DescriptorPool")
public class RubyDescriptorPool extends RubyObject { public class RubyDescriptorPool extends RubyObject {
public static void createRubyDescriptorPool(Ruby runtime) { public static void createRubyDescriptorPool(Ruby runtime) {
RubyModule protobuf = runtime.getClassFromPath("Google::Protobuf"); RubyModule protobuf = runtime.getClassFromPath("Google::Protobuf");
RubyClass cDescriptorPool = protobuf.defineClassUnder("DescriptorPool", runtime.getObject(), new ObjectAllocator() { RubyClass cDescriptorPool =
@Override protobuf.defineClassUnder(
public IRubyObject allocate(Ruby runtime, RubyClass klazz) { "DescriptorPool",
runtime.getObject(),
new ObjectAllocator() {
@Override
public IRubyObject allocate(Ruby runtime, RubyClass klazz) {
return new RubyDescriptorPool(runtime, klazz); return new RubyDescriptorPool(runtime, klazz);
} }
}); });
cDescriptorPool.defineAnnotatedMethods(RubyDescriptorPool.class); cDescriptorPool.defineAnnotatedMethods(RubyDescriptorPool.class);
descriptorPool = (RubyDescriptorPool) cDescriptorPool.newInstance(runtime.getCurrentContext(), Block.NULL_BLOCK); descriptorPool =
cDescriptor = (RubyClass) runtime.getClassFromPath("Google::Protobuf::Descriptor"); (RubyDescriptorPool)
cEnumDescriptor = (RubyClass) runtime.getClassFromPath("Google::Protobuf::EnumDescriptor"); cDescriptorPool.newInstance(runtime.getCurrentContext(), Block.NULL_BLOCK);
} cDescriptor = (RubyClass) runtime.getClassFromPath("Google::Protobuf::Descriptor");
cEnumDescriptor = (RubyClass) runtime.getClassFromPath("Google::Protobuf::EnumDescriptor");
public RubyDescriptorPool(Ruby runtime, RubyClass klazz) { }
super(runtime, klazz);
this.fileDescriptors = new ArrayList<>(); public RubyDescriptorPool(Ruby runtime, RubyClass klazz) {
this.symtab = new HashMap<IRubyObject, IRubyObject>(); super(runtime, klazz);
} this.fileDescriptors = new ArrayList<>();
this.symtab = new HashMap<IRubyObject, IRubyObject>();
@JRubyMethod }
public IRubyObject build(ThreadContext context, Block block) {
RubyClass cBuilder = (RubyClass) context.runtime.getClassFromPath("Google::Protobuf::Internal::Builder"); @JRubyMethod
RubyBasicObject ctx = (RubyBasicObject) cBuilder.newInstance(context, this, Block.NULL_BLOCK); public IRubyObject build(ThreadContext context, Block block) {
ctx.instance_eval(context, block); RubyClass cBuilder =
ctx.callMethod(context, "build"); // Needs to be called to support the deprecated syntax (RubyClass) context.runtime.getClassFromPath("Google::Protobuf::Internal::Builder");
return context.nil; RubyBasicObject ctx = (RubyBasicObject) cBuilder.newInstance(context, this, Block.NULL_BLOCK);
ctx.instance_eval(context, block);
ctx.callMethod(context, "build"); // Needs to be called to support the deprecated syntax
return context.nil;
}
/*
* call-seq:
* DescriptorPool.lookup(name) => descriptor
*
* Finds a Descriptor or EnumDescriptor by name and returns it, or nil if none
* exists with the given name.
*
* This currently lazy loads the ruby descriptor objects as they are requested.
* This allows us to leave the heavy lifting to the java library
*/
@JRubyMethod
public IRubyObject lookup(ThreadContext context, IRubyObject name) {
return Helpers.nullToNil(symtab.get(name), context.nil);
}
/*
* call-seq:
* DescriptorPool.generated_pool => descriptor_pool
*
* Class method that returns the global DescriptorPool. This is a singleton into
* which generated-code message and enum types are registered. The user may also
* register types in this pool for convenience so that they do not have to hold
* a reference to a private pool instance.
*/
@JRubyMethod(meta = true, name = "generated_pool")
public static IRubyObject generatedPool(ThreadContext context, IRubyObject recv) {
return descriptorPool;
}
@JRubyMethod(required = 1)
public IRubyObject add_serialized_file(ThreadContext context, IRubyObject data) {
byte[] bin = data.convertToString().getBytes();
try {
FileDescriptorProto.Builder builder = FileDescriptorProto.newBuilder().mergeFrom(bin);
registerFileDescriptor(context, builder);
} catch (InvalidProtocolBufferException e) {
throw RaiseException.from(
context.runtime,
(RubyClass) context.runtime.getClassFromPath("Google::Protobuf::ParseError"),
e.getMessage());
} }
return context.nil;
/* }
* call-seq:
* DescriptorPool.lookup(name) => descriptor protected void registerFileDescriptor(
* ThreadContext context, FileDescriptorProto.Builder builder) {
* Finds a Descriptor or EnumDescriptor by name and returns it, or nil if none final FileDescriptor fd;
* exists with the given name. try {
* fd = FileDescriptor.buildFrom(builder.build(), existingFileDescriptors());
* This currently lazy loads the ruby descriptor objects as they are requested. } catch (DescriptorValidationException e) {
* This allows us to leave the heavy lifting to the java library throw context.runtime.newRuntimeError(e.getMessage());
*/
@JRubyMethod
public IRubyObject lookup(ThreadContext context, IRubyObject name) {
return Helpers.nullToNil(symtab.get(name), context.nil);
}
/*
* call-seq:
* DescriptorPool.generated_pool => descriptor_pool
*
* Class method that returns the global DescriptorPool. This is a singleton into
* which generated-code message and enum types are registered. The user may also
* register types in this pool for convenience so that they do not have to hold
* a reference to a private pool instance.
*/
@JRubyMethod(meta = true, name = "generated_pool")
public static IRubyObject generatedPool(ThreadContext context, IRubyObject recv) {
return descriptorPool;
}
@JRubyMethod(required = 1)
public IRubyObject add_serialized_file (ThreadContext context, IRubyObject data ) {
byte[] bin = data.convertToString().getBytes();
try {
FileDescriptorProto.Builder builder = FileDescriptorProto.newBuilder().mergeFrom(bin);
registerFileDescriptor(context, builder);
} catch (InvalidProtocolBufferException e) {
throw RaiseException.from(context.runtime, (RubyClass) context.runtime.getClassFromPath("Google::Protobuf::ParseError"), e.getMessage());
}
return context.nil;
}
protected void registerFileDescriptor(ThreadContext context, FileDescriptorProto.Builder builder) {
final FileDescriptor fd;
try {
fd = FileDescriptor.buildFrom(builder.build(), existingFileDescriptors());
} catch (DescriptorValidationException e) {
throw context.runtime.newRuntimeError(e.getMessage());
}
String packageName = fd.getPackage();
if (!packageName.isEmpty()) {
packageName = packageName + ".";
}
// Need to make sure enums are registered first in case anything references them
for (EnumDescriptor ed : fd.getEnumTypes()) registerEnumDescriptor(context, ed, packageName);
for (Descriptor message : fd.getMessageTypes()) registerDescriptor(context, message, packageName);
// Mark this as a loaded file
fileDescriptors.add(fd);
} }
private void registerDescriptor(ThreadContext context, Descriptor descriptor, String parentPath) { String packageName = fd.getPackage();
String fullName = parentPath + descriptor.getName(); if (!packageName.isEmpty()) {
String fullPath = fullName + "."; packageName = packageName + ".";
RubyString name = context.runtime.newString(fullName);
RubyDescriptor des = (RubyDescriptor) cDescriptor.newInstance(context, Block.NULL_BLOCK);
des.setName(name);
des.setDescriptor(context, descriptor, this);
symtab.put(name, des);
// Need to make sure enums are registered first in case anything references them
for (EnumDescriptor ed : descriptor.getEnumTypes()) registerEnumDescriptor(context, ed, fullPath);
for (Descriptor message : descriptor.getNestedTypes()) registerDescriptor(context, message, fullPath);
}
private void registerEnumDescriptor(ThreadContext context, EnumDescriptor descriptor, String parentPath) {
RubyString name = context.runtime.newString(parentPath + descriptor.getName());
RubyEnumDescriptor des = (RubyEnumDescriptor) cEnumDescriptor.newInstance(context, Block.NULL_BLOCK);
des.setName(name);
des.setDescriptor(context, descriptor);
symtab.put(name, des);
} }
private FileDescriptor[] existingFileDescriptors() { // Need to make sure enums are registered first in case anything references them
return fileDescriptors.toArray(new FileDescriptor[fileDescriptors.size()]); for (EnumDescriptor ed : fd.getEnumTypes()) registerEnumDescriptor(context, ed, packageName);
} for (Descriptor message : fd.getMessageTypes())
registerDescriptor(context, message, packageName);
private static RubyClass cDescriptor;
private static RubyClass cEnumDescriptor; // Mark this as a loaded file
private static RubyDescriptorPool descriptorPool; fileDescriptors.add(fd);
}
private List<FileDescriptor> fileDescriptors;
private Map<IRubyObject, IRubyObject> symtab; private void registerDescriptor(ThreadContext context, Descriptor descriptor, String parentPath) {
String fullName = parentPath + descriptor.getName();
String fullPath = fullName + ".";
RubyString name = context.runtime.newString(fullName);
RubyDescriptor des = (RubyDescriptor) cDescriptor.newInstance(context, Block.NULL_BLOCK);
des.setName(name);
des.setDescriptor(context, descriptor, this);
symtab.put(name, des);
// Need to make sure enums are registered first in case anything references them
for (EnumDescriptor ed : descriptor.getEnumTypes())
registerEnumDescriptor(context, ed, fullPath);
for (Descriptor message : descriptor.getNestedTypes())
registerDescriptor(context, message, fullPath);
}
private void registerEnumDescriptor(
ThreadContext context, EnumDescriptor descriptor, String parentPath) {
RubyString name = context.runtime.newString(parentPath + descriptor.getName());
RubyEnumDescriptor des =
(RubyEnumDescriptor) cEnumDescriptor.newInstance(context, Block.NULL_BLOCK);
des.setName(name);
des.setDescriptor(context, descriptor);
symtab.put(name, des);
}
private FileDescriptor[] existingFileDescriptors() {
return fileDescriptors.toArray(new FileDescriptor[fileDescriptors.size()]);
}
private static RubyClass cDescriptor;
private static RubyClass cEnumDescriptor;
private static RubyDescriptorPool descriptorPool;
private List<FileDescriptor> fileDescriptors;
private Map<IRubyObject, IRubyObject> symtab;
} }

@ -38,41 +38,41 @@ import org.jruby.runtime.ThreadContext;
import org.jruby.runtime.builtin.IRubyObject; import org.jruby.runtime.builtin.IRubyObject;
public class RubyEnum { public class RubyEnum {
/* /*
* call-seq: * call-seq:
* Enum.lookup(number) => name * Enum.lookup(number) => name
* *
* This module method, provided on each generated enum module, looks up an enum * This module method, provided on each generated enum module, looks up an enum
* value by number and returns its name as a Ruby symbol, or nil if not found. * value by number and returns its name as a Ruby symbol, or nil if not found.
*/ */
@JRubyMethod(meta = true) @JRubyMethod(meta = true)
public static IRubyObject lookup(ThreadContext context, IRubyObject recv, IRubyObject number) { public static IRubyObject lookup(ThreadContext context, IRubyObject recv, IRubyObject number) {
RubyEnumDescriptor rubyEnumDescriptor = (RubyEnumDescriptor) getDescriptor(context, recv); RubyEnumDescriptor rubyEnumDescriptor = (RubyEnumDescriptor) getDescriptor(context, recv);
return rubyEnumDescriptor.numberToName(context, number); return rubyEnumDescriptor.numberToName(context, number);
} }
/* /*
* call-seq: * call-seq:
* Enum.resolve(name) => number * Enum.resolve(name) => number
* *
* This module method, provided on each generated enum module, looks up an enum * This module method, provided on each generated enum module, looks up an enum
* value by name (as a Ruby symbol) and returns its name, or nil if not found. * value by name (as a Ruby symbol) and returns its name, or nil if not found.
*/ */
@JRubyMethod(meta = true) @JRubyMethod(meta = true)
public static IRubyObject resolve(ThreadContext context, IRubyObject recv, IRubyObject name) { public static IRubyObject resolve(ThreadContext context, IRubyObject recv, IRubyObject name) {
RubyEnumDescriptor rubyEnumDescriptor = (RubyEnumDescriptor) getDescriptor(context, recv); RubyEnumDescriptor rubyEnumDescriptor = (RubyEnumDescriptor) getDescriptor(context, recv);
return rubyEnumDescriptor.nameToNumber(context, name); return rubyEnumDescriptor.nameToNumber(context, name);
} }
/* /*
* call-seq: * call-seq:
* Enum.descriptor * Enum.descriptor
* *
* This module method, provided on each generated enum module, returns the * This module method, provided on each generated enum module, returns the
* EnumDescriptor corresponding to this enum type. * EnumDescriptor corresponding to this enum type.
*/ */
@JRubyMethod(meta = true, name = "descriptor") @JRubyMethod(meta = true, name = "descriptor")
public static IRubyObject getDescriptor(ThreadContext context, IRubyObject recv) { public static IRubyObject getDescriptor(ThreadContext context, IRubyObject recv) {
return ((RubyModule) recv).getInstanceVariable(Utils.DESCRIPTOR_INSTANCE_VAR); return ((RubyModule) recv).getInstanceVariable(Utils.DESCRIPTOR_INSTANCE_VAR);
} }
} }

@ -39,8 +39,8 @@ import com.google.protobuf.Descriptors.FileDescriptor;
import org.jruby.Ruby; import org.jruby.Ruby;
import org.jruby.RubyClass; import org.jruby.RubyClass;
import org.jruby.RubyModule; import org.jruby.RubyModule;
import org.jruby.RubyObject;
import org.jruby.RubyNumeric; import org.jruby.RubyNumeric;
import org.jruby.RubyObject;
import org.jruby.anno.JRubyClass; import org.jruby.anno.JRubyClass;
import org.jruby.anno.JRubyMethod; import org.jruby.anno.JRubyMethod;
import org.jruby.runtime.Block; import org.jruby.runtime.Block;
@ -50,132 +50,147 @@ import org.jruby.runtime.builtin.IRubyObject;
@JRubyClass(name = "EnumDescriptor", include = "Enumerable") @JRubyClass(name = "EnumDescriptor", include = "Enumerable")
public class RubyEnumDescriptor extends RubyObject { public class RubyEnumDescriptor extends RubyObject {
public static void createRubyEnumDescriptor(Ruby runtime) { public static void createRubyEnumDescriptor(Ruby runtime) {
RubyModule mProtobuf = runtime.getClassFromPath("Google::Protobuf"); RubyModule mProtobuf = runtime.getClassFromPath("Google::Protobuf");
RubyClass cEnumDescriptor = mProtobuf.defineClassUnder("EnumDescriptor", runtime.getObject(), new ObjectAllocator() { RubyClass cEnumDescriptor =
@Override mProtobuf.defineClassUnder(
public IRubyObject allocate(Ruby runtime, RubyClass klazz) { "EnumDescriptor",
runtime.getObject(),
new ObjectAllocator() {
@Override
public IRubyObject allocate(Ruby runtime, RubyClass klazz) {
return new RubyEnumDescriptor(runtime, klazz); return new RubyEnumDescriptor(runtime, klazz);
} }
}); });
cEnumDescriptor.includeModule(runtime.getEnumerable()); cEnumDescriptor.includeModule(runtime.getEnumerable());
cEnumDescriptor.defineAnnotatedMethods(RubyEnumDescriptor.class); cEnumDescriptor.defineAnnotatedMethods(RubyEnumDescriptor.class);
} }
public RubyEnumDescriptor(Ruby runtime, RubyClass klazz) { public RubyEnumDescriptor(Ruby runtime, RubyClass klazz) {
super(runtime, klazz); super(runtime, klazz);
} }
/* /*
* call-seq: * call-seq:
* EnumDescriptor.name => name * EnumDescriptor.name => name
* *
* Returns the name of this enum type. * Returns the name of this enum type.
*/ */
@JRubyMethod(name = "name") @JRubyMethod(name = "name")
public IRubyObject getName(ThreadContext context) { public IRubyObject getName(ThreadContext context) {
return this.name; return this.name;
} }
/* /*
* call-seq: * call-seq:
* EnumDescriptor.each(&block) * EnumDescriptor.each(&block)
* *
* Iterates over key => value mappings in this enum's definition, yielding to * Iterates over key => value mappings in this enum's definition, yielding to
* the block with (key, value) arguments for each one. * the block with (key, value) arguments for each one.
*/ */
@JRubyMethod @JRubyMethod
public IRubyObject each(ThreadContext context, Block block) { public IRubyObject each(ThreadContext context, Block block) {
Ruby runtime = context.runtime; Ruby runtime = context.runtime;
for (EnumValueDescriptor enumValueDescriptor : descriptor.getValues()) { for (EnumValueDescriptor enumValueDescriptor : descriptor.getValues()) {
block.yield(context, runtime.newArray(runtime.newSymbol(enumValueDescriptor.getName()), block.yield(
runtime.newFixnum(enumValueDescriptor.getNumber()))); context,
} runtime.newArray(
return context.nil; runtime.newSymbol(enumValueDescriptor.getName()),
} runtime.newFixnum(enumValueDescriptor.getNumber())));
/*
* call-seq:
* EnumDescriptor.enummodule => module
*
* Returns the Ruby module corresponding to this enum type. Cannot be called
* until the enum descriptor has been added to a pool.
*/
@JRubyMethod
public IRubyObject enummodule(ThreadContext context) {
return module;
}
/*
* call-seq:
* EnumDescriptor.file_descriptor
*
* Returns the FileDescriptor object this enum belongs to.
*/
@JRubyMethod(name = "file_descriptor")
public IRubyObject getFileDescriptor(ThreadContext context) {
return RubyFileDescriptor.getRubyFileDescriptor(context, descriptor);
}
public boolean isValidValue(ThreadContext context, IRubyObject value) {
EnumValueDescriptor enumValue;
if (Utils.isRubyNum(value)) {
enumValue = descriptor.findValueByNumberCreatingIfUnknown(RubyNumeric.num2int(value));
} else {
enumValue = descriptor.findValueByName(value.asJavaString());
}
return enumValue != null;
} }
return context.nil;
protected IRubyObject nameToNumber(ThreadContext context, IRubyObject name) { }
EnumValueDescriptor value = descriptor.findValueByName(name.asJavaString());
return value == null ? context.nil : context.runtime.newFixnum(value.getNumber()); /*
* call-seq:
* EnumDescriptor.enummodule => module
*
* Returns the Ruby module corresponding to this enum type. Cannot be called
* until the enum descriptor has been added to a pool.
*/
@JRubyMethod
public IRubyObject enummodule(ThreadContext context) {
return module;
}
/*
* call-seq:
* EnumDescriptor.file_descriptor
*
* Returns the FileDescriptor object this enum belongs to.
*/
@JRubyMethod(name = "file_descriptor")
public IRubyObject getFileDescriptor(ThreadContext context) {
return RubyFileDescriptor.getRubyFileDescriptor(context, descriptor);
}
public boolean isValidValue(ThreadContext context, IRubyObject value) {
EnumValueDescriptor enumValue;
if (Utils.isRubyNum(value)) {
enumValue = descriptor.findValueByNumberCreatingIfUnknown(RubyNumeric.num2int(value));
} else {
enumValue = descriptor.findValueByName(value.asJavaString());
} }
protected IRubyObject numberToName(ThreadContext context, IRubyObject number) { return enumValue != null;
EnumValueDescriptor value = descriptor.findValueByNumber(RubyNumeric.num2int(number)); }
return value == null ? context.nil : context.runtime.newSymbol(value.getName());
protected IRubyObject nameToNumber(ThreadContext context, IRubyObject name) {
EnumValueDescriptor value = descriptor.findValueByName(name.asJavaString());
return value == null ? context.nil : context.runtime.newFixnum(value.getNumber());
}
protected IRubyObject numberToName(ThreadContext context, IRubyObject number) {
EnumValueDescriptor value = descriptor.findValueByNumber(RubyNumeric.num2int(number));
return value == null ? context.nil : context.runtime.newSymbol(value.getName());
}
protected void setDescriptor(ThreadContext context, EnumDescriptor descriptor) {
this.descriptor = descriptor;
this.module = buildModuleFromDescriptor(context);
}
protected void setName(IRubyObject name) {
this.name = name;
}
private RubyModule buildModuleFromDescriptor(ThreadContext context) {
Ruby runtime = context.runtime;
RubyModule enumModule = RubyModule.newModule(runtime);
boolean defaultValueRequiredButNotFound =
descriptor.getFile().getSyntax() == FileDescriptor.Syntax.PROTO3;
for (EnumValueDescriptor value : descriptor.getValues()) {
String name = value.getName();
// Make sure its a valid constant name before trying to create it
if (Character.isUpperCase(name.codePointAt(0))) {
enumModule.defineConstant(name, runtime.newFixnum(value.getNumber()));
} else {
runtime
.getWarnings()
.warn(
"Enum value "
+ name
+ " does not start with an uppercase letter as is required for Ruby"
+ " constants.");
}
if (value.getNumber() == 0) {
defaultValueRequiredButNotFound = false;
}
} }
protected void setDescriptor(ThreadContext context, EnumDescriptor descriptor) { if (defaultValueRequiredButNotFound) {
this.descriptor = descriptor; throw Utils.createTypeError(
this.module = buildModuleFromDescriptor(context); context, "Enum definition " + name + " does not contain a value for '0'");
} }
enumModule.instance_variable_set(runtime.newString(Utils.DESCRIPTOR_INSTANCE_VAR), this);
protected void setName(IRubyObject name) { enumModule.defineAnnotatedMethods(RubyEnum.class);
this.name = name; return enumModule;
} }
private RubyModule buildModuleFromDescriptor(ThreadContext context) { private EnumDescriptor descriptor;
Ruby runtime = context.runtime; private EnumDescriptorProto.Builder builder;
private IRubyObject name;
RubyModule enumModule = RubyModule.newModule(runtime); private RubyModule module;
boolean defaultValueRequiredButNotFound = descriptor.getFile().getSyntax() == FileDescriptor.Syntax.PROTO3;
for (EnumValueDescriptor value : descriptor.getValues()) {
String name = value.getName();
// Make sure its a valid constant name before trying to create it
if (Character.isUpperCase(name.codePointAt(0))) {
enumModule.defineConstant(name, runtime.newFixnum(value.getNumber()));
} else {
runtime.getWarnings().warn("Enum value " + name + " does not start with an uppercase letter as is required for Ruby constants.");
}
if (value.getNumber() == 0) {
defaultValueRequiredButNotFound = false;
}
}
if (defaultValueRequiredButNotFound) {
throw Utils.createTypeError(context, "Enum definition " + name + " does not contain a value for '0'");
}
enumModule.instance_variable_set(runtime.newString(Utils.DESCRIPTOR_INSTANCE_VAR), this);
enumModule.defineAnnotatedMethods(RubyEnum.class);
return enumModule;
}
private EnumDescriptor descriptor;
private EnumDescriptorProto.Builder builder;
private IRubyObject name;
private RubyModule module;
} }

@ -43,228 +43,237 @@ import org.jruby.runtime.builtin.IRubyObject;
@JRubyClass(name = "FieldDescriptor") @JRubyClass(name = "FieldDescriptor")
public class RubyFieldDescriptor extends RubyObject { public class RubyFieldDescriptor extends RubyObject {
public static void createRubyFieldDescriptor(Ruby runtime) { public static void createRubyFieldDescriptor(Ruby runtime) {
RubyModule mProtobuf = runtime.getClassFromPath("Google::Protobuf"); RubyModule mProtobuf = runtime.getClassFromPath("Google::Protobuf");
RubyClass cFieldDescriptor = mProtobuf.defineClassUnder("FieldDescriptor", runtime.getObject(), new ObjectAllocator() { RubyClass cFieldDescriptor =
@Override mProtobuf.defineClassUnder(
public IRubyObject allocate(Ruby runtime, RubyClass klazz) { "FieldDescriptor",
runtime.getObject(),
new ObjectAllocator() {
@Override
public IRubyObject allocate(Ruby runtime, RubyClass klazz) {
return new RubyFieldDescriptor(runtime, klazz); return new RubyFieldDescriptor(runtime, klazz);
} }
}); });
cFieldDescriptor.defineAnnotatedMethods(RubyFieldDescriptor.class); cFieldDescriptor.defineAnnotatedMethods(RubyFieldDescriptor.class);
} }
public RubyFieldDescriptor(Ruby runtime, RubyClass klazz) { public RubyFieldDescriptor(Ruby runtime, RubyClass klazz) {
super(runtime, klazz); super(runtime, klazz);
} }
/* /*
* call-seq: * call-seq:
* FieldDescriptor.default => default * FieldDescriptor.default => default
* *
* Returns this field's default, as a Ruby object, or nil if not yet set. * Returns this field's default, as a Ruby object, or nil if not yet set.
*/ */
// VALUE FieldDescriptor_default(VALUE _self) { // VALUE FieldDescriptor_default(VALUE _self) {
// DEFINE_SELF(FieldDescriptor, self, _self); // DEFINE_SELF(FieldDescriptor, self, _self);
// return layout_get_default(self->fielddef); // return layout_get_default(self->fielddef);
// } // }
/* /*
* call-seq: * call-seq:
* FieldDescriptor.label => label * FieldDescriptor.label => label
* *
* Returns this field's label (i.e., plurality), as a Ruby symbol. * Returns this field's label (i.e., plurality), as a Ruby symbol.
* *
* Valid field labels are: * Valid field labels are:
* :optional, :repeated * :optional, :repeated
*/ */
@JRubyMethod(name = "label") @JRubyMethod(name = "label")
public IRubyObject getLabel(ThreadContext context) { public IRubyObject getLabel(ThreadContext context) {
if (label == null) { if (label == null) {
calculateLabel(context); calculateLabel(context);
}
return label;
} }
return label;
}
/* /*
* call-seq: * call-seq:
* FieldDescriptor.name => name * FieldDescriptor.name => name
* *
* Returns the name of this field as a Ruby String, or nil if it is not set. * Returns the name of this field as a Ruby String, or nil if it is not set.
*/ */
@JRubyMethod(name = "name") @JRubyMethod(name = "name")
public IRubyObject getName(ThreadContext context) { public IRubyObject getName(ThreadContext context) {
return this.name; return this.name;
} }
/* /*
* call-seq: * call-seq:
* FieldDescriptor.subtype => message_or_enum_descriptor * FieldDescriptor.subtype => message_or_enum_descriptor
* *
* Returns the message or enum descriptor corresponding to this field's type if * Returns the message or enum descriptor corresponding to this field's type if
* it is a message or enum field, respectively, or nil otherwise. Cannot be * it is a message or enum field, respectively, or nil otherwise. Cannot be
* called *until* the containing message type is added to a pool (and thus * called *until* the containing message type is added to a pool (and thus
* resolved). * resolved).
*/ */
@JRubyMethod(name = "subtype") @JRubyMethod(name = "subtype")
public IRubyObject getSubtype(ThreadContext context) { public IRubyObject getSubtype(ThreadContext context) {
if (subtype == null) { if (subtype == null) {
calculateSubtype(context); calculateSubtype(context);
}
return subtype;
} }
return subtype;
}
/* /*
* call-seq: * call-seq:
* FieldDescriptor.type => type * FieldDescriptor.type => type
* *
* Returns this field's type, as a Ruby symbol, or nil if not yet set. * Returns this field's type, as a Ruby symbol, or nil if not yet set.
* *
* Valid field types are: * Valid field types are:
* :int32, :int64, :uint32, :uint64, :float, :double, :bool, :string, * :int32, :int64, :uint32, :uint64, :float, :double, :bool, :string,
* :bytes, :message. * :bytes, :message.
*/ */
@JRubyMethod(name = "type") @JRubyMethod(name = "type")
public IRubyObject getType(ThreadContext context) { public IRubyObject getType(ThreadContext context) {
return Utils.fieldTypeToRuby(context, descriptor.getType()); return Utils.fieldTypeToRuby(context, descriptor.getType());
} }
/* /*
* call-seq: * call-seq:
* FieldDescriptor.number => number * FieldDescriptor.number => number
* *
* Returns the tag number for this field. * Returns the tag number for this field.
*/ */
@JRubyMethod(name = "number") @JRubyMethod(name = "number")
public IRubyObject getNumber(ThreadContext context) { public IRubyObject getNumber(ThreadContext context) {
return this.number; return this.number;
} }
/* /*
* call-seq: * call-seq:
* FieldDescriptor.submsg_name => submsg_name * FieldDescriptor.submsg_name => submsg_name
* *
* Returns the name of the message or enum type corresponding to this field, if * Returns the name of the message or enum type corresponding to this field, if
* it is a message or enum field (respectively), or nil otherwise. This type * it is a message or enum field (respectively), or nil otherwise. This type
* name will be resolved within the context of the pool to which the containing * name will be resolved within the context of the pool to which the containing
* message type is added. * message type is added.
*/ */
// VALUE FieldDescriptor_submsg_name(VALUE _self) { // VALUE FieldDescriptor_submsg_name(VALUE _self) {
// DEFINE_SELF(FieldDescriptor, self, _self); // DEFINE_SELF(FieldDescriptor, self, _self);
// switch (upb_fielddef_type(self->fielddef)) { // switch (upb_fielddef_type(self->fielddef)) {
// case UPB_TYPE_ENUM: // case UPB_TYPE_ENUM:
// return rb_str_new2( // return rb_str_new2(
// upb_enumdef_fullname(upb_fielddef_enumsubdef(self->fielddef))); // upb_enumdef_fullname(upb_fielddef_enumsubdef(self->fielddef)));
// case UPB_TYPE_MESSAGE: // case UPB_TYPE_MESSAGE:
// return rb_str_new2( // return rb_str_new2(
// upb_msgdef_fullname(upb_fielddef_msgsubdef(self->fielddef))); // upb_msgdef_fullname(upb_fielddef_msgsubdef(self->fielddef)));
// default: // default:
// return Qnil; // return Qnil;
// } // }
// } // }
/* /*
* call-seq: * call-seq:
* FieldDescriptor.submsg_name = submsg_name * FieldDescriptor.submsg_name = submsg_name
* *
* Sets the name of the message or enum type corresponding to this field, if it * Sets the name of the message or enum type corresponding to this field, if it
* is a message or enum field (respectively). This type name will be resolved * is a message or enum field (respectively). This type name will be resolved
* within the context of the pool to which the containing message type is added. * within the context of the pool to which the containing message type is added.
* Cannot be called on field that are not of message or enum type, or on fields * Cannot be called on field that are not of message or enum type, or on fields
* that are part of a message type already added to a pool. * that are part of a message type already added to a pool.
*/ */
// @JRubyMethod(name = "submsg_name=") // @JRubyMethod(name = "submsg_name=")
// public IRubyObject setSubmsgName(ThreadContext context, IRubyObject name) { // public IRubyObject setSubmsgName(ThreadContext context, IRubyObject name) {
// this.builder.setTypeName("." + Utils.escapeIdentifier(name.asJavaString())); // this.builder.setTypeName("." + Utils.escapeIdentifier(name.asJavaString()));
// return context.runtime.getNil(); // return context.runtime.getNil();
// } // }
/* /*
* call-seq: * call-seq:
* FieldDescriptor.clear(message) * FieldDescriptor.clear(message)
* *
* Clears the field from the message if it's set. * Clears the field from the message if it's set.
*/ */
@JRubyMethod(name = "clear") @JRubyMethod(name = "clear")
public IRubyObject clearValue(ThreadContext context, IRubyObject message) { public IRubyObject clearValue(ThreadContext context, IRubyObject message) {
return ((RubyMessage) message).clearField(context, descriptor); return ((RubyMessage) message).clearField(context, descriptor);
} }
/* /*
* call-seq: * call-seq:
* FieldDescriptor.get(message) => value * FieldDescriptor.get(message) => value
* *
* Returns the value set for this field on the given message. Raises an * Returns the value set for this field on the given message. Raises an
* exception if message is of the wrong type. * exception if message is of the wrong type.
*/ */
@JRubyMethod(name = "get") @JRubyMethod(name = "get")
public IRubyObject getValue(ThreadContext context, IRubyObject message) { public IRubyObject getValue(ThreadContext context, IRubyObject message) {
return ((RubyMessage) message).getField(context, descriptor); return ((RubyMessage) message).getField(context, descriptor);
} }
/* /*
* call-seq: * call-seq:
* FieldDescriptor.has?(message) => boolean * FieldDescriptor.has?(message) => boolean
* *
* Returns whether the value is set on the given message. Raises an * Returns whether the value is set on the given message. Raises an
* exception when calling for fields that do not have presence. * exception when calling for fields that do not have presence.
*/ */
@JRubyMethod(name = "has?") @JRubyMethod(name = "has?")
public IRubyObject has(ThreadContext context, IRubyObject message) { public IRubyObject has(ThreadContext context, IRubyObject message) {
return ((RubyMessage) message).hasField(context, descriptor); return ((RubyMessage) message).hasField(context, descriptor);
} }
/* /*
* call-seq: * call-seq:
* FieldDescriptor.set(message, value) * FieldDescriptor.set(message, value)
* *
* Sets the value corresponding to this field to the given value on the given * Sets the value corresponding to this field to the given value on the given
* message. Raises an exception if message is of the wrong type. Performs the * message. Raises an exception if message is of the wrong type. Performs the
* ordinary type-checks for field setting. * ordinary type-checks for field setting.
*/ */
@JRubyMethod(name = "set") @JRubyMethod(name = "set")
public IRubyObject setValue(ThreadContext context, IRubyObject message, IRubyObject value) { public IRubyObject setValue(ThreadContext context, IRubyObject message, IRubyObject value) {
((RubyMessage) message).setField(context, descriptor, value); ((RubyMessage) message).setField(context, descriptor, value);
return context.nil; return context.nil;
} }
protected void setDescriptor(ThreadContext context, FieldDescriptor descriptor, RubyDescriptorPool pool) { protected void setDescriptor(
if (descriptor.isRequired() && descriptor.getFile().getSyntax() == FileDescriptor.Syntax.PROTO3) { ThreadContext context, FieldDescriptor descriptor, RubyDescriptorPool pool) {
throw Utils.createTypeError(context, descriptor.getName() + " is labeled required but required fields are unsupported in proto3"); if (descriptor.isRequired()
} && descriptor.getFile().getSyntax() == FileDescriptor.Syntax.PROTO3) {
this.descriptor = descriptor; throw Utils.createTypeError(
this.name = context.runtime.newString(descriptor.getName()); context,
this.pool = pool; descriptor.getName()
+ " is labeled required but required fields are unsupported in proto3");
} }
this.descriptor = descriptor;
this.name = context.runtime.newString(descriptor.getName());
this.pool = pool;
}
private void calculateLabel(ThreadContext context) { private void calculateLabel(ThreadContext context) {
if (descriptor.isRepeated()) { if (descriptor.isRepeated()) {
this.label = context.runtime.newSymbol("repeated"); this.label = context.runtime.newSymbol("repeated");
} else if (descriptor.isOptional()) { } else if (descriptor.isOptional()) {
this.label = context.runtime.newSymbol("optional"); this.label = context.runtime.newSymbol("optional");
} else { } else {
this.label = context.nil; this.label = context.nil;
}
} }
}
private void calculateSubtype(ThreadContext context) { private void calculateSubtype(ThreadContext context) {
FieldDescriptor.Type fdType = descriptor.getType(); FieldDescriptor.Type fdType = descriptor.getType();
if (fdType == FieldDescriptor.Type.MESSAGE) { if (fdType == FieldDescriptor.Type.MESSAGE) {
RubyString messageName = context.runtime.newString(descriptor.getMessageType().getFullName()); RubyString messageName = context.runtime.newString(descriptor.getMessageType().getFullName());
this.subtype = pool.lookup(context, messageName); this.subtype = pool.lookup(context, messageName);
} else if (fdType == FieldDescriptor.Type.ENUM) { } else if (fdType == FieldDescriptor.Type.ENUM) {
RubyString enumName = context.runtime.newString(descriptor.getEnumType().getFullName()); RubyString enumName = context.runtime.newString(descriptor.getEnumType().getFullName());
this.subtype = pool.lookup(context, enumName); this.subtype = pool.lookup(context, enumName);
} else { } else {
this.subtype = context.nil; this.subtype = context.nil;
}
} }
}
private static final String DOT = "."; private static final String DOT = ".";
private FieldDescriptor descriptor; private FieldDescriptor descriptor;
private IRubyObject name; private IRubyObject name;
private IRubyObject label; private IRubyObject label;
private IRubyObject number; private IRubyObject number;
private IRubyObject subtype; private IRubyObject subtype;
private RubyDescriptorPool pool; private RubyDescriptorPool pool;
} }

@ -32,7 +32,6 @@
package com.google.protobuf.jruby; package com.google.protobuf.jruby;
import com.google.protobuf.Descriptors.Descriptor;
import com.google.protobuf.Descriptors.FileDescriptor; import com.google.protobuf.Descriptors.FileDescriptor;
import com.google.protobuf.Descriptors.FileDescriptor.Syntax.*; import com.google.protobuf.Descriptors.FileDescriptor.Syntax.*;
import com.google.protobuf.Descriptors.GenericDescriptor; import com.google.protobuf.Descriptors.GenericDescriptor;
@ -46,61 +45,67 @@ import org.jruby.runtime.builtin.IRubyObject;
@JRubyClass(name = "FileDescriptor") @JRubyClass(name = "FileDescriptor")
public class RubyFileDescriptor extends RubyObject { public class RubyFileDescriptor extends RubyObject {
public static void createRubyFileDescriptor(Ruby runtime) { public static void createRubyFileDescriptor(Ruby runtime) {
RubyModule mProtobuf = runtime.getClassFromPath("Google::Protobuf"); RubyModule mProtobuf = runtime.getClassFromPath("Google::Protobuf");
cFileDescriptor = mProtobuf.defineClassUnder("FileDescriptor", runtime.getObject(), new ObjectAllocator() { cFileDescriptor =
@Override mProtobuf.defineClassUnder(
public IRubyObject allocate(Ruby runtime, RubyClass klazz) { "FileDescriptor",
runtime.getObject(),
new ObjectAllocator() {
@Override
public IRubyObject allocate(Ruby runtime, RubyClass klazz) {
return new RubyFileDescriptor(runtime, klazz); return new RubyFileDescriptor(runtime, klazz);
} }
}); });
cFileDescriptor.defineAnnotatedMethods(RubyFileDescriptor.class); cFileDescriptor.defineAnnotatedMethods(RubyFileDescriptor.class);
} }
public static RubyFileDescriptor getRubyFileDescriptor(ThreadContext context, GenericDescriptor descriptor) { public static RubyFileDescriptor getRubyFileDescriptor(
RubyFileDescriptor rfd = (RubyFileDescriptor) cFileDescriptor.newInstance(context, Block.NULL_BLOCK); ThreadContext context, GenericDescriptor descriptor) {
rfd.fileDescriptor = descriptor.getFile(); RubyFileDescriptor rfd =
return rfd; (RubyFileDescriptor) cFileDescriptor.newInstance(context, Block.NULL_BLOCK);
} rfd.fileDescriptor = descriptor.getFile();
return rfd;
}
public RubyFileDescriptor(Ruby runtime, RubyClass klazz) { public RubyFileDescriptor(Ruby runtime, RubyClass klazz) {
super(runtime, klazz); super(runtime, klazz);
} }
/* /*
* call-seq: * call-seq:
* FileDescriptor.name => name * FileDescriptor.name => name
* *
* Returns the name of the file. * Returns the name of the file.
*/ */
@JRubyMethod(name = "name") @JRubyMethod(name = "name")
public IRubyObject getName(ThreadContext context) { public IRubyObject getName(ThreadContext context) {
String name = fileDescriptor.getName(); String name = fileDescriptor.getName();
return name == null ? context.nil : context.runtime.newString(name); return name == null ? context.nil : context.runtime.newString(name);
} }
/* /*
* call-seq: * call-seq:
* FileDescriptor.syntax => syntax * FileDescriptor.syntax => syntax
* *
* Returns this file descriptors syntax. * Returns this file descriptors syntax.
* *
* Valid syntax versions are: * Valid syntax versions are:
* :proto2 or :proto3. * :proto2 or :proto3.
*/ */
@JRubyMethod(name = "syntax") @JRubyMethod(name = "syntax")
public IRubyObject getSyntax(ThreadContext context) { public IRubyObject getSyntax(ThreadContext context) {
switch (fileDescriptor.getSyntax()) { switch (fileDescriptor.getSyntax()) {
case PROTO2: case PROTO2:
return context.runtime.newSymbol("proto2"); return context.runtime.newSymbol("proto2");
case PROTO3: case PROTO3:
return context.runtime.newSymbol("proto3"); return context.runtime.newSymbol("proto3");
default: default:
return context.nil; return context.nil;
}
} }
}
private static RubyClass cFileDescriptor; private static RubyClass cFileDescriptor;
private FileDescriptor fileDescriptor; private FileDescriptor fileDescriptor;
} }

@ -34,6 +34,13 @@ package com.google.protobuf.jruby;
import com.google.protobuf.Descriptors.FieldDescriptor; import com.google.protobuf.Descriptors.FieldDescriptor;
import com.google.protobuf.DynamicMessage; import com.google.protobuf.DynamicMessage;
import java.nio.ByteBuffer;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.jruby.*; import org.jruby.*;
import org.jruby.anno.JRubyClass; import org.jruby.anno.JRubyClass;
import org.jruby.anno.JRubyMethod; import org.jruby.anno.JRubyMethod;
@ -43,432 +50,438 @@ import org.jruby.runtime.ObjectAllocator;
import org.jruby.runtime.ThreadContext; import org.jruby.runtime.ThreadContext;
import org.jruby.runtime.builtin.IRubyObject; import org.jruby.runtime.builtin.IRubyObject;
import java.nio.ByteBuffer;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@JRubyClass(name = "Map", include = "Enumerable") @JRubyClass(name = "Map", include = "Enumerable")
public class RubyMap extends RubyObject { public class RubyMap extends RubyObject {
public static void createRubyMap(Ruby runtime) { public static void createRubyMap(Ruby runtime) {
RubyModule protobuf = runtime.getClassFromPath("Google::Protobuf"); RubyModule protobuf = runtime.getClassFromPath("Google::Protobuf");
RubyClass cMap = protobuf.defineClassUnder("Map", runtime.getObject(), new ObjectAllocator() { RubyClass cMap =
@Override protobuf.defineClassUnder(
public IRubyObject allocate(Ruby ruby, RubyClass rubyClass) { "Map",
runtime.getObject(),
new ObjectAllocator() {
@Override
public IRubyObject allocate(Ruby ruby, RubyClass rubyClass) {
return new RubyMap(ruby, rubyClass); return new RubyMap(ruby, rubyClass);
} }
}); });
cMap.includeModule(runtime.getEnumerable()); cMap.includeModule(runtime.getEnumerable());
cMap.defineAnnotatedMethods(RubyMap.class); cMap.defineAnnotatedMethods(RubyMap.class);
} }
public RubyMap(Ruby ruby, RubyClass rubyClass) { public RubyMap(Ruby ruby, RubyClass rubyClass) {
super(ruby, rubyClass); super(ruby, rubyClass);
}
/*
* call-seq:
* Map.new(key_type, value_type, value_typeclass = nil, init_hashmap = {})
* => new map
*
* Allocates a new Map container. This constructor may be called with 2, 3, or 4
* arguments. The first two arguments are always present and are symbols (taking
* on the same values as field-type symbols in message descriptors) that
* indicate the type of the map key and value fields.
*
* The supported key types are: :int32, :int64, :uint32, :uint64, :fixed32,
* :fixed64, :sfixed32, :sfixed64, :sint32, :sint64, :bool, :string, :bytes.
*
* The supported value types are: :int32, :int64, :uint32, :uint64, :fixed32,
* :fixed64, :sfixed32, :sfixed64, :sint32, :sint64, :bool, :string, :bytes,
* :enum, :message.
*
* The third argument, value_typeclass, must be present if value_type is :enum
* or :message. As in RepeatedField#new, this argument must be a message class
* (for :message) or enum module (for :enum).
*
* The last argument, if present, provides initial content for map. Note that
* this may be an ordinary Ruby hashmap or another Map instance with identical
* key and value types. Also note that this argument may be present whether or
* not value_typeclass is present (and it is unambiguously separate from
* value_typeclass because value_typeclass's presence is strictly determined by
* value_type). The contents of this initial hashmap or Map instance are
* shallow-copied into the new Map: the original map is unmodified, but
* references to underlying objects will be shared if the value type is a
* message type.
*/
@JRubyMethod(required = 2, optional = 2)
public IRubyObject initialize(ThreadContext context, IRubyObject[] args) {
this.table = new HashMap<IRubyObject, IRubyObject>();
this.keyType = Utils.rubyToFieldType(args[0]);
this.valueType = Utils.rubyToFieldType(args[1]);
switch (keyType) {
case STRING:
case BYTES:
this.keyTypeIsString = true;
break;
case INT32:
case INT64:
case SINT32:
case SINT64:
case UINT32:
case UINT64:
case FIXED32:
case FIXED64:
case SFIXED32:
case SFIXED64:
case BOOL:
// These are OK.
break;
default:
throw context.runtime.newArgumentError("Invalid key type for map.");
} }
/* int initValueArg = 2;
* call-seq: if (needTypeclass(this.valueType) && args.length > 2) {
* Map.new(key_type, value_type, value_typeclass = nil, init_hashmap = {}) this.valueTypeClass = args[2];
* => new map Utils.validateTypeClass(context, this.valueType, this.valueTypeClass);
* initValueArg = 3;
* Allocates a new Map container. This constructor may be called with 2, 3, or 4 } else {
* arguments. The first two arguments are always present and are symbols (taking this.valueTypeClass = context.runtime.getNilClass();
* on the same values as field-type symbols in message descriptors) that
* indicate the type of the map key and value fields.
*
* The supported key types are: :int32, :int64, :uint32, :uint64, :fixed32,
* :fixed64, :sfixed32, :sfixed64, :sint32, :sint64, :bool, :string, :bytes.
*
* The supported value types are: :int32, :int64, :uint32, :uint64, :fixed32,
* :fixed64, :sfixed32, :sfixed64, :sint32, :sint64, :bool, :string, :bytes,
* :enum, :message.
*
* The third argument, value_typeclass, must be present if value_type is :enum
* or :message. As in RepeatedField#new, this argument must be a message class
* (for :message) or enum module (for :enum).
*
* The last argument, if present, provides initial content for map. Note that
* this may be an ordinary Ruby hashmap or another Map instance with identical
* key and value types. Also note that this argument may be present whether or
* not value_typeclass is present (and it is unambiguously separate from
* value_typeclass because value_typeclass's presence is strictly determined by
* value_type). The contents of this initial hashmap or Map instance are
* shallow-copied into the new Map: the original map is unmodified, but
* references to underlying objects will be shared if the value type is a
* message type.
*/
@JRubyMethod(required = 2, optional = 2)
public IRubyObject initialize(ThreadContext context, IRubyObject[] args) {
this.table = new HashMap<IRubyObject, IRubyObject>();
this.keyType = Utils.rubyToFieldType(args[0]);
this.valueType = Utils.rubyToFieldType(args[1]);
switch(keyType) {
case STRING:
case BYTES:
this.keyTypeIsString = true;
break;
case INT32:
case INT64:
case SINT32:
case SINT64:
case UINT32:
case UINT64:
case FIXED32:
case FIXED64:
case SFIXED32:
case SFIXED64:
case BOOL:
// These are OK.
break;
default:
throw context.runtime.newArgumentError("Invalid key type for map.");
}
int initValueArg = 2;
if (needTypeclass(this.valueType) && args.length > 2) {
this.valueTypeClass = args[2];
Utils.validateTypeClass(context, this.valueType, this.valueTypeClass);
initValueArg = 3;
} else {
this.valueTypeClass = context.runtime.getNilClass();
}
if (args.length > initValueArg) {
mergeIntoSelf(context, args[initValueArg]);
}
return this;
} }
/* if (args.length > initValueArg) {
* call-seq: mergeIntoSelf(context, args[initValueArg]);
* Map.[]=(key, value) => value
*
* Inserts or overwrites the value at the given key with the given new value.
* Throws an exception if the key type is incorrect. Returns the new value that
* was just inserted.
*/
@JRubyMethod(name = "[]=")
public IRubyObject indexSet(ThreadContext context, IRubyObject key, IRubyObject value) {
checkFrozen();
/*
* String types for keys return a different error than
* other types for keys, so deal with them specifically first
*/
if (keyTypeIsString && !(key instanceof RubySymbol || key instanceof RubyString)) {
throw Utils.createTypeError(context, "Expected string for map key");
}
key = Utils.checkType(context, keyType, "key", key, (RubyModule) valueTypeClass);
value = Utils.checkType(context, valueType, "value", value, (RubyModule) valueTypeClass);
IRubyObject symbol;
if (valueType == FieldDescriptor.Type.ENUM &&
Utils.isRubyNum(value) &&
! (symbol = RubyEnum.lookup(context, valueTypeClass, value)).isNil()) {
value = symbol;
}
this.table.put(key, value);
return value;
} }
return this;
}
/*
* call-seq:
* Map.[]=(key, value) => value
*
* Inserts or overwrites the value at the given key with the given new value.
* Throws an exception if the key type is incorrect. Returns the new value that
* was just inserted.
*/
@JRubyMethod(name = "[]=")
public IRubyObject indexSet(ThreadContext context, IRubyObject key, IRubyObject value) {
checkFrozen();
/* /*
* call-seq: * String types for keys return a different error than
* Map.[](key) => value * other types for keys, so deal with them specifically first
*
* Accesses the element at the given key. Throws an exception if the key type is
* incorrect. Returns nil when the key is not present in the map.
*/ */
@JRubyMethod(name = "[]") if (keyTypeIsString && !(key instanceof RubySymbol || key instanceof RubyString)) {
public IRubyObject index(ThreadContext context, IRubyObject key) { throw Utils.createTypeError(context, "Expected string for map key");
key = Utils.symToString(key);
return Helpers.nullToNil(table.get(key), context.nil);
} }
key = Utils.checkType(context, keyType, "key", key, (RubyModule) valueTypeClass);
/* value = Utils.checkType(context, valueType, "value", value, (RubyModule) valueTypeClass);
* call-seq: IRubyObject symbol;
* Map.==(other) => boolean if (valueType == FieldDescriptor.Type.ENUM
* && Utils.isRubyNum(value)
* Compares this map to another. Maps are equal if they have identical key sets, && !(symbol = RubyEnum.lookup(context, valueTypeClass, value)).isNil()) {
* and for each key, the values in both maps compare equal. Elements are value = symbol;
* compared as per normal Ruby semantics, by calling their :== methods (or
* performing a more efficient comparison for primitive types).
*
* Maps with dissimilar key types or value types/typeclasses are never equal,
* even if value comparison (for example, between integers and floats) would
* have otherwise indicated that every element has equal value.
*/
@JRubyMethod(name = "==")
public IRubyObject eq(ThreadContext context, IRubyObject _other) {
if (_other instanceof RubyHash)
return singleLevelHash(context).op_equal(context, _other);
RubyMap other = (RubyMap) _other;
if (this == other) return context.runtime.getTrue();
if (!typeCompatible(other) || this.table.size() != other.table.size())
return context.runtime.getFalse();
for (IRubyObject key : table.keySet()) {
if (! other.table.containsKey(key))
return context.runtime.getFalse();
if (! other.table.get(key).equals(table.get(key)))
return context.runtime.getFalse();
}
return context.runtime.getTrue();
} }
this.table.put(key, value);
/* return value;
* call-seq: }
* Map.inspect => string
* /*
* Returns a string representing this map's elements. It will be formatted as * call-seq:
* "{key => value, key => value, ...}", with each key and value string * Map.[](key) => value
* representation computed by its own #inspect method. *
*/ * Accesses the element at the given key. Throws an exception if the key type is
@JRubyMethod * incorrect. Returns nil when the key is not present in the map.
public IRubyObject inspect() { */
return singleLevelHash(getRuntime().getCurrentContext()).inspect(); @JRubyMethod(name = "[]")
public IRubyObject index(ThreadContext context, IRubyObject key) {
key = Utils.symToString(key);
return Helpers.nullToNil(table.get(key), context.nil);
}
/*
* call-seq:
* Map.==(other) => boolean
*
* Compares this map to another. Maps are equal if they have identical key sets,
* and for each key, the values in both maps compare equal. Elements are
* compared as per normal Ruby semantics, by calling their :== methods (or
* performing a more efficient comparison for primitive types).
*
* Maps with dissimilar key types or value types/typeclasses are never equal,
* even if value comparison (for example, between integers and floats) would
* have otherwise indicated that every element has equal value.
*/
@JRubyMethod(name = "==")
public IRubyObject eq(ThreadContext context, IRubyObject _other) {
if (_other instanceof RubyHash) return singleLevelHash(context).op_equal(context, _other);
RubyMap other = (RubyMap) _other;
if (this == other) return context.runtime.getTrue();
if (!typeCompatible(other) || this.table.size() != other.table.size())
return context.runtime.getFalse();
for (IRubyObject key : table.keySet()) {
if (!other.table.containsKey(key)) return context.runtime.getFalse();
if (!other.table.get(key).equals(table.get(key))) return context.runtime.getFalse();
} }
return context.runtime.getTrue();
/* }
* call-seq:
* Map.hash => hash_value /*
* * call-seq:
* Returns a hash value based on this map's contents. * Map.inspect => string
*/ *
@JRubyMethod * Returns a string representing this map's elements. It will be formatted as
public IRubyObject hash(ThreadContext context) { * "{key => value, key => value, ...}", with each key and value string
try { * representation computed by its own #inspect method.
MessageDigest digest = MessageDigest.getInstance("SHA-256"); */
for (IRubyObject key : table.keySet()) { @JRubyMethod
digest.update((byte) key.hashCode()); public IRubyObject inspect() {
digest.update((byte) table.get(key).hashCode()); return singleLevelHash(getRuntime().getCurrentContext()).inspect();
} }
return context.runtime.newFixnum(ByteBuffer.wrap(digest.digest()).getLong());
} catch (NoSuchAlgorithmException ignore) { /*
return context.runtime.newFixnum(System.identityHashCode(table)); * call-seq:
} * Map.hash => hash_value
*
* Returns a hash value based on this map's contents.
*/
@JRubyMethod
public IRubyObject hash(ThreadContext context) {
try {
MessageDigest digest = MessageDigest.getInstance("SHA-256");
for (IRubyObject key : table.keySet()) {
digest.update((byte) key.hashCode());
digest.update((byte) table.get(key).hashCode());
}
return context.runtime.newFixnum(ByteBuffer.wrap(digest.digest()).getLong());
} catch (NoSuchAlgorithmException ignore) {
return context.runtime.newFixnum(System.identityHashCode(table));
} }
}
/*
* call-seq: /*
* Map.keys => [list_of_keys] * call-seq:
* * Map.keys => [list_of_keys]
* Returns the list of keys contained in the map, in unspecified order. *
*/ * Returns the list of keys contained in the map, in unspecified order.
@JRubyMethod */
public IRubyObject keys(ThreadContext context) { @JRubyMethod
return RubyArray.newArray(context.runtime, table.keySet()); public IRubyObject keys(ThreadContext context) {
return RubyArray.newArray(context.runtime, table.keySet());
}
/*
* call-seq:
* Map.values => [list_of_values]
*
* Returns the list of values contained in the map, in unspecified order.
*/
@JRubyMethod
public IRubyObject values(ThreadContext context) {
return RubyArray.newArray(context.runtime, table.values());
}
/*
* call-seq:
* Map.clear
*
* Removes all entries from the map.
*/
@JRubyMethod
public IRubyObject clear(ThreadContext context) {
checkFrozen();
table.clear();
return context.nil;
}
/*
* call-seq:
* Map.each(&block)
*
* Invokes &block on each |key, value| pair in the map, in unspecified order.
* Note that Map also includes Enumerable; map thus acts like a normal Ruby
* sequence.
*/
@JRubyMethod
public IRubyObject each(ThreadContext context, Block block) {
for (IRubyObject key : table.keySet()) {
block.yieldSpecific(context, key, table.get(key));
} }
return context.nil;
/* }
* call-seq:
* Map.values => [list_of_values] /*
* * call-seq:
* Returns the list of values contained in the map, in unspecified order. * Map.delete(key) => old_value
*/ *
@JRubyMethod * Deletes the value at the given key, if any, returning either the old value or
public IRubyObject values(ThreadContext context) { * nil if none was present. Throws an exception if the key is of the wrong type.
return RubyArray.newArray(context.runtime, table.values()); */
@JRubyMethod
public IRubyObject delete(ThreadContext context, IRubyObject key) {
checkFrozen();
return table.remove(key);
}
/*
* call-seq:
* Map.has_key?(key) => bool
*
* Returns true if the given key is present in the map. Throws an exception if
* the key has the wrong type.
*/
@JRubyMethod(name = "has_key?")
public IRubyObject hasKey(ThreadContext context, IRubyObject key) {
return this.table.containsKey(key) ? context.runtime.getTrue() : context.runtime.getFalse();
}
/*
* call-seq:
* Map.length
*
* Returns the number of entries (key-value pairs) in the map.
*/
@JRubyMethod(name = {"length", "size"})
public IRubyObject length(ThreadContext context) {
return context.runtime.newFixnum(this.table.size());
}
/*
* call-seq:
* Map.dup => new_map
*
* Duplicates this map with a shallow copy. References to all non-primitive
* element objects (e.g., submessages) are shared.
*/
@JRubyMethod
public IRubyObject dup(ThreadContext context) {
RubyMap newMap = newThisType(context);
for (Map.Entry<IRubyObject, IRubyObject> entry : table.entrySet()) {
newMap.table.put(entry.getKey(), entry.getValue());
} }
return newMap;
/* }
* call-seq:
* Map.clear @JRubyMethod(name = "to_h")
* public RubyHash toHash(ThreadContext context) {
* Removes all entries from the map. Map<IRubyObject, IRubyObject> mapForHash = new HashMap();
*/
@JRubyMethod table.forEach(
public IRubyObject clear(ThreadContext context) { (key, value) -> {
checkFrozen(); if (!value.isNil()) {
table.clear(); if (value.respondsTo("to_h")) {
return context.nil; value = Helpers.invoke(context, value, "to_h");
} } else if (value.respondsTo("to_a")) {
value = Helpers.invoke(context, value, "to_a");
/*
* call-seq:
* Map.each(&block)
*
* Invokes &block on each |key, value| pair in the map, in unspecified order.
* Note that Map also includes Enumerable; map thus acts like a normal Ruby
* sequence.
*/
@JRubyMethod
public IRubyObject each(ThreadContext context, Block block) {
for (IRubyObject key : table.keySet()) {
block.yieldSpecific(context, key, table.get(key));
}
return context.nil;
}
/*
* call-seq:
* Map.delete(key) => old_value
*
* Deletes the value at the given key, if any, returning either the old value or
* nil if none was present. Throws an exception if the key is of the wrong type.
*/
@JRubyMethod
public IRubyObject delete(ThreadContext context, IRubyObject key) {
checkFrozen();
return table.remove(key);
}
/*
* call-seq:
* Map.has_key?(key) => bool
*
* Returns true if the given key is present in the map. Throws an exception if
* the key has the wrong type.
*/
@JRubyMethod(name = "has_key?")
public IRubyObject hasKey(ThreadContext context, IRubyObject key) {
return this.table.containsKey(key) ? context.runtime.getTrue() : context.runtime.getFalse();
}
/*
* call-seq:
* Map.length
*
* Returns the number of entries (key-value pairs) in the map.
*/
@JRubyMethod(name = {"length", "size"})
public IRubyObject length(ThreadContext context) {
return context.runtime.newFixnum(this.table.size());
}
/*
* call-seq:
* Map.dup => new_map
*
* Duplicates this map with a shallow copy. References to all non-primitive
* element objects (e.g., submessages) are shared.
*/
@JRubyMethod
public IRubyObject dup(ThreadContext context) {
RubyMap newMap = newThisType(context);
for (Map.Entry<IRubyObject, IRubyObject> entry : table.entrySet()) {
newMap.table.put(entry.getKey(), entry.getValue());
}
return newMap;
}
@JRubyMethod(name = "to_h")
public RubyHash toHash(ThreadContext context) {
Map<IRubyObject, IRubyObject> mapForHash = new HashMap();
table.forEach((key, value) -> {
if (!value.isNil()) {
if (value.respondsTo("to_h")) {
value = Helpers.invoke(context, value, "to_h");
} else if (value.respondsTo("to_a")) {
value = Helpers.invoke(context, value, "to_a");
}
mapForHash.put(key, value);
} }
mapForHash.put(key, value);
}
}); });
return RubyHash.newHash(context.runtime, mapForHash, context.nil); return RubyHash.newHash(context.runtime, mapForHash, context.nil);
} }
// Used by Google::Protobuf.deep_copy but not exposed directly. // Used by Google::Protobuf.deep_copy but not exposed directly.
protected IRubyObject deepCopy(ThreadContext context) { protected IRubyObject deepCopy(ThreadContext context) {
RubyMap newMap = newThisType(context); RubyMap newMap = newThisType(context);
switch (valueType) { switch (valueType) {
case MESSAGE: case MESSAGE:
for (IRubyObject key : table.keySet()) { for (IRubyObject key : table.keySet()) {
RubyMessage message = (RubyMessage) table.get(key); RubyMessage message = (RubyMessage) table.get(key);
newMap.table.put(key.dup(), message.deepCopy(context)); newMap.table.put(key.dup(), message.deepCopy(context));
}
break;
default:
for (IRubyObject key : table.keySet()) {
newMap.table.put(key.dup(), table.get(key).dup());
}
} }
return newMap; break;
} default:
protected List<DynamicMessage> build(ThreadContext context, RubyDescriptor descriptor, int depth, int recursionLimit) {
List<DynamicMessage> list = new ArrayList<DynamicMessage>();
RubyClass rubyClass = (RubyClass) descriptor.msgclass(context);
FieldDescriptor keyField = descriptor.getField("key");
FieldDescriptor valueField = descriptor.getField("value");
for (IRubyObject key : table.keySet()) { for (IRubyObject key : table.keySet()) {
RubyMessage mapMessage = (RubyMessage) rubyClass.newInstance(context, Block.NULL_BLOCK); newMap.table.put(key.dup(), table.get(key).dup());
mapMessage.setField(context, keyField, key);
mapMessage.setField(context, valueField, table.get(key));
list.add(mapMessage.build(context, depth + 1, recursionLimit));
} }
return list;
} }
return newMap;
protected RubyMap mergeIntoSelf(final ThreadContext context, IRubyObject hashmap) { }
if (hashmap instanceof RubyHash) {
((RubyHash) hashmap).visitAll(context, new RubyHash.Visitor() { protected List<DynamicMessage> build(
ThreadContext context, RubyDescriptor descriptor, int depth, int recursionLimit) {
List<DynamicMessage> list = new ArrayList<DynamicMessage>();
RubyClass rubyClass = (RubyClass) descriptor.msgclass(context);
FieldDescriptor keyField = descriptor.getField("key");
FieldDescriptor valueField = descriptor.getField("value");
for (IRubyObject key : table.keySet()) {
RubyMessage mapMessage = (RubyMessage) rubyClass.newInstance(context, Block.NULL_BLOCK);
mapMessage.setField(context, keyField, key);
mapMessage.setField(context, valueField, table.get(key));
list.add(mapMessage.build(context, depth + 1, recursionLimit));
}
return list;
}
protected RubyMap mergeIntoSelf(final ThreadContext context, IRubyObject hashmap) {
if (hashmap instanceof RubyHash) {
((RubyHash) hashmap)
.visitAll(
context,
new RubyHash.Visitor() {
@Override @Override
public void visit(IRubyObject key, IRubyObject val) { public void visit(IRubyObject key, IRubyObject val) {
if (val instanceof RubyHash && !valueTypeClass.isNil()) { if (val instanceof RubyHash && !valueTypeClass.isNil()) {
val = ((RubyClass) valueTypeClass).newInstance(context, val, Block.NULL_BLOCK); val = ((RubyClass) valueTypeClass).newInstance(context, val, Block.NULL_BLOCK);
} }
indexSet(context, key, val); indexSet(context, key, val);
} }
}, null); },
} else if (hashmap instanceof RubyMap) { null);
RubyMap other = (RubyMap) hashmap; } else if (hashmap instanceof RubyMap) {
if (!typeCompatible(other)) { RubyMap other = (RubyMap) hashmap;
throw Utils.createTypeError(context, "Attempt to merge Map with mismatching types"); if (!typeCompatible(other)) {
} throw Utils.createTypeError(context, "Attempt to merge Map with mismatching types");
} else { }
throw Utils.createTypeError(context, "Unknown type merging into Map"); } else {
} throw Utils.createTypeError(context, "Unknown type merging into Map");
return this;
}
protected boolean typeCompatible(RubyMap other) {
return this.keyType == other.keyType &&
this.valueType == other.valueType &&
this.valueTypeClass == other.valueTypeClass;
}
private RubyMap newThisType(ThreadContext context) {
RubyMap newMap;
if (needTypeclass(valueType)) {
newMap = (RubyMap) metaClass.newInstance(context,
Utils.fieldTypeToRuby(context, keyType),
Utils.fieldTypeToRuby(context, valueType),
valueTypeClass, Block.NULL_BLOCK);
} else {
newMap = (RubyMap) metaClass.newInstance(context,
Utils.fieldTypeToRuby(context, keyType),
Utils.fieldTypeToRuby(context, valueType),
Block.NULL_BLOCK);
}
newMap.table = new HashMap<IRubyObject, IRubyObject>();
return newMap;
} }
return this;
/* }
* toHash calls toHash on values, for some camparisons we only need
* a hash with the original objects still as values protected boolean typeCompatible(RubyMap other) {
*/ return this.keyType == other.keyType
private RubyHash singleLevelHash(ThreadContext context) { && this.valueType == other.valueType
return RubyHash.newHash(context.runtime, table, context.nil); && this.valueTypeClass == other.valueTypeClass;
}
private RubyMap newThisType(ThreadContext context) {
RubyMap newMap;
if (needTypeclass(valueType)) {
newMap =
(RubyMap)
metaClass.newInstance(
context,
Utils.fieldTypeToRuby(context, keyType),
Utils.fieldTypeToRuby(context, valueType),
valueTypeClass,
Block.NULL_BLOCK);
} else {
newMap =
(RubyMap)
metaClass.newInstance(
context,
Utils.fieldTypeToRuby(context, keyType),
Utils.fieldTypeToRuby(context, valueType),
Block.NULL_BLOCK);
} }
newMap.table = new HashMap<IRubyObject, IRubyObject>();
private boolean needTypeclass(FieldDescriptor.Type type) { return newMap;
switch(type) { }
case MESSAGE:
case ENUM: /*
return true; * toHash calls toHash on values, for some camparisons we only need
default: * a hash with the original objects still as values
return false; */
} private RubyHash singleLevelHash(ThreadContext context) {
return RubyHash.newHash(context.runtime, table, context.nil);
}
private boolean needTypeclass(FieldDescriptor.Type type) {
switch (type) {
case MESSAGE:
case ENUM:
return true;
default:
return false;
} }
}
private FieldDescriptor.Type keyType; private FieldDescriptor.Type keyType;
private FieldDescriptor.Type valueType; private FieldDescriptor.Type valueType;
private IRubyObject valueTypeClass; private IRubyObject valueTypeClass;
private Map<IRubyObject, IRubyObject> table; private Map<IRubyObject, IRubyObject> table;
private boolean keyTypeIsString = false; private boolean keyTypeIsString = false;
} }

@ -2,6 +2,10 @@ package com.google.protobuf.jruby;
import com.google.protobuf.Descriptors.FieldDescriptor; import com.google.protobuf.Descriptors.FieldDescriptor;
import com.google.protobuf.Descriptors.OneofDescriptor; import com.google.protobuf.Descriptors.OneofDescriptor;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import org.jruby.Ruby; import org.jruby.Ruby;
import org.jruby.RubyClass; import org.jruby.RubyClass;
import org.jruby.RubyModule; import org.jruby.RubyModule;
@ -13,74 +17,76 @@ import org.jruby.runtime.ObjectAllocator;
import org.jruby.runtime.ThreadContext; import org.jruby.runtime.ThreadContext;
import org.jruby.runtime.builtin.IRubyObject; import org.jruby.runtime.builtin.IRubyObject;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
@JRubyClass(name = "OneofDescriptor", include = "Enumerable") @JRubyClass(name = "OneofDescriptor", include = "Enumerable")
public class RubyOneofDescriptor extends RubyObject { public class RubyOneofDescriptor extends RubyObject {
public static void createRubyOneofDescriptor(Ruby runtime) { public static void createRubyOneofDescriptor(Ruby runtime) {
RubyModule protobuf = runtime.getClassFromPath("Google::Protobuf"); RubyModule protobuf = runtime.getClassFromPath("Google::Protobuf");
RubyClass cRubyOneofDescriptor = protobuf.defineClassUnder("OneofDescriptor", runtime.getObject(), new ObjectAllocator() { RubyClass cRubyOneofDescriptor =
@Override protobuf.defineClassUnder(
public IRubyObject allocate(Ruby ruby, RubyClass rubyClass) { "OneofDescriptor",
runtime.getObject(),
new ObjectAllocator() {
@Override
public IRubyObject allocate(Ruby ruby, RubyClass rubyClass) {
return new RubyOneofDescriptor(ruby, rubyClass); return new RubyOneofDescriptor(ruby, rubyClass);
} }
}); });
cRubyOneofDescriptor.defineAnnotatedMethods(RubyOneofDescriptor.class); cRubyOneofDescriptor.defineAnnotatedMethods(RubyOneofDescriptor.class);
cRubyOneofDescriptor.includeModule(runtime.getEnumerable()); cRubyOneofDescriptor.includeModule(runtime.getEnumerable());
} }
public RubyOneofDescriptor(Ruby ruby, RubyClass rubyClass) { public RubyOneofDescriptor(Ruby ruby, RubyClass rubyClass) {
super(ruby, rubyClass); super(ruby, rubyClass);
fields = new ArrayList<RubyFieldDescriptor>(); fields = new ArrayList<RubyFieldDescriptor>();
} }
/* /*
* call-seq: * call-seq:
* OneofDescriptor.name => name * OneofDescriptor.name => name
* *
* Returns the name of this oneof. * Returns the name of this oneof.
*/ */
@JRubyMethod(name = "name") @JRubyMethod(name = "name")
public IRubyObject getName(ThreadContext context) { public IRubyObject getName(ThreadContext context) {
return name; return name;
} }
/* /*
* call-seq: * call-seq:
* OneofDescriptor.each(&block) => nil * OneofDescriptor.each(&block) => nil
* *
* Iterates through fields in this oneof, yielding to the block on each one. * Iterates through fields in this oneof, yielding to the block on each one.
*/ */
@JRubyMethod @JRubyMethod
public IRubyObject each(ThreadContext context, Block block) { public IRubyObject each(ThreadContext context, Block block) {
for (RubyFieldDescriptor field : fields) { for (RubyFieldDescriptor field : fields) {
block.yieldSpecific(context, field); block.yieldSpecific(context, field);
}
return context.nil;
} }
return context.nil;
}
protected Collection<RubyFieldDescriptor> getFields() { protected Collection<RubyFieldDescriptor> getFields() {
return fields; return fields;
} }
protected OneofDescriptor getDescriptor() { protected OneofDescriptor getDescriptor() {
return descriptor; return descriptor;
} }
protected void setDescriptor(ThreadContext context, OneofDescriptor descriptor, Map<FieldDescriptor, RubyFieldDescriptor> fieldCache) { protected void setDescriptor(
this.descriptor = descriptor; ThreadContext context,
this.name = context.runtime.newString(descriptor.getName()); OneofDescriptor descriptor,
Map<FieldDescriptor, RubyFieldDescriptor> fieldCache) {
this.descriptor = descriptor;
this.name = context.runtime.newString(descriptor.getName());
for (FieldDescriptor fd : descriptor.getFields()) { for (FieldDescriptor fd : descriptor.getFields()) {
fields.add(fieldCache.get(fd)); fields.add(fieldCache.get(fd));
}
} }
}
private IRubyObject name; private IRubyObject name;
private List<RubyFieldDescriptor> fields; private List<RubyFieldDescriptor> fields;
private OneofDescriptor descriptor; private OneofDescriptor descriptor;
} }

@ -42,41 +42,42 @@ import org.jruby.runtime.builtin.IRubyObject;
@JRubyModule(name = "Protobuf") @JRubyModule(name = "Protobuf")
public class RubyProtobuf { public class RubyProtobuf {
public static void createProtobuf(Ruby runtime) { public static void createProtobuf(Ruby runtime) {
RubyModule mGoogle = runtime.getModule("Google"); RubyModule mGoogle = runtime.getModule("Google");
RubyModule mProtobuf = mGoogle.defineModuleUnder("Protobuf"); RubyModule mProtobuf = mGoogle.defineModuleUnder("Protobuf");
mProtobuf.defineAnnotatedMethods(RubyProtobuf.class); mProtobuf.defineAnnotatedMethods(RubyProtobuf.class);
RubyModule mInternal = mProtobuf.defineModuleUnder("Internal"); RubyModule mInternal = mProtobuf.defineModuleUnder("Internal");
} }
/* /*
* call-seq: * call-seq:
* Google::Protobuf.deep_copy(obj) => copy_of_obj * Google::Protobuf.deep_copy(obj) => copy_of_obj
* *
* Performs a deep copy of either a RepeatedField instance or a message object, * Performs a deep copy of either a RepeatedField instance or a message object,
* recursively copying its members. * recursively copying its members.
*/ */
@JRubyMethod(name = "deep_copy", meta = true) @JRubyMethod(name = "deep_copy", meta = true)
public static IRubyObject deepCopy(ThreadContext context, IRubyObject self, IRubyObject message) { public static IRubyObject deepCopy(ThreadContext context, IRubyObject self, IRubyObject message) {
if (message instanceof RubyMessage) { if (message instanceof RubyMessage) {
return ((RubyMessage) message).deepCopy(context); return ((RubyMessage) message).deepCopy(context);
} else if (message instanceof RubyRepeatedField) { } else if (message instanceof RubyRepeatedField) {
return ((RubyRepeatedField) message).deepCopy(context); return ((RubyRepeatedField) message).deepCopy(context);
} else { } else {
return ((RubyMap) message).deepCopy(context); return ((RubyMap) message).deepCopy(context);
}
} }
}
/* /*
* call-seq: * call-seq:
* Google::Protobuf.discard_unknown(msg) * Google::Protobuf.discard_unknown(msg)
* *
* Discard unknown fields in the given message object and recursively discard * Discard unknown fields in the given message object and recursively discard
* unknown fields in submessages. * unknown fields in submessages.
*/ */
@JRubyMethod(name = "discard_unknown", meta = true) @JRubyMethod(name = "discard_unknown", meta = true)
public static IRubyObject discardUnknown(ThreadContext context, IRubyObject self, IRubyObject message) { public static IRubyObject discardUnknown(
((RubyMessage) message).discardUnknownFields(context); ThreadContext context, IRubyObject self, IRubyObject message) {
return context.nil; ((RubyMessage) message).discardUnknownFields(context);
} return context.nil;
}
} }

@ -40,384 +40,391 @@ import org.jruby.runtime.Block;
import org.jruby.runtime.ObjectAllocator; import org.jruby.runtime.ObjectAllocator;
import org.jruby.runtime.ThreadContext; import org.jruby.runtime.ThreadContext;
import org.jruby.runtime.builtin.IRubyObject; import org.jruby.runtime.builtin.IRubyObject;
import java.util.Arrays;
@JRubyClass(name = "RepeatedClass", include = "Enumerable") @JRubyClass(name = "RepeatedClass", include = "Enumerable")
public class RubyRepeatedField extends RubyObject { public class RubyRepeatedField extends RubyObject {
public static void createRubyRepeatedField(Ruby runtime) { public static void createRubyRepeatedField(Ruby runtime) {
RubyModule mProtobuf = runtime.getClassFromPath("Google::Protobuf"); RubyModule mProtobuf = runtime.getClassFromPath("Google::Protobuf");
RubyClass cRepeatedField = mProtobuf.defineClassUnder("RepeatedField", runtime.getObject(), RubyClass cRepeatedField =
new ObjectAllocator() { mProtobuf.defineClassUnder(
@Override "RepeatedField",
public IRubyObject allocate(Ruby runtime, RubyClass klazz) { runtime.getObject(),
return new RubyRepeatedField(runtime, klazz); new ObjectAllocator() {
} @Override
}); public IRubyObject allocate(Ruby runtime, RubyClass klazz) {
cRepeatedField.defineAnnotatedMethods(RubyRepeatedField.class); return new RubyRepeatedField(runtime, klazz);
cRepeatedField.includeModule(runtime.getEnumerable()); }
});
cRepeatedField.defineAnnotatedMethods(RubyRepeatedField.class);
cRepeatedField.includeModule(runtime.getEnumerable());
}
public RubyRepeatedField(Ruby runtime, RubyClass klazz) {
super(runtime, klazz);
}
public RubyRepeatedField(
Ruby runtime, RubyClass klazz, FieldDescriptor.Type fieldType, IRubyObject typeClass) {
this(runtime, klazz);
this.fieldType = fieldType;
this.storage = runtime.newArray();
this.typeClass = typeClass;
}
@JRubyMethod(required = 1, optional = 2)
public IRubyObject initialize(ThreadContext context, IRubyObject[] args) {
Ruby runtime = context.runtime;
this.storage = runtime.newArray();
IRubyObject ary = null;
if (!(args[0] instanceof RubySymbol)) {
throw runtime.newArgumentError("Expected Symbol for type name");
} }
this.fieldType = Utils.rubyToFieldType(args[0]);
public RubyRepeatedField(Ruby runtime, RubyClass klazz) { if (fieldType == FieldDescriptor.Type.MESSAGE || fieldType == FieldDescriptor.Type.ENUM) {
super(runtime, klazz); if (args.length < 2)
} throw runtime.newArgumentError("Expected at least 2 arguments for message/enum");
typeClass = args[1];
public RubyRepeatedField(Ruby runtime, RubyClass klazz, FieldDescriptor.Type fieldType, IRubyObject typeClass) { if (args.length > 2) ary = args[2];
this(runtime, klazz); Utils.validateTypeClass(context, fieldType, typeClass);
this.fieldType = fieldType; } else {
this.storage = runtime.newArray(); if (args.length > 2) throw runtime.newArgumentError("Too many arguments: expected 1 or 2");
this.typeClass = typeClass; if (args.length > 1) ary = args[1];
}
@JRubyMethod(required = 1, optional = 2)
public IRubyObject initialize(ThreadContext context, IRubyObject[] args) {
Ruby runtime = context.runtime;
this.storage = runtime.newArray();
IRubyObject ary = null;
if (!(args[0] instanceof RubySymbol)) {
throw runtime.newArgumentError("Expected Symbol for type name");
}
this.fieldType = Utils.rubyToFieldType(args[0]);
if (fieldType == FieldDescriptor.Type.MESSAGE
|| fieldType == FieldDescriptor.Type.ENUM) {
if (args.length < 2)
throw runtime.newArgumentError("Expected at least 2 arguments for message/enum");
typeClass = args[1];
if (args.length > 2)
ary = args[2];
Utils.validateTypeClass(context, fieldType, typeClass);
} else {
if (args.length > 2)
throw runtime.newArgumentError("Too many arguments: expected 1 or 2");
if (args.length > 1)
ary = args[1];
}
if (ary != null) {
RubyArray arr = ary.convertToArray();
for (int i = 0; i < arr.size(); i++) {
this.storage.add(arr.eltInternal(i));
}
}
return this;
}
/*
* call-seq:
* RepeatedField.[]=(index, value)
*
* Sets the element at the given index. On out-of-bounds assignments, extends
* the array and fills the hole (if any) with default values.
*/
@JRubyMethod(name = "[]=")
public IRubyObject indexSet(ThreadContext context, IRubyObject index, IRubyObject value) {
int arrIndex = normalizeArrayIndex(index);
value = Utils.checkType(context, fieldType, name, value, (RubyModule) typeClass);
IRubyObject defaultValue = defaultValue(context);
for (int i = this.storage.size(); i < arrIndex; i++) {
this.storage.set(i, defaultValue);
}
this.storage.set(arrIndex, value);
return context.runtime.getNil();
}
/*
* call-seq:
* RepeatedField.[](index) => value
*
* Accesses the element at the given index. Returns nil on out-of-bounds
*/
@JRubyMethod(required=1, optional=1, name = {"at", "[]"})
public IRubyObject index(ThreadContext context, IRubyObject[] args) {
if (args.length == 1){
IRubyObject arg = args[0];
if (Utils.isRubyNum(arg)) {
/* standard case */
int arrIndex = normalizeArrayIndex(arg);
if (arrIndex < 0 || arrIndex >= this.storage.size()) {
return context.runtime.getNil();
}
return this.storage.eltInternal(arrIndex);
} else if (arg instanceof RubyRange) {
RubyRange range = ((RubyRange) arg);
int beg = RubyNumeric.num2int(range.first(context));
int len = RubyNumeric.num2int(range.size(context));
if (len == 0) return context.runtime.newEmptyArray();
return this.storage.subseq(beg, len);
}
}
/* assume 2 arguments */
int beg = RubyNumeric.num2int(args[0]);
int len = RubyNumeric.num2int(args[1]);
if (beg < 0) {
beg += this.storage.size();
}
if (beg >= this.storage.size()) {
return context.runtime.getNil();
}
return this.storage.subseq(beg, len);
}
/*
* call-seq:
* RepeatedField.push(value)
*
* Adds a new element to the repeated field.
*/
@JRubyMethod(name = {"push", "<<"}, required = 1, rest = true)
public IRubyObject push(ThreadContext context, IRubyObject[] args) {
for (int i = 0; i < args.length; i++) {
IRubyObject val = args[i];
if (fieldType != FieldDescriptor.Type.MESSAGE || !val.isNil()) {
val = Utils.checkType(context, fieldType, name, val, (RubyModule) typeClass);
}
storage.add(val);
}
return this;
}
/*
* private Ruby method used by RepeatedField.pop
*/
@JRubyMethod(visibility = org.jruby.runtime.Visibility.PRIVATE)
public IRubyObject pop_one(ThreadContext context) {
IRubyObject ret = this.storage.last();
this.storage.remove(ret);
return ret;
}
/*
* call-seq:
* RepeatedField.replace(list)
*
* Replaces the contents of the repeated field with the given list of elements.
*/
@JRubyMethod
public IRubyObject replace(ThreadContext context, IRubyObject list) {
RubyArray arr = (RubyArray) list;
checkArrayElementType(context, arr);
this.storage = arr;
return this;
} }
if (ary != null) {
/* RubyArray arr = ary.convertToArray();
* call-seq: for (int i = 0; i < arr.size(); i++) {
* RepeatedField.clear this.storage.add(arr.eltInternal(i));
* }
* Clears (removes all elements from) this repeated field.
*/
@JRubyMethod
public IRubyObject clear(ThreadContext context) {
this.storage.clear();
return this;
} }
return this;
/* }
* call-seq:
* RepeatedField.length /*
* * call-seq:
* Returns the length of this repeated field. * RepeatedField.[]=(index, value)
*/ *
@JRubyMethod(name = {"length", "size"}) * Sets the element at the given index. On out-of-bounds assignments, extends
public IRubyObject length(ThreadContext context) { * the array and fills the hole (if any) with default values.
return context.runtime.newFixnum(this.storage.size()); */
@JRubyMethod(name = "[]=")
public IRubyObject indexSet(ThreadContext context, IRubyObject index, IRubyObject value) {
int arrIndex = normalizeArrayIndex(index);
value = Utils.checkType(context, fieldType, name, value, (RubyModule) typeClass);
IRubyObject defaultValue = defaultValue(context);
for (int i = this.storage.size(); i < arrIndex; i++) {
this.storage.set(i, defaultValue);
} }
this.storage.set(arrIndex, value);
/* return context.runtime.getNil();
* call-seq: }
* RepeatedField.+(other) => repeated field
* /*
* Returns a new repeated field that contains the concatenated list of this * call-seq:
* repeated field's elements and other's elements. The other (second) list may * RepeatedField.[](index) => value
* be either another repeated field or a Ruby array. *
*/ * Accesses the element at the given index. Returns nil on out-of-bounds
@JRubyMethod(name = {"+"}) */
public IRubyObject plus(ThreadContext context, IRubyObject list) { @JRubyMethod(
RubyRepeatedField dup = (RubyRepeatedField) dup(context); required = 1,
if (list instanceof RubyArray) { optional = 1,
checkArrayElementType(context, (RubyArray) list); name = {"at", "[]"})
dup.storage.addAll((RubyArray) list); public IRubyObject index(ThreadContext context, IRubyObject[] args) {
} else { if (args.length == 1) {
RubyRepeatedField repeatedField = (RubyRepeatedField) list; IRubyObject arg = args[0];
if (! fieldType.equals(repeatedField.fieldType) || (typeClass != null && ! if (Utils.isRubyNum(arg)) {
typeClass.equals(repeatedField.typeClass))) /* standard case */
throw context.runtime.newArgumentError("Attempt to append RepeatedField with different element type."); int arrIndex = normalizeArrayIndex(arg);
dup.storage.addAll((RubyArray) repeatedField.toArray(context)); if (arrIndex < 0 || arrIndex >= this.storage.size()) {
return context.runtime.getNil();
} }
return dup; return this.storage.eltInternal(arrIndex);
} } else if (arg instanceof RubyRange) {
RubyRange range = ((RubyRange) arg);
/* int beg = RubyNumeric.num2int(range.first(context));
* call-seq: int len = RubyNumeric.num2int(range.size(context));
* RepeatedField.concat(other) => self
*
* concats the passed in array to self. Returns a Ruby array.
*/
@JRubyMethod
public IRubyObject concat(ThreadContext context, IRubyObject list) {
if (list instanceof RubyArray) {
checkArrayElementType(context, (RubyArray) list);
this.storage.addAll((RubyArray) list);
} else {
RubyRepeatedField repeatedField = (RubyRepeatedField) list;
if (! fieldType.equals(repeatedField.fieldType) || (typeClass != null && !
typeClass.equals(repeatedField.typeClass)))
throw context.runtime.newArgumentError("Attempt to append RepeatedField with different element type.");
this.storage.addAll((RubyArray) repeatedField.toArray(context));
}
return this;
}
/*
* call-seq:
* RepeatedField.hash => hash_value
*
* Returns a hash value computed from this repeated field's elements.
*/
@JRubyMethod
public IRubyObject hash(ThreadContext context) {
int hashCode = this.storage.hashCode();
return context.runtime.newFixnum(hashCode);
}
/*
* call-seq:
* RepeatedField.==(other) => boolean
*
* Compares this repeated field to another. Repeated fields are equal if their
* element types are equal, their lengths are equal, and each element is equal.
* Elements are compared as per normal Ruby semantics, by calling their :==
* methods (or performing a more efficient comparison for primitive types).
*/
@JRubyMethod(name = "==")
public IRubyObject eq(ThreadContext context, IRubyObject other) {
return this.toArray(context).op_equal(context, other);
}
/*
* call-seq:
* RepeatedField.each(&block)
*
* Invokes the block once for each element of the repeated field. RepeatedField
* also includes Enumerable; combined with this method, the repeated field thus
* acts like an ordinary Ruby sequence.
*/
@JRubyMethod
public IRubyObject each(ThreadContext context, Block block) {
this.storage.each(context, block);
return this;
}
if (len == 0) return context.runtime.newEmptyArray();
@JRubyMethod(name = {"to_ary", "to_a"}) return this.storage.subseq(beg, len);
public IRubyObject toArray(ThreadContext context) { }
return this.storage;
} }
/* assume 2 arguments */
/* int beg = RubyNumeric.num2int(args[0]);
* call-seq: int len = RubyNumeric.num2int(args[1]);
* RepeatedField.dup => repeated_field if (beg < 0) {
* beg += this.storage.size();
* Duplicates this repeated field with a shallow copy. References to all
* non-primitive element objects (e.g., submessages) are shared.
*/
@JRubyMethod
public IRubyObject dup(ThreadContext context) {
RubyRepeatedField dup = new RubyRepeatedField(context.runtime, metaClass, fieldType, typeClass);
dup.push(context, storage.toJavaArray());
return dup;
} }
if (beg >= this.storage.size()) {
@JRubyMethod return context.runtime.getNil();
public IRubyObject inspect() {
return storage.inspect();
} }
return this.storage.subseq(beg, len);
// Java API }
protected IRubyObject get(int index) {
return this.storage.eltInternal(index); /*
* call-seq:
* RepeatedField.push(value)
*
* Adds a new element to the repeated field.
*/
@JRubyMethod(
name = {"push", "<<"},
required = 1,
rest = true)
public IRubyObject push(ThreadContext context, IRubyObject[] args) {
for (int i = 0; i < args.length; i++) {
IRubyObject val = args[i];
if (fieldType != FieldDescriptor.Type.MESSAGE || !val.isNil()) {
val = Utils.checkType(context, fieldType, name, val, (RubyModule) typeClass);
}
storage.add(val);
} }
protected RubyRepeatedField deepCopy(ThreadContext context) { return this;
RubyRepeatedField copy = new RubyRepeatedField(context.runtime, metaClass, fieldType, typeClass); }
for (int i = 0; i < size(); i++) {
IRubyObject value = storage.eltInternal(i); /*
if (fieldType == FieldDescriptor.Type.MESSAGE) { * private Ruby method used by RepeatedField.pop
copy.storage.add(((RubyMessage) value).deepCopy(context)); */
} else { @JRubyMethod(visibility = org.jruby.runtime.Visibility.PRIVATE)
copy.storage.add(value); public IRubyObject pop_one(ThreadContext context) {
} IRubyObject ret = this.storage.last();
} this.storage.remove(ret);
return copy; return ret;
}
/*
* call-seq:
* RepeatedField.replace(list)
*
* Replaces the contents of the repeated field with the given list of elements.
*/
@JRubyMethod
public IRubyObject replace(ThreadContext context, IRubyObject list) {
RubyArray arr = (RubyArray) list;
checkArrayElementType(context, arr);
this.storage = arr;
return this;
}
/*
* call-seq:
* RepeatedField.clear
*
* Clears (removes all elements from) this repeated field.
*/
@JRubyMethod
public IRubyObject clear(ThreadContext context) {
this.storage.clear();
return this;
}
/*
* call-seq:
* RepeatedField.length
*
* Returns the length of this repeated field.
*/
@JRubyMethod(name = {"length", "size"})
public IRubyObject length(ThreadContext context) {
return context.runtime.newFixnum(this.storage.size());
}
/*
* call-seq:
* RepeatedField.+(other) => repeated field
*
* Returns a new repeated field that contains the concatenated list of this
* repeated field's elements and other's elements. The other (second) list may
* be either another repeated field or a Ruby array.
*/
@JRubyMethod(name = {"+"})
public IRubyObject plus(ThreadContext context, IRubyObject list) {
RubyRepeatedField dup = (RubyRepeatedField) dup(context);
if (list instanceof RubyArray) {
checkArrayElementType(context, (RubyArray) list);
dup.storage.addAll((RubyArray) list);
} else {
RubyRepeatedField repeatedField = (RubyRepeatedField) list;
if (!fieldType.equals(repeatedField.fieldType)
|| (typeClass != null && !typeClass.equals(repeatedField.typeClass)))
throw context.runtime.newArgumentError(
"Attempt to append RepeatedField with different element type.");
dup.storage.addAll((RubyArray) repeatedField.toArray(context));
} }
return dup;
protected void setName(String name) { }
this.name = name;
/*
* call-seq:
* RepeatedField.concat(other) => self
*
* concats the passed in array to self. Returns a Ruby array.
*/
@JRubyMethod
public IRubyObject concat(ThreadContext context, IRubyObject list) {
if (list instanceof RubyArray) {
checkArrayElementType(context, (RubyArray) list);
this.storage.addAll((RubyArray) list);
} else {
RubyRepeatedField repeatedField = (RubyRepeatedField) list;
if (!fieldType.equals(repeatedField.fieldType)
|| (typeClass != null && !typeClass.equals(repeatedField.typeClass)))
throw context.runtime.newArgumentError(
"Attempt to append RepeatedField with different element type.");
this.storage.addAll((RubyArray) repeatedField.toArray(context));
} }
return this;
protected int size() { }
return this.storage.size();
/*
* call-seq:
* RepeatedField.hash => hash_value
*
* Returns a hash value computed from this repeated field's elements.
*/
@JRubyMethod
public IRubyObject hash(ThreadContext context) {
int hashCode = this.storage.hashCode();
return context.runtime.newFixnum(hashCode);
}
/*
* call-seq:
* RepeatedField.==(other) => boolean
*
* Compares this repeated field to another. Repeated fields are equal if their
* element types are equal, their lengths are equal, and each element is equal.
* Elements are compared as per normal Ruby semantics, by calling their :==
* methods (or performing a more efficient comparison for primitive types).
*/
@JRubyMethod(name = "==")
public IRubyObject eq(ThreadContext context, IRubyObject other) {
return this.toArray(context).op_equal(context, other);
}
/*
* call-seq:
* RepeatedField.each(&block)
*
* Invokes the block once for each element of the repeated field. RepeatedField
* also includes Enumerable; combined with this method, the repeated field thus
* acts like an ordinary Ruby sequence.
*/
@JRubyMethod
public IRubyObject each(ThreadContext context, Block block) {
this.storage.each(context, block);
return this;
}
@JRubyMethod(name = {"to_ary", "to_a"})
public IRubyObject toArray(ThreadContext context) {
return this.storage;
}
/*
* call-seq:
* RepeatedField.dup => repeated_field
*
* Duplicates this repeated field with a shallow copy. References to all
* non-primitive element objects (e.g., submessages) are shared.
*/
@JRubyMethod
public IRubyObject dup(ThreadContext context) {
RubyRepeatedField dup = new RubyRepeatedField(context.runtime, metaClass, fieldType, typeClass);
dup.push(context, storage.toJavaArray());
return dup;
}
@JRubyMethod
public IRubyObject inspect() {
return storage.inspect();
}
// Java API
protected IRubyObject get(int index) {
return this.storage.eltInternal(index);
}
protected RubyRepeatedField deepCopy(ThreadContext context) {
RubyRepeatedField copy =
new RubyRepeatedField(context.runtime, metaClass, fieldType, typeClass);
for (int i = 0; i < size(); i++) {
IRubyObject value = storage.eltInternal(i);
if (fieldType == FieldDescriptor.Type.MESSAGE) {
copy.storage.add(((RubyMessage) value).deepCopy(context));
} else {
copy.storage.add(value);
}
} }
return copy;
private IRubyObject defaultValue(ThreadContext context) { }
SentinelOuterClass.Sentinel sentinel = SentinelOuterClass.Sentinel.getDefaultInstance();
Object value; protected void setName(String name) {
switch (fieldType) { this.name = name;
case INT32: }
value = sentinel.getDefaultInt32();
break; protected int size() {
case INT64: return this.storage.size();
value = sentinel.getDefaultInt64(); }
break;
case UINT32: private IRubyObject defaultValue(ThreadContext context) {
value = sentinel.getDefaultUnit32(); SentinelOuterClass.Sentinel sentinel = SentinelOuterClass.Sentinel.getDefaultInstance();
break; Object value;
case UINT64: switch (fieldType) {
value = sentinel.getDefaultUint64(); case INT32:
break; value = sentinel.getDefaultInt32();
case FLOAT: break;
value = sentinel.getDefaultFloat(); case INT64:
break; value = sentinel.getDefaultInt64();
case DOUBLE: break;
value = sentinel.getDefaultDouble(); case UINT32:
break; value = sentinel.getDefaultUnit32();
case BOOL: break;
value = sentinel.getDefaultBool(); case UINT64:
break; value = sentinel.getDefaultUint64();
case BYTES: break;
value = sentinel.getDefaultBytes(); case FLOAT:
break; value = sentinel.getDefaultFloat();
case STRING: break;
value = sentinel.getDefaultString(); case DOUBLE:
break; value = sentinel.getDefaultDouble();
case ENUM: break;
IRubyObject defaultEnumLoc = context.runtime.newFixnum(0); case BOOL:
return RubyEnum.lookup(context, typeClass, defaultEnumLoc); value = sentinel.getDefaultBool();
default: break;
return context.runtime.getNil(); case BYTES:
} value = sentinel.getDefaultBytes();
return Utils.wrapPrimaryValue(context, fieldType, value); break;
case STRING:
value = sentinel.getDefaultString();
break;
case ENUM:
IRubyObject defaultEnumLoc = context.runtime.newFixnum(0);
return RubyEnum.lookup(context, typeClass, defaultEnumLoc);
default:
return context.runtime.getNil();
} }
return Utils.wrapPrimaryValue(context, fieldType, value);
}
private void checkArrayElementType(ThreadContext context, RubyArray arr) { private void checkArrayElementType(ThreadContext context, RubyArray arr) {
for (int i = 0; i < arr.getLength(); i++) { for (int i = 0; i < arr.getLength(); i++) {
Utils.checkType(context, fieldType, name, arr.eltInternal(i), (RubyModule) typeClass); Utils.checkType(context, fieldType, name, arr.eltInternal(i), (RubyModule) typeClass);
}
} }
}
private int normalizeArrayIndex(IRubyObject index) { private int normalizeArrayIndex(IRubyObject index) {
int arrIndex = RubyNumeric.num2int(index); int arrIndex = RubyNumeric.num2int(index);
int arrSize = this.storage.size(); int arrSize = this.storage.size();
if (arrIndex < 0 && arrSize > 0) { if (arrIndex < 0 && arrSize > 0) {
arrIndex = arrSize + arrIndex; arrIndex = arrSize + arrIndex;
}
return arrIndex;
} }
return arrIndex;
}
private FieldDescriptor.Type fieldType; private FieldDescriptor.Type fieldType;
private IRubyObject typeClass; private IRubyObject typeClass;
private RubyArray storage; private RubyArray storage;
private String name; private String name;
} }

@ -37,74 +37,53 @@ package com.google.protobuf.jruby;
public final class SentinelOuterClass { public final class SentinelOuterClass {
private SentinelOuterClass() {} private SentinelOuterClass() {}
public static void registerAllExtensions(
com.google.protobuf.ExtensionRegistry registry) { public static void registerAllExtensions(com.google.protobuf.ExtensionRegistry registry) {}
}
public interface SentinelOrBuilder extends public interface SentinelOrBuilder
extends
// @@protoc_insertion_point(interface_extends:com.google.protobuf.jruby.Sentinel) // @@protoc_insertion_point(interface_extends:com.google.protobuf.jruby.Sentinel)
com.google.protobuf.MessageOrBuilder { com.google.protobuf.MessageOrBuilder {
/** /** <code>optional int32 default_int32 = 1;</code> */
* <code>optional int32 default_int32 = 1;</code>
*/
int getDefaultInt32(); int getDefaultInt32();
/** /** <code>optional int64 default_int64 = 2;</code> */
* <code>optional int64 default_int64 = 2;</code>
*/
long getDefaultInt64(); long getDefaultInt64();
/** /** <code>optional uint32 default_unit32 = 3;</code> */
* <code>optional uint32 default_unit32 = 3;</code>
*/
int getDefaultUnit32(); int getDefaultUnit32();
/** /** <code>optional uint64 default_uint64 = 4;</code> */
* <code>optional uint64 default_uint64 = 4;</code>
*/
long getDefaultUint64(); long getDefaultUint64();
/** /** <code>optional string default_string = 5;</code> */
* <code>optional string default_string = 5;</code>
*/
java.lang.String getDefaultString(); java.lang.String getDefaultString();
/** /** <code>optional string default_string = 5;</code> */
* <code>optional string default_string = 5;</code> com.google.protobuf.ByteString getDefaultStringBytes();
*/
com.google.protobuf.ByteString /** <code>optional bool default_bool = 6;</code> */
getDefaultStringBytes();
/**
* <code>optional bool default_bool = 6;</code>
*/
boolean getDefaultBool(); boolean getDefaultBool();
/** /** <code>optional float default_float = 7;</code> */
* <code>optional float default_float = 7;</code>
*/
float getDefaultFloat(); float getDefaultFloat();
/** /** <code>optional double default_double = 8;</code> */
* <code>optional double default_double = 8;</code>
*/
double getDefaultDouble(); double getDefaultDouble();
/** /** <code>optional bytes default_bytes = 9;</code> */
* <code>optional bytes default_bytes = 9;</code>
*/
com.google.protobuf.ByteString getDefaultBytes(); com.google.protobuf.ByteString getDefaultBytes();
} }
/** /** Protobuf type {@code com.google.protobuf.jruby.Sentinel} */
* Protobuf type {@code com.google.protobuf.jruby.Sentinel} public static final class Sentinel extends com.google.protobuf.GeneratedMessage
*/ implements
public static final class Sentinel extends
com.google.protobuf.GeneratedMessage implements
// @@protoc_insertion_point(message_implements:com.google.protobuf.jruby.Sentinel) // @@protoc_insertion_point(message_implements:com.google.protobuf.jruby.Sentinel)
SentinelOrBuilder { SentinelOrBuilder {
// Use Sentinel.newBuilder() to construct. // Use Sentinel.newBuilder() to construct.
private Sentinel(com.google.protobuf.GeneratedMessage.Builder builder) { private Sentinel(com.google.protobuf.GeneratedMessage.Builder builder) {
super(builder); super(builder);
} }
private Sentinel() { private Sentinel() {
defaultInt32_ = 0; defaultInt32_ = 0;
defaultInt64_ = 0L; defaultInt64_ = 0L;
@ -118,40 +97,42 @@ public final class SentinelOuterClass {
} }
@java.lang.Override @java.lang.Override
public final com.google.protobuf.UnknownFieldSet public final com.google.protobuf.UnknownFieldSet getUnknownFields() {
getUnknownFields() {
return com.google.protobuf.UnknownFieldSet.getDefaultInstance(); return com.google.protobuf.UnknownFieldSet.getDefaultInstance();
} }
public static final com.google.protobuf.Descriptors.Descriptor
getDescriptor() { public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() {
return com.google.protobuf.jruby.SentinelOuterClass.internal_static_com_google_protobuf_jruby_Sentinel_descriptor; return com.google.protobuf.jruby.SentinelOuterClass
.internal_static_com_google_protobuf_jruby_Sentinel_descriptor;
} }
protected com.google.protobuf.GeneratedMessage.FieldAccessorTable protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
internalGetFieldAccessorTable() { internalGetFieldAccessorTable() {
return com.google.protobuf.jruby.SentinelOuterClass.internal_static_com_google_protobuf_jruby_Sentinel_fieldAccessorTable return com.google.protobuf.jruby.SentinelOuterClass
.internal_static_com_google_protobuf_jruby_Sentinel_fieldAccessorTable
.ensureFieldAccessorsInitialized( .ensureFieldAccessorsInitialized(
com.google.protobuf.jruby.SentinelOuterClass.Sentinel.class, com.google.protobuf.jruby.SentinelOuterClass.Sentinel.Builder.class); com.google.protobuf.jruby.SentinelOuterClass.Sentinel.class,
com.google.protobuf.jruby.SentinelOuterClass.Sentinel.Builder.class);
} }
public static final com.google.protobuf.Parser<Sentinel> PARSER = public static final com.google.protobuf.Parser<Sentinel> PARSER =
new com.google.protobuf.AbstractParser<Sentinel>() { new com.google.protobuf.AbstractParser<Sentinel>() {
public Sentinel parsePartialFrom( public Sentinel parsePartialFrom(
com.google.protobuf.CodedInputStream input, com.google.protobuf.CodedInputStream input,
com.google.protobuf.ExtensionRegistryLite extensionRegistry) com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws com.google.protobuf.InvalidProtocolBufferException { throws com.google.protobuf.InvalidProtocolBufferException {
Builder builder = newBuilder(); Builder builder = newBuilder();
try { try {
builder.mergeFrom(input, extensionRegistry); builder.mergeFrom(input, extensionRegistry);
} catch (com.google.protobuf.InvalidProtocolBufferException e) { } catch (com.google.protobuf.InvalidProtocolBufferException e) {
throw e.setUnfinishedMessage(builder.buildPartial()); throw e.setUnfinishedMessage(builder.buildPartial());
} catch (java.io.IOException e) { } catch (java.io.IOException e) {
throw new com.google.protobuf.InvalidProtocolBufferException( throw new com.google.protobuf.InvalidProtocolBufferException(e.getMessage())
e.getMessage()).setUnfinishedMessage(builder.buildPartial()); .setUnfinishedMessage(builder.buildPartial());
} }
return builder.buildPartial(); return builder.buildPartial();
} }
}; };
@java.lang.Override @java.lang.Override
public com.google.protobuf.Parser<Sentinel> getParserForType() { public com.google.protobuf.Parser<Sentinel> getParserForType() {
@ -160,52 +141,41 @@ public final class SentinelOuterClass {
public static final int DEFAULT_INT32_FIELD_NUMBER = 1; public static final int DEFAULT_INT32_FIELD_NUMBER = 1;
private int defaultInt32_; private int defaultInt32_;
/** /** <code>optional int32 default_int32 = 1;</code> */
* <code>optional int32 default_int32 = 1;</code>
*/
public int getDefaultInt32() { public int getDefaultInt32() {
return defaultInt32_; return defaultInt32_;
} }
public static final int DEFAULT_INT64_FIELD_NUMBER = 2; public static final int DEFAULT_INT64_FIELD_NUMBER = 2;
private long defaultInt64_; private long defaultInt64_;
/** /** <code>optional int64 default_int64 = 2;</code> */
* <code>optional int64 default_int64 = 2;</code>
*/
public long getDefaultInt64() { public long getDefaultInt64() {
return defaultInt64_; return defaultInt64_;
} }
public static final int DEFAULT_UNIT32_FIELD_NUMBER = 3; public static final int DEFAULT_UNIT32_FIELD_NUMBER = 3;
private int defaultUnit32_; private int defaultUnit32_;
/** /** <code>optional uint32 default_unit32 = 3;</code> */
* <code>optional uint32 default_unit32 = 3;</code>
*/
public int getDefaultUnit32() { public int getDefaultUnit32() {
return defaultUnit32_; return defaultUnit32_;
} }
public static final int DEFAULT_UINT64_FIELD_NUMBER = 4; public static final int DEFAULT_UINT64_FIELD_NUMBER = 4;
private long defaultUint64_; private long defaultUint64_;
/** /** <code>optional uint64 default_uint64 = 4;</code> */
* <code>optional uint64 default_uint64 = 4;</code>
*/
public long getDefaultUint64() { public long getDefaultUint64() {
return defaultUint64_; return defaultUint64_;
} }
public static final int DEFAULT_STRING_FIELD_NUMBER = 5; public static final int DEFAULT_STRING_FIELD_NUMBER = 5;
private java.lang.Object defaultString_; private java.lang.Object defaultString_;
/** /** <code>optional string default_string = 5;</code> */
* <code>optional string default_string = 5;</code>
*/
public java.lang.String getDefaultString() { public java.lang.String getDefaultString() {
java.lang.Object ref = defaultString_; java.lang.Object ref = defaultString_;
if (ref instanceof java.lang.String) { if (ref instanceof java.lang.String) {
return (java.lang.String) ref; return (java.lang.String) ref;
} else { } else {
com.google.protobuf.ByteString bs = com.google.protobuf.ByteString bs = (com.google.protobuf.ByteString) ref;
(com.google.protobuf.ByteString) ref;
java.lang.String s = bs.toStringUtf8(); java.lang.String s = bs.toStringUtf8();
if (bs.isValidUtf8()) { if (bs.isValidUtf8()) {
defaultString_ = s; defaultString_ = s;
@ -213,16 +183,12 @@ public final class SentinelOuterClass {
return s; return s;
} }
} }
/** /** <code>optional string default_string = 5;</code> */
* <code>optional string default_string = 5;</code> public com.google.protobuf.ByteString getDefaultStringBytes() {
*/
public com.google.protobuf.ByteString
getDefaultStringBytes() {
java.lang.Object ref = defaultString_; java.lang.Object ref = defaultString_;
if (ref instanceof java.lang.String) { if (ref instanceof java.lang.String) {
com.google.protobuf.ByteString b = com.google.protobuf.ByteString b =
com.google.protobuf.ByteString.copyFromUtf8( com.google.protobuf.ByteString.copyFromUtf8((java.lang.String) ref);
(java.lang.String) ref);
defaultString_ = b; defaultString_ = b;
return b; return b;
} else { } else {
@ -232,36 +198,28 @@ public final class SentinelOuterClass {
public static final int DEFAULT_BOOL_FIELD_NUMBER = 6; public static final int DEFAULT_BOOL_FIELD_NUMBER = 6;
private boolean defaultBool_; private boolean defaultBool_;
/** /** <code>optional bool default_bool = 6;</code> */
* <code>optional bool default_bool = 6;</code>
*/
public boolean getDefaultBool() { public boolean getDefaultBool() {
return defaultBool_; return defaultBool_;
} }
public static final int DEFAULT_FLOAT_FIELD_NUMBER = 7; public static final int DEFAULT_FLOAT_FIELD_NUMBER = 7;
private float defaultFloat_; private float defaultFloat_;
/** /** <code>optional float default_float = 7;</code> */
* <code>optional float default_float = 7;</code>
*/
public float getDefaultFloat() { public float getDefaultFloat() {
return defaultFloat_; return defaultFloat_;
} }
public static final int DEFAULT_DOUBLE_FIELD_NUMBER = 8; public static final int DEFAULT_DOUBLE_FIELD_NUMBER = 8;
private double defaultDouble_; private double defaultDouble_;
/** /** <code>optional double default_double = 8;</code> */
* <code>optional double default_double = 8;</code>
*/
public double getDefaultDouble() { public double getDefaultDouble() {
return defaultDouble_; return defaultDouble_;
} }
public static final int DEFAULT_BYTES_FIELD_NUMBER = 9; public static final int DEFAULT_BYTES_FIELD_NUMBER = 9;
private com.google.protobuf.ByteString defaultBytes_; private com.google.protobuf.ByteString defaultBytes_;
/** /** <code>optional bytes default_bytes = 9;</code> */
* <code>optional bytes default_bytes = 9;</code>
*/
public com.google.protobuf.ByteString getDefaultBytes() { public com.google.protobuf.ByteString getDefaultBytes() {
return defaultBytes_; return defaultBytes_;
} }
@ -271,47 +229,52 @@ public final class SentinelOuterClass {
throws com.google.protobuf.InvalidProtocolBufferException { throws com.google.protobuf.InvalidProtocolBufferException {
return PARSER.parseFrom(data); return PARSER.parseFrom(data);
} }
public static com.google.protobuf.jruby.SentinelOuterClass.Sentinel parseFrom( public static com.google.protobuf.jruby.SentinelOuterClass.Sentinel parseFrom(
com.google.protobuf.ByteString data, com.google.protobuf.ByteString data,
com.google.protobuf.ExtensionRegistryLite extensionRegistry) com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws com.google.protobuf.InvalidProtocolBufferException { throws com.google.protobuf.InvalidProtocolBufferException {
return PARSER.parseFrom(data, extensionRegistry); return PARSER.parseFrom(data, extensionRegistry);
} }
public static com.google.protobuf.jruby.SentinelOuterClass.Sentinel parseFrom(byte[] data) public static com.google.protobuf.jruby.SentinelOuterClass.Sentinel parseFrom(byte[] data)
throws com.google.protobuf.InvalidProtocolBufferException { throws com.google.protobuf.InvalidProtocolBufferException {
return PARSER.parseFrom(data); return PARSER.parseFrom(data);
} }
public static com.google.protobuf.jruby.SentinelOuterClass.Sentinel parseFrom( public static com.google.protobuf.jruby.SentinelOuterClass.Sentinel parseFrom(
byte[] data, byte[] data, com.google.protobuf.ExtensionRegistryLite extensionRegistry)
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws com.google.protobuf.InvalidProtocolBufferException { throws com.google.protobuf.InvalidProtocolBufferException {
return PARSER.parseFrom(data, extensionRegistry); return PARSER.parseFrom(data, extensionRegistry);
} }
public static com.google.protobuf.jruby.SentinelOuterClass.Sentinel parseFrom(java.io.InputStream input)
throws java.io.IOException { public static com.google.protobuf.jruby.SentinelOuterClass.Sentinel parseFrom(
java.io.InputStream input) throws java.io.IOException {
return PARSER.parseFrom(input); return PARSER.parseFrom(input);
} }
public static com.google.protobuf.jruby.SentinelOuterClass.Sentinel parseFrom( public static com.google.protobuf.jruby.SentinelOuterClass.Sentinel parseFrom(
java.io.InputStream input, java.io.InputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry)
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws java.io.IOException { throws java.io.IOException {
return PARSER.parseFrom(input, extensionRegistry); return PARSER.parseFrom(input, extensionRegistry);
} }
public static com.google.protobuf.jruby.SentinelOuterClass.Sentinel parseDelimitedFrom(java.io.InputStream input)
throws java.io.IOException { public static com.google.protobuf.jruby.SentinelOuterClass.Sentinel parseDelimitedFrom(
java.io.InputStream input) throws java.io.IOException {
return PARSER.parseDelimitedFrom(input); return PARSER.parseDelimitedFrom(input);
} }
public static com.google.protobuf.jruby.SentinelOuterClass.Sentinel parseDelimitedFrom( public static com.google.protobuf.jruby.SentinelOuterClass.Sentinel parseDelimitedFrom(
java.io.InputStream input, java.io.InputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry)
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws java.io.IOException { throws java.io.IOException {
return PARSER.parseDelimitedFrom(input, extensionRegistry); return PARSER.parseDelimitedFrom(input, extensionRegistry);
} }
public static com.google.protobuf.jruby.SentinelOuterClass.Sentinel parseFrom( public static com.google.protobuf.jruby.SentinelOuterClass.Sentinel parseFrom(
com.google.protobuf.CodedInputStream input) com.google.protobuf.CodedInputStream input) throws java.io.IOException {
throws java.io.IOException {
return PARSER.parseFrom(input); return PARSER.parseFrom(input);
} }
public static com.google.protobuf.jruby.SentinelOuterClass.Sentinel parseFrom( public static com.google.protobuf.jruby.SentinelOuterClass.Sentinel parseFrom(
com.google.protobuf.CodedInputStream input, com.google.protobuf.CodedInputStream input,
com.google.protobuf.ExtensionRegistryLite extensionRegistry) com.google.protobuf.ExtensionRegistryLite extensionRegistry)
@ -319,36 +282,45 @@ public final class SentinelOuterClass {
return PARSER.parseFrom(input, extensionRegistry); return PARSER.parseFrom(input, extensionRegistry);
} }
public static Builder newBuilder() { return new Builder(); } public static Builder newBuilder() {
public Builder newBuilderForType() { return newBuilder(); } return new Builder();
public static Builder newBuilder(com.google.protobuf.jruby.SentinelOuterClass.Sentinel prototype) { }
public Builder newBuilderForType() {
return newBuilder();
}
public static Builder newBuilder(
com.google.protobuf.jruby.SentinelOuterClass.Sentinel prototype) {
return newBuilder().mergeFrom(prototype); return newBuilder().mergeFrom(prototype);
} }
public Builder toBuilder() { return newBuilder(this); }
public Builder toBuilder() {
return newBuilder(this);
}
@java.lang.Override @java.lang.Override
protected Builder newBuilderForType( protected Builder newBuilderForType(com.google.protobuf.GeneratedMessage.BuilderParent parent) {
com.google.protobuf.GeneratedMessage.BuilderParent parent) {
Builder builder = new Builder(parent); Builder builder = new Builder(parent);
return builder; return builder;
} }
/** /** Protobuf type {@code com.google.protobuf.jruby.Sentinel} */
* Protobuf type {@code com.google.protobuf.jruby.Sentinel} public static final class Builder extends com.google.protobuf.GeneratedMessage.Builder<Builder>
*/ implements
public static final class Builder extends
com.google.protobuf.GeneratedMessage.Builder<Builder> implements
// @@protoc_insertion_point(builder_implements:com.google.protobuf.jruby.Sentinel) // @@protoc_insertion_point(builder_implements:com.google.protobuf.jruby.Sentinel)
com.google.protobuf.jruby.SentinelOuterClass.SentinelOrBuilder { com.google.protobuf.jruby.SentinelOuterClass.SentinelOrBuilder {
public static final com.google.protobuf.Descriptors.Descriptor public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() {
getDescriptor() { return com.google.protobuf.jruby.SentinelOuterClass
return com.google.protobuf.jruby.SentinelOuterClass.internal_static_com_google_protobuf_jruby_Sentinel_descriptor; .internal_static_com_google_protobuf_jruby_Sentinel_descriptor;
} }
protected com.google.protobuf.GeneratedMessage.FieldAccessorTable protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
internalGetFieldAccessorTable() { internalGetFieldAccessorTable() {
return com.google.protobuf.jruby.SentinelOuterClass.internal_static_com_google_protobuf_jruby_Sentinel_fieldAccessorTable return com.google.protobuf.jruby.SentinelOuterClass
.internal_static_com_google_protobuf_jruby_Sentinel_fieldAccessorTable
.ensureFieldAccessorsInitialized( .ensureFieldAccessorsInitialized(
com.google.protobuf.jruby.SentinelOuterClass.Sentinel.class, com.google.protobuf.jruby.SentinelOuterClass.Sentinel.Builder.class); com.google.protobuf.jruby.SentinelOuterClass.Sentinel.class,
com.google.protobuf.jruby.SentinelOuterClass.Sentinel.Builder.class);
} }
// Construct using com.google.protobuf.jruby.SentinelOuterClass.Sentinel.newBuilder() // Construct using com.google.protobuf.jruby.SentinelOuterClass.Sentinel.newBuilder()
@ -356,15 +328,15 @@ public final class SentinelOuterClass {
maybeForceBuilderInitialization(); maybeForceBuilderInitialization();
} }
private Builder( private Builder(com.google.protobuf.GeneratedMessage.BuilderParent parent) {
com.google.protobuf.GeneratedMessage.BuilderParent parent) {
super(parent); super(parent);
maybeForceBuilderInitialization(); maybeForceBuilderInitialization();
} }
private void maybeForceBuilderInitialization() { private void maybeForceBuilderInitialization() {
if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) { if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {}
}
} }
public Builder clear() { public Builder clear() {
super.clear(); super.clear();
defaultInt32_ = 0; defaultInt32_ = 0;
@ -388,9 +360,9 @@ public final class SentinelOuterClass {
return this; return this;
} }
public com.google.protobuf.Descriptors.Descriptor public com.google.protobuf.Descriptors.Descriptor getDescriptorForType() {
getDescriptorForType() { return com.google.protobuf.jruby.SentinelOuterClass
return com.google.protobuf.jruby.SentinelOuterClass.internal_static_com_google_protobuf_jruby_Sentinel_descriptor; .internal_static_com_google_protobuf_jruby_Sentinel_descriptor;
} }
public com.google.protobuf.jruby.SentinelOuterClass.Sentinel getDefaultInstanceForType() { public com.google.protobuf.jruby.SentinelOuterClass.Sentinel getDefaultInstanceForType() {
@ -406,7 +378,8 @@ public final class SentinelOuterClass {
} }
public com.google.protobuf.jruby.SentinelOuterClass.Sentinel buildPartial() { public com.google.protobuf.jruby.SentinelOuterClass.Sentinel buildPartial() {
com.google.protobuf.jruby.SentinelOuterClass.Sentinel result = new com.google.protobuf.jruby.SentinelOuterClass.Sentinel(this); com.google.protobuf.jruby.SentinelOuterClass.Sentinel result =
new com.google.protobuf.jruby.SentinelOuterClass.Sentinel(this);
result.defaultInt32_ = defaultInt32_; result.defaultInt32_ = defaultInt32_;
result.defaultInt64_ = defaultInt64_; result.defaultInt64_ = defaultInt64_;
result.defaultUnit32_ = defaultUnit32_; result.defaultUnit32_ = defaultUnit32_;
@ -420,26 +393,19 @@ public final class SentinelOuterClass {
return result; return result;
} }
private int defaultInt32_;
private int defaultInt32_ ; /** <code>optional int32 default_int32 = 1;</code> */
/**
* <code>optional int32 default_int32 = 1;</code>
*/
public int getDefaultInt32() { public int getDefaultInt32() {
return defaultInt32_; return defaultInt32_;
} }
/** /** <code>optional int32 default_int32 = 1;</code> */
* <code>optional int32 default_int32 = 1;</code>
*/
public Builder setDefaultInt32(int value) { public Builder setDefaultInt32(int value) {
defaultInt32_ = value; defaultInt32_ = value;
onChanged(); onChanged();
return this; return this;
} }
/** /** <code>optional int32 default_int32 = 1;</code> */
* <code>optional int32 default_int32 = 1;</code>
*/
public Builder clearDefaultInt32() { public Builder clearDefaultInt32() {
defaultInt32_ = 0; defaultInt32_ = 0;
@ -447,25 +413,19 @@ public final class SentinelOuterClass {
return this; return this;
} }
private long defaultInt64_ ; private long defaultInt64_;
/** /** <code>optional int64 default_int64 = 2;</code> */
* <code>optional int64 default_int64 = 2;</code>
*/
public long getDefaultInt64() { public long getDefaultInt64() {
return defaultInt64_; return defaultInt64_;
} }
/** /** <code>optional int64 default_int64 = 2;</code> */
* <code>optional int64 default_int64 = 2;</code>
*/
public Builder setDefaultInt64(long value) { public Builder setDefaultInt64(long value) {
defaultInt64_ = value; defaultInt64_ = value;
onChanged(); onChanged();
return this; return this;
} }
/** /** <code>optional int64 default_int64 = 2;</code> */
* <code>optional int64 default_int64 = 2;</code>
*/
public Builder clearDefaultInt64() { public Builder clearDefaultInt64() {
defaultInt64_ = 0L; defaultInt64_ = 0L;
@ -473,25 +433,19 @@ public final class SentinelOuterClass {
return this; return this;
} }
private int defaultUnit32_ ; private int defaultUnit32_;
/** /** <code>optional uint32 default_unit32 = 3;</code> */
* <code>optional uint32 default_unit32 = 3;</code>
*/
public int getDefaultUnit32() { public int getDefaultUnit32() {
return defaultUnit32_; return defaultUnit32_;
} }
/** /** <code>optional uint32 default_unit32 = 3;</code> */
* <code>optional uint32 default_unit32 = 3;</code>
*/
public Builder setDefaultUnit32(int value) { public Builder setDefaultUnit32(int value) {
defaultUnit32_ = value; defaultUnit32_ = value;
onChanged(); onChanged();
return this; return this;
} }
/** /** <code>optional uint32 default_unit32 = 3;</code> */
* <code>optional uint32 default_unit32 = 3;</code>
*/
public Builder clearDefaultUnit32() { public Builder clearDefaultUnit32() {
defaultUnit32_ = 0; defaultUnit32_ = 0;
@ -499,25 +453,19 @@ public final class SentinelOuterClass {
return this; return this;
} }
private long defaultUint64_ ; private long defaultUint64_;
/** /** <code>optional uint64 default_uint64 = 4;</code> */
* <code>optional uint64 default_uint64 = 4;</code>
*/
public long getDefaultUint64() { public long getDefaultUint64() {
return defaultUint64_; return defaultUint64_;
} }
/** /** <code>optional uint64 default_uint64 = 4;</code> */
* <code>optional uint64 default_uint64 = 4;</code>
*/
public Builder setDefaultUint64(long value) { public Builder setDefaultUint64(long value) {
defaultUint64_ = value; defaultUint64_ = value;
onChanged(); onChanged();
return this; return this;
} }
/** /** <code>optional uint64 default_uint64 = 4;</code> */
* <code>optional uint64 default_uint64 = 4;</code>
*/
public Builder clearDefaultUint64() { public Builder clearDefaultUint64() {
defaultUint64_ = 0L; defaultUint64_ = 0L;
@ -526,14 +474,11 @@ public final class SentinelOuterClass {
} }
private java.lang.Object defaultString_ = ""; private java.lang.Object defaultString_ = "";
/** /** <code>optional string default_string = 5;</code> */
* <code>optional string default_string = 5;</code>
*/
public java.lang.String getDefaultString() { public java.lang.String getDefaultString() {
java.lang.Object ref = defaultString_; java.lang.Object ref = defaultString_;
if (!(ref instanceof java.lang.String)) { if (!(ref instanceof java.lang.String)) {
com.google.protobuf.ByteString bs = com.google.protobuf.ByteString bs = (com.google.protobuf.ByteString) ref;
(com.google.protobuf.ByteString) ref;
java.lang.String s = bs.toStringUtf8(); java.lang.String s = bs.toStringUtf8();
if (bs.isValidUtf8()) { if (bs.isValidUtf8()) {
defaultString_ = s; defaultString_ = s;
@ -543,77 +488,59 @@ public final class SentinelOuterClass {
return (java.lang.String) ref; return (java.lang.String) ref;
} }
} }
/** /** <code>optional string default_string = 5;</code> */
* <code>optional string default_string = 5;</code> public com.google.protobuf.ByteString getDefaultStringBytes() {
*/
public com.google.protobuf.ByteString
getDefaultStringBytes() {
java.lang.Object ref = defaultString_; java.lang.Object ref = defaultString_;
if (ref instanceof String) { if (ref instanceof String) {
com.google.protobuf.ByteString b = com.google.protobuf.ByteString b =
com.google.protobuf.ByteString.copyFromUtf8( com.google.protobuf.ByteString.copyFromUtf8((java.lang.String) ref);
(java.lang.String) ref);
defaultString_ = b; defaultString_ = b;
return b; return b;
} else { } else {
return (com.google.protobuf.ByteString) ref; return (com.google.protobuf.ByteString) ref;
} }
} }
/** /** <code>optional string default_string = 5;</code> */
* <code>optional string default_string = 5;</code> public Builder setDefaultString(java.lang.String value) {
*/
public Builder setDefaultString(
java.lang.String value) {
if (value == null) { if (value == null) {
throw new NullPointerException(); throw new NullPointerException();
} }
defaultString_ = value; defaultString_ = value;
onChanged(); onChanged();
return this; return this;
} }
/** /** <code>optional string default_string = 5;</code> */
* <code>optional string default_string = 5;</code>
*/
public Builder clearDefaultString() { public Builder clearDefaultString() {
defaultString_ = getDefaultInstance().getDefaultString(); defaultString_ = getDefaultInstance().getDefaultString();
onChanged(); onChanged();
return this; return this;
} }
/** /** <code>optional string default_string = 5;</code> */
* <code>optional string default_string = 5;</code> public Builder setDefaultStringBytes(com.google.protobuf.ByteString value) {
*/
public Builder setDefaultStringBytes(
com.google.protobuf.ByteString value) {
if (value == null) { if (value == null) {
throw new NullPointerException(); throw new NullPointerException();
} }
defaultString_ = value; defaultString_ = value;
onChanged(); onChanged();
return this; return this;
} }
private boolean defaultBool_ ; private boolean defaultBool_;
/** /** <code>optional bool default_bool = 6;</code> */
* <code>optional bool default_bool = 6;</code>
*/
public boolean getDefaultBool() { public boolean getDefaultBool() {
return defaultBool_; return defaultBool_;
} }
/** /** <code>optional bool default_bool = 6;</code> */
* <code>optional bool default_bool = 6;</code>
*/
public Builder setDefaultBool(boolean value) { public Builder setDefaultBool(boolean value) {
defaultBool_ = value; defaultBool_ = value;
onChanged(); onChanged();
return this; return this;
} }
/** /** <code>optional bool default_bool = 6;</code> */
* <code>optional bool default_bool = 6;</code>
*/
public Builder clearDefaultBool() { public Builder clearDefaultBool() {
defaultBool_ = false; defaultBool_ = false;
@ -621,25 +548,19 @@ public final class SentinelOuterClass {
return this; return this;
} }
private float defaultFloat_ ; private float defaultFloat_;
/** /** <code>optional float default_float = 7;</code> */
* <code>optional float default_float = 7;</code>
*/
public float getDefaultFloat() { public float getDefaultFloat() {
return defaultFloat_; return defaultFloat_;
} }
/** /** <code>optional float default_float = 7;</code> */
* <code>optional float default_float = 7;</code>
*/
public Builder setDefaultFloat(float value) { public Builder setDefaultFloat(float value) {
defaultFloat_ = value; defaultFloat_ = value;
onChanged(); onChanged();
return this; return this;
} }
/** /** <code>optional float default_float = 7;</code> */
* <code>optional float default_float = 7;</code>
*/
public Builder clearDefaultFloat() { public Builder clearDefaultFloat() {
defaultFloat_ = 0F; defaultFloat_ = 0F;
@ -647,25 +568,19 @@ public final class SentinelOuterClass {
return this; return this;
} }
private double defaultDouble_ ; private double defaultDouble_;
/** /** <code>optional double default_double = 8;</code> */
* <code>optional double default_double = 8;</code>
*/
public double getDefaultDouble() { public double getDefaultDouble() {
return defaultDouble_; return defaultDouble_;
} }
/** /** <code>optional double default_double = 8;</code> */
* <code>optional double default_double = 8;</code>
*/
public Builder setDefaultDouble(double value) { public Builder setDefaultDouble(double value) {
defaultDouble_ = value; defaultDouble_ = value;
onChanged(); onChanged();
return this; return this;
} }
/** /** <code>optional double default_double = 8;</code> */
* <code>optional double default_double = 8;</code>
*/
public Builder clearDefaultDouble() { public Builder clearDefaultDouble() {
defaultDouble_ = 0D; defaultDouble_ = 0D;
@ -674,33 +589,28 @@ public final class SentinelOuterClass {
} }
private com.google.protobuf.ByteString defaultBytes_ = com.google.protobuf.ByteString.EMPTY; private com.google.protobuf.ByteString defaultBytes_ = com.google.protobuf.ByteString.EMPTY;
/** /** <code>optional bytes default_bytes = 9;</code> */
* <code>optional bytes default_bytes = 9;</code>
*/
public com.google.protobuf.ByteString getDefaultBytes() { public com.google.protobuf.ByteString getDefaultBytes() {
return defaultBytes_; return defaultBytes_;
} }
/** /** <code>optional bytes default_bytes = 9;</code> */
* <code>optional bytes default_bytes = 9;</code>
*/
public Builder setDefaultBytes(com.google.protobuf.ByteString value) { public Builder setDefaultBytes(com.google.protobuf.ByteString value) {
if (value == null) { if (value == null) {
throw new NullPointerException(); throw new NullPointerException();
} }
defaultBytes_ = value; defaultBytes_ = value;
onChanged(); onChanged();
return this; return this;
} }
/** /** <code>optional bytes default_bytes = 9;</code> */
* <code>optional bytes default_bytes = 9;</code>
*/
public Builder clearDefaultBytes() { public Builder clearDefaultBytes() {
defaultBytes_ = getDefaultInstance().getDefaultBytes(); defaultBytes_ = getDefaultInstance().getDefaultBytes();
onChanged(); onChanged();
return this; return this;
} }
public final Builder setUnknownFields( public final Builder setUnknownFields(
final com.google.protobuf.UnknownFieldSet unknownFields) { final com.google.protobuf.UnknownFieldSet unknownFields) {
return this; return this;
@ -711,12 +621,13 @@ public final class SentinelOuterClass {
return this; return this;
} }
// @@protoc_insertion_point(builder_scope:com.google.protobuf.jruby.Sentinel) // @@protoc_insertion_point(builder_scope:com.google.protobuf.jruby.Sentinel)
} }
// @@protoc_insertion_point(class_scope:com.google.protobuf.jruby.Sentinel) // @@protoc_insertion_point(class_scope:com.google.protobuf.jruby.Sentinel)
private static final com.google.protobuf.jruby.SentinelOuterClass.Sentinel defaultInstance;static { private static final com.google.protobuf.jruby.SentinelOuterClass.Sentinel defaultInstance;
static {
defaultInstance = new com.google.protobuf.jruby.SentinelOuterClass.Sentinel(); defaultInstance = new com.google.protobuf.jruby.SentinelOuterClass.Sentinel();
} }
@ -727,49 +638,55 @@ public final class SentinelOuterClass {
public com.google.protobuf.jruby.SentinelOuterClass.Sentinel getDefaultInstanceForType() { public com.google.protobuf.jruby.SentinelOuterClass.Sentinel getDefaultInstanceForType() {
return defaultInstance; return defaultInstance;
} }
} }
private static final com.google.protobuf.Descriptors.Descriptor private static final com.google.protobuf.Descriptors.Descriptor
internal_static_com_google_protobuf_jruby_Sentinel_descriptor; internal_static_com_google_protobuf_jruby_Sentinel_descriptor;
private static private static com.google.protobuf.GeneratedMessage.FieldAccessorTable
com.google.protobuf.GeneratedMessage.FieldAccessorTable
internal_static_com_google_protobuf_jruby_Sentinel_fieldAccessorTable; internal_static_com_google_protobuf_jruby_Sentinel_fieldAccessorTable;
public static com.google.protobuf.Descriptors.FileDescriptor public static com.google.protobuf.Descriptors.FileDescriptor getDescriptor() {
getDescriptor() {
return descriptor; return descriptor;
} }
private static com.google.protobuf.Descriptors.FileDescriptor
descriptor; private static com.google.protobuf.Descriptors.FileDescriptor descriptor;
static { static {
java.lang.String[] descriptorData = { java.lang.String[] descriptorData = {
"\n\016sentinel.proto\022\031com.google.protobuf.jr" + "\n\016sentinel.proto\022\031com.google.protobuf.jr"
"uby\"\334\001\n\010Sentinel\022\025\n\rdefault_int32\030\001 \001(\005\022" + + "uby\"\334\001\n\010Sentinel\022\025\n\rdefault_int32\030\001 \001(\005\022"
"\025\n\rdefault_int64\030\002 \001(\003\022\026\n\016default_unit32" + + "\025\n\rdefault_int64\030\002 \001(\003\022\026\n\016default_unit32"
"\030\003 \001(\r\022\026\n\016default_uint64\030\004 \001(\004\022\026\n\016defaul" + + "\030\003 \001(\r\022\026\n\016default_uint64\030\004 \001(\004\022\026\n\016defaul"
"t_string\030\005 \001(\t\022\024\n\014default_bool\030\006 \001(\010\022\025\n\r" + + "t_string\030\005 \001(\t\022\024\n\014default_bool\030\006 \001(\010\022\025\n\r"
"default_float\030\007 \001(\002\022\026\n\016default_double\030\010 " + + "default_float\030\007 \001(\002\022\026\n\016default_double\030\010 "
"\001(\001\022\025\n\rdefault_bytes\030\t \001(\014B\002H\002b\006proto3" + "\001(\001\022\025\n\rdefault_bytes\030\t \001(\014B\002H\002b\006proto3"
}; };
com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner = com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner =
new com.google.protobuf.Descriptors.FileDescriptor. InternalDescriptorAssigner() { new com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner() {
public com.google.protobuf.ExtensionRegistry assignDescriptors( public com.google.protobuf.ExtensionRegistry assignDescriptors(
com.google.protobuf.Descriptors.FileDescriptor root) { com.google.protobuf.Descriptors.FileDescriptor root) {
descriptor = root; descriptor = root;
return null; return null;
} }
}; };
com.google.protobuf.Descriptors.FileDescriptor com.google.protobuf.Descriptors.FileDescriptor.internalBuildGeneratedFileFrom(
.internalBuildGeneratedFileFrom(descriptorData, descriptorData, new com.google.protobuf.Descriptors.FileDescriptor[] {}, assigner);
new com.google.protobuf.Descriptors.FileDescriptor[] {
}, assigner);
internal_static_com_google_protobuf_jruby_Sentinel_descriptor = internal_static_com_google_protobuf_jruby_Sentinel_descriptor =
getDescriptor().getMessageTypes().get(0); getDescriptor().getMessageTypes().get(0);
internal_static_com_google_protobuf_jruby_Sentinel_fieldAccessorTable = new internal_static_com_google_protobuf_jruby_Sentinel_fieldAccessorTable =
com.google.protobuf.GeneratedMessage.FieldAccessorTable( new com.google.protobuf.GeneratedMessage.FieldAccessorTable(
internal_static_com_google_protobuf_jruby_Sentinel_descriptor, internal_static_com_google_protobuf_jruby_Sentinel_descriptor,
new java.lang.String[] { "DefaultInt32", "DefaultInt64", "DefaultUnit32", "DefaultUint64", "DefaultString", "DefaultBool", "DefaultFloat", "DefaultDouble", "DefaultBytes", }); new java.lang.String[] {
"DefaultInt32",
"DefaultInt64",
"DefaultUnit32",
"DefaultUint64",
"DefaultString",
"DefaultBool",
"DefaultFloat",
"DefaultDouble",
"DefaultBytes",
});
} }
// @@protoc_insertion_point(outer_class_scope) // @@protoc_insertion_point(outer_class_scope)

@ -35,6 +35,7 @@ package com.google.protobuf.jruby;
import com.google.protobuf.ByteString; import com.google.protobuf.ByteString;
import com.google.protobuf.DescriptorProtos.FieldDescriptorProto; import com.google.protobuf.DescriptorProtos.FieldDescriptorProto;
import com.google.protobuf.Descriptors.FieldDescriptor; import com.google.protobuf.Descriptors.FieldDescriptor;
import java.math.BigInteger;
import org.jcodings.specific.ASCIIEncoding; import org.jcodings.specific.ASCIIEncoding;
import org.jruby.*; import org.jruby.*;
import org.jruby.exceptions.RaiseException; import org.jruby.exceptions.RaiseException;
@ -44,302 +45,363 @@ import org.jruby.runtime.Helpers;
import org.jruby.runtime.ThreadContext; import org.jruby.runtime.ThreadContext;
import org.jruby.runtime.builtin.IRubyObject; import org.jruby.runtime.builtin.IRubyObject;
import java.math.BigInteger;
public class Utils { public class Utils {
public static FieldDescriptor.Type rubyToFieldType(IRubyObject typeClass) { public static FieldDescriptor.Type rubyToFieldType(IRubyObject typeClass) {
return FieldDescriptor.Type.valueOf(typeClass.asJavaString().toUpperCase()); return FieldDescriptor.Type.valueOf(typeClass.asJavaString().toUpperCase());
} }
public static IRubyObject fieldTypeToRuby(ThreadContext context, FieldDescriptor.Type type) { public static IRubyObject fieldTypeToRuby(ThreadContext context, FieldDescriptor.Type type) {
return fieldTypeToRuby(context, type.name()); return fieldTypeToRuby(context, type.name());
} }
public static IRubyObject fieldTypeToRuby(ThreadContext context, FieldDescriptorProto.Type type) { public static IRubyObject fieldTypeToRuby(ThreadContext context, FieldDescriptorProto.Type type) {
return fieldTypeToRuby(context, type.name()); return fieldTypeToRuby(context, type.name());
} }
private static IRubyObject fieldTypeToRuby(ThreadContext context, String typeName) { private static IRubyObject fieldTypeToRuby(ThreadContext context, String typeName) {
return context.runtime.newSymbol(typeName.replace("TYPE_", "").toLowerCase()); return context.runtime.newSymbol(typeName.replace("TYPE_", "").toLowerCase());
} }
public static IRubyObject checkType(
ThreadContext context,
FieldDescriptor.Type fieldType,
String fieldName,
IRubyObject value,
RubyModule typeClass) {
Ruby runtime = context.runtime;
switch (fieldType) {
case SFIXED32:
case SFIXED64:
case FIXED64:
case SINT64:
case SINT32:
case FIXED32:
case INT32:
case INT64:
case UINT32:
case UINT64:
if (!isRubyNum(value))
throw createExpectedTypeError(context, "number", "integral", fieldName, value);
public static IRubyObject checkType(ThreadContext context, FieldDescriptor.Type fieldType, if (value instanceof RubyFloat) {
String fieldName, IRubyObject value, RubyModule typeClass) { double doubleVal = RubyNumeric.num2dbl(value);
Ruby runtime = context.runtime; if (Math.floor(doubleVal) != doubleVal) {
throw runtime.newRangeError(
switch(fieldType) { "Non-integral floating point value assigned to integer field '"
case SFIXED32: + fieldName
case SFIXED64: + "' (given "
case FIXED64: + value.getMetaClass()
case SINT64: + ").");
case SINT32: }
case FIXED32: }
case INT32: if (fieldType == FieldDescriptor.Type.UINT32
case INT64: || fieldType == FieldDescriptor.Type.UINT64
case UINT32: || fieldType == FieldDescriptor.Type.FIXED32
case UINT64: || fieldType == FieldDescriptor.Type.FIXED64) {
if (!isRubyNum(value)) if (((RubyNumeric) value).isNegative()) {
throw createExpectedTypeError(context, "number", "integral", fieldName, value); throw runtime.newRangeError(
"Assigning negative value to unsigned integer field '"
if (value instanceof RubyFloat) { + fieldName
double doubleVal = RubyNumeric.num2dbl(value); + "' (given "
if (Math.floor(doubleVal) != doubleVal) { + value.getMetaClass()
throw runtime.newRangeError("Non-integral floating point value assigned to integer field '" + fieldName + "' (given " + value.getMetaClass() + ")."); + ").");
} }
}
if (fieldType == FieldDescriptor.Type.UINT32 || fieldType == FieldDescriptor.Type.UINT64 ||
fieldType == FieldDescriptor.Type.FIXED32 || fieldType == FieldDescriptor.Type.FIXED64) {
if (((RubyNumeric) value).isNegative()) {
throw runtime.newRangeError("Assigning negative value to unsigned integer field '" + fieldName + "' (given " + value.getMetaClass() + ").");
}
}
switch(fieldType) {
case INT32:
RubyNumeric.num2int(value);
break;
case UINT32:
case FIXED32:
num2uint(value);
break;
case UINT64:
case FIXED64:
num2ulong(context.runtime, value);
break;
default:
RubyNumeric.num2long(value);
break;
}
break;
case FLOAT:
if (!isRubyNum(value))
throw createExpectedTypeError(context, "number", "float", fieldName, value);
break;
case DOUBLE:
if (!isRubyNum(value))
throw createExpectedTypeError(context, "number", "double", fieldName, value);
break;
case BOOL:
if (!(value instanceof RubyBoolean))
throw createInvalidTypeError(context, "boolean", fieldName, value);
break;
case BYTES:
value = validateAndEncodeString(context, "bytes", fieldName, value, "Encoding::ASCII_8BIT");
break;
case STRING:
value = validateAndEncodeString(context, "string", fieldName, symToString(value), "Encoding::UTF_8");
break;
case MESSAGE:
if (value.getMetaClass() != typeClass) {
// See if we can convert the value before flagging it as invalid
String className = typeClass.getName();
if (className.equals("Google::Protobuf::Timestamp") && value instanceof RubyTime) {
RubyTime rt = (RubyTime) value;
RubyHash timestampArgs =
Helpers.constructHash(runtime,
runtime.newString("nanos"), rt.nsec(), false,
runtime.newString("seconds"), rt.to_i(), false);
return ((RubyClass) typeClass).newInstance(context, timestampArgs, Block.NULL_BLOCK);
} else if (className.equals("Google::Protobuf::Duration") && value instanceof RubyNumeric) {
IRubyObject seconds;
if (value instanceof RubyFloat) {
seconds = ((RubyFloat) value).truncate(context);
} else if (value instanceof RubyRational) {
seconds = ((RubyRational) value).to_i(context);
} else if (value instanceof RubyBigDecimal) {
seconds = ((RubyBigDecimal) value).to_int(context);
} else {
seconds = ((RubyInteger) value).to_i();
}
IRubyObject nanos = ((RubyNumeric) value).remainder(context, RubyFixnum.one(runtime));
if (nanos instanceof RubyFloat) {
nanos = ((RubyFloat) nanos).op_mul(context, 1000000000);
} else if (nanos instanceof RubyRational) {
nanos = ((RubyRational) nanos).op_mul(context, runtime.newFixnum(1000000000));
} else if (nanos instanceof RubyBigDecimal) {
nanos = ((RubyBigDecimal) nanos).op_mul(context, runtime.newFixnum(1000000000));
} else {
nanos = ((RubyInteger) nanos).op_mul(context, 1000000000);
}
RubyHash durationArgs =
Helpers.constructHash(runtime,
runtime.newString("nanos"), ((RubyNumeric) nanos).round(context), false,
runtime.newString("seconds"), seconds, false);
return ((RubyClass) typeClass).newInstance(context, durationArgs, Block.NULL_BLOCK);
}
// Not able to convert so flag as invalid
throw createTypeError(context, "Invalid type " + value.getMetaClass() + " to assign to submessage field '" + fieldName + "'.");
}
break;
case ENUM:
boolean isValid = ((RubyEnumDescriptor) typeClass.getInstanceVariable(DESCRIPTOR_INSTANCE_VAR)).isValidValue(context, value);
if (!isValid) {
throw runtime.newRangeError("Unknown symbol value for enum field '" + fieldName + "'.");
}
break;
default:
break;
} }
return value;
}
public static IRubyObject wrapPrimaryValue(ThreadContext context, FieldDescriptor.Type fieldType, Object value) {
return wrapPrimaryValue(context, fieldType, value, false);
}
public static IRubyObject wrapPrimaryValue(ThreadContext context, FieldDescriptor.Type fieldType, Object value, boolean encodeBytes) {
Ruby runtime = context.runtime;
switch (fieldType) { switch (fieldType) {
case INT32: case INT32:
case SFIXED32: RubyNumeric.num2int(value);
case SINT32: break;
return runtime.newFixnum((Integer) value); case UINT32:
case SFIXED64: case FIXED32:
case SINT64: num2uint(value);
case INT64: break;
return runtime.newFixnum((Long) value); case UINT64:
case FIXED32: case FIXED64:
case UINT32: num2ulong(context.runtime, value);
return runtime.newFixnum(((Integer) value) & (-1l >>> 32)); break;
case FIXED64: default:
case UINT64: RubyNumeric.num2long(value);
long ret = (Long) value; break;
return ret >= 0 ? runtime.newFixnum(ret) :
RubyBignum.newBignum(runtime, UINT64_COMPLEMENTARY.add(new BigInteger(ret + "")));
case FLOAT:
return runtime.newFloat((Float) value);
case DOUBLE:
return runtime.newFloat((Double) value);
case BOOL:
return (Boolean) value ? runtime.getTrue() : runtime.getFalse();
case BYTES: {
IRubyObject wrapped = encodeBytes ?
RubyString.newString(runtime, ((ByteString) value).toStringUtf8(), ASCIIEncoding.INSTANCE) :
RubyString.newString(runtime, ((ByteString) value).toByteArray());
wrapped.setFrozen(true);
return wrapped;
}
case STRING: {
IRubyObject wrapped = runtime.newString(value.toString());
wrapped.setFrozen(true);
return wrapped;
}
default:
return runtime.getNil();
} }
} break;
case FLOAT:
if (!isRubyNum(value))
throw createExpectedTypeError(context, "number", "float", fieldName, value);
break;
case DOUBLE:
if (!isRubyNum(value))
throw createExpectedTypeError(context, "number", "double", fieldName, value);
break;
case BOOL:
if (!(value instanceof RubyBoolean))
throw createInvalidTypeError(context, "boolean", fieldName, value);
break;
case BYTES:
value = validateAndEncodeString(context, "bytes", fieldName, value, "Encoding::ASCII_8BIT");
break;
case STRING:
value =
validateAndEncodeString(
context, "string", fieldName, symToString(value), "Encoding::UTF_8");
break;
case MESSAGE:
if (value.getMetaClass() != typeClass) {
// See if we can convert the value before flagging it as invalid
String className = typeClass.getName();
if (className.equals("Google::Protobuf::Timestamp") && value instanceof RubyTime) {
RubyTime rt = (RubyTime) value;
RubyHash timestampArgs =
Helpers.constructHash(
runtime,
runtime.newString("nanos"),
rt.nsec(),
false,
runtime.newString("seconds"),
rt.to_i(),
false);
return ((RubyClass) typeClass).newInstance(context, timestampArgs, Block.NULL_BLOCK);
} else if (className.equals("Google::Protobuf::Duration")
&& value instanceof RubyNumeric) {
IRubyObject seconds;
if (value instanceof RubyFloat) {
seconds = ((RubyFloat) value).truncate(context);
} else if (value instanceof RubyRational) {
seconds = ((RubyRational) value).to_i(context);
} else if (value instanceof RubyBigDecimal) {
seconds = ((RubyBigDecimal) value).to_int(context);
} else {
seconds = ((RubyInteger) value).to_i();
}
public static int num2uint(IRubyObject value) { IRubyObject nanos = ((RubyNumeric) value).remainder(context, RubyFixnum.one(runtime));
long longVal = RubyNumeric.num2long(value); if (nanos instanceof RubyFloat) {
if (longVal > UINT_MAX) nanos = ((RubyFloat) nanos).op_mul(context, 1000000000);
throw value.getRuntime().newRangeError("Integer " + longVal + " too big to convert to 'unsigned int'"); } else if (nanos instanceof RubyRational) {
long num = longVal; nanos = ((RubyRational) nanos).op_mul(context, runtime.newFixnum(1000000000));
if (num > Integer.MAX_VALUE || num < Integer.MIN_VALUE) } else if (nanos instanceof RubyBigDecimal) {
// encode to UINT32 nanos = ((RubyBigDecimal) nanos).op_mul(context, runtime.newFixnum(1000000000));
num = (-longVal ^ (-1l >>> 32) ) + 1; } else {
RubyNumeric.checkInt(value, num); nanos = ((RubyInteger) nanos).op_mul(context, 1000000000);
return (int) num; }
}
public static long num2ulong(Ruby runtime, IRubyObject value) { RubyHash durationArgs =
if (value instanceof RubyFloat) { Helpers.constructHash(
RubyBignum bignum = RubyBignum.newBignum(runtime, ((RubyFloat) value).getDoubleValue()); runtime,
return RubyBignum.big2ulong(bignum); runtime.newString("nanos"),
} else if (value instanceof RubyBignum) { ((RubyNumeric) nanos).round(context),
return RubyBignum.big2ulong((RubyBignum) value); false,
} else { runtime.newString("seconds"),
return RubyNumeric.num2long(value); seconds,
false);
return ((RubyClass) typeClass).newInstance(context, durationArgs, Block.NULL_BLOCK);
}
// Not able to convert so flag as invalid
throw createTypeError(
context,
"Invalid type "
+ value.getMetaClass()
+ " to assign to submessage field '"
+ fieldName
+ "'.");
} }
}
/* break;
* Helper to make it easier to support symbols being passed instead of strings case ENUM:
*/ boolean isValid =
public static IRubyObject symToString(IRubyObject sym) { ((RubyEnumDescriptor) typeClass.getInstanceVariable(DESCRIPTOR_INSTANCE_VAR))
if (sym instanceof RubySymbol) { .isValidValue(context, value);
return ((RubySymbol) sym).id2name(); if (!isValid) {
throw runtime.newRangeError("Unknown symbol value for enum field '" + fieldName + "'.");
} }
return sym; break;
default:
break;
} }
return value;
public static void checkNameAvailability(ThreadContext context, String name) { }
if (context.runtime.getObject().getConstantAt(name) != null)
throw context.runtime.newNameError(name + " is already defined", name); public static IRubyObject wrapPrimaryValue(
ThreadContext context, FieldDescriptor.Type fieldType, Object value) {
return wrapPrimaryValue(context, fieldType, value, false);
}
public static IRubyObject wrapPrimaryValue(
ThreadContext context, FieldDescriptor.Type fieldType, Object value, boolean encodeBytes) {
Ruby runtime = context.runtime;
switch (fieldType) {
case INT32:
case SFIXED32:
case SINT32:
return runtime.newFixnum((Integer) value);
case SFIXED64:
case SINT64:
case INT64:
return runtime.newFixnum((Long) value);
case FIXED32:
case UINT32:
return runtime.newFixnum(((Integer) value) & (-1l >>> 32));
case FIXED64:
case UINT64:
long ret = (Long) value;
return ret >= 0
? runtime.newFixnum(ret)
: RubyBignum.newBignum(runtime, UINT64_COMPLEMENTARY.add(new BigInteger(ret + "")));
case FLOAT:
return runtime.newFloat((Float) value);
case DOUBLE:
return runtime.newFloat((Double) value);
case BOOL:
return (Boolean) value ? runtime.getTrue() : runtime.getFalse();
case BYTES:
{
IRubyObject wrapped =
encodeBytes
? RubyString.newString(
runtime, ((ByteString) value).toStringUtf8(), ASCIIEncoding.INSTANCE)
: RubyString.newString(runtime, ((ByteString) value).toByteArray());
wrapped.setFrozen(true);
return wrapped;
}
case STRING:
{
IRubyObject wrapped = runtime.newString(value.toString());
wrapped.setFrozen(true);
return wrapped;
}
default:
return runtime.getNil();
} }
}
public static boolean isMapEntry(FieldDescriptor fieldDescriptor) {
return fieldDescriptor.getType() == FieldDescriptor.Type.MESSAGE && public static int num2uint(IRubyObject value) {
fieldDescriptor.isRepeated() && long longVal = RubyNumeric.num2long(value);
fieldDescriptor.getMessageType().getOptions().getMapEntry(); if (longVal > UINT_MAX)
throw value
.getRuntime()
.newRangeError("Integer " + longVal + " too big to convert to 'unsigned int'");
long num = longVal;
if (num > Integer.MAX_VALUE || num < Integer.MIN_VALUE)
// encode to UINT32
num = (-longVal ^ (-1l >>> 32)) + 1;
RubyNumeric.checkInt(value, num);
return (int) num;
}
public static long num2ulong(Ruby runtime, IRubyObject value) {
if (value instanceof RubyFloat) {
RubyBignum bignum = RubyBignum.newBignum(runtime, ((RubyFloat) value).getDoubleValue());
return RubyBignum.big2ulong(bignum);
} else if (value instanceof RubyBignum) {
return RubyBignum.big2ulong((RubyBignum) value);
} else {
return RubyNumeric.num2long(value);
} }
}
public static RaiseException createTypeError(ThreadContext context, String message) {
if (cTypeError == null) { /*
cTypeError = (RubyClass) context.runtime.getClassFromPath("Google::Protobuf::TypeError"); * Helper to make it easier to support symbols being passed instead of strings
} */
return RaiseException.from(context.runtime, cTypeError, message); public static IRubyObject symToString(IRubyObject sym) {
if (sym instanceof RubySymbol) {
return ((RubySymbol) sym).id2name();
} }
return sym;
public static RaiseException createExpectedTypeError(ThreadContext context, String type, String fieldType, String fieldName, IRubyObject value) { }
return createTypeError(context, String.format(EXPECTED_TYPE_ERROR_FORMAT, type, fieldType, fieldName, value.getMetaClass()));
public static void checkNameAvailability(ThreadContext context, String name) {
if (context.runtime.getObject().getConstantAt(name) != null)
throw context.runtime.newNameError(name + " is already defined", name);
}
public static boolean isMapEntry(FieldDescriptor fieldDescriptor) {
return fieldDescriptor.getType() == FieldDescriptor.Type.MESSAGE
&& fieldDescriptor.isRepeated()
&& fieldDescriptor.getMessageType().getOptions().getMapEntry();
}
public static RaiseException createTypeError(ThreadContext context, String message) {
if (cTypeError == null) {
cTypeError = (RubyClass) context.runtime.getClassFromPath("Google::Protobuf::TypeError");
} }
return RaiseException.from(context.runtime, cTypeError, message);
public static RaiseException createInvalidTypeError(ThreadContext context, String fieldType, String fieldName, IRubyObject value) { }
return createTypeError(context, String.format(INVALID_TYPE_ERROR_FORMAT, fieldType, fieldName, value.getMetaClass()));
public static RaiseException createExpectedTypeError(
ThreadContext context, String type, String fieldType, String fieldName, IRubyObject value) {
return createTypeError(
context,
String.format(
EXPECTED_TYPE_ERROR_FORMAT, type, fieldType, fieldName, value.getMetaClass()));
}
public static RaiseException createInvalidTypeError(
ThreadContext context, String fieldType, String fieldName, IRubyObject value) {
return createTypeError(
context,
String.format(INVALID_TYPE_ERROR_FORMAT, fieldType, fieldName, value.getMetaClass()));
}
protected static boolean isRubyNum(Object value) {
return value instanceof RubyFixnum || value instanceof RubyFloat || value instanceof RubyBignum;
}
protected static void validateTypeClass(
ThreadContext context, FieldDescriptor.Type type, IRubyObject value) {
Ruby runtime = context.runtime;
if (!(value instanceof RubyModule)) {
throw runtime.newArgumentError("TypeClass has incorrect type");
} }
RubyModule klass = (RubyModule) value;
protected static boolean isRubyNum(Object value) { IRubyObject descriptor = klass.getInstanceVariable(DESCRIPTOR_INSTANCE_VAR);
return value instanceof RubyFixnum || value instanceof RubyFloat || value instanceof RubyBignum; if (descriptor.isNil()) {
throw runtime.newArgumentError(
"Type class has no descriptor. Please pass a "
+ "class or enum as returned by the DescriptorPool.");
} }
if (type == FieldDescriptor.Type.MESSAGE) {
protected static void validateTypeClass(ThreadContext context, FieldDescriptor.Type type, IRubyObject value) { if (!(descriptor instanceof RubyDescriptor)) {
Ruby runtime = context.runtime; throw runtime.newArgumentError("Descriptor has an incorrect type");
if (!(value instanceof RubyModule)) { }
throw runtime.newArgumentError("TypeClass has incorrect type"); } else if (type == FieldDescriptor.Type.ENUM) {
} if (!(descriptor instanceof RubyEnumDescriptor)) {
RubyModule klass = (RubyModule) value; throw runtime.newArgumentError("Descriptor has an incorrect type");
IRubyObject descriptor = klass.getInstanceVariable(DESCRIPTOR_INSTANCE_VAR); }
if (descriptor.isNil()) {
throw runtime.newArgumentError("Type class has no descriptor. Please pass a " +
"class or enum as returned by the DescriptorPool.");
}
if (type == FieldDescriptor.Type.MESSAGE) {
if (! (descriptor instanceof RubyDescriptor)) {
throw runtime.newArgumentError("Descriptor has an incorrect type");
}
} else if (type == FieldDescriptor.Type.ENUM) {
if (! (descriptor instanceof RubyEnumDescriptor)) {
throw runtime.newArgumentError("Descriptor has an incorrect type");
}
}
} }
}
private static IRubyObject validateAndEncodeString(ThreadContext context, String fieldType, String fieldName, IRubyObject value, String encoding) { private static IRubyObject validateAndEncodeString(
if (!(value instanceof RubyString)) ThreadContext context,
throw createInvalidTypeError(context, fieldType, fieldName, value); String fieldType,
String fieldName,
IRubyObject value,
String encoding) {
if (!(value instanceof RubyString))
throw createInvalidTypeError(context, fieldType, fieldName, value);
value = ((RubyString) value).encode(context, context.runtime.evalScriptlet(encoding)); value = ((RubyString) value).encode(context, context.runtime.evalScriptlet(encoding));
value.setFrozen(true); value.setFrozen(true);
return value; return value;
} }
public static final String DESCRIPTOR_INSTANCE_VAR = "@descriptor"; public static final String DESCRIPTOR_INSTANCE_VAR = "@descriptor";
public static final String EQUAL_SIGN = "="; public static final String EQUAL_SIGN = "=";
private static final BigInteger UINT64_COMPLEMENTARY = new BigInteger("18446744073709551616"); //Math.pow(2, 64) private static final BigInteger UINT64_COMPLEMENTARY =
new BigInteger("18446744073709551616"); // Math.pow(2, 64)
private static final String EXPECTED_TYPE_ERROR_FORMAT = "Expected %s type for %s field '%s' (given %s)."; private static final String EXPECTED_TYPE_ERROR_FORMAT =
private static final String INVALID_TYPE_ERROR_FORMAT = "Invalid argument for %s field '%s' (given %s)."; "Expected %s type for %s field '%s' (given %s).";
private static final String INVALID_TYPE_ERROR_FORMAT =
"Invalid argument for %s field '%s' (given %s).";
private static final long UINT_MAX = 0xffffffffl; private static final long UINT_MAX = 0xffffffffl;
private static RubyClass cTypeError; private static RubyClass cTypeError;
} }

@ -33,30 +33,29 @@
package google; package google;
import com.google.protobuf.jruby.*; import com.google.protobuf.jruby.*;
import java.io.IOException;
import org.jruby.Ruby; import org.jruby.Ruby;
import org.jruby.runtime.load.BasicLibraryService; import org.jruby.runtime.load.BasicLibraryService;
import java.io.IOException;
public class ProtobufJavaService implements BasicLibraryService { public class ProtobufJavaService implements BasicLibraryService {
@Override @Override
public boolean basicLoad(Ruby ruby) throws IOException { public boolean basicLoad(Ruby ruby) throws IOException {
ruby.defineModule("Google"); ruby.defineModule("Google");
/* /*
* The order these happen in is important because we * The order these happen in is important because we
* save a static reference to some classes and they * save a static reference to some classes and they
* need to exist before we try to save a reference to them * need to exist before we try to save a reference to them
*/ */
RubyProtobuf.createProtobuf(ruby); RubyProtobuf.createProtobuf(ruby);
RubyFileDescriptor.createRubyFileDescriptor(ruby); RubyFileDescriptor.createRubyFileDescriptor(ruby);
RubyEnumDescriptor.createRubyEnumDescriptor(ruby); RubyEnumDescriptor.createRubyEnumDescriptor(ruby);
RubyRepeatedField.createRubyRepeatedField(ruby); RubyRepeatedField.createRubyRepeatedField(ruby);
RubyFieldDescriptor.createRubyFieldDescriptor(ruby); RubyFieldDescriptor.createRubyFieldDescriptor(ruby);
RubyMap.createRubyMap(ruby); RubyMap.createRubyMap(ruby);
RubyOneofDescriptor.createRubyOneofDescriptor(ruby); RubyOneofDescriptor.createRubyOneofDescriptor(ruby);
RubyDescriptor.createRubyDescriptor(ruby); RubyDescriptor.createRubyDescriptor(ruby);
RubyDescriptorPool.createRubyDescriptorPool(ruby); RubyDescriptorPool.createRubyDescriptorPool(ruby);
return true; return true;
} }
} }

Loading…
Cancel
Save