@kontor/kontor-sdk 1.0.0-alpha.39 → 1.0.0-alpha.40
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/dist/cjs/sdk/actions/kontor/public/call-view.js.map +1 -1
- package/dist/cjs/sdk/chains/definitions/signet.js +2 -2
- package/dist/cjs/sdk/test/e2e.test-deprecated.js +2 -0
- package/dist/cjs/sdk/test/e2e.test-deprecated.js.map +1 -0
- package/dist/cjs/sdk/utils/wit/codecs/bool.js +9 -21
- package/dist/cjs/sdk/utils/wit/codecs/bool.js.map +1 -1
- package/dist/cjs/sdk/utils/wit/codecs/contract-address.js +92 -0
- package/dist/cjs/sdk/utils/wit/codecs/contract-address.js.map +1 -0
- package/dist/cjs/sdk/utils/wit/codecs/index.js +29 -0
- package/dist/cjs/sdk/utils/wit/codecs/index.js.map +1 -0
- package/dist/cjs/sdk/utils/wit/codecs/list.js +21 -95
- package/dist/cjs/sdk/utils/wit/codecs/list.js.map +1 -1
- package/dist/cjs/sdk/utils/wit/codecs/numerics.js +228 -0
- package/dist/cjs/sdk/utils/wit/codecs/numerics.js.map +1 -0
- package/dist/cjs/sdk/utils/wit/codecs/option.js +21 -72
- package/dist/cjs/sdk/utils/wit/codecs/option.js.map +1 -1
- package/dist/cjs/sdk/utils/wit/codecs/result.js +32 -0
- package/dist/cjs/sdk/utils/wit/codecs/result.js.map +1 -0
- package/dist/cjs/sdk/utils/wit/codecs/string.js +16 -21
- package/dist/cjs/sdk/utils/wit/codecs/string.js.map +1 -1
- package/dist/cjs/sdk/utils/wit/codecs/unit.js +11 -19
- package/dist/cjs/sdk/utils/wit/codecs/unit.js.map +1 -1
- package/dist/cjs/sdk/utils/wit/codecs/util.js +185 -0
- package/dist/cjs/sdk/utils/wit/codecs/util.js.map +1 -0
- package/dist/cjs/sdk/utils/wit/decode-wit-parameter.js +297 -163
- package/dist/cjs/sdk/utils/wit/decode-wit-parameter.js.map +1 -1
- package/dist/cjs/sdk/utils/wit/encode-wit-parameters.js +214 -221
- package/dist/cjs/sdk/utils/wit/encode-wit-parameters.js.map +1 -1
- package/dist/cjs/tsconfig.build.tsbuildinfo +1 -1
- package/dist/cjs/wit/built-ins.js +19 -0
- package/dist/cjs/wit/built-ins.js.map +1 -0
- package/dist/cjs/wit/regex.js +1 -1
- package/dist/cjs/wit/regex.js.map +1 -1
- package/dist/cjs/wit/wit-parser/core/errors/signature.js +17 -2
- package/dist/cjs/wit/wit-parser/core/errors/signature.js.map +1 -1
- package/dist/cjs/wit/wit-parser/core/signatures.js +18 -0
- package/dist/cjs/wit/wit-parser/core/signatures.js.map +1 -1
- package/dist/cjs/wit/wit-parser/core/types/{records.js → user-defined.js} +1 -1
- package/dist/cjs/wit/wit-parser/core/types/user-defined.js.map +1 -0
- package/dist/cjs/wit/wit-parser/core/user-defined.js +271 -0
- package/dist/cjs/wit/wit-parser/core/user-defined.js.map +1 -0
- package/dist/cjs/wit/wit-parser/core/utils.js +29 -7
- package/dist/cjs/wit/wit-parser/core/utils.js.map +1 -1
- package/dist/cjs/wit/wit-parser/parse-wit-parameter.js +9 -3
- package/dist/cjs/wit/wit-parser/parse-wit-parameter.js.map +1 -1
- package/dist/cjs/wit/wit-parser/parse-wit.js +7 -3
- package/dist/cjs/wit/wit-parser/parse-wit.js.map +1 -1
- package/dist/esm/sdk/actions/kontor/public/call-view.js.map +1 -1
- package/dist/esm/sdk/chains/definitions/signet.js +2 -2
- package/dist/esm/sdk/test/e2e.test-deprecated.js +197 -0
- package/dist/esm/sdk/test/e2e.test-deprecated.js.map +1 -0
- package/dist/esm/sdk/utils/wit/codecs/bool.js +9 -21
- package/dist/esm/sdk/utils/wit/codecs/bool.js.map +1 -1
- package/dist/esm/sdk/utils/wit/codecs/contract-address.js +92 -0
- package/dist/esm/sdk/utils/wit/codecs/contract-address.js.map +1 -0
- package/dist/esm/sdk/utils/wit/codecs/index.js +9 -0
- package/dist/esm/sdk/utils/wit/codecs/index.js.map +1 -0
- package/dist/esm/sdk/utils/wit/codecs/list.js +20 -114
- package/dist/esm/sdk/utils/wit/codecs/list.js.map +1 -1
- package/dist/esm/sdk/utils/wit/codecs/numerics.js +234 -0
- package/dist/esm/sdk/utils/wit/codecs/numerics.js.map +1 -0
- package/dist/esm/sdk/utils/wit/codecs/option.js +21 -88
- package/dist/esm/sdk/utils/wit/codecs/option.js.map +1 -1
- package/dist/esm/sdk/utils/wit/codecs/result.js +29 -0
- package/dist/esm/sdk/utils/wit/codecs/result.js.map +1 -0
- package/dist/esm/sdk/utils/wit/codecs/string.js +22 -22
- package/dist/esm/sdk/utils/wit/codecs/string.js.map +1 -1
- package/dist/esm/sdk/utils/wit/codecs/unit.js +12 -21
- package/dist/esm/sdk/utils/wit/codecs/unit.js.map +1 -1
- package/dist/esm/sdk/utils/wit/codecs/util.js +181 -0
- package/dist/esm/sdk/utils/wit/codecs/util.js.map +1 -0
- package/dist/esm/sdk/utils/wit/decode-wit-parameter.js +322 -188
- package/dist/esm/sdk/utils/wit/decode-wit-parameter.js.map +1 -1
- package/dist/esm/sdk/utils/wit/encode-wit-parameters.js +230 -233
- package/dist/esm/sdk/utils/wit/encode-wit-parameters.js.map +1 -1
- package/dist/esm/tsconfig.build.tsbuildinfo +1 -1
- package/dist/esm/wit/built-ins.js +16 -0
- package/dist/esm/wit/built-ins.js.map +1 -0
- package/dist/esm/wit/regex.js +1 -1
- package/dist/esm/wit/regex.js.map +1 -1
- package/dist/esm/wit/wit-parser/core/errors/signature.js +15 -1
- package/dist/esm/wit/wit-parser/core/errors/signature.js.map +1 -1
- package/dist/esm/wit/wit-parser/core/signatures.js +14 -0
- package/dist/esm/wit/wit-parser/core/signatures.js.map +1 -1
- package/dist/esm/wit/wit-parser/core/types/signatures.js.map +1 -1
- package/dist/esm/wit/wit-parser/core/types/user-defined.js +2 -0
- package/dist/esm/wit/wit-parser/core/types/user-defined.js.map +1 -0
- package/dist/esm/wit/wit-parser/core/types/utils.js +25 -0
- package/dist/esm/wit/wit-parser/core/types/utils.js.map +1 -1
- package/dist/esm/wit/wit-parser/core/user-defined.js +280 -0
- package/dist/esm/wit/wit-parser/core/user-defined.js.map +1 -0
- package/dist/esm/wit/wit-parser/core/utils.js +33 -36
- package/dist/esm/wit/wit-parser/core/utils.js.map +1 -1
- package/dist/esm/wit/wit-parser/parse-wit-parameter.js +10 -4
- package/dist/esm/wit/wit-parser/parse-wit-parameter.js.map +1 -1
- package/dist/esm/wit/wit-parser/parse-wit.js +8 -4
- package/dist/esm/wit/wit-parser/parse-wit.js.map +1 -1
- package/dist/types/sdk/actions/kontor/public/call-view.d.ts +2 -1
- package/dist/types/sdk/actions/kontor/public/call-view.d.ts.map +1 -1
- package/dist/types/sdk/chains/definitions/signet.d.ts +2 -2
- package/dist/types/sdk/test/e2e.test-deprecated.d.ts +2 -0
- package/dist/types/sdk/test/e2e.test-deprecated.d.ts.map +1 -0
- package/dist/types/sdk/types/contract.d.ts +5 -5
- package/dist/types/sdk/types/contract.d.ts.map +1 -1
- package/dist/types/sdk/utils/wit/codecs/bool.d.ts +2 -2
- package/dist/types/sdk/utils/wit/codecs/bool.d.ts.map +1 -1
- package/dist/types/sdk/utils/wit/codecs/contract-address.d.ts +5 -0
- package/dist/types/sdk/utils/wit/codecs/contract-address.d.ts.map +1 -0
- package/dist/types/sdk/utils/wit/codecs/index.d.ts +9 -0
- package/dist/types/sdk/utils/wit/codecs/index.d.ts.map +1 -0
- package/dist/types/sdk/utils/wit/codecs/list.d.ts +2 -16
- package/dist/types/sdk/utils/wit/codecs/list.d.ts.map +1 -1
- package/dist/types/sdk/utils/wit/codecs/numerics.d.ts +14 -0
- package/dist/types/sdk/utils/wit/codecs/numerics.d.ts.map +1 -0
- package/dist/types/sdk/utils/wit/codecs/option.d.ts +3 -23
- package/dist/types/sdk/utils/wit/codecs/option.d.ts.map +1 -1
- package/dist/types/sdk/utils/wit/codecs/result.d.ts +4 -0
- package/dist/types/sdk/utils/wit/codecs/result.d.ts.map +1 -0
- package/dist/types/sdk/utils/wit/codecs/string.d.ts +6 -2
- package/dist/types/sdk/utils/wit/codecs/string.d.ts.map +1 -1
- package/dist/types/sdk/utils/wit/codecs/types.d.ts +4 -0
- package/dist/types/sdk/utils/wit/codecs/types.d.ts.map +1 -1
- package/dist/types/sdk/utils/wit/codecs/unit.d.ts +2 -11
- package/dist/types/sdk/utils/wit/codecs/unit.d.ts.map +1 -1
- package/dist/types/sdk/utils/wit/codecs/util.d.ts +12 -0
- package/dist/types/sdk/utils/wit/codecs/util.d.ts.map +1 -0
- package/dist/types/sdk/utils/wit/decode-wit-parameter.d.ts +9 -31
- package/dist/types/sdk/utils/wit/decode-wit-parameter.d.ts.map +1 -1
- package/dist/types/sdk/utils/wit/encode-wit-parameters.d.ts +9 -1
- package/dist/types/sdk/utils/wit/encode-wit-parameters.d.ts.map +1 -1
- package/dist/types/wit/built-ins.d.ts +6 -0
- package/dist/types/wit/built-ins.d.ts.map +1 -0
- package/dist/types/wit/regex.d.ts.map +1 -1
- package/dist/types/wit/utils.d.ts +53 -33
- package/dist/types/wit/utils.d.ts.map +1 -1
- package/dist/types/wit/wit-parser/core/errors/signature.d.ts +7 -1
- package/dist/types/wit/wit-parser/core/errors/signature.d.ts.map +1 -1
- package/dist/types/wit/wit-parser/core/signatures.d.ts +10 -0
- package/dist/types/wit/wit-parser/core/signatures.d.ts.map +1 -1
- package/dist/types/wit/wit-parser/core/types/signatures.d.ts +6 -2
- package/dist/types/wit/wit-parser/core/types/signatures.d.ts.map +1 -1
- package/dist/types/wit/wit-parser/core/types/user-defined.d.ts +134 -0
- package/dist/types/wit/wit-parser/core/types/user-defined.d.ts.map +1 -0
- package/dist/types/wit/wit-parser/core/types/utils.d.ts +86 -11
- package/dist/types/wit/wit-parser/core/types/utils.d.ts.map +1 -1
- package/dist/types/wit/wit-parser/core/user-defined.d.ts +19 -0
- package/dist/types/wit/wit-parser/core/user-defined.d.ts.map +1 -0
- package/dist/types/wit/wit-parser/core/utils.d.ts +8 -4
- package/dist/types/wit/wit-parser/core/utils.d.ts.map +1 -1
- package/dist/types/wit/wit-parser/parse-wit-parameter.d.ts +11 -5
- package/dist/types/wit/wit-parser/parse-wit-parameter.d.ts.map +1 -1
- package/dist/types/wit/wit-parser/parse-wit.d.ts +7 -3
- package/dist/types/wit/wit-parser/parse-wit.d.ts.map +1 -1
- package/dist/types/wit/wit.d.ts +20 -12
- package/dist/types/wit/wit.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/sdk/actions/get-contract.test-d.ts +430 -50
- package/src/sdk/actions/get-contract.test.ts +324 -24
- package/src/sdk/actions/kontor/public/call-view.ts +2 -1
- package/src/sdk/actions/kontor/public/proc-contract.test-d.ts +107 -0
- package/src/sdk/actions/kontor/public/proc-contract.test.ts +234 -21
- package/src/sdk/actions/kontor/public/view-contract.test-d.ts +240 -0
- package/src/sdk/actions/kontor/public/view-contract.test.ts +613 -18
- package/src/sdk/chains/definitions/signet.ts +2 -2
- package/src/sdk/clients/base/create-rpc-client.test.ts +2 -2
- package/src/sdk/clients/create-public-client.test.ts +2 -2
- package/src/sdk/clients/kontor/create-public-client.test.ts +2 -2
- package/src/sdk/clients/transports/http-rpc.test.ts +0 -24
- package/src/sdk/test/e2e.test-deprecated.ts +195 -0
- package/src/sdk/types/contract.test-d.ts +489 -55
- package/src/sdk/types/contract.ts +6 -7
- package/src/sdk/utils/wit/codecs/bool.test.ts +29 -0
- package/src/sdk/utils/wit/codecs/bool.ts +10 -25
- package/src/sdk/utils/wit/codecs/contract-address.test.ts +37 -0
- package/src/sdk/utils/wit/codecs/contract-address.ts +114 -0
- package/src/sdk/utils/wit/codecs/index.ts +20 -0
- package/src/sdk/utils/wit/codecs/list.test-d.ts +13 -0
- package/src/sdk/utils/wit/codecs/list.test.ts +55 -0
- package/src/sdk/utils/wit/codecs/list.ts +21 -150
- package/src/sdk/utils/wit/codecs/numerics.test.ts +399 -0
- package/src/sdk/utils/wit/codecs/numerics.ts +304 -0
- package/src/sdk/utils/wit/codecs/option.test.ts +71 -0
- package/src/sdk/utils/wit/codecs/option.ts +21 -120
- package/src/sdk/utils/wit/codecs/result.test.ts +82 -0
- package/src/sdk/utils/wit/codecs/result.ts +37 -0
- package/src/sdk/utils/wit/codecs/string.test.ts +62 -0
- package/src/sdk/utils/wit/codecs/string.ts +23 -25
- package/src/sdk/utils/wit/codecs/types.ts +5 -0
- package/src/sdk/utils/wit/codecs/unit.test.ts +27 -0
- package/src/sdk/utils/wit/codecs/unit.ts +14 -38
- package/src/sdk/utils/wit/codecs/util.test.ts +221 -0
- package/src/sdk/utils/wit/codecs/util.ts +193 -0
- package/src/sdk/utils/wit/decode-wit-parameter.test.ts +1264 -32
- package/src/sdk/utils/wit/decode-wit-parameter.ts +508 -211
- package/src/sdk/utils/wit/encode-wit-parameters.test.ts +955 -91
- package/src/sdk/utils/wit/encode-wit-parameters.ts +277 -274
- package/src/sdk/utils/wit/get-wit-item.test.ts +1 -1
- package/src/wit/built-ins.ts +23 -0
- package/src/wit/regex.ts +1 -1
- package/src/wit/utils.ts +120 -74
- package/src/wit/wit-parser/core/errors/signature.ts +13 -2
- package/src/wit/wit-parser/core/signatures.ts +28 -0
- package/src/wit/wit-parser/core/types/signatures.test-d.ts +21 -0
- package/src/wit/wit-parser/core/types/signatures.ts +19 -2
- package/src/wit/wit-parser/core/types/user-defined.test-d.ts +1308 -0
- package/src/wit/wit-parser/core/types/user-defined.ts +412 -0
- package/src/wit/wit-parser/core/types/utils.test-d.ts +43 -2
- package/src/wit/wit-parser/core/types/utils.ts +143 -14
- package/src/wit/wit-parser/core/user-defined.test.ts +609 -0
- package/src/wit/wit-parser/core/user-defined.ts +392 -0
- package/src/wit/wit-parser/core/utils.test.ts +334 -115
- package/src/wit/wit-parser/core/utils.ts +54 -38
- package/src/wit/wit-parser/parse-wit-parameter.test.ts +282 -4
- package/src/wit/wit-parser/parse-wit-parameter.ts +37 -11
- package/src/wit/wit-parser/parse-wit.test.ts +738 -12
- package/src/wit/wit-parser/parse-wit.ts +25 -10
- package/src/wit/wit.ts +37 -16
- package/vitest.config.ts +5 -0
- package/dist/cjs/sdk/utils/wit/codecs/decimal.js +0 -148
- package/dist/cjs/sdk/utils/wit/codecs/decimal.js.map +0 -1
- package/dist/cjs/sdk/utils/wit/codecs/enum.js +0 -94
- package/dist/cjs/sdk/utils/wit/codecs/enum.js.map +0 -1
- package/dist/cjs/sdk/utils/wit/codecs/integer.js +0 -125
- package/dist/cjs/sdk/utils/wit/codecs/integer.js.map +0 -1
- package/dist/cjs/sdk/utils/wit/codecs/s64.js +0 -57
- package/dist/cjs/sdk/utils/wit/codecs/s64.js.map +0 -1
- package/dist/cjs/sdk/utils/wit/codecs/u64.js +0 -56
- package/dist/cjs/sdk/utils/wit/codecs/u64.js.map +0 -1
- package/dist/cjs/wit/wit-parser/core/records.js +0 -70
- package/dist/cjs/wit/wit-parser/core/records.js.map +0 -1
- package/dist/cjs/wit/wit-parser/core/types/records.js.map +0 -1
- package/dist/esm/sdk/utils/wit/codecs/decimal.js +0 -165
- package/dist/esm/sdk/utils/wit/codecs/decimal.js.map +0 -1
- package/dist/esm/sdk/utils/wit/codecs/enum.js +0 -104
- package/dist/esm/sdk/utils/wit/codecs/enum.js.map +0 -1
- package/dist/esm/sdk/utils/wit/codecs/integer.js +0 -167
- package/dist/esm/sdk/utils/wit/codecs/integer.js.map +0 -1
- package/dist/esm/sdk/utils/wit/codecs/s64.js +0 -65
- package/dist/esm/sdk/utils/wit/codecs/s64.js.map +0 -1
- package/dist/esm/sdk/utils/wit/codecs/u64.js +0 -63
- package/dist/esm/sdk/utils/wit/codecs/u64.js.map +0 -1
- package/dist/esm/wit/wit-parser/core/records.js +0 -73
- package/dist/esm/wit/wit-parser/core/records.js.map +0 -1
- package/dist/esm/wit/wit-parser/core/types/records.js +0 -2
- package/dist/esm/wit/wit-parser/core/types/records.js.map +0 -1
- package/dist/types/sdk/utils/wit/codecs/decimal.d.ts +0 -42
- package/dist/types/sdk/utils/wit/codecs/decimal.d.ts.map +0 -1
- package/dist/types/sdk/utils/wit/codecs/enum.d.ts +0 -49
- package/dist/types/sdk/utils/wit/codecs/enum.d.ts.map +0 -1
- package/dist/types/sdk/utils/wit/codecs/integer.d.ts +0 -36
- package/dist/types/sdk/utils/wit/codecs/integer.d.ts.map +0 -1
- package/dist/types/sdk/utils/wit/codecs/s64.d.ts +0 -23
- package/dist/types/sdk/utils/wit/codecs/s64.d.ts.map +0 -1
- package/dist/types/sdk/utils/wit/codecs/u64.d.ts +0 -23
- package/dist/types/sdk/utils/wit/codecs/u64.d.ts.map +0 -1
- package/dist/types/wit/wit-parser/core/records.d.ts +0 -4
- package/dist/types/wit/wit-parser/core/records.d.ts.map +0 -1
- package/dist/types/wit/wit-parser/core/types/records.d.ts +0 -51
- package/dist/types/wit/wit-parser/core/types/records.d.ts.map +0 -1
- package/src/sdk/test/e2e.test.ts +0 -194
- package/src/sdk/utils/wit/codecs/decimal.ts +0 -215
- package/src/sdk/utils/wit/codecs/enum.ts +0 -114
- package/src/sdk/utils/wit/codecs/integer.ts +0 -193
- package/src/sdk/utils/wit/codecs/s64.ts +0 -76
- package/src/sdk/utils/wit/codecs/u64.ts +0 -73
- package/src/wit/wit-parser/core/records.test.ts +0 -69
- package/src/wit/wit-parser/core/records.ts +0 -101
- package/src/wit/wit-parser/core/types/records.test-d.ts +0 -331
- package/src/wit/wit-parser/core/types/records.ts +0 -91
|
@@ -0,0 +1,399 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
IntegerCodec,
|
|
5
|
+
DecimalCodec,
|
|
6
|
+
U8Codec,
|
|
7
|
+
U16Codec,
|
|
8
|
+
U32Codec,
|
|
9
|
+
U64Codec,
|
|
10
|
+
S8Codec,
|
|
11
|
+
S16Codec,
|
|
12
|
+
S32Codec,
|
|
13
|
+
S64Codec,
|
|
14
|
+
} from "./numerics.js";
|
|
15
|
+
describe("numerics codecs", () => {
|
|
16
|
+
describe("IntegerCodec", () => {
|
|
17
|
+
it("decodes a positive integer wave struct", () => {
|
|
18
|
+
const v = IntegerCodec.decodeWave(
|
|
19
|
+
"{r0: 1, r1: 0, r2: 0, r3: 0, sign: plus}",
|
|
20
|
+
);
|
|
21
|
+
expect(v).toBe(1n);
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
it("decodes a negative integer wave struct", () => {
|
|
25
|
+
const v = IntegerCodec.decodeWave(
|
|
26
|
+
"{r0: 1, r1: 0, r2: 0, r3: 0, sign: minus}",
|
|
27
|
+
);
|
|
28
|
+
expect(v).toBe(-1n);
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
it("defaults r1..r3 to 0 when omitted", () => {
|
|
32
|
+
const v = IntegerCodec.decodeWave("{r0: 42, sign: plus}");
|
|
33
|
+
expect(v).toBe(42n);
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
it("accepts underscores in limb literals", () => {
|
|
37
|
+
const v = IntegerCodec.decodeWave("{r0: 1234, sign: plus}");
|
|
38
|
+
expect(v).toBe(1234n);
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
it("round-trips: decode -> encode -> decode", () => {
|
|
42
|
+
const wave = "{r0: 7, r1: 0, r2: 0, r3: 0, sign: plus}";
|
|
43
|
+
const js1 = IntegerCodec.decodeWave(wave);
|
|
44
|
+
const wave2 = IntegerCodec.encodeWave(js1);
|
|
45
|
+
const js2 = IntegerCodec.decodeWave(wave2);
|
|
46
|
+
expect(js2).toBe(js1);
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
it("round-trips large values within 128-bit magnitude", () => {
|
|
50
|
+
const values = [
|
|
51
|
+
0n,
|
|
52
|
+
1n,
|
|
53
|
+
-1n,
|
|
54
|
+
(1n << 32n) - 1n,
|
|
55
|
+
1n << 32n,
|
|
56
|
+
(1n << 96n) + 123n,
|
|
57
|
+
(1n << 127n) - 1n,
|
|
58
|
+
-((1n << 127n) - 1n),
|
|
59
|
+
];
|
|
60
|
+
|
|
61
|
+
for (const v of values) {
|
|
62
|
+
const wave = IntegerCodec.encodeWave(v);
|
|
63
|
+
const decoded = IntegerCodec.decodeWave(wave);
|
|
64
|
+
expect(decoded).toBe(v);
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
it("throws on missing r0", () => {
|
|
69
|
+
expect(() => IntegerCodec.decodeWave("{sign: plus}")).toThrow(
|
|
70
|
+
'missing required key "r0"',
|
|
71
|
+
);
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
it("throws on missing sign", () => {
|
|
75
|
+
expect(() => IntegerCodec.decodeWave("{r0: 1}")).toThrow(
|
|
76
|
+
'missing required key "sign"',
|
|
77
|
+
);
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
it("throws on invalid sign", () => {
|
|
81
|
+
expect(() => IntegerCodec.decodeWave("{r0: 1, sign: PLUS}")).toThrow(
|
|
82
|
+
"invalid sign",
|
|
83
|
+
);
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
it("throws on invalid limb literal", () => {
|
|
87
|
+
expect(() => IntegerCodec.decodeWave("{r0: 1.2, sign: plus}")).toThrow(
|
|
88
|
+
"invalid integer for r0",
|
|
89
|
+
);
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
it("throws when limb is out of u32 range", () => {
|
|
93
|
+
const tooBig = (1n << 32n).toString(); // 2^32
|
|
94
|
+
expect(() =>
|
|
95
|
+
IntegerCodec.decodeWave(`{r0: ${tooBig}, sign: plus}`),
|
|
96
|
+
).toThrow("r0 must be a u32");
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
it("throws on duplicate keys", () => {
|
|
100
|
+
expect(() =>
|
|
101
|
+
IntegerCodec.decodeWave("{r0: 1, r0: 2, sign: plus}"),
|
|
102
|
+
).toThrow('duplicate key "r0"');
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
it("throws on unexpected keys", () => {
|
|
106
|
+
expect(() =>
|
|
107
|
+
IntegerCodec.decodeWave("{r0: 1, r9: 2, sign: plus}"),
|
|
108
|
+
).toThrow('unexpected key "r9"');
|
|
109
|
+
});
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
describe("DecimalCodec", () => {
|
|
113
|
+
it("decodes a positive decimal wave struct into [coef, 18]", () => {
|
|
114
|
+
const v = DecimalCodec.decodeWave(
|
|
115
|
+
"{r0: 7, r1: 0, r2: 0, r3: 0, sign: plus}",
|
|
116
|
+
);
|
|
117
|
+
expect(v).toEqual([7n, 18]);
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
it("decodes a negative decimal wave struct", () => {
|
|
121
|
+
const v = DecimalCodec.decodeWave(
|
|
122
|
+
"{r0: 7, r1: 0, r2: 0, r3: 0, sign: minus}",
|
|
123
|
+
);
|
|
124
|
+
expect(v).toEqual([-7n, 18]);
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
it("defaults r1..r3 to 0 when omitted", () => {
|
|
128
|
+
const v = DecimalCodec.decodeWave("{r0: 123, sign: plus}");
|
|
129
|
+
expect(v).toEqual([123n, 18]);
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
it("accepts underscores in limb literals", () => {
|
|
133
|
+
const v = DecimalCodec.decodeWave("{r0: 1_234, sign: plus}");
|
|
134
|
+
expect(v).toEqual([1234n, 18]);
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
it("round-trips: decode -> encode -> decode", () => {
|
|
138
|
+
const wave = "{r0: 7, r1: 0, r2: 0, r3: 0, sign: plus}";
|
|
139
|
+
const js1 = DecimalCodec.decodeWave(wave);
|
|
140
|
+
const wave2 = DecimalCodec.encodeWave(js1);
|
|
141
|
+
const js2 = DecimalCodec.decodeWave(wave2);
|
|
142
|
+
expect(js2).toEqual(js1);
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
it("encodes by upscaling to 18 decimals", () => {
|
|
146
|
+
// [1, 0] => 1 * 10^18 in magnitude
|
|
147
|
+
const wave = DecimalCodec.encodeWave([1n, 0]);
|
|
148
|
+
const decoded = DecimalCodec.decodeWave(wave);
|
|
149
|
+
expect(decoded).toEqual([1n * 10n ** 18n, 18]);
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
it("throws on downscale requirement (scale > 18)", () => {
|
|
153
|
+
expect(() => DecimalCodec.encodeWave([1n, 19])).toThrow(
|
|
154
|
+
"cannot downscale",
|
|
155
|
+
);
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
it("throws on invalid sign", () => {
|
|
159
|
+
expect(() => DecimalCodec.decodeWave("{r0: 1, sign: nope}")).toThrow(
|
|
160
|
+
"invalid sign",
|
|
161
|
+
);
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
it("throws on invalid limb literal", () => {
|
|
165
|
+
expect(() => DecimalCodec.decodeWave("{r0: 1.2, sign: plus}")).toThrow(
|
|
166
|
+
"invalid integer for r0",
|
|
167
|
+
);
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
it("throws when limb is out of u64 range", () => {
|
|
171
|
+
const tooBig = (1n << 64n).toString(); // 2^64
|
|
172
|
+
expect(() =>
|
|
173
|
+
DecimalCodec.decodeWave(`{r0: ${tooBig}, sign: plus}`),
|
|
174
|
+
).toThrow("r0 must be a u64");
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
it("throws on missing r0", () => {
|
|
178
|
+
expect(() => DecimalCodec.decodeWave("{sign: plus}")).toThrow(
|
|
179
|
+
'missing required key "r0"',
|
|
180
|
+
);
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
it("throws on missing sign", () => {
|
|
184
|
+
expect(() => DecimalCodec.decodeWave("{r0: 1}")).toThrow(
|
|
185
|
+
'missing required key "sign"',
|
|
186
|
+
);
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
it("throws on duplicate keys", () => {
|
|
190
|
+
expect(() =>
|
|
191
|
+
DecimalCodec.decodeWave("{r0: 1, r0: 2, sign: plus}"),
|
|
192
|
+
).toThrow('duplicate key "r0"');
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
it("throws on unexpected keys", () => {
|
|
196
|
+
expect(() =>
|
|
197
|
+
DecimalCodec.decodeWave("{r0: 1, nope: 2, sign: plus}"),
|
|
198
|
+
).toThrow('unexpected key "nope"');
|
|
199
|
+
});
|
|
200
|
+
});
|
|
201
|
+
describe("IntegerCodec.encodeWave", () => {
|
|
202
|
+
it("encodes 0", () => {
|
|
203
|
+
expect(IntegerCodec.encodeWave(0n)).toBe(
|
|
204
|
+
"{r0: 0, r1: 0, r2: 0, r3: 0, sign: plus}",
|
|
205
|
+
);
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
it("encodes 1 and -1", () => {
|
|
209
|
+
expect(IntegerCodec.encodeWave(1n)).toBe(
|
|
210
|
+
"{r0: 1, r1: 0, r2: 0, r3: 0, sign: plus}",
|
|
211
|
+
);
|
|
212
|
+
expect(IntegerCodec.encodeWave(-1n)).toBe(
|
|
213
|
+
"{r0: 1, r1: 0, r2: 0, r3: 0, sign: minus}",
|
|
214
|
+
);
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
it("encodes 2^32 (checks limb carry)", () => {
|
|
218
|
+
// 2^32 => r0 = 0, r1 = 1
|
|
219
|
+
expect(IntegerCodec.encodeWave(1n << 32n)).toBe(
|
|
220
|
+
"{r0: 0, r1: 1, r2: 0, r3: 0, sign: plus}",
|
|
221
|
+
);
|
|
222
|
+
});
|
|
223
|
+
|
|
224
|
+
it("encodes a value spanning multiple limbs", () => {
|
|
225
|
+
// r0=5, r1=4, r2=3, r3=2
|
|
226
|
+
const v = (2n << 96n) | (3n << 64n) | (4n << 32n) | 5n;
|
|
227
|
+
|
|
228
|
+
expect(IntegerCodec.encodeWave(v)).toBe(
|
|
229
|
+
"{r0: 5, r1: 4, r2: 3, r3: 2, sign: plus}",
|
|
230
|
+
);
|
|
231
|
+
});
|
|
232
|
+
describe("DecimalCodec.encodeWave", () => {
|
|
233
|
+
it("encodes [0, 18]", () => {
|
|
234
|
+
expect(DecimalCodec.encodeWave([0n, 18])).toBe(
|
|
235
|
+
"{r0: 0, r1: 0, r2: 0, r3: 0, sign: plus}",
|
|
236
|
+
);
|
|
237
|
+
});
|
|
238
|
+
|
|
239
|
+
it("encodes sign for negative coefficients", () => {
|
|
240
|
+
expect(DecimalCodec.encodeWave([-7n, 18])).toBe(
|
|
241
|
+
"{r0: 7, r1: 0, r2: 0, r3: 0, sign: minus}",
|
|
242
|
+
);
|
|
243
|
+
});
|
|
244
|
+
|
|
245
|
+
it("upscales smaller scales to 18 and encodes limbs", () => {
|
|
246
|
+
// [1,0] => 1 * 10^18
|
|
247
|
+
// 10^18 in hex is 0x0de0b6b3a7640000 which fits in r0 (u64)
|
|
248
|
+
expect(DecimalCodec.encodeWave([1n, 0])).toBe(
|
|
249
|
+
"{r0: 1000000000000000000, r1: 0, r2: 0, r3: 0, sign: plus}",
|
|
250
|
+
);
|
|
251
|
+
});
|
|
252
|
+
|
|
253
|
+
it("encodes a decimal spanning multiple 64-bit limbs", () => {
|
|
254
|
+
// magnitude = (r3<<192) | (r2<<128) | (r1<<64) | r0
|
|
255
|
+
const wave = "{r0: 5, r1: 4, r2: 3, r3: 2, sign: plus}";
|
|
256
|
+
const decoded = DecimalCodec.decodeWave(wave);
|
|
257
|
+
expect(DecimalCodec.encodeWave(decoded)).toBe(wave);
|
|
258
|
+
});
|
|
259
|
+
});
|
|
260
|
+
});
|
|
261
|
+
});
|
|
262
|
+
|
|
263
|
+
describe("numerics: fixed-width integer codecs", () => {
|
|
264
|
+
it("returns number for <=32-bit and bigint for 64-bit", () => {
|
|
265
|
+
expect(typeof U8Codec.decodeWave("1")).toBe("number");
|
|
266
|
+
expect(typeof U16Codec.decodeWave("1")).toBe("number");
|
|
267
|
+
expect(typeof U32Codec.decodeWave("1")).toBe("number");
|
|
268
|
+
|
|
269
|
+
expect(typeof S8Codec.decodeWave("-1")).toBe("number");
|
|
270
|
+
expect(typeof S16Codec.decodeWave("-1")).toBe("number");
|
|
271
|
+
expect(typeof S32Codec.decodeWave("-1")).toBe("number");
|
|
272
|
+
|
|
273
|
+
expect(typeof U64Codec.decodeWave("1")).toBe("bigint");
|
|
274
|
+
expect(typeof S64Codec.decodeWave("-1")).toBe("bigint");
|
|
275
|
+
});
|
|
276
|
+
|
|
277
|
+
it("accepts underscores in wave literals", () => {
|
|
278
|
+
expect(U16Codec.decodeWave("65_535")).toBe(65535);
|
|
279
|
+
expect(U64Codec.decodeWave("18_446_744_073_709_551_615")).toBe(
|
|
280
|
+
18446744073709551615n,
|
|
281
|
+
);
|
|
282
|
+
});
|
|
283
|
+
|
|
284
|
+
describe("unsigned bounds", () => {
|
|
285
|
+
it("u8", () => {
|
|
286
|
+
expect(U8Codec.decodeWave("0")).toBe(0);
|
|
287
|
+
expect(U8Codec.decodeWave("255")).toBe(255);
|
|
288
|
+
|
|
289
|
+
expect(() => U8Codec.decodeWave("-1")).toThrow("u8 out of range");
|
|
290
|
+
expect(() => U8Codec.decodeWave("256")).toThrow("u8 out of range");
|
|
291
|
+
|
|
292
|
+
expect(U8Codec.encodeWave(0)).toBe("0");
|
|
293
|
+
expect(U8Codec.encodeWave(255)).toBe("255");
|
|
294
|
+
expect(() => U8Codec.encodeWave(256)).toThrow("u8 out of range");
|
|
295
|
+
});
|
|
296
|
+
|
|
297
|
+
it("u16", () => {
|
|
298
|
+
expect(U16Codec.decodeWave("0")).toBe(0);
|
|
299
|
+
expect(U16Codec.decodeWave("65535")).toBe(65535);
|
|
300
|
+
|
|
301
|
+
expect(() => U16Codec.decodeWave("-1")).toThrow("u16 out of range");
|
|
302
|
+
expect(() => U16Codec.decodeWave("65536")).toThrow("u16 out of range");
|
|
303
|
+
|
|
304
|
+
expect(U16Codec.encodeWave(65535)).toBe("65535");
|
|
305
|
+
});
|
|
306
|
+
|
|
307
|
+
it("u32", () => {
|
|
308
|
+
expect(U32Codec.decodeWave("0")).toBe(0);
|
|
309
|
+
expect(U32Codec.decodeWave("4294967295")).toBe(4294967295);
|
|
310
|
+
|
|
311
|
+
expect(() => U32Codec.decodeWave("-1")).toThrow("u32 out of range");
|
|
312
|
+
expect(() => U32Codec.decodeWave("4294967296")).toThrow(
|
|
313
|
+
"u32 out of range",
|
|
314
|
+
);
|
|
315
|
+
|
|
316
|
+
expect(U32Codec.encodeWave(4294967295)).toBe("4294967295");
|
|
317
|
+
});
|
|
318
|
+
|
|
319
|
+
it("u64", () => {
|
|
320
|
+
expect(U64Codec.decodeWave("0")).toBe(0n);
|
|
321
|
+
expect(U64Codec.decodeWave("18446744073709551615")).toBe(
|
|
322
|
+
18446744073709551615n,
|
|
323
|
+
);
|
|
324
|
+
|
|
325
|
+
expect(() => U64Codec.decodeWave("-1")).toThrow("u64 out of range");
|
|
326
|
+
expect(() => U64Codec.decodeWave("18446744073709551616")).toThrow(
|
|
327
|
+
"u64 out of range",
|
|
328
|
+
);
|
|
329
|
+
|
|
330
|
+
expect(U64Codec.encodeWave(18446744073709551615n)).toBe(
|
|
331
|
+
"18446744073709551615",
|
|
332
|
+
);
|
|
333
|
+
});
|
|
334
|
+
});
|
|
335
|
+
|
|
336
|
+
describe("signed bounds", () => {
|
|
337
|
+
it("s8", () => {
|
|
338
|
+
expect(S8Codec.decodeWave("-128")).toBe(-128);
|
|
339
|
+
expect(S8Codec.decodeWave("127")).toBe(127);
|
|
340
|
+
|
|
341
|
+
expect(() => S8Codec.decodeWave("-129")).toThrow("s8 out of range");
|
|
342
|
+
expect(() => S8Codec.decodeWave("128")).toThrow("s8 out of range");
|
|
343
|
+
});
|
|
344
|
+
|
|
345
|
+
it("s16", () => {
|
|
346
|
+
expect(S16Codec.decodeWave("-32768")).toBe(-32768);
|
|
347
|
+
expect(S16Codec.decodeWave("32767")).toBe(32767);
|
|
348
|
+
|
|
349
|
+
expect(() => S16Codec.decodeWave("-32769")).toThrow("s16 out of range");
|
|
350
|
+
expect(() => S16Codec.decodeWave("32768")).toThrow("s16 out of range");
|
|
351
|
+
});
|
|
352
|
+
|
|
353
|
+
it("s32", () => {
|
|
354
|
+
expect(S32Codec.decodeWave("-2147483648")).toBe(-2147483648);
|
|
355
|
+
expect(S32Codec.decodeWave("2147483647")).toBe(2147483647);
|
|
356
|
+
|
|
357
|
+
expect(() => S32Codec.decodeWave("-2147483649")).toThrow(
|
|
358
|
+
"s32 out of range",
|
|
359
|
+
);
|
|
360
|
+
expect(() => S32Codec.decodeWave("2147483648")).toThrow(
|
|
361
|
+
"s32 out of range",
|
|
362
|
+
);
|
|
363
|
+
});
|
|
364
|
+
|
|
365
|
+
it("s64", () => {
|
|
366
|
+
expect(S64Codec.decodeWave("-9223372036854775808")).toBe(
|
|
367
|
+
-9223372036854775808n,
|
|
368
|
+
);
|
|
369
|
+
expect(S64Codec.decodeWave("9223372036854775807")).toBe(
|
|
370
|
+
9223372036854775807n,
|
|
371
|
+
);
|
|
372
|
+
|
|
373
|
+
expect(() => S64Codec.decodeWave("-9223372036854775809")).toThrow(
|
|
374
|
+
"s64 out of range",
|
|
375
|
+
);
|
|
376
|
+
expect(() => S64Codec.decodeWave("9223372036854775808")).toThrow(
|
|
377
|
+
"s64 out of range",
|
|
378
|
+
);
|
|
379
|
+
});
|
|
380
|
+
});
|
|
381
|
+
|
|
382
|
+
it("throws on non-integer literals", () => {
|
|
383
|
+
expect(() => U32Codec.decodeWave("1.2")).toThrow("invalid integer: u32");
|
|
384
|
+
expect(() => S16Codec.decodeWave("NaN")).toThrow("invalid integer: s16");
|
|
385
|
+
expect(() => U64Codec.decodeWave("1e3")).toThrow("invalid integer: u64");
|
|
386
|
+
});
|
|
387
|
+
|
|
388
|
+
it("round-trips", () => {
|
|
389
|
+
const nums = [0, 1, 255, 65535, 12345];
|
|
390
|
+
for (const n of nums) {
|
|
391
|
+
expect(U16Codec.decodeWave(U16Codec.encodeWave(n))).toBe(n);
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
const bigs = [0n, 1n, 10n, 18446744073709551615n];
|
|
395
|
+
for (const b of bigs) {
|
|
396
|
+
expect(U64Codec.decodeWave(U64Codec.encodeWave(b))).toBe(b);
|
|
397
|
+
}
|
|
398
|
+
});
|
|
399
|
+
});
|
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
// numerics.ts
|
|
2
|
+
import { stripOuter, splitTopLevelComma, splitTopLevelColon } from "./util.js";
|
|
3
|
+
import type { Codec } from "./types.js";
|
|
4
|
+
|
|
5
|
+
type Decimal = [bigint, number];
|
|
6
|
+
|
|
7
|
+
const TARGET_SCALE = 18;
|
|
8
|
+
|
|
9
|
+
const U32_MAX = (1n << 32n) - 1n;
|
|
10
|
+
const U64_MAX = (1n << 64n) - 1n;
|
|
11
|
+
|
|
12
|
+
/* -------------------------------------------------------------------------- */
|
|
13
|
+
/* Utils */
|
|
14
|
+
/* -------------------------------------------------------------------------- */
|
|
15
|
+
|
|
16
|
+
function assertU32(x: bigint, ctx: string): bigint {
|
|
17
|
+
if (x < 0n || x > U32_MAX) {
|
|
18
|
+
throw new Error(`${ctx} must be a u32`);
|
|
19
|
+
}
|
|
20
|
+
return x;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function assertU64(x: bigint, ctx: string): bigint {
|
|
24
|
+
if (x < 0n || x > U64_MAX) {
|
|
25
|
+
throw new Error(`${ctx} must be a u64`);
|
|
26
|
+
}
|
|
27
|
+
return x;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function parseBigIntLiteral(expr: string, ctx: string): bigint {
|
|
31
|
+
const normalized = expr.trim().replace(/_/g, "");
|
|
32
|
+
if (!/^[+-]?\d+$/.test(normalized)) {
|
|
33
|
+
throw new Error(`invalid integer for ${ctx}: "${expr}"`);
|
|
34
|
+
}
|
|
35
|
+
return BigInt(normalized);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function parseIntNumberWave(expr: string, ctx: string): number {
|
|
39
|
+
const s = expr.trim().replace(/_/g, "");
|
|
40
|
+
if (!/^[+-]?\d+$/.test(s)) throw new Error(`invalid integer: ${ctx}`);
|
|
41
|
+
const n = Number(s);
|
|
42
|
+
if (!Number.isFinite(n) || !Number.isInteger(n))
|
|
43
|
+
throw new Error(`invalid integer: ${ctx}`);
|
|
44
|
+
return n;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function parseIntBigWave(expr: string, ctx: string): bigint {
|
|
48
|
+
const s = expr.trim().replace(/_/g, "");
|
|
49
|
+
if (!/^[+-]?\d+$/.test(s)) throw new Error(`invalid integer: ${ctx}`);
|
|
50
|
+
return BigInt(s);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function pow10n(n: number): bigint {
|
|
54
|
+
let p = 1n;
|
|
55
|
+
for (let i = 0; i < n; i++) p *= 10n;
|
|
56
|
+
return p;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/* -------------------------------------------------------------------------- */
|
|
60
|
+
/* Fixed-width integer scalars */
|
|
61
|
+
/* -------------------------------------------------------------------------- */
|
|
62
|
+
|
|
63
|
+
const U8_MIN = 0;
|
|
64
|
+
const U8_MAX_N = 255;
|
|
65
|
+
|
|
66
|
+
const U16_MIN = 0;
|
|
67
|
+
const U16_MAX_N = 65535;
|
|
68
|
+
|
|
69
|
+
const U32_MIN = 0;
|
|
70
|
+
const U32_MAX_N = 4294967295;
|
|
71
|
+
|
|
72
|
+
const S8_MIN = -128;
|
|
73
|
+
const S8_MAX_N = 127;
|
|
74
|
+
|
|
75
|
+
const S16_MIN = -32768;
|
|
76
|
+
const S16_MAX_N = 32767;
|
|
77
|
+
|
|
78
|
+
const S32_MIN = -2147483648;
|
|
79
|
+
const S32_MAX_N = 2147483647;
|
|
80
|
+
|
|
81
|
+
const U64_MAX_B = (1n << 64n) - 1n;
|
|
82
|
+
const S64_MIN_B = -(1n << 63n);
|
|
83
|
+
const S64_MAX_B = (1n << 63n) - 1n;
|
|
84
|
+
|
|
85
|
+
function makeNumberIntCodec(
|
|
86
|
+
name: string,
|
|
87
|
+
min: number,
|
|
88
|
+
max: number,
|
|
89
|
+
): Codec<number> {
|
|
90
|
+
return {
|
|
91
|
+
decodeWave(expr: string): number {
|
|
92
|
+
const n = parseIntNumberWave(expr, name);
|
|
93
|
+
if (n < min || n > max) throw new Error(`${name} out of range`);
|
|
94
|
+
return n;
|
|
95
|
+
},
|
|
96
|
+
encodeWave(value: number): string {
|
|
97
|
+
if (!Number.isFinite(value) || !Number.isInteger(value)) {
|
|
98
|
+
throw new Error(`${name} out of range`);
|
|
99
|
+
}
|
|
100
|
+
if (value < min || value > max) throw new Error(`${name} out of range`);
|
|
101
|
+
return String(value);
|
|
102
|
+
},
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function makeBigIntCodec(
|
|
107
|
+
name: string,
|
|
108
|
+
min: bigint,
|
|
109
|
+
max: bigint,
|
|
110
|
+
): Codec<bigint> {
|
|
111
|
+
return {
|
|
112
|
+
decodeWave(expr: string): bigint {
|
|
113
|
+
const n = parseIntBigWave(expr, name);
|
|
114
|
+
if (n < min || n > max) throw new Error(`${name} out of range`);
|
|
115
|
+
return n;
|
|
116
|
+
},
|
|
117
|
+
encodeWave(value: bigint): string {
|
|
118
|
+
if (value < min || value > max) throw new Error(`${name} out of range`);
|
|
119
|
+
return value.toString(10);
|
|
120
|
+
},
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// Unsigned
|
|
125
|
+
export const U8Codec = makeNumberIntCodec("u8", U8_MIN, U8_MAX_N);
|
|
126
|
+
export const U16Codec = makeNumberIntCodec("u16", U16_MIN, U16_MAX_N);
|
|
127
|
+
export const U32Codec = makeNumberIntCodec("u32", U32_MIN, U32_MAX_N);
|
|
128
|
+
export const U64Codec = makeBigIntCodec("u64", 0n, U64_MAX_B);
|
|
129
|
+
|
|
130
|
+
// Signed
|
|
131
|
+
export const S8Codec = makeNumberIntCodec("s8", S8_MIN, S8_MAX_N);
|
|
132
|
+
export const S16Codec = makeNumberIntCodec("s16", S16_MIN, S16_MAX_N);
|
|
133
|
+
export const S32Codec = makeNumberIntCodec("s32", S32_MIN, S32_MAX_N);
|
|
134
|
+
export const S64Codec = makeBigIntCodec("s64", S64_MIN_B, S64_MAX_B);
|
|
135
|
+
|
|
136
|
+
/* -------------------------------------------------------------------------- */
|
|
137
|
+
/* Integer (struct limbs) */
|
|
138
|
+
/* -------------------------------------------------------------------------- */
|
|
139
|
+
|
|
140
|
+
type IntegerWave = {
|
|
141
|
+
r0: bigint;
|
|
142
|
+
r1: bigint;
|
|
143
|
+
r2: bigint;
|
|
144
|
+
r3: bigint;
|
|
145
|
+
sign: "plus" | "minus";
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
function parseIntegerWave(expr: string): IntegerWave {
|
|
149
|
+
const { inner } = stripOuter(expr, "{", "}");
|
|
150
|
+
if (!inner) throw new Error("empty integer expression");
|
|
151
|
+
|
|
152
|
+
const parts = splitTopLevelComma(inner);
|
|
153
|
+
const seen = new Set<string>();
|
|
154
|
+
|
|
155
|
+
const out: Partial<IntegerWave> = { r1: 0n, r2: 0n, r3: 0n };
|
|
156
|
+
|
|
157
|
+
for (const part of parts) {
|
|
158
|
+
const [k, v] = splitTopLevelColon(part);
|
|
159
|
+
if (seen.has(k)) throw new Error(`duplicate key "${k}"`);
|
|
160
|
+
seen.add(k);
|
|
161
|
+
|
|
162
|
+
switch (k) {
|
|
163
|
+
case "r0":
|
|
164
|
+
case "r1":
|
|
165
|
+
case "r2":
|
|
166
|
+
case "r3":
|
|
167
|
+
(out as any)[k] = assertU32(parseBigIntLiteral(v, k), k);
|
|
168
|
+
break;
|
|
169
|
+
case "sign":
|
|
170
|
+
if (v !== "plus" && v !== "minus") {
|
|
171
|
+
throw new Error(`invalid sign "${v}"`);
|
|
172
|
+
}
|
|
173
|
+
out.sign = v;
|
|
174
|
+
break;
|
|
175
|
+
default:
|
|
176
|
+
throw new Error(`unexpected key "${k}"`);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
if (out.r0 === undefined) throw new Error(`missing required key "r0"`);
|
|
181
|
+
if (!out.sign) throw new Error(`missing required key "sign"`);
|
|
182
|
+
|
|
183
|
+
return out as IntegerWave;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
function integerWaveToJs(w: IntegerWave): bigint {
|
|
187
|
+
const value = (w.r3 << 96n) | (w.r2 << 64n) | (w.r1 << 32n) | w.r0;
|
|
188
|
+
return w.sign === "minus" ? -value : value;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
function integerJsToWave(v: bigint): IntegerWave {
|
|
192
|
+
const sign = v < 0n ? "minus" : "plus";
|
|
193
|
+
const abs = v < 0n ? -v : v;
|
|
194
|
+
|
|
195
|
+
return {
|
|
196
|
+
r0: abs & U32_MAX,
|
|
197
|
+
r1: (abs >> 32n) & U32_MAX,
|
|
198
|
+
r2: (abs >> 64n) & U32_MAX,
|
|
199
|
+
r3: (abs >> 96n) & U32_MAX,
|
|
200
|
+
sign,
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
export const IntegerCodec: Codec<bigint> = {
|
|
205
|
+
decodeWave(expr: string) {
|
|
206
|
+
return integerWaveToJs(parseIntegerWave(expr));
|
|
207
|
+
},
|
|
208
|
+
|
|
209
|
+
encodeWave(value: bigint) {
|
|
210
|
+
const w = integerJsToWave(value);
|
|
211
|
+
return `{r0: ${w.r0}, r1: ${w.r1}, r2: ${w.r2}, r3: ${w.r3}, sign: ${w.sign}}`;
|
|
212
|
+
},
|
|
213
|
+
};
|
|
214
|
+
|
|
215
|
+
/* -------------------------------------------------------------------------- */
|
|
216
|
+
/* Decimal (struct limbs) */
|
|
217
|
+
/* -------------------------------------------------------------------------- */
|
|
218
|
+
|
|
219
|
+
type DecimalWave = {
|
|
220
|
+
r0: bigint;
|
|
221
|
+
r1: bigint;
|
|
222
|
+
r2: bigint;
|
|
223
|
+
r3: bigint;
|
|
224
|
+
sign: "plus" | "minus";
|
|
225
|
+
};
|
|
226
|
+
|
|
227
|
+
function parseDecimalWave(expr: string): DecimalWave {
|
|
228
|
+
const { inner } = stripOuter(expr, "{", "}");
|
|
229
|
+
if (!inner) throw new Error("empty decimal expression");
|
|
230
|
+
|
|
231
|
+
const parts = splitTopLevelComma(inner);
|
|
232
|
+
const seen = new Set<string>();
|
|
233
|
+
|
|
234
|
+
const out: Partial<DecimalWave> = { r1: 0n, r2: 0n, r3: 0n };
|
|
235
|
+
|
|
236
|
+
for (const part of parts) {
|
|
237
|
+
const [k, v] = splitTopLevelColon(part);
|
|
238
|
+
if (seen.has(k)) throw new Error(`duplicate key "${k}"`);
|
|
239
|
+
seen.add(k);
|
|
240
|
+
|
|
241
|
+
switch (k) {
|
|
242
|
+
case "r0":
|
|
243
|
+
case "r1":
|
|
244
|
+
case "r2":
|
|
245
|
+
case "r3":
|
|
246
|
+
(out as any)[k] = assertU64(parseBigIntLiteral(v, k), k);
|
|
247
|
+
break;
|
|
248
|
+
case "sign":
|
|
249
|
+
if (v !== "plus" && v !== "minus") {
|
|
250
|
+
throw new Error(`invalid sign "${v}"`);
|
|
251
|
+
}
|
|
252
|
+
out.sign = v;
|
|
253
|
+
break;
|
|
254
|
+
default:
|
|
255
|
+
throw new Error(`unexpected key "${k}"`);
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
if (out.r0 === undefined) throw new Error(`missing required key "r0"`);
|
|
260
|
+
if (!out.sign) throw new Error(`missing required key "sign"`);
|
|
261
|
+
|
|
262
|
+
return out as DecimalWave;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
function decimalWaveToJs(w: DecimalWave): Decimal {
|
|
266
|
+
const mag = (w.r3 << 192n) | (w.r2 << 128n) | (w.r1 << 64n) | w.r0;
|
|
267
|
+
|
|
268
|
+
const signed = w.sign === "minus" ? -mag : mag;
|
|
269
|
+
return [signed, TARGET_SCALE];
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
function decimalJsToWave([coef, scale]: Decimal): DecimalWave {
|
|
273
|
+
if (scale > TARGET_SCALE) {
|
|
274
|
+
throw new Error(
|
|
275
|
+
`cannot downscale decimal from ${scale} to ${TARGET_SCALE}`,
|
|
276
|
+
);
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
const sign = coef < 0n ? "minus" : "plus";
|
|
280
|
+
const abs = coef < 0n ? -coef : coef;
|
|
281
|
+
const scaled = abs * pow10n(TARGET_SCALE - scale);
|
|
282
|
+
|
|
283
|
+
const r0 = scaled & U64_MAX;
|
|
284
|
+
const r1 = (scaled >> 64n) & U64_MAX;
|
|
285
|
+
const r2 = (scaled >> 128n) & U64_MAX;
|
|
286
|
+
const r3 = (scaled >> 192n) & U64_MAX;
|
|
287
|
+
|
|
288
|
+
if (scaled >> 256n !== 0n) {
|
|
289
|
+
throw new Error("decimal magnitude does not fit in 256 bits");
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
return { r0, r1, r2, r3, sign };
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
export const DecimalCodec: Codec<Decimal> = {
|
|
296
|
+
decodeWave(expr: string) {
|
|
297
|
+
return decimalWaveToJs(parseDecimalWave(expr));
|
|
298
|
+
},
|
|
299
|
+
|
|
300
|
+
encodeWave(value: Decimal) {
|
|
301
|
+
const w = decimalJsToWave(value);
|
|
302
|
+
return `{r0: ${w.r0}, r1: ${w.r1}, r2: ${w.r2}, r3: ${w.r3}, sign: ${w.sign}}`;
|
|
303
|
+
},
|
|
304
|
+
};
|