33 package com.google.protobuf.jruby;
37 import org.jruby.anno.JRubyClass;
38 import org.jruby.anno.JRubyMethod;
39 import org.jruby.runtime.Block;
40 import org.jruby.runtime.ObjectAllocator;
41 import org.jruby.runtime.ThreadContext;
42 import org.jruby.runtime.builtin.IRubyObject;
43 import java.util.Arrays;
45 @JRubyClass(
name =
"RepeatedClass", include =
"Enumerable")
48 RubyModule mProtobuf = runtime.getClassFromPath(
"Google::Protobuf");
49 RubyClass
cRepeatedField = mProtobuf.defineClassUnder(
"RepeatedField", runtime.getObject(),
50 new ObjectAllocator() {
52 public IRubyObject allocate(Ruby runtime, RubyClass klazz) {
61 super(runtime, klazz);
66 this.fieldType = fieldType;
67 this.storage = runtime.newArray();
68 this.typeClass = typeClass;
71 @JRubyMethod(required = 1, optional = 2)
72 public IRubyObject initialize(ThreadContext context, IRubyObject[]
args) {
73 Ruby runtime = context.runtime;
74 this.storage = runtime.newArray();
75 IRubyObject ary =
null;
76 if (!(
args[0] instanceof RubySymbol)) {
77 throw runtime.newArgumentError(
"Expected Symbol for type name");
83 throw runtime.newArgumentError(
"Expected at least 2 arguments for message/enum");
90 throw runtime.newArgumentError(
"Too many arguments: expected 1 or 2");
95 RubyArray arr = ary.convertToArray();
96 for (
int i = 0;
i < arr.size();
i++) {
97 this.storage.add(arr.eltInternal(
i));
110 @JRubyMethod(
name =
"[]=")
111 public IRubyObject indexSet(ThreadContext context, IRubyObject
index, IRubyObject
value) {
112 int arrIndex = normalizeArrayIndex(
index);
114 IRubyObject defaultValue = defaultValue(context);
115 for (
int i = this.storage.size();
i < arrIndex;
i++) {
116 this.storage.set(
i, defaultValue);
118 this.storage.set(arrIndex,
value);
119 return context.runtime.getNil();
128 @JRubyMethod(required=1, optional=1,
name = {
"at",
"[]"})
129 public IRubyObject
index(ThreadContext context, IRubyObject[]
args) {
130 if (
args.length == 1){
131 IRubyObject arg =
args[0];
134 int arrIndex = normalizeArrayIndex(arg);
135 if (arrIndex < 0 || arrIndex >= this.storage.size()) {
136 return context.runtime.getNil();
138 return this.storage.eltInternal(arrIndex);
139 }
else if (arg instanceof RubyRange) {
140 RubyRange
range = ((RubyRange) arg);
141 int beg = RubyNumeric.num2int(
range.first(context));
142 int to = RubyNumeric.num2int(
range.last(context));
143 int len = to - beg + 1;
144 return this.storage.subseq(beg,
len);
148 int beg = RubyNumeric.num2int(
args[0]);
149 int len = RubyNumeric.num2int(
args[1]);
151 beg += this.storage.size();
153 if (beg >= this.storage.size()) {
154 return context.runtime.getNil();
156 return this.storage.subseq(beg,
len);
165 @JRubyMethod(
name = {
"push",
"<<"})
166 public IRubyObject
push(ThreadContext context, IRubyObject
value) {
168 value == context.runtime.getNil())) {
171 this.storage.add(
value);
178 @JRubyMethod(visibility = org.jruby.runtime.Visibility.PRIVATE)
179 public IRubyObject pop_one(ThreadContext context) {
180 IRubyObject ret = this.storage.last();
181 this.storage.remove(ret);
192 public IRubyObject
replace(ThreadContext context, IRubyObject list) {
193 RubyArray arr = (RubyArray) list;
194 checkArrayElementType(context, arr);
206 public IRubyObject
clear(ThreadContext context) {
207 this.storage.clear();
217 @JRubyMethod(
name = {
"length",
"size"})
218 public IRubyObject
length(ThreadContext context) {
219 return context.runtime.newFixnum(this.storage.size());
230 @JRubyMethod(
name = {
"+"})
231 public IRubyObject
plus(ThreadContext context, IRubyObject list) {
233 if (list instanceof RubyArray) {
234 checkArrayElementType(context, (RubyArray) list);
235 dup.
storage.addAll((RubyArray) list);
238 if (! fieldType.equals(repeatedField.
fieldType) || (typeClass !=
null && !
239 typeClass.equals(repeatedField.
typeClass)))
240 throw context.runtime.newArgumentError(
"Attempt to append RepeatedField with different element type.");
253 public IRubyObject
concat(ThreadContext context, IRubyObject list) {
254 if (list instanceof RubyArray) {
255 checkArrayElementType(context, (RubyArray) list);
256 this.storage.addAll((RubyArray) list);
259 if (! fieldType.equals(repeatedField.
fieldType) || (typeClass !=
null && !
260 typeClass.equals(repeatedField.
typeClass)))
261 throw context.runtime.newArgumentError(
"Attempt to append RepeatedField with different element type.");
262 this.storage.addAll((RubyArray) repeatedField.
toArray(context));
274 public IRubyObject
hash(ThreadContext context) {
275 int hashCode = this.storage.hashCode();
276 return context.runtime.newFixnum(hashCode);
288 @JRubyMethod(
name =
"==")
289 public IRubyObject eq(ThreadContext context, IRubyObject other) {
290 return this.toArray(context).op_equal(context, other);
302 public IRubyObject
each(ThreadContext context, Block block) {
303 this.storage.each(context, block);
308 @JRubyMethod(
name = {
"to_ary",
"to_a"})
309 public IRubyObject
toArray(ThreadContext context) {
321 public IRubyObject
dup(ThreadContext context) {
323 for (
int i = 0;
i < this.storage.size();
i++) {
324 dup.
push(context, this.storage.eltInternal(
i));
330 protected IRubyObject
get(
int index) {
331 return this.storage.eltInternal(
index);
336 for (
int i = 0;
i <
size();
i++) {
337 IRubyObject
value = storage.eltInternal(
i);
348 return this.storage.size();
356 value = sentinel.getDefaultInt32();
359 value = sentinel.getDefaultInt64();
362 value = sentinel.getDefaultUnit32();
365 value = sentinel.getDefaultUint64();
368 value = sentinel.getDefaultFloat();
371 value = sentinel.getDefaultDouble();
374 value = sentinel.getDefaultBool();
377 value = sentinel.getDefaultBytes();
380 value = sentinel.getDefaultString();
383 IRubyObject defaultEnumLoc = context.runtime.newFixnum(0);
386 return context.runtime.getNil();
392 for (
int i = 0;
i < arr.getLength();
i++) {
393 Utils.
checkType(context, fieldType, arr.eltInternal(
i), (RubyModule) typeClass);
398 int arrIndex = RubyNumeric.num2int(
index);
399 int arrSize = this.storage.size();
400 if (arrIndex < 0 && arrSize > 0) {
401 arrIndex = arrSize + arrIndex;