import {assert} from './asserts';import {encode} from './base32-encode';import type {ReadonlyJSONValue} from './json';import * as utf8 from './utf8';
export const BYTE_LENGTH = 20;
export const STRING_LENGTH = 32;
declare const hashTag: unique symbol;
export type Hash = {[hashTag]: true};
const hashRe = /^[0-9a-v]{32}$/;const tempHashRe = /^t\/[0-9a-v]{30}$/;
export async function hashOf(value: ReadonlyJSONValue): Promise<Hash> { const typedArray = utf8.encode(JSON.stringify(value)); const buf = await crypto.subtle.digest('SHA-512', typedArray); const buf2 = new Uint8Array(buf, 0, BYTE_LENGTH); return encode(buf2) as unknown as Hash;}
export function parse(s: string): Hash { assertHash(s); return s;}
export const emptyHash = '00000000000000000000000000000000' as unknown as Hash;
export const newTempHash = makeNewTempHashFunction();
export function makeNewTempHashFunction(): () => Hash { return makeNewFakeHashFunction('t/');}
export function makeNewFakeHashFunction(hashPrefix: string): () => Hash { let tempHashCounter = 0; return () => { return (hashPrefix + (tempHashCounter++) .toString() .padStart(STRING_LENGTH - hashPrefix.length, '0')) as unknown as Hash; };}
export function isHash(v: unknown): v is Hash { return typeof v === 'string' && (hashRe.test(v) || tempHashRe.test(v));}
export function isTempHash(v: unknown): v is Hash { return typeof v === 'string' && tempHashRe.test(v);}
export function assertNotTempHash(hash: Hash): void { if (tempHashRe.test(hash as unknown as string)) { throw new Error('Unexpected temp hash'); }}
export function assertHash(v: unknown): asserts v is Hash { if (!isHash(v)) { throw new Error(`Invalid hash: '${v}'`); }}
export function fakeHash(s: string): Hash { const fake = 'fake'; assert( /^[a-v0-9]*$/.test(s), `Fake hash must be a valid substring of a hash: ${s}`, ); assert(s.length <= STRING_LENGTH - fake.length, 'Fake hash is too long'); return (fake + s.padStart(STRING_LENGTH - fake.length, '0')) as unknown as Hash;}