Skip to content

Commit

Permalink
feat: add hasCode to Digest (#308)
Browse files Browse the repository at this point in the history
To give a hint to tsc that a `MultihashDigest` has a specific code,
add a disambiguator `hasCode` function.

This lets us define functions that require a certain multihash code
with type saftey.
  • Loading branch information
achingbrain committed Sep 16, 2024
1 parent c55bdfd commit a5fbf61
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 2 deletions.
7 changes: 7 additions & 0 deletions src/hashes/digest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,3 +69,10 @@ export class Digest<Code extends number, Size extends number> implements Multiha
this.bytes = bytes
}
}

/**
* Used to check that the passed multihash has the passed code
*/
export function hasCode <T extends number> (digest: MultihashDigest, code: T): digest is MultihashDigest<T> {
return digest.code === code
}
2 changes: 1 addition & 1 deletion src/hashes/identity.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { coerce } from '../bytes.js'
import * as Digest from './digest.js'

const code = 0x0
const code: 0x0 = 0x0
const name = 'identity'

const encode: (input: Uint8Array) => Uint8Array = coerce
Expand Down
27 changes: 26 additions & 1 deletion test/test-multihash.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,13 @@ import { hash as slSha512 } from '@stablelib/sha512'
import { assert } from 'aegir/chai'
import { sha1 as chSha1 } from 'crypto-hash'
import { fromHex, fromString } from '../src/bytes.js'
import { decode as decodeDigest, create as createDigest } from '../src/hashes/digest.js'
import { decode as decodeDigest, create as createDigest, hasCode as digestHasCode } from '../src/hashes/digest.js'
import { identity } from '../src/hashes/identity.js'
import { sha1 } from '../src/hashes/sha1.js'
import { sha256, sha512 } from '../src/hashes/sha2.js'
import invalid from './fixtures/invalid-multihash.js'
import valid from './fixtures/valid-multihash.js'
import type { MultihashDigest } from '../src/cid.js'

const sample = (code: number | string, size: number, hex: string): Uint8Array => {
const toHex = (i: number | string): string => {
Expand Down Expand Up @@ -158,4 +159,28 @@ describe('multihash', () => {
assert.match(String(error), /Unknown type, must be binary type/)
}
})

describe('hasCode', () => {
it('asserts that a multihash has the expected code', () => {
const buf = Uint8Array.from([0, 1, 2, 3])

// remove code type from MultihashDigest
const hash = decodeDigest(identity.digest(buf).bytes)

// a function that requires a specific type of multihash
function needIdentity (_: MultihashDigest<0x0>): void {

}

assert.isTrue(digestHasCode(hash, identity.code))

// @ts-expect-error fails to compile as hash is MultihashDigest<number>
needIdentity(hash)

// hint to tsc that hash is MultihashDigest<0x0>
if (digestHasCode(hash, identity.code)) {
needIdentity(hash)
}
})
})
})

0 comments on commit a5fbf61

Please sign in to comment.