aboutsummaryrefslogtreecommitdiffhomepage
path: root/ruby/src/main/java/com/google/protobuf/jruby/RubyFieldDescriptor.java
diff options
context:
space:
mode:
Diffstat (limited to 'ruby/src/main/java/com/google/protobuf/jruby/RubyFieldDescriptor.java')
-rw-r--r--ruby/src/main/java/com/google/protobuf/jruby/RubyFieldDescriptor.java248
1 files changed, 248 insertions, 0 deletions
diff --git a/ruby/src/main/java/com/google/protobuf/jruby/RubyFieldDescriptor.java b/ruby/src/main/java/com/google/protobuf/jruby/RubyFieldDescriptor.java
new file mode 100644
index 00000000..38226c4e
--- /dev/null
+++ b/ruby/src/main/java/com/google/protobuf/jruby/RubyFieldDescriptor.java
@@ -0,0 +1,248 @@
+/*
+ * 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.DescriptorProtos;
+import com.google.protobuf.Descriptors;
+import org.jruby.*;
+import org.jruby.anno.JRubyClass;
+import org.jruby.anno.JRubyMethod;
+import org.jruby.runtime.ObjectAllocator;
+import org.jruby.runtime.ThreadContext;
+import org.jruby.runtime.builtin.IRubyObject;
+
+@JRubyClass(name = "FieldDescriptor")
+public class RubyFieldDescriptor extends RubyObject {
+ public static void createRubyFileDescriptor(Ruby runtime) {
+ RubyModule mProtobuf = runtime.getClassFromPath("Google::Protobuf");
+ RubyClass cFieldDescriptor = mProtobuf.defineClassUnder("FieldDescriptor", runtime.getObject(), new ObjectAllocator() {
+ @Override
+ public IRubyObject allocate(Ruby runtime, RubyClass klazz) {
+ return new RubyFieldDescriptor(runtime, klazz);
+ }
+ });
+ cFieldDescriptor.defineAnnotatedMethods(RubyFieldDescriptor.class);
+ }
+
+ public RubyFieldDescriptor(Ruby runtime, RubyClass klazz) {
+ super(runtime, klazz);
+ }
+
+ /*
+ * call-seq:
+ * FieldDescriptor.new => field
+ *
+ * Returns a new field descriptor. Its name, type, etc. must be set before it is
+ * added to a message type.
+ */
+ @JRubyMethod
+ public IRubyObject initialize(ThreadContext context) {
+ builder = DescriptorProtos.FieldDescriptorProto.newBuilder();
+ return this;
+ }
+
+ /*
+ * call-seq:
+ * FieldDescriptor.label = label
+ *
+ * Sets the label on this field. Cannot be called if field is part of a message
+ * type already in a pool.
+ */
+ @JRubyMethod(name = "label=")
+ public IRubyObject setLabel(ThreadContext context, IRubyObject value) {
+ this.builder.setLabel(
+ DescriptorProtos.FieldDescriptorProto.Label.valueOf("LABEL_" + value.asJavaString().toUpperCase()));
+ return context.runtime.getNil();
+ }
+
+ /*
+ * call-seq:
+ * FieldDescriptor.name => name
+ *
+ * Returns the name of this field.
+ */
+ @JRubyMethod(name = "name")
+ public IRubyObject getName(ThreadContext context) {
+ return this.name;
+ }
+
+ @JRubyMethod(name = "subtype")
+ public IRubyObject getSubType(ThreadContext context) {
+ return subType;
+ }
+
+ /*
+ * call-seq:
+ * FieldDescriptor.name = name
+ *
+ * Sets the name of this field. Cannot be called once the containing message
+ * type, if any, is added to a pool.
+ */
+ @JRubyMethod(name = "name=")
+ public IRubyObject setName(ThreadContext context, IRubyObject value) {
+ String nameStr = value.asJavaString();
+ this.name = context.runtime.newString(nameStr);
+ this.builder.setName(Utils.escapeIdentifier(nameStr));
+ return context.runtime.getNil();
+ }
+
+ /*
+ * call-seq:
+ * FieldDescriptor.type => type
+ *
+ * Returns this field's type, as a Ruby symbol, or nil if not yet set.
+ *
+ * Valid field types are:
+ * :int32, :int64, :uint32, :uint64, :float, :double, :bool, :string,
+ * :bytes, :message.
+ */
+ @JRubyMethod(name = "type")
+ public IRubyObject getType(ThreadContext context) {
+ return Utils.fieldTypeToRuby(context, this.builder.getType());
+ }
+
+ /*
+ * call-seq:
+ * FieldDescriptor.type = type
+ *
+ * Sets this field's type. Cannot be called if field is part of a message type
+ * already in a pool.
+ */
+ @JRubyMethod(name = "type=")
+ public IRubyObject setType(ThreadContext context, IRubyObject value) {
+ this.builder.setType(DescriptorProtos.FieldDescriptorProto.Type.valueOf("TYPE_" + value.asJavaString().toUpperCase()));
+ return context.runtime.getNil();
+ }
+
+ /*
+ * call-seq:
+ * FieldDescriptor.number = number
+ *
+ * Sets the tag number for this field. Cannot be called if field is part of a
+ * message type already in a pool.
+ */
+ @JRubyMethod(name = "number=")
+ public IRubyObject setNumber(ThreadContext context, IRubyObject value) {
+ this.builder.setNumber(RubyNumeric.num2int(value));
+ return context.runtime.getNil();
+ }
+
+ /*
+ * call-seq:
+ * FieldDescriptor.submsg_name = submsg_name
+ *
+ * Sets the name of the message or enum type corresponding to this field, if it
+ * is a message or enum field (respectively). This type name will be resolved
+ * within the context of the pool to which the containing message type is added.
+ * Cannot be called on field that are not of message or enum type, or on fields
+ * that are part of a message type already added to a pool.
+ */
+ @JRubyMethod(name = "submsg_name=")
+ public IRubyObject setSubmsgName(ThreadContext context, IRubyObject name) {
+ this.builder.setTypeName("." + Utils.escapeIdentifier(name.asJavaString()));
+ return context.runtime.getNil();
+ }
+
+ /*
+ * call-seq:
+ * FieldDescriptor.get(message) => value
+ *
+ * Returns the value set for this field on the given message. Raises an
+ * exception if message is of the wrong type.
+ */
+ @JRubyMethod(name = "get")
+ public IRubyObject getValue(ThreadContext context, IRubyObject msgRb) {
+ RubyMessage message = (RubyMessage) msgRb;
+ if (message.getDescriptor() != fieldDef.getContainingType()) {
+ throw context.runtime.newTypeError("set method called on wrong message type");
+ }
+ return message.getField(context, fieldDef);
+ }
+
+ /*
+ * call-seq:
+ * FieldDescriptor.set(message, value)
+ *
+ * Sets the value corresponding to this field to the given value on the given
+ * message. Raises an exception if message is of the wrong type. Performs the
+ * ordinary type-checks for field setting.
+ */
+ @JRubyMethod(name = "set")
+ public IRubyObject setValue(ThreadContext context, IRubyObject msgRb, IRubyObject value) {
+ RubyMessage message = (RubyMessage) msgRb;
+ if (message.getDescriptor() != fieldDef.getContainingType()) {
+ throw context.runtime.newTypeError("set method called on wrong message type");
+ }
+ message.setField(context, fieldDef, value);
+ return context.runtime.getNil();
+ }
+
+ protected void setSubType(IRubyObject rubyDescriptor) {
+ this.subType = rubyDescriptor;
+ }
+
+ protected void setFieldDef(Descriptors.FieldDescriptor fieldDescriptor) {
+ this.fieldDef = fieldDescriptor;
+ }
+
+ protected void setOneofName(IRubyObject name) {
+ oneofName = name;
+ }
+
+ protected void setOneofIndex(int index) {
+ hasOneofIndex = true;
+ oneofIndex = index;
+ }
+
+ protected IRubyObject getOneofName() {
+ return oneofName;
+ }
+
+ protected Descriptors.FieldDescriptor getFieldDef() {
+ return fieldDef;
+ }
+
+ protected DescriptorProtos.FieldDescriptorProto build() {
+ if (hasOneofIndex)
+ builder.setOneofIndex(oneofIndex);
+ return this.builder.build();
+ }
+
+ private DescriptorProtos.FieldDescriptorProto.Builder builder;
+ private IRubyObject name;
+ private IRubyObject subType;
+ private IRubyObject oneofName;
+ private Descriptors.FieldDescriptor fieldDef;
+ private int oneofIndex;
+ private boolean hasOneofIndex = false;
+}