From 90c8afa7351f1bd769ddb3381655e3599bf9c4f2 Mon Sep 17 00:00:00 2001 From: Irakli Gozalishvili Date: Wed, 19 Jul 2023 10:29:04 -0700 Subject: [PATCH 1/5] feat: incremental-hasher --- src/hashes/interface.ts | 65 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 63 insertions(+), 2 deletions(-) diff --git a/src/hashes/interface.ts b/src/hashes/interface.ts index b7e9edf6..6be54993 100644 --- a/src/hashes/interface.ts +++ b/src/hashes/interface.ts @@ -9,7 +9,7 @@ // a bunch of places that parse it to extract (code, digest, size). By creating // this first class representation we avoid reparsing and things generally fit // really nicely. -export interface MultihashDigest { +export interface MultihashDigest { /** * Code of the multihash */ @@ -23,7 +23,7 @@ export interface MultihashDigest { /** * byte length of the `this.digest` */ - size: number + size: Size /** * Binary representation of this multihash digest. @@ -70,3 +70,64 @@ export interface MultihashHasher { export interface SyncMultihashHasher extends MultihashHasher { digest: (input: Uint8Array) => MultihashDigest } + +/** + * Incremental variant of the `MultihashHasher` that can be used to compute + * digest of the payloads that would be impractical or impossible to load all + * into a memory. + */ +export interface IncrementalMultihashHasher< + Code extends MulticodecCode, + Size extends number, + Digest = MultihashDigest +> { + /** + * Size of the digest this hasher produces. + */ + size: Size + + /** + * Code of the multihash + */ + code: Code + + /** + * Name of the multihash + */ + name: string + + /** + * Number of bytes that were consumed. + */ + count(): bigint + + /** + * Returns multihash digest of the bytes written so far. Should not have + * side-effects, meaning you should be able to write some more bytes and + * call `digest` again to get the digest for all the bytes written from + * creation (or from reset) + */ + digest(): Digest + + /** + * Computes the digest of the given input and writes it into the provided + * `output` at given `offset`. The `offset` is optional and if omitted is + * implicitly `0`. The optional `asMultihash` whith is implicitly `true`, + * can be use to control whether multihash prefix is written, if `false` + * only the raw digest writtend omitting the prefix. + */ + digestInto(output: Uint8Array, offset?: number, asMultihash?: boolean): this + + /** + * Writes bytes to be digested. + */ + write(bytes: Uint8Array): this + + /** + * Resets this hasher to its initial state. Can be used to recycle this + * instance. It resets `count` and and discards all the bytes that were + * written prior. + */ + reset(): this +} + From 83513a84913786ef16f656860b30ad53c246db5a Mon Sep 17 00:00:00 2001 From: Irakli Gozalishvili Date: Wed, 19 Jul 2023 10:36:09 -0700 Subject: [PATCH 2/5] add MulticodecCode type --- src/block/interface.ts | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/block/interface.ts b/src/block/interface.ts index df583589..d595e89f 100644 --- a/src/block/interface.ts +++ b/src/block/interface.ts @@ -35,6 +35,22 @@ export interface Phantom { [Marker]?: T } +/** + * [Multicodec code] usually used to tag [multiformat]. It is simply an Integer that + * utilizes `Phantom` type to capture code name which typescript aware tools will + * surface providing info about the code withouth having to look it up in the table. + * + * Type also can be used to convey the fact that value must be a multicodec + * + * [multiformat]:https://multiformats.io/ + * [multicodec code]:https://github.com/multiformats/multicodec/blob/master/table.csv + */ +export type MulticodecCode< + Code extends number = number, + Name extends string = string +> = Code & Phantom + + /** * Represents an IPLD block (including its CID) that can be decoded to data of * type `T`. From d9ffdbfd0f470308a41c79eae9185f436e866f17 Mon Sep 17 00:00:00 2001 From: Irakli Gozalishvili Date: Wed, 19 Jul 2023 10:37:28 -0700 Subject: [PATCH 3/5] import MulticodecCode --- src/hashes/interface.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/hashes/interface.ts b/src/hashes/interface.ts index 6be54993..8350d694 100644 --- a/src/hashes/interface.ts +++ b/src/hashes/interface.ts @@ -1,4 +1,5 @@ // # Multihash +import { MulticodecCode } from '../block/interface.js' /** * Represents a multihash digest which carries information about the @@ -9,7 +10,7 @@ // a bunch of places that parse it to extract (code, digest, size). By creating // this first class representation we avoid reparsing and things generally fit // really nicely. -export interface MultihashDigest { +export interface MultihashDigest { /** * Code of the multihash */ @@ -35,7 +36,7 @@ export interface MultihashDigest { +export interface MultihashHasher { /** * Takes binary `input` and returns it (multi) hash digest. Return value is * either promise of a digest or a digest. This way general use can `await` @@ -67,7 +68,7 @@ export interface MultihashHasher { * `SyncMultihashHasher` is useful in certain APIs where async hashing would be * impractical e.g. implementation of Hash Array Mapped Trie (HAMT). */ -export interface SyncMultihashHasher extends MultihashHasher { +export interface SyncMultihashHasher extends MultihashHasher { digest: (input: Uint8Array) => MultihashDigest } From bdb104989b98d8bcacefc3af7cfa6a8d07192cc3 Mon Sep 17 00:00:00 2001 From: Irakli Gozalishvili Date: Wed, 19 Jul 2023 10:38:38 -0700 Subject: [PATCH 4/5] import as type --- src/hashes/interface.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hashes/interface.ts b/src/hashes/interface.ts index 8350d694..c922b274 100644 --- a/src/hashes/interface.ts +++ b/src/hashes/interface.ts @@ -1,5 +1,5 @@ // # Multihash -import { MulticodecCode } from '../block/interface.js' +import type { MulticodecCode } from '../block/interface.js' /** * Represents a multihash digest which carries information about the From 2b7743f73d3d8717fdae7b84ff321801a387c05c Mon Sep 17 00:00:00 2001 From: Irakli Gozalishvili Date: Thu, 20 Jul 2023 11:35:46 -0700 Subject: [PATCH 5/5] address some feedback --- src/hashes/interface.ts | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/src/hashes/interface.ts b/src/hashes/interface.ts index c922b274..29ab9d57 100644 --- a/src/hashes/interface.ts +++ b/src/hashes/interface.ts @@ -111,13 +111,22 @@ export interface IncrementalMultihashHasher< digest(): Digest /** - * Computes the digest of the given input and writes it into the provided - * `output` at given `offset`. The `offset` is optional and if omitted is - * implicitly `0`. The optional `asMultihash` whith is implicitly `true`, - * can be use to control whether multihash prefix is written, if `false` - * only the raw digest writtend omitting the prefix. + * Encodes multihash of the bytes written so far (since creation or + * reset) into provided `target` at given `offset`. If `offset` not + * provided it is implicitly `0`. + * + * @param [offset=0] - Byte offset in the `target`. + */ + readDigest(target: Uint8Array, offset?: number): this + + /** + * Encodes raw digest (without multihash header) of the bytes written + * so far (since creation or reset) into provided `target` at given + * `offset`. If `offset` not provided it is implicitly `0`. + * + * @param [offset=0] - Byte offset in the `target`. */ - digestInto(output: Uint8Array, offset?: number, asMultihash?: boolean): this + read(target: Uint8Array, offset?: number): this /** * Writes bytes to be digested.