Index: third_party/protobuf/ruby/src/main/java/com/google/protobuf/jruby/RubyMap.java |
diff --git a/third_party/protobuf/ruby/src/main/java/com/google/protobuf/jruby/RubyMap.java b/third_party/protobuf/ruby/src/main/java/com/google/protobuf/jruby/RubyMap.java |
deleted file mode 100644 |
index 2d4c03b567ea70b6a9f3681bf4df24ede01f6f51..0000000000000000000000000000000000000000 |
--- a/third_party/protobuf/ruby/src/main/java/com/google/protobuf/jruby/RubyMap.java |
+++ /dev/null |
@@ -1,434 +0,0 @@ |
-/* |
- * Protocol Buffers - Google's data interchange format |
- * Copyright 2014 Google Inc. All rights reserved. |
- * https://developers.google.com/protocol-buffers/ |
- * |
- * Redistribution and use in source and binary forms, with or without |
- * modification, are permitted provided that the following conditions are |
- * met: |
- * |
- * * Redistributions of source code must retain the above copyright |
- * notice, this list of conditions and the following disclaimer. |
- * * Redistributions in binary form must reproduce the above |
- * copyright notice, this list of conditions and the following disclaimer |
- * in the documentation and/or other materials provided with the |
- * distribution. |
- * * Neither the name of Google Inc. nor the names of its |
- * contributors may be used to endorse or promote products derived from |
- * this software without specific prior written permission. |
- * |
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
- */ |
- |
-package com.google.protobuf.jruby; |
- |
-import com.google.protobuf.Descriptors; |
-import com.google.protobuf.DynamicMessage; |
-import com.google.protobuf.MapEntry; |
-import org.jruby.*; |
-import org.jruby.anno.JRubyClass; |
-import org.jruby.anno.JRubyMethod; |
-import org.jruby.internal.runtime.methods.DynamicMethod; |
-import org.jruby.runtime.Block; |
-import org.jruby.runtime.ObjectAllocator; |
-import org.jruby.runtime.ThreadContext; |
-import org.jruby.runtime.builtin.IRubyObject; |
-import org.jruby.util.ByteList; |
- |
-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") |
-public class RubyMap extends RubyObject { |
- public static void createRubyMap(Ruby runtime) { |
- RubyModule protobuf = runtime.getClassFromPath("Google::Protobuf"); |
- RubyClass cMap = protobuf.defineClassUnder("Map", runtime.getObject(), new ObjectAllocator() { |
- @Override |
- public IRubyObject allocate(Ruby ruby, RubyClass rubyClass) { |
- return new RubyMap(ruby, rubyClass); |
- } |
- }); |
- cMap.includeModule(runtime.getEnumerable()); |
- cMap.defineAnnotatedMethods(RubyMap.class); |
- } |
- |
- public RubyMap(Ruby ruby, RubyClass 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, :bool, |
- * :string, :bytes. |
- * |
- * The supported value types are: :int32, :int64, :uint32, :uint64, :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 INT32: |
- case INT64: |
- case UINT32: |
- case UINT64: |
- case BOOL: |
- case STRING: |
- case BYTES: |
- // 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(); |
- } |
- |
- // Table value type is always UINT64: this ensures enough space to store the |
- // native_slot value. |
- if (args.length > initValueArg) { |
- mergeIntoSelf(context, args[initValueArg]); |
- } |
- 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) { |
- Utils.checkType(context, keyType, key, (RubyModule) valueTypeClass); |
- Utils.checkType(context, valueType, value, (RubyModule) valueTypeClass); |
- IRubyObject symbol; |
- if (valueType == Descriptors.FieldDescriptor.Type.ENUM && |
- Utils.isRubyNum(value) && |
- ! (symbol = RubyEnum.lookup(context, valueTypeClass, value)).isNil()) { |
- value = symbol; |
- } |
- this.table.put(key, value); |
- return value; |
- } |
- |
- /* |
- * call-seq: |
- * Map.[](key) => value |
- * |
- * 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 = "[]") |
- public IRubyObject index(ThreadContext context, IRubyObject key) { |
- if (table.containsKey(key)) |
- return this.table.get(key); |
- return context.runtime.getNil(); |
- } |
- |
- /* |
- * 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 toHash(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.inspect => string |
- * |
- * Returns a string representing this map's elements. It will be formatted as |
- * "{key => value, key => value, ...}", with each key and value string |
- * representation computed by its own #inspect method. |
- */ |
- @JRubyMethod |
- public IRubyObject inspect() { |
- return toHash(getRuntime().getCurrentContext()).inspect(); |
- } |
- |
- /* |
- * 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.newString(new ByteList(digest.digest())); |
- } catch (NoSuchAlgorithmException ignore) { |
- return context.runtime.newFixnum(System.identityHashCode(table)); |
- } |
- } |
- |
- /* |
- * call-seq: |
- * Map.keys => [list_of_keys] |
- * |
- * Returns the list of keys contained in the map, in unspecified order. |
- */ |
- @JRubyMethod |
- 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) { |
- table.clear(); |
- return context.runtime.getNil(); |
- } |
- |
- /* |
- * 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.runtime.getNil(); |
- } |
- |
- /* |
- * 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) { |
- 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 |
- 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", "to_hash"}) |
- public RubyHash toHash(ThreadContext context) { |
- return RubyHash.newHash(context.runtime, table, context.runtime.getNil()); |
- } |
- |
- // Used by Google::Protobuf.deep_copy but not exposed directly. |
- protected IRubyObject deepCopy(ThreadContext context) { |
- RubyMap newMap = newThisType(context); |
- switch (valueType) { |
- case MESSAGE: |
- for (IRubyObject key : table.keySet()) { |
- RubyMessage message = (RubyMessage) table.get(key); |
- 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; |
- } |
- |
- protected List<DynamicMessage> build(ThreadContext context, RubyDescriptor descriptor) { |
- List<DynamicMessage> list = new ArrayList<DynamicMessage>(); |
- RubyClass rubyClass = (RubyClass) descriptor.msgclass(context); |
- Descriptors.FieldDescriptor keyField = descriptor.lookup("key").getFieldDef(); |
- Descriptors.FieldDescriptor valueField = descriptor.lookup("value").getFieldDef(); |
- 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)); |
- } |
- return list; |
- } |
- |
- protected RubyMap mergeIntoSelf(final ThreadContext context, IRubyObject hashmap) { |
- if (hashmap instanceof RubyHash) { |
- ((RubyHash) hashmap).visitAll(new RubyHash.Visitor() { |
- @Override |
- public void visit(IRubyObject key, IRubyObject val) { |
- indexSet(context, key, val); |
- } |
- }); |
- } else if (hashmap instanceof RubyMap) { |
- RubyMap other = (RubyMap) hashmap; |
- if (!typeCompatible(other)) { |
- throw context.runtime.newTypeError("Attempt to merge Map with mismatching types"); |
- } |
- } else { |
- throw context.runtime.newTypeError("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; |
- } |
- |
- private boolean needTypeclass(Descriptors.FieldDescriptor.Type type) { |
- switch(type) { |
- case MESSAGE: |
- case ENUM: |
- return true; |
- default: |
- return false; |
- } |
- } |
- |
- private Descriptors.FieldDescriptor.Type keyType; |
- private Descriptors.FieldDescriptor.Type valueType; |
- private IRubyObject valueTypeClass; |
- private Map<IRubyObject, IRubyObject> table; |
-} |