@0x/contracts-test-utils: Allow hexSlice() to take negative numbers, and a range.

This commit is contained in:
Lawrence Forman 2019-09-13 14:07:49 -04:00 committed by Lawrence Forman
parent 6a8242a6ca
commit 58a5ab4550
2 changed files with 26 additions and 9 deletions

View File

@ -81,6 +81,10 @@
{ {
"note": "Add `Numberish` type.", "note": "Add `Numberish` type.",
"pr": 2131 "pr": 2131
},
{
"note": "Tweaks/Upgrades to `hex_utils`, most notably `hexSlice()`",
"pr": "TODO"
} }
] ]
}, },

View File

@ -3,6 +3,7 @@ import * as crypto from 'crypto';
import * as ethUtil from 'ethereumjs-util'; import * as ethUtil from 'ethereumjs-util';
import { constants } from './constants'; import { constants } from './constants';
import { Numberish } from './types';
const { WORD_LENGTH } = constants; const { WORD_LENGTH } = constants;
const WORD_CEIL = new BigNumber(2).pow(WORD_LENGTH * 8); const WORD_CEIL = new BigNumber(2).pow(WORD_LENGTH * 8);
@ -24,39 +25,44 @@ export function hexRandom(size: number = WORD_LENGTH): string {
/** /**
* Left-pad a hex number to a number of bytes. * Left-pad a hex number to a number of bytes.
*/ */
export function hexLeftPad(n: string | BigNumber | number, size: number = WORD_LENGTH): string { export function hexLeftPad(n: Numberish, size: number = WORD_LENGTH): string {
return ethUtil.bufferToHex(ethUtil.setLengthLeft(toHex(n), size)); return ethUtil.bufferToHex(ethUtil.setLengthLeft(toHex(n), size));
} }
/** /**
* Right-pad a hex number to a number of bytes. * Right-pad a hex number to a number of bytes.
*/ */
export function hexRightPad(n: string | BigNumber | number, size: number = WORD_LENGTH): string { export function hexRightPad(n: Numberish, size: number = WORD_LENGTH): string {
return ethUtil.bufferToHex(ethUtil.setLengthRight(toHex(n), size)); return ethUtil.bufferToHex(ethUtil.setLengthRight(toHex(n), size));
} }
/** /**
* Inverts a hex word. * Inverts a hex word.
*/ */
export function hexInvert(n: string | BigNumber | number, size: number = WORD_LENGTH): string { export function hexInvert(n: Numberish, size: number = WORD_LENGTH): string {
const buf = ethUtil.setLengthLeft(toHex(n), size); const buf = ethUtil.setLengthLeft(toHex(n), size);
// tslint:disable-next-line: no-bitwise // tslint:disable-next-line: no-bitwise
return ethUtil.bufferToHex(Buffer.from(buf.map(b => ~b))); return ethUtil.bufferToHex(Buffer.from(buf.map(b => ~b)));
} }
/** /**
* Slices off the desired number of bytes from a hex number. * Slices a hex number.
*/ */
export function hexSlice(n: string | BigNumber | number, size: number): string { export function hexSlice(n: Numberish, start: number, end?: number): string {
const hex = toHex(n); const hex = toHex(n).substr(2);
return '0x'.concat(toHex(n).slice(size * 2 + 2, hex.length)); const sliceStart = start >= 0 ? start * 2 : Math.max(0, hex.length + start * 2);
let sliceEnd = hex.length;
if (end !== undefined) {
sliceEnd = end >= 0 ? end * 2 : Math.max(0, hex.length + end * 2);
}
return '0x'.concat(hex.substring(sliceStart, sliceEnd));
} }
/** /**
* Convert a string, a number, or a BigNumber into a hex string. * Convert a string, a number, or a BigNumber into a hex string.
* Works with negative numbers, as well. * Works with negative numbers, as well.
*/ */
export function toHex(n: string | BigNumber | number, size: number = WORD_LENGTH): string { export function toHex(n: Numberish, size: number = WORD_LENGTH): string {
if (typeof n === 'string' && /^0x[0-9a-f]+$/i.test(n)) { if (typeof n === 'string' && /^0x[0-9a-f]+$/i.test(n)) {
// Already a hex. // Already a hex.
return n; return n;
@ -64,7 +70,14 @@ export function toHex(n: string | BigNumber | number, size: number = WORD_LENGTH
let _n = new BigNumber(n); let _n = new BigNumber(n);
if (_n.isNegative()) { if (_n.isNegative()) {
// Perform two's-complement. // Perform two's-complement.
_n = new BigNumber(hexInvert(toHex(_n.abs()), size).substr(2), 16).plus(1).mod(WORD_CEIL); // prettier-ignore
_n = new BigNumber(
hexInvert(
toHex(_n.abs()),
size,
).substr(2),
16,
).plus(1).mod(WORD_CEIL);
} }
return `0x${_n.toString(16)}`; return `0x${_n.toString(16)}`;
} }