binary-structures
Version:
Yet another declarative binary packer/parser, but built for modern browsers.
134 lines (133 loc) • 6.85 kB
TypeScript
import 'improved-map';
import { Size } from './serialization';
export declare type Primitive = number | string | ArrayBuffer;
export declare type Mapped<T> = Map<string, T>;
export declare type Encoded_Map = Mapped<any>;
export declare type Encoded_Array = Array<any>;
export declare type Encoded = Primitive | Encoded_Map | Encoded_Array;
export declare type Map_Context = Encoded_Map;
export declare type Array_Context = Encoded_Array;
export declare type Context = Encoded;
export declare const Parent: unique symbol;
export interface Contextualized<P> {
[Parent]?: P;
}
export declare type Context_Type<E extends Encoded, C> = E & Contextualized<C>;
export declare type Context_Map<Encoded, Context> = Context_Type<Mapped<Encoded>, Context>;
export declare type Context_Array<Encoded, Context> = Context_Type<Array<Encoded>, Context>;
export declare type Context_Iterable<Encoded, Context> = Context_Map<Encoded, Context> | Context_Array<Encoded, Context>;
export declare type Encoder<Decoded, E extends Encoded, Context> = (decoded: Decoded, context?: Context) => E;
export declare type Decoder<E extends Encoded, Decoded, Context> = (encoded: E, context?: Context) => Decoded;
export interface Transcoders<E extends Encoded, Decoded, Context> {
encode?: Encoder<Decoded, E, Context>;
decode?: Decoder<E, Decoded, Context>;
little_endian?: boolean;
}
export declare const inspect_transcoder: <T>(data: T, context?: any) => T;
export declare const inspect: {
encode: <T>(data: T, context?: any) => T;
decode: <T>(data: T, context?: any) => T;
};
/** A function to fetch the data to be packed.
* It is provided by the code handling the input data and called by the packer function to fetch the data to pack.
*/
export interface Fetcher<Decoded> {
(): Decoded;
}
/** A function to deliver the parsed result to the correct place.
* It is provided by the code managing the results container and called by the parser function with the parsed data.
*/
export interface Deliver<Decoded> {
(data: Decoded): void;
}
export interface Parse_Options<Context> {
byte_offset?: number;
little_endian?: boolean;
context?: Context;
}
export interface Pack_Options<C> extends Parse_Options<C> {
data_view?: DataView;
}
export interface Packed {
buffer: ArrayBuffer;
size: Size;
}
export interface Parsed<Decoded> {
data: Decoded;
size: Size;
}
export interface Packer<Decoded, Context> {
(source: Decoded | Fetcher<Decoded>, options?: Pack_Options<Context>): Packed;
}
export interface Parser<Decoded, Context> {
(data_view: DataView, options?: Parse_Options<Context>, deliver?: Deliver<Decoded>): Parsed<Decoded>;
}
export interface Struct<Decoded, Context> {
pack: Packer<Decoded, Context>;
parse: Parser<Decoded, Context>;
}
export declare const Bits: <D, C>(bits: number, transcoders?: Transcoders<string | number, D, C>) => Struct<D, C>;
export declare const Uint: <D, C>(bits: number, transcoders?: Transcoders<string | number, D, C>) => Struct<D, C>;
export declare const Int: <D, C>(bits: number, transcoders?: Transcoders<string | number, D, C>) => Struct<D, C>;
export declare const Float: <D, C>(bits: number, transcoders?: Transcoders<string | number, D, C>) => Struct<D, C>;
export declare const Utf8: <D, C>(bits: number, transcoders?: Transcoders<string, D, C>) => Struct<D, C>;
export declare type Numeric<C> = number | {
bits?: number;
bytes?: number;
} | ((context?: C) => number);
/** Byte_Buffer doesn't do any serialization, but just copies bytes to/from an ArrayBuffer that's a subset of the
* serialized buffer. Byte_Buffer only works on byte-aligned data.
*
* @param {Numeric} length
* @param {Transcoders<ArrayBuffer, any>} transcoders
*/
export declare const Byte_Buffer: <D, C>(length: Numeric<C>, transcoders?: Transcoders<ArrayBuffer, D, C>) => {
pack: (source: D | Fetcher<D>, options?: Pack_Options<C>) => Packed;
parse: (data_view: DataView, options?: Parse_Options<C>, deliver?: Deliver<D> | undefined) => {
data: D;
size: number;
};
};
export declare const Padding: <C>(bits: Numeric<C>, transcoders?: Transcoders<number, any, C>) => Struct<any, C>;
export declare type Chooser<C> = (context?: C) => number | string;
export interface Choices<D, C> {
[choice: number]: Struct<D, C>;
[choice: string]: Struct<D, C>;
}
export interface Branch<D, C> {
chooser: Chooser<C>;
choices: Choices<D, C>;
default_choice?: Struct<D, C>;
}
export declare const Branch: <D, C>({ chooser, choices, default_choice }: Branch<D, C>) => Struct<D, C>;
export declare const Embed: <D, C extends Context_Iterable<D, S>, S>(embedded: Struct<Context_Iterable<D, S>, S> | Struct<D, C>) => Struct<D | Context_Type<Map<string, D>, S> | Context_Type<D[], S>, C>;
export declare type Map_Item<I> = Struct<I, Mapped<I>>;
export declare type Map_Iterable<I> = Array<[string, Map_Item<I>]>;
export declare type Map_Transcoders<I, D, C> = Transcoders<Mapped<I>, D, C>;
export interface Binary_Map<I, D, C> extends Mapped<Map_Item<I>>, Struct<D, C> {
pack: (source: D | Fetcher<D>, options?: Pack_Options<C>, encoded?: Context_Map<I, C>) => Packed;
parse: (data_view: DataView, options?: Parse_Options<C>, deliver?: Deliver<D>, results?: Context_Map<I, C>) => Parsed<D>;
}
export declare function Binary_Map<I, D, C>(transcoders?: Map_Transcoders<I, D, C> | Map_Iterable<I>, iterable?: Map_Iterable<I> | Map_Transcoders<I, D, C>): Binary_Map<I, D, C>;
export declare namespace Binary_Map {
let object_encoder: (obj: any) => Map<any, any>;
let object_decoder: (map: Map<any, any>) => any;
let object_transcoders: {
encode: (obj: any) => Map<any, any>;
decode: (map: Map<any, any>) => any;
};
}
export declare type Array_Item<I> = Struct<I, Array<I>>;
export declare type Array_Transcoders<I, D, C> = Transcoders<Array<I>, D, C>;
export interface Binary_Array<I, D, C> extends Array<Array_Item<I>>, Struct<D, C> {
pack: (source: D | Fetcher<D>, options?: Pack_Options<C>, fetcher?: Fetcher<I>) => Packed;
__pack_loop: (fetcher: Fetcher<I>, options: Pack_Options<Array<I>>, store: (result: Packed) => void, parent?: C) => number;
parse: (data_view: DataView, options?: Parse_Options<C>, deliver?: Deliver<D>, results?: Context_Array<I, C>) => Parsed<D>;
__parse_loop: (data_view: DataView, options: Parse_Options<Context_Array<I, C>>, deliver: Deliver<I>, parent?: C) => number;
}
export declare const Binary_Array: <I, D, C>(...elements: (Transcoders<I[], D, C> | Struct<I, I[]>)[]) => Binary_Array<I, D, C>;
export interface Repeat_Options<I, D, C> extends Array_Transcoders<I, D, C> {
count?: Numeric<C>;
bytes?: Numeric<C>;
}
export declare const Repeat: <I, D, C>(...elements: (Repeat_Options<I, D, C> | Struct<I, I[]>)[]) => Binary_Array<I, D, C>;