@dstanesc/o-o-o-o-o-o-o
Version:
O-O-O-O-O-O-O is a collection of content addressed persistent data structures
139 lines (126 loc) • 3.8 kB
text/typescript
import { Link, Block, IndexedValue } from './types'
import { CID } from 'multiformats/cid'
import * as Raw from 'multiformats/codecs/raw'
import { sha256 } from 'multiformats/hashes/sha2'
import { pack, unpack } from 'msgpackr'
import { chunkyStore } from '@dstanesc/store-chunky-bytes'
const { create, readAll } = chunkyStore()
const CID_VERSION = 1
const CODEC_CODE = Raw.code
interface SearchIndex {
create: (
values: IndexedValue[],
blockPut: (block: Block) => Promise<void>,
blockGet: (cid: any) => Promise<Uint8Array>
) => Promise<Link>
search: (
link: Link,
blockGet: (cid: any) => Promise<Uint8Array>,
value: any
) => Promise<IndexedValue>
}
interface LinkCodec {
encode: (blockBytes: Uint8Array) => Promise<Link>
decode: (linkBytes: Uint8Array) => Link
parseString: (encoded: string) => Link
encodeString: (link: Link) => string
}
interface BlockCodec {
encode: (
json: any,
blockPut: (block: Block) => Promise<void>
) => Promise<Link>
decode: (
link: Link,
blockGet: (cid: any) => Promise<Uint8Array>
) => Promise<any>
}
interface ValueCodec {
encode: (value: any) => Uint8Array
decode: (valueBytes: Uint8Array) => any
}
const valueCodecFactory = (): ValueCodec => {
const encode = (value: any): Uint8Array => {
return pack(value) as Uint8Array
}
const decode = (valueBytes: Uint8Array): any => {
return unpack(valueBytes)
}
return { encode, decode }
}
const linkCodecFactory = (): LinkCodec => {
const encode = async (blockBytes: Uint8Array): Promise<Link> => {
const hash = await sha256.digest(blockBytes)
return CID.create(CID_VERSION, CODEC_CODE, hash)
}
const decode = (linkBytes: Uint8Array): Link => {
return CID.decode(linkBytes)
}
const parseString = (encodedString: string): Link => {
return CID.parse(encodedString)
}
const encodeString = (link: Link): string => {
return link.toString()
}
return { encode, decode, encodeString, parseString }
}
const blockCodecFactory = (): BlockCodec => {
const { encode: linkEncode, decode: linkDecode } = linkCodecFactory()
const encode = async (
json: any,
blockPut: (block: Block) => Promise<void>
): Promise<Link> => {
const bytes = pack(json)
const link = await linkEncode(bytes)
await blockPut({ cid: link, bytes })
return link
}
const decode = async (
link: Link,
blockGet: (cid: any) => Promise<Uint8Array>
): Promise<any> => {
const blockBytes = await blockGet(link)
return unpack(blockBytes)
}
return { encode, decode }
}
const multiBlockCodecFactory = (
chunk: (data: Uint8Array) => Uint32Array
): BlockCodec => {
const { encode: linkEncode, decode: linkDecode } = linkCodecFactory()
const encode = async (
json: any,
blockPut: (block: Block) => Promise<void>
): Promise<Link> => {
const buf = pack(json)
const { root, index, blocks } = await create({
buf,
chunk,
encode: linkEncode,
})
for (const block of blocks) await blockPut(block)
return root
}
const decode = async (
link: Link,
blockGet: (cid: any) => Promise<Uint8Array>
): Promise<any> => {
const bytes = await readAll({
root: link,
decode: linkDecode,
get: blockGet,
})
return unpack(bytes)
}
return { encode, decode }
}
export {
LinkCodec,
BlockCodec,
ValueCodec,
SearchIndex,
valueCodecFactory,
linkCodecFactory,
blockCodecFactory,
multiBlockCodecFactory,
}