Skip to content

Commit 553bdee

Browse files
authored
feat: define sync multihash hasher interface
1 parent c936a6d commit 553bdee

File tree

5 files changed

+61
-19
lines changed

5 files changed

+61
-19
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,4 @@ node_modules
88
yarn.lock
99
types
1010
test/ts-use/tsconfig.tsbuildinfo
11+
test/tsconfig.tsbuildinfo

src/hashes/identity.js

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
1-
// @ts-check
2-
3-
import { from } from './hasher.js'
41
import { coerce } from '../bytes.js'
2+
import * as Digest from './digest.js'
3+
4+
export const code = 0x0
5+
export const name = 'identity'
6+
7+
/**
8+
* @param {Uint8Array} input
9+
* @returns {Digest.Digest<typeof code, number>}
10+
*/
11+
export const digest = (input) => Digest.create(code, coerce(input))
512

6-
export const identity = from({
7-
name: 'identity',
8-
code: 0x0,
9-
encode: (input) => coerce(input)
10-
})
13+
/** @type {import('./interface').SyncMultihashHasher<typeof code>} */
14+
export const identity = { code, name, digest }

src/hashes/interface.ts

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,11 @@
99
// a bunch of places that parse it to extract (code, digest, size). By creating
1010
// this first class representation we avoid reparsing and things generally fit
1111
// really nicely.
12-
export interface MultihashDigest {
12+
export interface MultihashDigest<Code extends number = number> {
1313
/**
1414
* Code of the multihash
1515
*/
16-
code: number
16+
code: Code
1717

1818
/**
1919
* Raw digest (without a hashing algorithm info)
@@ -35,20 +35,38 @@ export interface MultihashDigest {
3535
* Hasher represents a hashing algorithm implementation that produces as
3636
* `MultihashDigest`.
3737
*/
38-
export interface MultihashHasher {
38+
export interface MultihashHasher<Code extends number = number> {
3939
/**
40-
* Takes binary `input` and returns it (multi) hash digest.
40+
* Takes binary `input` and returns it (multi) hash digest. Return value is
41+
* either promise of a digest or a digest. This way general use can `await`
42+
* while performance critical code may asses return value to decide whether
43+
* await is needed.
44+
*
4145
* @param {Uint8Array} input
4246
*/
43-
digest(input: Uint8Array): Promise<MultihashDigest>
47+
digest(input: Uint8Array): Promise<MultihashDigest> | MultihashDigest
4448

4549
/**
4650
* Name of the multihash
4751
*/
48-
name: string
52+
name: string
4953

5054
/**
5155
* Code of the multihash
5256
*/
53-
code: number
57+
code: Code
58+
}
59+
60+
/**
61+
* Sync variant of `MultihashHasher` that refines return type of the `digest`
62+
* to `MultihashDigest`. It is subtype of `MultihashHasher` so implementations
63+
* of this interface can be passed anywhere `MultihashHasher` is expected,
64+
* allowing consumer to either `await` or check the return type to decide
65+
* whether to await or proceed with return value.
66+
*
67+
* `SyncMultihashHasher` is useful in certain APIs where async hashing would be
68+
* impractical e.g. implementation of Hash Array Mapped Trie (HAMT).
69+
*/
70+
export interface SyncMultihashHasher<Code extends number = number> extends MultihashHasher<Code> {
71+
digest(input: Uint8Array): MultihashDigest
5472
}

test/test-multihash.js

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ describe('multihash', () => {
6363
assert.deepStrictEqual(hash2.bytes, hash.bytes)
6464
})
6565

66-
it('hash identity', async () => {
66+
it('hash identity async', async () => {
6767
const hash = await identity.digest(fromString('test'))
6868
assert.deepStrictEqual(hash.code, identity.code)
6969
assert.deepStrictEqual(identity.code, 0)
@@ -73,6 +73,17 @@ describe('multihash', () => {
7373
assert.deepStrictEqual(hash2.code, identity.code)
7474
assert.deepStrictEqual(hash2.bytes, hash.bytes)
7575
})
76+
77+
it('hash identity sync', () => {
78+
const hash = identity.digest(fromString('test'))
79+
assert.deepStrictEqual(hash.code, identity.code)
80+
assert.deepStrictEqual(identity.code, 0)
81+
assert.deepStrictEqual(hash.digest, fromString('test'))
82+
83+
const hash2 = decodeDigest(hash.bytes)
84+
assert.deepStrictEqual(hash2.code, identity.code)
85+
assert.deepStrictEqual(hash2.bytes, hash.bytes)
86+
})
7687
})
7788
describe('decode', () => {
7889
for (const { encoding, hex, size } of valid) {

test/tsconfig.json

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,21 @@
2828
"skipLibCheck": true,
2929
"stripInternal": true,
3030
"resolveJsonModule": true,
31-
"noEmit": true
31+
"noEmit": true,
32+
"paths": {
33+
"multiformats": [
34+
"../types/src/index"
35+
],
36+
"multiformats/*": [
37+
"../types/src/*"
38+
]
39+
}
3240
},
3341
"include": [
34-
"test/",
3542
"."
3643
],
3744
"exclude": [
38-
"ts-use/"
45+
"ts-use/",
46+
"node_modules"
3947
]
4048
}

0 commit comments

Comments
 (0)