Quantity.java
/*
* Copyright ConsenSys AG.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.besu.ethereum.api.jsonrpc.internal.results;
import java.math.BigInteger;
import java.util.Objects;
import org.apache.tuweni.bytes.Bytes;
import org.apache.tuweni.bytes.Bytes32;
import org.apache.tuweni.units.bigints.UInt256;
import org.apache.tuweni.units.bigints.UInt256Value;
import org.apache.tuweni.units.bigints.UInt64Value;
/**
* Utility for formatting "quantity" fields and results to be returned. Quantity fields are
* represented as minimal length hex strings with no zero-padding. There is one exception to this
* rule: quantities equal to zero are represented by the hex string "0x0".
*/
public class Quantity {
private static final String HEX_PREFIX = "0x";
public static final String HEX_ZERO = "0x0";
private Quantity() {}
public static String create(final UInt256Value<?> value) {
return uint256ToHex(value);
}
public static String create(final UInt64Value<?> value) {
return (value == null || value.isZero()) ? HEX_ZERO : value.toMinimalBytes().toShortHexString();
}
public static String create(final int value) {
return uint256ToHex(UInt256.valueOf(value));
}
public static String create(final long value) {
return uint256ToHex(UInt256.fromHexString(Long.toHexString(value)));
}
public static String create(final Bytes value) {
return create(value.toArrayUnsafe());
}
public static String create(final byte[] value) {
return uint256ToHex(UInt256.fromBytes(Bytes32.leftPad(Bytes.wrap(value))));
}
public static String create(final BigInteger value) {
return uint256ToHex(UInt256.valueOf(value));
}
public static String create(final byte value) {
return formatMinimalValue(Integer.toHexString(value));
}
/**
* Fixed-length bytes sequences and should be returned as hex strings zero-padded to the expected
* length.
*
* @param val the value to encode in the string
* @param byteLength the number of bytes to be represented in the output string.
* @return A zero-padded string containing byteLength * 2 characters, not including the 0x prefix
*/
public static String longToPaddedHex(final long val, final int byteLength) {
final String formatted = Long.toHexString(val);
final String zeroPadding = "0".repeat(byteLength * 2 - formatted.length());
return String.format("%s%s%s", HEX_PREFIX, zeroPadding, formatted);
}
/**
* Checks if value is prefixed with '0x'
*
* @param value that is checked
* @return true if value is prefixed with '0x', false otherwise
*/
public static boolean isValid(final String value) {
return value.startsWith(HEX_PREFIX);
}
private static String uint256ToHex(final UInt256Value<?> value) {
return value == null ? null : formatMinimalValue(value.toMinimalBytes().toShortHexString());
}
private static String formatMinimalValue(final String hexValue) {
final String prefixedHexString = prefixHexNotation(hexValue);
return Objects.equals(prefixedHexString, HEX_PREFIX) ? HEX_ZERO : prefixedHexString;
}
private static String prefixHexNotation(final String hexValue) {
return hexValue.startsWith(HEX_PREFIX) ? hexValue : HEX_PREFIX + hexValue;
}
}