links-notation 0.22.0 → 0.24.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/README.md +3 -0
- package/dist/index.js +904 -109
- package/index.d.ts +96 -0
- package/package.json +4 -4
- package/src/Binary.js +772 -0
- package/src/Link.js +3 -47
- package/src/ReferenceLiteral.js +66 -0
- package/src/grammar.pegjs +12 -2
- package/src/index.js +16 -0
- package/src/parser-generated.js +262 -89
- package/tests/Binary.test.js +165 -0
- package/tests/EmptyReference.test.js +2 -2
- package/tests/ReferenceFidelity.test.js +99 -0
- package/bun.lock +0 -213
package/dist/index.js
CHANGED
|
@@ -1,3 +1,49 @@
|
|
|
1
|
+
// src/ReferenceLiteral.js
|
|
2
|
+
function hasReferenceLiteralPrefix(text, start = 0) {
|
|
3
|
+
return /^~[0-9]+\{/.test(text.slice(start));
|
|
4
|
+
}
|
|
5
|
+
function encodeReferenceLiteral(text) {
|
|
6
|
+
if (typeof text !== "string" || !text.isWellFormed()) {
|
|
7
|
+
throw new TypeError("Reference must be well-formed Unicode text");
|
|
8
|
+
}
|
|
9
|
+
const hex = Array.from(new TextEncoder().encode(text), (byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
10
|
+
return `~1{${hex}}`;
|
|
11
|
+
}
|
|
12
|
+
function decodeReferenceLiteral(literal) {
|
|
13
|
+
const match = /^~([0-9]+)\{([0-9a-fA-F]*)\}$/.exec(literal);
|
|
14
|
+
if (!match || match[0] !== literal || match[1] !== "1" || match[2].length % 2 !== 0) {
|
|
15
|
+
throw new TypeError("Invalid or unsupported reference literal (expected ~1{UTF-8 hex})");
|
|
16
|
+
}
|
|
17
|
+
return new TextDecoder("utf-8", { fatal: true, ignoreBOM: true }).decode(Uint8Array.from(match[2].match(/../g) ?? [], (hex) => parseInt(hex, 16)));
|
|
18
|
+
}
|
|
19
|
+
function formatReference(text) {
|
|
20
|
+
if (typeof text !== "string" || !text.isWellFormed()) {
|
|
21
|
+
throw new TypeError("Reference must be well-formed Unicode text");
|
|
22
|
+
}
|
|
23
|
+
if (!text || /[\u0000-\u001f\u007f]/u.test(text)) {
|
|
24
|
+
return encodeReferenceLiteral(text);
|
|
25
|
+
}
|
|
26
|
+
if (!text.startsWith("#") && !/^~[0-9]+\{/.test(text) && !/[\p{White_Space}\ufeff():"'`]/u.test(text)) {
|
|
27
|
+
return text;
|
|
28
|
+
}
|
|
29
|
+
let choice = null;
|
|
30
|
+
for (const quote of ["'", '"', "`"]) {
|
|
31
|
+
if (text.startsWith(quote))
|
|
32
|
+
continue;
|
|
33
|
+
let longest = 0;
|
|
34
|
+
let run = 0;
|
|
35
|
+
for (const character of text) {
|
|
36
|
+
run = character === quote ? run + 1 : 0;
|
|
37
|
+
longest = Math.max(longest, run);
|
|
38
|
+
}
|
|
39
|
+
const count = longest + 1 | 1;
|
|
40
|
+
if (choice === null || count < choice.count)
|
|
41
|
+
choice = { quote, count };
|
|
42
|
+
}
|
|
43
|
+
const delimiter = choice.quote.repeat(choice.count);
|
|
44
|
+
return delimiter + text + delimiter;
|
|
45
|
+
}
|
|
46
|
+
|
|
1
47
|
// src/Link.js
|
|
2
48
|
class Link {
|
|
3
49
|
constructor(id = null, values = null) {
|
|
@@ -39,26 +85,7 @@ class Link {
|
|
|
39
85
|
if (reference === null || reference === undefined) {
|
|
40
86
|
return "";
|
|
41
87
|
}
|
|
42
|
-
|
|
43
|
-
return '""';
|
|
44
|
-
}
|
|
45
|
-
const hasSingleQuote = reference.includes("'");
|
|
46
|
-
const hasDoubleQuote = reference.includes('"');
|
|
47
|
-
const needsQuoting = reference.startsWith("#") || reference.includes(":") || reference.includes("(") || reference.includes(")") || reference.includes(" ") || reference.includes("\t") || reference.includes(`
|
|
48
|
-
`) || reference.includes("\r") || hasDoubleQuote || hasSingleQuote;
|
|
49
|
-
if (hasSingleQuote && hasDoubleQuote) {
|
|
50
|
-
return `'${reference.replace(/'/g, "\\'")}'`;
|
|
51
|
-
}
|
|
52
|
-
if (hasDoubleQuote) {
|
|
53
|
-
return `'${reference}'`;
|
|
54
|
-
}
|
|
55
|
-
if (hasSingleQuote) {
|
|
56
|
-
return `"${reference}"`;
|
|
57
|
-
}
|
|
58
|
-
if (needsQuoting) {
|
|
59
|
-
return `'${reference}'`;
|
|
60
|
-
}
|
|
61
|
-
return reference;
|
|
88
|
+
return formatReference(reference);
|
|
62
89
|
}
|
|
63
90
|
toLinkOrIdString() {
|
|
64
91
|
if (!this.values || this.values.length === 0) {
|
|
@@ -631,14 +658,19 @@ function peg$parse(input, options) {
|
|
|
631
658
|
const peg$c0 = "(";
|
|
632
659
|
const peg$c1 = ")";
|
|
633
660
|
const peg$c2 = ":";
|
|
634
|
-
const peg$c3 =
|
|
635
|
-
const peg$c4 = "
|
|
636
|
-
const peg$c5 = "
|
|
637
|
-
const peg$c6 = "
|
|
661
|
+
const peg$c3 = "~";
|
|
662
|
+
const peg$c4 = "{";
|
|
663
|
+
const peg$c5 = "}";
|
|
664
|
+
const peg$c6 = '"';
|
|
665
|
+
const peg$c7 = "'";
|
|
666
|
+
const peg$c8 = "`";
|
|
667
|
+
const peg$c9 = " ";
|
|
638
668
|
const peg$r0 = /^[ \t]/;
|
|
639
669
|
const peg$r1 = /^[\r\n]/;
|
|
640
|
-
const peg$r2 = /^[
|
|
641
|
-
const peg$r3 = /^[^ \t\n
|
|
670
|
+
const peg$r2 = /^[0-9]/;
|
|
671
|
+
const peg$r3 = /^[^} \t\r\n()]/;
|
|
672
|
+
const peg$r4 = /^[ \t\n\r]/;
|
|
673
|
+
const peg$r5 = /^[^ \t\n\r(:)]/;
|
|
642
674
|
const peg$e0 = peg$classExpectation([" ", "\t"], false, false, false);
|
|
643
675
|
const peg$e1 = peg$classExpectation(["\r", `
|
|
644
676
|
`], false, false, false);
|
|
@@ -646,13 +678,19 @@ function peg$parse(input, options) {
|
|
|
646
678
|
const peg$e3 = peg$literalExpectation("(", false);
|
|
647
679
|
const peg$e4 = peg$literalExpectation(")", false);
|
|
648
680
|
const peg$e5 = peg$literalExpectation(":", false);
|
|
649
|
-
const peg$e6 = peg$literalExpectation(
|
|
650
|
-
const peg$e7 = peg$
|
|
651
|
-
const peg$e8 = peg$literalExpectation("
|
|
652
|
-
const peg$e9 = peg$
|
|
653
|
-
|
|
681
|
+
const peg$e6 = peg$literalExpectation("~", false);
|
|
682
|
+
const peg$e7 = peg$classExpectation([["0", "9"]], false, false, false);
|
|
683
|
+
const peg$e8 = peg$literalExpectation("{", false);
|
|
684
|
+
const peg$e9 = peg$classExpectation(["}", " ", "\t", "\r", `
|
|
685
|
+
`, "(", ")"], true, false, false);
|
|
686
|
+
const peg$e10 = peg$literalExpectation("}", false);
|
|
687
|
+
const peg$e11 = peg$literalExpectation('"', false);
|
|
688
|
+
const peg$e12 = peg$literalExpectation("'", false);
|
|
689
|
+
const peg$e13 = peg$literalExpectation("`", false);
|
|
690
|
+
const peg$e14 = peg$literalExpectation(" ", false);
|
|
691
|
+
const peg$e15 = peg$classExpectation([" ", "\t", `
|
|
654
692
|
`, "\r"], false, false, false);
|
|
655
|
-
const peg$
|
|
693
|
+
const peg$e16 = peg$classExpectation([" ", "\t", `
|
|
656
694
|
`, "\r", "(", ":", ")"], true, false, false);
|
|
657
695
|
function peg$f0() {
|
|
658
696
|
return resetState();
|
|
@@ -749,10 +787,19 @@ function peg$parse(input, options) {
|
|
|
749
787
|
function peg$f28(id) {
|
|
750
788
|
return { id, values: [] };
|
|
751
789
|
}
|
|
752
|
-
function peg$f29(
|
|
790
|
+
function peg$f29() {
|
|
791
|
+
return hasReferenceLiteralPrefix(input, offset());
|
|
792
|
+
}
|
|
793
|
+
function peg$f30(literal) {
|
|
794
|
+
return decodeReferenceLiteral(literal);
|
|
795
|
+
}
|
|
796
|
+
function peg$f31() {
|
|
797
|
+
return !hasReferenceLiteralPrefix(input, offset());
|
|
798
|
+
}
|
|
799
|
+
function peg$f32(chars) {
|
|
753
800
|
return chars.join("");
|
|
754
801
|
}
|
|
755
|
-
function peg$
|
|
802
|
+
function peg$f33() {
|
|
756
803
|
const pos = offset();
|
|
757
804
|
const result = parseQuotedStringAt(input, pos, '"');
|
|
758
805
|
if (result) {
|
|
@@ -762,19 +809,19 @@ function peg$parse(input, options) {
|
|
|
762
809
|
}
|
|
763
810
|
return false;
|
|
764
811
|
}
|
|
765
|
-
function peg$
|
|
812
|
+
function peg$f34(chars) {
|
|
766
813
|
return parsedValue;
|
|
767
814
|
}
|
|
768
|
-
function peg$
|
|
815
|
+
function peg$f35(c, cs) {
|
|
769
816
|
return [c].concat(cs).join("");
|
|
770
817
|
}
|
|
771
|
-
function peg$
|
|
818
|
+
function peg$f36() {
|
|
772
819
|
return parsedLength > 1 && (parsedLength--, true);
|
|
773
820
|
}
|
|
774
|
-
function peg$
|
|
821
|
+
function peg$f37(c) {
|
|
775
822
|
return c;
|
|
776
823
|
}
|
|
777
|
-
function peg$
|
|
824
|
+
function peg$f38() {
|
|
778
825
|
const pos = offset();
|
|
779
826
|
const result = parseQuotedStringAt(input, pos, "'");
|
|
780
827
|
if (result) {
|
|
@@ -784,19 +831,19 @@ function peg$parse(input, options) {
|
|
|
784
831
|
}
|
|
785
832
|
return false;
|
|
786
833
|
}
|
|
787
|
-
function peg$
|
|
834
|
+
function peg$f39(chars) {
|
|
788
835
|
return parsedValue;
|
|
789
836
|
}
|
|
790
|
-
function peg$
|
|
837
|
+
function peg$f40(c, cs) {
|
|
791
838
|
return [c].concat(cs).join("");
|
|
792
839
|
}
|
|
793
|
-
function peg$
|
|
840
|
+
function peg$f41() {
|
|
794
841
|
return parsedLength > 1 && (parsedLength--, true);
|
|
795
842
|
}
|
|
796
|
-
function peg$
|
|
843
|
+
function peg$f42(c) {
|
|
797
844
|
return c;
|
|
798
845
|
}
|
|
799
|
-
function peg$
|
|
846
|
+
function peg$f43() {
|
|
800
847
|
const pos = offset();
|
|
801
848
|
const result = parseQuotedStringAt(input, pos, "`");
|
|
802
849
|
if (result) {
|
|
@@ -806,34 +853,34 @@ function peg$parse(input, options) {
|
|
|
806
853
|
}
|
|
807
854
|
return false;
|
|
808
855
|
}
|
|
809
|
-
function peg$
|
|
856
|
+
function peg$f44(chars) {
|
|
810
857
|
return parsedValue;
|
|
811
858
|
}
|
|
812
|
-
function peg$
|
|
859
|
+
function peg$f45(c, cs) {
|
|
813
860
|
return [c].concat(cs).join("");
|
|
814
861
|
}
|
|
815
|
-
function peg$
|
|
862
|
+
function peg$f46() {
|
|
816
863
|
return parsedLength > 1 && (parsedLength--, true);
|
|
817
864
|
}
|
|
818
|
-
function peg$
|
|
865
|
+
function peg$f47(c) {
|
|
819
866
|
return c;
|
|
820
867
|
}
|
|
821
|
-
function peg$
|
|
868
|
+
function peg$f48() {
|
|
822
869
|
return indentationStack.slice();
|
|
823
870
|
}
|
|
824
|
-
function peg$
|
|
871
|
+
function peg$f49(spaces) {
|
|
825
872
|
setBaseIndentation(spaces);
|
|
826
873
|
}
|
|
827
|
-
function peg$
|
|
874
|
+
function peg$f50(spaces) {
|
|
828
875
|
return normalizeIndentation(spaces) > getCurrentIndentation();
|
|
829
876
|
}
|
|
830
|
-
function peg$
|
|
877
|
+
function peg$f51(spaces) {
|
|
831
878
|
pushIndentation(spaces);
|
|
832
879
|
}
|
|
833
|
-
function peg$
|
|
880
|
+
function peg$f52(spaces) {
|
|
834
881
|
return checkIndentation(spaces);
|
|
835
882
|
}
|
|
836
|
-
function peg$
|
|
883
|
+
function peg$f53() {
|
|
837
884
|
return isInsideNestedContext();
|
|
838
885
|
}
|
|
839
886
|
let peg$currPos = options.peg$currPos | 0;
|
|
@@ -1680,30 +1727,198 @@ function peg$parse(input, options) {
|
|
|
1680
1727
|
}
|
|
1681
1728
|
function peg$parsereference() {
|
|
1682
1729
|
let s0;
|
|
1683
|
-
s0 = peg$
|
|
1730
|
+
s0 = peg$parsereferenceLiteral();
|
|
1684
1731
|
if (s0 === peg$FAILED) {
|
|
1685
|
-
s0 = peg$
|
|
1732
|
+
s0 = peg$parsequotedReference();
|
|
1733
|
+
if (s0 === peg$FAILED) {
|
|
1734
|
+
s0 = peg$parsesimpleReference();
|
|
1735
|
+
}
|
|
1686
1736
|
}
|
|
1687
1737
|
return s0;
|
|
1688
1738
|
}
|
|
1689
|
-
function peg$
|
|
1690
|
-
let s0, s1, s2;
|
|
1739
|
+
function peg$parsereferenceLiteral() {
|
|
1740
|
+
let s0, s1, s2, s3, s4, s5, s6, s7, s8, s9;
|
|
1691
1741
|
s0 = peg$currPos;
|
|
1692
|
-
s1 =
|
|
1693
|
-
|
|
1742
|
+
s1 = peg$currPos;
|
|
1743
|
+
peg$silentFails++;
|
|
1744
|
+
if (input.charCodeAt(peg$currPos) === 126) {
|
|
1745
|
+
s2 = peg$c3;
|
|
1746
|
+
peg$currPos++;
|
|
1747
|
+
} else {
|
|
1748
|
+
s2 = peg$FAILED;
|
|
1749
|
+
if (peg$silentFails === 0) {
|
|
1750
|
+
peg$fail(peg$e6);
|
|
1751
|
+
}
|
|
1752
|
+
}
|
|
1753
|
+
peg$silentFails--;
|
|
1694
1754
|
if (s2 !== peg$FAILED) {
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1755
|
+
peg$currPos = s1;
|
|
1756
|
+
s1 = undefined;
|
|
1757
|
+
} else {
|
|
1758
|
+
s1 = peg$FAILED;
|
|
1759
|
+
}
|
|
1760
|
+
if (s1 !== peg$FAILED) {
|
|
1761
|
+
peg$savedPos = peg$currPos;
|
|
1762
|
+
s2 = peg$f29();
|
|
1763
|
+
if (s2) {
|
|
1764
|
+
s2 = undefined;
|
|
1765
|
+
} else {
|
|
1766
|
+
s2 = peg$FAILED;
|
|
1767
|
+
}
|
|
1768
|
+
if (s2 !== peg$FAILED) {
|
|
1769
|
+
s3 = peg$currPos;
|
|
1770
|
+
s4 = peg$currPos;
|
|
1771
|
+
if (input.charCodeAt(peg$currPos) === 126) {
|
|
1772
|
+
s5 = peg$c3;
|
|
1773
|
+
peg$currPos++;
|
|
1774
|
+
} else {
|
|
1775
|
+
s5 = peg$FAILED;
|
|
1776
|
+
if (peg$silentFails === 0) {
|
|
1777
|
+
peg$fail(peg$e6);
|
|
1778
|
+
}
|
|
1779
|
+
}
|
|
1780
|
+
if (s5 !== peg$FAILED) {
|
|
1781
|
+
s6 = [];
|
|
1782
|
+
s7 = input.charAt(peg$currPos);
|
|
1783
|
+
if (peg$r2.test(s7)) {
|
|
1784
|
+
peg$currPos++;
|
|
1785
|
+
} else {
|
|
1786
|
+
s7 = peg$FAILED;
|
|
1787
|
+
if (peg$silentFails === 0) {
|
|
1788
|
+
peg$fail(peg$e7);
|
|
1789
|
+
}
|
|
1790
|
+
}
|
|
1791
|
+
if (s7 !== peg$FAILED) {
|
|
1792
|
+
while (s7 !== peg$FAILED) {
|
|
1793
|
+
s6.push(s7);
|
|
1794
|
+
s7 = input.charAt(peg$currPos);
|
|
1795
|
+
if (peg$r2.test(s7)) {
|
|
1796
|
+
peg$currPos++;
|
|
1797
|
+
} else {
|
|
1798
|
+
s7 = peg$FAILED;
|
|
1799
|
+
if (peg$silentFails === 0) {
|
|
1800
|
+
peg$fail(peg$e7);
|
|
1801
|
+
}
|
|
1802
|
+
}
|
|
1803
|
+
}
|
|
1804
|
+
} else {
|
|
1805
|
+
s6 = peg$FAILED;
|
|
1806
|
+
}
|
|
1807
|
+
if (s6 !== peg$FAILED) {
|
|
1808
|
+
if (input.charCodeAt(peg$currPos) === 123) {
|
|
1809
|
+
s7 = peg$c4;
|
|
1810
|
+
peg$currPos++;
|
|
1811
|
+
} else {
|
|
1812
|
+
s7 = peg$FAILED;
|
|
1813
|
+
if (peg$silentFails === 0) {
|
|
1814
|
+
peg$fail(peg$e8);
|
|
1815
|
+
}
|
|
1816
|
+
}
|
|
1817
|
+
if (s7 !== peg$FAILED) {
|
|
1818
|
+
s8 = [];
|
|
1819
|
+
s9 = input.charAt(peg$currPos);
|
|
1820
|
+
if (peg$r3.test(s9)) {
|
|
1821
|
+
peg$currPos++;
|
|
1822
|
+
} else {
|
|
1823
|
+
s9 = peg$FAILED;
|
|
1824
|
+
if (peg$silentFails === 0) {
|
|
1825
|
+
peg$fail(peg$e9);
|
|
1826
|
+
}
|
|
1827
|
+
}
|
|
1828
|
+
while (s9 !== peg$FAILED) {
|
|
1829
|
+
s8.push(s9);
|
|
1830
|
+
s9 = input.charAt(peg$currPos);
|
|
1831
|
+
if (peg$r3.test(s9)) {
|
|
1832
|
+
peg$currPos++;
|
|
1833
|
+
} else {
|
|
1834
|
+
s9 = peg$FAILED;
|
|
1835
|
+
if (peg$silentFails === 0) {
|
|
1836
|
+
peg$fail(peg$e9);
|
|
1837
|
+
}
|
|
1838
|
+
}
|
|
1839
|
+
}
|
|
1840
|
+
if (input.charCodeAt(peg$currPos) === 125) {
|
|
1841
|
+
s9 = peg$c5;
|
|
1842
|
+
peg$currPos++;
|
|
1843
|
+
} else {
|
|
1844
|
+
s9 = peg$FAILED;
|
|
1845
|
+
if (peg$silentFails === 0) {
|
|
1846
|
+
peg$fail(peg$e10);
|
|
1847
|
+
}
|
|
1848
|
+
}
|
|
1849
|
+
if (s9 !== peg$FAILED) {
|
|
1850
|
+
s5 = [s5, s6, s7, s8, s9];
|
|
1851
|
+
s4 = s5;
|
|
1852
|
+
} else {
|
|
1853
|
+
peg$currPos = s4;
|
|
1854
|
+
s4 = peg$FAILED;
|
|
1855
|
+
}
|
|
1856
|
+
} else {
|
|
1857
|
+
peg$currPos = s4;
|
|
1858
|
+
s4 = peg$FAILED;
|
|
1859
|
+
}
|
|
1860
|
+
} else {
|
|
1861
|
+
peg$currPos = s4;
|
|
1862
|
+
s4 = peg$FAILED;
|
|
1863
|
+
}
|
|
1864
|
+
} else {
|
|
1865
|
+
peg$currPos = s4;
|
|
1866
|
+
s4 = peg$FAILED;
|
|
1867
|
+
}
|
|
1868
|
+
if (s4 !== peg$FAILED) {
|
|
1869
|
+
s3 = input.substring(s3, peg$currPos);
|
|
1870
|
+
} else {
|
|
1871
|
+
s3 = s4;
|
|
1872
|
+
}
|
|
1873
|
+
if (s3 !== peg$FAILED) {
|
|
1874
|
+
peg$savedPos = s0;
|
|
1875
|
+
s0 = peg$f30(s3);
|
|
1876
|
+
} else {
|
|
1877
|
+
peg$currPos = s0;
|
|
1878
|
+
s0 = peg$FAILED;
|
|
1879
|
+
}
|
|
1880
|
+
} else {
|
|
1881
|
+
peg$currPos = s0;
|
|
1882
|
+
s0 = peg$FAILED;
|
|
1698
1883
|
}
|
|
1884
|
+
} else {
|
|
1885
|
+
peg$currPos = s0;
|
|
1886
|
+
s0 = peg$FAILED;
|
|
1887
|
+
}
|
|
1888
|
+
return s0;
|
|
1889
|
+
}
|
|
1890
|
+
function peg$parsesimpleReference() {
|
|
1891
|
+
let s0, s1, s2, s3;
|
|
1892
|
+
s0 = peg$currPos;
|
|
1893
|
+
peg$savedPos = peg$currPos;
|
|
1894
|
+
s1 = peg$f31();
|
|
1895
|
+
if (s1) {
|
|
1896
|
+
s1 = undefined;
|
|
1699
1897
|
} else {
|
|
1700
1898
|
s1 = peg$FAILED;
|
|
1701
1899
|
}
|
|
1702
1900
|
if (s1 !== peg$FAILED) {
|
|
1703
|
-
|
|
1704
|
-
|
|
1901
|
+
s2 = [];
|
|
1902
|
+
s3 = peg$parsereferenceSymbol();
|
|
1903
|
+
if (s3 !== peg$FAILED) {
|
|
1904
|
+
while (s3 !== peg$FAILED) {
|
|
1905
|
+
s2.push(s3);
|
|
1906
|
+
s3 = peg$parsereferenceSymbol();
|
|
1907
|
+
}
|
|
1908
|
+
} else {
|
|
1909
|
+
s2 = peg$FAILED;
|
|
1910
|
+
}
|
|
1911
|
+
if (s2 !== peg$FAILED) {
|
|
1912
|
+
peg$savedPos = s0;
|
|
1913
|
+
s0 = peg$f32(s2);
|
|
1914
|
+
} else {
|
|
1915
|
+
peg$currPos = s0;
|
|
1916
|
+
s0 = peg$FAILED;
|
|
1917
|
+
}
|
|
1918
|
+
} else {
|
|
1919
|
+
peg$currPos = s0;
|
|
1920
|
+
s0 = peg$FAILED;
|
|
1705
1921
|
}
|
|
1706
|
-
s0 = s1;
|
|
1707
1922
|
return s0;
|
|
1708
1923
|
}
|
|
1709
1924
|
function peg$parsequotedReference() {
|
|
@@ -1723,12 +1938,12 @@ function peg$parse(input, options) {
|
|
|
1723
1938
|
s1 = peg$currPos;
|
|
1724
1939
|
peg$silentFails++;
|
|
1725
1940
|
if (input.charCodeAt(peg$currPos) === 34) {
|
|
1726
|
-
s2 = peg$
|
|
1941
|
+
s2 = peg$c6;
|
|
1727
1942
|
peg$currPos++;
|
|
1728
1943
|
} else {
|
|
1729
1944
|
s2 = peg$FAILED;
|
|
1730
1945
|
if (peg$silentFails === 0) {
|
|
1731
|
-
peg$fail(peg$
|
|
1946
|
+
peg$fail(peg$e11);
|
|
1732
1947
|
}
|
|
1733
1948
|
}
|
|
1734
1949
|
peg$silentFails--;
|
|
@@ -1740,7 +1955,7 @@ function peg$parse(input, options) {
|
|
|
1740
1955
|
}
|
|
1741
1956
|
if (s1 !== peg$FAILED) {
|
|
1742
1957
|
peg$savedPos = peg$currPos;
|
|
1743
|
-
s2 = peg$
|
|
1958
|
+
s2 = peg$f33();
|
|
1744
1959
|
if (s2) {
|
|
1745
1960
|
s2 = undefined;
|
|
1746
1961
|
} else {
|
|
@@ -1750,7 +1965,7 @@ function peg$parse(input, options) {
|
|
|
1750
1965
|
s3 = peg$parseconsumeDouble();
|
|
1751
1966
|
if (s3 !== peg$FAILED) {
|
|
1752
1967
|
peg$savedPos = s0;
|
|
1753
|
-
s0 = peg$
|
|
1968
|
+
s0 = peg$f34(s3);
|
|
1754
1969
|
} else {
|
|
1755
1970
|
peg$currPos = s0;
|
|
1756
1971
|
s0 = peg$FAILED;
|
|
@@ -1785,7 +2000,7 @@ function peg$parse(input, options) {
|
|
|
1785
2000
|
s3 = peg$parseconsumeDoubleMore();
|
|
1786
2001
|
}
|
|
1787
2002
|
peg$savedPos = s0;
|
|
1788
|
-
s0 = peg$
|
|
2003
|
+
s0 = peg$f35(s1, s2);
|
|
1789
2004
|
} else {
|
|
1790
2005
|
peg$currPos = s0;
|
|
1791
2006
|
s0 = peg$FAILED;
|
|
@@ -1796,7 +2011,7 @@ function peg$parse(input, options) {
|
|
|
1796
2011
|
let s0, s1, s2;
|
|
1797
2012
|
s0 = peg$currPos;
|
|
1798
2013
|
peg$savedPos = peg$currPos;
|
|
1799
|
-
s1 = peg$
|
|
2014
|
+
s1 = peg$f36();
|
|
1800
2015
|
if (s1) {
|
|
1801
2016
|
s1 = undefined;
|
|
1802
2017
|
} else {
|
|
@@ -1814,7 +2029,7 @@ function peg$parse(input, options) {
|
|
|
1814
2029
|
}
|
|
1815
2030
|
if (s2 !== peg$FAILED) {
|
|
1816
2031
|
peg$savedPos = s0;
|
|
1817
|
-
s0 = peg$
|
|
2032
|
+
s0 = peg$f37(s2);
|
|
1818
2033
|
} else {
|
|
1819
2034
|
peg$currPos = s0;
|
|
1820
2035
|
s0 = peg$FAILED;
|
|
@@ -1831,12 +2046,12 @@ function peg$parse(input, options) {
|
|
|
1831
2046
|
s1 = peg$currPos;
|
|
1832
2047
|
peg$silentFails++;
|
|
1833
2048
|
if (input.charCodeAt(peg$currPos) === 39) {
|
|
1834
|
-
s2 = peg$
|
|
2049
|
+
s2 = peg$c7;
|
|
1835
2050
|
peg$currPos++;
|
|
1836
2051
|
} else {
|
|
1837
2052
|
s2 = peg$FAILED;
|
|
1838
2053
|
if (peg$silentFails === 0) {
|
|
1839
|
-
peg$fail(peg$
|
|
2054
|
+
peg$fail(peg$e12);
|
|
1840
2055
|
}
|
|
1841
2056
|
}
|
|
1842
2057
|
peg$silentFails--;
|
|
@@ -1848,7 +2063,7 @@ function peg$parse(input, options) {
|
|
|
1848
2063
|
}
|
|
1849
2064
|
if (s1 !== peg$FAILED) {
|
|
1850
2065
|
peg$savedPos = peg$currPos;
|
|
1851
|
-
s2 = peg$
|
|
2066
|
+
s2 = peg$f38();
|
|
1852
2067
|
if (s2) {
|
|
1853
2068
|
s2 = undefined;
|
|
1854
2069
|
} else {
|
|
@@ -1858,7 +2073,7 @@ function peg$parse(input, options) {
|
|
|
1858
2073
|
s3 = peg$parseconsumeSingle();
|
|
1859
2074
|
if (s3 !== peg$FAILED) {
|
|
1860
2075
|
peg$savedPos = s0;
|
|
1861
|
-
s0 = peg$
|
|
2076
|
+
s0 = peg$f39(s3);
|
|
1862
2077
|
} else {
|
|
1863
2078
|
peg$currPos = s0;
|
|
1864
2079
|
s0 = peg$FAILED;
|
|
@@ -1893,7 +2108,7 @@ function peg$parse(input, options) {
|
|
|
1893
2108
|
s3 = peg$parseconsumeSingleMore();
|
|
1894
2109
|
}
|
|
1895
2110
|
peg$savedPos = s0;
|
|
1896
|
-
s0 = peg$
|
|
2111
|
+
s0 = peg$f40(s1, s2);
|
|
1897
2112
|
} else {
|
|
1898
2113
|
peg$currPos = s0;
|
|
1899
2114
|
s0 = peg$FAILED;
|
|
@@ -1904,7 +2119,7 @@ function peg$parse(input, options) {
|
|
|
1904
2119
|
let s0, s1, s2;
|
|
1905
2120
|
s0 = peg$currPos;
|
|
1906
2121
|
peg$savedPos = peg$currPos;
|
|
1907
|
-
s1 = peg$
|
|
2122
|
+
s1 = peg$f41();
|
|
1908
2123
|
if (s1) {
|
|
1909
2124
|
s1 = undefined;
|
|
1910
2125
|
} else {
|
|
@@ -1922,7 +2137,7 @@ function peg$parse(input, options) {
|
|
|
1922
2137
|
}
|
|
1923
2138
|
if (s2 !== peg$FAILED) {
|
|
1924
2139
|
peg$savedPos = s0;
|
|
1925
|
-
s0 = peg$
|
|
2140
|
+
s0 = peg$f42(s2);
|
|
1926
2141
|
} else {
|
|
1927
2142
|
peg$currPos = s0;
|
|
1928
2143
|
s0 = peg$FAILED;
|
|
@@ -1939,12 +2154,12 @@ function peg$parse(input, options) {
|
|
|
1939
2154
|
s1 = peg$currPos;
|
|
1940
2155
|
peg$silentFails++;
|
|
1941
2156
|
if (input.charCodeAt(peg$currPos) === 96) {
|
|
1942
|
-
s2 = peg$
|
|
2157
|
+
s2 = peg$c8;
|
|
1943
2158
|
peg$currPos++;
|
|
1944
2159
|
} else {
|
|
1945
2160
|
s2 = peg$FAILED;
|
|
1946
2161
|
if (peg$silentFails === 0) {
|
|
1947
|
-
peg$fail(peg$
|
|
2162
|
+
peg$fail(peg$e13);
|
|
1948
2163
|
}
|
|
1949
2164
|
}
|
|
1950
2165
|
peg$silentFails--;
|
|
@@ -1956,7 +2171,7 @@ function peg$parse(input, options) {
|
|
|
1956
2171
|
}
|
|
1957
2172
|
if (s1 !== peg$FAILED) {
|
|
1958
2173
|
peg$savedPos = peg$currPos;
|
|
1959
|
-
s2 = peg$
|
|
2174
|
+
s2 = peg$f43();
|
|
1960
2175
|
if (s2) {
|
|
1961
2176
|
s2 = undefined;
|
|
1962
2177
|
} else {
|
|
@@ -1966,7 +2181,7 @@ function peg$parse(input, options) {
|
|
|
1966
2181
|
s3 = peg$parseconsumeBacktick();
|
|
1967
2182
|
if (s3 !== peg$FAILED) {
|
|
1968
2183
|
peg$savedPos = s0;
|
|
1969
|
-
s0 = peg$
|
|
2184
|
+
s0 = peg$f44(s3);
|
|
1970
2185
|
} else {
|
|
1971
2186
|
peg$currPos = s0;
|
|
1972
2187
|
s0 = peg$FAILED;
|
|
@@ -2001,7 +2216,7 @@ function peg$parse(input, options) {
|
|
|
2001
2216
|
s3 = peg$parseconsumeBacktickMore();
|
|
2002
2217
|
}
|
|
2003
2218
|
peg$savedPos = s0;
|
|
2004
|
-
s0 = peg$
|
|
2219
|
+
s0 = peg$f45(s1, s2);
|
|
2005
2220
|
} else {
|
|
2006
2221
|
peg$currPos = s0;
|
|
2007
2222
|
s0 = peg$FAILED;
|
|
@@ -2012,7 +2227,7 @@ function peg$parse(input, options) {
|
|
|
2012
2227
|
let s0, s1, s2;
|
|
2013
2228
|
s0 = peg$currPos;
|
|
2014
2229
|
peg$savedPos = peg$currPos;
|
|
2015
|
-
s1 = peg$
|
|
2230
|
+
s1 = peg$f46();
|
|
2016
2231
|
if (s1) {
|
|
2017
2232
|
s1 = undefined;
|
|
2018
2233
|
} else {
|
|
@@ -2030,7 +2245,7 @@ function peg$parse(input, options) {
|
|
|
2030
2245
|
}
|
|
2031
2246
|
if (s2 !== peg$FAILED) {
|
|
2032
2247
|
peg$savedPos = s0;
|
|
2033
|
-
s0 = peg$
|
|
2248
|
+
s0 = peg$f47(s2);
|
|
2034
2249
|
} else {
|
|
2035
2250
|
peg$currPos = s0;
|
|
2036
2251
|
s0 = peg$FAILED;
|
|
@@ -2046,7 +2261,7 @@ function peg$parse(input, options) {
|
|
|
2046
2261
|
s0 = peg$currPos;
|
|
2047
2262
|
s1 = "";
|
|
2048
2263
|
peg$savedPos = s0;
|
|
2049
|
-
s1 = peg$
|
|
2264
|
+
s1 = peg$f48();
|
|
2050
2265
|
s0 = s1;
|
|
2051
2266
|
return s0;
|
|
2052
2267
|
}
|
|
@@ -2055,28 +2270,28 @@ function peg$parse(input, options) {
|
|
|
2055
2270
|
s0 = peg$currPos;
|
|
2056
2271
|
s1 = [];
|
|
2057
2272
|
if (input.charCodeAt(peg$currPos) === 32) {
|
|
2058
|
-
s2 = peg$
|
|
2273
|
+
s2 = peg$c9;
|
|
2059
2274
|
peg$currPos++;
|
|
2060
2275
|
} else {
|
|
2061
2276
|
s2 = peg$FAILED;
|
|
2062
2277
|
if (peg$silentFails === 0) {
|
|
2063
|
-
peg$fail(peg$
|
|
2278
|
+
peg$fail(peg$e14);
|
|
2064
2279
|
}
|
|
2065
2280
|
}
|
|
2066
2281
|
while (s2 !== peg$FAILED) {
|
|
2067
2282
|
s1.push(s2);
|
|
2068
2283
|
if (input.charCodeAt(peg$currPos) === 32) {
|
|
2069
|
-
s2 = peg$
|
|
2284
|
+
s2 = peg$c9;
|
|
2070
2285
|
peg$currPos++;
|
|
2071
2286
|
} else {
|
|
2072
2287
|
s2 = peg$FAILED;
|
|
2073
2288
|
if (peg$silentFails === 0) {
|
|
2074
|
-
peg$fail(peg$
|
|
2289
|
+
peg$fail(peg$e14);
|
|
2075
2290
|
}
|
|
2076
2291
|
}
|
|
2077
2292
|
}
|
|
2078
2293
|
peg$savedPos = s0;
|
|
2079
|
-
s1 = peg$
|
|
2294
|
+
s1 = peg$f49(s1);
|
|
2080
2295
|
s0 = s1;
|
|
2081
2296
|
return s0;
|
|
2082
2297
|
}
|
|
@@ -2085,28 +2300,28 @@ function peg$parse(input, options) {
|
|
|
2085
2300
|
s0 = peg$currPos;
|
|
2086
2301
|
s1 = [];
|
|
2087
2302
|
if (input.charCodeAt(peg$currPos) === 32) {
|
|
2088
|
-
s2 = peg$
|
|
2303
|
+
s2 = peg$c9;
|
|
2089
2304
|
peg$currPos++;
|
|
2090
2305
|
} else {
|
|
2091
2306
|
s2 = peg$FAILED;
|
|
2092
2307
|
if (peg$silentFails === 0) {
|
|
2093
|
-
peg$fail(peg$
|
|
2308
|
+
peg$fail(peg$e14);
|
|
2094
2309
|
}
|
|
2095
2310
|
}
|
|
2096
2311
|
while (s2 !== peg$FAILED) {
|
|
2097
2312
|
s1.push(s2);
|
|
2098
2313
|
if (input.charCodeAt(peg$currPos) === 32) {
|
|
2099
|
-
s2 = peg$
|
|
2314
|
+
s2 = peg$c9;
|
|
2100
2315
|
peg$currPos++;
|
|
2101
2316
|
} else {
|
|
2102
2317
|
s2 = peg$FAILED;
|
|
2103
2318
|
if (peg$silentFails === 0) {
|
|
2104
|
-
peg$fail(peg$
|
|
2319
|
+
peg$fail(peg$e14);
|
|
2105
2320
|
}
|
|
2106
2321
|
}
|
|
2107
2322
|
}
|
|
2108
2323
|
peg$savedPos = peg$currPos;
|
|
2109
|
-
s2 = peg$
|
|
2324
|
+
s2 = peg$f50(s1);
|
|
2110
2325
|
if (s2) {
|
|
2111
2326
|
s2 = undefined;
|
|
2112
2327
|
} else {
|
|
@@ -2114,7 +2329,7 @@ function peg$parse(input, options) {
|
|
|
2114
2329
|
}
|
|
2115
2330
|
if (s2 !== peg$FAILED) {
|
|
2116
2331
|
peg$savedPos = s0;
|
|
2117
|
-
s0 = peg$
|
|
2332
|
+
s0 = peg$f51(s1);
|
|
2118
2333
|
} else {
|
|
2119
2334
|
peg$currPos = s0;
|
|
2120
2335
|
s0 = peg$FAILED;
|
|
@@ -2126,28 +2341,28 @@ function peg$parse(input, options) {
|
|
|
2126
2341
|
s0 = peg$currPos;
|
|
2127
2342
|
s1 = [];
|
|
2128
2343
|
if (input.charCodeAt(peg$currPos) === 32) {
|
|
2129
|
-
s2 = peg$
|
|
2344
|
+
s2 = peg$c9;
|
|
2130
2345
|
peg$currPos++;
|
|
2131
2346
|
} else {
|
|
2132
2347
|
s2 = peg$FAILED;
|
|
2133
2348
|
if (peg$silentFails === 0) {
|
|
2134
|
-
peg$fail(peg$
|
|
2349
|
+
peg$fail(peg$e14);
|
|
2135
2350
|
}
|
|
2136
2351
|
}
|
|
2137
2352
|
while (s2 !== peg$FAILED) {
|
|
2138
2353
|
s1.push(s2);
|
|
2139
2354
|
if (input.charCodeAt(peg$currPos) === 32) {
|
|
2140
|
-
s2 = peg$
|
|
2355
|
+
s2 = peg$c9;
|
|
2141
2356
|
peg$currPos++;
|
|
2142
2357
|
} else {
|
|
2143
2358
|
s2 = peg$FAILED;
|
|
2144
2359
|
if (peg$silentFails === 0) {
|
|
2145
|
-
peg$fail(peg$
|
|
2360
|
+
peg$fail(peg$e14);
|
|
2146
2361
|
}
|
|
2147
2362
|
}
|
|
2148
2363
|
}
|
|
2149
2364
|
peg$savedPos = peg$currPos;
|
|
2150
|
-
s2 = peg$
|
|
2365
|
+
s2 = peg$f52(s1);
|
|
2151
2366
|
if (s2) {
|
|
2152
2367
|
s2 = undefined;
|
|
2153
2368
|
} else {
|
|
@@ -2358,7 +2573,7 @@ function peg$parse(input, options) {
|
|
|
2358
2573
|
let s0, s1, s2, s3;
|
|
2359
2574
|
s0 = peg$currPos;
|
|
2360
2575
|
peg$savedPos = peg$currPos;
|
|
2361
|
-
s1 = peg$
|
|
2576
|
+
s1 = peg$f53();
|
|
2362
2577
|
if (s1) {
|
|
2363
2578
|
s1 = undefined;
|
|
2364
2579
|
} else {
|
|
@@ -2457,12 +2672,12 @@ function peg$parse(input, options) {
|
|
|
2457
2672
|
function peg$parsewhiteSpaceSymbol() {
|
|
2458
2673
|
let s0;
|
|
2459
2674
|
s0 = input.charAt(peg$currPos);
|
|
2460
|
-
if (peg$
|
|
2675
|
+
if (peg$r4.test(s0)) {
|
|
2461
2676
|
peg$currPos++;
|
|
2462
2677
|
} else {
|
|
2463
2678
|
s0 = peg$FAILED;
|
|
2464
2679
|
if (peg$silentFails === 0) {
|
|
2465
|
-
peg$fail(peg$
|
|
2680
|
+
peg$fail(peg$e15);
|
|
2466
2681
|
}
|
|
2467
2682
|
}
|
|
2468
2683
|
return s0;
|
|
@@ -2470,12 +2685,12 @@ function peg$parse(input, options) {
|
|
|
2470
2685
|
function peg$parsereferenceSymbol() {
|
|
2471
2686
|
let s0;
|
|
2472
2687
|
s0 = input.charAt(peg$currPos);
|
|
2473
|
-
if (peg$
|
|
2688
|
+
if (peg$r5.test(s0)) {
|
|
2474
2689
|
peg$currPos++;
|
|
2475
2690
|
} else {
|
|
2476
2691
|
s0 = peg$FAILED;
|
|
2477
2692
|
if (peg$silentFails === 0) {
|
|
2478
|
-
peg$fail(peg$
|
|
2693
|
+
peg$fail(peg$e16);
|
|
2479
2694
|
}
|
|
2480
2695
|
}
|
|
2481
2696
|
return s0;
|
|
@@ -2980,16 +3195,596 @@ class FormatOptions {
|
|
|
2980
3195
|
// src/FormatConfig.js
|
|
2981
3196
|
class FormatConfig extends FormatOptions {
|
|
2982
3197
|
}
|
|
3198
|
+
// src/Binary.js
|
|
3199
|
+
var U64 = (1n << 64n) - 1n;
|
|
3200
|
+
var WIDTHS = [1, 2, 4, 8];
|
|
3201
|
+
function requireValue(condition, message) {
|
|
3202
|
+
if (!condition)
|
|
3203
|
+
throw new RangeError(message);
|
|
3204
|
+
}
|
|
3205
|
+
function uint64(value) {
|
|
3206
|
+
requireValue(typeof value === "bigint" || Number.isSafeInteger(value) && value >= 0, "expected uint64");
|
|
3207
|
+
const result = BigInt(value);
|
|
3208
|
+
requireValue(result >= 0n && result <= U64, "uint64 overflow");
|
|
3209
|
+
return result;
|
|
3210
|
+
}
|
|
3211
|
+
|
|
3212
|
+
class External {
|
|
3213
|
+
constructor(value) {
|
|
3214
|
+
this.value = uint64(value);
|
|
3215
|
+
}
|
|
3216
|
+
}
|
|
3217
|
+
|
|
3218
|
+
class ArityRange {
|
|
3219
|
+
constructor(min = 2, max = 2) {
|
|
3220
|
+
this.min = uint64(min);
|
|
3221
|
+
this.max = max === null ? null : uint64(max);
|
|
3222
|
+
requireValue(this.min > 0n && this.min <= U64 >> 4n && (this.max === null || this.max >= this.min), "invalid arity");
|
|
3223
|
+
}
|
|
3224
|
+
contains(length) {
|
|
3225
|
+
return BigInt(length) >= this.min && (this.max === null || BigInt(length) <= this.max);
|
|
3226
|
+
}
|
|
3227
|
+
get fixed() {
|
|
3228
|
+
return this.min === this.max;
|
|
3229
|
+
}
|
|
3230
|
+
static parse(text) {
|
|
3231
|
+
requireValue(/^[0-9]+(?:\.\.[0-9]*)?$/.test(text), "invalid arity");
|
|
3232
|
+
const parts = text.split("..");
|
|
3233
|
+
return new ArityRange(BigInt(parts[0]), parts.at(-1) === "" ? null : BigInt(parts.at(-1)));
|
|
3234
|
+
}
|
|
3235
|
+
}
|
|
3236
|
+
|
|
3237
|
+
class DecodeLimits {
|
|
3238
|
+
constructor(values = {}) {
|
|
3239
|
+
Object.assign(this, {
|
|
3240
|
+
maxLinks: 2 ** 22,
|
|
3241
|
+
maxReferences: 2 ** 24,
|
|
3242
|
+
maxNodes: 2 ** 22,
|
|
3243
|
+
maxStringBytes: 64 * 2 ** 20,
|
|
3244
|
+
maxDepth: 64
|
|
3245
|
+
}, values);
|
|
3246
|
+
for (const key of Object.keys(this)) {
|
|
3247
|
+
requireValue([
|
|
3248
|
+
"maxLinks",
|
|
3249
|
+
"maxReferences",
|
|
3250
|
+
"maxNodes",
|
|
3251
|
+
"maxStringBytes",
|
|
3252
|
+
"maxDepth"
|
|
3253
|
+
].includes(key), "unknown limit");
|
|
3254
|
+
requireValue(Number.isSafeInteger(this[key]) && this[key] >= 0, "invalid limit");
|
|
3255
|
+
}
|
|
3256
|
+
}
|
|
3257
|
+
static unlimited() {
|
|
3258
|
+
return new DecodeLimits({
|
|
3259
|
+
maxLinks: Number.MAX_SAFE_INTEGER,
|
|
3260
|
+
maxReferences: Number.MAX_SAFE_INTEGER,
|
|
3261
|
+
maxNodes: Number.MAX_SAFE_INTEGER,
|
|
3262
|
+
maxStringBytes: Number.MAX_SAFE_INTEGER,
|
|
3263
|
+
maxDepth: Number.MAX_SAFE_INTEGER
|
|
3264
|
+
});
|
|
3265
|
+
}
|
|
3266
|
+
}
|
|
3267
|
+
|
|
3268
|
+
class BinaryLinoOptions {
|
|
3269
|
+
constructor(externalReferences = false, arity = new ArityRange, packedWidths = false) {
|
|
3270
|
+
Object.assign(this, { externalReferences, arity, packedWidths });
|
|
3271
|
+
}
|
|
3272
|
+
static ofPacket(packet) {
|
|
3273
|
+
let min = 2, max = 2;
|
|
3274
|
+
for (const [, link] of packet.links()) {
|
|
3275
|
+
min = Math.min(min, link.length);
|
|
3276
|
+
max = Math.max(max, link.length);
|
|
3277
|
+
}
|
|
3278
|
+
return new BinaryLinoOptions(packet.externalReferences, new ArityRange(min, max), new Set(packet.sections.map((s) => s.width)).size > 1);
|
|
3279
|
+
}
|
|
3280
|
+
}
|
|
3281
|
+
|
|
3282
|
+
class Section {
|
|
3283
|
+
constructor(gap, arity, width, links) {
|
|
3284
|
+
Object.assign(this, { gap: uint64(gap), arity, width, links });
|
|
3285
|
+
}
|
|
3286
|
+
}
|
|
3287
|
+
function referenceWidth(reference, external) {
|
|
3288
|
+
const value = reference instanceof External ? reference.value : uint64(reference);
|
|
3289
|
+
requireValue(!(reference instanceof External) || external, "external references disabled");
|
|
3290
|
+
for (const width of WIDTHS)
|
|
3291
|
+
if (value < 1n << BigInt(width * 8 - Number(external)))
|
|
3292
|
+
return width;
|
|
3293
|
+
throw new RangeError("reference exceeds capacity");
|
|
3294
|
+
}
|
|
3295
|
+
function leb(out, input) {
|
|
3296
|
+
let value = uint64(input);
|
|
3297
|
+
while (value >= 128n) {
|
|
3298
|
+
out.push(Number(value & 127n) | 128);
|
|
3299
|
+
value >>= 7n;
|
|
3300
|
+
}
|
|
3301
|
+
out.push(Number(value));
|
|
3302
|
+
}
|
|
3303
|
+
|
|
3304
|
+
class PacketReader {
|
|
3305
|
+
constructor(bytes, offset = 0) {
|
|
3306
|
+
requireValue(bytes instanceof Uint8Array && Number.isSafeInteger(offset) && offset >= 0 && offset <= bytes.length, "invalid byte cursor");
|
|
3307
|
+
this.bytes = bytes;
|
|
3308
|
+
this.offset = offset;
|
|
3309
|
+
}
|
|
3310
|
+
raw(width) {
|
|
3311
|
+
requireValue(width <= this.bytes.length - this.offset, "unexpected end of packet");
|
|
3312
|
+
let result = 0n;
|
|
3313
|
+
for (let i = 0;i < width; i++)
|
|
3314
|
+
result |= BigInt(this.bytes[this.offset++]) << BigInt(i * 8);
|
|
3315
|
+
return result;
|
|
3316
|
+
}
|
|
3317
|
+
leb() {
|
|
3318
|
+
let value = 0n;
|
|
3319
|
+
for (let shift = 0n;shift < 64n; shift += 7n) {
|
|
3320
|
+
const byte = this.raw(1);
|
|
3321
|
+
requireValue(shift !== 63n || (byte & 127n) <= 1n, "LEB128 overflow");
|
|
3322
|
+
value |= (byte & 127n) << shift;
|
|
3323
|
+
if (byte < 128n)
|
|
3324
|
+
return value;
|
|
3325
|
+
}
|
|
3326
|
+
throw new RangeError("LEB128 overflow");
|
|
3327
|
+
}
|
|
3328
|
+
read(limits = new DecodeLimits) {
|
|
3329
|
+
if (this.offset === this.bytes.length)
|
|
3330
|
+
return null;
|
|
3331
|
+
const header = Number(this.raw(1));
|
|
3332
|
+
requireValue((header & 240) === 16, "unsupported binary version");
|
|
3333
|
+
const sections = [], counts = [];
|
|
3334
|
+
if (header & 2) {
|
|
3335
|
+
requireValue((header & 12) === 0, "explicit header width bits set");
|
|
3336
|
+
const sectionCount = this.leb();
|
|
3337
|
+
requireValue(sectionCount <= BigInt(limits.maxLinks), "too many sections");
|
|
3338
|
+
let address = 1n, total = 0n;
|
|
3339
|
+
for (let i = 0n;i < sectionCount; i++) {
|
|
3340
|
+
const shape = this.leb(), gap = shape & 4n ? this.leb() : 0n;
|
|
3341
|
+
const min = shape >> 4n, extra = shape & 8n ? this.leb() : null;
|
|
3342
|
+
const arity = new ArityRange(min, extra === null ? min : extra === 0n ? null : uint64(min + extra));
|
|
3343
|
+
const count = this.leb();
|
|
3344
|
+
address = uint64(address + gap + count);
|
|
3345
|
+
total += count;
|
|
3346
|
+
requireValue(total <= BigInt(limits.maxLinks), "too many links");
|
|
3347
|
+
sections.push(new Section(gap, arity, WIDTHS[Number(shape & 3n)], []));
|
|
3348
|
+
counts.push(Number(count));
|
|
3349
|
+
}
|
|
3350
|
+
} else {
|
|
3351
|
+
const count = this.leb();
|
|
3352
|
+
uint64(6n + count);
|
|
3353
|
+
requireValue(count <= BigInt(limits.maxLinks), "too many links");
|
|
3354
|
+
if (count) {
|
|
3355
|
+
sections.push(new Section(5, new ArityRange, WIDTHS[header >> 2 & 3], []));
|
|
3356
|
+
counts.push(Number(count));
|
|
3357
|
+
}
|
|
3358
|
+
}
|
|
3359
|
+
let references = 0n;
|
|
3360
|
+
for (let i = 0;i < sections.length; i++) {
|
|
3361
|
+
const section = sections[i];
|
|
3362
|
+
for (let j = 0;j < counts[i]; j++) {
|
|
3363
|
+
const length = uint64(section.arity.min + (section.arity.fixed ? 0n : this.leb()));
|
|
3364
|
+
requireValue(section.arity.contains(length), "link outside arity");
|
|
3365
|
+
references += length;
|
|
3366
|
+
requireValue(references <= BigInt(limits.maxReferences), "too many references");
|
|
3367
|
+
const link = [], top = 1n << BigInt(section.width * 8 - 1);
|
|
3368
|
+
for (let k = 0n;k < length; k++) {
|
|
3369
|
+
const raw = this.raw(section.width);
|
|
3370
|
+
link.push(header & 1 && raw >= top ? new External(raw === top ? 0n : (top << 1n) - raw) : raw);
|
|
3371
|
+
}
|
|
3372
|
+
section.links.push(link);
|
|
3373
|
+
}
|
|
3374
|
+
}
|
|
3375
|
+
return new LinksPacket(Boolean(header & 1), sections);
|
|
3376
|
+
}
|
|
3377
|
+
}
|
|
3378
|
+
|
|
3379
|
+
class LinksPacket {
|
|
3380
|
+
constructor(externalReferences = false, sections = []) {
|
|
3381
|
+
Object.assign(this, { externalReferences, sections });
|
|
3382
|
+
}
|
|
3383
|
+
links() {
|
|
3384
|
+
const result = [];
|
|
3385
|
+
let address = 1n;
|
|
3386
|
+
for (const section of this.sections) {
|
|
3387
|
+
address = uint64(address + uint64(section.gap));
|
|
3388
|
+
for (const link of section.links) {
|
|
3389
|
+
result.push([
|
|
3390
|
+
address,
|
|
3391
|
+
link.map((r) => r instanceof External ? r : uint64(r))
|
|
3392
|
+
]);
|
|
3393
|
+
address = uint64(address + 1n);
|
|
3394
|
+
}
|
|
3395
|
+
}
|
|
3396
|
+
return result;
|
|
3397
|
+
}
|
|
3398
|
+
validate(limits = new DecodeLimits) {
|
|
3399
|
+
requireValue(this.sections.length <= limits.maxLinks && this.links().length <= limits.maxLinks, "too many links or sections");
|
|
3400
|
+
let references = 0;
|
|
3401
|
+
for (const s of this.sections) {
|
|
3402
|
+
requireValue(WIDTHS.includes(s.width), "invalid width");
|
|
3403
|
+
new ArityRange(s.arity.min, s.arity.max);
|
|
3404
|
+
for (const link of s.links) {
|
|
3405
|
+
requireValue(s.arity.contains(link.length), "link outside arity");
|
|
3406
|
+
references += link.length;
|
|
3407
|
+
requireValue(references <= limits.maxReferences, "too many references");
|
|
3408
|
+
for (const r of link)
|
|
3409
|
+
requireValue(referenceWidth(r, this.externalReferences) <= s.width, "reference outside width");
|
|
3410
|
+
}
|
|
3411
|
+
}
|
|
3412
|
+
return this;
|
|
3413
|
+
}
|
|
3414
|
+
toBytes(limits = new DecodeLimits) {
|
|
3415
|
+
this.validate(limits);
|
|
3416
|
+
const s = this.sections[0];
|
|
3417
|
+
const compact = !s || this.sections.length === 1 && s.gap === 5n && s.arity.min === 2n && s.arity.max === 2n && s.links.length > 0;
|
|
3418
|
+
const out = [16 | Number(this.externalReferences)];
|
|
3419
|
+
if (compact) {
|
|
3420
|
+
out[0] |= WIDTHS.indexOf(s?.width ?? 1) << 2;
|
|
3421
|
+
leb(out, s?.links.length ?? 0);
|
|
3422
|
+
} else {
|
|
3423
|
+
out[0] |= 2;
|
|
3424
|
+
leb(out, this.sections.length);
|
|
3425
|
+
for (const s of this.sections) {
|
|
3426
|
+
leb(out, s.arity.min << 4n | BigInt(WIDTHS.indexOf(s.width) | (s.gap ? 4 : 0) | (s.arity.fixed ? 0 : 8)));
|
|
3427
|
+
if (s.gap)
|
|
3428
|
+
leb(out, s.gap);
|
|
3429
|
+
if (!s.arity.fixed)
|
|
3430
|
+
leb(out, s.arity.max === null ? 0n : s.arity.max - s.arity.min);
|
|
3431
|
+
leb(out, s.links.length);
|
|
3432
|
+
}
|
|
3433
|
+
}
|
|
3434
|
+
for (const s of this.sections)
|
|
3435
|
+
for (const link of s.links) {
|
|
3436
|
+
if (!s.arity.fixed)
|
|
3437
|
+
leb(out, BigInt(link.length) - s.arity.min);
|
|
3438
|
+
for (const r of link) {
|
|
3439
|
+
const bits = BigInt(s.width * 8);
|
|
3440
|
+
let raw = r instanceof External ? r.value === 0n ? 1n << bits - 1n : (1n << bits) - r.value : uint64(r);
|
|
3441
|
+
for (let i = 0;i < s.width; i++) {
|
|
3442
|
+
out.push(Number(raw & 255n));
|
|
3443
|
+
raw >>= 8n;
|
|
3444
|
+
}
|
|
3445
|
+
}
|
|
3446
|
+
}
|
|
3447
|
+
return Uint8Array.from(out);
|
|
3448
|
+
}
|
|
3449
|
+
static fromBytes(bytes, limits = new DecodeLimits) {
|
|
3450
|
+
const reader = new PacketReader(bytes), packet = reader.read(limits);
|
|
3451
|
+
requireValue(packet !== null, "empty input");
|
|
3452
|
+
requireValue(reader.offset === bytes.length, "trailing bytes");
|
|
3453
|
+
return packet;
|
|
3454
|
+
}
|
|
3455
|
+
static parseLinks(text) {
|
|
3456
|
+
return text.split(";").filter((s) => s.trim()).map((entry) => {
|
|
3457
|
+
const [a, refs] = entry.split(":");
|
|
3458
|
+
return [
|
|
3459
|
+
uint64(BigInt(a.trim())),
|
|
3460
|
+
refs.trim().split(/\s+/).filter(Boolean).map((r) => r.startsWith("#") ? new External(BigInt(r.slice(1))) : uint64(BigInt(r)))
|
|
3461
|
+
];
|
|
3462
|
+
});
|
|
3463
|
+
}
|
|
3464
|
+
static pack(externalReferences, input, packedWidths = false) {
|
|
3465
|
+
const links = input.map(([a, r]) => [uint64(a), r]);
|
|
3466
|
+
let previous = 0n;
|
|
3467
|
+
const needs = links.map(([a, refs]) => {
|
|
3468
|
+
requireValue(a > previous && a < U64 && refs.length > 0, "invalid address order or empty link");
|
|
3469
|
+
previous = a;
|
|
3470
|
+
return refs.reduce((need, r) => Math.max(need, referenceWidth(r, externalReferences)), 1);
|
|
3471
|
+
});
|
|
3472
|
+
function layout(packed) {
|
|
3473
|
+
if (!links.length)
|
|
3474
|
+
return [];
|
|
3475
|
+
const widest = needs.reduce((a, b) => Math.max(a, b), 1), opens = [], bests = [];
|
|
3476
|
+
let costs = Array(8).fill(Infinity);
|
|
3477
|
+
const cheapest = (c) => c.reduce((best, v, s) => v < c[best] ? s : best, 0);
|
|
3478
|
+
for (let i = 0;i < links.length; i++) {
|
|
3479
|
+
const best = cheapest(costs), before = i ? costs[best] : 0, next = Array(8).fill(Infinity);
|
|
3480
|
+
let mask = 0;
|
|
3481
|
+
bests.push(best);
|
|
3482
|
+
for (let state = 0;state < 8; state++) {
|
|
3483
|
+
const width = WIDTHS[state >> 1], variable = state & 1;
|
|
3484
|
+
if (!packed && width !== widest || width < needs[i])
|
|
3485
|
+
continue;
|
|
3486
|
+
const opening = before + 2 + variable;
|
|
3487
|
+
const continuing = i && links[i - 1][0] + 1n === links[i][0] && (variable || links[i - 1][1].length === links[i][1].length) ? costs[state] : Infinity;
|
|
3488
|
+
if (continuing <= opening)
|
|
3489
|
+
next[state] = continuing + links[i][1].length * width + variable;
|
|
3490
|
+
else {
|
|
3491
|
+
next[state] = opening + links[i][1].length * width + variable;
|
|
3492
|
+
mask |= 1 << state;
|
|
3493
|
+
}
|
|
3494
|
+
}
|
|
3495
|
+
opens.push(mask);
|
|
3496
|
+
costs = next;
|
|
3497
|
+
}
|
|
3498
|
+
const result = [];
|
|
3499
|
+
let end = links.length, state = cheapest(costs);
|
|
3500
|
+
for (let i = links.length - 1;i >= 0; i--)
|
|
3501
|
+
if (opens[i] & 1 << state) {
|
|
3502
|
+
result.push([end - i, WIDTHS[state >> 1]]);
|
|
3503
|
+
end = i;
|
|
3504
|
+
state = bests[i];
|
|
3505
|
+
}
|
|
3506
|
+
return result.reverse();
|
|
3507
|
+
}
|
|
3508
|
+
function packet(plan) {
|
|
3509
|
+
const sections = [];
|
|
3510
|
+
let index = 0, address = 1n;
|
|
3511
|
+
for (const [count, width] of plan) {
|
|
3512
|
+
const members = links.slice(index, index + count), start = members[0][0];
|
|
3513
|
+
let min = Infinity, max = 0;
|
|
3514
|
+
for (const [, r] of members) {
|
|
3515
|
+
min = Math.min(min, r.length);
|
|
3516
|
+
max = Math.max(max, r.length);
|
|
3517
|
+
}
|
|
3518
|
+
sections.push(new Section(start - address, new ArityRange(min, max), width, members.map(([, r]) => r)));
|
|
3519
|
+
index += count;
|
|
3520
|
+
address = start + BigInt(count);
|
|
3521
|
+
}
|
|
3522
|
+
return new LinksPacket(externalReferences, sections);
|
|
3523
|
+
}
|
|
3524
|
+
const uniform = packet(layout(false));
|
|
3525
|
+
if (!packedWidths)
|
|
3526
|
+
return uniform;
|
|
3527
|
+
const packed = packet(layout(true));
|
|
3528
|
+
return packed.toBytes(DecodeLimits.unlimited()).length < uniform.toBytes(DecodeLimits.unlimited()).length ? packed : uniform;
|
|
3529
|
+
}
|
|
3530
|
+
}
|
|
3531
|
+
|
|
3532
|
+
class Encoder {
|
|
3533
|
+
constructor(options) {
|
|
3534
|
+
this.options = options;
|
|
3535
|
+
this.doublets = [];
|
|
3536
|
+
this.tuples = [];
|
|
3537
|
+
this.created = new Map;
|
|
3538
|
+
this.powers = [["i", 1n]];
|
|
3539
|
+
}
|
|
3540
|
+
link(items) {
|
|
3541
|
+
const key = items.map(([k, v]) => `${k}${v}`).join(",");
|
|
3542
|
+
if (!this.created.has(key)) {
|
|
3543
|
+
const doublet = items.length === 2 && items.every(([k]) => k !== "t"), target = doublet ? this.doublets : this.tuples;
|
|
3544
|
+
const node = [doublet ? "d" : "t", BigInt(target.length)];
|
|
3545
|
+
target.push(items);
|
|
3546
|
+
this.created.set(key, node);
|
|
3547
|
+
}
|
|
3548
|
+
return this.created.get(key);
|
|
3549
|
+
}
|
|
3550
|
+
chain(items) {
|
|
3551
|
+
let tail = ["i", 0n];
|
|
3552
|
+
for (let i = items.length - 1;i >= 0; i--)
|
|
3553
|
+
tail = this.link([items[i], tail]);
|
|
3554
|
+
return tail;
|
|
3555
|
+
}
|
|
3556
|
+
typed(marker, elements) {
|
|
3557
|
+
const items = [["i", BigInt(marker)], ...elements];
|
|
3558
|
+
return items.length !== 2 && this.options.arity.contains(items.length) ? this.link(items) : this.link([items[0], this.chain(elements)]);
|
|
3559
|
+
}
|
|
3560
|
+
list(elements) {
|
|
3561
|
+
if (!elements.length)
|
|
3562
|
+
return ["i", 0n];
|
|
3563
|
+
return elements.length === 2 || this.options.arity.contains(elements.length) ? this.link(elements) : this.typed(4, elements);
|
|
3564
|
+
}
|
|
3565
|
+
unary(value) {
|
|
3566
|
+
const powers = [];
|
|
3567
|
+
for (let bit = 63;bit >= 0; bit--)
|
|
3568
|
+
if (value & 1n << BigInt(bit)) {
|
|
3569
|
+
while (this.powers.length <= bit) {
|
|
3570
|
+
const p = this.powers.at(-1);
|
|
3571
|
+
this.powers.push(this.link([p, p]));
|
|
3572
|
+
}
|
|
3573
|
+
powers.push(this.powers[bit]);
|
|
3574
|
+
}
|
|
3575
|
+
let sum = powers.pop() ?? ["i", 0n];
|
|
3576
|
+
while (powers.length)
|
|
3577
|
+
sum = this.link([powers.pop(), sum]);
|
|
3578
|
+
return sum;
|
|
3579
|
+
}
|
|
3580
|
+
scalar(value) {
|
|
3581
|
+
return this.options.externalReferences && value < 1n << 63n ? ["e", value] : this.unary(value);
|
|
3582
|
+
}
|
|
3583
|
+
reference(text) {
|
|
3584
|
+
if (/^(0|[1-9][0-9]*)$/.test(text) && text.length <= 20 && BigInt(text) <= U64) {
|
|
3585
|
+
const value = BigInt(text);
|
|
3586
|
+
return this.options.externalReferences && value < 1n << 63n ? ["e", value] : this.link([["i", 2n], this.unary(value)]);
|
|
3587
|
+
}
|
|
3588
|
+
return this.typed(3, Array.from(text, (c) => this.scalar(BigInt(c.codePointAt(0)))));
|
|
3589
|
+
}
|
|
3590
|
+
encode(node) {
|
|
3591
|
+
if (node.id !== null && !node.values.length)
|
|
3592
|
+
return this.reference(node.id);
|
|
3593
|
+
if (node.id !== null) {
|
|
3594
|
+
const id = this.reference(node.id);
|
|
3595
|
+
return this.typed(5, [id, ...node.values.map((v) => this.encode(v))]);
|
|
3596
|
+
}
|
|
3597
|
+
return this.list(node.values.map((v) => this.encode(v)));
|
|
3598
|
+
}
|
|
3599
|
+
finish() {
|
|
3600
|
+
const resolve = ([k, v]) => k === "e" ? new External(v) : k === "i" ? v : 6n + v + (k === "t" ? BigInt(this.doublets.length) : 0n);
|
|
3601
|
+
return LinksPacket.pack(this.options.externalReferences, this.doublets.concat(this.tuples).map((items, i) => [6n + BigInt(i), items.map(resolve)]), this.options.packedWidths);
|
|
3602
|
+
}
|
|
3603
|
+
}
|
|
3604
|
+
|
|
3605
|
+
class Decoder {
|
|
3606
|
+
constructor(packet, limits) {
|
|
3607
|
+
packet.validate(limits);
|
|
3608
|
+
this.limits = limits;
|
|
3609
|
+
this.links = [];
|
|
3610
|
+
this.unary = [];
|
|
3611
|
+
this.nodes = limits.maxNodes;
|
|
3612
|
+
this.strings = limits.maxStringBytes;
|
|
3613
|
+
for (const [address, refs] of packet.links()) {
|
|
3614
|
+
requireValue(address === 6n + BigInt(this.links.length) && refs.every((r) => r instanceof External || r < address), "document addresses must be contiguous and references backward");
|
|
3615
|
+
const value = (r) => r instanceof External ? null : r <= 1n ? r : r >= 6n ? this.unary[Number(r - 6n)] : null;
|
|
3616
|
+
const a = refs.length === 2 ? value(refs[0]) : null, b = refs.length === 2 ? value(refs[1]) : null;
|
|
3617
|
+
this.unary.push(a !== null && b !== null && a + b <= U64 ? a + b : null);
|
|
3618
|
+
this.links.push(refs);
|
|
3619
|
+
}
|
|
3620
|
+
}
|
|
3621
|
+
chain(tail) {
|
|
3622
|
+
const elements = [];
|
|
3623
|
+
while (tail !== 0n) {
|
|
3624
|
+
requireValue(typeof tail === "bigint" && tail >= 6n, "broken chain");
|
|
3625
|
+
const items = this.links[Number(tail - 6n)];
|
|
3626
|
+
requireValue(items.length === 2 && elements.length < this.limits.maxNodes, "broken or excessive chain");
|
|
3627
|
+
elements.push(items[0]);
|
|
3628
|
+
tail = items[1];
|
|
3629
|
+
}
|
|
3630
|
+
return elements;
|
|
3631
|
+
}
|
|
3632
|
+
number(r) {
|
|
3633
|
+
const value = r instanceof External ? r.value : r <= 1n ? r : r >= 6n ? this.unary[Number(r - 6n)] : null;
|
|
3634
|
+
requireValue(value !== null, "expected unary number");
|
|
3635
|
+
return value;
|
|
3636
|
+
}
|
|
3637
|
+
text(text) {
|
|
3638
|
+
this.strings -= new globalThis.TextEncoder().encode(text).length;
|
|
3639
|
+
requireValue(this.strings >= 0, "string budget exceeded");
|
|
3640
|
+
return new Link(text);
|
|
3641
|
+
}
|
|
3642
|
+
decode(r, depth) {
|
|
3643
|
+
requireValue(depth < this.limits.maxDepth && --this.nodes >= 0, "node or depth budget exceeded");
|
|
3644
|
+
if (r instanceof External)
|
|
3645
|
+
return this.text(String(r.value));
|
|
3646
|
+
if (r === 0n)
|
|
3647
|
+
return new Link;
|
|
3648
|
+
requireValue(r >= 6n, "standalone marker");
|
|
3649
|
+
const items = this.links[Number(r - 6n)];
|
|
3650
|
+
let elements;
|
|
3651
|
+
if (typeof items[0] === "bigint" && items[0] >= 1n && items[0] <= 5n) {
|
|
3652
|
+
const marker = Number(items[0]);
|
|
3653
|
+
elements = items.length !== 2 || marker === 2 ? items.slice(1) : this.chain(items[1]);
|
|
3654
|
+
if (marker === 2) {
|
|
3655
|
+
requireValue(elements.length === 1, "number needs one value");
|
|
3656
|
+
return this.text(String(this.number(elements[0])));
|
|
3657
|
+
}
|
|
3658
|
+
if (marker === 3) {
|
|
3659
|
+
const chars = [];
|
|
3660
|
+
let byteCount = 0;
|
|
3661
|
+
for (const e of elements) {
|
|
3662
|
+
const p = this.number(e);
|
|
3663
|
+
requireValue(p <= 0x10ffffn && !(p >= 0xd800n && p <= 0xdfffn), "invalid Unicode scalar");
|
|
3664
|
+
const size = p <= 0x7fn ? 1 : p <= 0x7ffn ? 2 : p <= 0xffffn ? 3 : 4;
|
|
3665
|
+
requireValue(size <= this.strings - byteCount, "string budget exceeded");
|
|
3666
|
+
byteCount += size;
|
|
3667
|
+
chars.push(String.fromCodePoint(Number(p)));
|
|
3668
|
+
}
|
|
3669
|
+
return this.text(chars.join(""));
|
|
3670
|
+
}
|
|
3671
|
+
if (marker === 5) {
|
|
3672
|
+
requireValue(elements.length > 0, "identified needs id");
|
|
3673
|
+
const id = this.decode(elements[0], depth);
|
|
3674
|
+
requireValue(id.id !== null && !id.values.length, "id must be reference");
|
|
3675
|
+
return new Link(id.id, elements.slice(1).map((e) => this.decode(e, depth + 1)));
|
|
3676
|
+
}
|
|
3677
|
+
requireValue(marker === 4, "invalid typed marker");
|
|
3678
|
+
} else
|
|
3679
|
+
elements = items;
|
|
3680
|
+
return new Link(null, elements.map((e) => this.decode(e, depth + 1)));
|
|
3681
|
+
}
|
|
3682
|
+
document() {
|
|
3683
|
+
if (!this.links.length)
|
|
3684
|
+
return [];
|
|
3685
|
+
const root = this.links.at(-1);
|
|
3686
|
+
let elements;
|
|
3687
|
+
if (root.length === 2 && root[0] === 4n)
|
|
3688
|
+
elements = this.chain(root[1]);
|
|
3689
|
+
else {
|
|
3690
|
+
requireValue(!(typeof root[0] === "bigint" && root[0] >= 1n && root[0] <= 5n), "root must be list");
|
|
3691
|
+
elements = root;
|
|
3692
|
+
}
|
|
3693
|
+
return elements.map((e) => this.decode(e, 0));
|
|
3694
|
+
}
|
|
3695
|
+
}
|
|
3696
|
+
function canonical(node) {
|
|
3697
|
+
if (node.id === null && node.values.length === 1 && node.values[0].id !== null && !node.values[0].values.length)
|
|
3698
|
+
return node.values[0];
|
|
3699
|
+
return new Link(node.id, node.values.map(canonical));
|
|
3700
|
+
}
|
|
3701
|
+
function formatBinaryReference(text) {
|
|
3702
|
+
return formatReference(text);
|
|
3703
|
+
}
|
|
3704
|
+
function formatBinaryDocument(document) {
|
|
3705
|
+
function nested(node, top = false) {
|
|
3706
|
+
if (node.id !== null && !node.values.length)
|
|
3707
|
+
return formatBinaryReference(node.id);
|
|
3708
|
+
const values = node.values.map((v) => nested(v)).join(" ");
|
|
3709
|
+
if (node.id !== null)
|
|
3710
|
+
return `(${formatBinaryReference(node.id)}: ${values})`;
|
|
3711
|
+
if (node.values.length === 1 && node.values[0].id !== null && !node.values[0].values.length)
|
|
3712
|
+
return `((${values}))`;
|
|
3713
|
+
return top && node.values.length >= 2 ? values : `(${values})`;
|
|
3714
|
+
}
|
|
3715
|
+
return document.map((n) => nested(n, true)).join(`
|
|
3716
|
+
`);
|
|
3717
|
+
}
|
|
3718
|
+
|
|
3719
|
+
class BinaryLinoCodec {
|
|
3720
|
+
constructor(options = new BinaryLinoOptions, limits = new DecodeLimits) {
|
|
3721
|
+
Object.assign(this, { options, limits });
|
|
3722
|
+
}
|
|
3723
|
+
encodePacket(document) {
|
|
3724
|
+
requireValue(this.options.arity.contains(2), "arity must contain 2");
|
|
3725
|
+
const pending = document.map((n) => [n, 0]);
|
|
3726
|
+
let nodes = 0, strings = 0;
|
|
3727
|
+
while (pending.length) {
|
|
3728
|
+
const [n, depth] = pending.pop();
|
|
3729
|
+
requireValue(n instanceof Link && depth < this.limits.maxDepth, "invalid model or excessive depth");
|
|
3730
|
+
nodes += 1 + Number(n.id !== null && n.values.length > 0);
|
|
3731
|
+
if (n.id !== null) {
|
|
3732
|
+
requireValue(typeof n.id === "string" && n.id.isWellFormed(), "invalid Unicode string");
|
|
3733
|
+
strings += new globalThis.TextEncoder().encode(n.id).length;
|
|
3734
|
+
}
|
|
3735
|
+
requireValue(nodes <= this.limits.maxNodes && strings <= this.limits.maxStringBytes, "model budget exceeded");
|
|
3736
|
+
for (const v of n.values)
|
|
3737
|
+
pending.push([v, depth + 1]);
|
|
3738
|
+
}
|
|
3739
|
+
const encoder = new Encoder(this.options);
|
|
3740
|
+
if (document.length)
|
|
3741
|
+
encoder.list(document.map((n) => encoder.encode(n)));
|
|
3742
|
+
return encoder.finish().validate(this.limits);
|
|
3743
|
+
}
|
|
3744
|
+
encode(document) {
|
|
3745
|
+
return this.encodePacket(document).toBytes(this.limits);
|
|
3746
|
+
}
|
|
3747
|
+
decodePacket(packet) {
|
|
3748
|
+
return new Decoder(packet, this.limits).document();
|
|
3749
|
+
}
|
|
3750
|
+
decode(bytes) {
|
|
3751
|
+
return this.decodePacket(LinksPacket.fromBytes(bytes, this.limits));
|
|
3752
|
+
}
|
|
3753
|
+
parseDocument(text, parser = new Parser) {
|
|
3754
|
+
return parser.parse(text).map(canonical);
|
|
3755
|
+
}
|
|
3756
|
+
formatDocument(document) {
|
|
3757
|
+
return formatBinaryDocument(document);
|
|
3758
|
+
}
|
|
3759
|
+
encodeText(text, parser) {
|
|
3760
|
+
return this.encode(this.parseDocument(text, parser));
|
|
3761
|
+
}
|
|
3762
|
+
decodeText(bytes) {
|
|
3763
|
+
return this.formatDocument(this.decode(bytes));
|
|
3764
|
+
}
|
|
3765
|
+
}
|
|
2983
3766
|
export {
|
|
3767
|
+
ArityRange,
|
|
3768
|
+
BinaryLinoCodec,
|
|
3769
|
+
BinaryLinoOptions,
|
|
2984
3770
|
DEFAULT_MAX_DEPTH,
|
|
3771
|
+
DecodeLimits,
|
|
3772
|
+
External,
|
|
2985
3773
|
FormatConfig,
|
|
2986
3774
|
FormatOptions,
|
|
2987
3775
|
Link,
|
|
2988
3776
|
LinksGroup,
|
|
3777
|
+
LinksPacket,
|
|
3778
|
+
PacketReader,
|
|
2989
3779
|
ParseError,
|
|
2990
3780
|
Parser,
|
|
3781
|
+
Section,
|
|
2991
3782
|
StreamParseError,
|
|
2992
3783
|
StreamParser,
|
|
3784
|
+
decodeReferenceLiteral,
|
|
3785
|
+
encodeReferenceLiteral,
|
|
3786
|
+
formatBinaryDocument,
|
|
3787
|
+
formatBinaryReference,
|
|
2993
3788
|
formatLinks,
|
|
2994
3789
|
stripComments
|
|
2995
3790
|
};
|