-
Notifications
You must be signed in to change notification settings - Fork 10
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
refactor: create HexUInt32 class (#1776)
* refactor: create HexUInt32 class * refactor: add extra check length in test * refactor: add method to validate length
- Loading branch information
1 parent
ff326dc
commit f8699f2
Showing
2 changed files
with
121 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
import { InvalidDataType } from '@vechain/sdk-errors'; | ||
import { type HexInt } from './HexInt'; | ||
import { HexUInt } from './HexUInt'; | ||
|
||
/** | ||
* Represents a 32-byte hexadecimal unsigned integer. | ||
* | ||
* @extends HexUInt | ||
*/ | ||
class HexUInt32 extends HexUInt { | ||
/** | ||
* Expected byte length. | ||
* @type {number} | ||
*/ | ||
private static readonly BYTE_LENGTH = 32; | ||
|
||
/** | ||
* Regular expression for matching 32 bytes hexadecimal strings. | ||
* An empty input is represented as a empty digits. | ||
* | ||
* @type {RegExp} | ||
*/ | ||
private static readonly REGEX_HEXUINT32: RegExp = /^(0x)?[0-9a-f]{64}$/i; | ||
|
||
/** | ||
* Checks if the given string expression is a valid 32 bytes unsigned hexadecimal value. | ||
* | ||
* @param {string} exp - The string representation of a hexadecimal value. | ||
* | ||
* @return {boolean} - True if the expression is a valid 32 bytes unsigned hexadecimal value, case-insensitive, | ||
* optionally prefixed with `0x`; false otherwise. | ||
*/ | ||
public static isValid(exp: string): boolean { | ||
return HexUInt32.REGEX_HEXUINT32.test(exp); | ||
} | ||
|
||
/** | ||
* Ensures the hexadecimal string representation is 32 bytes long. | ||
* @param {string} hexString - The hexadecimal string to validate. | ||
* @returns {string} The 32 bytes long hexadecimal string. | ||
*/ | ||
private static convertTo32Bytes(hexString: string): string { | ||
const nonPrefixedHex = hexString.replace(/^0x/, ''); | ||
|
||
return nonPrefixedHex.padStart(this.BYTE_LENGTH * 2, '0'); | ||
} | ||
|
||
/** | ||
* Creates a HexUInt32 instance with enforced 32 bytes length. | ||
* @param {bigint | number | string | Uint8Array | HexInt} exp - The expression to convert. | ||
* @returns {HexUInt32} The HexUInt32 object representing the given expression. | ||
* @throws {InvalidDataType} If the value is not a valid 32-byte hex string. | ||
*/ | ||
public static of( | ||
exp: bigint | number | string | Uint8Array | HexInt | ||
): HexUInt32 { | ||
try { | ||
const hexUInt = HexUInt.of(exp); | ||
|
||
const hexDigits = this.convertTo32Bytes(hexUInt.toString()); | ||
|
||
return new HexUInt32(hexUInt.sign, hexDigits); | ||
} catch (e) { | ||
throw new InvalidDataType( | ||
'HexUInt32.of', | ||
'not a 32 bytes long hexadecimal positive integer expression', | ||
{ exp: `${exp}`, e }, | ||
e | ||
); | ||
} | ||
} | ||
} | ||
|
||
export { HexUInt32 }; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
import { describe, expect, test } from '@jest/globals'; | ||
import { InvalidDataType } from '@vechain/sdk-errors'; | ||
import { HexUInt32 } from '../../src/vcdm/HexUInt32'; | ||
|
||
/** | ||
* Test HexUInt32 class. | ||
* @group unit/vcdm | ||
*/ | ||
describe('HexUInt32 class tests', () => { | ||
describe('Construction tests', () => { | ||
test('Return an HexUInt32 instance of the provided expression', () => { | ||
const expression = '0xcaffee'; | ||
const expectedHexUInt32 = | ||
'0x0000000000000000000000000000000000000000000000000000000000caffee'; | ||
|
||
const hexUInt32 = HexUInt32.of(expression); | ||
|
||
expect(hexUInt32).toBeInstanceOf(HexUInt32); | ||
expect(hexUInt32.toString()).toEqual(expectedHexUInt32); | ||
}); | ||
|
||
test('Checks if the provided expression is a valid 32 bytes unsigned hexadecimal value', () => { | ||
const expression = | ||
'0x0000000000000000000000000000000000000000000000000000000000caffee'; | ||
|
||
expect(HexUInt32.isValid(expression)).toBeTruthy(); | ||
}); | ||
|
||
test('Throw an error if the provided argument is not an unsigned expression', () => { | ||
const exp = '-0xnotUnsigned'; | ||
expect(() => HexUInt32.of(exp)).toThrow(InvalidDataType); | ||
}); | ||
}); | ||
|
||
describe('Polymorphism equivalence', () => { | ||
test('Equal for bigint, bytes, hex expression, number', () => { | ||
const ofBigInt = HexUInt32.of(255n); | ||
const ofBytes = HexUInt32.of(Uint8Array.of(255)); | ||
const ofHex = HexUInt32.of('0xff'); | ||
const ofNumber = HexUInt32.of(255); | ||
expect(ofBigInt.toString()).toHaveLength(66); | ||
expect(ofBigInt.isEqual(ofBytes)).toBeTruthy(); | ||
expect(ofBytes.isEqual(ofHex)).toBeTruthy(); | ||
expect(ofHex.isEqual(ofNumber)).toBeTruthy(); | ||
}); | ||
}); | ||
}); |
f8699f2
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Test Coverage
Summary