import { MultiSetCounter } from '../index' /** * Implement this interface to support the use of different hash functions. Note that * your backend will need to be registered using `HasherFactory.register(..)` before * it can be used. */ export interface Hasher { /** * Generate hash of the provided string. */ hash(val: string): V /** * Returns the number of consecutive zeros in the provided hash value. * @param hashVal The hash value as computed by the `hash(..)` method. */ runLength(hashVal: V): number /** * Determine the register index for a given hash value. * @param hashVal The hash value as computed by the `hash(..)` method. */ regIdx(hashVal: V): number /** * Returns the length, in bits, of hash values generated by this `Hasher`. */ readonly hashLen: number /** * The unique name of this `Hasher` implementation. Used to ensure counters * are compatible before merging, as well as to instantiate the proper backend * when deserializing. */ readonly hasherId: string /** Maximum number of register bits supported by a `Hasher` implementation */ readonly maxPrecision: number } interface HasherFactoryImpl { new(counter: MultiSetCounter): Hasher } export class HasherFactory { private static factories: Map = new Map() /** * Used to register custom backends so that they may be instantiated given their unique id * (see `Options.hasherId`). See the `Jenkins32` class for an example of how to register your backend. */ static register(hasherId: string, f: HasherFactoryImpl) { if (HasherFactory.factories.has(hasherId)) console.warn(`[HyperLogLog] HasherFactory '${hasherId}' is already registered and will be overwritten`) this.factories.set(hasherId, f) } /** * Builds a `Hasher` instance given it's `hasherId` and the counter it will be used with. This is * used internally by `HyperLogLog` during construction and deserialization. */ static build(hasherId: string, counter: MultiSetCounter): Hasher { if (!HasherFactory.factories.has(hasherId)) console.warn(`[HyperLogLog] HasherFactory '${hasherId}' doesn't exist or hasn't been registered with the HasherFactory! See HasherFactory.register(..)`) const ctor = HasherFactory.factories.get(hasherId) return new ctor(counter) } }