diff --git a/web3.js/src/util/encoding.js b/web3.js/src/util/encoding.js new file mode 100644 index 0000000000..16b9817a72 --- /dev/null +++ b/web3.js/src/util/encoding.js @@ -0,0 +1,32 @@ +// @flow + +export function decodeLength(bytes: Array): number { + let len = 0; + let size = 0; + // eslint-disable-next-line no-constant-condition + while (true) { + let elem = bytes.shift(); + len |= (elem & 0x7f) << (size * 7); + size += 1; + if ((elem & 0x80) === 0) { + break; + } + } + return len; +} + +export function encodeLength(bytes: Array, len: number) { + let rem_len = len; + // eslint-disable-next-line no-constant-condition + while (true) { + let elem = rem_len & 0x7f; + rem_len >>= 7; + if (rem_len == 0) { + bytes.push(elem); + break; + } else { + elem |= 0x80; + bytes.push(elem); + } + } +} diff --git a/web3.js/test/shortvec-encoding.test.js b/web3.js/test/shortvec-encoding.test.js new file mode 100644 index 0000000000..e3b2fa980c --- /dev/null +++ b/web3.js/test/shortvec-encoding.test.js @@ -0,0 +1,71 @@ +// @flow + +import {decodeLength, encodeLength} from '../src/util/shortvec-encoding'; + +function checkDecodedArray(array: Array, expectedValue: number) { + expect(decodeLength(array)).toEqual(expectedValue); + expect(array.length).toEqual(0); +} + +test('shortvec decodeLength', () => { + let array = []; + checkDecodedArray(array, 0); + + array = [5]; + checkDecodedArray(array, 5); + + array = [0x7f]; + checkDecodedArray(array, 0x7f); + + array = [0x80, 0x01]; + checkDecodedArray(array, 0x80); + + array = [0xff, 0x01]; + checkDecodedArray(array, 0xff); + + array = [0x80, 0x02]; + checkDecodedArray(array, 0x100); + + array = [0xff, 0xff, 0x01]; + checkDecodedArray(array, 0x7fff); + + array = [0x80, 0x80, 0x80, 0x01]; + checkDecodedArray(array, 0x200000); +}); + +function checkEncodedArray( + array: Array, + len: number, + prevLength: number, + addedLength: number, + expectedArray: Array, +) { + encodeLength(array, len); + expect(array.length).toEqual(prevLength); + expect(array.slice(-addedLength)).toEqual(expectedArray); +} + +test('shortvec encodeLength', () => { + let array = []; + let prevLength = 1; + checkEncodedArray(array, 0, prevLength, 1, [0]); + + checkEncodedArray(array, 5, (prevLength += 1), 1, [5]); + + checkEncodedArray(array, 0x7f, (prevLength += 1), 1, [0x7f]); + + checkEncodedArray(array, 0x80, (prevLength += 2), 2, [0x80, 0x01]); + + checkEncodedArray(array, 0xff, (prevLength += 2), 2, [0xff, 0x01]); + + checkEncodedArray(array, 0x100, (prevLength += 2), 2, [0x80, 0x02]); + + checkEncodedArray(array, 0x7fff, (prevLength += 3), 3, [0xff, 0xff, 0x01]); + + prevLength = checkEncodedArray(array, 0x200000, (prevLength += 4), 4, [ + 0x80, + 0x80, + 0x80, + 0x01, + ]); +});