diff options
Diffstat (limited to 'ruby/src')
-rw-r--r-- | ruby/src/main/java/com/google/protobuf/jruby/RubyMessage.java | 29 | ||||
-rw-r--r-- | ruby/src/main/java/com/google/protobuf/jruby/RubyRepeatedField.java | 24 |
2 files changed, 35 insertions, 18 deletions
diff --git a/ruby/src/main/java/com/google/protobuf/jruby/RubyMessage.java b/ruby/src/main/java/com/google/protobuf/jruby/RubyMessage.java index 04bc0b76..c7fd7aa7 100644 --- a/ruby/src/main/java/com/google/protobuf/jruby/RubyMessage.java +++ b/ruby/src/main/java/com/google/protobuf/jruby/RubyMessage.java @@ -246,16 +246,15 @@ public class RubyMessage extends RubyObject { public IRubyObject dup(ThreadContext context) { RubyMessage dup = (RubyMessage) metaClass.newInstance(context, Block.NULL_BLOCK); IRubyObject value; - for (Descriptors.FieldDescriptor fieldDescriptor : builder.getAllFields().keySet()) { + for (Descriptors.FieldDescriptor fieldDescriptor : this.descriptor.getFields()) { if (fieldDescriptor.isRepeated()) { - dup.repeatedFields.put(fieldDescriptor, getRepeatedField(context, fieldDescriptor)); - } else if (builder.hasField(fieldDescriptor)) { - dup.fields.put(fieldDescriptor, wrapField(context, fieldDescriptor, builder.getField(fieldDescriptor))); + dup.addRepeatedField(fieldDescriptor, this.getRepeatedField(context, fieldDescriptor)); + } else if (fields.containsKey(fieldDescriptor)) { + dup.fields.put(fieldDescriptor, fields.get(fieldDescriptor)); + } else if (this.builder.hasField(fieldDescriptor)) { + dup.fields.put(fieldDescriptor, wrapField(context, fieldDescriptor, this.builder.getField(fieldDescriptor))); } } - for (Descriptors.FieldDescriptor fieldDescriptor : fields.keySet()) { - dup.fields.put(fieldDescriptor, fields.get(fieldDescriptor)); - } for (Descriptors.FieldDescriptor fieldDescriptor : maps.keySet()) { dup.maps.put(fieldDescriptor, maps.get(fieldDescriptor)); } @@ -411,6 +410,7 @@ public class RubyMessage extends RubyObject { for (int i = 0; i < count; i++) { ret.push(context, wrapField(context, fieldDescriptor, this.builder.getRepeatedField(fieldDescriptor, i))); } + addRepeatedField(fieldDescriptor, ret); return ret; } @@ -659,14 +659,14 @@ public class RubyMessage extends RubyObject { } else { Descriptors.FieldDescriptor.Type fieldType = fieldDescriptor.getType(); IRubyObject typeClass = context.runtime.getObject(); + boolean addValue = true; if (fieldType == Descriptors.FieldDescriptor.Type.MESSAGE) { typeClass = ((RubyDescriptor) getDescriptorForField(context, fieldDescriptor)).msgclass(context); + if (value.isNil()){ + addValue = false; + } } else if (fieldType == Descriptors.FieldDescriptor.Type.ENUM) { typeClass = ((RubyEnumDescriptor) getDescriptorForField(context, fieldDescriptor)).enummodule(context); - } - Utils.checkType(context, fieldType, value, (RubyModule) typeClass); - // Convert integer enum to symbol - if (fieldType == Descriptors.FieldDescriptor.Type.ENUM) { Descriptors.EnumDescriptor enumDescriptor = fieldDescriptor.getEnumType(); if (Utils.isRubyNum(value)) { Descriptors.EnumValueDescriptor val = @@ -674,7 +674,12 @@ public class RubyMessage extends RubyObject { if (val.getIndex() != -1) value = context.runtime.newSymbol(val.getName()); } } - this.fields.put(fieldDescriptor, value); + if (addValue) { + Utils.checkType(context, fieldType, value, (RubyModule) typeClass); + this.fields.put(fieldDescriptor, value); + } else { + this.fields.remove(fieldDescriptor); + } } } return context.runtime.getNil(); 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 9788317a..84bf8956 100644 --- a/ruby/src/main/java/com/google/protobuf/jruby/RubyRepeatedField.java +++ b/ruby/src/main/java/com/google/protobuf/jruby/RubyRepeatedField.java @@ -108,8 +108,9 @@ public class RubyRepeatedField extends RubyObject { */ @JRubyMethod(name = "[]=") public IRubyObject indexSet(ThreadContext context, IRubyObject index, IRubyObject value) { + int arrIndex = normalizeArrayIndex(index); Utils.checkType(context, fieldType, value, (RubyModule) typeClass); - this.storage.set(RubyNumeric.num2int(index), value); + this.storage.set(arrIndex, value); return context.runtime.getNil(); } @@ -117,12 +118,15 @@ public class RubyRepeatedField extends RubyObject { * call-seq: * RepeatedField.[](index) => value * - * Accesses the element at the given index. Throws an exception on out-of-bounds - * errors. + * Accesses the element at the given index. Returns nil on out-of-bounds */ @JRubyMethod(name = "[]") public IRubyObject index(ThreadContext context, IRubyObject index) { - return this.storage.eltInternal(RubyNumeric.num2int(index)); + int arrIndex = normalizeArrayIndex(index); + if (arrIndex < 0 || arrIndex >= this.storage.size()) { + return context.runtime.getNil(); + } + return this.storage.eltInternal(arrIndex); } /* @@ -134,8 +138,7 @@ public class RubyRepeatedField extends RubyObject { @JRubyMethod(rest = true) public IRubyObject insert(ThreadContext context, IRubyObject[] args) { for (int i = 0; i < args.length; i++) { - Utils.checkType(context, fieldType, args[i], (RubyModule) typeClass); - this.storage.add(args[i]); + push(context, args[i]); } return context.runtime.getNil(); } @@ -385,6 +388,15 @@ public class RubyRepeatedField extends RubyObject { } } + private int normalizeArrayIndex(IRubyObject index) { + int arrIndex = RubyNumeric.num2int(index); + int arrSize = this.storage.size(); + if (arrIndex < 0 && arrSize > 0) { + arrIndex = arrSize + arrIndex; + } + return arrIndex; + } + private RubyArray storage; private Descriptors.FieldDescriptor.Type fieldType; private IRubyObject typeClass; |