diff --git a/README.md b/README.md index bbc494c..e403ec6 100644 --- a/README.md +++ b/README.md @@ -17,10 +17,10 @@ import { n } from '@haaxor1689/nil'; const mySchema = n.string(14); // Parse into Uint8Array -const buffer = mySchema.toBuffer('Hello world!!!'); +const buffer = await mySchema.toBuffer('Hello world!!!'); // Prase from Uint8Array -const parsed = mySchema.fromBuffer(buffer); +const parsed = await mySchema.fromBuffer(buffer); ``` Creating an object schema @@ -36,10 +36,10 @@ const User = n.object({ type User = n.output; // { username: string; age: number; active: boolean; } -const buffer = User.toBuffer({ username: 'Jane', age: 30, active: true }); +const buffer = await User.toBuffer({ username: 'Jane', age: 30, active: true }); // Prase from Uint8Array -User.fromBuffer(buffer); +await User.fromBuffer(buffer); ``` ## Primitives @@ -231,8 +231,8 @@ All Nil schemas contain these methods. ```ts .transform( - afterDecode: (v: Input, ctx?: ParseContext) => Output, - beforeEncode: (v: Output, ctx?: ParseContext) => Input + afterDecode: (v: Input, ctx?: ParseContext) => Promise, + beforeEncode: (v: Output, ctx?: ParseContext) => Promise ) ``` @@ -256,7 +256,7 @@ const MySchema = n type MySchema = z.output; // Resulting buffer will start with correct `itemCount` number -MySchema.toBuffer([1, 2, 3, 4]); +await MySchema.toBuffer([1, 2, 3, 4]); ``` You can also access the current context when creating transformations to reference other attributes from the parent type (if any). The easiest way to do this is by using the `resolvePath` helper function. @@ -282,7 +282,7 @@ const MySchema = n.object({ ### `.fromBuffer` ```ts -.fromBuffer(data: Uint8Array): Output +.fromBuffer(data: Uint8Array): Promise ``` Tries to parse given buffer into output type of used schema. Throws errors on failure. @@ -290,7 +290,7 @@ Tries to parse given buffer into output type of used schema. Throws errors on fa ### `.toBuffer` ```ts -.toBuffer(value: Output): Uint8Array +.toBuffer(value: Output): Promise ``` Tries to serialize a given object into a buffer. diff --git a/package.json b/package.json index 925df4c..88f6a84 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@haaxor1689/nil", - "version": "0.1.2", + "version": "0.1.3", "description": "TypeScript-first binary data parsing library with static type inference", "author": "Maroš Beťko ", "repository": { diff --git a/src/helpers/util.ts b/src/helpers/util.ts index f041b7d..2146a7f 100644 --- a/src/helpers/util.ts +++ b/src/helpers/util.ts @@ -11,16 +11,16 @@ export type identity = T; export type flatten = identity<{ [k in keyof T]: T[k] }>; // FIXME: Improve types -type ObjectMapper = (value: T, key: string) => U; -export const mapValues = ( +type ObjectMapper = (value: T, key: string) => Promise; +export const mapValues = async ( obj: Record, mapper: ObjectMapper -): Record => { +): Promise> => { const result: Record = {}; for (const key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { - result[key] = mapper(obj[key], key); + result[key] = await mapper(obj[key], key); } } diff --git a/src/types.ts b/src/types.ts index 87666ae..6d1d0f5 100644 --- a/src/types.ts +++ b/src/types.ts @@ -32,24 +32,24 @@ export abstract class NilType { abstract _decode(data: DataView, ctx?: ParseContext): Input; abstract _encode(data: DataView, value: Input, ctx?: ParseContext): void; - _afterDecode(value: Input, _ctx?: ParseContext): Output { + async _afterDecode(value: Input, _ctx?: ParseContext): Promise { return value as never; } - _beforeEncode(value: Output, _ctx?: ParseContext): Input { + async _beforeEncode(value: Output, _ctx?: ParseContext): Promise { return value as never; } abstract size(value?: Input, ctx?: ParseContext): number; - fromBuffer(data: Uint8Array): Output { + async fromBuffer(data: Uint8Array): Promise { const view = new DataView(data.buffer); const val = this._decode(view); - return this._afterDecode(val); + return await this._afterDecode(val); } - toBuffer(value: Output): Uint8Array { - const val = this._beforeEncode(value); + async toBuffer(value: Output): Promise { + const val = await this._beforeEncode(value); const buffer = new Uint8Array(this.size(val)); const view = new DataView(buffer.buffer); this._encode(view, val); @@ -89,14 +89,14 @@ class NilEffects< this._def.schema._encode(data, value, ctx); } - _afterDecode(value: Input, ctx?: ParseContext): Output { + async _afterDecode(value: Input, ctx?: ParseContext): Promise { const { schema } = this._def; - return this._def.transform[0](schema._afterDecode(value, ctx), ctx); + return this._def.transform[0](await schema._afterDecode(value, ctx), ctx); } - _beforeEncode(value: Output, ctx?: ParseContext): Input { + async _beforeEncode(value: Output, ctx?: ParseContext): Promise { const { schema } = this._def; - return schema._beforeEncode(this._def.transform[1](value, ctx), ctx); + return await schema._beforeEncode(this._def.transform[1](value, ctx), ctx); } } @@ -365,30 +365,37 @@ class NilArray extends NilType< }); } - _afterDecode(value: T['_input'][], ctx?: ParseContext) { + async _afterDecode(value: T['_input'][], ctx?: ParseContext) { const { schema } = this._def; - return value.map((v, i) => { + + const arr = []; + for (let i = 0; i < value.length; i++) { + const v = value[i]; const newCtx: ParseContext = { // FIXME: Types value: value as never, path: [...(ctx?.path ?? []), i], parent: ctx }; - return schema._afterDecode(v, newCtx); - }); + arr.push(await schema._afterDecode(v, newCtx)); + } + return arr; } - _beforeEncode(value: T['_output'][], ctx?: ParseContext) { + async _beforeEncode(value: T['_output'][], ctx?: ParseContext) { const { schema } = this._def; - return value.map((v, i) => { + const arr = []; + for (let i = 0; i < value.length; i++) { + const v = value[i]; const newCtx: ParseContext = { // FIXME: Types value: value as never, path: [...(ctx?.path ?? []), i], parent: ctx }; - return schema._beforeEncode(v, newCtx); - }); + arr.push(await schema._beforeEncode(v, newCtx)); + } + return arr; } #elementSize(value?: T['_input'][], ctx?: ParseContext) { @@ -488,7 +495,7 @@ class NilObject< parent: ctx }; return v._afterDecode(value[k as keyof Input], newCtx); - }) as Output; + }) as Promise; } _beforeEncode(value: Output, ctx?: ParseContext) { @@ -501,7 +508,7 @@ class NilObject< parent: ctx }; return v._beforeEncode(value[k as keyof Output], newCtx); - }) as Input; + }) as Promise; } } @@ -574,7 +581,7 @@ export class NilEnum< this._def.type._encode(data, value); } - _afterDecode(value: T['_input']): O[number] { + async _afterDecode(value: T['_input']) { const option = this._def.options[value]; if (option === undefined) throw new Error( @@ -583,7 +590,7 @@ export class NilEnum< return option; } - _beforeEncode(value: O[number]): T['_input'] { + async _beforeEncode(value: O[number]) { const index = this._def.options.indexOf(value); if (index === -1) throw new Error(