1b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* 2b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Protocol Buffers - Google's data interchange format 3b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Copyright 2014 Google Inc. All rights reserved. 4b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * https://developers.google.com/protocol-buffers/ 5b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * 6b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Redistribution and use in source and binary forms, with or without 7b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * modification, are permitted provided that the following conditions are 8b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * met: 9b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * 10b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * * Redistributions of source code must retain the above copyright 11b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * notice, this list of conditions and the following disclaimer. 12b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * * Redistributions in binary form must reproduce the above 13b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * copyright notice, this list of conditions and the following disclaimer 14b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * in the documentation and/or other materials provided with the 15b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * distribution. 16b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * * Neither the name of Google Inc. nor the names of its 17b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * contributors may be used to endorse or promote products derived from 18b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * this software without specific prior written permission. 19b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * 20b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 23b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 24b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 25b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 26b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer */ 32b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 33b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerpackage com.google.protobuf.jruby; 34b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 35b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerimport com.google.protobuf.*; 36b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerimport org.jruby.*; 37b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerimport org.jruby.anno.JRubyMethod; 38b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerimport org.jruby.runtime.Block; 39b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerimport org.jruby.runtime.Helpers; 40b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerimport org.jruby.runtime.ThreadContext; 41b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerimport org.jruby.runtime.builtin.IRubyObject; 42b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerimport org.jruby.util.ByteList; 43b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 44b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerimport java.util.HashMap; 45b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerimport java.util.Map; 46b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 47b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerpublic class RubyMessage extends RubyObject { 48b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public RubyMessage(Ruby ruby, RubyClass klazz, Descriptors.Descriptor descriptor) { 49b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer super(ruby, klazz); 50b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer this.descriptor = descriptor; 51b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 52b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 53b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /* 54b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * call-seq: 55b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Message.new(kwargs) => new_message 56b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * 57b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Creates a new instance of the given message class. Keyword arguments may be 58b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * provided with keywords corresponding to field names. 59b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * 60b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Note that no literal Message class exists. Only concrete classes per message 61b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * type exist, as provided by the #msgclass method on Descriptors after they 62b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * have been added to a pool. The method definitions described here on the 63b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Message class are provided on each concrete message class. 64b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer */ 65b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @JRubyMethod(optional = 1) 66b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public IRubyObject initialize(final ThreadContext context, IRubyObject[] args) { 67b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer final Ruby runtime = context.runtime; 68b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer this.cRepeatedField = (RubyClass) runtime.getClassFromPath("Google::Protobuf::RepeatedField"); 69b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer this.cMap = (RubyClass) runtime.getClassFromPath("Google::Protobuf::Map"); 70b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer this.builder = DynamicMessage.newBuilder(this.descriptor); 71b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer this.repeatedFields = new HashMap<Descriptors.FieldDescriptor, RubyRepeatedField>(); 72b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer this.maps = new HashMap<Descriptors.FieldDescriptor, RubyMap>(); 73b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer this.fields = new HashMap<Descriptors.FieldDescriptor, IRubyObject>(); 74b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer this.oneofCases = new HashMap<Descriptors.OneofDescriptor, Descriptors.FieldDescriptor>(); 75b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (args.length == 1) { 76b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (!(args[0] instanceof RubyHash)) { 77b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer throw runtime.newArgumentError("expected Hash arguments."); 78b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 79b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer RubyHash hash = args[0].convertToHash(); 80b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer hash.visitAll(new RubyHash.Visitor() { 81b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @Override 82b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public void visit(IRubyObject key, IRubyObject value) { 83b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (!(key instanceof RubySymbol)) 84b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer throw runtime.newTypeError("Expected symbols as hash keys in initialization map."); 85b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer final Descriptors.FieldDescriptor fieldDescriptor = findField(context, key); 86b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 87b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (Utils.isMapEntry(fieldDescriptor)) { 88b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (!(value instanceof RubyHash)) 89b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer throw runtime.newArgumentError("Expected Hash object as initializer value for map field '" + key.asJavaString() + "'."); 90b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 91b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer final RubyMap map = newMapForField(context, fieldDescriptor); 92b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer map.mergeIntoSelf(context, value); 93b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer maps.put(fieldDescriptor, map); 94b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } else if (fieldDescriptor.isRepeated()) { 95b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (!(value instanceof RubyArray)) 96b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer throw runtime.newArgumentError("Expected array as initializer value for repeated field '" + key.asJavaString() + "'."); 97b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer RubyRepeatedField repeatedField = rubyToRepeatedField(context, fieldDescriptor, value); 98b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer addRepeatedField(fieldDescriptor, repeatedField); 99b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } else { 100b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer Descriptors.OneofDescriptor oneof = fieldDescriptor.getContainingOneof(); 101b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (oneof != null) { 102b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer oneofCases.put(oneof, fieldDescriptor); 103b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 104b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer fields.put(fieldDescriptor, value); 105b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 106b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 107b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 108b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer }); 109b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 110b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return this; 111b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 112b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 113b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /* 114b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * call-seq: 115b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Message.[]=(index, value) 116b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * 117b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Sets a field's value by field name. The provided field name should be a 118b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * string. 119b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer */ 120b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @JRubyMethod(name = "[]=") 121b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public IRubyObject indexSet(ThreadContext context, IRubyObject fieldName, IRubyObject value) { 122b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer Descriptors.FieldDescriptor fieldDescriptor = findField(context, fieldName); 123b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return setField(context, fieldDescriptor, value); 124b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 125b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 126b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /* 127b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * call-seq: 128b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Message.[](index) => value 129b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * 130b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Accesses a field's value by field name. The provided field name should be a 131b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * string. 132b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer */ 133b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @JRubyMethod(name = "[]") 134b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public IRubyObject index(ThreadContext context, IRubyObject fieldName) { 135b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer Descriptors.FieldDescriptor fieldDescriptor = findField(context, fieldName); 136b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return getField(context, fieldDescriptor); 137b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 138b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 139b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /* 140b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * call-seq: 141b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Message.inspect => string 142b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * 143b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Returns a human-readable string representing this message. It will be 144b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * formatted as "<MessageType: field1: value1, field2: value2, ...>". Each 145b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * field's value is represented according to its own #inspect method. 146b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer */ 147b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @JRubyMethod 148b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public IRubyObject inspect() { 149b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer String cname = metaClass.getName(); 150b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer StringBuilder sb = new StringBuilder("<"); 151b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer sb.append(cname); 152b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer sb.append(": "); 153b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer sb.append(this.layoutInspect()); 154b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer sb.append(">"); 155b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 156b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return getRuntime().newString(sb.toString()); 157b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 158b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 159b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /* 160b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * call-seq: 161b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Message.hash => hash_value 162b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * 163b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Returns a hash value that represents this message's field values. 164b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer */ 165b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @JRubyMethod 166b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public IRubyObject hash(ThreadContext context) { 167b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer int hashCode = System.identityHashCode(this); 168b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return context.runtime.newFixnum(hashCode); 169b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 170b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 171b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /* 172b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * call-seq: 173b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Message.==(other) => boolean 174b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * 175b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Performs a deep comparison of this message with another. Messages are equal 176b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * if they have the same type and if each field is equal according to the :== 177b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * method's semantics (a more efficient comparison may actually be done if the 178b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * field is of a primitive type). 179b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer */ 180b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @JRubyMethod(name = "==") 181b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public IRubyObject eq(ThreadContext context, IRubyObject other) { 182b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer Ruby runtime = context.runtime; 183b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (!(other instanceof RubyMessage)) 184b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return runtime.getFalse(); 185b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer RubyMessage message = (RubyMessage) other; 186b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (descriptor != message.descriptor) { 187b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return runtime.getFalse(); 188b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 189b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 190b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer for (Descriptors.FieldDescriptor fdef : descriptor.getFields()) { 191b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer IRubyObject thisVal = getField(context, fdef); 192b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer IRubyObject thatVal = message.getField(context, fdef); 193b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer IRubyObject ret = thisVal.callMethod(context, "==", thatVal); 194b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (!ret.isTrue()) { 195b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return runtime.getFalse(); 196b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 197b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 198b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return runtime.getTrue(); 199b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 200b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 201b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /* 202b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * call-seq: 203b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Message.method_missing(*args) 204b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * 205b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Provides accessors and setters for message fields according to their field 206b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * names. For any field whose name does not conflict with a built-in method, an 207b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * accessor is provided with the same name as the field, and a setter is 208b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * provided with the name of the field plus the '=' suffix. Thus, given a 209b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * message instance 'msg' with field 'foo', the following code is valid: 210b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * 211b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * msg.foo = 42 212b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * puts msg.foo 213b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer */ 214b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @JRubyMethod(name = "method_missing", rest = true) 215b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public IRubyObject methodMissing(ThreadContext context, IRubyObject[] args) { 216b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (args.length == 1) { 217b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer RubyDescriptor rubyDescriptor = (RubyDescriptor) getDescriptor(context, metaClass); 218b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer IRubyObject oneofDescriptor = rubyDescriptor.lookupOneof(context, args[0]); 219b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (oneofDescriptor.isNil()) { 220b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (!hasField(args[0])) { 221b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return Helpers.invokeSuper(context, this, metaClass, "method_missing", args, Block.NULL_BLOCK); 222b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 223b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return index(context, args[0]); 224b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 225b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer RubyOneofDescriptor rubyOneofDescriptor = (RubyOneofDescriptor) oneofDescriptor; 226b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer Descriptors.FieldDescriptor fieldDescriptor = 227b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer oneofCases.get(rubyOneofDescriptor.getOneofDescriptor()); 228b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (fieldDescriptor == null) 229b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return context.runtime.getNil(); 230b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 231b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return context.runtime.newSymbol(fieldDescriptor.getName()); 232b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } else { 233b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // fieldName is RubySymbol 234b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer RubyString field = args[0].asString(); 235b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer RubyString equalSign = context.runtime.newString(Utils.EQUAL_SIGN); 236b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (field.end_with_p(context, equalSign).isTrue()) { 237b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer field.chomp_bang(context, equalSign); 238b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 239b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 240b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (!hasField(field)) { 241b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return Helpers.invokeSuper(context, this, metaClass, "method_missing", args, Block.NULL_BLOCK); 242b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 243b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return indexSet(context, field, args[1]); 244b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 245b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 246b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 247b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** 248b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * call-seq: 249b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Message.dup => new_message 250b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Performs a shallow copy of this message and returns the new copy. 251b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer */ 252b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @JRubyMethod 253b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public IRubyObject dup(ThreadContext context) { 254b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer RubyMessage dup = (RubyMessage) metaClass.newInstance(context, Block.NULL_BLOCK); 255b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer IRubyObject value; 256b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer for (Descriptors.FieldDescriptor fieldDescriptor : this.descriptor.getFields()) { 257b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (fieldDescriptor.isRepeated()) { 258b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer dup.addRepeatedField(fieldDescriptor, this.getRepeatedField(context, fieldDescriptor)); 259b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } else if (fields.containsKey(fieldDescriptor)) { 260b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer dup.fields.put(fieldDescriptor, fields.get(fieldDescriptor)); 261b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } else if (this.builder.hasField(fieldDescriptor)) { 262b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer dup.fields.put(fieldDescriptor, wrapField(context, fieldDescriptor, this.builder.getField(fieldDescriptor))); 263b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 264b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 265b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer for (Descriptors.FieldDescriptor fieldDescriptor : maps.keySet()) { 266b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer dup.maps.put(fieldDescriptor, maps.get(fieldDescriptor)); 267b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 268b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return dup; 269b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 270b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 271b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /* 272b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * call-seq: 273b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Message.descriptor => descriptor 274b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * 275b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Class method that returns the Descriptor instance corresponding to this 276b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * message class's type. 277b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer */ 278b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @JRubyMethod(name = "descriptor", meta = true) 279b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public static IRubyObject getDescriptor(ThreadContext context, IRubyObject recv) { 280b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return ((RubyClass) recv).getInstanceVariable(Utils.DESCRIPTOR_INSTANCE_VAR); 281b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 282b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 283b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /* 284b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * call-seq: 285b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * MessageClass.encode(msg) => bytes 286b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * 287b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Encodes the given message object to its serialized form in protocol buffers 288b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * wire format. 289b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer */ 290b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @JRubyMethod(meta = true) 291b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public static IRubyObject encode(ThreadContext context, IRubyObject recv, IRubyObject value) { 292b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer RubyMessage message = (RubyMessage) value; 293b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return context.runtime.newString(new ByteList(message.build(context).toByteArray())); 294b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 295b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 296b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /* 297b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * call-seq: 298b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * MessageClass.decode(data) => message 299b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * 300b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Decodes the given data (as a string containing bytes in protocol buffers wire 301b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * format) under the interpretration given by this message class's definition 302b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * and returns a message object with the corresponding field values. 303b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer */ 304b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @JRubyMethod(meta = true) 305b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public static IRubyObject decode(ThreadContext context, IRubyObject recv, IRubyObject data) { 306b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer byte[] bin = data.convertToString().getBytes(); 307b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer RubyMessage ret = (RubyMessage) ((RubyClass) recv).newInstance(context, Block.NULL_BLOCK); 308b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer try { 309b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer ret.builder.mergeFrom(bin); 310b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } catch (InvalidProtocolBufferException e) { 311b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer throw context.runtime.newRuntimeError(e.getMessage()); 312b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 313b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return ret; 314b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 315b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 316b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /* 317b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * call-seq: 318b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * MessageClass.encode_json(msg) => json_string 319b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * 320b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Encodes the given message object into its serialized JSON representation. 321b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer */ 322b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @JRubyMethod(name = "encode_json", meta = true) 323b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public static IRubyObject encodeJson(ThreadContext context, IRubyObject recv, IRubyObject msgRb) { 324b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer RubyMessage message = (RubyMessage) msgRb; 325b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return Helpers.invoke(context, message.toHash(context), "to_json"); 326b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 327b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 328b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /* 329b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * call-seq: 330b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * MessageClass.decode_json(data) => message 331b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * 332b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Decodes the given data (as a string containing bytes in protocol buffers wire 333b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * format) under the interpretration given by this message class's definition 334b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * and returns a message object with the corresponding field values. 335b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer */ 336b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @JRubyMethod(name = "decode_json", meta = true) 337b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public static IRubyObject decodeJson(ThreadContext context, IRubyObject recv, IRubyObject json) { 338b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer Ruby runtime = context.runtime; 339b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer RubyMessage ret = (RubyMessage) ((RubyClass) recv).newInstance(context, Block.NULL_BLOCK); 340b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer RubyModule jsonModule = runtime.getClassFromPath("JSON"); 341b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer RubyHash opts = RubyHash.newHash(runtime); 342b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer opts.fastASet(runtime.newSymbol("symbolize_names"), runtime.getTrue()); 343b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer IRubyObject[] args = new IRubyObject[] { Helpers.invoke(context, jsonModule, "parse", json, opts) }; 344b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer ret.initialize(context, args); 345b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return ret; 346b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 347b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 348b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @JRubyMethod(name = {"to_h", "to_hash"}) 349b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public IRubyObject toHash(ThreadContext context) { 350b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer Ruby runtime = context.runtime; 351b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer RubyHash ret = RubyHash.newHash(runtime); 352b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer for (Descriptors.FieldDescriptor fdef : this.descriptor.getFields()) { 353b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer IRubyObject value = getField(context, fdef); 354b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (!value.isNil()) { 355b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (value.respondsTo("to_h")) { 356b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer value = Helpers.invoke(context, value, "to_h"); 357b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } else if (value.respondsTo("to_a")) { 358b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer value = Helpers.invoke(context, value, "to_a"); 359b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 360b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 361b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer ret.fastASet(runtime.newSymbol(fdef.getName()), value); 362b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 363b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return ret; 364b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 365b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 366b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer protected DynamicMessage build(ThreadContext context) { 367b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return build(context, 0); 368b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 369b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 370b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer protected DynamicMessage build(ThreadContext context, int depth) { 371b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (depth > SINK_MAXIMUM_NESTING) { 372b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer throw context.runtime.newRuntimeError("Maximum recursion depth exceeded during encoding."); 373b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 374b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer for (Descriptors.FieldDescriptor fieldDescriptor : maps.keySet()) { 375b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer this.builder.clearField(fieldDescriptor); 376b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer RubyDescriptor mapDescriptor = (RubyDescriptor) getDescriptorForField(context, fieldDescriptor); 377b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer for (DynamicMessage kv : maps.get(fieldDescriptor).build(context, mapDescriptor)) { 378b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer this.builder.addRepeatedField(fieldDescriptor, kv); 379b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 380b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 381b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer for (Descriptors.FieldDescriptor fieldDescriptor : repeatedFields.keySet()) { 382b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer RubyRepeatedField repeatedField = repeatedFields.get(fieldDescriptor); 383b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer this.builder.clearField(fieldDescriptor); 384b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer for (int i = 0; i < repeatedField.size(); i++) { 385b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer Object item = convert(context, fieldDescriptor, repeatedField.get(i), depth); 386b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer this.builder.addRepeatedField(fieldDescriptor, item); 387b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 388b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 389b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer for (Descriptors.FieldDescriptor fieldDescriptor : fields.keySet()) { 390b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer IRubyObject value = fields.get(fieldDescriptor); 391b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer this.builder.setField(fieldDescriptor, convert(context, fieldDescriptor, value, depth)); 392b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 393b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return this.builder.build(); 394b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 395b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 396b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer protected Descriptors.Descriptor getDescriptor() { 397b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return this.descriptor; 398b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 399b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 400b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // Internal use only, called by Google::Protobuf.deep_copy 401b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer protected IRubyObject deepCopy(ThreadContext context) { 402b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer RubyMessage copy = (RubyMessage) metaClass.newInstance(context, Block.NULL_BLOCK); 403b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer for (Descriptors.FieldDescriptor fdef : this.descriptor.getFields()) { 404b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (fdef.isRepeated()) { 405b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer copy.addRepeatedField(fdef, this.getRepeatedField(context, fdef).deepCopy(context)); 406b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } else if (fields.containsKey(fdef)) { 407b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer copy.fields.put(fdef, fields.get(fdef)); 408b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } else if (this.builder.hasField(fdef)) { 409b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer copy.fields.put(fdef, wrapField(context, fdef, this.builder.getField(fdef))); 410b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 411b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 412b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return copy; 413b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 414b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 415b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer private RubyRepeatedField getRepeatedField(ThreadContext context, Descriptors.FieldDescriptor fieldDescriptor) { 416b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (this.repeatedFields.containsKey(fieldDescriptor)) { 417b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return this.repeatedFields.get(fieldDescriptor); 418b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 419b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer int count = this.builder.getRepeatedFieldCount(fieldDescriptor); 420b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer RubyRepeatedField ret = repeatedFieldForFieldDescriptor(context, fieldDescriptor); 421b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer for (int i = 0; i < count; i++) { 422b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer ret.push(context, wrapField(context, fieldDescriptor, this.builder.getRepeatedField(fieldDescriptor, i))); 423b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 424b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer addRepeatedField(fieldDescriptor, ret); 425b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return ret; 426b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 427b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 428b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer private void addRepeatedField(Descriptors.FieldDescriptor fieldDescriptor, RubyRepeatedField repeatedField) { 429b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer this.repeatedFields.put(fieldDescriptor, repeatedField); 430b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 431b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 432b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer private IRubyObject buildFrom(ThreadContext context, DynamicMessage dynamicMessage) { 433b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer this.builder.mergeFrom(dynamicMessage); 434b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return this; 435b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 436b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 437b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer private Descriptors.FieldDescriptor findField(ThreadContext context, IRubyObject fieldName) { 438b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer String nameStr = fieldName.asJavaString(); 439b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer Descriptors.FieldDescriptor ret = this.descriptor.findFieldByName(Utils.escapeIdentifier(nameStr)); 440b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (ret == null) 441b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer throw context.runtime.newArgumentError("field " + fieldName.asJavaString() + " is not found"); 442b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return ret; 443b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 444b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 445b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer private boolean hasField(IRubyObject fieldName) { 446b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer String nameStr = fieldName.asJavaString(); 447b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return this.descriptor.findFieldByName(Utils.escapeIdentifier(nameStr)) != null; 448b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 449b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 450b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer private void checkRepeatedFieldType(ThreadContext context, IRubyObject value, 451b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer Descriptors.FieldDescriptor fieldDescriptor) { 452b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer Ruby runtime = context.runtime; 453b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (!(value instanceof RubyRepeatedField)) { 454b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer throw runtime.newTypeError("Expected repeated field array"); 455b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 456b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 457b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 458b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // convert a ruby object to protobuf type, with type check 459b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer private Object convert(ThreadContext context, 460b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer Descriptors.FieldDescriptor fieldDescriptor, 461b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer IRubyObject value, int depth) { 462b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer Ruby runtime = context.runtime; 463b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer Object val = null; 464b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer switch (fieldDescriptor.getType()) { 465b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer case INT32: 466b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer case INT64: 467b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer case UINT32: 468b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer case UINT64: 469b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (!Utils.isRubyNum(value)) { 470b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer throw runtime.newTypeError("Expected number type for integral field."); 471b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 472b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer Utils.checkIntTypePrecision(context, fieldDescriptor.getType(), value); 473b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer switch (fieldDescriptor.getType()) { 474b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer case INT32: 475b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer val = RubyNumeric.num2int(value); 476b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer break; 477b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer case INT64: 478b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer val = RubyNumeric.num2long(value); 479b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer break; 480b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer case UINT32: 481b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer val = Utils.num2uint(value); 482b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer break; 483b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer case UINT64: 484b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer val = Utils.num2ulong(context.runtime, value); 485b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer break; 486b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer default: 487b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer break; 488b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 489b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer break; 490b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer case FLOAT: 491b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (!Utils.isRubyNum(value)) 492b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer throw runtime.newTypeError("Expected number type for float field."); 493b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer val = (float) RubyNumeric.num2dbl(value); 494b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer break; 495b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer case DOUBLE: 496b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (!Utils.isRubyNum(value)) 497b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer throw runtime.newTypeError("Expected number type for double field."); 498b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer val = RubyNumeric.num2dbl(value); 499b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer break; 500b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer case BOOL: 501b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (!(value instanceof RubyBoolean)) 502b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer throw runtime.newTypeError("Invalid argument for boolean field."); 503b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer val = value.isTrue(); 504b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer break; 505b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer case BYTES: 506b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer case STRING: 507b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer Utils.validateStringEncoding(context.runtime, fieldDescriptor.getType(), value); 508b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer RubyString str = (RubyString) value; 509b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer switch (fieldDescriptor.getType()) { 510b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer case BYTES: 511b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer val = ByteString.copyFrom(str.getBytes()); 512b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer break; 513b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer case STRING: 514b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer val = str.asJavaString(); 515b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer break; 516b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer default: 517b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer break; 518b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 519b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer break; 520b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer case MESSAGE: 521b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer RubyClass typeClass = (RubyClass) ((RubyDescriptor) getDescriptorForField(context, fieldDescriptor)).msgclass(context); 522b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (!value.getMetaClass().equals(typeClass)) 523b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer throw runtime.newTypeError(value, "Invalid type to assign to submessage field."); 524b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer val = ((RubyMessage) value).build(context, depth + 1); 525b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer break; 526b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer case ENUM: 527b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer Descriptors.EnumDescriptor enumDescriptor = fieldDescriptor.getEnumType(); 528b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 529b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (Utils.isRubyNum(value)) { 530b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer val = enumDescriptor.findValueByNumberCreatingIfUnknown(RubyNumeric.num2int(value)); 531b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } else if (value instanceof RubySymbol) { 532b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer val = enumDescriptor.findValueByName(value.asJavaString()); 533b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } else { 534b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer throw runtime.newTypeError("Expected number or symbol type for enum field."); 535b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 536b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (val == null) { 537b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer throw runtime.newRangeError("Enum value " + value + " is not found."); 538b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 539b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer break; 540b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer default: 541b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer break; 542b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 543b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return val; 544b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 545b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 546b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer private IRubyObject wrapField(ThreadContext context, Descriptors.FieldDescriptor fieldDescriptor, Object value) { 547b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (value == null) { 548b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return context.runtime.getNil(); 549b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 550b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer Ruby runtime = context.runtime; 551b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer switch (fieldDescriptor.getType()) { 552b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer case INT32: 553b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer case INT64: 554b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer case UINT32: 555b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer case UINT64: 556b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer case FLOAT: 557b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer case DOUBLE: 558b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer case BOOL: 559b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer case BYTES: 560b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer case STRING: 561b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return Utils.wrapPrimaryValue(context, fieldDescriptor.getType(), value); 562b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer case MESSAGE: 563b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer RubyClass typeClass = (RubyClass) ((RubyDescriptor) getDescriptorForField(context, fieldDescriptor)).msgclass(context); 564b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer RubyMessage msg = (RubyMessage) typeClass.newInstance(context, Block.NULL_BLOCK); 565b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return msg.buildFrom(context, (DynamicMessage) value); 566b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer case ENUM: 567b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer Descriptors.EnumValueDescriptor enumValueDescriptor = (Descriptors.EnumValueDescriptor) value; 568b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (enumValueDescriptor.getIndex() == -1) { // UNKNOWN ENUM VALUE 569b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return runtime.newFixnum(enumValueDescriptor.getNumber()); 570b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 571b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return runtime.newSymbol(enumValueDescriptor.getName()); 572b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer default: 573b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return runtime.newString(value.toString()); 574b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 575b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 576b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 577b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer private RubyRepeatedField repeatedFieldForFieldDescriptor(ThreadContext context, 578b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer Descriptors.FieldDescriptor fieldDescriptor) { 579b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer IRubyObject typeClass = context.runtime.getNilClass(); 580b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 581b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer IRubyObject descriptor = getDescriptorForField(context, fieldDescriptor); 582b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer Descriptors.FieldDescriptor.Type type = fieldDescriptor.getType(); 583b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (type == Descriptors.FieldDescriptor.Type.MESSAGE) { 584b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer typeClass = ((RubyDescriptor) descriptor).msgclass(context); 585b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 586b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } else if (type == Descriptors.FieldDescriptor.Type.ENUM) { 587b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer typeClass = ((RubyEnumDescriptor) descriptor).enummodule(context); 588b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 589b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return new RubyRepeatedField(context.runtime, cRepeatedField, type, typeClass); 590b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 591b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 592b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer protected IRubyObject getField(ThreadContext context, Descriptors.FieldDescriptor fieldDescriptor) { 593b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer Descriptors.OneofDescriptor oneofDescriptor = fieldDescriptor.getContainingOneof(); 594b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (oneofDescriptor != null) { 595b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (oneofCases.containsKey(oneofDescriptor)) { 596b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (oneofCases.get(oneofDescriptor) != fieldDescriptor) 597b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return context.runtime.getNil(); 598b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return fields.get(fieldDescriptor); 599b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } else { 600b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer Descriptors.FieldDescriptor oneofCase = builder.getOneofFieldDescriptor(oneofDescriptor); 601b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (oneofCase != fieldDescriptor) return context.runtime.getNil(); 602b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer IRubyObject value = wrapField(context, oneofCase, builder.getField(oneofCase)); 603b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer fields.put(fieldDescriptor, value); 604b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return value; 605b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 606b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 607b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 608b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (Utils.isMapEntry(fieldDescriptor)) { 609b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer RubyMap map = maps.get(fieldDescriptor); 610b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (map == null) { 611b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer map = newMapForField(context, fieldDescriptor); 612b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer int mapSize = this.builder.getRepeatedFieldCount(fieldDescriptor); 613b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer Descriptors.FieldDescriptor keyField = fieldDescriptor.getMessageType().findFieldByNumber(1); 614b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer Descriptors.FieldDescriptor valueField = fieldDescriptor.getMessageType().findFieldByNumber(2); 615b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer RubyDescriptor kvDescriptor = (RubyDescriptor) getDescriptorForField(context, fieldDescriptor); 616b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer RubyClass kvClass = (RubyClass) kvDescriptor.msgclass(context); 617b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer for (int i = 0; i < mapSize; i++) { 618b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer RubyMessage kvMessage = (RubyMessage) kvClass.newInstance(context, Block.NULL_BLOCK); 619b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer DynamicMessage message = (DynamicMessage) this.builder.getRepeatedField(fieldDescriptor, i); 620b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer kvMessage.buildFrom(context, message); 621b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer map.indexSet(context, kvMessage.getField(context, keyField), kvMessage.getField(context, valueField)); 622b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 623b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer maps.put(fieldDescriptor, map); 624b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 625b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return map; 626b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 627b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (fieldDescriptor.isRepeated()) { 628b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return getRepeatedField(context, fieldDescriptor); 629b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 630b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (fieldDescriptor.getType() != Descriptors.FieldDescriptor.Type.MESSAGE || 631b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer this.builder.hasField(fieldDescriptor) || fields.containsKey(fieldDescriptor)) { 632b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (fields.containsKey(fieldDescriptor)) { 633b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return fields.get(fieldDescriptor); 634b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } else { 635b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer IRubyObject value = wrapField(context, fieldDescriptor, this.builder.getField(fieldDescriptor)); 636b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (this.builder.hasField(fieldDescriptor)) { 637b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer fields.put(fieldDescriptor, value); 638b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 639b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return value; 640b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 641b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 642b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return context.runtime.getNil(); 643b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 644b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 645b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer protected IRubyObject setField(ThreadContext context, Descriptors.FieldDescriptor fieldDescriptor, IRubyObject value) { 646b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (Utils.isMapEntry(fieldDescriptor)) { 647b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (!(value instanceof RubyMap)) { 648b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer throw context.runtime.newTypeError("Expected Map instance"); 649b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 650b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer RubyMap thisMap = (RubyMap) getField(context, fieldDescriptor); 651b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer thisMap.mergeIntoSelf(context, value); 652b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } else if (fieldDescriptor.isRepeated()) { 653b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer checkRepeatedFieldType(context, value, fieldDescriptor); 654b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (value instanceof RubyRepeatedField) { 655b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer addRepeatedField(fieldDescriptor, (RubyRepeatedField) value); 656b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } else { 657b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer RubyArray ary = value.convertToArray(); 658b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer RubyRepeatedField repeatedField = rubyToRepeatedField(context, fieldDescriptor, ary); 659b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer addRepeatedField(fieldDescriptor, repeatedField); 660b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 661b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } else { 662b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer Descriptors.OneofDescriptor oneofDescriptor = fieldDescriptor.getContainingOneof(); 663b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (oneofDescriptor != null) { 664b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer Descriptors.FieldDescriptor oneofCase = oneofCases.get(oneofDescriptor); 665b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (oneofCase != null && oneofCase != fieldDescriptor) { 666b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer fields.remove(oneofCase); 667b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 668b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (value.isNil()) { 669b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer oneofCases.remove(oneofDescriptor); 670b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer fields.remove(fieldDescriptor); 671b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } else { 672b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer oneofCases.put(oneofDescriptor, fieldDescriptor); 673b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer fields.put(fieldDescriptor, value); 674b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 675b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } else { 676b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer Descriptors.FieldDescriptor.Type fieldType = fieldDescriptor.getType(); 677b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer IRubyObject typeClass = context.runtime.getObject(); 678b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer boolean addValue = true; 679b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (fieldType == Descriptors.FieldDescriptor.Type.MESSAGE) { 680b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer typeClass = ((RubyDescriptor) getDescriptorForField(context, fieldDescriptor)).msgclass(context); 681b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (value.isNil()){ 682b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer addValue = false; 683b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 684b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } else if (fieldType == Descriptors.FieldDescriptor.Type.ENUM) { 685b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer typeClass = ((RubyEnumDescriptor) getDescriptorForField(context, fieldDescriptor)).enummodule(context); 686b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer Descriptors.EnumDescriptor enumDescriptor = fieldDescriptor.getEnumType(); 687b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (Utils.isRubyNum(value)) { 688b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer Descriptors.EnumValueDescriptor val = 689b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer enumDescriptor.findValueByNumberCreatingIfUnknown(RubyNumeric.num2int(value)); 690b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (val.getIndex() != -1) value = context.runtime.newSymbol(val.getName()); 691b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 692b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 693b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (addValue) { 694b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer Utils.checkType(context, fieldType, value, (RubyModule) typeClass); 695b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer this.fields.put(fieldDescriptor, value); 696b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } else { 697b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer this.fields.remove(fieldDescriptor); 698b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 699b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 700b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 701b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return context.runtime.getNil(); 702b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 703b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 704b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer private String layoutInspect() { 705b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer ThreadContext context = getRuntime().getCurrentContext(); 706b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer StringBuilder sb = new StringBuilder(); 707b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer for (Descriptors.FieldDescriptor fdef : descriptor.getFields()) { 708b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer sb.append(Utils.unescapeIdentifier(fdef.getName())); 709b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer sb.append(": "); 710b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer sb.append(getField(context, fdef).inspect()); 711b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer sb.append(", "); 712b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 713b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return sb.substring(0, sb.length() - 2); 714b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 715b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 716b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer private IRubyObject getDescriptorForField(ThreadContext context, Descriptors.FieldDescriptor fieldDescriptor) { 717b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer RubyDescriptor thisRbDescriptor = (RubyDescriptor) getDescriptor(context, metaClass); 718b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return thisRbDescriptor.lookup(fieldDescriptor.getName()).getSubType(context); 719b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 720b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 721b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer private RubyRepeatedField rubyToRepeatedField(ThreadContext context, 722b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer Descriptors.FieldDescriptor fieldDescriptor, IRubyObject value) { 723b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer RubyArray arr = value.convertToArray(); 724b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer RubyRepeatedField repeatedField = repeatedFieldForFieldDescriptor(context, fieldDescriptor); 725b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer for (int i = 0; i < arr.size(); i++) { 726b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer repeatedField.push(context, arr.eltInternal(i)); 727b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 728b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return repeatedField; 729b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 730b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 731b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer private RubyMap newMapForField(ThreadContext context, Descriptors.FieldDescriptor fieldDescriptor) { 732b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer RubyDescriptor mapDescriptor = (RubyDescriptor) getDescriptorForField(context, fieldDescriptor); 733b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer Descriptors.FieldDescriptor keyField = fieldDescriptor.getMessageType().findFieldByNumber(1); 734b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer Descriptors.FieldDescriptor valueField = fieldDescriptor.getMessageType().findFieldByNumber(2); 735b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer IRubyObject keyType = RubySymbol.newSymbol(context.runtime, keyField.getType().name()); 736b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer IRubyObject valueType = RubySymbol.newSymbol(context.runtime, valueField.getType().name()); 737b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (valueField.getType() == Descriptors.FieldDescriptor.Type.MESSAGE) { 738b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer RubyFieldDescriptor rubyFieldDescriptor = (RubyFieldDescriptor) mapDescriptor.lookup(context, 739b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer context.runtime.newString("value")); 740b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer RubyDescriptor rubyDescriptor = (RubyDescriptor) rubyFieldDescriptor.getSubType(context); 741b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return (RubyMap) cMap.newInstance(context, keyType, valueType, 742b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer rubyDescriptor.msgclass(context), Block.NULL_BLOCK); 743b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } else { 744b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return (RubyMap) cMap.newInstance(context, keyType, valueType, Block.NULL_BLOCK); 745b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 746b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 747b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 748b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer private Descriptors.FieldDescriptor getOneofCase(Descriptors.OneofDescriptor oneof) { 749b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (oneofCases.containsKey(oneof)) { 750b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return oneofCases.get(oneof); 751b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 752b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return builder.getOneofFieldDescriptor(oneof); 753b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 754b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 755b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer private Descriptors.Descriptor descriptor; 756b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer private DynamicMessage.Builder builder; 757b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer private RubyClass cRepeatedField; 758b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer private RubyClass cMap; 759b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer private Map<Descriptors.FieldDescriptor, RubyRepeatedField> repeatedFields; 760b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer private Map<Descriptors.FieldDescriptor, RubyMap> maps; 761b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer private Map<Descriptors.FieldDescriptor, IRubyObject> fields; 762b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer private Map<Descriptors.OneofDescriptor, Descriptors.FieldDescriptor> oneofCases; 763b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 764b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer private static final int SINK_MAXIMUM_NESTING = 64; 765b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer} 766