Skip to content

Instantly share code, notes, and snippets.

@olizilla
Created June 30, 2021 13:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save olizilla/bb27a08e32fbdd544788ec0514a16d5c to your computer and use it in GitHub Desktop.
Save olizilla/bb27a08e32fbdd544788ec0514a16d5c to your computer and use it in GitHub Desktop.
CarReaderIdb - A CarReader impl that decodes blocks directly to idb via idb-keyval
import * as idb from 'idb-keyval'
import { CID } from 'multiformats'
import { BytesReader } from '@ipld/car/lib/coding'
import { createDecoder, asyncIterableReader } from '@ipld/car/lib/decoder.js'
export class CarReaderIdb {
_version: number;
_roots: Array<CID>;
constructor (version: number, roots: Array<CID>) {
this._version = version
this._roots = roots
}
get version () {
return this._version
}
/**
* Get the list of roots defined by the CAR referenced by this reader. May be
* zero or more `CID`s.
*/
async getRoots () {
return this._roots
}
/**
* Check whether a given `CID` exists within the CAR referenced by this
* reader.
*/
async has (key: CID) {
const val = await idb.get(key.toString())
return !!val
}
/**
* Fetch a `Block` (a `{ cid:CID, bytes:Uint8Array }` pair) from the CAR
* referenced by this reader matching the provided `CID`. In the case where
* the provided `CID` doesn't exist within the CAR, `undefined` will be
* returned.
*/
async get (key: CID) {
return idb.get(key.toString())
}
/**
* Returns a `BlockIterator` (`AsyncIterable<Block>`) that iterates over all
* of the `Block`s (`{ cid:CID, bytes:Uint8Array }` pairs) contained within
* the CAR referenced by this reader.
*/
async * blocks () {
const keys = await idb.keys()
for (const key of keys) {
yield idb.get(key)
}
}
/**
* Returns a `CIDIterator` (`AsyncIterable<CID>`) that iterates over all of
* the `CID`s contained within the CAR referenced by this reader.
*/
async * cids () {
for await (const block of this.blocks()) {
yield block.cid
}
}
/**
* Instantiate a {@link CarReaderIdb} from a `AsyncIterable<Uint8Array>`, such as
* a [modern Node.js stream](https://nodejs.org/api/stream.html#stream_streams_compatibility_with_async_generators_and_async_iterators).
*/
static async fromIterable (asyncIterable: AsyncIterable<Uint8Array>) {
if (!asyncIterable || !(typeof asyncIterable[Symbol.asyncIterator] === 'function')) {
throw new TypeError('fromIterable() requires an async iterable')
}
return decodeReaderComplete(asyncIterableReader(asyncIterable))
}
}
async function decodeReaderComplete (reader: BytesReader) {
const decoder = createDecoder(reader)
const { version, roots } = await decoder.header()
for await (const block of decoder.blocks()) {
idb.set(block.cid.toString(), block)
}
return new CarReaderIdb(version, roots)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment