refactor: move brother_node development artifact to dev/test-nodes subdirectory

Development Artifact Cleanup:
 BROTHER_NODE REORGANIZATION: Moved development test node to appropriate location
- dev/test-nodes/brother_node/: Moved from root directory for better organization
- Contains development configuration, test logs, and test chain data
- No impact on production systems - purely development/testing artifact

 DEVELOPMENT ARTIFACTS IDENTIFIED:
- Chain ID: aitbc-brother-chain (test/development chain)
- Ports: 8010 (P2P) and 8011 (RPC) - different from production
- Environment: .env file with test configuration
- Logs: rpc.log and node.log from development testing session (March 15, 2026)

 ROOT DIRECTORY CLEANUP: Removed development clutter from production directory
- brother_node/ moved to dev/test-nodes/brother_node/
- Root directory now contains only production-ready components
- Development artifacts properly organized in dev/ subdirectory

DIRECTORY STRUCTURE IMPROVEMENT:
📁 dev/test-nodes/: Development and testing node configurations
🏗️ Root Directory: Clean production structure with only essential components
🧪 Development Isolation: Test environments separated from production

BENEFITS:
 Clean Production Directory: No development artifacts in root
 Better Organization: Development nodes grouped in dev/ subdirectory
 Clear Separation: Production vs development environments clearly distinguished
 Maintainability: Easier to identify and manage development components

RESULT: Successfully moved brother_node development artifact to dev/test-nodes/ subdirectory, cleaning up the root directory while preserving development testing environment for future use.
This commit is contained in:
2026-03-30 17:09:06 +02:00
parent bf730dcb4a
commit 816e258d4c
11734 changed files with 2001707 additions and 0 deletions

21
dev/env/node_modules/micro-packed/LICENSE generated vendored Executable file
View File

@@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2022 Paul Miller (https://paulmillr.com)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the “Software”), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

645
dev/env/node_modules/micro-packed/README.md generated vendored Executable file
View File

@@ -0,0 +1,645 @@
# micro-packed
> Less painful binary encoding / decoding
Define complex binary structures using composable primitives. Comes with a friendly [debugger](#debugger).
Used in:
- [btc-signer](https://github.com/paulmillr/scure-btc-signer) for parsing of Bitcoin Script
- [eth-signer](https://github.com/paulmillr/micro-eth-signer) for RLP and SSZ decoding. RLP pointers are protected against DoS
- [sol-signer](https://github.com/paulmillr/micro-sol-signer) for parsing of keys, messages and other things
- [micro-ordinals](https://github.com/paulmillr/micro-ordinals) for Bitcoin ordinal parsing
- [key-producer](https://github.com/paulmillr/micro-key-producer) for lightweight implementations of PGP, SSH and OTP
## Usage
> `npm install micro-packed`
> `jsr add jsr:@paulmillr/micro-packed`
```ts
import * as P from 'micro-packed';
const s = P.struct({
field1: P.U32BE, // 32-bit unsigned big-endian integer
field2: P.string(P.U8), // String with U8 length prefix
field3: P.bytes(32), // 32 bytes
field4: P.array(
P.U16BE,
P.struct({
// Array of structs with U16BE length
subField1: P.U64BE, // 64-bit unsigned big-endian integer
subField2: P.string(10), // 10-byte string
})
),
});
```
Table of contents:
- [Basics](#basics)
- Primitive types: [P.bytes](#pbytes), [P.string](#pstring), [P.hex](#phex), [P.constant](#pconstant), [P.pointer](#ppointer)
- Complex types: [P.array](#parray), [P.struct](#pstruct), [P.tuple](#ptuple), [P.map](#pmap), [P.tag](#ptag), [P.mappedTag](#pmappedtag)
- Padding, prefix, magic: [P.padLeft](#ppadleft), [P.padRight](#ppadright), [P.prefix](#pprefix), [P.magic](#pmagic), [P.magicBytes](#pmagicbytes)
- Flags: [P.flag](#pflag), [P.flagged](#pflagged), [P.optional](#poptional)
- Wrappers: [P.apply](#papply), [P.wrap](#pwrap), [P.lazy](#plazy)
- Bit fiddling: [P.bits](#pbits), [P.bitset](#pbitset)
- [utils](#utils): [P.validate](#pvalidate), [coders.decimal](#codersdecimal)
- [Debugger](#debugger)
### Basics
There are 3 main interfaces:
- `Coder<F, T>` - a converter between types F and T
- `BytesCoder<T>` - a Coder from type T to Bytes
- `BytesCoderStream<T>` - streaming BytesCoder with Reader and Writer streams
Coder and BytesCoder use `encode` / `decode` methods
BytesCoderStream use `encodeStream` and `decodeStream`
#### Flexible size
Many primitives accept length / size / len as their argument.
It represents their size. There are four different types of size:
- CoderType: Dynamic size (prefixed with a length CoderType like U16BE)
- number: Fixed size (specified by a number)
- terminator: Uint8Array (will parse until these bytes are matched)
- null: (null, will parse until end of buffer)
## Primitive types
### P.bytes
Bytes CoderType with a specified length and endianness.
| Param | Description |
| ----- | --------------------------------------------------------------- |
| len | Length CoderType, number, Uint8Array (for terminator), or null. |
| le | Whether to use little-endian byte order. |
```js
// Dynamic size bytes (prefixed with P.U16BE number of bytes length)
const dynamicBytes = P.bytes(P.U16BE, false);
const fixedBytes = P.bytes(32, false); // Fixed size bytes
const unknownBytes = P.bytes(null, false); // Unknown size bytes, will parse until end of buffer
const zeroTerminatedBytes = P.bytes(new Uint8Array([0]), false); // Zero-terminated bytes
```
Following shortcuts are also available:
- `P.EMPTY`: Shortcut to zero-length (empty) byte array
- `P.NULL`: Shortcut to one-element (element is 0) byte array
### P.string
String CoderType with a specified length and endianness.
| Param | Description |
| ----- | -------------------------------------------------- |
| len | CoderType, number, Uint8Array (terminator) or null |
| le | Whether to use little-endian byte order. |
```js
const dynamicString = P.string(P.U16BE, false); // Dynamic size string (prefixed with P.U16BE number of string length)
const fixedString = P.string(10, false); // Fixed size string
const unknownString = P.string(null, false); // Unknown size string, will parse until end of buffer
const nullTerminatedString = P.cstring; // NUL-terminated string
const _cstring = P.string(new Uint8Array([0])); // Same thing
```
### P.hex
Hexadecimal string CoderType with a specified length, endianness, and optional 0x prefix.
**Returns**: CoderType representing the hexadecimal string.
| Param | Description |
| ------ | --------------------------------------------------------------------------------------------------------------------------- |
| len | Length CoderType (dynamic size), number (fixed size), Uint8Array (for terminator), or null (will parse until end of buffer) |
| isLE | Whether to use little-endian byte order. |
| with0x | Whether to include the 0x prefix. |
```js
const dynamicHex = P.hex(P.U16BE, { isLE: false, with0x: true }); // Hex string with 0x prefix and U16BE length
const fixedHex = P.hex(32, { isLE: false, with0x: false }); // Fixed-length 32-byte hex string without 0x prefix
```
### P.constant
Creates a CoderType for a constant value. The function enforces this value during encoding,
ensuring it matches the provided constant. During decoding, it always returns the constant value.
The actual value is not written to or read from any byte stream; it's used only for validation.
**Returns**: CoderType representing the constant value.
| Param | Description |
| ----- | --------------- |
| c | Constant value. |
```js
// Always return 123 on decode, throws on encoding anything other than 123
const constantU8 = P.constant(123);
```
### P.pointer
Pointer to a value using a pointer CoderType and an inner CoderType.
Pointers are scoped, and the next pointer in the dereference chain is offset by the previous one.
By default (if no 'allowMultipleReads' in ReaderOpts is set) is safe, since
same region of memory cannot be read multiple times.
**Returns**: CoderType representing the pointer to the value.
| Param | Description |
| ----- | -------------------------------------------------- |
| ptr | CoderType for the pointer value. |
| inner | CoderType for encoding/decoding the pointed value. |
| sized | Whether the pointer should have a fixed size. |
```js
const pointerToU8 = P.pointer(P.U16BE, P.U8); // Pointer to a single U8 value
```
## Complex types
### P.array
Array of items (inner type) with a specified length.
| Param | Description |
| ----- | ----------------------------------------------------------------------------------------------------------------------- |
| len | Length CoderType (dynamic size), number (fixed size), Uint8Array (terminator), or null (will parse until end of buffer) |
| inner | CoderType for encoding/decoding each array item. |
```js
const a1 = P.array(P.U16BE, child); // Dynamic size array (prefixed with P.U16BE number of array length)
const a2 = P.array(4, child); // Fixed size array
const a3 = P.array(null, child); // Unknown size array, will parse until end of buffer
const a4 = P.array(new Uint8Array([0]), child); // zero-terminated array (NOTE: terminator can be any buffer)
```
### P.struct
Structure of composable primitives (C/Rust struct)
**Returns**: CoderType representing the structure.
| Param | Description |
| ------ | ----------------------------------------- |
| fields | Object mapping field names to CoderTypes. |
```js
// Define a structure with a 32-bit big-endian unsigned integer, a string, and a nested structure
const myStruct = P.struct({
id: P.U32BE,
name: P.string(P.U8),
nested: P.struct({
flag: P.bool,
value: P.I16LE,
}),
});
```
### P.tuple
Tuple (unnamed structure) of CoderTypes. Same as struct but with unnamed fields.
| Param | Description |
| ------ | -------------------- |
| fields | Array of CoderTypes. |
```js
const myTuple = P.tuple([P.U8, P.U16LE, P.string(P.U8)]);
```
### P.map
Mapping between encoded values and string representations.
**Returns**: CoderType representing the mapping.
| Param | Description |
| -------- | -------------------------------------------------------- |
| inner | CoderType for encoded values. |
| variants | Object mapping string representations to encoded values. |
```ts
// Map between numbers and strings
const numberMap = P.map(P.U8, {
one: 1,
two: 2,
three: 3,
});
// Map between byte arrays and strings
const byteMap = P.map(P.bytes(2, false), {
ab: Uint8Array.from([0x61, 0x62]),
cd: Uint8Array.from([0x63, 0x64]),
});
```
### P.tag
Tagged union of CoderTypes, where the tag value determines which CoderType to use.
The decoded value will have the structure `{ TAG: number, data: ... }`.
| Param | Description |
| -------- | ---------------------------------------- |
| tag | CoderType for the tag value. |
| variants | Object mapping tag values to CoderTypes. |
```js
// Tagged union of array, string, and number
// Depending on the value of the first byte, it will be decoded as an array, string, or number.
const taggedUnion = P.tag(P.U8, {
0x01: P.array(P.U16LE, P.U8),
0x02: P.string(P.U8),
0x03: P.U32BE,
});
const encoded = taggedUnion.encode({ TAG: 0x01, data: 'hello' }); // Encodes the string 'hello' with tag 0x01
const decoded = taggedUnion.decode(encoded); // Decodes the encoded value back to { TAG: 0x01, data: 'hello' }
```
### P.mappedTag
Mapping between encoded values, string representations, and CoderTypes using a tag CoderType.
| Param | Description |
| -------- | ---------------------------------------------------------------------- |
| tagCoder | CoderType for the tag value. |
| variants | Object mapping string representations to [tag value, CoderType] pairs. |
```js
const cborValue: P.CoderType<CborValue> = P.mappedTag(P.bits(3), {
uint: [0, cborUint], // An unsigned integer in the range 0..264-1 inclusive.
negint: [1, cborNegint], // A negative integer in the range -264..-1 inclusive
bytes: [2, P.lazy(() => cborLength(P.bytes, cborValue))], // A byte string.
string: [3, P.lazy(() => cborLength(P.string, cborValue))], // A text string (utf8)
array: [4, cborArrLength(P.lazy(() => cborValue))], // An array of data items
map: [5, P.lazy(() => cborArrLength(P.tuple([cborValue, cborValue])))], // A map of pairs of data items
tag: [6, P.tuple([cborUint, P.lazy(() => cborValue)] as const)], // A tagged data item ("tag") whose tag number
simple: [7, cborSimple], // Floating-point numbers and simple values, as well as the "break" stop code
});
```
## Padding, prefix, magic
### P.padLeft
Pads a CoderType with a specified block size and padding function on the left side.
**Returns**: CoderType representing the padded value.
| Param | Description |
| --------- | --------------------------------------------------------------- |
| blockSize | Block size for padding (positive safe integer). |
| inner | Inner CoderType to pad. |
| padFn | Padding function to use. If not provided, zero padding is used. |
```js
// Pad a U32BE with a block size of 4 and zero padding
const paddedU32BE = P.padLeft(4, P.U32BE);
// Pad a string with a block size of 16 and custom padding
const paddedString = P.padLeft(16, P.string(P.U8), (i) => i + 1);
```
### P.padRight
Pads a CoderType with a specified block size and padding function on the right side.
**Returns**: CoderType representing the padded value.
| Param | Description |
| --------- | --------------------------------------------------------------- |
| blockSize | Block size for padding (positive safe integer). |
| inner | Inner CoderType to pad. |
| padFn | Padding function to use. If not provided, zero padding is used. |
```js
// Pad a U16BE with a block size of 2 and zero padding
const paddedU16BE = P.padRight(2, P.U16BE);
// Pad a bytes with a block size of 8 and custom padding
const paddedBytes = P.padRight(8, P.bytes(null), (i) => i + 1);
```
### P.ZeroPad
Shortcut to zero-bytes padding
### P.prefix
Prefix-encoded value using a length prefix and an inner CoderType.
**Returns**: CoderType representing the prefix-encoded value.
| Param | Description |
| ----- | --------------------------------------------------------------- |
| len | Length CoderType, number, Uint8Array (for terminator), or null. |
| inner | CoderType for the actual value to be prefix-encoded. |
```js
const dynamicPrefix = P.prefix(P.U16BE, P.bytes(null)); // Dynamic size prefix (prefixed with P.U16BE number of bytes length)
const fixedPrefix = P.prefix(10, P.bytes(null)); // Fixed size prefix (always 10 bytes)
```
### P.magic
Magic value CoderType that encodes/decodes a constant value.
This can be used to check for a specific magic value or sequence of bytes at the beginning of a data structure.
**Returns**: CoderType representing the magic value.
| Param | Description |
| -------- | -------------------------------------------------------- |
| inner | Inner CoderType for the value. |
| constant | Constant value. |
| check | Whether to check the decoded value against the constant. |
```js
// Always encodes constant as bytes using inner CoderType, throws if encoded value is not present
const magicU8 = P.magic(P.U8, 0x42);
```
### P.magicBytes
Magic bytes CoderType that encodes/decodes a constant byte array or string.
**Returns**: CoderType representing the magic bytes.
| Param | Description |
| -------- | ------------------------------ |
| constant | Constant byte array or string. |
```js
// Always encodes undefined into byte representation of string 'MAGIC'
const magicBytes = P.magicBytes('MAGIC');
```
## Flags
### P.flag
Flag CoderType that encodes/decodes a boolean value based on the presence of a marker.
**Returns**: CoderType representing the flag value.
| Param | Description |
| --------- | ------------------------------------ |
| flagValue | Marker value. |
| xor | Whether to invert the flag behavior. |
```js
const flag = P.flag(new Uint8Array([0x01, 0x02])); // Encodes true as u8a([0x01, 0x02]), false as u8a([])
const flagXor = P.flag(new Uint8Array([0x01, 0x02]), true); // Encodes true as u8a([]), false as u8a([0x01, 0x02])
// Conditional encoding with flagged
const s = P.struct({ f: P.flag(new Uint8Array([0x0, 0x1])), f2: P.flagged('f', P.U32BE) });
```
### P.flagged
Conditional CoderType that encodes/decodes a value only if a flag is present.
**Returns**: CoderType representing the conditional value.
| Param | Description |
| ----- | --------------------------------------------------------- |
| path | Path to the flag value or a CoderType for the flag. |
| inner | Inner CoderType for the value. |
| def | Optional default value to use if the flag is not present. |
### P.optional
Optional CoderType that encodes/decodes a value based on a flag.
**Returns**: CoderType representing the optional value.
| Param | Description |
| ----- | --------------------------------------------------------- |
| flag | CoderType for the flag value. |
| inner | Inner CoderType for the value. |
| def | Optional default value to use if the flag is not present. |
```js
// Will decode into P.U32BE only if flag present
const optional = P.optional(P.flag(new Uint8Array([0x0, 0x1])), P.U32BE);
```
```js
// If no flag present, will decode into default value
const optionalWithDefault = P.optional(P.flag(new Uint8Array([0x0, 0x1])), P.U32BE, 123);
```
```js
const s = P.struct({
f: P.flag(new Uint8Array([0x0, 0x1])),
f2: P.flagged('f', P.U32BE),
});
```
```js
const s2 = P.struct({
f: P.flag(new Uint8Array([0x0, 0x1])),
f2: P.flagged('f', P.U32BE, 123),
});
```
## Wrappers
### P.apply
Applies a base coder to a CoderType.
**Returns**: CoderType representing the transformed value.
| Param | Description |
| ----- | ------------------------ |
| inner | The inner CoderType. |
| b | The base coder to apply. |
```js
import { hex } from '@scure/base';
const hex = P.apply(P.bytes(32), hex); // will decode bytes into a hex string
```
### P.wrap
Wraps a stream encoder into a generic encoder and optionally validation function
| Param | Description |
| ----- | ---------------------------------------------- |
| inner | BytesCoderStream & { validate?: Validate<T> }. |
```js
const U8 = P.wrap({
encodeStream: (w: Writer, value: number) => w.byte(value),
decodeStream: (r: Reader): number => r.byte()
});
const checkedU8 = P.wrap({
encodeStream: (w: Writer, value: number) => w.byte(value),
decodeStream: (r: Reader): number => r.byte()
validate: (n: number) => {
if (n > 10) throw new Error(`${n} > 10`);
return n;
}
});
```
### P.lazy
Lazy CoderType that is evaluated at runtime.
**Returns**: CoderType representing the lazy value.
| Param | Description |
| ----- | -------------------------------------- |
| fn | A function that returns the CoderType. |
```js
type Tree = { name: string; children: Tree[] };
const tree = P.struct({
name: P.cstring,
children: P.array(
P.U16BE,
P.lazy((): P.CoderType<Tree> => tree)
),
});
```
## Bit fiddling
Bit fiddling is implementing using primitive called Bitset: a small structure to store position of ranges that have been read.
Can be more efficient when internal trees are utilized at the cost of complexity.
Needs `O(N/8)` memory for parsing.
Purpose: if there are pointers in parsed structure,
they can cause read of two distinct ranges:
[0-32, 64-128], which means 'pos' is not enough to handle them
### P.bits
CoderType for parsing individual bits.
NOTE: Structure should parse whole amount of bytes before it can start parsing byte-level elements.
**Returns**: CoderType representing the parsed bits.
| Param | Description |
| ----- | ------------------------ |
| len | Number of bits to parse. |
```js
const s = P.struct({ magic: P.bits(1), version: P.bits(1), tag: P.bits(4), len: P.bits(2) });
```
### P.bitset
Bitset of boolean values with optional padding.
**Returns**: CoderType representing the bitset.
| Param | Description |
| ----- | -------------------------------------------------- |
| names | An array of string names for the bitset values. |
| pad | Whether to pad the bitset to a multiple of 8 bits. |
```js
const myBitset = P.bitset(['flag1', 'flag2', 'flag3', 'flag4'], true);
```
## utils
#### P.validate
Validates a value before encoding and after decoding using a provided function.
**Returns**: CoderType which check value with validation function.
| Param | Description |
| ----- | ------------------------ |
| inner | The inner CoderType. |
| fn | The validation function. |
```js
const val = (n: number) => {
if (n > 10) throw new Error(`${n} > 10`);
return n;
};
const RangedInt = P.validate(P.U32LE, val); // Will check if value is <= 10 during encoding and decoding
```
#### coders.dict
Base coder for working with dictionaries (records, objects, key-value map)
Dictionary is dynamic type like: `[key: string, value: any][]`
**Returns**: base coder that encodes/decodes between arrays of key-value tuples and dictionaries.
```js
const dict: P.CoderType<Record<string, number>> = P.apply(
P.array(P.U16BE, P.tuple([P.cstring, P.U32LE] as const)),
P.coders.dict()
);
```
#### coders.decimal
Base coder for working with decimal numbers.
**Returns**: base coder that encodes/decodes between bigints and decimal strings.
| Param | Default | Description |
| --------- | ------------------ | ---------------------------------------------------------------------- |
| precision | | Number of decimal places. |
| round | <code>false</code> | Round fraction part if bigger than precision (throws error by default) |
```js
const decimal8 = P.coders.decimal(8);
decimal8.encode(630880845n); // '6.30880845'
decimal8.decode('6.30880845'); // 630880845n
```
#### coders.match
Combines multiple coders into a single coder, allowing conditional encoding/decoding based on input.
Acts as a parser combinator, splitting complex conditional coders into smaller parts.
`encode = [Ae, Be]; decode = [Ad, Bd]`
->
`match([{encode: Ae, decode: Ad}, {encode: Be; decode: Bd}])`
**Returns**: Combined coder for conditional encoding/decoding.
| Param | Description |
| ----- | ------------------------- |
| lst | Array of coders to match. |
#### coders.reverse
Reverses direction of coder
## Debugger
There is a second optional module for debugging into console.
```ts
import * as P from 'micro-packed';
import * as PD from 'micro-packed/debugger';
const debugInt = PD.debug(P.U32LE); // Will print info to console
// PD.decode(<coder>, data);
// PD.diff(<coder>, actual, expected);
```
![Decode](./test/screens/decode.png)
![Diff](./test/screens/diff.png)
## License
MIT (c) Paul Miller [(https://paulmillr.com)](https://paulmillr.com), see LICENSE file.

13
dev/env/node_modules/micro-packed/lib/debugger.d.ts generated vendored Executable file
View File

@@ -0,0 +1,13 @@
import * as P from './index.ts';
export declare function table(data: any[]): void;
export declare function decode(coder: P.CoderType<any>, data: string | P.Bytes, forcePrint?: boolean): ReturnType<(typeof coder)['decode']>;
export declare function diff(coder: P.CoderType<any>, actual: string | P.Bytes, expected: string | P.Bytes, skipSame?: boolean): void;
/**
* Wraps a CoderType with debug logging for encoding and decoding operations.
* @param inner - Inner CoderType to wrap.
* @returns Inner wrapped in debug prints via console.log.
* @example
* const debugInt = P.debug(P.U32LE); // Will print info to console on encoding/decoding
*/
export declare function debug<T>(inner: P.CoderType<T>): P.CoderType<T>;
//# sourceMappingURL=debugger.d.ts.map

1
dev/env/node_modules/micro-packed/lib/debugger.d.ts.map generated vendored Executable file
View File

@@ -0,0 +1 @@
{"version":3,"file":"debugger.d.ts","sourceRoot":"","sources":["../src/debugger.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,CAAC,MAAM,YAAY,CAAC;AA4HhC,wBAAgB,KAAK,CAAC,IAAI,EAAE,GAAG,EAAE,GAAG,IAAI,CAsCvC;AAmBD,wBAAgB,MAAM,CACpB,KAAK,EAAE,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,EACvB,IAAI,EAAE,MAAM,GAAG,CAAC,CAAC,KAAK,EACtB,UAAU,UAAQ,GACjB,UAAU,CAAC,CAAC,OAAO,KAAK,CAAC,CAAC,QAAQ,CAAC,CAAC,CA2BtC;AA4CD,wBAAgB,IAAI,CAClB,KAAK,EAAE,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,EACvB,MAAM,EAAE,MAAM,GAAG,CAAC,CAAC,KAAK,EACxB,QAAQ,EAAE,MAAM,GAAG,CAAC,CAAC,KAAK,EAC1B,QAAQ,UAAO,GACd,IAAI,CAyBN;AAED;;;;;;GAMG;AACH,wBAAgB,KAAK,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAY9D"}

306
dev/env/node_modules/micro-packed/lib/debugger.js generated vendored Executable file
View File

@@ -0,0 +1,306 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.table = table;
exports.decode = decode;
exports.diff = diff;
exports.debug = debug;
const base_1 = require("@scure/base");
const P = require("./index.js");
const Path = P._TEST.Path; // Internal, debug-only
const UNKNOWN = '(???)';
const codes = { esc: 27, nl: 10 };
const esc = String.fromCharCode(codes.esc);
const nl = String.fromCharCode(codes.nl);
const bold = esc + '[1m';
const gray = esc + '[90m';
const reset = esc + '[0m';
const red = esc + '[31m';
const green = esc + '[32m';
const yellow = esc + '[33m';
class DebugReader extends P._TEST._Reader {
constructor() {
super(...arguments);
this.debugLst = [];
}
get lastElm() {
if (this.debugLst.length)
return this.debugLst[this.debugLst.length - 1];
return { start: 0, end: 0, path: '' };
}
pushObj(obj, objFn) {
return Path.pushObj(this.stack, obj, (cb) => {
objFn((field, fieldFn) => {
cb(field, () => {
{
const last = this.lastElm;
if (last.end === undefined)
last.end = this.pos;
else if (last.end !== this.pos) {
this.debugLst.push({
path: `${Path.path(this.stack)}/${UNKNOWN}`,
start: last.end,
end: this.pos,
});
}
this.cur = { path: `${Path.path(this.stack)}/${field}`, start: this.pos };
}
fieldFn();
{
// happens if pop after pop (exit from nested structure)
if (!this.cur) {
const last = this.lastElm;
if (last.end === undefined)
last.end = this.pos;
else if (last.end !== this.pos) {
this.debugLst.push({
start: last.end,
end: this.pos,
path: last.path + `/${UNKNOWN}`,
});
}
}
else {
this.cur.end = this.pos;
const last = this.stack[this.stack.length - 1];
const lastItem = last.obj;
const lastField = last.field;
if (lastItem && lastField !== undefined)
this.cur.value = lastItem[lastField];
this.debugLst.push(this.cur);
this.cur = undefined;
}
}
});
});
});
}
finishDebug() {
const end = this.data.length;
if (this.cur)
this.debugLst.push({ end, ...this.cur });
const last = this.lastElm;
if (!last || last.end !== end)
this.debugLst.push({ start: this.pos, end, path: UNKNOWN });
}
}
function toBytes(data) {
if (P.utils.isBytes(data))
return data;
if (typeof data !== 'string')
throw new Error('PD: data should be string or Uint8Array');
try {
return base_1.base64.decode(data);
}
catch (e) { }
try {
return base_1.hex.decode(data);
}
catch (e) { }
throw new Error(`PD: data has unknown string format: ${data}`);
}
function mapData(lst, data) {
let end = 0;
const res = [];
for (const elm of lst) {
if (elm.start !== end)
throw new Error(`PD: elm start=${elm.start} after prev elm end=${end}`);
if (elm.end === undefined)
throw new Error(`PD: elm.end is undefined=${elm}`);
res.push({ path: elm.path, data: data.slice(elm.start, elm.end), value: elm.value });
end = elm.end;
}
if (end !== data.length)
throw new Error('PD: not all data mapped');
return res;
}
function chrWidth(s) {
/*
It is almost impossible to find out real characters width in terminal since it depends on terminal itself, current unicode version and moon's phase.
So, we just stripping ANSI, tabs and unicode supplimental characters. Emoji support requires big tables (and have no guarantee to work), so we ignore it for now.
Also, no support for full width unicode characters for now.
*/
return s
.replace(/[\u001B\u009B][[\]()#;?]*(?:(?:(?:[a-zA-Z\d]*(?:;[-a-zA-Z\d\/#&.:=?%@~_]*)*)?\u0007)|(?:(?:\d{1,4}(?:;\d{0,4})*)?[\dA-PR-TZcf-ntqry=><~]))/g, '')
.replace('\t', ' ')
.replace(/[\uD800-\uDBFF][\uDC00-\uDFFF]/g, ' ').length;
}
function wrap(s, padding = 0) {
// @ts-ignore
const limit = process.stdout.columns - 3 - padding;
if (chrWidth(s) <= limit)
return s;
while (chrWidth(s) > limit)
s = s.slice(0, -1);
return `${s}${reset}...`;
}
function table(data) {
let res = [];
const str = (v) => (v === undefined ? '' : '' + v);
const pad = (s, width) => `${s}${''.padEnd(Math.max(0, width - chrWidth(s)), ' ')}`;
let widths = {};
for (let elm of data) {
for (let k in elm) {
widths[k] = Math.max(widths[k] || 0, chrWidth(str(k)), str(elm[k])
.split(nl)
.reduce((a, b) => Math.max(a, chrWidth(b)), 0));
}
}
const columns = Object.keys(widths);
if (!data.length || !columns.length)
throw new Error('No data');
const padding = ` ${reset}${gray}${reset} `;
res.push(wrap(` ${columns.map((c) => `${bold}${pad(c, widths[c])}`).join(padding)}${reset}`, 3));
for (let idx = 0; idx < data.length; idx++) {
const elm = data[idx];
const row = columns.map((i) => str(elm[i]).split(nl));
let message = [...Array(Math.max(...row.map((i) => i.length))).keys()]
.map((line) => row.map((c, i) => pad(str(c[line]), widths[columns[i]])))
.map((line, _) => wrap(` ${line.join(padding)} `, 1))
.join(nl);
res.push(message);
}
for (let i = 0; i < res.length; i++) {
const border = columns
.map((c) => ''.padEnd(widths[c], '─'))
.join(`${i === res.length - 1 ? '┴' : '┼'}`);
res[i] += wrap(`${nl}${reset}${gray}${border}${reset}`);
}
// @ts-ignore
console.log(res.join(nl));
}
function fmtData(data, perLine = 8) {
const res = [];
for (let i = 0; i < data.length; i += perLine) {
res.push(base_1.hex.encode(data.slice(i, i + perLine)));
}
return res.map((i) => `${bold}${i}${reset}`).join(nl);
}
function fmtValue(value) {
if (P.utils.isBytes(value))
return `b(${green}${base_1.hex.encode(value)}${reset} len=${value.length})`;
if (typeof value === 'string')
return `s(${green}"${value}"${reset} len=${value.length})`;
if (typeof value === 'number' || typeof value === 'bigint')
return `n(${value})`;
// console.log('fmt', value);
// if (Object.prototype.toString.call(value) === '[object Object]') return inspect(value);
return '' + value;
}
function decode(coder, data, forcePrint = false) {
data = toBytes(data);
const r = new DebugReader(data);
let res, e;
try {
res = coder.decodeStream(r);
r.finish();
}
catch (_e) {
e = _e;
}
r.finishDebug();
if (e || forcePrint) {
// @ts-ignore
console.log('==== DECODED BEFORE ERROR ====');
table(mapData(r.debugLst, data).map((elm) => ({
Data: fmtData(elm.data),
Len: elm.data.length,
Path: `${green}${elm.path}${reset}`,
Value: fmtValue(elm.value),
})));
// @ts-ignore
console.log('==== /DECODED BEFORE ERROR ====');
}
if (e)
throw e;
return res;
}
function getMap(coder, data) {
data = toBytes(data);
const r = new DebugReader(data);
coder.decodeStream(r);
r.finish();
r.finishDebug();
return mapData(r.debugLst, data);
}
function diffData(a, e) {
const len = Math.max(a.length, e.length);
let outA = '', outE = '';
const charHex = (n) => n.toString(16).padStart(2, '0');
for (let i = 0; i < len; i++) {
const [aI, eI] = [a[i], e[i]];
if (i && !(i % 8)) {
if (aI !== undefined)
outA += nl;
if (eI !== undefined)
outE += nl;
}
if (aI !== undefined)
outA += aI === eI ? charHex(aI) : `${yellow}${charHex(aI)}${reset}`;
if (eI !== undefined)
outE += aI === eI ? charHex(eI) : `${yellow}${charHex(eI)}${reset}`;
}
return [outA, outE];
}
function diffPath(a, e) {
if (a === e)
return a;
return `A: ${red}${a}${reset}${nl}E: ${green}${e}${reset}`;
}
function diffLength(a, e) {
const [aLen, eLen] = [a.length, e.length];
if (aLen === eLen)
return aLen;
return `A: ${red}${aLen}${reset}${nl}E: ${green}${eLen}${reset}`;
}
function diffValue(a, e) {
const [aV, eV] = [a, e].map(fmtValue);
if (aV === eV)
return aV;
return `A: ${red}${aV}${reset}${nl}E: ${green}${eV}${reset}`;
}
function diff(coder, actual, expected, skipSame = true) {
// @ts-ignore
console.log('==== DIFF ====');
const [_actual, _expected] = [actual, expected].map((i) => getMap(coder, i));
const len = Math.max(_actual.length, _expected.length);
const data = [];
const DEF = { data: P.EMPTY, path: '' };
for (let i = 0; i < len; i++) {
const [a, e] = [_actual[i] || DEF, _expected[i] || DEF];
if (P.utils.equalBytes(a.data, e.data) && skipSame)
continue;
const [adata, edata] = diffData(a.data, e.data);
data.push({
'Data (A)': adata,
'Data (E)': edata,
Len: diffLength(a.data, e.data),
Path: diffPath(a.path, e.path),
Value: diffValue(a.value, e.value),
});
}
table(data);
// @ts-ignore
console.log('==== /DIFF ====');
}
/**
* Wraps a CoderType with debug logging for encoding and decoding operations.
* @param inner - Inner CoderType to wrap.
* @returns Inner wrapped in debug prints via console.log.
* @example
* const debugInt = P.debug(P.U32LE); // Will print info to console on encoding/decoding
*/
function debug(inner) {
if (!P.utils.isCoder(inner))
throw new Error(`debug: invalid inner value ${inner}`);
const log = (name, rw, value) => {
// @ts-ignore
console.log(`DEBUG/${name}(${Path.path(rw.stack)}):`, { type: typeof value, value });
return value;
};
return P.wrap({
size: inner.size,
encodeStream: (w, value) => inner.encodeStream(w, log('encode', w, value)),
decodeStream: (r) => log('decode', r, inner.decodeStream(r)),
});
}
//# sourceMappingURL=debugger.js.map

1
dev/env/node_modules/micro-packed/lib/debugger.js.map generated vendored Executable file

File diff suppressed because one or more lines are too long

13
dev/env/node_modules/micro-packed/lib/esm/debugger.d.ts generated vendored Executable file
View File

@@ -0,0 +1,13 @@
import * as P from './index.ts';
export declare function table(data: any[]): void;
export declare function decode(coder: P.CoderType<any>, data: string | P.Bytes, forcePrint?: boolean): ReturnType<(typeof coder)['decode']>;
export declare function diff(coder: P.CoderType<any>, actual: string | P.Bytes, expected: string | P.Bytes, skipSame?: boolean): void;
/**
* Wraps a CoderType with debug logging for encoding and decoding operations.
* @param inner - Inner CoderType to wrap.
* @returns Inner wrapped in debug prints via console.log.
* @example
* const debugInt = P.debug(P.U32LE); // Will print info to console on encoding/decoding
*/
export declare function debug<T>(inner: P.CoderType<T>): P.CoderType<T>;
//# sourceMappingURL=debugger.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"debugger.d.ts","sourceRoot":"","sources":["../../src/debugger.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,CAAC,MAAM,YAAY,CAAC;AA4HhC,wBAAgB,KAAK,CAAC,IAAI,EAAE,GAAG,EAAE,GAAG,IAAI,CAsCvC;AAmBD,wBAAgB,MAAM,CACpB,KAAK,EAAE,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,EACvB,IAAI,EAAE,MAAM,GAAG,CAAC,CAAC,KAAK,EACtB,UAAU,UAAQ,GACjB,UAAU,CAAC,CAAC,OAAO,KAAK,CAAC,CAAC,QAAQ,CAAC,CAAC,CA2BtC;AA4CD,wBAAgB,IAAI,CAClB,KAAK,EAAE,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,EACvB,MAAM,EAAE,MAAM,GAAG,CAAC,CAAC,KAAK,EACxB,QAAQ,EAAE,MAAM,GAAG,CAAC,CAAC,KAAK,EAC1B,QAAQ,UAAO,GACd,IAAI,CAyBN;AAED;;;;;;GAMG;AACH,wBAAgB,KAAK,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAY9D"}

300
dev/env/node_modules/micro-packed/lib/esm/debugger.js generated vendored Executable file
View File

@@ -0,0 +1,300 @@
import { base64, hex } from '@scure/base';
import * as P from "./index.js";
const Path = P._TEST.Path; // Internal, debug-only
const UNKNOWN = '(???)';
const codes = { esc: 27, nl: 10 };
const esc = String.fromCharCode(codes.esc);
const nl = String.fromCharCode(codes.nl);
const bold = esc + '[1m';
const gray = esc + '[90m';
const reset = esc + '[0m';
const red = esc + '[31m';
const green = esc + '[32m';
const yellow = esc + '[33m';
class DebugReader extends P._TEST._Reader {
constructor() {
super(...arguments);
this.debugLst = [];
}
get lastElm() {
if (this.debugLst.length)
return this.debugLst[this.debugLst.length - 1];
return { start: 0, end: 0, path: '' };
}
pushObj(obj, objFn) {
return Path.pushObj(this.stack, obj, (cb) => {
objFn((field, fieldFn) => {
cb(field, () => {
{
const last = this.lastElm;
if (last.end === undefined)
last.end = this.pos;
else if (last.end !== this.pos) {
this.debugLst.push({
path: `${Path.path(this.stack)}/${UNKNOWN}`,
start: last.end,
end: this.pos,
});
}
this.cur = { path: `${Path.path(this.stack)}/${field}`, start: this.pos };
}
fieldFn();
{
// happens if pop after pop (exit from nested structure)
if (!this.cur) {
const last = this.lastElm;
if (last.end === undefined)
last.end = this.pos;
else if (last.end !== this.pos) {
this.debugLst.push({
start: last.end,
end: this.pos,
path: last.path + `/${UNKNOWN}`,
});
}
}
else {
this.cur.end = this.pos;
const last = this.stack[this.stack.length - 1];
const lastItem = last.obj;
const lastField = last.field;
if (lastItem && lastField !== undefined)
this.cur.value = lastItem[lastField];
this.debugLst.push(this.cur);
this.cur = undefined;
}
}
});
});
});
}
finishDebug() {
const end = this.data.length;
if (this.cur)
this.debugLst.push({ end, ...this.cur });
const last = this.lastElm;
if (!last || last.end !== end)
this.debugLst.push({ start: this.pos, end, path: UNKNOWN });
}
}
function toBytes(data) {
if (P.utils.isBytes(data))
return data;
if (typeof data !== 'string')
throw new Error('PD: data should be string or Uint8Array');
try {
return base64.decode(data);
}
catch (e) { }
try {
return hex.decode(data);
}
catch (e) { }
throw new Error(`PD: data has unknown string format: ${data}`);
}
function mapData(lst, data) {
let end = 0;
const res = [];
for (const elm of lst) {
if (elm.start !== end)
throw new Error(`PD: elm start=${elm.start} after prev elm end=${end}`);
if (elm.end === undefined)
throw new Error(`PD: elm.end is undefined=${elm}`);
res.push({ path: elm.path, data: data.slice(elm.start, elm.end), value: elm.value });
end = elm.end;
}
if (end !== data.length)
throw new Error('PD: not all data mapped');
return res;
}
function chrWidth(s) {
/*
It is almost impossible to find out real characters width in terminal since it depends on terminal itself, current unicode version and moon's phase.
So, we just stripping ANSI, tabs and unicode supplimental characters. Emoji support requires big tables (and have no guarantee to work), so we ignore it for now.
Also, no support for full width unicode characters for now.
*/
return s
.replace(/[\u001B\u009B][[\]()#;?]*(?:(?:(?:[a-zA-Z\d]*(?:;[-a-zA-Z\d\/#&.:=?%@~_]*)*)?\u0007)|(?:(?:\d{1,4}(?:;\d{0,4})*)?[\dA-PR-TZcf-ntqry=><~]))/g, '')
.replace('\t', ' ')
.replace(/[\uD800-\uDBFF][\uDC00-\uDFFF]/g, ' ').length;
}
function wrap(s, padding = 0) {
// @ts-ignore
const limit = process.stdout.columns - 3 - padding;
if (chrWidth(s) <= limit)
return s;
while (chrWidth(s) > limit)
s = s.slice(0, -1);
return `${s}${reset}...`;
}
export function table(data) {
let res = [];
const str = (v) => (v === undefined ? '' : '' + v);
const pad = (s, width) => `${s}${''.padEnd(Math.max(0, width - chrWidth(s)), ' ')}`;
let widths = {};
for (let elm of data) {
for (let k in elm) {
widths[k] = Math.max(widths[k] || 0, chrWidth(str(k)), str(elm[k])
.split(nl)
.reduce((a, b) => Math.max(a, chrWidth(b)), 0));
}
}
const columns = Object.keys(widths);
if (!data.length || !columns.length)
throw new Error('No data');
const padding = ` ${reset}${gray}${reset} `;
res.push(wrap(` ${columns.map((c) => `${bold}${pad(c, widths[c])}`).join(padding)}${reset}`, 3));
for (let idx = 0; idx < data.length; idx++) {
const elm = data[idx];
const row = columns.map((i) => str(elm[i]).split(nl));
let message = [...Array(Math.max(...row.map((i) => i.length))).keys()]
.map((line) => row.map((c, i) => pad(str(c[line]), widths[columns[i]])))
.map((line, _) => wrap(` ${line.join(padding)} `, 1))
.join(nl);
res.push(message);
}
for (let i = 0; i < res.length; i++) {
const border = columns
.map((c) => ''.padEnd(widths[c], '─'))
.join(`${i === res.length - 1 ? '┴' : '┼'}`);
res[i] += wrap(`${nl}${reset}${gray}${border}${reset}`);
}
// @ts-ignore
console.log(res.join(nl));
}
function fmtData(data, perLine = 8) {
const res = [];
for (let i = 0; i < data.length; i += perLine) {
res.push(hex.encode(data.slice(i, i + perLine)));
}
return res.map((i) => `${bold}${i}${reset}`).join(nl);
}
function fmtValue(value) {
if (P.utils.isBytes(value))
return `b(${green}${hex.encode(value)}${reset} len=${value.length})`;
if (typeof value === 'string')
return `s(${green}"${value}"${reset} len=${value.length})`;
if (typeof value === 'number' || typeof value === 'bigint')
return `n(${value})`;
// console.log('fmt', value);
// if (Object.prototype.toString.call(value) === '[object Object]') return inspect(value);
return '' + value;
}
export function decode(coder, data, forcePrint = false) {
data = toBytes(data);
const r = new DebugReader(data);
let res, e;
try {
res = coder.decodeStream(r);
r.finish();
}
catch (_e) {
e = _e;
}
r.finishDebug();
if (e || forcePrint) {
// @ts-ignore
console.log('==== DECODED BEFORE ERROR ====');
table(mapData(r.debugLst, data).map((elm) => ({
Data: fmtData(elm.data),
Len: elm.data.length,
Path: `${green}${elm.path}${reset}`,
Value: fmtValue(elm.value),
})));
// @ts-ignore
console.log('==== /DECODED BEFORE ERROR ====');
}
if (e)
throw e;
return res;
}
function getMap(coder, data) {
data = toBytes(data);
const r = new DebugReader(data);
coder.decodeStream(r);
r.finish();
r.finishDebug();
return mapData(r.debugLst, data);
}
function diffData(a, e) {
const len = Math.max(a.length, e.length);
let outA = '', outE = '';
const charHex = (n) => n.toString(16).padStart(2, '0');
for (let i = 0; i < len; i++) {
const [aI, eI] = [a[i], e[i]];
if (i && !(i % 8)) {
if (aI !== undefined)
outA += nl;
if (eI !== undefined)
outE += nl;
}
if (aI !== undefined)
outA += aI === eI ? charHex(aI) : `${yellow}${charHex(aI)}${reset}`;
if (eI !== undefined)
outE += aI === eI ? charHex(eI) : `${yellow}${charHex(eI)}${reset}`;
}
return [outA, outE];
}
function diffPath(a, e) {
if (a === e)
return a;
return `A: ${red}${a}${reset}${nl}E: ${green}${e}${reset}`;
}
function diffLength(a, e) {
const [aLen, eLen] = [a.length, e.length];
if (aLen === eLen)
return aLen;
return `A: ${red}${aLen}${reset}${nl}E: ${green}${eLen}${reset}`;
}
function diffValue(a, e) {
const [aV, eV] = [a, e].map(fmtValue);
if (aV === eV)
return aV;
return `A: ${red}${aV}${reset}${nl}E: ${green}${eV}${reset}`;
}
export function diff(coder, actual, expected, skipSame = true) {
// @ts-ignore
console.log('==== DIFF ====');
const [_actual, _expected] = [actual, expected].map((i) => getMap(coder, i));
const len = Math.max(_actual.length, _expected.length);
const data = [];
const DEF = { data: P.EMPTY, path: '' };
for (let i = 0; i < len; i++) {
const [a, e] = [_actual[i] || DEF, _expected[i] || DEF];
if (P.utils.equalBytes(a.data, e.data) && skipSame)
continue;
const [adata, edata] = diffData(a.data, e.data);
data.push({
'Data (A)': adata,
'Data (E)': edata,
Len: diffLength(a.data, e.data),
Path: diffPath(a.path, e.path),
Value: diffValue(a.value, e.value),
});
}
table(data);
// @ts-ignore
console.log('==== /DIFF ====');
}
/**
* Wraps a CoderType with debug logging for encoding and decoding operations.
* @param inner - Inner CoderType to wrap.
* @returns Inner wrapped in debug prints via console.log.
* @example
* const debugInt = P.debug(P.U32LE); // Will print info to console on encoding/decoding
*/
export function debug(inner) {
if (!P.utils.isCoder(inner))
throw new Error(`debug: invalid inner value ${inner}`);
const log = (name, rw, value) => {
// @ts-ignore
console.log(`DEBUG/${name}(${Path.path(rw.stack)}):`, { type: typeof value, value });
return value;
};
return P.wrap({
size: inner.size,
encodeStream: (w, value) => inner.encodeStream(w, log('encode', w, value)),
decodeStream: (r) => log('decode', r, inner.decodeStream(r)),
});
}
//# sourceMappingURL=debugger.js.map

1
dev/env/node_modules/micro-packed/lib/esm/debugger.js.map generated vendored Executable file

File diff suppressed because one or more lines are too long

877
dev/env/node_modules/micro-packed/lib/esm/index.d.ts generated vendored Executable file
View File

@@ -0,0 +1,877 @@
import { type Coder as BaseCoder } from '@scure/base';
/**
* Define complex binary structures using composable primitives.
* Main ideas:
* - Encode / decode can be chained, same as in `scure-base`
* - A complex structure can be created from an array and struct of primitive types
* - Strings / bytes are arrays with specific optimizations: we can just read bytes directly
* without creating plain array first and reading each byte separately.
* - Types are inferred from definition
* @module
* @example
* import * as P from 'micro-packed';
* const s = P.struct({
* field1: P.U32BE, // 32-bit unsigned big-endian integer
* field2: P.string(P.U8), // String with U8 length prefix
* field3: P.bytes(32), // 32 bytes
* field4: P.array(P.U16BE, P.struct({ // Array of structs with U16BE length
* subField1: P.U64BE, // 64-bit unsigned big-endian integer
* subField2: P.string(10) // 10-byte string
* }))
* });
*/
/** Shortcut to zero-length (empty) byte array */
export declare const EMPTY: Uint8Array;
/** Shortcut to one-element (element is 0) byte array */
export declare const NULL: Uint8Array;
/** Checks if two Uint8Arrays are equal. Not constant-time. */
declare function equalBytes(a: Uint8Array, b: Uint8Array): boolean;
/** Checks if the given value is a Uint8Array. */
declare function isBytes(a: unknown): a is Bytes;
/**
* Concatenates multiple Uint8Arrays.
* Engines limit functions to 65K+ arguments.
* @param arrays Array of Uint8Array elements
* @returns Concatenated Uint8Array
*/
declare function concatBytes(...arrays: Uint8Array[]): Uint8Array;
/**
* Checks if the provided value is a plain object, not created from any class or special constructor.
* Array, Uint8Array and others are not plain objects.
* @param obj - The value to be checked.
*/
declare function isPlainObject(obj: any): boolean;
export declare const utils: {
equalBytes: typeof equalBytes;
isBytes: typeof isBytes;
isCoder: typeof isCoder;
checkBounds: typeof checkBounds;
concatBytes: typeof concatBytes;
createView: (arr: Uint8Array) => DataView;
isPlainObject: typeof isPlainObject;
};
export type Bytes = Uint8Array;
export type Option<T> = T | undefined;
/**
* Coder encodes and decodes between two types.
* @property {(from: F) => T} encode - Encodes (converts) F to T
* @property {(to: T) => F} decode - Decodes (converts) T to F
*/
export interface Coder<F, T> {
encode(from: F): T;
decode(to: T): F;
}
/**
* BytesCoder converts value between a type and a byte array
* @property {number} [size] - Size hint for the element.
* @property {(data: T) => Bytes} encode - Encodes a value of type T to a byte array
* @property {(data: Bytes, opts?: ReaderOpts) => T} decode - Decodes a byte array to a value of type T
*/
export interface BytesCoder<T> extends Coder<T, Bytes> {
size?: number;
encode: (data: T) => Bytes;
decode: (data: Bytes, opts?: ReaderOpts) => T;
}
/**
* BytesCoderStream converts value between a type and a byte array, using streams.
* @property {number} [size] - Size hint for the element.
* @property {(w: Writer, value: T) => void} encodeStream - Encodes a value of type T to a byte array using a Writer stream.
* @property {(r: Reader) => T} decodeStream - Decodes a byte array to a value of type T using a Reader stream.
*/
export interface BytesCoderStream<T> {
size?: number;
encodeStream: (w: Writer, value: T) => void;
decodeStream: (r: Reader) => T;
}
export type CoderType<T> = BytesCoderStream<T> & BytesCoder<T>;
export type Sized<T> = CoderType<T> & {
size: number;
};
export type UnwrapCoder<T> = T extends CoderType<infer U> ? U : T;
/**
* Validation function. Should return value after validation.
* Can be used to narrow types
*/
export type Validate<T> = (elm: T) => T;
export type Length = CoderType<number> | CoderType<bigint> | number | Bytes | string | null;
type ArrLike<T> = Array<T> | ReadonlyArray<T>;
export type TypedArray = Uint8Array | Int8Array | Uint8ClampedArray | Uint16Array | Int16Array | Uint32Array | Int32Array;
/** Writable version of a type, where readonly properties are made writable. */
export type Writable<T> = T extends {} ? T extends TypedArray ? T : {
-readonly [P in keyof T]: Writable<T[P]>;
} : T;
export type Values<T> = T[keyof T];
export type NonUndefinedKey<T, K extends keyof T> = T[K] extends undefined ? never : K;
export type NullableKey<T, K extends keyof T> = T[K] extends NonNullable<T[K]> ? never : K;
export type OptKey<T, K extends keyof T> = NullableKey<T, K> & NonUndefinedKey<T, K>;
export type ReqKey<T, K extends keyof T> = T[K] extends NonNullable<T[K]> ? K : never;
export type OptKeys<T> = Pick<T, {
[K in keyof T]: OptKey<T, K>;
}[keyof T]>;
export type ReqKeys<T> = Pick<T, {
[K in keyof T]: ReqKey<T, K>;
}[keyof T]>;
export type StructInput<T extends Record<string, any>> = {
[P in keyof ReqKeys<T>]: T[P];
} & {
[P in keyof OptKeys<T>]?: T[P];
};
export type StructRecord<T extends Record<string, any>> = {
[P in keyof T]: CoderType<T[P]>;
};
export type StructOut = Record<string, any>;
/** Padding function that takes an index and returns a padding value. */
export type PadFn = (i: number) => number;
/** Path related utils (internal) */
type Path = {
obj: StructOut;
field?: string;
};
type PathStack = Path[];
export type _PathObjFn = (cb: (field: string, fieldFn: Function) => void) => void;
declare const Path: {
/**
* Internal method for handling stack of paths (debug, errors, dynamic fields via path)
* This is looks ugly (callback), but allows us to force stack cleaning by construction (.pop always after function).
* Also, this makes impossible:
* - pushing field when stack is empty
* - pushing field inside of field (real bug)
* NOTE: we don't want to do '.pop' on error!
*/
pushObj: (stack: PathStack, obj: StructOut, objFn: _PathObjFn) => void;
path: (stack: PathStack) => string;
err: (name: string, stack: PathStack, msg: string | Error) => Error;
resolve: (stack: PathStack, path: string) => StructOut | undefined;
};
/**
* Options for the Reader class.
* @property {boolean} [allowUnreadBytes: false] - If there are remaining unparsed bytes, the decoding is probably wrong.
* @property {boolean} [allowMultipleReads: false] - The check enforces parser termination. If pointers can read the same region of memory multiple times, you can cause combinatorial explosion by creating an array of pointers to the same address and cause DoS.
*/
export type ReaderOpts = {
allowUnreadBytes?: boolean;
allowMultipleReads?: boolean;
};
export type Reader = {
/** Current position in the buffer. */
readonly pos: number;
/** Number of bytes left in the buffer. */
readonly leftBytes: number;
/** Total number of bytes in the buffer. */
readonly totalBytes: number;
/** Checks if the end of the buffer has been reached. */
isEnd(): boolean;
/**
* Creates an error with the given message. Adds information about current field path.
* If Error object provided, saves original stack trace.
* @param msg - The error message or an Error object.
* @returns The created Error object.
*/
err(msg: string | Error): Error;
/**
* Reads a specified number of bytes from the buffer.
*
* WARNING: Uint8Array is subarray of original buffer. Do not modify.
* @param n - The number of bytes to read.
* @param peek - If `true`, the bytes are read without advancing the position.
* @returns The read bytes as a Uint8Array.
*/
bytes(n: number, peek?: boolean): Uint8Array;
/**
* Reads a single byte from the buffer.
* @param peek - If `true`, the byte is read without advancing the position.
* @returns The read byte as a number.
*/
byte(peek?: boolean): number;
/**
* Reads a specified number of bits from the buffer.
* @param bits - The number of bits to read.
* @returns The read bits as a number.
*/
bits(bits: number): number;
/**
* Finds the first occurrence of a needle in the buffer.
* @param needle - The needle to search for.
* @param pos - The starting position for the search.
* @returns The position of the first occurrence of the needle, or `undefined` if not found.
*/
find(needle: Bytes, pos?: number): number | undefined;
/**
* Creates a new Reader instance at the specified offset.
* Complex and unsafe API: currently only used in eth ABI parsing of pointers.
* Required to break pointer boundaries inside arrays for complex structure.
* Please use only if absolutely necessary!
* @param n - The offset to create the new Reader at.
* @returns A new Reader instance at the specified offset.
*/
offsetReader(n: number): Reader;
};
export type Writer = {
/**
* Creates an error with the given message. Adds information about current field path.
* If Error object provided, saves original stack trace.
* @param msg - The error message or an Error object.
* @returns The created Error object.
*/
err(msg: string | Error): Error;
/**
* Writes a byte array to the buffer.
* @param b - The byte array to write.
*/
bytes(b: Bytes): void;
/**
* Writes a single byte to the buffer.
* @param b - The byte to write.
*/
byte(b: number): void;
/**
* Writes a specified number of bits to the buffer.
* @param value - The value to write.
* @param bits - The number of bits to write.
*/
bits(value: number, bits: number): void;
};
/**
* Internal structure. Reader class for reading from a byte array.
* `stack` is internal: for debugger and logging
* @class Reader
*/
declare class _Reader implements Reader {
pos: number;
readonly data: Bytes;
readonly opts: ReaderOpts;
readonly stack: PathStack;
private parent;
private parentOffset;
private bitBuf;
private bitPos;
private bs;
private view;
constructor(data: Bytes, opts?: ReaderOpts, stack?: PathStack, parent?: _Reader | undefined, parentOffset?: number);
/** Internal method for pointers. */
_enablePointers(): void;
private markBytesBS;
private markBytes;
pushObj(obj: StructOut, objFn: _PathObjFn): void;
readView(n: number, fn: (view: DataView, pos: number) => number): number;
absBytes(n: number): Uint8Array;
finish(): void;
err(msg: string | Error): Error;
offsetReader(n: number): _Reader;
bytes(n: number, peek?: boolean): Uint8Array;
byte(peek?: boolean): number;
get leftBytes(): number;
get totalBytes(): number;
isEnd(): boolean;
bits(bits: number): number;
find(needle: Bytes, pos?: number): number | undefined;
}
/**
* Internal structure. Writer class for writing to a byte array.
* The `stack` argument of constructor is internal, for debugging and logs.
* @class Writer
*/
declare class _Writer implements Writer {
pos: number;
readonly stack: PathStack;
private buffers;
ptrs: {
pos: number;
ptr: CoderType<number>;
buffer: Bytes;
}[];
private bitBuf;
private bitPos;
private viewBuf;
private view;
private finished;
constructor(stack?: PathStack);
pushObj(obj: StructOut, objFn: _PathObjFn): void;
writeView(len: number, fn: (view: DataView) => void): void;
err(msg: string | Error): Error;
bytes(b: Bytes): void;
byte(b: number): void;
finish(clean?: boolean): Bytes;
bits(value: number, bits: number): void;
}
/** Internal function for checking bit bounds of bigint in signed/unsinged form */
declare function checkBounds(value: bigint, bits: bigint, signed: boolean): void;
/**
* Validates a value before encoding and after decoding using a provided function.
* @param inner - The inner CoderType.
* @param fn - The validation function.
* @returns CoderType which check value with validation function.
* @example
* const val = (n: number) => {
* if (n > 10) throw new Error(`${n} > 10`);
* return n;
* };
*
* const RangedInt = P.validate(P.U32LE, val); // Will check if value is <= 10 during encoding and decoding
*/
export declare function validate<T>(inner: CoderType<T>, fn: Validate<T>): CoderType<T>;
/**
* Wraps a stream encoder into a generic encoder and optionally validation function
* @param {inner} inner BytesCoderStream & { validate?: Validate<T> }.
* @returns The wrapped CoderType.
* @example
* const U8 = P.wrap({
* encodeStream: (w: Writer, value: number) => w.byte(value),
* decodeStream: (r: Reader): number => r.byte()
* });
* const checkedU8 = P.wrap({
* encodeStream: (w: Writer, value: number) => w.byte(value),
* decodeStream: (r: Reader): number => r.byte()
* validate: (n: number) => {
* if (n > 10) throw new Error(`${n} > 10`);
* return n;
* }
* });
*/
export declare const wrap: <T>(inner: BytesCoderStream<T> & {
validate?: Validate<T>;
}) => CoderType<T>;
/**
* Checks if the given value is a CoderType.
* @param elm - The value to check.
* @returns True if the value is a CoderType, false otherwise.
*/
export declare function isCoder<T>(elm: any): elm is CoderType<T>;
/**
* Base coder for working with dictionaries (records, objects, key-value map)
* Dictionary is dynamic type like: `[key: string, value: any][]`
* @returns base coder that encodes/decodes between arrays of key-value tuples and dictionaries.
* @example
* const dict: P.CoderType<Record<string, number>> = P.apply(
* P.array(P.U16BE, P.tuple([P.cstring, P.U32LE] as const)),
* P.coders.dict()
* );
*/
declare function dict<T>(): BaseCoder<[string, T][], Record<string, T>>;
type Enum = {
[k: string]: number | string;
} & {
[k: number]: string;
};
type EnumKeys<T extends Enum> = keyof T;
/**
* Base coder for working with TypeScript enums.
* @param e - TypeScript enum.
* @returns base coder that encodes/decodes between numbers and enum keys.
* @example
* enum Color { Red, Green, Blue }
* const colorCoder = P.coders.tsEnum(Color);
* colorCoder.encode(Color.Red); // 'Red'
* colorCoder.decode('Green'); // 1
*/
declare function tsEnum<T extends Enum>(e: T): BaseCoder<number, EnumKeys<T>>;
/**
* Base coder for working with decimal numbers.
* @param precision - Number of decimal places.
* @param round - Round fraction part if bigger than precision (throws error by default)
* @returns base coder that encodes/decodes between bigints and decimal strings.
* @example
* const decimal8 = P.coders.decimal(8);
* decimal8.encode(630880845n); // '6.30880845'
* decimal8.decode('6.30880845'); // 630880845n
*/
declare function decimal(precision: number, round?: boolean): Coder<bigint, string>;
type BaseInput<F> = F extends BaseCoder<infer T, any> ? T : never;
type BaseOutput<F> = F extends BaseCoder<any, infer T> ? T : never;
/**
* Combines multiple coders into a single coder, allowing conditional encoding/decoding based on input.
* Acts as a parser combinator, splitting complex conditional coders into smaller parts.
*
* `encode = [Ae, Be]; decode = [Ad, Bd]`
* ->
* `match([{encode: Ae, decode: Ad}, {encode: Be; decode: Bd}])`
*
* @param lst - Array of coders to match.
* @returns Combined coder for conditional encoding/decoding.
*/
declare function match<L extends BaseCoder<unknown | undefined, unknown | undefined>[], I = {
[K in keyof L]: NonNullable<BaseInput<L[K]>>;
}[number], O = {
[K in keyof L]: NonNullable<BaseOutput<L[K]>>;
}[number]>(lst: L): BaseCoder<I, O>;
export declare const coders: {
dict: typeof dict;
numberBigint: BaseCoder<bigint, number>;
tsEnum: typeof tsEnum;
decimal: typeof decimal;
match: typeof match;
reverse: <F, T>(coder: Coder<F, T>) => Coder<T, F>;
};
/**
* CoderType for parsing individual bits.
* NOTE: Structure should parse whole amount of bytes before it can start parsing byte-level elements.
* @param len - Number of bits to parse.
* @returns CoderType representing the parsed bits.
* @example
* const s = P.struct({ magic: P.bits(1), version: P.bits(1), tag: P.bits(4), len: P.bits(2) });
*/
export declare const bits: (len: number) => CoderType<number>;
/**
* CoderType for working with bigint values.
* Unsized bigint values should be wrapped in a container (e.g., bytes or string).
*
* `0n = new Uint8Array([])`
*
* `1n = new Uint8Array([1n])`
*
* Please open issue, if you need different behavior for zero.
*
* @param size - Size of the bigint in bytes.
* @param le - Whether to use little-endian byte order.
* @param signed - Whether the bigint is signed.
* @param sized - Whether the bigint should have a fixed size.
* @returns CoderType representing the bigint value.
* @example
* const U512BE = P.bigint(64, false, true, true); // Define a CoderType for a 512-bit unsigned big-endian integer
*/
export declare const bigint: (size: number, le?: boolean, signed?: boolean, sized?: boolean) => CoderType<bigint>;
/** Unsigned 256-bit little-endian integer CoderType. */
export declare const U256LE: CoderType<bigint>;
/** Unsigned 256-bit big-endian integer CoderType. */
export declare const U256BE: CoderType<bigint>;
/** Signed 256-bit little-endian integer CoderType. */
export declare const I256LE: CoderType<bigint>;
/** Signed 256-bit big-endian integer CoderType. */
export declare const I256BE: CoderType<bigint>;
/** Unsigned 128-bit little-endian integer CoderType. */
export declare const U128LE: CoderType<bigint>;
/** Unsigned 128-bit big-endian integer CoderType. */
export declare const U128BE: CoderType<bigint>;
/** Signed 128-bit little-endian integer CoderType. */
export declare const I128LE: CoderType<bigint>;
/** Signed 128-bit big-endian integer CoderType. */
export declare const I128BE: CoderType<bigint>;
/** Unsigned 64-bit little-endian integer CoderType. */
export declare const U64LE: CoderType<bigint>;
/** Unsigned 64-bit big-endian integer CoderType. */
export declare const U64BE: CoderType<bigint>;
/** Signed 64-bit little-endian integer CoderType. */
export declare const I64LE: CoderType<bigint>;
/** Signed 64-bit big-endian integer CoderType. */
export declare const I64BE: CoderType<bigint>;
/**
* CoderType for working with numbber values (up to 6 bytes/48 bits).
* Unsized int values should be wrapped in a container (e.g., bytes or string).
*
* `0 = new Uint8Array([])`
*
* `1 = new Uint8Array([1n])`
*
* Please open issue, if you need different behavior for zero.
*
* @param size - Size of the number in bytes.
* @param le - Whether to use little-endian byte order.
* @param signed - Whether the number is signed.
* @param sized - Whether the number should have a fixed size.
* @returns CoderType representing the number value.
* @example
* const uint64BE = P.bigint(8, false, true); // Define a CoderType for a 64-bit unsigned big-endian integer
*/
export declare const int: (size: number, le?: boolean, signed?: boolean, sized?: boolean) => CoderType<number>;
/** Unsigned 32-bit little-endian integer CoderType. */
export declare const U32LE: CoderType<number>;
/** Unsigned 32-bit big-endian integer CoderType. */
export declare const U32BE: CoderType<number>;
/** Signed 32-bit little-endian integer CoderType. */
export declare const I32LE: CoderType<number>;
/** Signed 32-bit big-endian integer CoderType. */
export declare const I32BE: CoderType<number>;
/** Unsigned 16-bit little-endian integer CoderType. */
export declare const U16LE: CoderType<number>;
/** Unsigned 16-bit big-endian integer CoderType. */
export declare const U16BE: CoderType<number>;
/** Signed 16-bit little-endian integer CoderType. */
export declare const I16LE: CoderType<number>;
/** Signed 16-bit big-endian integer CoderType. */
export declare const I16BE: CoderType<number>;
/** Unsigned 8-bit integer CoderType. */
export declare const U8: CoderType<number>;
/** Signed 8-bit integer CoderType. */
export declare const I8: CoderType<number>;
/** 32-bit big-endian floating point CoderType ("binary32", IEEE 754-2008). */
export declare const F32BE: CoderType<number>;
/** 32-bit little-endian floating point CoderType ("binary32", IEEE 754-2008). */
export declare const F32LE: CoderType<number>;
/** A 64-bit big-endian floating point type ("binary64", IEEE 754-2008). Any JS number can be encoded. */
export declare const F64BE: CoderType<number>;
/** A 64-bit little-endian floating point type ("binary64", IEEE 754-2008). Any JS number can be encoded. */
export declare const F64LE: CoderType<number>;
/** Boolean CoderType. */
export declare const bool: CoderType<boolean>;
/**
* Bytes CoderType with a specified length and endianness.
* The bytes can have:
* - Dynamic size (prefixed with a length CoderType like U16BE)
* - Fixed size (specified by a number)
* - Unknown size (null, will parse until end of buffer)
* - Zero-terminated (terminator can be any Uint8Array)
* @param len - CoderType, number, Uint8Array (terminator) or null
* @param le - Whether to use little-endian byte order.
* @returns CoderType representing the bytes.
* @example
* // Dynamic size bytes (prefixed with P.U16BE number of bytes length)
* const dynamicBytes = P.bytes(P.U16BE, false);
* const fixedBytes = P.bytes(32, false); // Fixed size bytes
* const unknownBytes = P.bytes(null, false); // Unknown size bytes, will parse until end of buffer
* const zeroTerminatedBytes = P.bytes(new Uint8Array([0]), false); // Zero-terminated bytes
*/
declare const createBytes: (len: Length, le?: boolean) => CoderType<Bytes>;
export { createBytes as bytes, createHex as hex };
/**
* Prefix-encoded value using a length prefix and an inner CoderType.
* The prefix can have:
* - Dynamic size (prefixed with a length CoderType like U16BE)
* - Fixed size (specified by a number)
* - Unknown size (null, will parse until end of buffer)
* - Zero-terminated (terminator can be any Uint8Array)
* @param len - Length CoderType (dynamic size), number (fixed size), Uint8Array (for terminator), or null (will parse until end of buffer)
* @param inner - CoderType for the actual value to be prefix-encoded.
* @returns CoderType representing the prefix-encoded value.
* @example
* const dynamicPrefix = P.prefix(P.U16BE, P.bytes(null)); // Dynamic size prefix (prefixed with P.U16BE number of bytes length)
* const fixedPrefix = P.prefix(10, P.bytes(null)); // Fixed size prefix (always 10 bytes)
*/
export declare function prefix<T>(len: Length, inner: CoderType<T>): CoderType<T>;
/**
* String CoderType with a specified length and endianness.
* The string can be:
* - Dynamic size (prefixed with a length CoderType like U16BE)
* - Fixed size (specified by a number)
* - Unknown size (null, will parse until end of buffer)
* - Zero-terminated (terminator can be any Uint8Array)
* @param len - Length CoderType (dynamic size), number (fixed size), Uint8Array (for terminator), or null (will parse until end of buffer)
* @param le - Whether to use little-endian byte order.
* @returns CoderType representing the string.
* @example
* const dynamicString = P.string(P.U16BE, false); // Dynamic size string (prefixed with P.U16BE number of string length)
* const fixedString = P.string(10, false); // Fixed size string
* const unknownString = P.string(null, false); // Unknown size string, will parse until end of buffer
* const nullTerminatedString = P.cstring; // NUL-terminated string
* const _cstring = P.string(new Uint8Array([0])); // Same thing
*/
export declare const string: (len: Length, le?: boolean) => CoderType<string>;
/** NUL-terminated string CoderType. */
export declare const cstring: CoderType<string>;
type HexOpts = {
isLE?: boolean;
with0x?: boolean;
};
/**
* Hexadecimal string CoderType with a specified length, endianness, and optional 0x prefix.
* @param len - Length CoderType (dynamic size), number (fixed size), Uint8Array (for terminator), or null (will parse until end of buffer)
* @param le - Whether to use little-endian byte order.
* @param withZero - Whether to include the 0x prefix.
* @returns CoderType representing the hexadecimal string.
* @example
* const dynamicHex = P.hex(P.U16BE, {isLE: false, with0x: true}); // Hex string with 0x prefix and U16BE length
* const fixedHex = P.hex(32, {isLE: false, with0x: false}); // Fixed-length 32-byte hex string without 0x prefix
*/
declare const createHex: (len: Length, options?: HexOpts) => CoderType<string>;
/**
* Applies a base coder to a CoderType.
* @param inner - The inner CoderType.
* @param b - The base coder to apply.
* @returns CoderType representing the transformed value.
* @example
* import { hex } from '@scure/base';
* const hex = P.apply(P.bytes(32), hex); // will decode bytes into a hex string
*/
export declare function apply<T, F>(inner: CoderType<T>, base: BaseCoder<T, F>): CoderType<F>;
/**
* Lazy CoderType that is evaluated at runtime.
* @param fn - A function that returns the CoderType.
* @returns CoderType representing the lazy value.
* @example
* type Tree = { name: string; children: Tree[] };
* const tree = P.struct({
* name: P.cstring,
* children: P.array(
* P.U16BE,
* P.lazy((): P.CoderType<Tree> => tree)
* ),
* });
*/
export declare function lazy<T>(fn: () => CoderType<T>): CoderType<T>;
/**
* Flag CoderType that encodes/decodes a boolean value based on the presence of a marker.
* @param flagValue - Marker value.
* @param xor - Whether to invert the flag behavior.
* @returns CoderType representing the flag value.
* @example
* const flag = P.flag(new Uint8Array([0x01, 0x02])); // Encodes true as u8a([0x01, 0x02]), false as u8a([])
* const flagXor = P.flag(new Uint8Array([0x01, 0x02]), true); // Encodes true as u8a([]), false as u8a([0x01, 0x02])
* // Conditional encoding with flagged
* const s = P.struct({ f: P.flag(new Uint8Array([0x0, 0x1])), f2: P.flagged('f', P.U32BE) });
*/
export declare const flag: (flagValue: Bytes, xor?: boolean) => CoderType<boolean | undefined>;
/**
* Conditional CoderType that encodes/decodes a value only if a flag is present.
* @param path - Path to the flag value or a CoderType for the flag.
* @param inner - Inner CoderType for the value.
* @param def - Optional default value to use if the flag is not present.
* @returns CoderType representing the conditional value.
* @example
* const s = P.struct({
* f: P.flag(new Uint8Array([0x0, 0x1])),
* f2: P.flagged('f', P.U32BE)
* });
*
* @example
* const s2 = P.struct({
* f: P.flag(new Uint8Array([0x0, 0x1])),
* f2: P.flagged('f', P.U32BE, 123)
* });
*/
export declare function flagged<T>(path: string | CoderType<boolean>, inner: CoderType<T>, def?: T): CoderType<Option<T>>;
/**
* Optional CoderType that encodes/decodes a value based on a flag.
* @param flag - CoderType for the flag value.
* @param inner - Inner CoderType for the value.
* @param def - Optional default value to use if the flag is not present.
* @returns CoderType representing the optional value.
* @example
* // Will decode into P.U32BE only if flag present
* const optional = P.optional(P.flag(new Uint8Array([0x0, 0x1])), P.U32BE);
*
* @example
* // If no flag present, will decode into default value
* const optionalWithDefault = P.optional(P.flag(new Uint8Array([0x0, 0x1])), P.U32BE, 123);
*/
export declare function optional<T>(flag: CoderType<boolean>, inner: CoderType<T>, def?: T): CoderType<Option<T>>;
/**
* Magic value CoderType that encodes/decodes a constant value.
* This can be used to check for a specific magic value or sequence of bytes at the beginning of a data structure.
* @param inner - Inner CoderType for the value.
* @param constant - Constant value.
* @param check - Whether to check the decoded value against the constant.
* @returns CoderType representing the magic value.
* @example
* // Always encodes constant as bytes using inner CoderType, throws if encoded value is not present
* const magicU8 = P.magic(P.U8, 0x42);
*/
export declare function magic<T>(inner: CoderType<T>, constant: T, check?: boolean): CoderType<undefined>;
/**
* Magic bytes CoderType that encodes/decodes a constant byte array or string.
* @param constant - Constant byte array or string.
* @returns CoderType representing the magic bytes.
* @example
* // Always encodes undefined into byte representation of string 'MAGIC'
* const magicBytes = P.magicBytes('MAGIC');
*/
export declare const magicBytes: (constant: Bytes | string) => CoderType<undefined>;
/**
* Creates a CoderType for a constant value. The function enforces this value during encoding,
* ensuring it matches the provided constant. During decoding, it always returns the constant value.
* The actual value is not written to or read from any byte stream; it's used only for validation.
*
* @param c - Constant value.
* @returns CoderType representing the constant value.
* @example
* // Always return 123 on decode, throws on encoding anything other than 123
* const constantU8 = P.constant(123);
*/
export declare function constant<T>(c: T): CoderType<T>;
/**
* Structure of composable primitives (C/Rust struct)
* @param fields - Object mapping field names to CoderTypes.
* @returns CoderType representing the structure.
* @example
* // Define a structure with a 32-bit big-endian unsigned integer, a string, and a nested structure
* const myStruct = P.struct({
* id: P.U32BE,
* name: P.string(P.U8),
* nested: P.struct({
* flag: P.bool,
* value: P.I16LE
* })
* });
*/
export declare function struct<T extends Record<string, any>>(fields: StructRecord<T>): CoderType<StructInput<T>>;
/**
* Tuple (unnamed structure) of CoderTypes. Same as struct but with unnamed fields.
* @param fields - Array of CoderTypes.
* @returns CoderType representing the tuple.
* @example
* const myTuple = P.tuple([P.U8, P.U16LE, P.string(P.U8)]);
*/
export declare function tuple<T extends ArrLike<CoderType<any>>, O = Writable<{
[K in keyof T]: UnwrapCoder<T[K]>;
}>>(fields: T): CoderType<O>;
/**
* Array of items (inner type) with a specified length.
* @param len - Length CoderType (dynamic size), number (fixed size), Uint8Array (for terminator), or null (will parse until end of buffer)
* @param inner - CoderType for encoding/decoding each array item.
* @returns CoderType representing the array.
* @example
* const a1 = P.array(P.U16BE, child); // Dynamic size array (prefixed with P.U16BE number of array length)
* const a2 = P.array(4, child); // Fixed size array
* const a3 = P.array(null, child); // Unknown size array, will parse until end of buffer
* const a4 = P.array(new Uint8Array([0]), child); // zero-terminated array (NOTE: terminator can be any buffer)
*/
export declare function array<T>(len: Length, inner: CoderType<T>): CoderType<T[]>;
/**
* Mapping between encoded values and string representations.
* @param inner - CoderType for encoded values.
* @param variants - Object mapping string representations to encoded values.
* @returns CoderType representing the mapping.
* @example
* // Map between numbers and strings
* const numberMap = P.map(P.U8, {
* 'one': 1,
* 'two': 2,
* 'three': 3
* });
*
* // Map between byte arrays and strings
* const byteMap = P.map(P.bytes(2, false), {
* 'ab': Uint8Array.from([0x61, 0x62]),
* 'cd': Uint8Array.from([0x63, 0x64])
* });
*/
export declare function map<T>(inner: CoderType<T>, variants: Record<string, T>): CoderType<string>;
/**
* Tagged union of CoderTypes, where the tag value determines which CoderType to use.
* The decoded value will have the structure `{ TAG: number, data: ... }`.
* @param tag - CoderType for the tag value.
* @param variants - Object mapping tag values to CoderTypes.
* @returns CoderType representing the tagged union.
* @example
* // Tagged union of array, string, and number
* // Depending on the value of the first byte, it will be decoded as an array, string, or number.
* const taggedUnion = P.tag(P.U8, {
* 0x01: P.array(P.U16LE, P.U8),
* 0x02: P.string(P.U8),
* 0x03: P.U32BE
* });
*
* const encoded = taggedUnion.encode({ TAG: 0x01, data: 'hello' }); // Encodes the string 'hello' with tag 0x01
* const decoded = taggedUnion.decode(encoded); // Decodes the encoded value back to { TAG: 0x01, data: 'hello' }
*/
export declare function tag<T extends Values<{
[P in keyof Variants]: {
TAG: P;
data: UnwrapCoder<Variants[P]>;
};
}>, TagValue extends string | number, Variants extends Record<TagValue, CoderType<any>>>(tag: CoderType<TagValue>, variants: Variants): CoderType<T>;
/**
* Mapping between encoded values, string representations, and CoderTypes using a tag CoderType.
* @param tagCoder - CoderType for the tag value.
* @param variants - Object mapping string representations to [tag value, CoderType] pairs.
* * @returns CoderType representing the mapping.
* @example
* const cborValue: P.CoderType<CborValue> = P.mappedTag(P.bits(3), {
* uint: [0, cborUint], // An unsigned integer in the range 0..264-1 inclusive.
* negint: [1, cborNegint], // A negative integer in the range -264..-1 inclusive
* bytes: [2, P.lazy(() => cborLength(P.bytes, cborValue))], // A byte string.
* string: [3, P.lazy(() => cborLength(P.string, cborValue))], // A text string (utf8)
* array: [4, cborArrLength(P.lazy(() => cborValue))], // An array of data items
* map: [5, P.lazy(() => cborArrLength(P.tuple([cborValue, cborValue])))], // A map of pairs of data items
* tag: [6, P.tuple([cborUint, P.lazy(() => cborValue)] as const)], // A tagged data item ("tag") whose tag number
* simple: [7, cborSimple], // Floating-point numbers and simple values, as well as the "break" stop code
* });
*/
export declare function mappedTag<T extends Values<{
[P in keyof Variants]: {
TAG: P;
data: UnwrapCoder<Variants[P][1]>;
};
}>, TagValue extends string | number, Variants extends Record<string, [TagValue, CoderType<any>]>>(tagCoder: CoderType<TagValue>, variants: Variants): CoderType<T>;
/**
* Bitset of boolean values with optional padding.
* @param names - An array of string names for the bitset values.
* @param pad - Whether to pad the bitset to a multiple of 8 bits.
* @returns CoderType representing the bitset.
* @template Names
* @example
* const myBitset = P.bitset(['flag1', 'flag2', 'flag3', 'flag4'], true);
*/
export declare function bitset<Names extends readonly string[]>(names: Names, pad?: boolean): CoderType<Record<Names[number], boolean>>;
/** Padding function which always returns zero */
export declare const ZeroPad: PadFn;
/**
* Pads a CoderType with a specified block size and padding function on the left side.
* @param blockSize - Block size for padding (positive safe integer).
* @param inner - Inner CoderType to pad.
* @param padFn - Padding function to use. If not provided, zero padding is used.
* @returns CoderType representing the padded value.
* @example
* // Pad a U32BE with a block size of 4 and zero padding
* const paddedU32BE = P.padLeft(4, P.U32BE);
*
* // Pad a string with a block size of 16 and custom padding
* const paddedString = P.padLeft(16, P.string(P.U8), (i) => i + 1);
*/
export declare function padLeft<T>(blockSize: number, inner: CoderType<T>, padFn: Option<PadFn>): CoderType<T>;
/**
* Pads a CoderType with a specified block size and padding function on the right side.
* @param blockSize - Block size for padding (positive safe integer).
* @param inner - Inner CoderType to pad.
* @param padFn - Padding function to use. If not provided, zero padding is used.
* @returns CoderType representing the padded value.
* @example
* // Pad a U16BE with a block size of 2 and zero padding
* const paddedU16BE = P.padRight(2, P.U16BE);
*
* // Pad a bytes with a block size of 8 and custom padding
* const paddedBytes = P.padRight(8, P.bytes(null), (i) => i + 1);
*/
export declare function padRight<T>(blockSize: number, inner: CoderType<T>, padFn: Option<PadFn>): CoderType<T>;
/**
* Pointer to a value using a pointer CoderType and an inner CoderType.
* Pointers are scoped, and the next pointer in the dereference chain is offset by the previous one.
* By default (if no 'allowMultipleReads' in ReaderOpts is set) is safe, since
* same region of memory cannot be read multiple times.
* @param ptr - CoderType for the pointer value.
* @param inner - CoderType for encoding/decoding the pointed value.
* @param sized - Whether the pointer should have a fixed size.
* @returns CoderType representing the pointer to the value.
* @example
* const pointerToU8 = P.pointer(P.U16BE, P.U8); // Pointer to a single U8 value
*/
export declare function pointer<T>(ptr: CoderType<number>, inner: CoderType<T>, sized?: boolean): CoderType<T>;
export declare const _TEST: {
_bitset: {
BITS: number;
FULL_MASK: number;
len: (len: number) => number;
create: (len: number) => Uint32Array;
clean: (bs: Uint32Array) => Uint32Array;
debug: (bs: Uint32Array) => string[];
checkLen: (bs: Uint32Array, len: number) => void;
chunkLen: (bsLen: number, pos: number, len: number) => void;
set: (bs: Uint32Array, chunk: number, value: number, allowRewrite?: boolean) => boolean;
pos: (pos: number, i: number) => {
chunk: number;
mask: number;
};
indices: (bs: Uint32Array, len: number, invert?: boolean) => number[];
range: (arr: number[]) => {
pos: number;
length: number;
}[];
rangeDebug: (bs: Uint32Array, len: number, invert?: boolean) => string;
setRange: (bs: Uint32Array, bsLen: number, pos: number, len: number, allowRewrite?: boolean) => boolean;
};
_Reader: typeof _Reader;
_Writer: typeof _Writer;
Path: {
/**
* Internal method for handling stack of paths (debug, errors, dynamic fields via path)
* This is looks ugly (callback), but allows us to force stack cleaning by construction (.pop always after function).
* Also, this makes impossible:
* - pushing field when stack is empty
* - pushing field inside of field (real bug)
* NOTE: we don't want to do '.pop' on error!
*/
pushObj: (stack: PathStack, obj: StructOut, objFn: _PathObjFn) => void;
path: (stack: PathStack) => string;
err(name: string, stack: PathStack, msg: string | Error): Error;
resolve: (stack: PathStack, path: string) => StructOut | undefined;
};
};
//# sourceMappingURL=index.d.ts.map

1
dev/env/node_modules/micro-packed/lib/esm/index.d.ts.map generated vendored Executable file

File diff suppressed because one or more lines are too long

1992
dev/env/node_modules/micro-packed/lib/esm/index.js generated vendored Executable file

File diff suppressed because it is too large Load Diff

1
dev/env/node_modules/micro-packed/lib/esm/index.js.map generated vendored Executable file

File diff suppressed because one or more lines are too long

10
dev/env/node_modules/micro-packed/lib/esm/package.json generated vendored Executable file
View File

@@ -0,0 +1,10 @@
{
"type": "module",
"sideEffects": false,
"browser": {
"node:crypto": false
},
"node": {
"./crypto": "./esm/cryptoNode.js"
}
}

877
dev/env/node_modules/micro-packed/lib/index.d.ts generated vendored Executable file
View File

@@ -0,0 +1,877 @@
import { type Coder as BaseCoder } from '@scure/base';
/**
* Define complex binary structures using composable primitives.
* Main ideas:
* - Encode / decode can be chained, same as in `scure-base`
* - A complex structure can be created from an array and struct of primitive types
* - Strings / bytes are arrays with specific optimizations: we can just read bytes directly
* without creating plain array first and reading each byte separately.
* - Types are inferred from definition
* @module
* @example
* import * as P from 'micro-packed';
* const s = P.struct({
* field1: P.U32BE, // 32-bit unsigned big-endian integer
* field2: P.string(P.U8), // String with U8 length prefix
* field3: P.bytes(32), // 32 bytes
* field4: P.array(P.U16BE, P.struct({ // Array of structs with U16BE length
* subField1: P.U64BE, // 64-bit unsigned big-endian integer
* subField2: P.string(10) // 10-byte string
* }))
* });
*/
/** Shortcut to zero-length (empty) byte array */
export declare const EMPTY: Uint8Array;
/** Shortcut to one-element (element is 0) byte array */
export declare const NULL: Uint8Array;
/** Checks if two Uint8Arrays are equal. Not constant-time. */
declare function equalBytes(a: Uint8Array, b: Uint8Array): boolean;
/** Checks if the given value is a Uint8Array. */
declare function isBytes(a: unknown): a is Bytes;
/**
* Concatenates multiple Uint8Arrays.
* Engines limit functions to 65K+ arguments.
* @param arrays Array of Uint8Array elements
* @returns Concatenated Uint8Array
*/
declare function concatBytes(...arrays: Uint8Array[]): Uint8Array;
/**
* Checks if the provided value is a plain object, not created from any class or special constructor.
* Array, Uint8Array and others are not plain objects.
* @param obj - The value to be checked.
*/
declare function isPlainObject(obj: any): boolean;
export declare const utils: {
equalBytes: typeof equalBytes;
isBytes: typeof isBytes;
isCoder: typeof isCoder;
checkBounds: typeof checkBounds;
concatBytes: typeof concatBytes;
createView: (arr: Uint8Array) => DataView;
isPlainObject: typeof isPlainObject;
};
export type Bytes = Uint8Array;
export type Option<T> = T | undefined;
/**
* Coder encodes and decodes between two types.
* @property {(from: F) => T} encode - Encodes (converts) F to T
* @property {(to: T) => F} decode - Decodes (converts) T to F
*/
export interface Coder<F, T> {
encode(from: F): T;
decode(to: T): F;
}
/**
* BytesCoder converts value between a type and a byte array
* @property {number} [size] - Size hint for the element.
* @property {(data: T) => Bytes} encode - Encodes a value of type T to a byte array
* @property {(data: Bytes, opts?: ReaderOpts) => T} decode - Decodes a byte array to a value of type T
*/
export interface BytesCoder<T> extends Coder<T, Bytes> {
size?: number;
encode: (data: T) => Bytes;
decode: (data: Bytes, opts?: ReaderOpts) => T;
}
/**
* BytesCoderStream converts value between a type and a byte array, using streams.
* @property {number} [size] - Size hint for the element.
* @property {(w: Writer, value: T) => void} encodeStream - Encodes a value of type T to a byte array using a Writer stream.
* @property {(r: Reader) => T} decodeStream - Decodes a byte array to a value of type T using a Reader stream.
*/
export interface BytesCoderStream<T> {
size?: number;
encodeStream: (w: Writer, value: T) => void;
decodeStream: (r: Reader) => T;
}
export type CoderType<T> = BytesCoderStream<T> & BytesCoder<T>;
export type Sized<T> = CoderType<T> & {
size: number;
};
export type UnwrapCoder<T> = T extends CoderType<infer U> ? U : T;
/**
* Validation function. Should return value after validation.
* Can be used to narrow types
*/
export type Validate<T> = (elm: T) => T;
export type Length = CoderType<number> | CoderType<bigint> | number | Bytes | string | null;
type ArrLike<T> = Array<T> | ReadonlyArray<T>;
export type TypedArray = Uint8Array | Int8Array | Uint8ClampedArray | Uint16Array | Int16Array | Uint32Array | Int32Array;
/** Writable version of a type, where readonly properties are made writable. */
export type Writable<T> = T extends {} ? T extends TypedArray ? T : {
-readonly [P in keyof T]: Writable<T[P]>;
} : T;
export type Values<T> = T[keyof T];
export type NonUndefinedKey<T, K extends keyof T> = T[K] extends undefined ? never : K;
export type NullableKey<T, K extends keyof T> = T[K] extends NonNullable<T[K]> ? never : K;
export type OptKey<T, K extends keyof T> = NullableKey<T, K> & NonUndefinedKey<T, K>;
export type ReqKey<T, K extends keyof T> = T[K] extends NonNullable<T[K]> ? K : never;
export type OptKeys<T> = Pick<T, {
[K in keyof T]: OptKey<T, K>;
}[keyof T]>;
export type ReqKeys<T> = Pick<T, {
[K in keyof T]: ReqKey<T, K>;
}[keyof T]>;
export type StructInput<T extends Record<string, any>> = {
[P in keyof ReqKeys<T>]: T[P];
} & {
[P in keyof OptKeys<T>]?: T[P];
};
export type StructRecord<T extends Record<string, any>> = {
[P in keyof T]: CoderType<T[P]>;
};
export type StructOut = Record<string, any>;
/** Padding function that takes an index and returns a padding value. */
export type PadFn = (i: number) => number;
/** Path related utils (internal) */
type Path = {
obj: StructOut;
field?: string;
};
type PathStack = Path[];
export type _PathObjFn = (cb: (field: string, fieldFn: Function) => void) => void;
declare const Path: {
/**
* Internal method for handling stack of paths (debug, errors, dynamic fields via path)
* This is looks ugly (callback), but allows us to force stack cleaning by construction (.pop always after function).
* Also, this makes impossible:
* - pushing field when stack is empty
* - pushing field inside of field (real bug)
* NOTE: we don't want to do '.pop' on error!
*/
pushObj: (stack: PathStack, obj: StructOut, objFn: _PathObjFn) => void;
path: (stack: PathStack) => string;
err: (name: string, stack: PathStack, msg: string | Error) => Error;
resolve: (stack: PathStack, path: string) => StructOut | undefined;
};
/**
* Options for the Reader class.
* @property {boolean} [allowUnreadBytes: false] - If there are remaining unparsed bytes, the decoding is probably wrong.
* @property {boolean} [allowMultipleReads: false] - The check enforces parser termination. If pointers can read the same region of memory multiple times, you can cause combinatorial explosion by creating an array of pointers to the same address and cause DoS.
*/
export type ReaderOpts = {
allowUnreadBytes?: boolean;
allowMultipleReads?: boolean;
};
export type Reader = {
/** Current position in the buffer. */
readonly pos: number;
/** Number of bytes left in the buffer. */
readonly leftBytes: number;
/** Total number of bytes in the buffer. */
readonly totalBytes: number;
/** Checks if the end of the buffer has been reached. */
isEnd(): boolean;
/**
* Creates an error with the given message. Adds information about current field path.
* If Error object provided, saves original stack trace.
* @param msg - The error message or an Error object.
* @returns The created Error object.
*/
err(msg: string | Error): Error;
/**
* Reads a specified number of bytes from the buffer.
*
* WARNING: Uint8Array is subarray of original buffer. Do not modify.
* @param n - The number of bytes to read.
* @param peek - If `true`, the bytes are read without advancing the position.
* @returns The read bytes as a Uint8Array.
*/
bytes(n: number, peek?: boolean): Uint8Array;
/**
* Reads a single byte from the buffer.
* @param peek - If `true`, the byte is read without advancing the position.
* @returns The read byte as a number.
*/
byte(peek?: boolean): number;
/**
* Reads a specified number of bits from the buffer.
* @param bits - The number of bits to read.
* @returns The read bits as a number.
*/
bits(bits: number): number;
/**
* Finds the first occurrence of a needle in the buffer.
* @param needle - The needle to search for.
* @param pos - The starting position for the search.
* @returns The position of the first occurrence of the needle, or `undefined` if not found.
*/
find(needle: Bytes, pos?: number): number | undefined;
/**
* Creates a new Reader instance at the specified offset.
* Complex and unsafe API: currently only used in eth ABI parsing of pointers.
* Required to break pointer boundaries inside arrays for complex structure.
* Please use only if absolutely necessary!
* @param n - The offset to create the new Reader at.
* @returns A new Reader instance at the specified offset.
*/
offsetReader(n: number): Reader;
};
export type Writer = {
/**
* Creates an error with the given message. Adds information about current field path.
* If Error object provided, saves original stack trace.
* @param msg - The error message or an Error object.
* @returns The created Error object.
*/
err(msg: string | Error): Error;
/**
* Writes a byte array to the buffer.
* @param b - The byte array to write.
*/
bytes(b: Bytes): void;
/**
* Writes a single byte to the buffer.
* @param b - The byte to write.
*/
byte(b: number): void;
/**
* Writes a specified number of bits to the buffer.
* @param value - The value to write.
* @param bits - The number of bits to write.
*/
bits(value: number, bits: number): void;
};
/**
* Internal structure. Reader class for reading from a byte array.
* `stack` is internal: for debugger and logging
* @class Reader
*/
declare class _Reader implements Reader {
pos: number;
readonly data: Bytes;
readonly opts: ReaderOpts;
readonly stack: PathStack;
private parent;
private parentOffset;
private bitBuf;
private bitPos;
private bs;
private view;
constructor(data: Bytes, opts?: ReaderOpts, stack?: PathStack, parent?: _Reader | undefined, parentOffset?: number);
/** Internal method for pointers. */
_enablePointers(): void;
private markBytesBS;
private markBytes;
pushObj(obj: StructOut, objFn: _PathObjFn): void;
readView(n: number, fn: (view: DataView, pos: number) => number): number;
absBytes(n: number): Uint8Array;
finish(): void;
err(msg: string | Error): Error;
offsetReader(n: number): _Reader;
bytes(n: number, peek?: boolean): Uint8Array;
byte(peek?: boolean): number;
get leftBytes(): number;
get totalBytes(): number;
isEnd(): boolean;
bits(bits: number): number;
find(needle: Bytes, pos?: number): number | undefined;
}
/**
* Internal structure. Writer class for writing to a byte array.
* The `stack` argument of constructor is internal, for debugging and logs.
* @class Writer
*/
declare class _Writer implements Writer {
pos: number;
readonly stack: PathStack;
private buffers;
ptrs: {
pos: number;
ptr: CoderType<number>;
buffer: Bytes;
}[];
private bitBuf;
private bitPos;
private viewBuf;
private view;
private finished;
constructor(stack?: PathStack);
pushObj(obj: StructOut, objFn: _PathObjFn): void;
writeView(len: number, fn: (view: DataView) => void): void;
err(msg: string | Error): Error;
bytes(b: Bytes): void;
byte(b: number): void;
finish(clean?: boolean): Bytes;
bits(value: number, bits: number): void;
}
/** Internal function for checking bit bounds of bigint in signed/unsinged form */
declare function checkBounds(value: bigint, bits: bigint, signed: boolean): void;
/**
* Validates a value before encoding and after decoding using a provided function.
* @param inner - The inner CoderType.
* @param fn - The validation function.
* @returns CoderType which check value with validation function.
* @example
* const val = (n: number) => {
* if (n > 10) throw new Error(`${n} > 10`);
* return n;
* };
*
* const RangedInt = P.validate(P.U32LE, val); // Will check if value is <= 10 during encoding and decoding
*/
export declare function validate<T>(inner: CoderType<T>, fn: Validate<T>): CoderType<T>;
/**
* Wraps a stream encoder into a generic encoder and optionally validation function
* @param {inner} inner BytesCoderStream & { validate?: Validate<T> }.
* @returns The wrapped CoderType.
* @example
* const U8 = P.wrap({
* encodeStream: (w: Writer, value: number) => w.byte(value),
* decodeStream: (r: Reader): number => r.byte()
* });
* const checkedU8 = P.wrap({
* encodeStream: (w: Writer, value: number) => w.byte(value),
* decodeStream: (r: Reader): number => r.byte()
* validate: (n: number) => {
* if (n > 10) throw new Error(`${n} > 10`);
* return n;
* }
* });
*/
export declare const wrap: <T>(inner: BytesCoderStream<T> & {
validate?: Validate<T>;
}) => CoderType<T>;
/**
* Checks if the given value is a CoderType.
* @param elm - The value to check.
* @returns True if the value is a CoderType, false otherwise.
*/
export declare function isCoder<T>(elm: any): elm is CoderType<T>;
/**
* Base coder for working with dictionaries (records, objects, key-value map)
* Dictionary is dynamic type like: `[key: string, value: any][]`
* @returns base coder that encodes/decodes between arrays of key-value tuples and dictionaries.
* @example
* const dict: P.CoderType<Record<string, number>> = P.apply(
* P.array(P.U16BE, P.tuple([P.cstring, P.U32LE] as const)),
* P.coders.dict()
* );
*/
declare function dict<T>(): BaseCoder<[string, T][], Record<string, T>>;
type Enum = {
[k: string]: number | string;
} & {
[k: number]: string;
};
type EnumKeys<T extends Enum> = keyof T;
/**
* Base coder for working with TypeScript enums.
* @param e - TypeScript enum.
* @returns base coder that encodes/decodes between numbers and enum keys.
* @example
* enum Color { Red, Green, Blue }
* const colorCoder = P.coders.tsEnum(Color);
* colorCoder.encode(Color.Red); // 'Red'
* colorCoder.decode('Green'); // 1
*/
declare function tsEnum<T extends Enum>(e: T): BaseCoder<number, EnumKeys<T>>;
/**
* Base coder for working with decimal numbers.
* @param precision - Number of decimal places.
* @param round - Round fraction part if bigger than precision (throws error by default)
* @returns base coder that encodes/decodes between bigints and decimal strings.
* @example
* const decimal8 = P.coders.decimal(8);
* decimal8.encode(630880845n); // '6.30880845'
* decimal8.decode('6.30880845'); // 630880845n
*/
declare function decimal(precision: number, round?: boolean): Coder<bigint, string>;
type BaseInput<F> = F extends BaseCoder<infer T, any> ? T : never;
type BaseOutput<F> = F extends BaseCoder<any, infer T> ? T : never;
/**
* Combines multiple coders into a single coder, allowing conditional encoding/decoding based on input.
* Acts as a parser combinator, splitting complex conditional coders into smaller parts.
*
* `encode = [Ae, Be]; decode = [Ad, Bd]`
* ->
* `match([{encode: Ae, decode: Ad}, {encode: Be; decode: Bd}])`
*
* @param lst - Array of coders to match.
* @returns Combined coder for conditional encoding/decoding.
*/
declare function match<L extends BaseCoder<unknown | undefined, unknown | undefined>[], I = {
[K in keyof L]: NonNullable<BaseInput<L[K]>>;
}[number], O = {
[K in keyof L]: NonNullable<BaseOutput<L[K]>>;
}[number]>(lst: L): BaseCoder<I, O>;
export declare const coders: {
dict: typeof dict;
numberBigint: BaseCoder<bigint, number>;
tsEnum: typeof tsEnum;
decimal: typeof decimal;
match: typeof match;
reverse: <F, T>(coder: Coder<F, T>) => Coder<T, F>;
};
/**
* CoderType for parsing individual bits.
* NOTE: Structure should parse whole amount of bytes before it can start parsing byte-level elements.
* @param len - Number of bits to parse.
* @returns CoderType representing the parsed bits.
* @example
* const s = P.struct({ magic: P.bits(1), version: P.bits(1), tag: P.bits(4), len: P.bits(2) });
*/
export declare const bits: (len: number) => CoderType<number>;
/**
* CoderType for working with bigint values.
* Unsized bigint values should be wrapped in a container (e.g., bytes or string).
*
* `0n = new Uint8Array([])`
*
* `1n = new Uint8Array([1n])`
*
* Please open issue, if you need different behavior for zero.
*
* @param size - Size of the bigint in bytes.
* @param le - Whether to use little-endian byte order.
* @param signed - Whether the bigint is signed.
* @param sized - Whether the bigint should have a fixed size.
* @returns CoderType representing the bigint value.
* @example
* const U512BE = P.bigint(64, false, true, true); // Define a CoderType for a 512-bit unsigned big-endian integer
*/
export declare const bigint: (size: number, le?: boolean, signed?: boolean, sized?: boolean) => CoderType<bigint>;
/** Unsigned 256-bit little-endian integer CoderType. */
export declare const U256LE: CoderType<bigint>;
/** Unsigned 256-bit big-endian integer CoderType. */
export declare const U256BE: CoderType<bigint>;
/** Signed 256-bit little-endian integer CoderType. */
export declare const I256LE: CoderType<bigint>;
/** Signed 256-bit big-endian integer CoderType. */
export declare const I256BE: CoderType<bigint>;
/** Unsigned 128-bit little-endian integer CoderType. */
export declare const U128LE: CoderType<bigint>;
/** Unsigned 128-bit big-endian integer CoderType. */
export declare const U128BE: CoderType<bigint>;
/** Signed 128-bit little-endian integer CoderType. */
export declare const I128LE: CoderType<bigint>;
/** Signed 128-bit big-endian integer CoderType. */
export declare const I128BE: CoderType<bigint>;
/** Unsigned 64-bit little-endian integer CoderType. */
export declare const U64LE: CoderType<bigint>;
/** Unsigned 64-bit big-endian integer CoderType. */
export declare const U64BE: CoderType<bigint>;
/** Signed 64-bit little-endian integer CoderType. */
export declare const I64LE: CoderType<bigint>;
/** Signed 64-bit big-endian integer CoderType. */
export declare const I64BE: CoderType<bigint>;
/**
* CoderType for working with numbber values (up to 6 bytes/48 bits).
* Unsized int values should be wrapped in a container (e.g., bytes or string).
*
* `0 = new Uint8Array([])`
*
* `1 = new Uint8Array([1n])`
*
* Please open issue, if you need different behavior for zero.
*
* @param size - Size of the number in bytes.
* @param le - Whether to use little-endian byte order.
* @param signed - Whether the number is signed.
* @param sized - Whether the number should have a fixed size.
* @returns CoderType representing the number value.
* @example
* const uint64BE = P.bigint(8, false, true); // Define a CoderType for a 64-bit unsigned big-endian integer
*/
export declare const int: (size: number, le?: boolean, signed?: boolean, sized?: boolean) => CoderType<number>;
/** Unsigned 32-bit little-endian integer CoderType. */
export declare const U32LE: CoderType<number>;
/** Unsigned 32-bit big-endian integer CoderType. */
export declare const U32BE: CoderType<number>;
/** Signed 32-bit little-endian integer CoderType. */
export declare const I32LE: CoderType<number>;
/** Signed 32-bit big-endian integer CoderType. */
export declare const I32BE: CoderType<number>;
/** Unsigned 16-bit little-endian integer CoderType. */
export declare const U16LE: CoderType<number>;
/** Unsigned 16-bit big-endian integer CoderType. */
export declare const U16BE: CoderType<number>;
/** Signed 16-bit little-endian integer CoderType. */
export declare const I16LE: CoderType<number>;
/** Signed 16-bit big-endian integer CoderType. */
export declare const I16BE: CoderType<number>;
/** Unsigned 8-bit integer CoderType. */
export declare const U8: CoderType<number>;
/** Signed 8-bit integer CoderType. */
export declare const I8: CoderType<number>;
/** 32-bit big-endian floating point CoderType ("binary32", IEEE 754-2008). */
export declare const F32BE: CoderType<number>;
/** 32-bit little-endian floating point CoderType ("binary32", IEEE 754-2008). */
export declare const F32LE: CoderType<number>;
/** A 64-bit big-endian floating point type ("binary64", IEEE 754-2008). Any JS number can be encoded. */
export declare const F64BE: CoderType<number>;
/** A 64-bit little-endian floating point type ("binary64", IEEE 754-2008). Any JS number can be encoded. */
export declare const F64LE: CoderType<number>;
/** Boolean CoderType. */
export declare const bool: CoderType<boolean>;
/**
* Bytes CoderType with a specified length and endianness.
* The bytes can have:
* - Dynamic size (prefixed with a length CoderType like U16BE)
* - Fixed size (specified by a number)
* - Unknown size (null, will parse until end of buffer)
* - Zero-terminated (terminator can be any Uint8Array)
* @param len - CoderType, number, Uint8Array (terminator) or null
* @param le - Whether to use little-endian byte order.
* @returns CoderType representing the bytes.
* @example
* // Dynamic size bytes (prefixed with P.U16BE number of bytes length)
* const dynamicBytes = P.bytes(P.U16BE, false);
* const fixedBytes = P.bytes(32, false); // Fixed size bytes
* const unknownBytes = P.bytes(null, false); // Unknown size bytes, will parse until end of buffer
* const zeroTerminatedBytes = P.bytes(new Uint8Array([0]), false); // Zero-terminated bytes
*/
declare const createBytes: (len: Length, le?: boolean) => CoderType<Bytes>;
export { createBytes as bytes, createHex as hex };
/**
* Prefix-encoded value using a length prefix and an inner CoderType.
* The prefix can have:
* - Dynamic size (prefixed with a length CoderType like U16BE)
* - Fixed size (specified by a number)
* - Unknown size (null, will parse until end of buffer)
* - Zero-terminated (terminator can be any Uint8Array)
* @param len - Length CoderType (dynamic size), number (fixed size), Uint8Array (for terminator), or null (will parse until end of buffer)
* @param inner - CoderType for the actual value to be prefix-encoded.
* @returns CoderType representing the prefix-encoded value.
* @example
* const dynamicPrefix = P.prefix(P.U16BE, P.bytes(null)); // Dynamic size prefix (prefixed with P.U16BE number of bytes length)
* const fixedPrefix = P.prefix(10, P.bytes(null)); // Fixed size prefix (always 10 bytes)
*/
export declare function prefix<T>(len: Length, inner: CoderType<T>): CoderType<T>;
/**
* String CoderType with a specified length and endianness.
* The string can be:
* - Dynamic size (prefixed with a length CoderType like U16BE)
* - Fixed size (specified by a number)
* - Unknown size (null, will parse until end of buffer)
* - Zero-terminated (terminator can be any Uint8Array)
* @param len - Length CoderType (dynamic size), number (fixed size), Uint8Array (for terminator), or null (will parse until end of buffer)
* @param le - Whether to use little-endian byte order.
* @returns CoderType representing the string.
* @example
* const dynamicString = P.string(P.U16BE, false); // Dynamic size string (prefixed with P.U16BE number of string length)
* const fixedString = P.string(10, false); // Fixed size string
* const unknownString = P.string(null, false); // Unknown size string, will parse until end of buffer
* const nullTerminatedString = P.cstring; // NUL-terminated string
* const _cstring = P.string(new Uint8Array([0])); // Same thing
*/
export declare const string: (len: Length, le?: boolean) => CoderType<string>;
/** NUL-terminated string CoderType. */
export declare const cstring: CoderType<string>;
type HexOpts = {
isLE?: boolean;
with0x?: boolean;
};
/**
* Hexadecimal string CoderType with a specified length, endianness, and optional 0x prefix.
* @param len - Length CoderType (dynamic size), number (fixed size), Uint8Array (for terminator), or null (will parse until end of buffer)
* @param le - Whether to use little-endian byte order.
* @param withZero - Whether to include the 0x prefix.
* @returns CoderType representing the hexadecimal string.
* @example
* const dynamicHex = P.hex(P.U16BE, {isLE: false, with0x: true}); // Hex string with 0x prefix and U16BE length
* const fixedHex = P.hex(32, {isLE: false, with0x: false}); // Fixed-length 32-byte hex string without 0x prefix
*/
declare const createHex: (len: Length, options?: HexOpts) => CoderType<string>;
/**
* Applies a base coder to a CoderType.
* @param inner - The inner CoderType.
* @param b - The base coder to apply.
* @returns CoderType representing the transformed value.
* @example
* import { hex } from '@scure/base';
* const hex = P.apply(P.bytes(32), hex); // will decode bytes into a hex string
*/
export declare function apply<T, F>(inner: CoderType<T>, base: BaseCoder<T, F>): CoderType<F>;
/**
* Lazy CoderType that is evaluated at runtime.
* @param fn - A function that returns the CoderType.
* @returns CoderType representing the lazy value.
* @example
* type Tree = { name: string; children: Tree[] };
* const tree = P.struct({
* name: P.cstring,
* children: P.array(
* P.U16BE,
* P.lazy((): P.CoderType<Tree> => tree)
* ),
* });
*/
export declare function lazy<T>(fn: () => CoderType<T>): CoderType<T>;
/**
* Flag CoderType that encodes/decodes a boolean value based on the presence of a marker.
* @param flagValue - Marker value.
* @param xor - Whether to invert the flag behavior.
* @returns CoderType representing the flag value.
* @example
* const flag = P.flag(new Uint8Array([0x01, 0x02])); // Encodes true as u8a([0x01, 0x02]), false as u8a([])
* const flagXor = P.flag(new Uint8Array([0x01, 0x02]), true); // Encodes true as u8a([]), false as u8a([0x01, 0x02])
* // Conditional encoding with flagged
* const s = P.struct({ f: P.flag(new Uint8Array([0x0, 0x1])), f2: P.flagged('f', P.U32BE) });
*/
export declare const flag: (flagValue: Bytes, xor?: boolean) => CoderType<boolean | undefined>;
/**
* Conditional CoderType that encodes/decodes a value only if a flag is present.
* @param path - Path to the flag value or a CoderType for the flag.
* @param inner - Inner CoderType for the value.
* @param def - Optional default value to use if the flag is not present.
* @returns CoderType representing the conditional value.
* @example
* const s = P.struct({
* f: P.flag(new Uint8Array([0x0, 0x1])),
* f2: P.flagged('f', P.U32BE)
* });
*
* @example
* const s2 = P.struct({
* f: P.flag(new Uint8Array([0x0, 0x1])),
* f2: P.flagged('f', P.U32BE, 123)
* });
*/
export declare function flagged<T>(path: string | CoderType<boolean>, inner: CoderType<T>, def?: T): CoderType<Option<T>>;
/**
* Optional CoderType that encodes/decodes a value based on a flag.
* @param flag - CoderType for the flag value.
* @param inner - Inner CoderType for the value.
* @param def - Optional default value to use if the flag is not present.
* @returns CoderType representing the optional value.
* @example
* // Will decode into P.U32BE only if flag present
* const optional = P.optional(P.flag(new Uint8Array([0x0, 0x1])), P.U32BE);
*
* @example
* // If no flag present, will decode into default value
* const optionalWithDefault = P.optional(P.flag(new Uint8Array([0x0, 0x1])), P.U32BE, 123);
*/
export declare function optional<T>(flag: CoderType<boolean>, inner: CoderType<T>, def?: T): CoderType<Option<T>>;
/**
* Magic value CoderType that encodes/decodes a constant value.
* This can be used to check for a specific magic value or sequence of bytes at the beginning of a data structure.
* @param inner - Inner CoderType for the value.
* @param constant - Constant value.
* @param check - Whether to check the decoded value against the constant.
* @returns CoderType representing the magic value.
* @example
* // Always encodes constant as bytes using inner CoderType, throws if encoded value is not present
* const magicU8 = P.magic(P.U8, 0x42);
*/
export declare function magic<T>(inner: CoderType<T>, constant: T, check?: boolean): CoderType<undefined>;
/**
* Magic bytes CoderType that encodes/decodes a constant byte array or string.
* @param constant - Constant byte array or string.
* @returns CoderType representing the magic bytes.
* @example
* // Always encodes undefined into byte representation of string 'MAGIC'
* const magicBytes = P.magicBytes('MAGIC');
*/
export declare const magicBytes: (constant: Bytes | string) => CoderType<undefined>;
/**
* Creates a CoderType for a constant value. The function enforces this value during encoding,
* ensuring it matches the provided constant. During decoding, it always returns the constant value.
* The actual value is not written to or read from any byte stream; it's used only for validation.
*
* @param c - Constant value.
* @returns CoderType representing the constant value.
* @example
* // Always return 123 on decode, throws on encoding anything other than 123
* const constantU8 = P.constant(123);
*/
export declare function constant<T>(c: T): CoderType<T>;
/**
* Structure of composable primitives (C/Rust struct)
* @param fields - Object mapping field names to CoderTypes.
* @returns CoderType representing the structure.
* @example
* // Define a structure with a 32-bit big-endian unsigned integer, a string, and a nested structure
* const myStruct = P.struct({
* id: P.U32BE,
* name: P.string(P.U8),
* nested: P.struct({
* flag: P.bool,
* value: P.I16LE
* })
* });
*/
export declare function struct<T extends Record<string, any>>(fields: StructRecord<T>): CoderType<StructInput<T>>;
/**
* Tuple (unnamed structure) of CoderTypes. Same as struct but with unnamed fields.
* @param fields - Array of CoderTypes.
* @returns CoderType representing the tuple.
* @example
* const myTuple = P.tuple([P.U8, P.U16LE, P.string(P.U8)]);
*/
export declare function tuple<T extends ArrLike<CoderType<any>>, O = Writable<{
[K in keyof T]: UnwrapCoder<T[K]>;
}>>(fields: T): CoderType<O>;
/**
* Array of items (inner type) with a specified length.
* @param len - Length CoderType (dynamic size), number (fixed size), Uint8Array (for terminator), or null (will parse until end of buffer)
* @param inner - CoderType for encoding/decoding each array item.
* @returns CoderType representing the array.
* @example
* const a1 = P.array(P.U16BE, child); // Dynamic size array (prefixed with P.U16BE number of array length)
* const a2 = P.array(4, child); // Fixed size array
* const a3 = P.array(null, child); // Unknown size array, will parse until end of buffer
* const a4 = P.array(new Uint8Array([0]), child); // zero-terminated array (NOTE: terminator can be any buffer)
*/
export declare function array<T>(len: Length, inner: CoderType<T>): CoderType<T[]>;
/**
* Mapping between encoded values and string representations.
* @param inner - CoderType for encoded values.
* @param variants - Object mapping string representations to encoded values.
* @returns CoderType representing the mapping.
* @example
* // Map between numbers and strings
* const numberMap = P.map(P.U8, {
* 'one': 1,
* 'two': 2,
* 'three': 3
* });
*
* // Map between byte arrays and strings
* const byteMap = P.map(P.bytes(2, false), {
* 'ab': Uint8Array.from([0x61, 0x62]),
* 'cd': Uint8Array.from([0x63, 0x64])
* });
*/
export declare function map<T>(inner: CoderType<T>, variants: Record<string, T>): CoderType<string>;
/**
* Tagged union of CoderTypes, where the tag value determines which CoderType to use.
* The decoded value will have the structure `{ TAG: number, data: ... }`.
* @param tag - CoderType for the tag value.
* @param variants - Object mapping tag values to CoderTypes.
* @returns CoderType representing the tagged union.
* @example
* // Tagged union of array, string, and number
* // Depending on the value of the first byte, it will be decoded as an array, string, or number.
* const taggedUnion = P.tag(P.U8, {
* 0x01: P.array(P.U16LE, P.U8),
* 0x02: P.string(P.U8),
* 0x03: P.U32BE
* });
*
* const encoded = taggedUnion.encode({ TAG: 0x01, data: 'hello' }); // Encodes the string 'hello' with tag 0x01
* const decoded = taggedUnion.decode(encoded); // Decodes the encoded value back to { TAG: 0x01, data: 'hello' }
*/
export declare function tag<T extends Values<{
[P in keyof Variants]: {
TAG: P;
data: UnwrapCoder<Variants[P]>;
};
}>, TagValue extends string | number, Variants extends Record<TagValue, CoderType<any>>>(tag: CoderType<TagValue>, variants: Variants): CoderType<T>;
/**
* Mapping between encoded values, string representations, and CoderTypes using a tag CoderType.
* @param tagCoder - CoderType for the tag value.
* @param variants - Object mapping string representations to [tag value, CoderType] pairs.
* * @returns CoderType representing the mapping.
* @example
* const cborValue: P.CoderType<CborValue> = P.mappedTag(P.bits(3), {
* uint: [0, cborUint], // An unsigned integer in the range 0..264-1 inclusive.
* negint: [1, cborNegint], // A negative integer in the range -264..-1 inclusive
* bytes: [2, P.lazy(() => cborLength(P.bytes, cborValue))], // A byte string.
* string: [3, P.lazy(() => cborLength(P.string, cborValue))], // A text string (utf8)
* array: [4, cborArrLength(P.lazy(() => cborValue))], // An array of data items
* map: [5, P.lazy(() => cborArrLength(P.tuple([cborValue, cborValue])))], // A map of pairs of data items
* tag: [6, P.tuple([cborUint, P.lazy(() => cborValue)] as const)], // A tagged data item ("tag") whose tag number
* simple: [7, cborSimple], // Floating-point numbers and simple values, as well as the "break" stop code
* });
*/
export declare function mappedTag<T extends Values<{
[P in keyof Variants]: {
TAG: P;
data: UnwrapCoder<Variants[P][1]>;
};
}>, TagValue extends string | number, Variants extends Record<string, [TagValue, CoderType<any>]>>(tagCoder: CoderType<TagValue>, variants: Variants): CoderType<T>;
/**
* Bitset of boolean values with optional padding.
* @param names - An array of string names for the bitset values.
* @param pad - Whether to pad the bitset to a multiple of 8 bits.
* @returns CoderType representing the bitset.
* @template Names
* @example
* const myBitset = P.bitset(['flag1', 'flag2', 'flag3', 'flag4'], true);
*/
export declare function bitset<Names extends readonly string[]>(names: Names, pad?: boolean): CoderType<Record<Names[number], boolean>>;
/** Padding function which always returns zero */
export declare const ZeroPad: PadFn;
/**
* Pads a CoderType with a specified block size and padding function on the left side.
* @param blockSize - Block size for padding (positive safe integer).
* @param inner - Inner CoderType to pad.
* @param padFn - Padding function to use. If not provided, zero padding is used.
* @returns CoderType representing the padded value.
* @example
* // Pad a U32BE with a block size of 4 and zero padding
* const paddedU32BE = P.padLeft(4, P.U32BE);
*
* // Pad a string with a block size of 16 and custom padding
* const paddedString = P.padLeft(16, P.string(P.U8), (i) => i + 1);
*/
export declare function padLeft<T>(blockSize: number, inner: CoderType<T>, padFn: Option<PadFn>): CoderType<T>;
/**
* Pads a CoderType with a specified block size and padding function on the right side.
* @param blockSize - Block size for padding (positive safe integer).
* @param inner - Inner CoderType to pad.
* @param padFn - Padding function to use. If not provided, zero padding is used.
* @returns CoderType representing the padded value.
* @example
* // Pad a U16BE with a block size of 2 and zero padding
* const paddedU16BE = P.padRight(2, P.U16BE);
*
* // Pad a bytes with a block size of 8 and custom padding
* const paddedBytes = P.padRight(8, P.bytes(null), (i) => i + 1);
*/
export declare function padRight<T>(blockSize: number, inner: CoderType<T>, padFn: Option<PadFn>): CoderType<T>;
/**
* Pointer to a value using a pointer CoderType and an inner CoderType.
* Pointers are scoped, and the next pointer in the dereference chain is offset by the previous one.
* By default (if no 'allowMultipleReads' in ReaderOpts is set) is safe, since
* same region of memory cannot be read multiple times.
* @param ptr - CoderType for the pointer value.
* @param inner - CoderType for encoding/decoding the pointed value.
* @param sized - Whether the pointer should have a fixed size.
* @returns CoderType representing the pointer to the value.
* @example
* const pointerToU8 = P.pointer(P.U16BE, P.U8); // Pointer to a single U8 value
*/
export declare function pointer<T>(ptr: CoderType<number>, inner: CoderType<T>, sized?: boolean): CoderType<T>;
export declare const _TEST: {
_bitset: {
BITS: number;
FULL_MASK: number;
len: (len: number) => number;
create: (len: number) => Uint32Array;
clean: (bs: Uint32Array) => Uint32Array;
debug: (bs: Uint32Array) => string[];
checkLen: (bs: Uint32Array, len: number) => void;
chunkLen: (bsLen: number, pos: number, len: number) => void;
set: (bs: Uint32Array, chunk: number, value: number, allowRewrite?: boolean) => boolean;
pos: (pos: number, i: number) => {
chunk: number;
mask: number;
};
indices: (bs: Uint32Array, len: number, invert?: boolean) => number[];
range: (arr: number[]) => {
pos: number;
length: number;
}[];
rangeDebug: (bs: Uint32Array, len: number, invert?: boolean) => string;
setRange: (bs: Uint32Array, bsLen: number, pos: number, len: number, allowRewrite?: boolean) => boolean;
};
_Reader: typeof _Reader;
_Writer: typeof _Writer;
Path: {
/**
* Internal method for handling stack of paths (debug, errors, dynamic fields via path)
* This is looks ugly (callback), but allows us to force stack cleaning by construction (.pop always after function).
* Also, this makes impossible:
* - pushing field when stack is empty
* - pushing field inside of field (real bug)
* NOTE: we don't want to do '.pop' on error!
*/
pushObj: (stack: PathStack, obj: StructOut, objFn: _PathObjFn) => void;
path: (stack: PathStack) => string;
err(name: string, stack: PathStack, msg: string | Error): Error;
resolve: (stack: PathStack, path: string) => StructOut | undefined;
};
};
//# sourceMappingURL=index.d.ts.map

1
dev/env/node_modules/micro-packed/lib/index.d.ts.map generated vendored Executable file

File diff suppressed because one or more lines are too long

2023
dev/env/node_modules/micro-packed/lib/index.js generated vendored Executable file

File diff suppressed because it is too large Load Diff

1
dev/env/node_modules/micro-packed/lib/index.js.map generated vendored Executable file

File diff suppressed because one or more lines are too long

72
dev/env/node_modules/micro-packed/package.json generated vendored Executable file
View File

@@ -0,0 +1,72 @@
{
"name": "micro-packed",
"version": "0.7.3",
"description": "Define complex binary structures using composable primitives",
"dependencies": {
"@scure/base": "~1.2.5"
},
"files": [
"!lib/_type_test.js",
"!lib/_type_test.js.map",
"!lib/_type_test.d.ts",
"!lib/_type_test.d.ts.map",
"!lib/esm/_type_test.js",
"!lib/esm/_type_test.js.map",
"!lib/esm/_type_test.d.ts",
"!lib/esm/_type_test.d.ts.map",
"!src/_type_test.ts",
"lib",
"src"
],
"main": "lib/index.js",
"module": "lib/esm/index.js",
"types": "lib/index.d.ts",
"exports": {
".": {
"import": "./lib/esm/index.js",
"require": "./lib/index.js"
},
"./debugger": {
"import": "./lib/esm/debugger.js",
"require": "./lib/debugger.js"
}
},
"sideEffects": false,
"scripts": {
"bench": "node benchmark/index.js noble",
"bench:all": "node benchmark/index.js",
"build": "tsc && tsc -p tsconfig.cjs.json",
"build:release": "npx jsbt esbuild test/build",
"lint": "prettier --check src",
"format": "prettier --write src",
"test": "node test/index.js",
"test:bun": "bun test/index.js",
"test:deno": "deno --allow-env --allow-read test/index.js",
"test:slow": "node test/slow.test.js"
},
"author": "Paul Miller (https://paulmillr.com)",
"license": "MIT",
"homepage": "https://github.com/paulmillr/micro-packed",
"repository": {
"type": "git",
"url": "git+https://github.com/paulmillr/micro-packed.git"
},
"devDependencies": {
"@paulmillr/jsbt": "0.3.3",
"fast-check": "3.0.0",
"micro-bmark": "0.4.1",
"micro-should": "0.5.2",
"prettier": "3.5.3",
"typescript": "5.8.3"
},
"keywords": [
"encode",
"encoder",
"binary",
"bytes",
"struct",
"tuple",
"enum"
],
"funding": "https://paulmillr.com/funding/"
}

309
dev/env/node_modules/micro-packed/src/debugger.ts generated vendored Executable file
View File

@@ -0,0 +1,309 @@
import { base64, hex } from '@scure/base';
import * as P from './index.ts';
const Path = P._TEST.Path; // Internal, debug-only
const UNKNOWN = '(???)';
const codes = { esc: 27, nl: 10 };
const esc = String.fromCharCode(codes.esc);
const nl = String.fromCharCode(codes.nl);
const bold = esc + '[1m';
const gray = esc + '[90m';
const reset = esc + '[0m';
const red = esc + '[31m';
const green = esc + '[32m';
const yellow = esc + '[33m';
type DebugPath = { start: number; end?: number; path: string; value?: any };
class DebugReader extends P._TEST._Reader {
debugLst: DebugPath[] = [];
cur?: DebugPath;
get lastElm() {
if (this.debugLst.length) return this.debugLst[this.debugLst.length - 1];
return { start: 0, end: 0, path: '' };
}
pushObj(obj: P.StructOut, objFn: P._PathObjFn) {
return Path.pushObj(this.stack, obj, (cb) => {
objFn((field: string, fieldFn: Function) => {
cb(field, () => {
{
const last = this.lastElm;
if (last.end === undefined) last.end = this.pos;
else if (last.end !== this.pos) {
this.debugLst.push({
path: `${Path.path(this.stack)}/${UNKNOWN}`,
start: last.end,
end: this.pos,
});
}
this.cur = { path: `${Path.path(this.stack)}/${field}`, start: this.pos };
}
fieldFn();
{
// happens if pop after pop (exit from nested structure)
if (!this.cur) {
const last = this.lastElm;
if (last.end === undefined) last.end = this.pos;
else if (last.end !== this.pos) {
this.debugLst.push({
start: last.end,
end: this.pos,
path: last.path + `/${UNKNOWN}`,
});
}
} else {
this.cur.end = this.pos;
const last = this.stack[this.stack.length - 1];
const lastItem = last.obj;
const lastField = last.field;
if (lastItem && lastField !== undefined) this.cur.value = lastItem[lastField];
this.debugLst.push(this.cur);
this.cur = undefined;
}
}
});
});
});
}
finishDebug(): void {
const end = this.data.length;
if (this.cur) this.debugLst.push({ end, ...this.cur });
const last = this.lastElm;
if (!last || last.end !== end) this.debugLst.push({ start: this.pos, end, path: UNKNOWN });
}
}
function toBytes(data: string | P.Bytes): P.Bytes {
if (P.utils.isBytes(data)) return data;
if (typeof data !== 'string') throw new Error('PD: data should be string or Uint8Array');
try {
return base64.decode(data);
} catch (e) {}
try {
return hex.decode(data);
} catch (e) {}
throw new Error(`PD: data has unknown string format: ${data}`);
}
type DebugData = { path: string; data: P.Bytes; value?: any };
function mapData(lst: DebugPath[], data: P.Bytes): DebugData[] {
let end = 0;
const res: DebugData[] = [];
for (const elm of lst) {
if (elm.start !== end) throw new Error(`PD: elm start=${elm.start} after prev elm end=${end}`);
if (elm.end === undefined) throw new Error(`PD: elm.end is undefined=${elm}`);
res.push({ path: elm.path, data: data.slice(elm.start, elm.end), value: elm.value });
end = elm.end;
}
if (end !== data.length) throw new Error('PD: not all data mapped');
return res;
}
function chrWidth(s: string) {
/*
It is almost impossible to find out real characters width in terminal since it depends on terminal itself, current unicode version and moon's phase.
So, we just stripping ANSI, tabs and unicode supplimental characters. Emoji support requires big tables (and have no guarantee to work), so we ignore it for now.
Also, no support for full width unicode characters for now.
*/
return s
.replace(
/[\u001B\u009B][[\]()#;?]*(?:(?:(?:[a-zA-Z\d]*(?:;[-a-zA-Z\d\/#&.:=?%@~_]*)*)?\u0007)|(?:(?:\d{1,4}(?:;\d{0,4})*)?[\dA-PR-TZcf-ntqry=><~]))/g,
''
)
.replace('\t', ' ')
.replace(/[\uD800-\uDBFF][\uDC00-\uDFFF]/g, ' ').length;
}
function wrap(s: string, padding: number = 0) {
// @ts-ignore
const limit = process.stdout.columns - 3 - padding;
if (chrWidth(s) <= limit) return s;
while (chrWidth(s) > limit) s = s.slice(0, -1);
return `${s}${reset}...`;
}
export function table(data: any[]): void {
let res: string[] = [];
const str = (v: any) => (v === undefined ? '' : '' + v);
const pad = (s: string, width: number) =>
`${s}${''.padEnd(Math.max(0, width - chrWidth(s)), ' ')}`;
let widths: Record<string, number> = {};
for (let elm of data) {
for (let k in elm) {
widths[k] = Math.max(
widths[k] || 0,
chrWidth(str(k)),
str(elm[k])
.split(nl)
.reduce((a, b) => Math.max(a, chrWidth(b)), 0)
);
}
}
const columns = Object.keys(widths);
if (!data.length || !columns.length) throw new Error('No data');
const padding = ` ${reset}${gray}${reset} `;
res.push(wrap(` ${columns.map((c) => `${bold}${pad(c, widths[c])}`).join(padding)}${reset}`, 3));
for (let idx = 0; idx < data.length; idx++) {
const elm = data[idx];
const row = columns.map((i) => str(elm[i]).split(nl));
let message = [...Array(Math.max(...row.map((i) => i.length))).keys()]
.map((line) => row.map((c, i) => pad(str(c[line]), widths[columns[i]])))
.map((line, _) => wrap(` ${line.join(padding)} `, 1))
.join(nl);
res.push(message);
}
for (let i = 0; i < res.length; i++) {
const border = columns
.map((c) => ''.padEnd(widths[c], '─'))
.join(`${i === res.length - 1 ? '┴' : '┼'}`);
res[i] += wrap(`${nl}${reset}${gray}${border}${reset}`);
}
// @ts-ignore
console.log(res.join(nl));
}
function fmtData(data: P.Bytes, perLine = 8) {
const res = [];
for (let i = 0; i < data.length; i += perLine) {
res.push(hex.encode(data.slice(i, i + perLine)));
}
return res.map((i) => `${bold}${i}${reset}`).join(nl);
}
function fmtValue(value: any) {
if (P.utils.isBytes(value)) return `b(${green}${hex.encode(value)}${reset} len=${value.length})`;
if (typeof value === 'string') return `s(${green}"${value}"${reset} len=${value.length})`;
if (typeof value === 'number' || typeof value === 'bigint') return `n(${value})`;
// console.log('fmt', value);
// if (Object.prototype.toString.call(value) === '[object Object]') return inspect(value);
return '' + value;
}
export function decode(
coder: P.CoderType<any>,
data: string | P.Bytes,
forcePrint = false
): ReturnType<(typeof coder)['decode']> {
data = toBytes(data);
const r = new DebugReader(data);
let res, e;
try {
res = coder.decodeStream(r);
r.finish();
} catch (_e) {
e = _e;
}
r.finishDebug();
if (e || forcePrint) {
// @ts-ignore
console.log('==== DECODED BEFORE ERROR ====');
table(
mapData(r.debugLst, data).map((elm) => ({
Data: fmtData(elm.data),
Len: elm.data.length,
Path: `${green}${elm.path}${reset}`,
Value: fmtValue(elm.value),
}))
);
// @ts-ignore
console.log('==== /DECODED BEFORE ERROR ====');
}
if (e) throw e;
return res;
}
function getMap(coder: P.CoderType<any>, data: string | P.Bytes) {
data = toBytes(data);
const r = new DebugReader(data);
coder.decodeStream(r);
r.finish();
r.finishDebug();
return mapData(r.debugLst, data);
}
function diffData(a: P.Bytes, e: P.Bytes) {
const len = Math.max(a.length, e.length);
let outA = '',
outE = '';
const charHex = (n: number) => n.toString(16).padStart(2, '0');
for (let i = 0; i < len; i++) {
const [aI, eI] = [a[i], e[i]];
if (i && !(i % 8)) {
if (aI !== undefined) outA += nl;
if (eI !== undefined) outE += nl;
}
if (aI !== undefined) outA += aI === eI ? charHex(aI) : `${yellow}${charHex(aI)}${reset}`;
if (eI !== undefined) outE += aI === eI ? charHex(eI) : `${yellow}${charHex(eI)}${reset}`;
}
return [outA, outE];
}
function diffPath(a: string, e: string) {
if (a === e) return a;
return `A: ${red}${a}${reset}${nl}E: ${green}${e}${reset}`;
}
function diffLength(a: P.Bytes, e: P.Bytes) {
const [aLen, eLen] = [a.length, e.length];
if (aLen === eLen) return aLen;
return `A: ${red}${aLen}${reset}${nl}E: ${green}${eLen}${reset}`;
}
function diffValue(a: any, e: any) {
const [aV, eV] = [a, e].map(fmtValue);
if (aV === eV) return aV;
return `A: ${red}${aV}${reset}${nl}E: ${green}${eV}${reset}`;
}
export function diff(
coder: P.CoderType<any>,
actual: string | P.Bytes,
expected: string | P.Bytes,
skipSame = true
): void {
// @ts-ignore
console.log('==== DIFF ====');
const [_actual, _expected] = [actual, expected].map((i) => getMap(coder, i)) as [
DebugData[],
DebugData[],
];
const len = Math.max(_actual.length, _expected.length);
const data = [];
const DEF = { data: P.EMPTY, path: '' };
for (let i = 0; i < len; i++) {
const [a, e] = [_actual[i] || DEF, _expected[i] || DEF];
if (P.utils.equalBytes(a.data, e.data) && skipSame) continue;
const [adata, edata] = diffData(a.data, e.data);
data.push({
'Data (A)': adata,
'Data (E)': edata,
Len: diffLength(a.data, e.data),
Path: diffPath(a.path, e.path),
Value: diffValue(a.value, e.value),
});
}
table(data);
// @ts-ignore
console.log('==== /DIFF ====');
}
/**
* Wraps a CoderType with debug logging for encoding and decoding operations.
* @param inner - Inner CoderType to wrap.
* @returns Inner wrapped in debug prints via console.log.
* @example
* const debugInt = P.debug(P.U32LE); // Will print info to console on encoding/decoding
*/
export function debug<T>(inner: P.CoderType<T>): P.CoderType<T> {
if (!P.utils.isCoder(inner)) throw new Error(`debug: invalid inner value ${inner}`);
const log = (name: string, rw: P.Reader | P.Writer, value: any) => {
// @ts-ignore
console.log(`DEBUG/${name}(${Path.path(rw.stack)}):`, { type: typeof value, value });
return value;
};
return P.wrap({
size: inner.size,
encodeStream: (w: P.Writer, value: T) => inner.encodeStream(w, log('encode', w, value)),
decodeStream: (r: P.Reader): T => log('decode', r, inner.decodeStream(r)),
});
}

2196
dev/env/node_modules/micro-packed/src/index.ts generated vendored Executable file

File diff suppressed because it is too large Load Diff

3
dev/env/node_modules/micro-packed/src/package.json generated vendored Executable file
View File

@@ -0,0 +1,3 @@
{
"type": "module"
}