-
Notifications
You must be signed in to change notification settings - Fork 22
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
chore: template for internal-layer-protocol
- Loading branch information
Showing
5 changed files
with
208 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,116 @@ | ||
import { CID } from "multiformats"; | ||
import { encode, decode } from "cborg"; | ||
import { Result } from "@adviser/cement" | ||
|
||
export interface FPEnvelope<T> { | ||
readonly type: string; // "car" | "file" | "meta" | "wal" | ||
readonly payload: T | ||
} | ||
|
||
export interface FPEnvelopeCar extends FPEnvelope<Uint8Array> { | ||
readonly type: "car"; | ||
} | ||
|
||
export interface FPEnvelopeFile extends FPEnvelope<Uint8Array> { | ||
readonly type: "file"; | ||
} | ||
|
||
export interface FPMeta { | ||
readonly cid: string; | ||
readonly data: Uint8Array; | ||
readonly parents: string[]; | ||
} | ||
|
||
export interface FPEnvelopeMeta extends FPEnvelope<FPMeta> { | ||
readonly type: "meta"; | ||
} | ||
|
||
export interface FPWALCarsOps { | ||
readonly cars: CID[]; | ||
} | ||
export interface FPWAL { | ||
// fileOperations: any[]; will be added with connector-fixes | ||
// noLoaderOps: any[]; will be added with connector-fixes | ||
readonly operations: FPWALCarsOps[]; | ||
} | ||
export interface FPEnvelopeWAL extends FPEnvelope<FPWAL> { | ||
readonly type: "wal"; | ||
} | ||
|
||
export function WAL2FPMsg(fpwal: FPWAL): Uint8Array { | ||
return encode({ type: "wal", payload: JSON.parse(JSON.stringify(fpwal)) } as FPEnvelopeWAL); | ||
} | ||
|
||
export function FPMsg2WAL(fpmsg: Uint8Array): Result<FPWAL> { | ||
const renv = FPMsgMatch2Envelope(fpmsg, "wal"); | ||
if (renv.isErr()) { | ||
return Result.Err(renv.Err()); | ||
} | ||
const convertCids = renv.Ok().payload as FPWAL; | ||
for (const op of convertCids.operations) { | ||
const cars = [] | ||
for (const strCid of op.cars) { | ||
for (const cidVal of Object.values(strCid)) { | ||
cars.push(CID.parse(cidVal)); | ||
} | ||
} | ||
(op as {cars: CID[]}).cars = cars; | ||
} | ||
return Result.Ok(renv.Ok().payload as FPWAL); | ||
} | ||
|
||
export function Meta2FPMsg(fpmeta: FPMeta): Uint8Array { | ||
return encode({ type: "meta", payload: fpmeta } as FPEnvelopeMeta); | ||
} | ||
|
||
export function FPMsg2Meta(fpmsg: Uint8Array): Result<FPMeta> { | ||
const renv = FPMsgMatch2Envelope(fpmsg, "meta"); | ||
if (renv.isErr()) { | ||
return Result.Err(renv.Err()); | ||
} | ||
return Result.Ok(renv.Ok().payload as FPMeta); | ||
} | ||
|
||
export function Car2FPMsg(fpcar: Uint8Array): Uint8Array { | ||
return encode({ type: "car", payload: fpcar } as FPEnvelopeCar); | ||
} | ||
|
||
export function FPMsg2Car(fpmsg: Uint8Array): Result<Uint8Array> { | ||
const renv = FPMsgMatch2Envelope(fpmsg, "car"); | ||
if (renv.isErr()) { | ||
return Result.Err(renv.Err()); | ||
} | ||
return Result.Ok(renv.Ok().payload as Uint8Array); | ||
} | ||
|
||
export function File2FPMsg(fpfile: Uint8Array): Uint8Array { | ||
return encode({ type: "file", payload: fpfile } as FPEnvelopeFile); | ||
} | ||
|
||
export function FPMsg2File(fpmsg: Uint8Array): Result<Uint8Array> { | ||
const renv = FPMsgMatch2Envelope(fpmsg, "file"); | ||
if (renv.isErr()) { | ||
return Result.Err(renv.Err()); | ||
} | ||
return Result.Ok(renv.Ok().payload as Uint8Array); | ||
} | ||
|
||
export function FPMsgMatch2Envelope(fpmsg: Uint8Array, ...types: string[]): Result<FPEnvelope<unknown>> { | ||
let env: FPEnvelope<unknown>; | ||
try { | ||
env = decode(fpmsg); | ||
} catch (e) { | ||
return Result.Err(`failed to decode envelope: ${e}`); | ||
} | ||
if (typeof env !== "object") { | ||
return Result.Err(`expected envelope to be an object`); | ||
} | ||
if (typeof env.type !== "string") { | ||
return Result.Err(`expected type to be a string`); | ||
} | ||
if (types.length > 0 && !types.includes(env.type)) { | ||
return Result.Err(`expected type to be ${types}`); | ||
} | ||
// need to check if the payload is a valid WAL | ||
return Result.Ok(env); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
import { encode } from "cborg"; | ||
import { bs, Result } from '@fireproof/core' | ||
import { CID } from "multiformats"; | ||
|
||
it("unknown bytes", () => { | ||
expect(bs.FPMsgMatch2Envelope(Uint8Array.from([1, 2, 3]), "bla").Err().message).toStrictEqual( | ||
"failed to decode envelope: Error: CBOR decode error: too many terminals, data makes no sense" | ||
); | ||
}); | ||
|
||
it("unknown type", () => { | ||
expect(bs.FPMsgMatch2Envelope(encode({ type: "blax", payload: 4 }), "bla")) | ||
.toStrictEqual(Result.Err("expected type to be bla")); | ||
}) | ||
|
||
it("no type", () => { | ||
expect(bs.FPMsgMatch2Envelope(encode({ type: "blax", payload: 4 }))) | ||
.toStrictEqual(Result.Ok({ type: "blax", payload: 4 })); | ||
}) | ||
|
||
it("car type", () => { | ||
expect(bs.FPMsg2Car(bs.Car2FPMsg(Uint8Array.from([1, 2, 3]))).Ok()).toStrictEqual(Uint8Array.from([1, 2, 3])); | ||
}) | ||
|
||
it("file type", () => { | ||
expect(bs.FPMsg2File(bs.File2FPMsg(Uint8Array.from([1, 2, 3]))).Ok()).toStrictEqual(Uint8Array.from([1, 2, 3])); | ||
}) | ||
|
||
it("meta type", () => { | ||
const ref = { | ||
cid: "CID", | ||
data: Uint8Array.from([1, 2, 3]), | ||
parents: ["C1", "C2"] | ||
}; | ||
expect(bs.FPMsg2Meta(bs.Meta2FPMsg(ref)).Ok()).toStrictEqual(ref); | ||
}) | ||
|
||
it("wal type", () => { | ||
const ref: bs.FPWAL = { | ||
operations: [ | ||
{ | ||
cars: [ | ||
CID.parse("bag4yvqabciqdzvfxrxfi6feubspyz666zegmp3z5w556mr4ykya2kkdm22r7pyy") | ||
] | ||
}, | ||
{ | ||
cars: [ | ||
CID.parse("bag4yvqabciqd2ul2tw4mdcpvfq2pdqhvnqp2ktuyrtcl3j3gwhxbjzjt62xzeaq") | ||
] | ||
} | ||
] | ||
}; | ||
const res = bs.FPMsg2WAL(bs.WAL2FPMsg(ref)).Ok(); | ||
expect(res).toStrictEqual(ref); | ||
expect(res.operations[0].cars[0].version).toStrictEqual(1); | ||
}) |