colbin 0.0.0-stage → 0.8.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/LICENSE +21 -0
- package/README.md +206 -2
- package/dist/asset.d.ts +11 -0
- package/dist/asset.d.ts.map +1 -0
- package/dist/asset.js +23 -0
- package/dist/asset.js.map +1 -0
- package/dist/colbin.inspect.wasm +0 -0
- package/dist/colbin.wasm +0 -0
- package/dist/core.d.ts +199 -0
- package/dist/core.d.ts.map +1 -0
- package/dist/core.js +360 -0
- package/dist/core.js.map +1 -0
- package/dist/errors.d.ts +33 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +32 -0
- package/dist/errors.js.map +1 -0
- package/dist/generated/wasm-inline.d.ts +2 -0
- package/dist/generated/wasm-inline.d.ts.map +1 -0
- package/dist/generated/wasm-inline.js +7 -0
- package/dist/generated/wasm-inline.js.map +1 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +43 -0
- package/dist/index.js.map +1 -0
- package/dist/inspect.d.ts +11 -0
- package/dist/inspect.d.ts.map +1 -0
- package/dist/inspect.js +29 -0
- package/dist/inspect.js.map +1 -0
- package/dist/materialize.d.ts +66 -0
- package/dist/materialize.d.ts.map +1 -0
- package/dist/materialize.js +342 -0
- package/dist/materialize.js.map +1 -0
- package/dist/node.d.ts +10 -0
- package/dist/node.d.ts.map +1 -0
- package/dist/node.js +24 -0
- package/dist/node.js.map +1 -0
- package/dist/shared.d.ts +5 -0
- package/dist/shared.d.ts.map +1 -0
- package/dist/shared.js +5 -0
- package/dist/shared.js.map +1 -0
- package/package.json +54 -4
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Ivan Angulo Reyna
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,207 @@
|
|
|
1
|
-
#
|
|
1
|
+
# colbin
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
A columnar binary format for the JSON a backend actually sends: lists of
|
|
4
|
+
records, all the same shape. The field names travel once, as a schema, instead
|
|
5
|
+
of once per record; the values travel as columns, bit-packed.
|
|
6
|
+
|
|
7
|
+
This package is the browser and Node client — a WebAssembly module compiled
|
|
8
|
+
from the Rust implementation, and a small wrapper that turns its output into
|
|
9
|
+
JavaScript objects **without JSON text in the middle**.
|
|
10
|
+
|
|
11
|
+
```
|
|
12
|
+
npm install colbin
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Quickstart
|
|
16
|
+
|
|
17
|
+
```js
|
|
18
|
+
import { Codec } from 'colbin'
|
|
19
|
+
|
|
20
|
+
const codec = await Codec.open() // compiles the module, once
|
|
21
|
+
|
|
22
|
+
const response = await fetch('/api/products')
|
|
23
|
+
const rows = codec.unmarshal(new Uint8Array(await response.arrayBuffer()))
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
`Codec.open()` is async because compiling WebAssembly is. Everything after it
|
|
27
|
+
is synchronous: `unmarshal`, `marshal`, `columns` and the rest are straight
|
|
28
|
+
runs of wasm calls with no `await` in them.
|
|
29
|
+
|
|
30
|
+
## The schema travels out of band
|
|
31
|
+
|
|
32
|
+
The delivery the format is built for sends the schema **once per connection**
|
|
33
|
+
and every message after it carries only its body:
|
|
34
|
+
|
|
35
|
+
```js
|
|
36
|
+
const codec = await Codec.open()
|
|
37
|
+
codec.setSchema(section) // sent once, by whatever channel
|
|
38
|
+
|
|
39
|
+
const rows = codec.unmarshal(message) // every message after it
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
A message can also carry its own schema, for a file or a one-off response —
|
|
43
|
+
that is what `marshal`'s `standalone` is, and `unmarshal` reads it with no
|
|
44
|
+
`setSchema` call at all.
|
|
45
|
+
|
|
46
|
+
## Writing
|
|
47
|
+
|
|
48
|
+
```js
|
|
49
|
+
const { message, section, standalone, warnings } = codec.marshal(rows)
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
`marshal` takes a value or JSON text. A string is handed to the encoder as it
|
|
53
|
+
stands, which is the only way to carry an integer past 2^53 in: by the time it
|
|
54
|
+
is a JavaScript `Number`, it has already been rounded.
|
|
55
|
+
|
|
56
|
+
`standalone` is the same document with its section in front of it. It is
|
|
57
|
+
composed on first read, not encoded a second time.
|
|
58
|
+
|
|
59
|
+
Pass `{ verify: true }` to decode the message back and walk it against the
|
|
60
|
+
input before it is returned. It costs about 65% on top of the encode and what
|
|
61
|
+
it catches is a codec bug rather than a caller's mistake — worth having in a
|
|
62
|
+
test suite, and in the first deployment of anything whose shapes are new.
|
|
63
|
+
|
|
64
|
+
## The API
|
|
65
|
+
|
|
66
|
+
| | |
|
|
67
|
+
|---|---|
|
|
68
|
+
| `Codec.open(opts?)` | compile + instantiate. `opts.module` takes a pre-compiled `WebAssembly.Module`, `opts.wasm` takes bytes, a `Response`, or a URL |
|
|
69
|
+
| `Codec.fromModule(module)` | a second handle over a module compiled already — an instance, no compile |
|
|
70
|
+
| `Codec.preload()` | start the compile without waiting for it |
|
|
71
|
+
| `codec.unmarshal(bytes, opts?)` | **the headline** — objects, no JSON text when the shape allows it |
|
|
72
|
+
| `codec.columns(bytes, opts?)` | the columns themselves, for a grid or a chart that never wants row objects. `null` when the message is not that shape |
|
|
73
|
+
| `codec.toJSONText(bytes, opts?)` | the text path, for every shape |
|
|
74
|
+
| `codec.marshal(value \| jsonText, opts?)` | `{ message, section, standalone, warnings }` |
|
|
75
|
+
| `codec.setSchema(section \| null)` | hold a section for the messages that follow; `null` clears it |
|
|
76
|
+
| `codec.inspect(bytes, opts?)` | the field tree, with a byte span on every node. Needs `colbin/inspect` — see below |
|
|
77
|
+
| `codec.lastPath` | `'materialize'` or `'json'` — which path the last `unmarshal` took |
|
|
78
|
+
| `codec.canInspect` | whether this handle's module has the span walk in it |
|
|
79
|
+
| `unmarshal` / `columns` / `toJSONText` / `marshal` / `inspect` | the same, without holding a handle, each `await`ed |
|
|
80
|
+
| `ColbinError` | `code`, `offset`, `line`, `path`, `message`, `warnings` |
|
|
81
|
+
|
|
82
|
+
Every call that can fail throws a `ColbinError` carrying the module's whole
|
|
83
|
+
diagnostic — the byte offset, the line for a failure in JSON text, and the path
|
|
84
|
+
through the document. A *successful* `marshal` can still have something to say
|
|
85
|
+
(an always-null column, a null where an object belongs), so warnings ride on
|
|
86
|
+
the result rather than being thrown.
|
|
87
|
+
|
|
88
|
+
## Two paths, and which one you got
|
|
89
|
+
|
|
90
|
+
When the message is a table — a list of records, which is the shape this format
|
|
91
|
+
is for — `unmarshal` never writes JSON text. The module hands over columns in a
|
|
92
|
+
flat typed buffer and the objects are built in JavaScript from a generated,
|
|
93
|
+
monomorphic row builder cached per schema.
|
|
94
|
+
|
|
95
|
+
Anything else (a nested document, a heterogeneous list, a bare object) falls
|
|
96
|
+
back to the JSON-text path automatically. `codec.lastPath` says which ran, so a
|
|
97
|
+
caller can find out they are on the slower one without guessing.
|
|
98
|
+
|
|
99
|
+
The fast path is also the one that is **exact past 2^53**: a column whose values
|
|
100
|
+
do not fit a `Number` comes back as `bigint`, per column, using range
|
|
101
|
+
information the column header already carries. The JSON fallback goes through
|
|
102
|
+
`JSON.parse` and rounds like any other JSON reader would.
|
|
103
|
+
|
|
104
|
+
Under a Content-Security-Policy without `unsafe-eval`, the generated row builder
|
|
105
|
+
cannot be compiled. The package detects that once and falls back to a generic
|
|
106
|
+
builder, which costs about ten times as much as the generated one and is still
|
|
107
|
+
two orders of magnitude below the decode.
|
|
108
|
+
|
|
109
|
+
## Numbers
|
|
110
|
+
|
|
111
|
+
1000 product records, seven fields. Node 24 / V8, best of twelve runs, no
|
|
112
|
+
network. `bun run bench` in this directory reproduces it.
|
|
113
|
+
|
|
114
|
+
| | wire | gzipped |
|
|
115
|
+
|---|---:|---:|
|
|
116
|
+
| minified JSON | 106 670 B | 12 124 B |
|
|
117
|
+
| colbin — 30 411 B of message, 64 B of section | **30 475 B** | **3 250 B** |
|
|
118
|
+
|
|
119
|
+
The section is the 64 bytes, and it is sent once per connection rather than
|
|
120
|
+
once per message.
|
|
121
|
+
|
|
122
|
+
| | |
|
|
123
|
+
|---|---:|
|
|
124
|
+
| `codec.unmarshal` — objects in hand, no JSON text | **0.14 ms** |
|
|
125
|
+
| `JSON.parse` of the same document, as a reference point | 0.26 ms |
|
|
126
|
+
| `codec.toJSONText` | 0.20 ms |
|
|
127
|
+
| `JSON.stringify` of the same document | 0.15 ms |
|
|
128
|
+
| `codec.marshal` — parse, infer, build | 1.15 ms |
|
|
129
|
+
| `codec.marshal` with `{ verify: true }` | 1.88 ms |
|
|
130
|
+
|
|
131
|
+
The reference rows are there to calibrate the others, not as a bar the design
|
|
132
|
+
had to clear. What the project optimises for is backend CPU, backend RAM and
|
|
133
|
+
transfer size; client CPU is budget to spend in service of those.
|
|
134
|
+
|
|
135
|
+
## Entry points
|
|
136
|
+
|
|
137
|
+
| | |
|
|
138
|
+
|---|---|
|
|
139
|
+
| `colbin` | the module inline as base64. No bundler configuration, no runtime 404 mode |
|
|
140
|
+
| `colbin` on Node | the `node` condition: reads `colbin.wasm` from beside the JavaScript |
|
|
141
|
+
| `colbin/asset` | `new URL('./colbin.wasm', import.meta.url)` — Vite, webpack 5, Rollup and Parcel all emit it as an asset, and it works unbundled in a browser too |
|
|
142
|
+
| `colbin/inspect` | the same, over the **other module**: the one built with `inspect`. See below |
|
|
143
|
+
| `colbin/colbin.wasm` | the module file itself, for a build step that wants to place it |
|
|
144
|
+
|
|
145
|
+
Measured, on the modules this version ships:
|
|
146
|
+
|
|
147
|
+
| | raw | gzipped |
|
|
148
|
+
|---|---:|---:|
|
|
149
|
+
| `colbin.wasm` — what `colbin/asset` serves | 209 109 B | **84 195 B** |
|
|
150
|
+
| the same module as inline base64 | 279 124 B | **114 271 B** |
|
|
151
|
+
| `colbin.inspect.wasm` — what `colbin/inspect` serves | 224 199 B | 90 127 B |
|
|
152
|
+
| the wrapper's own JavaScript, all entries | 36 085 B | 10 651 B |
|
|
153
|
+
|
|
154
|
+
Inline costs **36% more over the wire** than the asset, gzipped. Base64 breaks
|
|
155
|
+
the byte alignment gzip's matcher works on, so gzip recovers much less of the
|
|
156
|
+
33% expansion than the raw ratio suggests. Inline is still the default because
|
|
157
|
+
it needs no configuration and cannot 404; a page that cares about the transfer
|
|
158
|
+
should import `colbin/asset`, or hand `Codec.open` its own source:
|
|
159
|
+
|
|
160
|
+
```js
|
|
161
|
+
const codec = await Codec.open({ wasm: fetch('/colbin.wasm') })
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
### `inspect` is a separate module
|
|
165
|
+
|
|
166
|
+
`codec.inspect()` — the field tree with a byte span on every node — is the one
|
|
167
|
+
thing here that only a tool wants: something that *draws* the bytes rather than
|
|
168
|
+
reads them. It is 15 KB of module, and it used to be in the module everybody
|
|
169
|
+
downloaded.
|
|
170
|
+
|
|
171
|
+
So it is not. `colbin` and `colbin/asset` carry the build without it, and
|
|
172
|
+
`colbin/inspect` carries the build with it:
|
|
173
|
+
|
|
174
|
+
```js
|
|
175
|
+
import { Codec } from 'colbin/inspect'
|
|
176
|
+
|
|
177
|
+
const codec = await Codec.open()
|
|
178
|
+
const report = codec.inspect(message, { section }) // fields, with byte spans
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
`codec.canInspect` says which build a handle is over, and calling `inspect()`
|
|
182
|
+
on one that cannot throws an error naming the entry that can, rather than
|
|
183
|
+
failing as `inspect_message is not a function` several frames away.
|
|
184
|
+
|
|
185
|
+
Both modules go through `wasm-opt -O3`, which is worth 12% of the raw bytes and
|
|
186
|
+
4% gzipped over what `cargo` emits, and costs nothing measurable in throughput.
|
|
187
|
+
|
|
188
|
+
## Version pinning
|
|
189
|
+
|
|
190
|
+
> colbin 0.x makes no wire-compatibility promise across minor versions. A Go
|
|
191
|
+
> service on 0.3 and a browser on 0.2 will not interoperate, and the failure
|
|
192
|
+
> will look like corrupt data rather than a version error. Pin both.
|
|
193
|
+
|
|
194
|
+
One tag drives all three implementations: `v0.1.0` publishes `colbin@0.1.0`, and
|
|
195
|
+
is the Go module tag and the Rust crate version. Compatibility while on `0.x` is
|
|
196
|
+
by matching **minor** version.
|
|
197
|
+
|
|
198
|
+
## What this does not do
|
|
199
|
+
|
|
200
|
+
No streaming — the ABI is bytes in, bytes out, and allocates the whole input.
|
|
201
|
+
No worker wrapper: decoding off the main thread is your choice, and shipping one
|
|
202
|
+
would mean owning a message protocol. No types generated from the schema. The
|
|
203
|
+
column fast path covers tables; deeply nested or heterogeneous documents go
|
|
204
|
+
through the JSON-text path, which is correct but slower.
|
|
205
|
+
|
|
206
|
+
MIT. Source, format notes and the Go and Rust implementations:
|
|
207
|
+
<https://github.com/ivanjoz/colbin>.
|
package/dist/asset.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Codec as CodecClass } from './core.ts';
|
|
2
|
+
export * from './shared.ts';
|
|
3
|
+
/** Where the module is, as the bundler resolved it. Exported so a caller can
|
|
4
|
+
* prefetch it, or hand it to a service worker to cache. */
|
|
5
|
+
export declare const wasmURL: URL;
|
|
6
|
+
/** The handle. See `colbin`'s README for the shape. */
|
|
7
|
+
export declare const Codec: import("./core.ts").CodecEntry;
|
|
8
|
+
/** The same name as a type, for `let codec: Codec`. */
|
|
9
|
+
export type Codec = CodecClass;
|
|
10
|
+
export declare const unmarshal: (message: Uint8Array, options?: import("./core.ts").UnmarshalOptions) => Promise<unknown>, columns: (message: Uint8Array, options?: import("./core.ts").DecodeOptions) => Promise<import("./materialize.ts").ColumnTable | null>, toJSONText: (message: Uint8Array, options?: import("./core.ts").DecodeOptions) => Promise<string>, marshal: (value: unknown, options?: import("./core.ts").MarshalOptions) => Promise<import("./core.ts").Marshaled>, inspect: (message: Uint8Array, options?: import("./core.ts").DecodeOptions) => Promise<import("./core.ts").Report>;
|
|
11
|
+
//# sourceMappingURL=asset.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"asset.d.ts","sourceRoot":"","sources":["../src/asset.ts"],"names":[],"mappings":"AAYA,OAAO,EAAyB,KAAK,IAAI,UAAU,EAAmB,MAAM,WAAW,CAAA;AAEvF,cAAc,aAAa,CAAA;AAE3B;2DAC2D;AAC3D,eAAO,MAAM,OAAO,KAA4C,CAAA;AAMhE,uDAAuD;AACvD,eAAO,MAAM,KAAK,gCAAoB,CAAA;AAEtC,uDAAuD;AACvD,MAAM,MAAM,KAAK,GAAG,UAAU,CAAA;AAE9B,eAAO,MAAQ,SAAS,6FAAE,OAAO,gIAAE,UAAU,yFAAE,OAAO,4GAAE,OAAO,2GAAuB,CAAA"}
|
package/dist/asset.js
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
// `colbin/asset` — the module as a file the bundler emits, not as base64.
|
|
2
|
+
//
|
|
3
|
+
// `new URL('./colbin.wasm', import.meta.url)` is the one spelling Vite,
|
|
4
|
+
// webpack 5, Rollup and Parcel all understand natively: each of them rewrites
|
|
5
|
+
// it to the hashed asset it emitted, and none of them needs a plugin or a
|
|
6
|
+
// loader rule to do it. Unbundled in a browser it is simply a relative URL, so
|
|
7
|
+
// the same file works from a plain `<script type="module">`.
|
|
8
|
+
//
|
|
9
|
+
// The cost against the default entry is a second request; the saving is that
|
|
10
|
+
// the module is not parsed as JavaScript and is cached by the browser as the
|
|
11
|
+
// `application/wasm` it is, which is what lets `compileStreaming` run.
|
|
12
|
+
import { codecFor, convenience, Codec as CodecClass } from "./core.js";
|
|
13
|
+
export * from "./shared.js";
|
|
14
|
+
/** Where the module is, as the bundler resolved it. Exported so a caller can
|
|
15
|
+
* prefetch it, or hand it to a service worker to cache. */
|
|
16
|
+
export const wasmURL = new URL('./colbin.wasm', import.meta.url);
|
|
17
|
+
function fetched() {
|
|
18
|
+
return fetch(wasmURL);
|
|
19
|
+
}
|
|
20
|
+
/** The handle. See `colbin`'s README for the shape. */
|
|
21
|
+
export const Codec = codecFor(fetched);
|
|
22
|
+
export const { unmarshal, columns, toJSONText, marshal, inspect } = convenience(Codec);
|
|
23
|
+
//# sourceMappingURL=asset.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"asset.js","sourceRoot":"","sources":["../src/asset.ts"],"names":[],"mappings":"AAAA,0EAA0E;AAC1E,EAAE;AACF,wEAAwE;AACxE,8EAA8E;AAC9E,0EAA0E;AAC1E,+EAA+E;AAC/E,6DAA6D;AAC7D,EAAE;AACF,6EAA6E;AAC7E,6EAA6E;AAC7E,uEAAuE;AAEvE,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,KAAK,IAAI,UAAU,EAAmB,MAAM,WAAW,CAAA;AAEvF,cAAc,aAAa,CAAA;AAE3B;2DAC2D;AAC3D,MAAM,CAAC,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,eAAe,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;AAEhE,SAAS,OAAO;IACd,OAAO,KAAK,CAAC,OAAO,CAAC,CAAA;AACvB,CAAC;AAED,uDAAuD;AACvD,MAAM,CAAC,MAAM,KAAK,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAA;AAKtC,MAAM,CAAC,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,WAAW,CAAC,KAAK,CAAC,CAAA"}
|
|
Binary file
|
package/dist/colbin.wasm
ADDED
|
Binary file
|
package/dist/core.d.ts
ADDED
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
import { type ColumnTable, type ReadRowsOptions } from './materialize.ts';
|
|
2
|
+
/**
|
|
3
|
+
* Anything `Codec.open` can turn into a compiled module.
|
|
4
|
+
*
|
|
5
|
+
* A `Response` (or a promise of one, which is what `fetch(...)` is before it is
|
|
6
|
+
* awaited) takes the streaming path; bytes are compiled directly; a `URL` or a
|
|
7
|
+
* URL string is fetched first.
|
|
8
|
+
*/
|
|
9
|
+
export type WasmSource = WebAssembly.Module | BufferSource | Response | URL | string | Promise<WebAssembly.Module | BufferSource | Response>;
|
|
10
|
+
export type OpenOptions = {
|
|
11
|
+
/** A module compiled already — by a service worker, a bundler plugin, or a
|
|
12
|
+
* previous `Codec.open()`. Skips every fetch and every compile. */
|
|
13
|
+
module?: WebAssembly.Module;
|
|
14
|
+
/** Where to get the module from, when it is not the entry's own default. */
|
|
15
|
+
wasm?: WasmSource;
|
|
16
|
+
};
|
|
17
|
+
/** One node of the field tree: a field, a table's column, or a list's element. */
|
|
18
|
+
export type Field = {
|
|
19
|
+
name: string;
|
|
20
|
+
key: number;
|
|
21
|
+
/** The wire shape — `int64`, `string`, `[]struct`, `float64 column`. */
|
|
22
|
+
type: string;
|
|
23
|
+
/** A pointer field: the format's "absent, rather than zero". */
|
|
24
|
+
optional: boolean;
|
|
25
|
+
/** Absolute offsets into the message, so a hex view needs no arithmetic. */
|
|
26
|
+
start: number;
|
|
27
|
+
end: number;
|
|
28
|
+
bytes: number;
|
|
29
|
+
children: Field[];
|
|
30
|
+
};
|
|
31
|
+
/** What `codec.inspect` returns: the message, described. */
|
|
32
|
+
export type Report = {
|
|
33
|
+
totalBytes: number;
|
|
34
|
+
/** The schema section, when the message carries one. Zero out of band. */
|
|
35
|
+
schemaBytes: number;
|
|
36
|
+
bodyBytes: number;
|
|
37
|
+
rootBytes: number;
|
|
38
|
+
/** Whether the run uses eight-bit keys, which costs a byte per present field. */
|
|
39
|
+
wide: boolean;
|
|
40
|
+
/** The row count of the root's list or table, or 1 for a lone record. */
|
|
41
|
+
rows: number;
|
|
42
|
+
/** Whether the document was wrapped, because its top level was not an object. */
|
|
43
|
+
envelope: boolean;
|
|
44
|
+
fields: Field[];
|
|
45
|
+
};
|
|
46
|
+
/** A message and the schema section that describes it. */
|
|
47
|
+
export type Marshaled = {
|
|
48
|
+
/** The body. Carries no schema: send `section` once per connection. */
|
|
49
|
+
message: Uint8Array;
|
|
50
|
+
/** The schema for `message`, for the out-of-band delivery. */
|
|
51
|
+
section: Uint8Array;
|
|
52
|
+
/** The same document with its section in front of it — what a file with
|
|
53
|
+
* nowhere else to put a schema needs. Composed on first read rather than
|
|
54
|
+
* encoded a second time. */
|
|
55
|
+
readonly standalone: Uint8Array;
|
|
56
|
+
/** A successful encode can still have something to say: an always-null
|
|
57
|
+
* column, a null where an object belongs. */
|
|
58
|
+
warnings: string[];
|
|
59
|
+
};
|
|
60
|
+
export type MarshalOptions = {
|
|
61
|
+
/**
|
|
62
|
+
* Decode the message that was just built and walk it against the input
|
|
63
|
+
* before handing it back, failing rather than returning bytes that do not
|
|
64
|
+
* read back. Off by default: it costs about 70% on top of the encode, and
|
|
65
|
+
* what it catches is a codec bug rather than a
|
|
66
|
+
* caller's mistake. Worth turning on in a test suite, and in the first
|
|
67
|
+
* deployment of anything whose shapes are new.
|
|
68
|
+
*/
|
|
69
|
+
verify?: boolean;
|
|
70
|
+
};
|
|
71
|
+
export type UnmarshalOptions = ReadRowsOptions & {
|
|
72
|
+
/** The schema for this message alone, in place of the held one. Does not
|
|
73
|
+
* replace what {@link Codec.setSchema} holds. */
|
|
74
|
+
section?: Uint8Array;
|
|
75
|
+
};
|
|
76
|
+
export type DecodeOptions = {
|
|
77
|
+
/** The schema for this message alone, in place of the held one. */
|
|
78
|
+
section?: Uint8Array;
|
|
79
|
+
};
|
|
80
|
+
/** Which path a call took. `materialize` never writes JSON text; `json` is the
|
|
81
|
+
* fallback for anything that is not the table shape INTERNALS.md §16.3 covers. */
|
|
82
|
+
export type Path = 'materialize' | 'json';
|
|
83
|
+
/**
|
|
84
|
+
* The handle. One WebAssembly instance, the schema it holds, and the module's
|
|
85
|
+
* whole surface.
|
|
86
|
+
*
|
|
87
|
+
* Construct it with `Codec.open()` from whichever entry point suits — `colbin`
|
|
88
|
+
* carries the module inline, `colbin/asset` resolves it as a URL beside
|
|
89
|
+
* itself.
|
|
90
|
+
*/
|
|
91
|
+
export declare class Codec {
|
|
92
|
+
#private;
|
|
93
|
+
private constructor();
|
|
94
|
+
/**
|
|
95
|
+
* Compiles the module and instantiates it. Async because compiling
|
|
96
|
+
* WebAssembly is; nothing after it is.
|
|
97
|
+
*/
|
|
98
|
+
static open(options?: OpenOptions): Promise<Codec>;
|
|
99
|
+
/** A second handle over an already-compiled module — its own instance, its
|
|
100
|
+
* own schema, no compile. */
|
|
101
|
+
static fromModule(module: WebAssembly.Module): Codec;
|
|
102
|
+
/**
|
|
103
|
+
* Holds a schema section for the messages that follow — the delivery the
|
|
104
|
+
* format recommends, where the section is sent once per connection and every
|
|
105
|
+
* message after it carries only its body. `null` clears it.
|
|
106
|
+
*
|
|
107
|
+
* A self-describing message ignores this and uses its own.
|
|
108
|
+
*/
|
|
109
|
+
setSchema(section: Uint8Array | null): void;
|
|
110
|
+
/** Which path the last {@link unmarshal} took: a caller that wants to know
|
|
111
|
+
* it landed on the slow one should not have to guess. */
|
|
112
|
+
get lastPath(): Path;
|
|
113
|
+
/**
|
|
114
|
+
* A message to real objects, without JSON text in the middle when the shape
|
|
115
|
+
* allows it.
|
|
116
|
+
*
|
|
117
|
+
* The fast path is the one that is exact past 2^53: a column whose values do
|
|
118
|
+
* not fit a `Number` comes back as `bigint`, where the JSON fallback goes
|
|
119
|
+
* through `JSON.parse` and rounds like any other JSON reader would.
|
|
120
|
+
* {@link lastPath} says which ran.
|
|
121
|
+
*/
|
|
122
|
+
unmarshal(message: Uint8Array, options?: UnmarshalOptions): unknown;
|
|
123
|
+
/**
|
|
124
|
+
* The columns themselves, for a caller feeding a grid or a chart that never
|
|
125
|
+
* wants row objects — it skips even the 7 µs the row build costs.
|
|
126
|
+
*
|
|
127
|
+
* Returns `null` when the message is not the table shape the fast path covers, since
|
|
128
|
+
* there is no honest column view of a nested document; such a caller should
|
|
129
|
+
* fall back to {@link unmarshal}.
|
|
130
|
+
*/
|
|
131
|
+
columns(message: Uint8Array, options?: DecodeOptions): ColumnTable | null;
|
|
132
|
+
/** A message back to JSON text. Every shape, and the only path for the ones
|
|
133
|
+
* {@link unmarshal} reports as `json`. */
|
|
134
|
+
toJSONText(message: Uint8Array, options?: DecodeOptions): string;
|
|
135
|
+
/**
|
|
136
|
+
* A value or JSON text to a colbin message.
|
|
137
|
+
*
|
|
138
|
+
* A string is taken as JSON text and handed to the module as it stands;
|
|
139
|
+
* anything else goes through `JSON.stringify` first — which means an integer
|
|
140
|
+
* past 2^53 must arrive as text, since by the time it is a JavaScript
|
|
141
|
+
* `Number` it has already been rounded.
|
|
142
|
+
*/
|
|
143
|
+
marshal(value: unknown, options?: MarshalOptions): Marshaled;
|
|
144
|
+
/**
|
|
145
|
+
* The field tree of a message, with every node's byte span — absolute
|
|
146
|
+
* offsets into the bytes handed in, so a hex view needs no arithmetic.
|
|
147
|
+
*
|
|
148
|
+
* Needs a module built with the `inspect` feature, which is **not** the one
|
|
149
|
+
* `colbin` and `colbin/asset` carry: the span walk is 15 KB that nothing but
|
|
150
|
+
* a tool drawing the bytes ever calls, so it has a module of its own behind
|
|
151
|
+
* `colbin/inspect`.
|
|
152
|
+
*/
|
|
153
|
+
inspect(message: Uint8Array, options?: DecodeOptions): Report;
|
|
154
|
+
/** Whether this handle's module can {@link inspect} — i.e. whether it came
|
|
155
|
+
* from `colbin/inspect` or another build with the feature on. */
|
|
156
|
+
get canInspect(): boolean;
|
|
157
|
+
/** Whether this handle's module carries the fast path. True of every build
|
|
158
|
+
* this package ships; false only for a module a caller supplied. */
|
|
159
|
+
get canMaterialize(): boolean;
|
|
160
|
+
/** The flag the encoder needs to write a document that carries its own
|
|
161
|
+
* schema, for a caller composing `encode` flags directly. */
|
|
162
|
+
static get SELF_DESCRIBING(): number;
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* The `Codec` an entry point exports: `open()` with the entry's own way of
|
|
166
|
+
* finding the module already wired in, overridable per call.
|
|
167
|
+
*
|
|
168
|
+
* Compiled once per entry and cached, so a page that opens a second handle
|
|
169
|
+
* pays for an instance and not for a compile.
|
|
170
|
+
*/
|
|
171
|
+
export declare function codecFor(source: () => WasmSource): CodecEntry;
|
|
172
|
+
export type CodecEntry = {
|
|
173
|
+
/** Compile (once per entry) and instantiate. */
|
|
174
|
+
open(options?: OpenOptions): Promise<Codec>;
|
|
175
|
+
/** A handle over a module compiled already — no fetch, no compile. */
|
|
176
|
+
fromModule(module: WebAssembly.Module): Codec;
|
|
177
|
+
/** Start the compile without waiting for it, so the first real call is not
|
|
178
|
+
* the one that pays for it. Failures are deliberately swallowed — `open`
|
|
179
|
+
* will surface the same one. */
|
|
180
|
+
preload(): void;
|
|
181
|
+
};
|
|
182
|
+
/**
|
|
183
|
+
* The free functions each entry re-exports — `unmarshal(bytes)` without
|
|
184
|
+
* holding a handle, for the caller who has one message to read and no
|
|
185
|
+
* connection to hold a schema for.
|
|
186
|
+
*
|
|
187
|
+
* They share one lazily-opened codec rather than opening a fresh one per call:
|
|
188
|
+
* a fresh instance per message is what the handle exists to avoid, and none of these
|
|
189
|
+
* hold a schema across calls, so there is nothing for the sharing to leak.
|
|
190
|
+
*/
|
|
191
|
+
export declare function convenience(entry: CodecEntry): Convenience;
|
|
192
|
+
export type Convenience = {
|
|
193
|
+
unmarshal(message: Uint8Array, options?: UnmarshalOptions): Promise<unknown>;
|
|
194
|
+
columns(message: Uint8Array, options?: DecodeOptions): Promise<ColumnTable | null>;
|
|
195
|
+
toJSONText(message: Uint8Array, options?: DecodeOptions): Promise<string>;
|
|
196
|
+
marshal(value: unknown, options?: MarshalOptions): Promise<Marshaled>;
|
|
197
|
+
inspect(message: Uint8Array, options?: DecodeOptions): Promise<Report>;
|
|
198
|
+
};
|
|
199
|
+
//# sourceMappingURL=core.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"core.d.ts","sourceRoot":"","sources":["../src/core.ts"],"names":[],"mappings":"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"}
|