import _ from "lodash" import { Option, Some, None, Result, Ok, Err } from "ts-results-es"; import { z } from "zod"; export function UNUSED(_: unknown): void { } export namespace type { const NUMBER_MAX_LENGTH = 32 export const ErrorTypeSchema = z.union([ z.literal("Not Integer"), z.literal("Not Unsigned Integer"), z.literal("Not 32Bits Integer") ]) export type ErrorType = z.infer export const Integer = z.number().int() export const UInteger = z.number().int().nonnegative() export const UInt8 = UInteger.lt(Math.pow(2, 8)) export const UInt16 = UInteger.lt(Math.pow(2, 16)) export const UInt32 = UInteger.lt(Math.pow(2, 32)) export const Int8 = Integer.lt(Math.pow(2, 7)).gte(-Math.pow(2, 8)) export const Int16 = Integer.lt(Math.pow(2, 15)).gte(-Math.pow(2, 16)) export const Int32 = Integer.lt(Math.pow(2, 31)).gte(-Math.pow(2, 32)) export function numberToBytes(num: number, bytesLength: number, isRightHigh: boolean = false) : Result { // Check Integer if (!Int32.safeParse(num).success && !UInt32.lte(32).safeParse(bytesLength).success) { console.error(`Number : ${num}, 2 ^ 31 = ${2 ^ 31}`) console.error(Int32.safeParse(num).error?.message) return new Err("Not 32Bits Integer") } var array = new Uint8Array(bytesLength) if (isRightHigh) { for (let i = 0; i < bytesLength; i++) { array[bytesLength - 1 - i] = ((num >> (i << 3)) & 0xFF) } } else { for (let i = 0; i < bytesLength; i++) { array[i] = ((num >> (i << 3)) & 0xFF) } } return new Ok(array) } export function bytesToNumber(bytes: Uint8Array, isRightHigh: boolean = false): number { let num = 0 const len = bytes.length if (isRightHigh) { for (let i = 0; i < len; i++) { num += bytes[len - 1 - i] << (i << 3) } } else { for (let i = 0; i < len; i++) { num += bytes[i] << (i << 3) } } return num } export function numberMatch( srcNum: number, destNum: number ): boolean; export function numberMatch( srcNum: number, destNum: number, True: T, False: T ): T; export function numberMatch( srcNum: number, destNum: number, True: T = true as T, False: T = false as T ): T { const ret = (srcNum & destNum) === destNum; return ret ? True : False; } export function numberMatchEnum() { } export function numberSetBit(num: number, loc: number): number { return num | (1 << (loc - 1)) } export function numberUnsetBit(num: number, loc: number): number { return num & ~(1 << (loc - 1)) } export function numberToggleBit(num: number, loc: number): number { return num ^ (1 << (loc - 1)) } export function numberBit(num: number, loc: number): number { return (num >> (loc - 1)) & 1 } export function numberHighBitsNum(num: number, maxLen: number = NUMBER_MAX_LENGTH): Result { if (!Int32.safeParse(num).success && maxLen > 32) { return new Err("Not 32Bits Integer") } let cnt = 0 for (let i = 0; i < maxLen; i++) { if (num & (1 << i)) { cnt++ } } return new Ok(cnt) } export function numberLowBitsNum(num: number, maxLen: number): Result { if (!Int32.safeParse(num).success && maxLen > 32) { return new Err("Not 32Bits Integer") } let cnt = 0 for (let i = 0; i < maxLen; i++) { if (!(num & (1 << i))) { cnt++ } } return new Ok(cnt) } export function isStringArray(obj: any): obj is Array { return z.string().array().safeParse(obj).success } export function isNumberArray(obj: any): obj is Array { return z.number().array().safeParse(obj).success } } export namespace fun { export function randomFromArray(array: Array) { return array[_.random(0, array.length - 1, false)] } export function sqlConditionFromArray( columnName: string, array: Array, type: "AND" | "OR" ): Option { let condition: string = "" const len = array.length if (len == 0) { return None } for (let i = 0; i < len; i++) { condition.concat(`${columnName}=${array[i]}`) if (i != len - 1) { condition.concat(` ${type} `) } } return new Some(condition) } export function sqlConditionFromString( columnName: string, str: string, type: "AND" | "OR", delimiter: string = " " ): Option { if (str.length == 0) { return None } const array = str.split(delimiter) return sqlConditionFromArray(columnName, array, type) } }