Skip to content

CIDs as interfaces #203

Closed
Closed
@achingbrain

Description

@achingbrain

#161 was closed and it looks like we've backtracked on the CIDs as interfaces thing. Now we have a Link interface and CID class that implements the link interface. We also have CIDs as an ArrayBufferView which, I don't know, maybe didn't turn out to be as useful as we thought it might be at the time, but the end result is it has extra properties byteOffset and byteLength which are obscured from the uninterested caller by making them non-enumerable. This works but it is very slow.

If we're going to town on #199 maybe we could do the CID-as-interface. I'd like to propose a very minimal interface, any static methods would be exposed as named exports instead.

export type CIDVersion = 0 | 1

export interface CID {
  version: CIDVersion
  code: number
  multihash: MultihashDigest
  bytes: Uint8Array

  equals: (other: CID | Uint8Array | string) => boolean
}

// create CIDs
export function createCID (version: CIDVersion, code: number, digest: MultihashDigest): CID
export function cidFromString (string: string): CID
export function cidFromBytes (bytes: Uint8Array): CID

// housekeeping
export function toV0 (cid: CID): CID
export function toV1 (cid: CID): CID
export function isCID (value: any): value is CID

Some thoughts:

  • toV0/toV1 can we live without these? A quick grep of the js-ipfs codebase and we only call them in tests and for top-level UI type output - the cli and the http gateway, would vote to remove and let users have their own utils for this
  • asCID/isCID my (perhaps unpopular) opinion is that these are named too similarly and that asCID is clunky to use in practice as it requires null-guarding on the output. If the CID interface is only the fields above perhaps we don't need to convert old impls into new ones any more (the original purpose of asCID IIRC)
  • parse/decode vs cidFromString/cidFromBytes - the meaning of the words 'parse' and 'decode' are so close as to be synonymous which makes the API hard to use without reference to documentation; let's just say what they do. @libp2p/peer-id has taken this approach and it makes the codebase a bit more straightforward to the newcomer.
  • toJSON can we live without this? Similar to toV0 and toV1 I only see it used in UIs.
  • toString(encoder?: MultibaseEncoder) omission - maybe if you have a non-default encoder you could just use it to encode the .bytes property of the CID instead of passing it to the toString method? Calling cid.toString() would only ever return the default encoding (base58btc for v0, base32 for v1). The current impl maintains a cache of strings which might be a reason to keep it? I am not sure where this has been a bottleneck in the past though.
  • CIDIface/CIDImpl - @multiformats/multiaddr and @libp2p/peer-id have avoided this sort of naming scheme by intentionally not exporting the default implementation. You only get factory functions that take some input and return something that conforms to the interface. I suggest following that convention here too.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions