layout-data 0.0.0-stage → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +35 -0
- package/LICENSE +373 -0
- package/README.md +125 -2
- package/dist/layout-data.js +8320 -0
- package/dist/types/Ldata.d.ts +169 -0
- package/dist/types/Ltag.d.ts +74 -0
- package/dist/types/codecs.d.ts +11 -0
- package/dist/types/dispatch.d.ts +11 -0
- package/dist/types/endian.d.ts +65 -0
- package/dist/types/index.d.ts +7 -0
- package/dist/types/internal_types.d.ts +65 -0
- package/dist/types/layout.d.ts +54 -0
- package/dist/types/observer.d.ts +43 -0
- package/dist/types/registry.d.ts +47 -0
- package/dist/types/reserved.d.ts +9 -0
- package/dist/types/structure.d.ts +27 -0
- package/dist/types/typedefs.d.ts +155 -0
- package/dist/types/types.d.ts +25 -0
- package/package.json +47 -3
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
export class Ldata extends EventEmitter<[never]> {
|
|
2
|
+
/**
|
|
3
|
+
* The class of a layout, built on the first use of its name: the name tells
|
|
4
|
+
* the layouts apart, as the registry holds one layout per name.
|
|
5
|
+
*
|
|
6
|
+
* @param {Layout} layout - A registered layout.
|
|
7
|
+
* @returns {typeof Ldata}
|
|
8
|
+
*/
|
|
9
|
+
static "__#private@#class_of"(layout: Layout): typeof Ldata;
|
|
10
|
+
/**
|
|
11
|
+
* Builds the class of a layout: a subclass of Ldata whose prototype holds
|
|
12
|
+
* the accessor of every tag, shared by all instances of the layout. The
|
|
13
|
+
* accessors are defined here so that they reach the private buffer.
|
|
14
|
+
*
|
|
15
|
+
* @param {Layout} layout
|
|
16
|
+
* @returns {typeof Ldata}
|
|
17
|
+
*/
|
|
18
|
+
static "__#private@#build_class"(layout: Layout): typeof Ldata;
|
|
19
|
+
/**
|
|
20
|
+
* Subscribes a function called for the accesses to every data block, with
|
|
21
|
+
* (data, kind, tags); the same function twice is one subscription
|
|
22
|
+
* (doc/spec-data-api.md §2.8).
|
|
23
|
+
*
|
|
24
|
+
* @param {Class_Access_Listener} listener
|
|
25
|
+
* @throws {TypeError} When listener is not a function.
|
|
26
|
+
*/
|
|
27
|
+
static on_access(listener: Class_Access_Listener): void;
|
|
28
|
+
/**
|
|
29
|
+
* Cancels a subscription of on_access; nothing happens for a function that
|
|
30
|
+
* is not subscribed.
|
|
31
|
+
*
|
|
32
|
+
* @param {Class_Access_Listener} listener
|
|
33
|
+
*/
|
|
34
|
+
static off_access(listener: Class_Access_Listener): void;
|
|
35
|
+
/**
|
|
36
|
+
* Creates a data block of a layout (doc/spec-data-api.md §2.1).
|
|
37
|
+
*
|
|
38
|
+
* `new Ldata(layout, name)` returns an instance of the class built for the
|
|
39
|
+
* layout name (a subclass of Ldata whose prototype holds the tag
|
|
40
|
+
* accessors), building the class on the first use of the name.
|
|
41
|
+
*
|
|
42
|
+
* @param {Layout | string} layout - A registered layout, or its name (get_layout).
|
|
43
|
+
* @param {string} name - The name of the Ldata instance, a string that cannot be changed afterwards.
|
|
44
|
+
* @throws {TypeError} When name is not a string.
|
|
45
|
+
* @throws {Error} For an unknown layout name, or a layout that is not the registered one.
|
|
46
|
+
*/
|
|
47
|
+
constructor(layout: Layout | string, name: string);
|
|
48
|
+
/** @returns {number} Size of the data block in bytes. */
|
|
49
|
+
get size(): number;
|
|
50
|
+
/** @returns {string} The name given at creation, used in logs and error messages. */
|
|
51
|
+
get name(): string;
|
|
52
|
+
/**
|
|
53
|
+
* The compiled layout of this data block (doc/design.md §3), read-only.
|
|
54
|
+
* The tag accessors are defined once on the prototype of the class built for the layout.
|
|
55
|
+
*
|
|
56
|
+
* @returns {Layout}
|
|
57
|
+
*/
|
|
58
|
+
get layout(): Layout;
|
|
59
|
+
/**
|
|
60
|
+
* Subscribes a listener; typed for `change` and `write`, any listener for
|
|
61
|
+
* another event name (doc/spec-data-api.md §2.7).
|
|
62
|
+
*
|
|
63
|
+
* @template {string | symbol} E
|
|
64
|
+
* @param {E} event
|
|
65
|
+
* @param {Data_Listener<E>} listener
|
|
66
|
+
* @returns {this}
|
|
67
|
+
*/
|
|
68
|
+
on<E extends string | symbol>(event: E, listener: Data_Listener<E>): this;
|
|
69
|
+
/**
|
|
70
|
+
* Subscribes a listener for one emission, typed like `on`.
|
|
71
|
+
*
|
|
72
|
+
* @template {string | symbol} E
|
|
73
|
+
* @param {E} event
|
|
74
|
+
* @param {Data_Listener<E>} listener
|
|
75
|
+
* @returns {this}
|
|
76
|
+
*/
|
|
77
|
+
once<E extends string | symbol>(event: E, listener: Data_Listener<E>): this;
|
|
78
|
+
/**
|
|
79
|
+
* Removes a listener, typed like `on`.
|
|
80
|
+
*
|
|
81
|
+
* @template {string | symbol} E
|
|
82
|
+
* @param {E} event
|
|
83
|
+
* @param {Data_Listener<E>} listener
|
|
84
|
+
* @returns {this}
|
|
85
|
+
*/
|
|
86
|
+
off<E extends string | symbol>(event: E, listener: Data_Listener<E>): this;
|
|
87
|
+
/**
|
|
88
|
+
* Retrieves the handle of a tag, creating it on first use.
|
|
89
|
+
* @param {string} tagname - The name of the tag to retrieve.
|
|
90
|
+
* @returns {Ltag|undefined} The Ltag handle, undefined for an unknown name.
|
|
91
|
+
*/
|
|
92
|
+
get(tagname: string): Ltag | undefined;
|
|
93
|
+
/**
|
|
94
|
+
* Runs fn synchronously and makes its writes one whole: no event is emitted
|
|
95
|
+
* during it; when fn returns, one detection runs and one `write` is emitted
|
|
96
|
+
* if fn wrote; when fn throws, the buffer is restored and no event is
|
|
97
|
+
* emitted (doc/spec-data-api.md §4.2). The return value of fn is not
|
|
98
|
+
* inspected: a Promise is neither awaited nor rejected.
|
|
99
|
+
*
|
|
100
|
+
* @template T
|
|
101
|
+
* @param {() => T} fn
|
|
102
|
+
* @returns {T} The return value of fn.
|
|
103
|
+
* @throws {Error} Inside a transaction; or whatever fn throws, after the rollback.
|
|
104
|
+
*/
|
|
105
|
+
transaction<T>(fn: () => T): T;
|
|
106
|
+
/**
|
|
107
|
+
* Reads a range of bytes (doc/spec-data-api.md §2.5).
|
|
108
|
+
*
|
|
109
|
+
* @param {number} [offset=0] - Byte offset.
|
|
110
|
+
* @param {number} [length] - Number of bytes, up to the end of the data block by default.
|
|
111
|
+
* @returns {Buffer} A copy: changing it does not affect the data block.
|
|
112
|
+
* @throws {RangeError} For an offset or length out of range.
|
|
113
|
+
*/
|
|
114
|
+
read_bytes(offset?: number, length?: number): Buffer;
|
|
115
|
+
/**
|
|
116
|
+
* Writes all the bytes of source from a byte offset (doc/spec-data-api.md §2.5).
|
|
117
|
+
* An empty source writes nothing and emits no `write`.
|
|
118
|
+
*
|
|
119
|
+
* @param {number} offset - Byte offset.
|
|
120
|
+
* @param {Uint8Array} source
|
|
121
|
+
* @throws {RangeError} For an offset out of range, or a run past the end of the data block.
|
|
122
|
+
* @throws {TypeError} When source is not a Uint8Array.
|
|
123
|
+
*/
|
|
124
|
+
write_bytes(offset: number, source: Uint8Array): void;
|
|
125
|
+
/**
|
|
126
|
+
* Writes the bits selected by mask of the byte at offset; the other bits
|
|
127
|
+
* are unchanged (doc/spec-data-api.md §2.5).
|
|
128
|
+
*
|
|
129
|
+
* @param {number} offset - Byte offset.
|
|
130
|
+
* @param {number} mask - An integer from 1 to 0xff.
|
|
131
|
+
* @param {boolean} value - Taken by truthiness.
|
|
132
|
+
* @throws {RangeError} For an offset out of range, or a mask that is not an integer from 1 to 0xff.
|
|
133
|
+
*/
|
|
134
|
+
write_bit(offset: number, mask: number, value: boolean): void;
|
|
135
|
+
/**
|
|
136
|
+
* Converts the bytes of a tag from a device-ordered IO buffer and writes
|
|
137
|
+
* them into the data block; a write like any other
|
|
138
|
+
* (doc/spec-data-api.md §2.9).
|
|
139
|
+
*
|
|
140
|
+
* @param {string} name - The tag name.
|
|
141
|
+
* @param {Uint8Array} io_buffer - Indexed like the byte offsets of the data block.
|
|
142
|
+
* @param {Endian} endian - Device byte order.
|
|
143
|
+
* @throws {Error} For an unknown tag name.
|
|
144
|
+
* @throws {RangeError} For another byte order, or a tag out of the IO buffer.
|
|
145
|
+
* @throws {TypeError} When io_buffer is not a Uint8Array.
|
|
146
|
+
*/
|
|
147
|
+
load_tag(name: string, io_buffer: Uint8Array, endian: Endian): void;
|
|
148
|
+
/**
|
|
149
|
+
* Converts the bytes of a tag and writes them into a device-ordered IO
|
|
150
|
+
* buffer; the data block is unchanged and no event is emitted
|
|
151
|
+
* (doc/spec-data-api.md §2.9).
|
|
152
|
+
*
|
|
153
|
+
* @param {string} name - The tag name.
|
|
154
|
+
* @param {Uint8Array} io_buffer - Indexed like the byte offsets of the data block.
|
|
155
|
+
* @param {Endian} endian - Device byte order.
|
|
156
|
+
* @throws {Error} For an unknown tag name.
|
|
157
|
+
* @throws {RangeError} For another byte order, or a tag out of the IO buffer.
|
|
158
|
+
* @throws {TypeError} When io_buffer is not a Uint8Array.
|
|
159
|
+
*/
|
|
160
|
+
store_tag(name: string, io_buffer: Uint8Array, endian: Endian): void;
|
|
161
|
+
#private;
|
|
162
|
+
}
|
|
163
|
+
import { EventEmitter } from "node:events";
|
|
164
|
+
import type { Layout } from "./typedefs.js";
|
|
165
|
+
import type { Data_Listener } from "./typedefs.js";
|
|
166
|
+
import { Ltag } from "./Ltag.js";
|
|
167
|
+
import { Buffer } from "node:buffer";
|
|
168
|
+
import type { Endian } from "./typedefs.js";
|
|
169
|
+
import type { Class_Access_Listener } from "./typedefs.js";
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/** @import { Endian, Tag_Listener, Tag_Type } from "./typedefs.js" */
|
|
2
|
+
/** @import { Layout_Entry } from "./internal_types.js" */
|
|
3
|
+
/**
|
|
4
|
+
* The interface of one tag of an Ldata (doc/spec-data-api.md §3). It holds no
|
|
5
|
+
* value: reading `value` decodes it from the buffer of the Ldata, writing it
|
|
6
|
+
* is the same as `ldata[name] = value`, and `load` / `store` are `load_tag` /
|
|
7
|
+
* `store_tag` of the Ldata for the name of the tag. `change` events
|
|
8
|
+
* (old_value, new_value) are emitted by the Observer of the Ldata.
|
|
9
|
+
*/
|
|
10
|
+
export class Ltag extends EventEmitter<[never]> {
|
|
11
|
+
/**
|
|
12
|
+
* @param {import("./Ldata.js").Ldata} ldata - The Ldata the tag belongs to.
|
|
13
|
+
* @param {Layout_Entry} entry - The compiled entry of the tag.
|
|
14
|
+
*/
|
|
15
|
+
constructor(ldata: import("./Ldata.js").Ldata, entry: Layout_Entry);
|
|
16
|
+
/**
|
|
17
|
+
* Subscribes a listener; `change` is typed (old_value, new_value), any
|
|
18
|
+
* listener for another event name (doc/spec-data-api.md §3).
|
|
19
|
+
*
|
|
20
|
+
* @template {string | symbol} E
|
|
21
|
+
* @param {E} event
|
|
22
|
+
* @param {Tag_Listener<E>} listener
|
|
23
|
+
* @returns {this}
|
|
24
|
+
*/
|
|
25
|
+
on<E extends string | symbol>(event: E, listener: Tag_Listener<E>): this;
|
|
26
|
+
/**
|
|
27
|
+
* Subscribes a listener for one emission, typed like `on`.
|
|
28
|
+
*
|
|
29
|
+
* @template {string | symbol} E
|
|
30
|
+
* @param {E} event
|
|
31
|
+
* @param {Tag_Listener<E>} listener
|
|
32
|
+
* @returns {this}
|
|
33
|
+
*/
|
|
34
|
+
once<E extends string | symbol>(event: E, listener: Tag_Listener<E>): this;
|
|
35
|
+
/**
|
|
36
|
+
* Removes a listener, typed like `on`.
|
|
37
|
+
*
|
|
38
|
+
* @template {string | symbol} E
|
|
39
|
+
* @param {E} event
|
|
40
|
+
* @param {Tag_Listener<E>} listener
|
|
41
|
+
* @returns {this}
|
|
42
|
+
*/
|
|
43
|
+
off<E extends string | symbol>(event: E, listener: Tag_Listener<E>): this;
|
|
44
|
+
/** @returns {string} */
|
|
45
|
+
get name(): string;
|
|
46
|
+
/** @returns {Tag_Type} Lower case type name. */
|
|
47
|
+
get type(): Tag_Type;
|
|
48
|
+
/** @returns {number} Size in bytes; a Bool has the byte it lies in. */
|
|
49
|
+
get size(): number;
|
|
50
|
+
/** @param {number | boolean} value */
|
|
51
|
+
set value(value: number | boolean);
|
|
52
|
+
/** @returns {number | boolean} */
|
|
53
|
+
get value(): number | boolean;
|
|
54
|
+
/**
|
|
55
|
+
* Same as `ldata.load_tag(name, io_buffer, endian)` (doc/spec-data-api.md §2.9).
|
|
56
|
+
*
|
|
57
|
+
* @param {Uint8Array} io_buffer
|
|
58
|
+
* @param {Endian} endian
|
|
59
|
+
*/
|
|
60
|
+
load(io_buffer: Uint8Array, endian: Endian): void;
|
|
61
|
+
/**
|
|
62
|
+
* Same as `ldata.store_tag(name, io_buffer, endian)` (doc/spec-data-api.md §2.9).
|
|
63
|
+
*
|
|
64
|
+
* @param {Uint8Array} io_buffer
|
|
65
|
+
* @param {Endian} endian
|
|
66
|
+
*/
|
|
67
|
+
store(io_buffer: Uint8Array, endian: Endian): void;
|
|
68
|
+
#private;
|
|
69
|
+
}
|
|
70
|
+
import { EventEmitter } from "node:events";
|
|
71
|
+
import type { Tag_Listener } from "./typedefs.js";
|
|
72
|
+
import type { Tag_Type } from "./typedefs.js";
|
|
73
|
+
import type { Endian } from "./typedefs.js";
|
|
74
|
+
import type { Layout_Entry } from "./internal_types.js";
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/** The largest finite float32 value; a finite number above it is refused by a Real. */
|
|
2
|
+
export const FLOAT32_MAX: 3.4028234663852886e+38;
|
|
3
|
+
/**
|
|
4
|
+
* Codec of each tag type (lower case): its size in bytes, `check(value)`, which
|
|
5
|
+
* returns null for a value that can be written and the reason otherwise,
|
|
6
|
+
* `get(buffer, byte, mask)` and `set(buffer, byte, mask, value)`. `set` is
|
|
7
|
+
* called with a checked value only (doc/spec-data-api.md §2.3).
|
|
8
|
+
*
|
|
9
|
+
* @type {Record<string, import("./internal_types.js").Codec>}
|
|
10
|
+
*/
|
|
11
|
+
export const CODECS: Record<string, import("./internal_types.js").Codec>;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Calls every listener of an event, in the order they subscribed, and pushes
|
|
3
|
+
* what a listener throws to `errors` instead of letting it stop the others.
|
|
4
|
+
* A `once` listener removes itself as usual.
|
|
5
|
+
*
|
|
6
|
+
* @param {import("node:events").EventEmitter | undefined} emitter - Nothing happens for undefined.
|
|
7
|
+
* @param {string} event
|
|
8
|
+
* @param {any[]} args
|
|
9
|
+
* @param {unknown[]} errors
|
|
10
|
+
*/
|
|
11
|
+
export function emit_all(emitter: import("node:events").EventEmitter | undefined, event: string, args: any[], errors: unknown[]): void;
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Throws for a byte order that is not one of BE, LE, BEBS and LEBS, instead of
|
|
3
|
+
* treating it as BE and corrupting the data silently.
|
|
4
|
+
*
|
|
5
|
+
* @param {string} endian
|
|
6
|
+
* @throws {RangeError}
|
|
7
|
+
*/
|
|
8
|
+
export function check_endian(endian: string): void;
|
|
9
|
+
/**
|
|
10
|
+
* Index in a device-ordered IO buffer of the byte of a single-byte entry
|
|
11
|
+
* (Bool, Byte, SInt, USInt): when the endian swaps the register bytes, the
|
|
12
|
+
* byte sits in the other half of its register.
|
|
13
|
+
*
|
|
14
|
+
* @param {number} byte - Byte offset of the entry.
|
|
15
|
+
* @param {Endian} endian - Device byte order.
|
|
16
|
+
* @returns {number}
|
|
17
|
+
*/
|
|
18
|
+
export function io_index(byte: number, endian: Endian): number;
|
|
19
|
+
/**
|
|
20
|
+
* The index in a device-ordered IO buffer of every byte of a data block: the
|
|
21
|
+
* byte `i` of the block is the byte `table[i]` of the IO buffer. The table
|
|
22
|
+
* makes loading and storing a whole block a plain byte copy, and it agrees
|
|
23
|
+
* with `load_entry` / `store_entry` for every entry (a Bool or a single-byte
|
|
24
|
+
* entry maps as `io_index`, a multi-byte entry as its endian).
|
|
25
|
+
*
|
|
26
|
+
* @param {Layout} layout - The compiled layout of the data block.
|
|
27
|
+
* @param {Endian} endian - Device byte order: BE, LE, BEBS or LEBS.
|
|
28
|
+
* @returns {Int32Array}
|
|
29
|
+
* @throws {RangeError} For another byte order.
|
|
30
|
+
*/
|
|
31
|
+
export function io_index_table(layout: Layout, endian: Endian): Int32Array;
|
|
32
|
+
/**
|
|
33
|
+
* Byte range [start, end) an entry occupies in a device-ordered IO buffer.
|
|
34
|
+
*
|
|
35
|
+
* @param {Layout_Entry} entry
|
|
36
|
+
* @param {Endian} endian - Device byte order.
|
|
37
|
+
* @returns {{start: number, end: number}}
|
|
38
|
+
*/
|
|
39
|
+
export function io_range(entry: Layout_Entry, endian: Endian): {
|
|
40
|
+
start: number;
|
|
41
|
+
end: number;
|
|
42
|
+
};
|
|
43
|
+
/**
|
|
44
|
+
* Copies an entry from a device-ordered IO buffer into a big-endian buffer.
|
|
45
|
+
* A Bool only changes its own bit. No change is detected here, and the byte
|
|
46
|
+
* order and the range in the IO buffer are not checked (Ldata does).
|
|
47
|
+
*
|
|
48
|
+
* @param {Layout_Entry} entry
|
|
49
|
+
* @param {Uint8Array} io_buffer - The device-ordered source.
|
|
50
|
+
* @param {Uint8Array} buffer - The big-endian destination.
|
|
51
|
+
* @param {Endian} endian - Device byte order.
|
|
52
|
+
*/
|
|
53
|
+
export function load_entry(entry: Layout_Entry, io_buffer: Uint8Array, buffer: Uint8Array, endian: Endian): void;
|
|
54
|
+
/**
|
|
55
|
+
* Copies an entry from a big-endian buffer into a device-ordered IO buffer.
|
|
56
|
+
*
|
|
57
|
+
* @param {Layout_Entry} entry
|
|
58
|
+
* @param {Uint8Array} buffer - The big-endian source.
|
|
59
|
+
* @param {Uint8Array} io_buffer - The device-ordered destination.
|
|
60
|
+
* @param {Endian} endian - Device byte order.
|
|
61
|
+
*/
|
|
62
|
+
export function store_entry(entry: Layout_Entry, buffer: Uint8Array, io_buffer: Uint8Array, endian: Endian): void;
|
|
63
|
+
import type { Endian } from "./typedefs.js";
|
|
64
|
+
import type { Layout } from "./typedefs.js";
|
|
65
|
+
import type { Layout_Entry } from "./internal_types.js";
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export { Ldata } from "./Ldata.js";
|
|
2
|
+
export { Ltag } from "./Ltag.js";
|
|
3
|
+
export { register_layout } from "./layout.js";
|
|
4
|
+
export { get_layout } from "./registry.js";
|
|
5
|
+
export { io_index_table } from "./endian.js";
|
|
6
|
+
export { render_types } from "./types.js";
|
|
7
|
+
export * from "./typedefs.js";
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Codec of one tag type on a big-endian buffer (doc/design.md §4).
|
|
3
|
+
*/
|
|
4
|
+
export type Codec = {
|
|
5
|
+
/**
|
|
6
|
+
* - Size in bytes.
|
|
7
|
+
*/
|
|
8
|
+
size: number;
|
|
9
|
+
/**
|
|
10
|
+
* - The reason a value is refused, null if it can be written.
|
|
11
|
+
*/
|
|
12
|
+
check: (value: any) => string | null;
|
|
13
|
+
get: (buffer: Buffer, byte: number, mask: number) => number | boolean;
|
|
14
|
+
set: (buffer: Buffer, byte: number, mask: number, value: number | boolean) => void;
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* One tag of a compiled layout.
|
|
18
|
+
*/
|
|
19
|
+
export type Layout_Entry = {
|
|
20
|
+
name: string;
|
|
21
|
+
/**
|
|
22
|
+
* - Lower case type name.
|
|
23
|
+
*/
|
|
24
|
+
type: import("./typedefs.js").Tag_Type;
|
|
25
|
+
init_value: number | boolean;
|
|
26
|
+
/**
|
|
27
|
+
* - Byte offset.
|
|
28
|
+
*/
|
|
29
|
+
byte: number;
|
|
30
|
+
/**
|
|
31
|
+
* - Position among the entries of the layout.
|
|
32
|
+
*/
|
|
33
|
+
index: number;
|
|
34
|
+
/**
|
|
35
|
+
* - Size in bytes.
|
|
36
|
+
*/
|
|
37
|
+
size: number;
|
|
38
|
+
/**
|
|
39
|
+
* - Bit mask of a Bool, 0xff otherwise.
|
|
40
|
+
*/
|
|
41
|
+
mask: number;
|
|
42
|
+
codec: Codec;
|
|
43
|
+
};
|
|
44
|
+
/**
|
|
45
|
+
* The expanded structure of a data block (the result of build_structure).
|
|
46
|
+
*/
|
|
47
|
+
export type Data_Struct = {
|
|
48
|
+
name: string;
|
|
49
|
+
/**
|
|
50
|
+
* - Total length in bits.
|
|
51
|
+
*/
|
|
52
|
+
length: number;
|
|
53
|
+
items: import("./typedefs.js").Layout_Item[];
|
|
54
|
+
};
|
|
55
|
+
/**
|
|
56
|
+
* The compiled data of a layout, kept apart from the public Layout
|
|
57
|
+
* (doc/design.md §3).
|
|
58
|
+
*/
|
|
59
|
+
export type Compiled_Layout = {
|
|
60
|
+
entries: Map<string, Layout_Entry>;
|
|
61
|
+
/**
|
|
62
|
+
* - The entries covering each byte.
|
|
63
|
+
*/
|
|
64
|
+
tags_at_byte: Layout_Entry[][];
|
|
65
|
+
};
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Compiles an expanded structure (the result of build_structure) into a Layout
|
|
3
|
+
* (doc/design.md §3) and registers it under its name, the one source of the
|
|
4
|
+
* layouts an Ldata is created from. Registering a structure whose canonical
|
|
5
|
+
* text equals the registered one of that name gives the registered Layout, so
|
|
6
|
+
* the same layout described twice is compiled once; another structure under a
|
|
7
|
+
* used name throws. Throws on an unknown type or a duplicated tag name; the
|
|
8
|
+
* other layout rules are checked by validate_structure. Internal.
|
|
9
|
+
*
|
|
10
|
+
* @param {Data_Struct} data_struct
|
|
11
|
+
* @returns {Layout}
|
|
12
|
+
* @throws {Error} When the name is used by another layout.
|
|
13
|
+
*/
|
|
14
|
+
export function register_structure(data_struct: Data_Struct): Layout;
|
|
15
|
+
/**
|
|
16
|
+
* Reads the sources of the layouts (doc/design.md §3), merges their layouts
|
|
17
|
+
* and fragments into one description and registers it with
|
|
18
|
+
* register_layout_data. Each source is the path of a YAML layout file or a
|
|
19
|
+
* parsed description; a list of sources is merged, so a layout may name a
|
|
20
|
+
* fragment of any source whatever the order. The root key `layouts` of a
|
|
21
|
+
* source maps layout names to item lists; every other root key is a fragment
|
|
22
|
+
* referenced by name.
|
|
23
|
+
*
|
|
24
|
+
* @param {Layout_Source | Layout_Source[]} sources
|
|
25
|
+
* @returns {Registered_Layouts}
|
|
26
|
+
* @throws {Error} With `errors`, every violation found, when the sources are not valid.
|
|
27
|
+
*/
|
|
28
|
+
export function register_sources(sources: Layout_Source | Layout_Source[]): Registered_Layouts;
|
|
29
|
+
/**
|
|
30
|
+
* Registers the layouts of the sources, once per process: a layout is
|
|
31
|
+
* described, registered under its name, and then used by that name
|
|
32
|
+
* (doc/spec-data-api.md §6.4). Nothing is registered when a source is not
|
|
33
|
+
* valid, and such a call does not use up the single call.
|
|
34
|
+
*
|
|
35
|
+
* @param {Layout_Source | Layout_Source[]} sources - The path of a YAML layout file, a parsed description, or a list of them.
|
|
36
|
+
* @returns {Registered_Layouts}
|
|
37
|
+
* @throws {Error} With `errors`, every violation found, when the sources are not valid.
|
|
38
|
+
* @throws {Error} When the layouts were registered by an earlier call.
|
|
39
|
+
*/
|
|
40
|
+
export function register_layout(sources: Layout_Source | Layout_Source[]): Registered_Layouts;
|
|
41
|
+
/**
|
|
42
|
+
* Registers the layouts of one description that is parsed and complete: the
|
|
43
|
+
* root key `layouts` and the fragments the layouts name. Internal.
|
|
44
|
+
*
|
|
45
|
+
* @param {Record<string, any>} root - The parsed description: `layouts` and the fragments.
|
|
46
|
+
* @param {string} [origin] - Names the source in errors.
|
|
47
|
+
* @returns {Registered_Layouts}
|
|
48
|
+
* @throws {Error} With `errors`, every violation found, when the description is not valid.
|
|
49
|
+
*/
|
|
50
|
+
export function register_layout_data(root: Record<string, any>, origin?: string): Registered_Layouts;
|
|
51
|
+
import type { Data_Struct } from "./internal_types.js";
|
|
52
|
+
import type { Layout } from "./typedefs.js";
|
|
53
|
+
import type { Layout_Source } from "./typedefs.js";
|
|
54
|
+
import type { Registered_Layouts } from "./typedefs.js";
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Detects the changes of an Ldata buffer by comparing it with a snapshot
|
|
3
|
+
* (doc/design.md §5.1) and reports each changed tag once.
|
|
4
|
+
*
|
|
5
|
+
* Every write path of the Ldata registers the byte range it wrote with
|
|
6
|
+
* touch(), then calls diff() (in a transaction: at its commit). Only the
|
|
7
|
+
* registered range is compared, the other bytes equal the snapshot by
|
|
8
|
+
* construction. A diff() called while the changes are being reported, by a
|
|
9
|
+
* handler writing a tag, is only recorded; the outer diff() runs another
|
|
10
|
+
* round once the current changes are reported.
|
|
11
|
+
*/
|
|
12
|
+
export class Observer {
|
|
13
|
+
/**
|
|
14
|
+
* @param {Buffer} buffer - The buffer of the Ldata.
|
|
15
|
+
* @param {string} name - The layout name, for errors.
|
|
16
|
+
* @param {Compiled_Layout} compiled - The compiled data of the layout of the Ldata.
|
|
17
|
+
* @param {(entry: Layout_Entry, old_value: any, new_value: any, errors: unknown[]) => void} report - Called for each change; what a handler throws goes to `errors`.
|
|
18
|
+
*/
|
|
19
|
+
constructor(buffer: Buffer, name: string, compiled: Compiled_Layout, report: (entry: Layout_Entry, old_value: any, new_value: any, errors: unknown[]) => void);
|
|
20
|
+
/**
|
|
21
|
+
* Registers the byte range [start, end) as written.
|
|
22
|
+
*
|
|
23
|
+
* @param {number} start
|
|
24
|
+
* @param {number} end - Exclusive.
|
|
25
|
+
*/
|
|
26
|
+
touch(start: number, end: number): void;
|
|
27
|
+
/**
|
|
28
|
+
* Forgets the registered range: the buffer was restored to the snapshot.
|
|
29
|
+
*/
|
|
30
|
+
discard(): void;
|
|
31
|
+
/**
|
|
32
|
+
* Reports every tag changed since the last diff. Nothing is thrown: what
|
|
33
|
+
* the handlers throw, and the exception of changes that do not settle, are
|
|
34
|
+
* pushed to `errors` after every change has been reported (doc/spec-data-api.md §4.4).
|
|
35
|
+
*
|
|
36
|
+
* @param {unknown[]} errors
|
|
37
|
+
*/
|
|
38
|
+
diff(errors: unknown[]): void;
|
|
39
|
+
#private;
|
|
40
|
+
}
|
|
41
|
+
import { Buffer } from "node:buffer";
|
|
42
|
+
import type { Compiled_Layout } from "./internal_types.js";
|
|
43
|
+
import type { Layout_Entry } from "./internal_types.js";
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @param {Layout} layout
|
|
3
|
+
* @param {Compiled_Layout} data
|
|
4
|
+
*/
|
|
5
|
+
export function set_compiled(layout: Layout, data: Compiled_Layout): void;
|
|
6
|
+
/**
|
|
7
|
+
* The compiled data of a layout made by this package.
|
|
8
|
+
*
|
|
9
|
+
* @param {Layout} layout
|
|
10
|
+
* @returns {Compiled_Layout}
|
|
11
|
+
* @throws {Error} For an object that is not a compiled layout.
|
|
12
|
+
*/
|
|
13
|
+
export function compiled_of(layout: Layout): Compiled_Layout;
|
|
14
|
+
/**
|
|
15
|
+
* @param {string} name
|
|
16
|
+
* @returns {Registered | undefined}
|
|
17
|
+
*/
|
|
18
|
+
export function registered_of(name: string): Registered | undefined;
|
|
19
|
+
/**
|
|
20
|
+
* @param {string} name
|
|
21
|
+
* @param {Registered} entry
|
|
22
|
+
*/
|
|
23
|
+
export function register(name: string, entry: Registered): void;
|
|
24
|
+
/**
|
|
25
|
+
* The registered layout of a name, undefined when there is none.
|
|
26
|
+
*
|
|
27
|
+
* @param {string} name
|
|
28
|
+
* @returns {Layout | undefined}
|
|
29
|
+
*/
|
|
30
|
+
export function find_layout(name: string): Layout | undefined;
|
|
31
|
+
/**
|
|
32
|
+
* The registered layout of a name (doc/spec-data-api.md §6.5).
|
|
33
|
+
*
|
|
34
|
+
* @param {string} name
|
|
35
|
+
* @returns {Layout}
|
|
36
|
+
* @throws {Error} When no layout of that name is registered.
|
|
37
|
+
*/
|
|
38
|
+
export function get_layout(name: string): Layout;
|
|
39
|
+
export type Registered = {
|
|
40
|
+
/**
|
|
41
|
+
* - The canonical text of the structure, to tell the same layout from another one.
|
|
42
|
+
*/
|
|
43
|
+
key: string;
|
|
44
|
+
layout: Layout;
|
|
45
|
+
};
|
|
46
|
+
import type { Layout } from "./typedefs.js";
|
|
47
|
+
import type { Compiled_Layout } from "./internal_types.js";
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Whether a tag name would shadow a member of a data block.
|
|
3
|
+
*
|
|
4
|
+
* @param {string} name
|
|
5
|
+
* @returns {boolean}
|
|
6
|
+
*/
|
|
7
|
+
export function is_reserved_name(name: string): boolean;
|
|
8
|
+
/** Event names of the library; a user does not emit them or use them for its own events. */
|
|
9
|
+
export const RESERVED_EVENTS: readonly string[];
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Expands a list of items (resolving `includes` and `coupling`, making offsets
|
|
3
|
+
* absolute) into the given structure. Internal. It changes the items it is given.
|
|
4
|
+
*
|
|
5
|
+
* @param {{name: string}} data_struct - The structure to fill in; only the name is given.
|
|
6
|
+
* @param {Layout_Item[]} items
|
|
7
|
+
* @returns {Data_Struct} The same object, now complete.
|
|
8
|
+
*/
|
|
9
|
+
export function build_structure(data_struct: {
|
|
10
|
+
name: string;
|
|
11
|
+
}, items: Layout_Item[]): Data_Struct;
|
|
12
|
+
/**
|
|
13
|
+
* Validates a structure built by build_structure against the layout rules
|
|
14
|
+
* (doc/spec.md §3, doc/design.md §3.1). Internal.
|
|
15
|
+
*
|
|
16
|
+
* @param {Data_Struct} data_struct
|
|
17
|
+
* @returns {string[]} descriptions of all violations, empty when the layout is valid
|
|
18
|
+
*/
|
|
19
|
+
export function validate_structure(data_struct: Data_Struct): string[];
|
|
20
|
+
/**
|
|
21
|
+
* Bit length of each tag type (lower case names).
|
|
22
|
+
*
|
|
23
|
+
* @type {Record<string, number>}
|
|
24
|
+
*/
|
|
25
|
+
export const TYPE_BITS: Record<string, number>;
|
|
26
|
+
import type { Layout_Item } from "./typedefs.js";
|
|
27
|
+
import type { Data_Struct } from "./internal_types.js";
|