OLD | NEW |
1 /* | 1 /* |
2 * Protocol Buffers - Google's data interchange format | 2 * Protocol Buffers - Google's data interchange format |
3 * Copyright 2014 Google Inc. All rights reserved. | 3 * Copyright 2014 Google Inc. All rights reserved. |
4 * https://developers.google.com/protocol-buffers/ | 4 * https://developers.google.com/protocol-buffers/ |
5 * | 5 * |
6 * Redistribution and use in source and binary forms, with or without | 6 * Redistribution and use in source and binary forms, with or without |
7 * modification, are permitted provided that the following conditions are | 7 * modification, are permitted provided that the following conditions are |
8 * met: | 8 * met: |
9 * | 9 * |
10 * * Redistributions of source code must retain the above copyright | 10 * * Redistributions of source code must retain the above copyright |
(...skipping 23 matching lines...) Expand all Loading... |
34 | 34 |
35 import com.google.protobuf.*; | 35 import com.google.protobuf.*; |
36 import org.jruby.*; | 36 import org.jruby.*; |
37 import org.jruby.anno.JRubyMethod; | 37 import org.jruby.anno.JRubyMethod; |
38 import org.jruby.runtime.Block; | 38 import org.jruby.runtime.Block; |
39 import org.jruby.runtime.Helpers; | 39 import org.jruby.runtime.Helpers; |
40 import org.jruby.runtime.ThreadContext; | 40 import org.jruby.runtime.ThreadContext; |
41 import org.jruby.runtime.builtin.IRubyObject; | 41 import org.jruby.runtime.builtin.IRubyObject; |
42 import org.jruby.util.ByteList; | 42 import org.jruby.util.ByteList; |
43 | 43 |
| 44 import java.security.MessageDigest; |
| 45 import java.security.NoSuchAlgorithmException; |
44 import java.util.HashMap; | 46 import java.util.HashMap; |
45 import java.util.Map; | 47 import java.util.Map; |
46 | 48 |
47 public class RubyMessage extends RubyObject { | 49 public class RubyMessage extends RubyObject { |
48 public RubyMessage(Ruby ruby, RubyClass klazz, Descriptors.Descriptor descri
ptor) { | 50 public RubyMessage(Ruby ruby, RubyClass klazz, Descriptors.Descriptor descri
ptor) { |
49 super(ruby, klazz); | 51 super(ruby, klazz); |
50 this.descriptor = descriptor; | 52 this.descriptor = descriptor; |
51 } | 53 } |
52 | 54 |
53 /* | 55 /* |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
157 } | 159 } |
158 | 160 |
159 /* | 161 /* |
160 * call-seq: | 162 * call-seq: |
161 * Message.hash => hash_value | 163 * Message.hash => hash_value |
162 * | 164 * |
163 * Returns a hash value that represents this message's field values. | 165 * Returns a hash value that represents this message's field values. |
164 */ | 166 */ |
165 @JRubyMethod | 167 @JRubyMethod |
166 public IRubyObject hash(ThreadContext context) { | 168 public IRubyObject hash(ThreadContext context) { |
167 int hashCode = System.identityHashCode(this); | 169 try { |
168 return context.runtime.newFixnum(hashCode); | 170 MessageDigest digest = MessageDigest.getInstance("SHA-256"); |
| 171 for (RubyMap map : maps.values()) { |
| 172 digest.update((byte) map.hashCode()); |
| 173 } |
| 174 for (RubyRepeatedField repeatedField : repeatedFields.values()) { |
| 175 digest.update((byte) repeatedFields.hashCode()); |
| 176 } |
| 177 for (IRubyObject field : fields.values()) { |
| 178 digest.update((byte) field.hashCode()); |
| 179 } |
| 180 return context.runtime.newString(new ByteList(digest.digest())); |
| 181 } catch (NoSuchAlgorithmException ignore) { |
| 182 return context.runtime.newFixnum(System.identityHashCode(this)); |
| 183 } |
169 } | 184 } |
170 | 185 |
171 /* | 186 /* |
172 * call-seq: | 187 * call-seq: |
173 * Message.==(other) => boolean | 188 * Message.==(other) => boolean |
174 * | 189 * |
175 * Performs a deep comparison of this message with another. Messages are equ
al | 190 * Performs a deep comparison of this message with another. Messages are equ
al |
176 * if they have the same type and if each field is equal according to the :=
= | 191 * if they have the same type and if each field is equal according to the :=
= |
177 * method's semantics (a more efficient comparison may actually be done if t
he | 192 * method's semantics (a more efficient comparison may actually be done if t
he |
178 * field is of a primitive type). | 193 * field is of a primitive type). |
(...skipping 318 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
497 throw runtime.newTypeError("Expected number type for double
field."); | 512 throw runtime.newTypeError("Expected number type for double
field."); |
498 val = RubyNumeric.num2dbl(value); | 513 val = RubyNumeric.num2dbl(value); |
499 break; | 514 break; |
500 case BOOL: | 515 case BOOL: |
501 if (!(value instanceof RubyBoolean)) | 516 if (!(value instanceof RubyBoolean)) |
502 throw runtime.newTypeError("Invalid argument for boolean fie
ld."); | 517 throw runtime.newTypeError("Invalid argument for boolean fie
ld."); |
503 val = value.isTrue(); | 518 val = value.isTrue(); |
504 break; | 519 break; |
505 case BYTES: | 520 case BYTES: |
506 case STRING: | 521 case STRING: |
507 Utils.validateStringEncoding(context.runtime, fieldDescriptor.ge
tType(), value); | 522 Utils.validateStringEncoding(context, fieldDescriptor.getType(),
value); |
508 RubyString str = (RubyString) value; | 523 RubyString str = (RubyString) value; |
509 switch (fieldDescriptor.getType()) { | 524 switch (fieldDescriptor.getType()) { |
510 case BYTES: | 525 case BYTES: |
511 val = ByteString.copyFrom(str.getBytes()); | 526 val = ByteString.copyFrom(str.getBytes()); |
512 break; | 527 break; |
513 case STRING: | 528 case STRING: |
514 val = str.asJavaString(); | 529 val = str.asJavaString(); |
515 break; | 530 break; |
516 default: | 531 default: |
517 break; | 532 break; |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
585 | 600 |
586 } else if (type == Descriptors.FieldDescriptor.Type.ENUM) { | 601 } else if (type == Descriptors.FieldDescriptor.Type.ENUM) { |
587 typeClass = ((RubyEnumDescriptor) descriptor).enummodule(context); | 602 typeClass = ((RubyEnumDescriptor) descriptor).enummodule(context); |
588 } | 603 } |
589 return new RubyRepeatedField(context.runtime, cRepeatedField, type, type
Class); | 604 return new RubyRepeatedField(context.runtime, cRepeatedField, type, type
Class); |
590 } | 605 } |
591 | 606 |
592 protected IRubyObject getField(ThreadContext context, Descriptors.FieldDescr
iptor fieldDescriptor) { | 607 protected IRubyObject getField(ThreadContext context, Descriptors.FieldDescr
iptor fieldDescriptor) { |
593 Descriptors.OneofDescriptor oneofDescriptor = fieldDescriptor.getContain
ingOneof(); | 608 Descriptors.OneofDescriptor oneofDescriptor = fieldDescriptor.getContain
ingOneof(); |
594 if (oneofDescriptor != null) { | 609 if (oneofDescriptor != null) { |
595 if (oneofCases.containsKey(oneofDescriptor)) { | 610 if (oneofCases.get(oneofDescriptor) == fieldDescriptor) { |
596 if (oneofCases.get(oneofDescriptor) != fieldDescriptor) | |
597 return context.runtime.getNil(); | |
598 return fields.get(fieldDescriptor); | 611 return fields.get(fieldDescriptor); |
599 } else { | 612 } else { |
600 Descriptors.FieldDescriptor oneofCase = builder.getOneofFieldDes
criptor(oneofDescriptor); | 613 Descriptors.FieldDescriptor oneofCase = builder.getOneofFieldDes
criptor(oneofDescriptor); |
601 if (oneofCase != fieldDescriptor) return context.runtime.getNil(
); | 614 if (oneofCase != fieldDescriptor) { |
| 615 if (fieldDescriptor.getType() == Descriptors.FieldDescriptor.T
ype.MESSAGE) { |
| 616 return context.runtime.getNil(); |
| 617 } else { |
| 618 return wrapField(context, fieldDescriptor, fieldDescriptor.g
etDefaultValue()); |
| 619 } |
| 620 } |
602 IRubyObject value = wrapField(context, oneofCase, builder.getFie
ld(oneofCase)); | 621 IRubyObject value = wrapField(context, oneofCase, builder.getFie
ld(oneofCase)); |
603 fields.put(fieldDescriptor, value); | 622 fields.put(fieldDescriptor, value); |
604 return value; | 623 return value; |
605 } | 624 } |
606 } | 625 } |
607 | 626 |
608 if (Utils.isMapEntry(fieldDescriptor)) { | 627 if (Utils.isMapEntry(fieldDescriptor)) { |
609 RubyMap map = maps.get(fieldDescriptor); | 628 RubyMap map = maps.get(fieldDescriptor); |
610 if (map == null) { | 629 if (map == null) { |
611 map = newMapForField(context, fieldDescriptor); | 630 map = newMapForField(context, fieldDescriptor); |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
684 } else if (fieldType == Descriptors.FieldDescriptor.Type.ENUM) { | 703 } else if (fieldType == Descriptors.FieldDescriptor.Type.ENUM) { |
685 typeClass = ((RubyEnumDescriptor) getDescriptorForField(cont
ext, fieldDescriptor)).enummodule(context); | 704 typeClass = ((RubyEnumDescriptor) getDescriptorForField(cont
ext, fieldDescriptor)).enummodule(context); |
686 Descriptors.EnumDescriptor enumDescriptor = fieldDescriptor.
getEnumType(); | 705 Descriptors.EnumDescriptor enumDescriptor = fieldDescriptor.
getEnumType(); |
687 if (Utils.isRubyNum(value)) { | 706 if (Utils.isRubyNum(value)) { |
688 Descriptors.EnumValueDescriptor val = | 707 Descriptors.EnumValueDescriptor val = |
689 enumDescriptor.findValueByNumberCreatingIfUnknow
n(RubyNumeric.num2int(value)); | 708 enumDescriptor.findValueByNumberCreatingIfUnknow
n(RubyNumeric.num2int(value)); |
690 if (val.getIndex() != -1) value = context.runtime.newSym
bol(val.getName()); | 709 if (val.getIndex() != -1) value = context.runtime.newSym
bol(val.getName()); |
691 } | 710 } |
692 } | 711 } |
693 if (addValue) { | 712 if (addValue) { |
694 Utils.checkType(context, fieldType, value, (RubyModule) type
Class); | 713 value = Utils.checkType(context, fieldType, value, (RubyModu
le) typeClass); |
695 this.fields.put(fieldDescriptor, value); | 714 this.fields.put(fieldDescriptor, value); |
696 } else { | 715 } else { |
697 this.fields.remove(fieldDescriptor); | 716 this.fields.remove(fieldDescriptor); |
698 } | 717 } |
699 } | 718 } |
700 } | 719 } |
701 return context.runtime.getNil(); | 720 return context.runtime.getNil(); |
702 } | 721 } |
703 | 722 |
704 private String layoutInspect() { | 723 private String layoutInspect() { |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
756 private DynamicMessage.Builder builder; | 775 private DynamicMessage.Builder builder; |
757 private RubyClass cRepeatedField; | 776 private RubyClass cRepeatedField; |
758 private RubyClass cMap; | 777 private RubyClass cMap; |
759 private Map<Descriptors.FieldDescriptor, RubyRepeatedField> repeatedFields; | 778 private Map<Descriptors.FieldDescriptor, RubyRepeatedField> repeatedFields; |
760 private Map<Descriptors.FieldDescriptor, RubyMap> maps; | 779 private Map<Descriptors.FieldDescriptor, RubyMap> maps; |
761 private Map<Descriptors.FieldDescriptor, IRubyObject> fields; | 780 private Map<Descriptors.FieldDescriptor, IRubyObject> fields; |
762 private Map<Descriptors.OneofDescriptor, Descriptors.FieldDescriptor> oneofC
ases; | 781 private Map<Descriptors.OneofDescriptor, Descriptors.FieldDescriptor> oneofC
ases; |
763 | 782 |
764 private static final int SINK_MAXIMUM_NESTING = 64; | 783 private static final int SINK_MAXIMUM_NESTING = 64; |
765 } | 784 } |
OLD | NEW |