From 42a21737648ac629af11a1781fb37c302c9801ff Mon Sep 17 00:00:00 2001 From: Rod Vagg Date: Fri, 4 Feb 2022 11:58:06 +1100 Subject: [PATCH] feat: formally expose MultihashHasher#encode It's always been there, and gets defined by the class, just not in the interface. SyncMultihashHasher hasn't had it, but in practice they all do have it (unless someone else has authored one since it was introduced that we don't know about). The addition to SyncMultihashHasher is technically breaking since it adds an additional burden to the API for implementers. But it's both very new, and the implementations (we're aware of) already implement with `encode()`. --- src/hashes/hasher.js | 10 +++++----- src/hashes/interface.ts | 23 +++++++++++++++++++++-- test/ts-use/src/main.ts | 38 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 64 insertions(+), 7 deletions(-) diff --git a/src/hashes/hasher.js b/src/hashes/hasher.js index 703e416b..2d1b43d4 100644 --- a/src/hashes/hasher.js +++ b/src/hashes/hasher.js @@ -1,5 +1,10 @@ import * as Digest from './digest.js' +/** + * @template T + * @typedef {import('./interface').Await} Await + */ + /** * @template {string} Name * @template {number} Code @@ -54,8 +59,3 @@ export class Hasher { * @template {number} Alg * @typedef {import('./interface').MultihashHasher} MultihashHasher */ - -/** - * @template T - * @typedef {Promise|T} Await - */ diff --git a/src/hashes/interface.ts b/src/hashes/interface.ts index 721745e8..f89db010 100644 --- a/src/hashes/interface.ts +++ b/src/hashes/interface.ts @@ -1,5 +1,7 @@ // # Multihash +export type Await = Promise | T + /** * Represents a multihash digest which carries information about the * hashing algorithm and an actual hash digest. @@ -37,14 +39,30 @@ export interface MultihashDigest { */ export interface MultihashHasher { /** - * Takes binary `input` and returns it (multi) hash digest. Return value is + * Takes binary `input` and returns it multihash digest. Return value is + * either promise of a digest or a digest. This way general use can `await` + * while performance critical code may asses return value to decide whether + * await is needed. + * + * @param {Uint8Array} input + */ + digest(input: Uint8Array): Await + + /** + * Takes binary `input` and returns it plain hash digest. Return value is * either promise of a digest or a digest. This way general use can `await` * while performance critical code may asses return value to decide whether * await is needed. * + * This is distinct from `digest()` which returns a multihash (prefixed) + * digest for this hasher as it only returns the encoded bytes that may + * otherwise be obtained from `digest().digest`. Only use `encode()` if you + * need to use this hasher as a standard hash digest generator; multihashes + * should otherwise be preferred. + * * @param {Uint8Array} input */ - digest(input: Uint8Array): Promise | MultihashDigest + encode(input: Uint8Array): Await /** * Name of the multihash @@ -69,4 +87,5 @@ export interface MultihashHasher { */ export interface SyncMultihashHasher extends MultihashHasher { digest(input: Uint8Array): MultihashDigest + encode(input: Uint8Array): Uint8Array } diff --git a/test/ts-use/src/main.ts b/test/ts-use/src/main.ts index d57c5688..278765d3 100644 --- a/test/ts-use/src/main.ts +++ b/test/ts-use/src/main.ts @@ -1,6 +1,11 @@ import * as Block from 'multiformats/block' import { sha256 } from 'multiformats/hashes/sha2' +import { identity } from 'multiformats/hashes/identity' import * as json from 'multiformats/codecs/json' +import { bytes } from 'multiformats' +import { MultihashHasher } from 'multiformats/hashes/hasher' +import { MultihashDigest } from 'multiformats/cid' +import { SyncMultihashHasher } from 'multiformats/hashes/interface' const main = async () => { const block = await Block.encode({ @@ -10,6 +15,39 @@ const main = async () => { }) console.log(block) + + console.log('async hasher') + await executeAsyncHasher(sha256, 'hash') + + console.log('sync hasher') + executeSyncHasher(identity, 'hash') +} + +async function executeAsyncHasher (hasher : MultihashHasher, input : string) { + const mhdigest : MultihashDigest = await hasher.digest(new TextEncoder().encode(input)) + const digest : Uint8Array = await hasher.encode(new TextEncoder().encode(input)) + console.log('multihash:', bytes.toHex(mhdigest.bytes)) + console.log('digest: ', bytes.toHex(digest)) + if (bytes.toHex(mhdigest.digest) !== bytes.toHex(digest)) { + throw new Error('busted interface') + } +} + +function executeSyncHasher (hasher : SyncMultihashHasher, input : string) { + const mhdigest : MultihashDigest = hasher.digest(new TextEncoder().encode(input)) + const digest : Uint8Array = hasher.encode(new TextEncoder().encode(input)) + console.log('multihash:', bytes.toHex(mhdigest.bytes)) + console.log('digest: ', bytes.toHex(digest)) + if (bytes.toHex(mhdigest.digest) !== bytes.toHex(digest)) { + throw new Error('busted interface') + } } export default main + +/* +main().catch((e) => { + console.error(e) + process.exit(1) +}) +*/