string/hashString.ts

/** @module String */

import { isStr } from './isStr'
import { isNonNegative } from '@number/isNonNegative'
/**
 * Creates a hash from a passed in string consistently
 * <br/>Not intended to be secure
 * <br/>Value comes from being a pure function
 * <br/>Given the same input, it will always return the same output
 * <br/>There is no expectation to convert back from the hash to the original string
 * @function
 * @param {String} str - String to be hashed
 * @param {number=} maxLength - Max length of the returned hash
 *
 * @returns {String} - Hashed version of the string
 */
export const hashString = <T extends string = string>(
  str: string,
  maxLength?: number
): T => {
  if (!isStr(str) || str.length == 0) return `0` as T

  str = str.split('').reverse().join('')

  let hash: any = 0
  for (let i = 0; i < str.length; i++) {
    const char = str.charCodeAt(i)
    hash = (hash << 5) - hash + char
    // Convert to positive 32bit integer
    hash = `${Math.abs(hash & hash)}`
  }

  return isNonNegative(maxLength)
    ? (hash.slice(0, maxLength) as T)
    : (hash as T)
}