zuzu-js 0.1.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 +5 -0
- package/README.md +113 -0
- package/bin/zuzu +17 -0
- package/bin/zuzu-build-browser-bundle +57 -0
- package/bin/zuzu-generate-browser-stdlib +584 -0
- package/bin/zuzu-js +23 -0
- package/bin/zuzu-js-compile +152 -0
- package/bin/zuzu-js-electron +19 -0
- package/dist/zuzu-browser-worker.js +45574 -0
- package/dist/zuzu-browser.js +45362 -0
- package/lib/browser-bundle-entry.js +160 -0
- package/lib/browser-gui-renderer.js +387 -0
- package/lib/browser-runtime.js +167 -0
- package/lib/browser-worker-entry.js +413 -0
- package/lib/browser-ztests/runner.html +103 -0
- package/lib/browser-ztests/runner.js +369 -0
- package/lib/cli.js +350 -0
- package/lib/collections.js +367 -0
- package/lib/compiler.js +303 -0
- package/lib/electron/launcher.js +70 -0
- package/lib/electron/main.js +956 -0
- package/lib/electron/preload.js +80 -0
- package/lib/electron/renderer.html +122 -0
- package/lib/electron/renderer.js +24 -0
- package/lib/execution-metadata.js +18 -0
- package/lib/gui/dom-renderer.js +778 -0
- package/lib/host/browser-host.js +278 -0
- package/lib/host/capabilities.js +47 -0
- package/lib/host/electron-host.js +15 -0
- package/lib/host/node-host.js +74 -0
- package/lib/paths.js +150 -0
- package/lib/runtime-entrypoints.js +60 -0
- package/lib/runtime-helpers.js +886 -0
- package/lib/runtime.js +3529 -0
- package/lib/tap.js +37 -0
- package/lib/transpiler-new/ast.js +23 -0
- package/lib/transpiler-new/codegen.js +2455 -0
- package/lib/transpiler-new/errors.js +28 -0
- package/lib/transpiler-new/index.js +26 -0
- package/lib/transpiler-new/lexer.js +834 -0
- package/lib/transpiler-new/parser.js +2332 -0
- package/lib/transpiler-new/validate-bindings.js +326 -0
- package/lib/transpiler-utils.js +95 -0
- package/lib/transpiler.js +33 -0
- package/lib/zuzu.js +53 -0
- package/modules/javascript.js +193 -0
- package/modules/std/archive.js +603 -0
- package/modules/std/clib.js +338 -0
- package/modules/std/data/csv.js +1331 -0
- package/modules/std/data/json.js +531 -0
- package/modules/std/data/xml.js +441 -0
- package/modules/std/data/yaml.js +256 -0
- package/modules/std/db-worker.js +250 -0
- package/modules/std/db.js +664 -0
- package/modules/std/digest/_hash.js +443 -0
- package/modules/std/digest/md5.js +26 -0
- package/modules/std/digest/sha.js +72 -0
- package/modules/std/eval.js +10 -0
- package/modules/std/gui/objects.js +1519 -0
- package/modules/std/internals.js +571 -0
- package/modules/std/io/socks-worker.js +318 -0
- package/modules/std/io/socks.js +186 -0
- package/modules/std/io.js +475 -0
- package/modules/std/marshal/cbor.js +463 -0
- package/modules/std/marshal/graph.js +1624 -0
- package/modules/std/marshal.js +87 -0
- package/modules/std/math/bignum.js +91 -0
- package/modules/std/math.js +79 -0
- package/modules/std/net/dns.js +306 -0
- package/modules/std/net/http.js +820 -0
- package/modules/std/net/smtp.js +943 -0
- package/modules/std/net/url.js +109 -0
- package/modules/std/proc.js +602 -0
- package/modules/std/secure.js +3724 -0
- package/modules/std/string/base64.js +138 -0
- package/modules/std/string.js +299 -0
- package/modules/std/task.js +914 -0
- package/modules/std/time.js +579 -0
- package/modules/std/tui.js +188 -0
- package/modules/std/worker-thread.js +246 -0
- package/modules/std/worker.js +790 -0
- package/package.json +67 -0
- package/stdlib/modules/javascript.zzm +99 -0
- package/stdlib/modules/perl.zzm +105 -0
- package/stdlib/modules/std/archive.zzm +132 -0
- package/stdlib/modules/std/cache/lru.zzm +174 -0
- package/stdlib/modules/std/clib.zzm +112 -0
- package/stdlib/modules/std/colour.zzm +220 -0
- package/stdlib/modules/std/config.zzm +818 -0
- package/stdlib/modules/std/data/cbor.zzm +497 -0
- package/stdlib/modules/std/data/csv.zzm +285 -0
- package/stdlib/modules/std/data/ini.zzm +472 -0
- package/stdlib/modules/std/data/json/schema/core.zzm +573 -0
- package/stdlib/modules/std/data/json/schema/format.zzm +581 -0
- package/stdlib/modules/std/data/json/schema/model.zzm +255 -0
- package/stdlib/modules/std/data/json/schema/output.zzm +272 -0
- package/stdlib/modules/std/data/json/schema/relative_pointer.zzm +299 -0
- package/stdlib/modules/std/data/json/schema/validation.zzm +1503 -0
- package/stdlib/modules/std/data/json/schema.zzm +306 -0
- package/stdlib/modules/std/data/json.zzm +102 -0
- package/stdlib/modules/std/data/kdl/json.zzm +460 -0
- package/stdlib/modules/std/data/kdl/xml.zzm +387 -0
- package/stdlib/modules/std/data/kdl.zzm +1631 -0
- package/stdlib/modules/std/data/toml.zzm +756 -0
- package/stdlib/modules/std/data/toon.zzm +1017 -0
- package/stdlib/modules/std/data/xml/escape.zzm +156 -0
- package/stdlib/modules/std/data/xml.zzm +276 -0
- package/stdlib/modules/std/data/yaml.zzm +94 -0
- package/stdlib/modules/std/db.zzm +173 -0
- package/stdlib/modules/std/defer.zzm +75 -0
- package/stdlib/modules/std/digest/crc32.zzm +196 -0
- package/stdlib/modules/std/digest/md5.zzm +54 -0
- package/stdlib/modules/std/digest/sha.zzm +83 -0
- package/stdlib/modules/std/dump.zzm +317 -0
- package/stdlib/modules/std/eval.zzm +63 -0
- package/stdlib/modules/std/getopt.zzm +432 -0
- package/stdlib/modules/std/gui/dialogue.zzm +592 -0
- package/stdlib/modules/std/gui/objects.zzm +123 -0
- package/stdlib/modules/std/gui.zzm +1914 -0
- package/stdlib/modules/std/internals.zzm +139 -0
- package/stdlib/modules/std/io/socks.zzm +139 -0
- package/stdlib/modules/std/io.zzm +157 -0
- package/stdlib/modules/std/lingua/en.zzm +347 -0
- package/stdlib/modules/std/log.zzm +169 -0
- package/stdlib/modules/std/mail.zzm +2726 -0
- package/stdlib/modules/std/marshal.zzm +138 -0
- package/stdlib/modules/std/math/bignum.zzm +98 -0
- package/stdlib/modules/std/math/range.zzm +116 -0
- package/stdlib/modules/std/math/roman.zzm +156 -0
- package/stdlib/modules/std/math.zzm +141 -0
- package/stdlib/modules/std/net/dns.zzm +93 -0
- package/stdlib/modules/std/net/http.zzm +278 -0
- package/stdlib/modules/std/net/smtp.zzm +257 -0
- package/stdlib/modules/std/net/url.zzm +69 -0
- package/stdlib/modules/std/path/jsonpointer.zzm +526 -0
- package/stdlib/modules/std/path/kdl.zzm +1003 -0
- package/stdlib/modules/std/path/simple.zzm +520 -0
- package/stdlib/modules/std/path/z/context.zzm +147 -0
- package/stdlib/modules/std/path/z/evaluate.zzm +549 -0
- package/stdlib/modules/std/path/z/functions.zzm +874 -0
- package/stdlib/modules/std/path/z/lexer.zzm +490 -0
- package/stdlib/modules/std/path/z/node.zzm +1455 -0
- package/stdlib/modules/std/path/z/operators.zzm +445 -0
- package/stdlib/modules/std/path/z/parser.zzm +359 -0
- package/stdlib/modules/std/path/z.zzm +403 -0
- package/stdlib/modules/std/path/zz/functions.zzm +828 -0
- package/stdlib/modules/std/path/zz/operators.zzm +1036 -0
- package/stdlib/modules/std/path/zz.zzm +100 -0
- package/stdlib/modules/std/proc.zzm +155 -0
- package/stdlib/modules/std/result.zzm +149 -0
- package/stdlib/modules/std/secure.zzm +606 -0
- package/stdlib/modules/std/string/base64.zzm +66 -0
- package/stdlib/modules/std/string/quoted_printable.zzm +485 -0
- package/stdlib/modules/std/string.zzm +179 -0
- package/stdlib/modules/std/task.zzm +221 -0
- package/stdlib/modules/std/template/z.zzm +531 -0
- package/stdlib/modules/std/template/zz.zzm +62 -0
- package/stdlib/modules/std/time.zzm +188 -0
- package/stdlib/modules/std/tui.zzm +89 -0
- package/stdlib/modules/std/uuid.zzm +223 -0
- package/stdlib/modules/std/web/session.zzm +388 -0
- package/stdlib/modules/std/web/static.zzm +329 -0
- package/stdlib/modules/std/web.zzm +1942 -0
- package/stdlib/modules/std/worker.zzm +202 -0
- package/stdlib/modules/std/zuzuzoo.zzm +3960 -0
- package/stdlib/modules/test/more.zzm +528 -0
- package/stdlib/modules/test/parser.zzm +209 -0
|
@@ -0,0 +1,497 @@
|
|
|
1
|
+
=encoding utf8
|
|
2
|
+
|
|
3
|
+
=head1 NAME
|
|
4
|
+
|
|
5
|
+
std/data/cbor - CBOR encoding and decoding for ZuzuScript.
|
|
6
|
+
|
|
7
|
+
=head1 SYNOPSIS
|
|
8
|
+
|
|
9
|
+
from std/data/cbor import CBOR, TaggedValue;
|
|
10
|
+
|
|
11
|
+
let codec := new CBOR();
|
|
12
|
+
let bytes := codec.encode({ answer: 42 });
|
|
13
|
+
let value := codec.decode(bytes);
|
|
14
|
+
|
|
15
|
+
// Decode CBOR maps to Zuzu PairLists instead of Dicts.
|
|
16
|
+
// This preserves key order and allows duplicate keys.
|
|
17
|
+
codec := new CBOR( pairlists: true );
|
|
18
|
+
|
|
19
|
+
=head1 IMPLEMENTATION SUPPORT
|
|
20
|
+
|
|
21
|
+
This module is supported by zuzu.pl, zuzu-rust, and zuzu-js on Node and
|
|
22
|
+
Electron. It is partially supported by zuzu-js in the browser: in-memory
|
|
23
|
+
CBOR encode/decode coverage passes, but file-backed load/dump coverage is
|
|
24
|
+
unsupported because browser filesystem capability is unavailable.
|
|
25
|
+
|
|
26
|
+
=head1 DESCRIPTION
|
|
27
|
+
|
|
28
|
+
Pure-Zuzu implementation of CBOR (RFC 8949).
|
|
29
|
+
|
|
30
|
+
=head1 EXPORTS
|
|
31
|
+
|
|
32
|
+
=head2 Classes
|
|
33
|
+
|
|
34
|
+
=over
|
|
35
|
+
|
|
36
|
+
=item C<< TaggedValue({ tag: Number, value: value }) >>
|
|
37
|
+
|
|
38
|
+
Constructs a tagged CBOR value. Returns: C<TaggedValue>. Stores the CBOR
|
|
39
|
+
tag number and associated value.
|
|
40
|
+
|
|
41
|
+
=item C<< CBOR({ pairlists?: Boolean }) >>
|
|
42
|
+
|
|
43
|
+
Constructs a CBOR codec. Returns: C<CBOR>. The C<pairlists> option makes
|
|
44
|
+
decoded maps return as C<PairList> values instead of C<Dict> values.
|
|
45
|
+
|
|
46
|
+
=over
|
|
47
|
+
|
|
48
|
+
=item C<< codec.encode(value) >>
|
|
49
|
+
|
|
50
|
+
Parameters: C<value> is any CBOR-encodable ZuzuScript value. Returns:
|
|
51
|
+
C<BinaryString>. Encodes C<value> as CBOR bytes.
|
|
52
|
+
|
|
53
|
+
=item C<< codec.encode_binarystring(value) >>
|
|
54
|
+
|
|
55
|
+
Alias for C<codec.encode(value)>.
|
|
56
|
+
|
|
57
|
+
=item C<< codec.decode(BinaryString raw) >>
|
|
58
|
+
|
|
59
|
+
Parameters: C<raw> is CBOR data. Returns: value. Decodes CBOR bytes into
|
|
60
|
+
the equivalent ZuzuScript value.
|
|
61
|
+
|
|
62
|
+
=item C<< codec.decode_binarystring(BinaryString raw) >>
|
|
63
|
+
|
|
64
|
+
Alias for C<codec.decode(raw)>.
|
|
65
|
+
|
|
66
|
+
=item C<< codec.load(Path path) >>
|
|
67
|
+
|
|
68
|
+
Parameters: C<path> is a C<std/io> C<Path>. Returns: value. Reads CBOR
|
|
69
|
+
bytes from C<path> and decodes them.
|
|
70
|
+
|
|
71
|
+
=item C<< codec.dump(Path path, value) >>
|
|
72
|
+
|
|
73
|
+
Parameters: C<path> is a C<std/io> C<Path> and C<value> is any
|
|
74
|
+
CBOR-encodable value. Returns: C<null>. Encodes C<value> and writes CBOR
|
|
75
|
+
bytes to C<path>.
|
|
76
|
+
|
|
77
|
+
=back
|
|
78
|
+
|
|
79
|
+
=back
|
|
80
|
+
|
|
81
|
+
=head1 COPYRIGHT AND LICENCE
|
|
82
|
+
|
|
83
|
+
B<< std/data/cbor >> is copyright Toby Inkster.
|
|
84
|
+
|
|
85
|
+
It is free software; you may redistribute it and/or modify it under
|
|
86
|
+
the terms of either the Artistic License 1.0 or the GNU General Public
|
|
87
|
+
License version 2.
|
|
88
|
+
|
|
89
|
+
=cut
|
|
90
|
+
|
|
91
|
+
from std/string import substr, index;
|
|
92
|
+
from std/string/base64 import encode, decode;
|
|
93
|
+
from std/time import Time;
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
let _B64_ALPHABET := "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
|
97
|
+
|
|
98
|
+
// Set to "PairList" to return CBOR objects as Zuzu PairLists.
|
|
99
|
+
let _DECODE_MAP_AS := "Dict";
|
|
100
|
+
|
|
101
|
+
class TaggedValue {
|
|
102
|
+
let Number tag;
|
|
103
|
+
let value;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function _div_floor ( Number n, Number d ) {
|
|
107
|
+
return floor( n / d ); // fix syntax highlighting
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
function _mod ( Number n, Number d ) {
|
|
111
|
+
return n - _div_floor( n, d ) * d;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
function _bytes_to_binary ( Array bytes ) {
|
|
115
|
+
let out := "";
|
|
116
|
+
let i := 0;
|
|
117
|
+
let n := bytes.length();
|
|
118
|
+
|
|
119
|
+
while ( i < n ) {
|
|
120
|
+
let b0 := bytes[i];
|
|
121
|
+
let b1 := null;
|
|
122
|
+
let b2 := null;
|
|
123
|
+
if ( i + 1 < n ) {
|
|
124
|
+
b1 := bytes[i + 1];
|
|
125
|
+
}
|
|
126
|
+
if ( i + 2 < n ) {
|
|
127
|
+
b2 := bytes[i + 2];
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
let c0 := _div_floor( b0, 4 );
|
|
131
|
+
let c1 := _mod( b0, 4 ) * 16;
|
|
132
|
+
let c2 := 64;
|
|
133
|
+
let c3 := 64;
|
|
134
|
+
|
|
135
|
+
if ( b1 ≢ null ) {
|
|
136
|
+
c1 += _div_floor( b1, 16 );
|
|
137
|
+
c2 := _mod( b1, 16 ) * 4;
|
|
138
|
+
if ( b2 ≢ null ) {
|
|
139
|
+
c2 += _div_floor( b2, 64 );
|
|
140
|
+
c3 := _mod( b2, 64 );
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
out _= substr( _B64_ALPHABET, c0, 1 );
|
|
145
|
+
out _= substr( _B64_ALPHABET, c1, 1 );
|
|
146
|
+
if ( c2 ≡ 64 ) {
|
|
147
|
+
out _= "=";
|
|
148
|
+
}
|
|
149
|
+
else {
|
|
150
|
+
out _= substr( _B64_ALPHABET, c2, 1 );
|
|
151
|
+
}
|
|
152
|
+
if ( c3 ≡ 64 ) {
|
|
153
|
+
out _= "=";
|
|
154
|
+
}
|
|
155
|
+
else {
|
|
156
|
+
out _= substr( _B64_ALPHABET, c3, 1 );
|
|
157
|
+
}
|
|
158
|
+
i += 3;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
return decode(out);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
function _binary_to_bytes ( BinaryString raw ) {
|
|
165
|
+
let b64 := encode(raw);
|
|
166
|
+
let out := [];
|
|
167
|
+
let i := 0;
|
|
168
|
+
let n := length b64;
|
|
169
|
+
|
|
170
|
+
while ( i < n ) {
|
|
171
|
+
let c0 := index( _B64_ALPHABET, substr( b64, i, 1 ) );
|
|
172
|
+
let c1 := index( _B64_ALPHABET, substr( b64, i + 1, 1 ) );
|
|
173
|
+
let ch2 := substr( b64, i + 2, 1 );
|
|
174
|
+
let ch3 := substr( b64, i + 3, 1 );
|
|
175
|
+
let c2 := -1;
|
|
176
|
+
let c3 := -1;
|
|
177
|
+
if ( ch2 ≢ "=" ) {
|
|
178
|
+
c2 := index( _B64_ALPHABET, ch2 );
|
|
179
|
+
}
|
|
180
|
+
if ( ch3 ≢ "=" ) {
|
|
181
|
+
c3 := index( _B64_ALPHABET, ch3 );
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
out.push( c0 * 4 + _div_floor( c1, 16 ) );
|
|
185
|
+
|
|
186
|
+
if ( c2 >= 0 ) {
|
|
187
|
+
out.push( _mod( c1, 16 ) * 16 + _div_floor( c2, 4 ) );
|
|
188
|
+
}
|
|
189
|
+
if ( c3 >= 0 ) {
|
|
190
|
+
out.push( _mod( c2, 4 ) * 64 + c3 );
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
i += 4;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
return out;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
function _is_int ( value ) {
|
|
200
|
+
if ( not( value instanceof Number ) ) {
|
|
201
|
+
return false;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
return _mod( value, 1 ) ≡ 0;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
function _emit_uint ( Array out, Number major, Number n ) {
|
|
208
|
+
if ( n < 24 ) {
|
|
209
|
+
out.push( major * 32 + n );
|
|
210
|
+
return;
|
|
211
|
+
}
|
|
212
|
+
if ( n < 256 ) {
|
|
213
|
+
out.push( major * 32 + 24 );
|
|
214
|
+
out.push(n);
|
|
215
|
+
return;
|
|
216
|
+
}
|
|
217
|
+
if ( n < 65536 ) {
|
|
218
|
+
out.push( major * 32 + 25 );
|
|
219
|
+
out.push( _mod( _div_floor( n, 256 ), 256 ) );
|
|
220
|
+
out.push( _mod( n, 256 ) );
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
223
|
+
if ( n < 4294967296 ) {
|
|
224
|
+
out.push( major * 32 + 26 );
|
|
225
|
+
out.push( _mod( _div_floor( n, 16777216 ), 256 ) );
|
|
226
|
+
out.push( _mod( _div_floor( n, 65536 ), 256 ) );
|
|
227
|
+
out.push( _mod( _div_floor( n, 256 ), 256 ) );
|
|
228
|
+
out.push( _mod( n, 256 ) );
|
|
229
|
+
return;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
let hi := _div_floor( n, 4294967296 );
|
|
233
|
+
let lo := _mod( n, 4294967296 );
|
|
234
|
+
out.push( major * 32 + 27 );
|
|
235
|
+
out.push( _mod( _div_floor( hi, 16777216 ), 256 ) );
|
|
236
|
+
out.push( _mod( _div_floor( hi, 65536 ), 256 ) );
|
|
237
|
+
out.push( _mod( _div_floor( hi, 256 ), 256 ) );
|
|
238
|
+
out.push( _mod( hi, 256 ) );
|
|
239
|
+
out.push( _mod( _div_floor( lo, 16777216 ), 256 ) );
|
|
240
|
+
out.push( _mod( _div_floor( lo, 65536 ), 256 ) );
|
|
241
|
+
out.push( _mod( _div_floor( lo, 256 ), 256 ) );
|
|
242
|
+
out.push( _mod( lo, 256 ) );
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
function _encode_value ( Array out, value ) {
|
|
246
|
+
if ( value ≡ null ) {
|
|
247
|
+
out.push(246);
|
|
248
|
+
return;
|
|
249
|
+
}
|
|
250
|
+
if ( value ≡ true ) {
|
|
251
|
+
out.push(245);
|
|
252
|
+
return;
|
|
253
|
+
}
|
|
254
|
+
if ( value ≡ false ) {
|
|
255
|
+
out.push(244);
|
|
256
|
+
return;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
if ( value instanceof Number ) {
|
|
260
|
+
die "CBOR.encode currently supports only integer Number values" if not _is_int(value);
|
|
261
|
+
if ( value >= 0 ) {
|
|
262
|
+
_emit_uint( out, 0, value );
|
|
263
|
+
}
|
|
264
|
+
else {
|
|
265
|
+
_emit_uint( out, 1, -1 - value );
|
|
266
|
+
}
|
|
267
|
+
return;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
if ( value instanceof BinaryString ) {
|
|
271
|
+
let b := _binary_to_bytes(value);
|
|
272
|
+
_emit_uint( out, 2, b.length() );
|
|
273
|
+
let i := 0;
|
|
274
|
+
while ( i < b.length() ) {
|
|
275
|
+
out.push( b[i] );
|
|
276
|
+
i++;
|
|
277
|
+
}
|
|
278
|
+
return;
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
if ( value instanceof String ) {
|
|
282
|
+
let b := _binary_to_bytes( to_binary(value) );
|
|
283
|
+
_emit_uint( out, 3, b.length() );
|
|
284
|
+
let i := 0;
|
|
285
|
+
while ( i < b.length() ) {
|
|
286
|
+
out.push( b[i] );
|
|
287
|
+
i++;
|
|
288
|
+
}
|
|
289
|
+
return;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
if ( value instanceof Array ) {
|
|
293
|
+
_emit_uint( out, 4, value.length() );
|
|
294
|
+
let i := 0;
|
|
295
|
+
while ( i < value.length() ) {
|
|
296
|
+
_encode_value( out, value[i] );
|
|
297
|
+
i++;
|
|
298
|
+
}
|
|
299
|
+
return;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
if ( value instanceof Set ) {
|
|
303
|
+
_emit_uint( out, 6, 258 );
|
|
304
|
+
_encode_value( out, value.sortstr() );
|
|
305
|
+
return;
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
if ( value instanceof Bag ) {
|
|
309
|
+
_encode_value( out, value.sortstr() );
|
|
310
|
+
return;
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
if ( value instanceof PairList ) {
|
|
314
|
+
let pairs := value.to_Array();
|
|
315
|
+
_emit_uint( out, 5, pairs.length() );
|
|
316
|
+
let i := 0;
|
|
317
|
+
while ( i < pairs.length() ) {
|
|
318
|
+
let pair := pairs[i]{pair};
|
|
319
|
+
_encode_value( out, pair[0] );
|
|
320
|
+
_encode_value( out, pair[1] );
|
|
321
|
+
i++;
|
|
322
|
+
}
|
|
323
|
+
return;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
if ( value instanceof Dict ) {
|
|
327
|
+
let keys := value.sorted_keys();
|
|
328
|
+
_emit_uint( out, 5, keys.length() );
|
|
329
|
+
let i := 0;
|
|
330
|
+
while ( i < keys.length() ) {
|
|
331
|
+
let k := keys[i];
|
|
332
|
+
_encode_value( out, k );
|
|
333
|
+
_encode_value( out, value.get(k) );
|
|
334
|
+
i++;
|
|
335
|
+
}
|
|
336
|
+
return;
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
if ( value instanceof TaggedValue ) {
|
|
340
|
+
_emit_uint( out, 6, value { tag } );
|
|
341
|
+
_encode_value( out, value { value } );
|
|
342
|
+
return;
|
|
343
|
+
}
|
|
344
|
+
if ( value instanceof Time ) {
|
|
345
|
+
_emit_uint( out, 6, 0 );
|
|
346
|
+
_encode_value( out, value.epoch() );
|
|
347
|
+
return;
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
die `CBOR cannot encode value of type ${typeof value}`;
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
function _read_uint ( Array bytes, Number ai, Number pos ) {
|
|
354
|
+
if ( ai < 24 ) {
|
|
355
|
+
return [ ai, pos ];
|
|
356
|
+
}
|
|
357
|
+
if ( ai ≡ 24 ) {
|
|
358
|
+
return [ bytes[pos], pos + 1 ];
|
|
359
|
+
}
|
|
360
|
+
if ( ai ≡ 25 ) {
|
|
361
|
+
return [ bytes[pos] * 256 + bytes[pos + 1], pos + 2 ];
|
|
362
|
+
}
|
|
363
|
+
if ( ai ≡ 26 ) {
|
|
364
|
+
return [ bytes[pos] * 16777216 + bytes[pos + 1] * 65536 + bytes[pos + 2] * 256 + bytes[pos + 3], pos + 4 ];
|
|
365
|
+
}
|
|
366
|
+
if ( ai ≡ 27 ) {
|
|
367
|
+
let hi := bytes[pos] * 16777216 + bytes[pos + 1] * 65536 + bytes[pos + 2] * 256 + bytes[pos + 3];
|
|
368
|
+
let lo := bytes[pos + 4] * 16777216 + bytes[pos + 5] * 65536 + bytes[pos + 6] * 256 + bytes[pos + 7];
|
|
369
|
+
return [ hi * 4294967296 + lo, pos + 8 ];
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
die `Unsupported CBOR additional info: ${ai}`;
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
function _decode_at ( Array bytes, Number pos ) {
|
|
376
|
+
let head := bytes[pos];
|
|
377
|
+
let major := _div_floor( head, 32 );
|
|
378
|
+
let ai := _mod( head, 32 );
|
|
379
|
+
let parsed := _read_uint( bytes, ai, pos + 1 );
|
|
380
|
+
let arg := parsed[0];
|
|
381
|
+
let p := parsed[1];
|
|
382
|
+
|
|
383
|
+
if ( major ≡ 0 ) {
|
|
384
|
+
return [ arg, p ];
|
|
385
|
+
}
|
|
386
|
+
if ( major ≡ 1 ) {
|
|
387
|
+
return [ -1 - arg, p ];
|
|
388
|
+
}
|
|
389
|
+
if ( major ≡ 2 ) {
|
|
390
|
+
let chunk := [];
|
|
391
|
+
let i := 0;
|
|
392
|
+
while ( i < arg ) {
|
|
393
|
+
chunk.push( bytes[p + i] );
|
|
394
|
+
i++;
|
|
395
|
+
}
|
|
396
|
+
return [ _bytes_to_binary(chunk), p + arg ];
|
|
397
|
+
}
|
|
398
|
+
if ( major ≡ 3 ) {
|
|
399
|
+
let chunk := [];
|
|
400
|
+
let i := 0;
|
|
401
|
+
while ( i < arg ) {
|
|
402
|
+
chunk.push( bytes[p + i] );
|
|
403
|
+
i++;
|
|
404
|
+
}
|
|
405
|
+
return [ to_string( _bytes_to_binary(chunk) ), p + arg ];
|
|
406
|
+
}
|
|
407
|
+
if ( major ≡ 4 ) {
|
|
408
|
+
let arr := [];
|
|
409
|
+
let i := 0;
|
|
410
|
+
let q := p;
|
|
411
|
+
while ( i < arg ) {
|
|
412
|
+
let item := _decode_at( bytes, q );
|
|
413
|
+
arr.push( item[0] );
|
|
414
|
+
q := item[1];
|
|
415
|
+
i++;
|
|
416
|
+
}
|
|
417
|
+
return [ arr, q ];
|
|
418
|
+
}
|
|
419
|
+
if ( major ≡ 5 ) {
|
|
420
|
+
let d := _DECODE_MAP_AS eq "PairList" ? new PairList() : new Dict();
|
|
421
|
+
let i := 0;
|
|
422
|
+
let q := p;
|
|
423
|
+
while ( i < arg ) {
|
|
424
|
+
let k := _decode_at( bytes, q );
|
|
425
|
+
let v := _decode_at( bytes, k[1] );
|
|
426
|
+
d.add( k[0], v[0] ) unless _DECODE_MAP_AS eq "Dict" and d.exists( k[0] );
|
|
427
|
+
q := v[1];
|
|
428
|
+
i++;
|
|
429
|
+
}
|
|
430
|
+
return [ d, q ];
|
|
431
|
+
}
|
|
432
|
+
if ( major ≡ 6 ) {
|
|
433
|
+
let tagged := _decode_at( bytes, p );
|
|
434
|
+
if ( arg ≡ 0 and tagged[0] instanceof Number ) {
|
|
435
|
+
return [ new Time( tagged[0] ), tagged[1] ];
|
|
436
|
+
}
|
|
437
|
+
if ( arg ≡ 258 and tagged[0] instanceof Array ) {
|
|
438
|
+
return [ tagged[0].to_Set(), tagged[1] ];
|
|
439
|
+
}
|
|
440
|
+
return [ new TaggedValue( tag: arg, value: tagged[0] ), tagged[1] ];
|
|
441
|
+
}
|
|
442
|
+
if ( major ≡ 7 ) {
|
|
443
|
+
if ( ai ≡ 20 ) {
|
|
444
|
+
return [ false, pos + 1 ];
|
|
445
|
+
}
|
|
446
|
+
if ( ai ≡ 21 ) {
|
|
447
|
+
return [ true, pos + 1 ];
|
|
448
|
+
}
|
|
449
|
+
if ( ai ≡ 22 ) {
|
|
450
|
+
return [ null, pos + 1 ];
|
|
451
|
+
}
|
|
452
|
+
die `Unsupported CBOR simple/float value (ai=${ai})`;
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
die `Unsupported CBOR major type: ${major}`;
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
class CBOR {
|
|
459
|
+
let pairlists := false;
|
|
460
|
+
|
|
461
|
+
method encode ( value ) {
|
|
462
|
+
let out := [];
|
|
463
|
+
_encode_value( out, value );
|
|
464
|
+
return _bytes_to_binary(out);
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
method encode_binarystring ( value ) {
|
|
468
|
+
return self.encode(value);
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
method decode ( BinaryString raw ) {
|
|
472
|
+
_DECODE_MAP_AS := pairlists ? "PairList" : "Dict";
|
|
473
|
+
let bytes := _binary_to_bytes(raw);
|
|
474
|
+
let parsed := _decode_at( bytes, 0 );
|
|
475
|
+
die "Trailing bytes after CBOR value" if parsed[1] < bytes.length();
|
|
476
|
+
return parsed[0];
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
method decode_binarystring ( BinaryString raw ) {
|
|
480
|
+
return self.decode(raw);
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
method load ( path ) {
|
|
484
|
+
from std/io import Path;
|
|
485
|
+
die "CBOR.load is denied by runtime policy" if __system__{deny_fs};
|
|
486
|
+
die "CBOR.load expects a std/io Path object" if not( path instanceof Path );
|
|
487
|
+
return self.decode( path.slurp() );
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
method dump ( path, value ) {
|
|
491
|
+
from std/io import Path;
|
|
492
|
+
die "CBOR.dump is denied by runtime policy" if __system__{deny_fs};
|
|
493
|
+
die "CBOR.dump expects a std/io Path object" if not( path instanceof Path );
|
|
494
|
+
path.spew( self.encode(value) );
|
|
495
|
+
return path;
|
|
496
|
+
}
|
|
497
|
+
}
|