forked from tornado-packages/noble-curves
utils: fix hexToNumber, improve validateObject
This commit is contained in:
parent
4780850748
commit
e14af67254
@ -35,7 +35,7 @@ export function numberToHexUnpadded(num: number | bigint): string {
|
|||||||
export function hexToNumber(hex: string): bigint {
|
export function hexToNumber(hex: string): bigint {
|
||||||
if (typeof hex !== 'string') throw new Error('string expected, got ' + typeof hex);
|
if (typeof hex !== 'string') throw new Error('string expected, got ' + typeof hex);
|
||||||
// Big Endian
|
// Big Endian
|
||||||
return BigInt(`0x${hex}`);
|
return BigInt(hex === '' ? '0' : `0x${hex}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Caching slows it down 2-3x
|
// Caching slows it down 2-3x
|
||||||
@ -114,31 +114,47 @@ export const bitSet = (n: bigint, pos: number, value: boolean) =>
|
|||||||
// Not using ** operator with bigints for old engines.
|
// Not using ** operator with bigints for old engines.
|
||||||
export const bitMask = (n: number) => (_2n << BigInt(n - 1)) - _1n;
|
export const bitMask = (n: number) => (_2n << BigInt(n - 1)) - _1n;
|
||||||
|
|
||||||
type ValMap = Record<string, string>;
|
const validatorFns = {
|
||||||
export function validateObject(object: object, validators: ValMap, optValidators: ValMap = {}) {
|
bigint: (val: any) => typeof val === 'bigint',
|
||||||
const validatorFns: Record<string, (val: any) => boolean> = {
|
function: (val: any) => typeof val === 'function',
|
||||||
bigint: (val) => typeof val === 'bigint',
|
boolean: (val: any) => typeof val === 'boolean',
|
||||||
function: (val) => typeof val === 'function',
|
string: (val: any) => typeof val === 'string',
|
||||||
boolean: (val) => typeof val === 'boolean',
|
isSafeInteger: (val: any) => Number.isSafeInteger(val),
|
||||||
string: (val) => typeof val === 'string',
|
array: (val: any) => Array.isArray(val),
|
||||||
isSafeInteger: (val) => Number.isSafeInteger(val),
|
field: (val: any, object: any) => (object as any).Fp.isValid(val),
|
||||||
array: (val) => Array.isArray(val),
|
hash: (val: any) => typeof val === 'function' && Number.isSafeInteger(val.outputLen),
|
||||||
field: (val) => (object as any).Fp.isValid(val),
|
} as const;
|
||||||
hash: (val) => typeof val === 'function' && Number.isSafeInteger(val.outputLen),
|
type Validator = keyof typeof validatorFns;
|
||||||
};
|
type ValMap<T extends Record<string, any>> = { [K in keyof T]?: Validator };
|
||||||
// type Key = keyof typeof validators;
|
// type Record<K extends string | number | symbol, T> = { [P in K]: T; }
|
||||||
const checkField = (fieldName: string, type: string, isOptional: boolean) => {
|
|
||||||
|
export function validateObject<T extends Record<string, any>>(
|
||||||
|
object: T,
|
||||||
|
validators: ValMap<T>,
|
||||||
|
optValidators: ValMap<T> = {}
|
||||||
|
) {
|
||||||
|
const checkField = (fieldName: keyof T, type: Validator, isOptional: boolean) => {
|
||||||
const checkVal = validatorFns[type];
|
const checkVal = validatorFns[type];
|
||||||
if (typeof checkVal !== 'function')
|
if (typeof checkVal !== 'function')
|
||||||
throw new Error(`Invalid validator "${type}", expected function`);
|
throw new Error(`Invalid validator "${type}", expected function`);
|
||||||
|
|
||||||
const val = object[fieldName as keyof typeof object];
|
const val = object[fieldName as keyof typeof object];
|
||||||
if (isOptional && val === undefined) return;
|
if (isOptional && val === undefined) return;
|
||||||
if (!checkVal(val)) {
|
if (!checkVal(val, object)) {
|
||||||
throw new Error(`Invalid param ${fieldName}=${val} (${typeof val}), expected ${type}`);
|
throw new Error(
|
||||||
|
`Invalid param ${String(fieldName)}=${val} (${typeof val}), expected ${type}`
|
||||||
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
for (let [fieldName, type] of Object.entries(validators)) checkField(fieldName, type, false);
|
for (const [fieldName, type] of Object.entries(validators)) checkField(fieldName, type!, false);
|
||||||
for (let [fieldName, type] of Object.entries(optValidators)) checkField(fieldName, type, true);
|
for (const [fieldName, type] of Object.entries(optValidators)) checkField(fieldName, type!, true);
|
||||||
return object;
|
return object;
|
||||||
}
|
}
|
||||||
|
// validate type tests
|
||||||
|
// const o: { a: number; b: number; c: number } = { a: 1, b: 5, c: 6 };
|
||||||
|
// const z0 = validateObject(o, { a: 'isSafeInteger' }, { c: 'bigint' }); // Ok!
|
||||||
|
// // Should fail type-check
|
||||||
|
// const z1 = validateObject(o, { a: 'tmp' }, { c: 'zz' });
|
||||||
|
// const z2 = validateObject(o, { a: 'isSafeInteger' }, { c: 'zz' });
|
||||||
|
// const z3 = validateObject(o, { test: 'boolean', z: 'bug' });
|
||||||
|
// const z4 = validateObject(o, { a: 'boolean', z: 'bug' });
|
||||||
|
Loading…
Reference in New Issue
Block a user