@oazmi/kitchensink
Version:
a collection of personal utility functions
165 lines • 9.06 kB
TypeScript
/** utility functions for packing and unpacking bytes (8-bits) of primitive javascript objects.
* > and hence the name of the module (*8(bit)pack*).
*
* @module
*/
import "./_dnt.polyfills.js";
import type { NumericArrayType, NumericType, VarNumericArrayType, VarNumericType } from "./typedefs.js";
/** binary primitive types.
* - {@link NumericType} various binary representations of number
* - {@link NumericArrayType} various binary representations of array of numbers. requires defining array length (number of items) during decoding as `args[0]`
* - `"bytes"` a `Uint8Array`, which requires defining a bytesize length during decoding as `args[0]`
* - `"str"` a string, which requires defining a bytesize length during decoding as `args[0]`
* - `"cstr"` a null-terminated (`"\u0000"`) string. the null termination byte character is automatically added when encoding
* - `"bool"` a boolean occupying a single byte
*/
export type PrimitiveType = PrimitiveArrayType | NumericType | VarNumericType | "cstr" | "bool";
/** primitive types that typically require length information to be decoded. */
export type PrimitiveArrayType = NumericArrayType | VarNumericArrayType | "bytes" | "str";
/** all unpack functions return their decoded outputs in a 2-tuple array;
* the first element being the decoded value `V`, and the second being the number of bytes this data occupied.
*/
export type Decoded<V, ByteSize extends number = number> = [value: V, bytesize: ByteSize];
/** primitive javascript types. */
export type JSPrimitive = string | boolean | number | bigint | number[] | Uint8Array;
/** packing function signature for {@link JSPrimitive} types. */
export type EncodeFunc<T extends JSPrimitive, ARGS extends any[] = []> = (value: T, ...args: ARGS) => Uint8Array;
/** unpacking function signature for {@link JSPrimitive} types. */
export type DecodeFunc<T extends JSPrimitive, ARGS extends any[] = []> = (buffer: Uint8Array, offset: number, ...args: ARGS) => Decoded<T>;
/** read `type` of value from buffer `buf`, starting at position `offset`. */
export declare const readFrom: (buf: Uint8Array, offset: number, type: PrimitiveType, ...args: any[]) => [value: JSPrimitive, new_offset: number];
/** write `type` of `value` to buffer `buf`, starting at position `offset`. */
export declare const writeTo: (buf: Uint8Array, offset: number, type: PrimitiveType, value: JSPrimitive, ...args: any[]) => [buf: Uint8Array, new_offset: number];
/** encode a sequential array of primitive items.
* to invert/decode the transformation, use {@link unpackSeq}.
*
* under the hood, this function uses {@link pack} for encoding each item.
*
* @example
* ```ts
* import { assertEquals } from "jsr:@std/assert"
*
* assertEquals(
* packSeq(["u4b", 0x12AB98], ["str", "hello"], ["bool", false]),
* Uint8Array.of(0x00, 0x12, 0xAB, 0x98, 104, 101, 108, 108, 111, 0),
* )
* ```
*/
export declare const packSeq: (...items: Parameters<typeof pack>[]) => Uint8Array;
/** decodes as a sequential array of items, provided that you pair the values with their `PrimitiveType`s.
* this is the inverse of {@link packSeq}.
*
* under the hood, this function uses {@link unpack} for decoding each item.
*
* @example
* ```ts
* import { assertEquals } from "jsr:@std/assert"
*
* assertEquals(
* unpackSeq(
* Uint8Array.of(0x00, 0x12, 0xAB, 0x98, 104, 101, 108, 108, 111, 0), // byte buffer
* 0, // starting index
* ["u4b"], // first decoded item should be a 4-byte unsigned integer in big-endian byte-order.
* ["str", 5], // the second item should be a string consisting of 5 bytes (5 characters in this case).
* ["bool"], // the last item should be a 1-byte boolean.
* ), [
* [0x12AB98, "hello", false], // decoded items
* 10, // bytes decoded
* ],
* )
* ```
*/
export declare const unpackSeq: (buf: Uint8Array, offset: number, ...items: [type: PrimitiveType, ...args: any[]][]) => Decoded<JSPrimitive[]>;
/** a primitive value encoder/packer for a given `type` (see {@link PrimitiveType}).
* to invert/decode the transformation, use {@link unpack}.
*
* under the hood, this function calls one of the following primitive value encoders, based on the `type` that you provide:
* - {@link encode_bool}, {@link encode_cstr}, {@link encode_str}, {@link encode_bytes},
* {@link encode_number}, {@link encode_number_array}, {@link encode_varint}, {@link encode_varint_array}
*
* @example
* ```ts
* import { assertEquals } from "jsr:@std/assert"
*
* // aliasing for brevity
* const u8 = Uint8Array, eq = assertEquals
*
* eq(pack("bool" , true), u8.of(1))
* eq(pack("cstr" , "hello"), u8.of(104, 101, 108, 108, 111, 0))
* eq(pack("str" , "hello"), u8.of(104, 101, 108, 108, 111))
* eq(pack("bytes", u8.of(1, 2, 3)), u8.of(1, 2, 3))
* // NOTE: if your device's native endian is not little-endian, then the test below will fail.
* eq(pack("f8l[]", [1.1, 2.2, 3**45.67]), new u8(Float64Array.of(1.1, 2.2, 3**45.67).buffer))
* ```
*/
export declare const pack: (type: PrimitiveType, value: JSPrimitive, ...args: any[]) => ReturnType<EncodeFunc<JSPrimitive>>;
/** a buffer decoder/unpacker for a primitive value of a certain `type` (see {@link PrimitiveType}).
* this is the inverse of {@link pack}.
*
* under the hood, this function calls one of the following primitive value decoders, based on the `type` that you provide:
* - {@link decode_bool}, {@link decode_cstr}, {@link decode_str}, {@link decode_bytes},
* {@link decode_number}, {@link decode_number_array}, {@link decode_varint}, {@link decode_varint_array}
*
* @example
* ```ts
* import { assertEquals } from "jsr:@std/assert"
*
* // aliasing for brevity
* const u8 = Uint8Array, eq = assertEquals
*
* eq(unpack(
* "bool", // type of value to decode
* u8.of(1, 0, 1), // buffer to decode from
* 1, // the index to begin decoding from
* ), [
* false, // returned decoded value
* 1, // number of bytes traversed while decoding (i.e. byte size of the decoded object)
* ])
*
* eq(unpack("cstr" , u8.of(97, 98, 99, 0, 100, 101), 0), ["abc" , 4])
* eq(unpack("str" , u8.of(97, 98, 99, 0, 100, 101), 0), ["abc\x00de", 6])
* eq(unpack("str" , u8.of(97, 98, 99, 0, 100, 101), 0, 4), ["abc\x00" , 4])
* eq(unpack("bytes", u8.of(0, 1, 2, 3, 4, 5, 6), 2, 4), [u8.of(2, 3, 4, 5), 4])
* eq(unpack("i2b[]", u8.of(0, 1, 2, 3, 4, 5), 2), [[0x0203, 0x0405] , 4])
* eq(unpack("i2b[]", u8.of(0, 1, 2, 3, 4, 5), 0, 2), [[0x0001, 0x0203] , 4])
* ```
*/
export declare const unpack: (type: PrimitiveType, buf: Uint8Array, offset: number, ...args: any[]) => ReturnType<DecodeFunc<JSPrimitive>>;
/** pack a `boolean` as 1-byte of data. */
export declare const encode_bool: EncodeFunc<boolean>;
/** unpack a `boolean` from 1-byte of data. */
export declare const decode_bool: DecodeFunc<boolean>;
/** pack a `string` as an array of characters, terminated by the `"\x00"` (or `"\u0000"`) charbyte.
* this is the traditional c-programming language convention for strings.
*/
export declare const encode_cstr: EncodeFunc<string>;
/** unpack a `string` as an array of characters that's terminated by `"\x00"` (or `"\u0000"`) charbyte.
* this is the traditional c-programming language convention for strings.
*/
export declare const decode_cstr: DecodeFunc<string>;
/** pack a `string` as an array of characters. */
export declare const encode_str: EncodeFunc<string>;
/** unpack a `string` as an array of characters.
* you must provide the `bytesize` of the string being decoded,
* otherwise the decoder will unpack till the end of the buffer.
*/
export declare const decode_str: DecodeFunc<string, [bytesize?: number]>;
/** pack a `Uint8Array` array of bytes as is. (ie: don't perform any operation). */
export declare const encode_bytes: EncodeFunc<Uint8Array>;
/** unpack a `Uint8Array` array of bytes.
* you must provide the `bytesize` of the bytes being decoded,
* otherwise the decoder will unpack till the end of the buffer.
*/
export declare const decode_bytes: DecodeFunc<Uint8Array, [bytesize?: number]>;
/** pack a numeric array (`number[]`) in the provided {@link NumericArrayType} byte representation. */
export declare const encode_number_array: EncodeFunc<number[], [type: NumericArrayType]>;
/** unpack a numeric array (`number[]`) that is encoded in one of {@link NumericArrayType} byte representation.
* you must provide the `array_length` of the array being decoded,
* otherwise the decoder will unpack till the end of the buffer.
*/
export declare const decode_number_array: DecodeFunc<number[], [type: NumericArrayType, array_length?: number]>;
/** pack a `number` in the provided {@link NumericType} byte representation. */
export declare const encode_number: EncodeFunc<number, [type: NumericType]>;
/** unpack a `number` in the provided {@link NumericType} byte representation. */
export declare const decode_number: DecodeFunc<number, [type: NumericType]>;
//# sourceMappingURL=eightpack.d.ts.map