59 lines
1.3 KiB
TypeScript
59 lines
1.3 KiB
TypeScript
// Copyright 2024 Signal Messenger, LLC
|
|
// SPDX-License-Identifier: AGPL-3.0-only
|
|
import { strictAssert } from './assert';
|
|
|
|
export function safeParseNumber(value: number | string): number | null {
|
|
if (typeof value === 'number') {
|
|
return value;
|
|
}
|
|
strictAssert(typeof value === 'string', 'Expected string or number');
|
|
const trimmed = value.trim();
|
|
if (trimmed === '') {
|
|
return null;
|
|
}
|
|
const parsed = Number(value);
|
|
if (!Number.isFinite(parsed)) {
|
|
return null;
|
|
}
|
|
if (parsed < Number.MIN_SAFE_INTEGER || parsed > Number.MAX_SAFE_INTEGER) {
|
|
return null;
|
|
}
|
|
return parsed;
|
|
}
|
|
|
|
export function safeParseInteger(
|
|
value: number | string,
|
|
trunc = false
|
|
): number | null {
|
|
const parsed = safeParseNumber(value);
|
|
if (parsed == null) {
|
|
return null;
|
|
}
|
|
if (trunc) {
|
|
return Math.trunc(parsed);
|
|
}
|
|
if (!Number.isInteger(parsed)) {
|
|
return null;
|
|
}
|
|
return parsed;
|
|
}
|
|
|
|
export function safeParseBigint(
|
|
value: bigint | number | string
|
|
): bigint | null {
|
|
if (typeof value === 'bigint') {
|
|
return value;
|
|
}
|
|
if (typeof value === 'number') {
|
|
if (!Number.isInteger(value)) {
|
|
return null;
|
|
}
|
|
return BigInt(value);
|
|
}
|
|
strictAssert(typeof value === 'string', 'Expected string, number, or bigint');
|
|
const trimmed = value.trim();
|
|
if (trimmed === '') {
|
|
return null;
|
|
}
|
|
return BigInt(value);
|
|
}
|