aboutsummaryrefslogtreecommitdiffhomepage
path: root/ruby/src/main/java/com/google/protobuf/jruby/RubyRepeatedField.java
diff options
context:
space:
mode:
Diffstat (limited to 'ruby/src/main/java/com/google/protobuf/jruby/RubyRepeatedField.java')
-rw-r--r--ruby/src/main/java/com/google/protobuf/jruby/RubyRepeatedField.java136
1 files changed, 71 insertions, 65 deletions
diff --git a/ruby/src/main/java/com/google/protobuf/jruby/RubyRepeatedField.java b/ruby/src/main/java/com/google/protobuf/jruby/RubyRepeatedField.java
index 84bf8956..946f9e74 100644
--- a/ruby/src/main/java/com/google/protobuf/jruby/RubyRepeatedField.java
+++ b/ruby/src/main/java/com/google/protobuf/jruby/RubyRepeatedField.java
@@ -40,6 +40,7 @@ import org.jruby.runtime.Block;
import org.jruby.runtime.ObjectAllocator;
import org.jruby.runtime.ThreadContext;
import org.jruby.runtime.builtin.IRubyObject;
+import java.util.Arrays;
@JRubyClass(name = "RepeatedClass", include = "Enumerable")
public class RubyRepeatedField extends RubyObject {
@@ -110,6 +111,10 @@ public class RubyRepeatedField extends RubyObject {
public IRubyObject indexSet(ThreadContext context, IRubyObject index, IRubyObject value) {
int arrIndex = normalizeArrayIndex(index);
Utils.checkType(context, fieldType, 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();
}
@@ -120,27 +125,35 @@ public class RubyRepeatedField extends RubyObject {
*
* Accesses the element at the given index. Returns nil on out-of-bounds
*/
- @JRubyMethod(name = "[]")
- public IRubyObject index(ThreadContext context, IRubyObject index) {
- int arrIndex = normalizeArrayIndex(index);
- if (arrIndex < 0 || arrIndex >= this.storage.size()) {
- return context.runtime.getNil();
+ @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 to = RubyNumeric.num2int(range.last(context));
+ int len = to - beg + 1;
+ return this.storage.subseq(beg, len);
+ }
}
- return this.storage.eltInternal(arrIndex);
- }
-
- /*
- * call-seq:
- * RepeatedField.insert(*args)
- *
- * Pushes each arg in turn onto the end of the repeated field.
- */
- @JRubyMethod(rest = true)
- public IRubyObject insert(ThreadContext context, IRubyObject[] args) {
- for (int i = 0; i < args.length; i++) {
- push(context, args[i]);
+ /* assume 2 arguments */
+ int beg = RubyNumeric.num2int(args[0]);
+ int len = RubyNumeric.num2int(args[1]);
+ if (beg < 0) {
+ beg += this.storage.size();
}
- return context.runtime.getNil();
+ if (beg >= this.storage.size()) {
+ return context.runtime.getNil();
+ }
+ return this.storage.subseq(beg, len);
}
/*
@@ -151,20 +164,19 @@ public class RubyRepeatedField extends RubyObject {
*/
@JRubyMethod(name = {"push", "<<"})
public IRubyObject push(ThreadContext context, IRubyObject value) {
- Utils.checkType(context, fieldType, value, (RubyModule) typeClass);
+ if (!(fieldType == Descriptors.FieldDescriptor.Type.MESSAGE &&
+ value == context.runtime.getNil())) {
+ Utils.checkType(context, fieldType, value, (RubyModule) typeClass);
+ }
this.storage.add(value);
- return this;
+ return this.storage;
}
/*
- * call-seq:
- * RepeatedField.pop => value
- *
- * Removes the last element and returns it. Throws an exception if the repeated
- * field is empty.
+ * private Ruby method used by RepeatedField.pop
*/
- @JRubyMethod
- public IRubyObject pop(ThreadContext context) {
+ @JRubyMethod(visibility = org.jruby.runtime.Visibility.PRIVATE)
+ public IRubyObject pop_one(ThreadContext context) {
IRubyObject ret = this.storage.last();
this.storage.remove(ret);
return ret;
@@ -181,7 +193,7 @@ public class RubyRepeatedField extends RubyObject {
RubyArray arr = (RubyArray) list;
checkArrayElementType(context, arr);
this.storage = arr;
- return context.runtime.getNil();
+ return this.storage;
}
/*
@@ -193,7 +205,7 @@ public class RubyRepeatedField extends RubyObject {
@JRubyMethod
public IRubyObject clear(ThreadContext context) {
this.storage.clear();
- return context.runtime.getNil();
+ return this.storage;
}
/*
@@ -202,7 +214,7 @@ public class RubyRepeatedField extends RubyObject {
*
* Returns the length of this repeated field.
*/
- @JRubyMethod(name = {"count", "length"})
+ @JRubyMethod(name = {"length", "size"})
public IRubyObject length(ThreadContext context) {
return context.runtime.newFixnum(this.storage.size());
}
@@ -215,7 +227,7 @@ public class RubyRepeatedField extends RubyObject {
* repeated field's elements and other's elements. The other (second) list may
* be either another repeated field or a Ruby array.
*/
- @JRubyMethod(name = "+")
+ @JRubyMethod(name = {"+"})
public IRubyObject plus(ThreadContext context, IRubyObject list) {
RubyRepeatedField dup = (RubyRepeatedField) dup(context);
if (list instanceof RubyArray) {
@@ -233,13 +245,34 @@ public class RubyRepeatedField extends RubyObject {
/*
* 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.storage;
+ }
+
+ /*
+ * 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 = System.identityHashCode(this.storage);
+ int hashCode = this.storage.hashCode();
return context.runtime.newFixnum(hashCode);
}
@@ -268,17 +301,12 @@ public class RubyRepeatedField extends RubyObject {
@JRubyMethod
public IRubyObject each(ThreadContext context, Block block) {
this.storage.each(context, block);
- return context.runtime.getNil();
+ return this.storage;
}
+
@JRubyMethod(name = {"to_ary", "to_a"})
public IRubyObject toArray(ThreadContext context) {
- for (int i = 0; i < this.storage.size(); i++) {
- IRubyObject defaultValue = defaultValue(context);
- if (storage.eltInternal(i).isNil()) {
- storage.set(i, defaultValue);
- }
- }
return this.storage;
}
@@ -298,31 +326,6 @@ public class RubyRepeatedField extends RubyObject {
return dup;
}
- /*
- * call-seq:
- * RepeatedField.inspect => string
- *
- * Returns a string representing this repeated field's elements. It will be
- * formated as "[<element>, <element>, ...]", with each element's string
- * representation computed by its own #inspect method.
- */
- @JRubyMethod
- public IRubyObject inspect() {
- StringBuilder str = new StringBuilder("[");
- for (int i = 0; i < this.storage.size(); i++) {
- str.append(storage.eltInternal(i).inspect());
- str.append(", ");
- }
-
- if (str.length() > 1) {
- str.replace(str.length() - 2, str.length(), "]");
- } else {
- str.append("]");
- }
-
- return getRuntime().newString(str.toString());
- }
-
// Java API
protected IRubyObject get(int index) {
return this.storage.eltInternal(index);
@@ -376,6 +379,9 @@ public class RubyRepeatedField extends RubyObject {
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();
}