Source

shared/math.ts

import { stringFormat } from "@decaf-ts/decorator-validation";
import { OverflowError } from "./errors";
import { ValidationError } from "@decaf-ts/db-decorators";

/**
 * @description Overflow-safe addition operation
 * @summary Adds two numbers and verifies no overflow by reverse-checking the operands
 * @param {number} a - First operand
 * @param {number} b - Second operand
 * @return {number} The sum of a and b
 * @function add
 * @throws {OverflowError} on addition overflow
 * @memberOf module:for-fabric.shared
 */
export function add(a: number, b: number): number {
  const c = a + b;
  if (a !== c - b || b !== c - a) {
    throw new OverflowError(`Addition overflow: ${a} + ${b}`);
  }
  return c;
}

/**
 * @description Overflow-safe subtraction operation
 * @summary Subtracts b from a and validates no overflow by reverse-checking the operands
 * @param {number} a - Minuend
 * @param {number} b - Subtrahend
 * @return {number} The difference a - b
 * @function sub
 * @throws {OverflowError} on subtaction overflow
 * @memberOf module:for-fabric.shared
 */
export function sub(a: number, b: number): number {
  const c = a - b;
  if (a !== c + b || b !== a - c) {
    throw new OverflowError(`Subtraction overflow: ${a} - ${b}`);
  }
  return c;
}

/**
 * @summary Safe Integer Parse
 *
 * @param {string} string
 *
 * @function safeParseInt
 *
 * @throws {ValidationError} if parseInt returns NaN
 *
 * @memberOf module:for-fabric.shared
 */
export function safeParseInt(string: string): number {
  // Regular expression to check if string only have digits
  const digitRegex = /^\d+$/;
  if (!digitRegex.test(string)) {
    throw new ValidationError(
      stringFormat("Failed to parse: {0}", "string contains digits")
    );
  }
  const parsedint = parseInt(string);
  if (isNaN(parsedint)) {
    throw new ValidationError(
      stringFormat("Failed to parse: {0}", "string is not a parsable integer")
    );
  }
  return parsedint;
}