@soundscript/soundscript 0.1.1 → 0.1.3
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/README.md +1 -1
- package/async.d.ts +3 -3
- package/async.js +2 -2
- package/async.js.map +1 -1
- package/codec.d.ts +3 -2
- package/codec.js +2 -2
- package/codec.js.map +1 -1
- package/compare.js +5 -10
- package/compare.js.map +1 -1
- package/decode.d.ts +6 -4
- package/decode.js +5 -5
- package/decode.js.map +1 -1
- package/derive.d.ts +6 -0
- package/derive.js +8 -0
- package/derive.js.map +1 -0
- package/encode.d.ts +11 -9
- package/encode.js +5 -5
- package/encode.js.map +1 -1
- package/experimental/thunk.js.map +1 -0
- package/fetch.d.ts +67 -0
- package/fetch.js +6 -0
- package/fetch.js.map +1 -0
- package/hash.js +9 -14
- package/hash.js.map +1 -1
- package/json.d.ts +29 -2
- package/json.js +124 -1
- package/json.js.map +1 -1
- package/numerics.d.ts +523 -0
- package/numerics.js +1357 -0
- package/numerics.js.map +1 -0
- package/package.json +122 -35
- package/random.d.ts +19 -0
- package/random.js +4 -0
- package/random.js.map +1 -0
- package/result.d.ts +21 -5
- package/result.js +55 -19
- package/result.js.map +1 -1
- package/soundscript/async.sts +7 -7
- package/soundscript/codec.sts +8 -7
- package/soundscript/compare.sts +5 -13
- package/soundscript/decode.sts +15 -13
- package/soundscript/derive.sts +7 -0
- package/soundscript/encode.sts +18 -16
- package/soundscript/fetch.sts +11 -0
- package/soundscript/hash.sts +9 -17
- package/soundscript/json.sts +209 -3
- package/soundscript/numerics.sts +1937 -0
- package/soundscript/random.sts +5 -0
- package/soundscript/result.sts +93 -24
- package/soundscript/text.sts +4 -0
- package/soundscript/typeclasses.sts +22 -16
- package/soundscript/url.sts +4 -0
- package/soundscript/value.sts +133 -0
- package/text.d.ts +24 -0
- package/text.js +4 -0
- package/text.js.map +1 -0
- package/typeclasses.d.ts +2 -2
- package/typeclasses.js +10 -9
- package/typeclasses.js.map +1 -1
- package/url.d.ts +37 -0
- package/url.js +4 -0
- package/url.js.map +1 -0
- package/value.d.ts +9 -0
- package/value.js +105 -0
- package/value.js.map +1 -0
- package/experimental/component.d.ts +0 -40
- package/experimental/component.js +0 -46
- package/experimental/component.js.map +0 -1
- package/soundscript/experimental/component.sts +0 -69
- package/thunk.js.map +0 -1
- /package/{thunk.d.ts → experimental/thunk.d.ts} +0 -0
- /package/{thunk.js → experimental/thunk.js} +0 -0
- /package/soundscript/{thunk.sts → experimental/thunk.sts} +0 -0
package/soundscript/json.sts
CHANGED
|
@@ -2,6 +2,22 @@ import type { Decoder } from '@soundscript/soundscript/decode';
|
|
|
2
2
|
import type { Encoder } from '@soundscript/soundscript/encode';
|
|
3
3
|
import { Failure } from '@soundscript/soundscript/failures';
|
|
4
4
|
import { isErr, type Result, resultOf } from '@soundscript/soundscript/result';
|
|
5
|
+
import {
|
|
6
|
+
F32,
|
|
7
|
+
F64,
|
|
8
|
+
format as formatNumeric,
|
|
9
|
+
I8,
|
|
10
|
+
I16,
|
|
11
|
+
I32,
|
|
12
|
+
I64,
|
|
13
|
+
isNumeric,
|
|
14
|
+
toHostNumber,
|
|
15
|
+
type Numeric,
|
|
16
|
+
U8,
|
|
17
|
+
U16,
|
|
18
|
+
U32,
|
|
19
|
+
U64,
|
|
20
|
+
} from './numerics.js';
|
|
5
21
|
|
|
6
22
|
export type JsonArray = JsonValue[];
|
|
7
23
|
export type JsonObject = {
|
|
@@ -35,8 +51,26 @@ export type JsonLikeValue =
|
|
|
35
51
|
| JsonLikeObject
|
|
36
52
|
| JsonLikeArray;
|
|
37
53
|
|
|
54
|
+
export type MachineJsonArray = MachineJsonLikeValue[];
|
|
55
|
+
export type MachineJsonObject = {
|
|
56
|
+
[key: string]: MachineJsonLikeValue;
|
|
57
|
+
};
|
|
58
|
+
export type MachineJsonLikeValue =
|
|
59
|
+
| string
|
|
60
|
+
| number
|
|
61
|
+
| boolean
|
|
62
|
+
| bigint
|
|
63
|
+
| null
|
|
64
|
+
| undefined
|
|
65
|
+
| Numeric
|
|
66
|
+
| MachineJsonObject
|
|
67
|
+
| MachineJsonArray;
|
|
68
|
+
|
|
69
|
+
export type MachineJsonNumericMode = 'tagged' | 'decimal-string' | 'json-number';
|
|
70
|
+
|
|
38
71
|
export interface JsonParseOptions {
|
|
39
72
|
int64?: 'default' | 'lossless';
|
|
73
|
+
numerics?: 'tagged';
|
|
40
74
|
}
|
|
41
75
|
|
|
42
76
|
export type JsonStringifyBigintMode = 'number' | 'reject' | 'string';
|
|
@@ -44,6 +78,7 @@ export type JsonStringifyBigintMode = 'number' | 'reject' | 'string';
|
|
|
44
78
|
export interface JsonStringifyOptions {
|
|
45
79
|
int64?: 'default' | 'string' | 'lossless';
|
|
46
80
|
readonly bigint?: JsonStringifyBigintMode;
|
|
81
|
+
numerics?: MachineJsonNumericMode;
|
|
47
82
|
}
|
|
48
83
|
|
|
49
84
|
const MAX_SAFE_INTEGER_BIGINT = BigInt(Number.MAX_SAFE_INTEGER);
|
|
@@ -66,12 +101,21 @@ export function parseJson(
|
|
|
66
101
|
text: string,
|
|
67
102
|
options: JsonParseOptions & { int64: 'lossless' },
|
|
68
103
|
): Result<LosslessJsonValue, JsonParseFailure>;
|
|
104
|
+
export function parseJson(
|
|
105
|
+
text: string,
|
|
106
|
+
options: JsonParseOptions & { numerics: 'tagged' },
|
|
107
|
+
): Result<MachineJsonLikeValue, JsonParseFailure>;
|
|
69
108
|
export function parseJson(
|
|
70
109
|
text: string,
|
|
71
110
|
options: JsonParseOptions = {},
|
|
72
|
-
): Result<JsonValue | LosslessJsonValue, JsonParseFailure> {
|
|
111
|
+
): Result<JsonValue | LosslessJsonValue | MachineJsonLikeValue, JsonParseFailure> {
|
|
73
112
|
return resultOf(
|
|
74
|
-
() =>
|
|
113
|
+
() => {
|
|
114
|
+
const parsed = options.int64 === 'lossless' ? parseLosslessJson(text) : JSON.parse(text);
|
|
115
|
+
return options.numerics === 'tagged'
|
|
116
|
+
? decodeTaggedMachineJsonValue(parsed as JsonValue | LosslessJsonValue)
|
|
117
|
+
: parsed;
|
|
118
|
+
},
|
|
75
119
|
(cause) => new JsonParseFailure(cause),
|
|
76
120
|
);
|
|
77
121
|
}
|
|
@@ -82,11 +126,34 @@ export function stringifyJson(
|
|
|
82
126
|
options: JsonStringifyOptions & { int64: 'string' | 'lossless' },
|
|
83
127
|
): Result<string, JsonStringifyFailure>;
|
|
84
128
|
export function stringifyJson(
|
|
85
|
-
value:
|
|
129
|
+
value: MachineJsonLikeValue,
|
|
130
|
+
options: JsonStringifyOptions & { numerics: MachineJsonNumericMode },
|
|
131
|
+
): Result<string, JsonStringifyFailure>;
|
|
132
|
+
export function stringifyJson(
|
|
133
|
+
value: JsonValue | LosslessJsonValue | MachineJsonLikeValue,
|
|
86
134
|
options: JsonStringifyOptions = {},
|
|
87
135
|
): Result<string, JsonStringifyFailure> {
|
|
88
136
|
return resultOf(
|
|
89
137
|
() => {
|
|
138
|
+
if (options.numerics) {
|
|
139
|
+
const normalized = normalizeMachineJsonLikeValue(
|
|
140
|
+
value as MachineJsonLikeValue,
|
|
141
|
+
new Set<object>(),
|
|
142
|
+
options.numerics,
|
|
143
|
+
'root',
|
|
144
|
+
);
|
|
145
|
+
const encoded = stringifyJsonLikeInternal(
|
|
146
|
+
normalized,
|
|
147
|
+
new Set<object>(),
|
|
148
|
+
options.bigint ?? 'reject',
|
|
149
|
+
'root',
|
|
150
|
+
);
|
|
151
|
+
if (encoded === undefined) {
|
|
152
|
+
throw new TypeError('JSON stringification produced no top-level value.');
|
|
153
|
+
}
|
|
154
|
+
return encoded;
|
|
155
|
+
}
|
|
156
|
+
|
|
90
157
|
if (options.int64 === 'string') {
|
|
91
158
|
return stringifyJsonWithInt64Mode(value as LosslessJsonValue, 'string');
|
|
92
159
|
}
|
|
@@ -322,6 +389,145 @@ function isJsonLikeValueInternal(
|
|
|
322
389
|
}
|
|
323
390
|
}
|
|
324
391
|
|
|
392
|
+
function normalizeMachineJsonLikeValue(
|
|
393
|
+
value: MachineJsonLikeValue,
|
|
394
|
+
visited: Set<object>,
|
|
395
|
+
numericMode: MachineJsonNumericMode,
|
|
396
|
+
position: 'array' | 'object' | 'root',
|
|
397
|
+
): JsonLikeValue {
|
|
398
|
+
if (isNumeric(value)) {
|
|
399
|
+
return normalizeMachineNumericJsonValue(value, numericMode);
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
switch (typeof value) {
|
|
403
|
+
case 'string':
|
|
404
|
+
case 'number':
|
|
405
|
+
case 'boolean':
|
|
406
|
+
case 'bigint':
|
|
407
|
+
return value;
|
|
408
|
+
case 'undefined':
|
|
409
|
+
return position === 'array' ? null : undefined;
|
|
410
|
+
case 'object':
|
|
411
|
+
if (value === null) {
|
|
412
|
+
return null;
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
if (visited.has(value)) {
|
|
416
|
+
throw new TypeError('Converting circular structure to machine JSON text.');
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
visited.add(value);
|
|
420
|
+
try {
|
|
421
|
+
if (Array.isArray(value)) {
|
|
422
|
+
return value.map((entry) =>
|
|
423
|
+
normalizeMachineJsonLikeValue(entry, visited, numericMode, 'array') ?? null
|
|
424
|
+
);
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
const result: Record<string, JsonLikeValue> = {};
|
|
428
|
+
for (const key of Object.keys(value)) {
|
|
429
|
+
const normalized = normalizeMachineJsonLikeValue(
|
|
430
|
+
(value as MachineJsonObject)[key]!,
|
|
431
|
+
visited,
|
|
432
|
+
numericMode,
|
|
433
|
+
'object',
|
|
434
|
+
);
|
|
435
|
+
if (normalized !== undefined) {
|
|
436
|
+
result[key] = normalized;
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
return result;
|
|
440
|
+
} finally {
|
|
441
|
+
visited.delete(value);
|
|
442
|
+
}
|
|
443
|
+
default:
|
|
444
|
+
throw new TypeError(`Unsupported machine JSON value kind: ${typeof value}`);
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
function normalizeMachineNumericJsonValue(
|
|
449
|
+
value: Numeric,
|
|
450
|
+
numericMode: MachineJsonNumericMode,
|
|
451
|
+
): JsonLikeValue {
|
|
452
|
+
switch (numericMode) {
|
|
453
|
+
case 'tagged':
|
|
454
|
+
return value.toJSON();
|
|
455
|
+
case 'decimal-string':
|
|
456
|
+
return formatNumeric(value);
|
|
457
|
+
case 'json-number':
|
|
458
|
+
switch (value.__soundscript_numeric_kind) {
|
|
459
|
+
case 'i64':
|
|
460
|
+
case 'u64':
|
|
461
|
+
throw new TypeError('json-number machine JSON mode does not support bigint-backed machine numerics.');
|
|
462
|
+
default:
|
|
463
|
+
return toHostNumber(value);
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
function decodeTaggedMachineJsonValue(value: JsonValue | LosslessJsonValue): MachineJsonLikeValue {
|
|
469
|
+
if (Array.isArray(value)) {
|
|
470
|
+
return value.map((entry) => decodeTaggedMachineJsonValue(entry));
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
if (value && typeof value === 'object') {
|
|
474
|
+
const taggedNumeric = decodeTaggedMachineNumeric(value);
|
|
475
|
+
if (taggedNumeric) {
|
|
476
|
+
return taggedNumeric;
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
const result: Record<string, MachineJsonLikeValue> = {};
|
|
480
|
+
for (const key of Object.keys(value)) {
|
|
481
|
+
result[key] = decodeTaggedMachineJsonValue(value[key]!);
|
|
482
|
+
}
|
|
483
|
+
return result;
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
return value;
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
function decodeTaggedMachineNumeric(
|
|
490
|
+
value: Record<string, JsonValue | LosslessJsonValue>,
|
|
491
|
+
): Numeric | undefined {
|
|
492
|
+
const numericKind = value.$numeric;
|
|
493
|
+
const numericValue = value.value;
|
|
494
|
+
const keys = Object.keys(value);
|
|
495
|
+
if (
|
|
496
|
+
typeof numericKind !== 'string' ||
|
|
497
|
+
typeof numericValue !== 'string' ||
|
|
498
|
+
keys.length !== 2 ||
|
|
499
|
+
!keys.includes('$numeric') ||
|
|
500
|
+
!keys.includes('value')
|
|
501
|
+
) {
|
|
502
|
+
return undefined;
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
switch (numericKind) {
|
|
506
|
+
case 'f64':
|
|
507
|
+
return F64.parse(numericValue);
|
|
508
|
+
case 'f32':
|
|
509
|
+
return F32.parse(numericValue);
|
|
510
|
+
case 'i8':
|
|
511
|
+
return I8.parse(numericValue);
|
|
512
|
+
case 'i16':
|
|
513
|
+
return I16.parse(numericValue);
|
|
514
|
+
case 'i32':
|
|
515
|
+
return I32.parse(numericValue);
|
|
516
|
+
case 'i64':
|
|
517
|
+
return I64.parse(numericValue);
|
|
518
|
+
case 'u8':
|
|
519
|
+
return U8.parse(numericValue);
|
|
520
|
+
case 'u16':
|
|
521
|
+
return U16.parse(numericValue);
|
|
522
|
+
case 'u32':
|
|
523
|
+
return U32.parse(numericValue);
|
|
524
|
+
case 'u64':
|
|
525
|
+
return U64.parse(numericValue);
|
|
526
|
+
default:
|
|
527
|
+
return undefined;
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
|
|
325
531
|
function stringifyJsonLikeInternal(
|
|
326
532
|
value: JsonLikeValue,
|
|
327
533
|
visited: Set<object>,
|