Coverage Summary for Class: ABICallSpec (co.rsk.peg)
Class |
Method, %
|
Line, %
|
ABICallSpec |
0%
(0/11)
|
0%
(0/37)
|
ABICallSpec$1 |
0%
(0/2)
|
0%
(0/4)
|
Total |
0%
(0/13)
|
0%
(0/41)
|
1 /*
2 * This file is part of RskJ
3 * Copyright (C) 2017 RSK Labs Ltd.
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU Lesser General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 package co.rsk.peg;
20
21 import com.google.common.primitives.SignedBytes;
22
23 import java.nio.charset.StandardCharsets;
24 import java.util.Arrays;
25 import java.util.Comparator;
26 import java.util.Objects;
27
28 /**
29 * Immutable representation of a function call
30 * spec to any given contract.
31 * For simplicity, each of the arguments is assumed to be a byte array.
32 * Encoding is up to the user.
33 *
34 * @author Ariel Mendelzon
35 */
36 public final class ABICallSpec {
37 public static final Comparator<ABICallSpec> byBytesComparator = new Comparator<ABICallSpec>() {
38 @Override
39 public int compare(ABICallSpec specA, ABICallSpec specB) {
40 return SignedBytes.lexicographicalComparator().compare(
41 specA.getEncoded(),
42 specB.getEncoded()
43 );
44 }
45 };
46
47 private String function;
48 private byte[][] arguments;
49
50 public ABICallSpec(String function, byte[][] arguments) {
51 this.function = function;
52 // Keep internal copies, so that the instance
53 // is immutable
54 this.arguments = copy(arguments);
55 }
56
57 public String getFunction() {
58 return function;
59 }
60
61 public byte[][] getArguments() {
62 return copy(arguments);
63 }
64
65 public byte[] getEncoded() {
66 byte[] functionBytes = function.getBytes(StandardCharsets.UTF_8);
67 int totalLength = functionBytes.length;
68 for (int i = 0; i < arguments.length; i++) {
69 totalLength += arguments[i].length;
70 }
71 byte[] result = new byte[totalLength];
72 System.arraycopy(functionBytes, 0, result, 0, functionBytes.length);
73 int offset = functionBytes.length;
74 for (int i = 0; i < arguments.length; i++) {
75 System.arraycopy(arguments[i], 0, result, offset, arguments[i].length);
76 offset += arguments[i].length;
77 }
78 return result;
79 }
80
81 @Override
82 public String toString() {
83 return String.format("Call to %s with %d arguments", function, arguments.length);
84 }
85
86 @Override
87 public boolean equals(Object other) {
88 if (this == other) {
89 return true;
90 }
91
92 if (other == null || this.getClass() != other.getClass()) {
93 return false;
94 }
95
96 ABICallSpec otherSpec = ((ABICallSpec) other);
97 return otherSpec.getFunction().equals(getFunction()) &&
98 areEqual(arguments, otherSpec.arguments);
99 }
100
101 @Override
102 public int hashCode() {
103 int[] argumentsHashes = Arrays.stream(arguments).map(argument -> Arrays.hashCode(argument)).mapToInt(Integer::intValue).toArray();
104 return Objects.hash(function, Arrays.hashCode(argumentsHashes));
105 }
106
107 private boolean areEqual(byte[][] first, byte[][] second) {
108 if (first.length != second.length) {
109 return false;
110 }
111
112 for (int i = 0; i < first.length; i++) {
113 if (!Arrays.equals(first[i], second[i])) {
114 return false;
115 }
116 }
117
118 return true;
119 }
120
121 private byte[][] copy(byte[][] array) {
122 byte[][] result = new byte[array.length][];
123 for (int i = 0; i < array.length; i++) {
124 result[i] = Arrays.copyOf(array[i], array[i].length);
125 }
126 return result;
127 }
128 }