Utils.java
Go to the documentation of this file.
1 /*
2  * Protocol Buffers - Google's data interchange format
3  * Copyright 2014 Google Inc. All rights reserved.
4  * https://developers.google.com/protocol-buffers/
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions are
8  * met:
9  *
10  * * Redistributions of source code must retain the above copyright
11  * notice, this list of conditions and the following disclaimer.
12  * * Redistributions in binary form must reproduce the above
13  * copyright notice, this list of conditions and the following disclaimer
14  * in the documentation and/or other materials provided with the
15  * distribution.
16  * * Neither the name of Google Inc. nor the names of its
17  * contributors may be used to endorse or promote products derived from
18  * this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32 
33 package com.google.protobuf.jruby;
34 
38 import org.jcodings.Encoding;
39 import org.jcodings.specific.ASCIIEncoding;
40 import org.jcodings.specific.USASCIIEncoding;
41 import org.jcodings.specific.UTF8Encoding;
42 import org.jruby.*;
43 import org.jruby.runtime.Block;
44 import org.jruby.runtime.ThreadContext;
45 import org.jruby.runtime.builtin.IRubyObject;
46 
47 import java.math.BigInteger;
48 
49 public class Utils {
50  public static Descriptors.FieldDescriptor.Type rubyToFieldType(IRubyObject typeClass) {
51  return Descriptors.FieldDescriptor.Type.valueOf(typeClass.asJavaString().toUpperCase());
52  }
53 
54  public static IRubyObject fieldTypeToRuby(ThreadContext context, Descriptors.FieldDescriptor.Type type) {
55  return fieldTypeToRuby(context, type.name());
56  }
57 
58  public static IRubyObject fieldTypeToRuby(ThreadContext context, DescriptorProtos.FieldDescriptorProto.Type type) {
59  return fieldTypeToRuby(context, type.name());
60  }
61 
62  private static IRubyObject fieldTypeToRuby(ThreadContext context, String typeName) {
63 
64  return context.runtime.newSymbol(typeName.replace("TYPE_", "").toLowerCase());
65  }
66 
67  public static IRubyObject checkType(ThreadContext context, Descriptors.FieldDescriptor.Type fieldType,
68  IRubyObject value, RubyModule typeClass) {
69  Ruby runtime = context.runtime;
70  Object val;
71  switch(fieldType) {
72  case INT32:
73  case INT64:
74  case UINT32:
75  case UINT64:
76  if (!isRubyNum(value)) {
77  throw runtime.newTypeError("Expected number type for integral field.");
78  }
79  switch(fieldType) {
80  case INT32:
81  RubyNumeric.num2int(value);
82  break;
83  case INT64:
84  RubyNumeric.num2long(value);
85  break;
86  case UINT32:
87  num2uint(value);
88  break;
89  default:
90  num2ulong(context.runtime, value);
91  break;
92  }
93  checkIntTypePrecision(context, fieldType, value);
94  break;
95  case FLOAT:
96  if (!isRubyNum(value))
97  throw runtime.newTypeError("Expected number type for float field.");
98  break;
99  case DOUBLE:
100  if (!isRubyNum(value))
101  throw runtime.newTypeError("Expected number type for double field.");
102  break;
103  case BOOL:
104  if (!(value instanceof RubyBoolean))
105  throw runtime.newTypeError("Invalid argument for boolean field.");
106  break;
107  case BYTES:
108  case STRING:
109  value = validateStringEncoding(context, fieldType, value);
110  break;
111  case MESSAGE:
112  if (value.getMetaClass() != typeClass) {
113  throw runtime.newTypeError(value, typeClass);
114  }
115  break;
116  case ENUM:
117  if (value instanceof RubySymbol) {
118  Descriptors.EnumDescriptor enumDescriptor =
119  ((RubyEnumDescriptor) typeClass.getInstanceVariable(DESCRIPTOR_INSTANCE_VAR)).getDescriptor();
120  val = enumDescriptor.findValueByName(value.asJavaString());
121  if (val == null)
122  throw runtime.newRangeError("Enum value " + value + " is not found.");
123  } else if(!isRubyNum(value)) {
124  throw runtime.newTypeError("Expected number or symbol type for enum field.");
125  }
126  break;
127  default:
128  break;
129  }
130  return value;
131  }
132 
133  public static IRubyObject wrapPrimaryValue(ThreadContext context, Descriptors.FieldDescriptor.Type fieldType, Object value) {
134  Ruby runtime = context.runtime;
135  switch (fieldType) {
136  case INT32:
137  return runtime.newFixnum((Integer) value);
138  case INT64:
139  return runtime.newFixnum((Long) value);
140  case UINT32:
141  return runtime.newFixnum(((Integer) value) & (-1l >>> 32));
142  case UINT64:
143  long ret = (Long) value;
144  return ret >= 0 ? runtime.newFixnum(ret) :
145  RubyBignum.newBignum(runtime, UINT64_COMPLEMENTARY.add(new BigInteger(ret + "")));
146  case FLOAT:
147  return runtime.newFloat((Float) value);
148  case DOUBLE:
149  return runtime.newFloat((Double) value);
150  case BOOL:
151  return (Boolean) value ? runtime.getTrue() : runtime.getFalse();
152  case BYTES: {
153  IRubyObject wrapped = runtime.newString(((ByteString) value).toStringUtf8());
154  wrapped.setFrozen(true);
155  return wrapped;
156  }
157  case STRING: {
158  IRubyObject wrapped = runtime.newString(value.toString());
159  wrapped.setFrozen(true);
160  return wrapped;
161  }
162  default:
163  return runtime.getNil();
164  }
165  }
166 
167  public static int num2uint(IRubyObject value) {
168  long longVal = RubyNumeric.num2long(value);
169  if (longVal > UINT_MAX)
170  throw value.getRuntime().newRangeError("Integer " + longVal + " too big to convert to 'unsigned int'");
171  long num = longVal;
172  if (num > Integer.MAX_VALUE || num < Integer.MIN_VALUE)
173  // encode to UINT32
174  num = (-longVal ^ (-1l >>> 32) ) + 1;
175  RubyNumeric.checkInt(value, num);
176  return (int) num;
177  }
178 
179  public static long num2ulong(Ruby runtime, IRubyObject value) {
180  if (value instanceof RubyFloat) {
181  RubyBignum bignum = RubyBignum.newBignum(runtime, ((RubyFloat) value).getDoubleValue());
182  return RubyBignum.big2ulong(bignum);
183  } else if (value instanceof RubyBignum) {
184  return RubyBignum.big2ulong((RubyBignum) value);
185  } else {
186  return RubyNumeric.num2long(value);
187  }
188  }
189 
190  public static IRubyObject validateStringEncoding(ThreadContext context, Descriptors.FieldDescriptor.Type type, IRubyObject value) {
191  if (!(value instanceof RubyString))
192  throw context.runtime.newTypeError("Invalid argument for string field.");
193  switch(type) {
194  case BYTES:
195  value = ((RubyString)value).encode(context, context.runtime.evalScriptlet("Encoding::ASCII_8BIT"));
196  break;
197  case STRING:
198  value = ((RubyString)value).encode(context, context.runtime.evalScriptlet("Encoding::UTF_8"));
199  break;
200  default:
201  break;
202  }
203  value.setFrozen(true);
204  return value;
205  }
206 
207  public static void checkNameAvailability(ThreadContext context, String name) {
208  if (context.runtime.getObject().getConstantAt(name) != null)
209  throw context.runtime.newNameError(name + " is already defined", name);
210  }
211 
217  public static String escapeIdentifier(String name) {
218  return name.replace(".", BADNAME_REPLACEMENT);
219  }
220 
226  public static String unescapeIdentifier(String name) {
227  return name.replace(BADNAME_REPLACEMENT, ".");
228  }
229 
230  public static boolean isMapEntry(Descriptors.FieldDescriptor fieldDescriptor) {
231  return fieldDescriptor.getType() == Descriptors.FieldDescriptor.Type.MESSAGE &&
232  fieldDescriptor.isRepeated() &&
233  fieldDescriptor.getMessageType().getOptions().getMapEntry();
234  }
235 
236  public static RubyFieldDescriptor msgdefCreateField(ThreadContext context, String label, IRubyObject name,
237  IRubyObject type, IRubyObject number, IRubyObject typeClass, RubyClass cFieldDescriptor) {
238  Ruby runtime = context.runtime;
239  RubyFieldDescriptor fieldDef = (RubyFieldDescriptor) cFieldDescriptor.newInstance(context, Block.NULL_BLOCK);
240  fieldDef.setLabel(context, runtime.newString(label));
241  fieldDef.setName(context, name);
242  fieldDef.setType(context, type);
243  fieldDef.setNumber(context, number);
244 
245  if (!typeClass.isNil()) {
246  if (!(typeClass instanceof RubyString)) {
247  throw runtime.newArgumentError("expected string for type class");
248  }
249  fieldDef.setSubmsgName(context, typeClass);
250  }
251  return fieldDef;
252  }
253 
254  protected static void checkIntTypePrecision(ThreadContext context, Descriptors.FieldDescriptor.Type type, IRubyObject value) {
255  if (value instanceof RubyFloat) {
256  double doubleVal = RubyNumeric.num2dbl(value);
257  if (Math.floor(doubleVal) != doubleVal) {
258  throw context.runtime.newRangeError("Non-integral floating point value assigned to integer field.");
259  }
260  }
262  if (RubyNumeric.num2dbl(value) < 0) {
263  throw context.runtime.newRangeError("Assigning negative value to unsigned integer field.");
264  }
265  }
266  }
267 
268  protected static boolean isRubyNum(Object value) {
269  return value instanceof RubyFixnum || value instanceof RubyFloat || value instanceof RubyBignum;
270  }
271 
272  protected static void validateTypeClass(ThreadContext context, Descriptors.FieldDescriptor.Type type, IRubyObject value) {
273  Ruby runtime = context.runtime;
274  if (!(value instanceof RubyModule)) {
275  throw runtime.newArgumentError("TypeClass has incorrect type");
276  }
277  RubyModule klass = (RubyModule) value;
278  IRubyObject descriptor = klass.getInstanceVariable(DESCRIPTOR_INSTANCE_VAR);
279  if (descriptor.isNil()) {
280  throw runtime.newArgumentError("Type class has no descriptor. Please pass a " +
281  "class or enum as returned by the DescriptorPool.");
282  }
284  if (! (descriptor instanceof RubyDescriptor)) {
285  throw runtime.newArgumentError("Descriptor has an incorrect type");
286  }
287  } else if (type == Descriptors.FieldDescriptor.Type.ENUM) {
288  if (! (descriptor instanceof RubyEnumDescriptor)) {
289  throw runtime.newArgumentError("Descriptor has an incorrect type");
290  }
291  }
292  }
293 
294  public static String BADNAME_REPLACEMENT = "__DOT__";
295 
296  public static String DESCRIPTOR_INSTANCE_VAR = "@descriptor";
297 
298  public static String EQUAL_SIGN = "=";
299 
300  private static BigInteger UINT64_COMPLEMENTARY = new BigInteger("18446744073709551616"); //Math.pow(2, 64)
301 
302  private static long UINT_MAX = 0xffffffffl;
303 }
com.google.protobuf.Descriptors
Definition: Descriptors.java:80
name
GLuint const GLchar * name
Definition: glcorearb.h:3055
com.google.protobuf.jruby.RubyFieldDescriptor.setLabel
IRubyObject setLabel(ThreadContext context, IRubyObject value)
Definition: RubyFieldDescriptor.java:93
com.google.protobuf.jruby.Utils.escapeIdentifier
static String escapeIdentifier(String name)
Definition: Utils.java:217
com.google.protobuf.Descriptors.FieldDescriptor.Type.UINT64
UINT64
Definition: Descriptors.java:1219
com.google.protobuf.jruby.Utils
Definition: Utils.java:49
com.google.protobuf.jruby.RubyFieldDescriptor.setSubmsgName
IRubyObject setSubmsgName(ThreadContext context, IRubyObject name)
Definition: RubyFieldDescriptor.java:198
com.google.protobuf.jruby.Utils.isMapEntry
static boolean isMapEntry(Descriptors.FieldDescriptor fieldDescriptor)
Definition: Utils.java:230
label
GLuint GLsizei const GLchar * label
Definition: glcorearb.h:4316
com.google.protobuf.jruby.Utils.BADNAME_REPLACEMENT
static String BADNAME_REPLACEMENT
Definition: Utils.java:294
com.google.protobuf.jruby.Utils.isRubyNum
static boolean isRubyNum(Object value)
Definition: Utils.java:268
com.google.protobuf.jruby.Utils.msgdefCreateField
static RubyFieldDescriptor msgdefCreateField(ThreadContext context, String label, IRubyObject name, IRubyObject type, IRubyObject number, IRubyObject typeClass, RubyClass cFieldDescriptor)
Definition: Utils.java:236
com.google.protobuf.Descriptors.FieldDescriptor.Type.MESSAGE
MESSAGE
Definition: Descriptors.java:1226
com.google.protobuf
Definition: ProtoCaliperBenchmark.java:2
com.google.protobuf.Descriptors.EnumDescriptor.findValueByName
EnumValueDescriptor findValueByName(final String name)
Definition: Descriptors.java:1643
cFieldDescriptor
VALUE cFieldDescriptor
descriptor
Descriptor * descriptor
Definition: php/ext/google/protobuf/protobuf.h:936
com.google.protobuf.Descriptors.FieldDescriptor.Type
Definition: Descriptors.java:1215
com.google.protobuf.jruby.Utils.validateTypeClass
static void validateTypeClass(ThreadContext context, Descriptors.FieldDescriptor.Type type, IRubyObject value)
Definition: Utils.java:272
com.google.protobuf.jruby.Utils.checkNameAvailability
static void checkNameAvailability(ThreadContext context, String name)
Definition: Utils.java:207
com.google.protobuf.jruby.Utils.validateStringEncoding
static IRubyObject validateStringEncoding(ThreadContext context, Descriptors.FieldDescriptor.Type type, IRubyObject value)
Definition: Utils.java:190
testing::internal::Double
FloatingPoint< double > Double
Definition: gtest-internal.h:429
com.google.protobuf.jruby.Utils.wrapPrimaryValue
static IRubyObject wrapPrimaryValue(ThreadContext context, Descriptors.FieldDescriptor.Type fieldType, Object value)
Definition: Utils.java:133
com.google.protobuf.jruby.Utils.unescapeIdentifier
static String unescapeIdentifier(String name)
Definition: Utils.java:226
com.google.protobuf.jruby.Utils.EQUAL_SIGN
static String EQUAL_SIGN
Definition: Utils.java:298
testing::internal::Float
FloatingPoint< float > Float
Definition: gtest-internal.h:428
com.google.protobuf.Descriptors.FieldDescriptor.Type.UINT32
UINT32
Definition: Descriptors.java:1228
com.google.protobuf.Descriptors.EnumDescriptor
Definition: Descriptors.java:1583
com.google.protobuf.jruby.Utils.rubyToFieldType
static Descriptors.FieldDescriptor.Type rubyToFieldType(IRubyObject typeClass)
Definition: Utils.java:50
com.google.protobuf.jruby.Utils.num2uint
static int num2uint(IRubyObject value)
Definition: Utils.java:167
com.google.protobuf.jruby.Utils.num2ulong
static long num2ulong(Ruby runtime, IRubyObject value)
Definition: Utils.java:179
com.google.protobuf.jruby.Utils.DESCRIPTOR_INSTANCE_VAR
static String DESCRIPTOR_INSTANCE_VAR
Definition: Utils.java:296
com.google.protobuf.jruby.Utils.checkIntTypePrecision
static void checkIntTypePrecision(ThreadContext context, Descriptors.FieldDescriptor.Type type, IRubyObject value)
Definition: Utils.java:254
com.google.protobuf.jruby.Utils.fieldTypeToRuby
static IRubyObject fieldTypeToRuby(ThreadContext context, String typeName)
Definition: Utils.java:62
com.google.protobuf.jruby.Utils.UINT64_COMPLEMENTARY
static BigInteger UINT64_COMPLEMENTARY
Definition: Utils.java:300
com.google.protobuf.jruby.RubyFieldDescriptor
Definition: RubyFieldDescriptor.java:45
com.google.protobuf.jruby.Utils.fieldTypeToRuby
static IRubyObject fieldTypeToRuby(ThreadContext context, DescriptorProtos.FieldDescriptorProto.Type type)
Definition: Utils.java:58
com.google.protobuf.jruby.RubyEnumDescriptor
Definition: RubyEnumDescriptor.java:50
java
type
GLenum type
Definition: glcorearb.h:2695
com.google.protobuf.jruby.RubyFieldDescriptor.setNumber
IRubyObject setNumber(ThreadContext context, IRubyObject value)
Definition: RubyFieldDescriptor.java:181
com.google
com
com.google.protobuf.jruby.RubyFieldDescriptor.setType
IRubyObject setType(ThreadContext context, IRubyObject value)
Definition: RubyFieldDescriptor.java:156
com.google.protobuf.jruby.Utils.checkType
static IRubyObject checkType(ThreadContext context, Descriptors.FieldDescriptor.Type fieldType, IRubyObject value, RubyModule typeClass)
Definition: Utils.java:67
com.google.protobuf.jruby.Utils.fieldTypeToRuby
static IRubyObject fieldTypeToRuby(ThreadContext context, Descriptors.FieldDescriptor.Type type)
Definition: Utils.java:54
com.google.protobuf.jruby.RubyFieldDescriptor.setName
IRubyObject setName(ThreadContext context, IRubyObject value)
Definition: RubyFieldDescriptor.java:120
val
GLuint GLfloat * val
Definition: glcorearb.h:3604
com.google.protobuf.jruby.RubyDescriptor
Definition: RubyDescriptor.java:50
value
GLsizei const GLfloat * value
Definition: glcorearb.h:3093
com.google.protobuf::DescriptorProtos
com.google.protobuf.Descriptors.FieldDescriptor.Type.valueOf
static Type valueOf(final FieldDescriptorProto.Type type)
Definition: Descriptors.java:1249
com.google.protobuf.jruby.Utils.UINT_MAX
static long UINT_MAX
Definition: Utils.java:302
klass
zend_class_entry * klass
Definition: php/ext/google/protobuf/protobuf.h:801
number
double number
Definition: cJSON.h:326
com.google.protobuf.Descriptors.FieldDescriptor.Type.ENUM
ENUM
Definition: Descriptors.java:1229
com.google.protobuf.Descriptors.FieldDescriptor
Definition: Descriptors.java:949
com.google.protobuf.ByteString
Definition: ByteString.java:67


libaditof
Author(s):
autogenerated on Wed May 21 2025 02:07:01