@researai/deepscientist 1.5.15 → 1.5.17
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 +385 -104
- package/bin/ds.js +1241 -110
- package/docs/en/00_QUICK_START.md +100 -19
- package/docs/en/01_SETTINGS_REFERENCE.md +34 -1
- package/docs/en/02_START_RESEARCH_GUIDE.md +7 -0
- package/docs/en/05_TUI_GUIDE.md +6 -0
- package/docs/en/06_RUNTIME_AND_CANVAS.md +4 -3
- package/docs/en/09_DOCTOR.md +25 -8
- package/docs/en/14_PROMPT_SKILLS_AND_MCP_GUIDE.md +63 -13
- package/docs/en/15_CODEX_PROVIDER_SETUP.md +37 -11
- package/docs/en/19_EXTERNAL_CONTROLLER_GUIDE.md +226 -0
- package/docs/en/19_LOCAL_BROWSER_AUTH.md +70 -0
- package/docs/en/20_WORKSPACE_MODES_GUIDE.md +250 -0
- package/docs/en/21_LOCAL_MODEL_BACKENDS_GUIDE.md +283 -0
- package/docs/en/91_DEVELOPMENT.md +237 -0
- package/docs/en/README.md +24 -2
- package/docs/zh/00_QUICK_START.md +89 -19
- package/docs/zh/01_SETTINGS_REFERENCE.md +34 -1
- package/docs/zh/02_START_RESEARCH_GUIDE.md +7 -0
- package/docs/zh/05_TUI_GUIDE.md +6 -0
- package/docs/zh/09_DOCTOR.md +26 -9
- package/docs/zh/14_PROMPT_SKILLS_AND_MCP_GUIDE.md +63 -13
- package/docs/zh/15_CODEX_PROVIDER_SETUP.md +37 -11
- package/docs/zh/19_EXTERNAL_CONTROLLER_GUIDE.md +226 -0
- package/docs/zh/19_LOCAL_BROWSER_AUTH.md +68 -0
- package/docs/zh/20_WORKSPACE_MODES_GUIDE.md +251 -0
- package/docs/zh/21_LOCAL_MODEL_BACKENDS_GUIDE.md +281 -0
- package/docs/zh/README.md +24 -2
- package/install.sh +46 -4
- package/package.json +2 -1
- package/pyproject.toml +1 -1
- package/src/deepscientist/__init__.py +1 -1
- package/src/deepscientist/acp/envelope.py +6 -0
- package/src/deepscientist/artifact/service.py +647 -22
- package/src/deepscientist/bash_exec/service.py +234 -9
- package/src/deepscientist/bridges/connectors.py +8 -2
- package/src/deepscientist/cli.py +115 -19
- package/src/deepscientist/codex_cli_compat.py +367 -22
- package/src/deepscientist/config/models.py +2 -1
- package/src/deepscientist/config/service.py +183 -13
- package/src/deepscientist/daemon/api/handlers.py +255 -31
- package/src/deepscientist/daemon/api/router.py +9 -0
- package/src/deepscientist/daemon/app.py +1146 -105
- package/src/deepscientist/diagnostics/__init__.py +6 -0
- package/src/deepscientist/diagnostics/runner_failures.py +130 -0
- package/src/deepscientist/doctor.py +207 -3
- package/src/deepscientist/gitops/__init__.py +10 -1
- package/src/deepscientist/gitops/diff.py +129 -0
- package/src/deepscientist/gitops/service.py +4 -1
- package/src/deepscientist/mcp/server.py +39 -0
- package/src/deepscientist/prompts/builder.py +275 -34
- package/src/deepscientist/quest/layout.py +15 -2
- package/src/deepscientist/quest/service.py +707 -55
- package/src/deepscientist/quest/stage_views.py +6 -1
- package/src/deepscientist/runners/codex.py +143 -43
- package/src/deepscientist/shared.py +19 -0
- package/src/deepscientist/skills/__init__.py +2 -2
- package/src/deepscientist/skills/installer.py +196 -5
- package/src/deepscientist/skills/registry.py +66 -0
- package/src/prompts/connectors/qq.md +18 -8
- package/src/prompts/connectors/weixin.md +16 -6
- package/src/prompts/contracts/shared_interaction.md +14 -2
- package/src/prompts/system.md +23 -5
- package/src/prompts/system_copilot.md +56 -0
- package/src/skills/analysis-campaign/SKILL.md +1 -0
- package/src/skills/baseline/SKILL.md +8 -0
- package/src/skills/decision/SKILL.md +8 -0
- package/src/skills/experiment/SKILL.md +8 -0
- package/src/skills/figure-polish/SKILL.md +1 -0
- package/src/skills/finalize/SKILL.md +1 -0
- package/src/skills/idea/SKILL.md +1 -0
- package/src/skills/intake-audit/SKILL.md +8 -0
- package/src/skills/mentor/SKILL.md +217 -0
- package/src/skills/mentor/references/correction-rules.md +210 -0
- package/src/skills/mentor/references/knowledge-profile.md +91 -0
- package/src/skills/mentor/references/persona-profile.md +138 -0
- package/src/skills/mentor/references/taste-profile.md +128 -0
- package/src/skills/mentor/references/thought-style-profile.md +138 -0
- package/src/skills/mentor/references/work-profile.md +289 -0
- package/src/skills/mentor/references/workflow-profile.md +240 -0
- package/src/skills/optimize/SKILL.md +1 -0
- package/src/skills/rebuttal/SKILL.md +1 -0
- package/src/skills/review/SKILL.md +1 -0
- package/src/skills/scout/SKILL.md +8 -0
- package/src/skills/write/SKILL.md +1 -0
- package/src/tui/dist/app/AppContainer.js +19 -11
- package/src/tui/dist/index.js +4 -1
- package/src/tui/dist/lib/api.js +33 -3
- package/src/tui/package.json +1 -1
- package/src/ui/dist/assets/AiManusChatView-Bv-Z8YpU.js +204 -0
- package/src/ui/dist/assets/AnalysisPlugin-BCKAfjba.js +1 -0
- package/src/ui/dist/assets/CliPlugin-BCKcpc35.js +109 -0
- package/src/ui/dist/assets/CodeEditorPlugin-DbOfSJ8K.js +2 -0
- package/src/ui/dist/assets/CodeViewerPlugin-CbaFRrUU.js +270 -0
- package/src/ui/dist/assets/DocViewerPlugin-DAjLVeQD.js +7 -0
- package/src/ui/dist/assets/GitCommitViewerPlugin-CIUqbUDO.js +1 -0
- package/src/ui/dist/assets/GitDiffViewerPlugin-CQACjoAA.js +6 -0
- package/src/ui/dist/assets/GitSnapshotViewer-0r4nLPke.js +30 -0
- package/src/ui/dist/assets/ImageViewerPlugin-nBOmI2v_.js +26 -0
- package/src/ui/dist/assets/LabCopilotPanel-BHxOxF4z.js +14 -0
- package/src/ui/dist/assets/LabPlugin-BKoZGs95.js +22 -0
- package/src/ui/dist/assets/LatexPlugin-ZwtV8pIp.js +25 -0
- package/src/ui/dist/assets/MarkdownViewerPlugin-DKqVfKyW.js +128 -0
- package/src/ui/dist/assets/MarketplacePlugin-BwxStZ9D.js +13 -0
- package/src/ui/dist/assets/NotebookEditor-BEQhaQbt.js +81 -0
- package/src/ui/dist/assets/{NotebookEditor-CccQYZjX.css → NotebookEditor-BHH8rdGj.css} +1 -1
- package/src/ui/dist/assets/NotebookEditor-BOr3x3Ej.css +1 -0
- package/src/ui/dist/assets/NotebookEditor-DB9N_T9q.js +361 -0
- package/src/ui/dist/assets/PdfLoader-Cy5jtWrr.css +1 -0
- package/src/ui/dist/assets/PdfLoader-eWBONbQP.js +16 -0
- package/src/ui/dist/assets/PdfMarkdownPlugin-D22YOZL3.js +1 -0
- package/src/ui/dist/assets/PdfViewerPlugin-c-RK9DLM.js +17 -0
- package/src/ui/dist/assets/PdfViewerPlugin-nwwE-fjJ.css +1 -0
- package/src/ui/dist/assets/SearchPlugin-CxF9ytAx.js +16 -0
- package/src/ui/dist/assets/SearchPlugin-DA4en4hK.css +1 -0
- package/src/ui/dist/assets/TextViewerPlugin-C5xqeeUH.js +54 -0
- package/src/ui/dist/assets/VNCViewer-BoLGLnHz.js +11 -0
- package/src/ui/dist/assets/bot-DREQOxzP.js +6 -0
- package/src/ui/dist/assets/browser-CTB2jwNe.js +8 -0
- package/src/ui/dist/assets/chevron-up-C9Qpx4DE.js +6 -0
- package/src/ui/dist/assets/code-WlFHE7z_.js +6 -0
- package/src/ui/dist/assets/file-content-BZMz3RYp.js +1 -0
- package/src/ui/dist/assets/file-diff-panel-CQhw0jS2.js +1 -0
- package/src/ui/dist/assets/file-jump-queue-DA-SdG__.js +1 -0
- package/src/ui/dist/assets/file-socket-CfQPKQKj.js +1 -0
- package/src/ui/dist/assets/git-commit-horizontal-DxZ8DCZh.js +6 -0
- package/src/ui/dist/assets/image-Bgl4VIyx.js +6 -0
- package/src/ui/dist/assets/index-BpV6lusQ.css +33 -0
- package/src/ui/dist/assets/index-CBNVuWcP.js +2496 -0
- package/src/ui/dist/assets/index-CwNu1aH4.js +11 -0
- package/src/ui/dist/assets/index-DrUnlf6K.js +1 -0
- package/src/ui/dist/assets/index-NW-h8VzN.js +1 -0
- package/src/ui/dist/assets/monaco-CiHMMNH_.js +1 -0
- package/src/ui/dist/assets/pdf-effect-queue-J8OnM0jE.js +6 -0
- package/src/ui/dist/assets/plugin-monaco-C8UgLomw.js +19 -0
- package/src/ui/dist/assets/plugin-notebook-HbW2K-1c.js +169 -0
- package/src/ui/dist/assets/plugin-pdf-CR8hgQBV.js +357 -0
- package/src/ui/dist/assets/plugin-terminal-MXFIPun8.js +227 -0
- package/src/ui/dist/assets/popover-CLc0pPP8.js +1 -0
- package/src/ui/dist/assets/project-sync-C9IdzdZW.js +1 -0
- package/src/ui/dist/assets/select-Cs2PmzwL.js +11 -0
- package/src/ui/dist/assets/sigma-ClKcHAXm.js +6 -0
- package/src/ui/dist/assets/trash-DwpbFr3w.js +11 -0
- package/src/ui/dist/assets/useCliAccess-NQ8m0Let.js +1 -0
- package/src/ui/dist/assets/useFileDiffOverlay-FuhcnKiw.js +1 -0
- package/src/ui/dist/assets/wrap-text-BC-Hltpd.js +11 -0
- package/src/ui/dist/assets/zoom-out-E_gaeAxL.js +11 -0
- package/src/ui/dist/index.html +5 -2
- package/src/ui/dist/assets/AiManusChatView-DDjbFnbt.js +0 -26597
- package/src/ui/dist/assets/AnalysisPlugin-Yb5IdmaU.js +0 -123
- package/src/ui/dist/assets/CliPlugin-e64sreyu.js +0 -31037
- package/src/ui/dist/assets/CodeEditorPlugin-C4D2TIkU.js +0 -427
- package/src/ui/dist/assets/CodeViewerPlugin-BVoNZIvC.js +0 -905
- package/src/ui/dist/assets/DocViewerPlugin-CLChbllo.js +0 -278
- package/src/ui/dist/assets/GitDiffViewerPlugin-C4xeFyFQ.js +0 -2661
- package/src/ui/dist/assets/ImageViewerPlugin-OiMUAcLi.js +0 -500
- package/src/ui/dist/assets/LabCopilotPanel-BjD2ThQF.js +0 -4104
- package/src/ui/dist/assets/LabPlugin-DQPg-NrB.js +0 -2677
- package/src/ui/dist/assets/LatexPlugin-CI05XAV9.js +0 -1792
- package/src/ui/dist/assets/MarkdownViewerPlugin-DpeBLYZf.js +0 -308
- package/src/ui/dist/assets/MarketplacePlugin-DolE58Q2.js +0 -413
- package/src/ui/dist/assets/NotebookEditor-7Qm2rSWD.js +0 -4214
- package/src/ui/dist/assets/NotebookEditor-C1kWaxKi.js +0 -84873
- package/src/ui/dist/assets/NotebookEditor-C3VQ7ylN.css +0 -1405
- package/src/ui/dist/assets/PdfLoader-BfOHw8Zw.js +0 -25468
- package/src/ui/dist/assets/PdfLoader-C-Y707R3.css +0 -49
- package/src/ui/dist/assets/PdfMarkdownPlugin-BulDREv1.js +0 -409
- package/src/ui/dist/assets/PdfViewerPlugin-C-daaOaL.js +0 -3095
- package/src/ui/dist/assets/PdfViewerPlugin-DQ11QcSf.css +0 -3627
- package/src/ui/dist/assets/SearchPlugin-CjpaiJ3A.js +0 -741
- package/src/ui/dist/assets/SearchPlugin-DDMrGDkh.css +0 -379
- package/src/ui/dist/assets/TextViewerPlugin-BxIyqPQC.js +0 -472
- package/src/ui/dist/assets/VNCViewer-HAg9mF7M.js +0 -18821
- package/src/ui/dist/assets/awareness-C0NPR2Dj.js +0 -292
- package/src/ui/dist/assets/bot-0DYntytV.js +0 -21
- package/src/ui/dist/assets/browser-BAcuE0Xj.js +0 -2895
- package/src/ui/dist/assets/code-B20Slj_w.js +0 -17
- package/src/ui/dist/assets/file-content-DT24KFma.js +0 -377
- package/src/ui/dist/assets/file-diff-panel-DK13YPql.js +0 -92
- package/src/ui/dist/assets/file-jump-queue-r5XKgJEV.js +0 -16
- package/src/ui/dist/assets/file-socket-B4T2o4nR.js +0 -58
- package/src/ui/dist/assets/function-B5QZkkHC.js +0 -1895
- package/src/ui/dist/assets/image-DSeR_sDS.js +0 -18
- package/src/ui/dist/assets/index-BrFje2Uk.js +0 -120
- package/src/ui/dist/assets/index-BwRJaoTl.js +0 -25
- package/src/ui/dist/assets/index-D_E4281X.js +0 -221322
- package/src/ui/dist/assets/index-DnYB3xb1.js +0 -159
- package/src/ui/dist/assets/index-G7AcWcMu.css +0 -12594
- package/src/ui/dist/assets/monaco-LExaAN3Y.js +0 -623
- package/src/ui/dist/assets/pdf-effect-queue-BJk5okWJ.js +0 -47
- package/src/ui/dist/assets/pdf_viewer-e0g1is2C.js +0 -8206
- package/src/ui/dist/assets/popover-D3Gg_FoV.js +0 -476
- package/src/ui/dist/assets/project-sync-C_ygLlVU.js +0 -297
- package/src/ui/dist/assets/select-CpAK6uWm.js +0 -1690
- package/src/ui/dist/assets/sigma-DEccaSgk.js +0 -22
- package/src/ui/dist/assets/square-check-big-uUfyVsbD.js +0 -17
- package/src/ui/dist/assets/trash-CXvwwSe8.js +0 -32
- package/src/ui/dist/assets/useCliAccess-Bnop4mgR.js +0 -957
- package/src/ui/dist/assets/useFileDiffOverlay-B8eUAX0I.js +0 -53
- package/src/ui/dist/assets/wrap-text-9vbOBpkW.js +0 -35
- package/src/ui/dist/assets/yjs-DncrqiZ8.js +0 -11243
- package/src/ui/dist/assets/zoom-out-BgVMmOW4.js +0 -34
|
@@ -1,1895 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Utility module to work with key-value stores.
|
|
3
|
-
*
|
|
4
|
-
* @module map
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* @template K
|
|
9
|
-
* @template V
|
|
10
|
-
* @typedef {Map<K,V>} GlobalMap
|
|
11
|
-
*/
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* Creates a new Map instance.
|
|
15
|
-
*
|
|
16
|
-
* @function
|
|
17
|
-
* @return {Map<any, any>}
|
|
18
|
-
*
|
|
19
|
-
* @function
|
|
20
|
-
*/
|
|
21
|
-
const create$2 = () => new Map();
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* Copy a Map object into a fresh Map object.
|
|
25
|
-
*
|
|
26
|
-
* @function
|
|
27
|
-
* @template K,V
|
|
28
|
-
* @param {Map<K,V>} m
|
|
29
|
-
* @return {Map<K,V>}
|
|
30
|
-
*/
|
|
31
|
-
const copy = m => {
|
|
32
|
-
const r = create$2();
|
|
33
|
-
m.forEach((v, k) => { r.set(k, v); });
|
|
34
|
-
return r
|
|
35
|
-
};
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* Get map property. Create T if property is undefined and set T on map.
|
|
39
|
-
*
|
|
40
|
-
* ```js
|
|
41
|
-
* const listeners = map.setIfUndefined(events, 'eventName', set.create)
|
|
42
|
-
* listeners.add(listener)
|
|
43
|
-
* ```
|
|
44
|
-
*
|
|
45
|
-
* @function
|
|
46
|
-
* @template {Map<any, any>} MAP
|
|
47
|
-
* @template {MAP extends Map<any,infer V> ? function():V : unknown} CF
|
|
48
|
-
* @param {MAP} map
|
|
49
|
-
* @param {MAP extends Map<infer K,any> ? K : unknown} key
|
|
50
|
-
* @param {CF} createT
|
|
51
|
-
* @return {ReturnType<CF>}
|
|
52
|
-
*/
|
|
53
|
-
const setIfUndefined = (map, key, createT) => {
|
|
54
|
-
let set = map.get(key);
|
|
55
|
-
if (set === undefined) {
|
|
56
|
-
map.set(key, set = createT());
|
|
57
|
-
}
|
|
58
|
-
return set
|
|
59
|
-
};
|
|
60
|
-
|
|
61
|
-
/**
|
|
62
|
-
* Creates an Array and populates it with the content of all key-value pairs using the `f(value, key)` function.
|
|
63
|
-
*
|
|
64
|
-
* @function
|
|
65
|
-
* @template K
|
|
66
|
-
* @template V
|
|
67
|
-
* @template R
|
|
68
|
-
* @param {Map<K,V>} m
|
|
69
|
-
* @param {function(V,K):R} f
|
|
70
|
-
* @return {Array<R>}
|
|
71
|
-
*/
|
|
72
|
-
const map = (m, f) => {
|
|
73
|
-
const res = [];
|
|
74
|
-
for (const [key, value] of m) {
|
|
75
|
-
res.push(f(value, key));
|
|
76
|
-
}
|
|
77
|
-
return res
|
|
78
|
-
};
|
|
79
|
-
|
|
80
|
-
/**
|
|
81
|
-
* Tests whether any key-value pairs pass the test implemented by `f(value, key)`.
|
|
82
|
-
*
|
|
83
|
-
* @todo should rename to some - similarly to Array.some
|
|
84
|
-
*
|
|
85
|
-
* @function
|
|
86
|
-
* @template K
|
|
87
|
-
* @template V
|
|
88
|
-
* @param {Map<K,V>} m
|
|
89
|
-
* @param {function(V,K):boolean} f
|
|
90
|
-
* @return {boolean}
|
|
91
|
-
*/
|
|
92
|
-
const any = (m, f) => {
|
|
93
|
-
for (const [key, value] of m) {
|
|
94
|
-
if (f(value, key)) {
|
|
95
|
-
return true
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
return false
|
|
99
|
-
};
|
|
100
|
-
|
|
101
|
-
/**
|
|
102
|
-
* Utility module to work with sets.
|
|
103
|
-
*
|
|
104
|
-
* @module set
|
|
105
|
-
*/
|
|
106
|
-
|
|
107
|
-
const create$1 = () => new Set();
|
|
108
|
-
|
|
109
|
-
/**
|
|
110
|
-
* Utility module to work with Arrays.
|
|
111
|
-
*
|
|
112
|
-
* @module array
|
|
113
|
-
*/
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
/**
|
|
117
|
-
* Return the last element of an array. The element must exist
|
|
118
|
-
*
|
|
119
|
-
* @template L
|
|
120
|
-
* @param {ArrayLike<L>} arr
|
|
121
|
-
* @return {L}
|
|
122
|
-
*/
|
|
123
|
-
const last = arr => arr[arr.length - 1];
|
|
124
|
-
|
|
125
|
-
/**
|
|
126
|
-
* Append elements from src to dest
|
|
127
|
-
*
|
|
128
|
-
* @template M
|
|
129
|
-
* @param {Array<M>} dest
|
|
130
|
-
* @param {Array<M>} src
|
|
131
|
-
*/
|
|
132
|
-
const appendTo = (dest, src) => {
|
|
133
|
-
for (let i = 0; i < src.length; i++) {
|
|
134
|
-
dest.push(src[i]);
|
|
135
|
-
}
|
|
136
|
-
};
|
|
137
|
-
|
|
138
|
-
/**
|
|
139
|
-
* Transforms something array-like to an actual Array.
|
|
140
|
-
*
|
|
141
|
-
* @function
|
|
142
|
-
* @template T
|
|
143
|
-
* @param {ArrayLike<T>|Iterable<T>} arraylike
|
|
144
|
-
* @return {T}
|
|
145
|
-
*/
|
|
146
|
-
const from = Array.from;
|
|
147
|
-
|
|
148
|
-
/**
|
|
149
|
-
* True iff condition holds on every element in the Array.
|
|
150
|
-
*
|
|
151
|
-
* @function
|
|
152
|
-
* @template {ArrayLike<any>} ARR
|
|
153
|
-
*
|
|
154
|
-
* @param {ARR} arr
|
|
155
|
-
* @param {ARR extends ArrayLike<infer S> ? ((value:S, index:number, arr:ARR) => boolean) : any} f
|
|
156
|
-
* @return {boolean}
|
|
157
|
-
*/
|
|
158
|
-
const every$1 = (arr, f) => {
|
|
159
|
-
for (let i = 0; i < arr.length; i++) {
|
|
160
|
-
if (!f(arr[i], i, arr)) {
|
|
161
|
-
return false
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
return true
|
|
165
|
-
};
|
|
166
|
-
|
|
167
|
-
/**
|
|
168
|
-
* True iff condition holds on some element in the Array.
|
|
169
|
-
*
|
|
170
|
-
* @function
|
|
171
|
-
* @template {ArrayLike<any>} ARR
|
|
172
|
-
*
|
|
173
|
-
* @param {ARR} arr
|
|
174
|
-
* @param {ARR extends ArrayLike<infer S> ? ((value:S, index:number, arr:ARR) => boolean) : never} f
|
|
175
|
-
* @return {boolean}
|
|
176
|
-
*/
|
|
177
|
-
const some = (arr, f) => {
|
|
178
|
-
for (let i = 0; i < arr.length; i++) {
|
|
179
|
-
if (f(arr[i], i, arr)) {
|
|
180
|
-
return true
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
return false
|
|
184
|
-
};
|
|
185
|
-
|
|
186
|
-
/**
|
|
187
|
-
* @template T
|
|
188
|
-
* @param {number} len
|
|
189
|
-
* @param {function(number, Array<T>):T} f
|
|
190
|
-
* @return {Array<T>}
|
|
191
|
-
*/
|
|
192
|
-
const unfold = (len, f) => {
|
|
193
|
-
const array = new Array(len);
|
|
194
|
-
for (let i = 0; i < len; i++) {
|
|
195
|
-
array[i] = f(i, array);
|
|
196
|
-
}
|
|
197
|
-
return array
|
|
198
|
-
};
|
|
199
|
-
|
|
200
|
-
const isArray = Array.isArray;
|
|
201
|
-
|
|
202
|
-
/**
|
|
203
|
-
* Observable class prototype.
|
|
204
|
-
*
|
|
205
|
-
* @module observable
|
|
206
|
-
*/
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
/**
|
|
210
|
-
* Handles named events.
|
|
211
|
-
* @experimental
|
|
212
|
-
*
|
|
213
|
-
* This is basically a (better typed) duplicate of Observable, which will replace Observable in the
|
|
214
|
-
* next release.
|
|
215
|
-
*
|
|
216
|
-
* @template {{[key in keyof EVENTS]: function(...any):void}} EVENTS
|
|
217
|
-
*/
|
|
218
|
-
class ObservableV2 {
|
|
219
|
-
constructor () {
|
|
220
|
-
/**
|
|
221
|
-
* Some desc.
|
|
222
|
-
* @type {Map<string, Set<any>>}
|
|
223
|
-
*/
|
|
224
|
-
this._observers = create$2();
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
/**
|
|
228
|
-
* @template {keyof EVENTS & string} NAME
|
|
229
|
-
* @param {NAME} name
|
|
230
|
-
* @param {EVENTS[NAME]} f
|
|
231
|
-
*/
|
|
232
|
-
on (name, f) {
|
|
233
|
-
setIfUndefined(this._observers, /** @type {string} */ (name), create$1).add(f);
|
|
234
|
-
return f
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
/**
|
|
238
|
-
* @template {keyof EVENTS & string} NAME
|
|
239
|
-
* @param {NAME} name
|
|
240
|
-
* @param {EVENTS[NAME]} f
|
|
241
|
-
*/
|
|
242
|
-
once (name, f) {
|
|
243
|
-
/**
|
|
244
|
-
* @param {...any} args
|
|
245
|
-
*/
|
|
246
|
-
const _f = (...args) => {
|
|
247
|
-
this.off(name, /** @type {any} */ (_f));
|
|
248
|
-
f(...args);
|
|
249
|
-
};
|
|
250
|
-
this.on(name, /** @type {any} */ (_f));
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
/**
|
|
254
|
-
* @template {keyof EVENTS & string} NAME
|
|
255
|
-
* @param {NAME} name
|
|
256
|
-
* @param {EVENTS[NAME]} f
|
|
257
|
-
*/
|
|
258
|
-
off (name, f) {
|
|
259
|
-
const observers = this._observers.get(name);
|
|
260
|
-
if (observers !== undefined) {
|
|
261
|
-
observers.delete(f);
|
|
262
|
-
if (observers.size === 0) {
|
|
263
|
-
this._observers.delete(name);
|
|
264
|
-
}
|
|
265
|
-
}
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
/**
|
|
269
|
-
* Emit a named event. All registered event listeners that listen to the
|
|
270
|
-
* specified name will receive the event.
|
|
271
|
-
*
|
|
272
|
-
* @todo This should catch exceptions
|
|
273
|
-
*
|
|
274
|
-
* @template {keyof EVENTS & string} NAME
|
|
275
|
-
* @param {NAME} name The event name.
|
|
276
|
-
* @param {Parameters<EVENTS[NAME]>} args The arguments that are applied to the event listener.
|
|
277
|
-
*/
|
|
278
|
-
emit (name, args) {
|
|
279
|
-
// copy all listeners to an array first to make sure that no event is emitted to listeners that are subscribed while the event handler is called.
|
|
280
|
-
return from((this._observers.get(name) || create$2()).values()).forEach(f => f(...args))
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
destroy () {
|
|
284
|
-
this._observers = create$2();
|
|
285
|
-
}
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
/* c8 ignore start */
|
|
289
|
-
/**
|
|
290
|
-
* Handles named events.
|
|
291
|
-
*
|
|
292
|
-
* @deprecated
|
|
293
|
-
* @template N
|
|
294
|
-
*/
|
|
295
|
-
class Observable {
|
|
296
|
-
constructor () {
|
|
297
|
-
/**
|
|
298
|
-
* Some desc.
|
|
299
|
-
* @type {Map<N, any>}
|
|
300
|
-
*/
|
|
301
|
-
this._observers = create$2();
|
|
302
|
-
}
|
|
303
|
-
|
|
304
|
-
/**
|
|
305
|
-
* @param {N} name
|
|
306
|
-
* @param {function} f
|
|
307
|
-
*/
|
|
308
|
-
on (name, f) {
|
|
309
|
-
setIfUndefined(this._observers, name, create$1).add(f);
|
|
310
|
-
}
|
|
311
|
-
|
|
312
|
-
/**
|
|
313
|
-
* @param {N} name
|
|
314
|
-
* @param {function} f
|
|
315
|
-
*/
|
|
316
|
-
once (name, f) {
|
|
317
|
-
/**
|
|
318
|
-
* @param {...any} args
|
|
319
|
-
*/
|
|
320
|
-
const _f = (...args) => {
|
|
321
|
-
this.off(name, _f);
|
|
322
|
-
f(...args);
|
|
323
|
-
};
|
|
324
|
-
this.on(name, _f);
|
|
325
|
-
}
|
|
326
|
-
|
|
327
|
-
/**
|
|
328
|
-
* @param {N} name
|
|
329
|
-
* @param {function} f
|
|
330
|
-
*/
|
|
331
|
-
off (name, f) {
|
|
332
|
-
const observers = this._observers.get(name);
|
|
333
|
-
if (observers !== undefined) {
|
|
334
|
-
observers.delete(f);
|
|
335
|
-
if (observers.size === 0) {
|
|
336
|
-
this._observers.delete(name);
|
|
337
|
-
}
|
|
338
|
-
}
|
|
339
|
-
}
|
|
340
|
-
|
|
341
|
-
/**
|
|
342
|
-
* Emit a named event. All registered event listeners that listen to the
|
|
343
|
-
* specified name will receive the event.
|
|
344
|
-
*
|
|
345
|
-
* @todo This should catch exceptions
|
|
346
|
-
*
|
|
347
|
-
* @param {N} name The event name.
|
|
348
|
-
* @param {Array<any>} args The arguments that are applied to the event listener.
|
|
349
|
-
*/
|
|
350
|
-
emit (name, args) {
|
|
351
|
-
// copy all listeners to an array first to make sure that no event is emitted to listeners that are subscribed while the event handler is called.
|
|
352
|
-
return from((this._observers.get(name) || create$2()).values()).forEach(f => f(...args))
|
|
353
|
-
}
|
|
354
|
-
|
|
355
|
-
destroy () {
|
|
356
|
-
this._observers = create$2();
|
|
357
|
-
}
|
|
358
|
-
}
|
|
359
|
-
/* c8 ignore end */
|
|
360
|
-
|
|
361
|
-
/**
|
|
362
|
-
* Common Math expressions.
|
|
363
|
-
*
|
|
364
|
-
* @module math
|
|
365
|
-
*/
|
|
366
|
-
|
|
367
|
-
const floor = Math.floor;
|
|
368
|
-
const abs = Math.abs;
|
|
369
|
-
|
|
370
|
-
/**
|
|
371
|
-
* @function
|
|
372
|
-
* @param {number} a
|
|
373
|
-
* @param {number} b
|
|
374
|
-
* @return {number} The smaller element of a and b
|
|
375
|
-
*/
|
|
376
|
-
const min = (a, b) => a < b ? a : b;
|
|
377
|
-
|
|
378
|
-
/**
|
|
379
|
-
* @function
|
|
380
|
-
* @param {number} a
|
|
381
|
-
* @param {number} b
|
|
382
|
-
* @return {number} The bigger element of a and b
|
|
383
|
-
*/
|
|
384
|
-
const max = (a, b) => a > b ? a : b;
|
|
385
|
-
|
|
386
|
-
/**
|
|
387
|
-
* Check whether n is negative, while considering the -0 edge case. While `-0 < 0` is false, this
|
|
388
|
-
* function returns true for -0,-1,,.. and returns false for 0,1,2,...
|
|
389
|
-
* @param {number} n
|
|
390
|
-
* @return {boolean} Wether n is negative. This function also distinguishes between -0 and +0
|
|
391
|
-
*/
|
|
392
|
-
const isNegativeZero = n => n !== 0 ? n < 0 : 1 / n < 0;
|
|
393
|
-
|
|
394
|
-
/* eslint-env browser */
|
|
395
|
-
|
|
396
|
-
/**
|
|
397
|
-
* Binary data constants.
|
|
398
|
-
*
|
|
399
|
-
* @module binary
|
|
400
|
-
*/
|
|
401
|
-
|
|
402
|
-
/**
|
|
403
|
-
* n-th bit activated.
|
|
404
|
-
*
|
|
405
|
-
* @type {number}
|
|
406
|
-
*/
|
|
407
|
-
const BIT1 = 1;
|
|
408
|
-
const BIT2 = 2;
|
|
409
|
-
const BIT3 = 4;
|
|
410
|
-
const BIT4 = 8;
|
|
411
|
-
const BIT6 = 32;
|
|
412
|
-
const BIT7 = 64;
|
|
413
|
-
const BIT8 = 128;
|
|
414
|
-
const BIT30 = 1 << 29;
|
|
415
|
-
const BITS5 = 31;
|
|
416
|
-
const BITS6 = 63;
|
|
417
|
-
const BITS7 = 127;
|
|
418
|
-
/**
|
|
419
|
-
* @type {number}
|
|
420
|
-
*/
|
|
421
|
-
const BITS31 = 0x7FFFFFFF;
|
|
422
|
-
|
|
423
|
-
/**
|
|
424
|
-
* Utility helpers for working with numbers.
|
|
425
|
-
*
|
|
426
|
-
* @module number
|
|
427
|
-
*/
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
const MAX_SAFE_INTEGER = Number.MAX_SAFE_INTEGER;
|
|
431
|
-
const MIN_SAFE_INTEGER = Number.MIN_SAFE_INTEGER;
|
|
432
|
-
|
|
433
|
-
/* c8 ignore next */
|
|
434
|
-
const isInteger = Number.isInteger || (num => typeof num === 'number' && isFinite(num) && floor(num) === num);
|
|
435
|
-
|
|
436
|
-
/**
|
|
437
|
-
* Utility module to work with strings.
|
|
438
|
-
*
|
|
439
|
-
* @module string
|
|
440
|
-
*/
|
|
441
|
-
|
|
442
|
-
const fromCharCode = String.fromCharCode;
|
|
443
|
-
|
|
444
|
-
/**
|
|
445
|
-
* @param {string} s
|
|
446
|
-
* @return {string}
|
|
447
|
-
*/
|
|
448
|
-
const toLowerCase = s => s.toLowerCase();
|
|
449
|
-
|
|
450
|
-
const trimLeftRegex = /^\s*/g;
|
|
451
|
-
|
|
452
|
-
/**
|
|
453
|
-
* @param {string} s
|
|
454
|
-
* @return {string}
|
|
455
|
-
*/
|
|
456
|
-
const trimLeft = s => s.replace(trimLeftRegex, '');
|
|
457
|
-
|
|
458
|
-
const fromCamelCaseRegex = /([A-Z])/g;
|
|
459
|
-
|
|
460
|
-
/**
|
|
461
|
-
* @param {string} s
|
|
462
|
-
* @param {string} separator
|
|
463
|
-
* @return {string}
|
|
464
|
-
*/
|
|
465
|
-
const fromCamelCase = (s, separator) => trimLeft(s.replace(fromCamelCaseRegex, match => `${separator}${toLowerCase(match)}`));
|
|
466
|
-
|
|
467
|
-
/**
|
|
468
|
-
* @param {string} str
|
|
469
|
-
* @return {Uint8Array<ArrayBuffer>}
|
|
470
|
-
*/
|
|
471
|
-
const _encodeUtf8Polyfill = str => {
|
|
472
|
-
const encodedString = unescape(encodeURIComponent(str));
|
|
473
|
-
const len = encodedString.length;
|
|
474
|
-
const buf = new Uint8Array(len);
|
|
475
|
-
for (let i = 0; i < len; i++) {
|
|
476
|
-
buf[i] = /** @type {number} */ (encodedString.codePointAt(i));
|
|
477
|
-
}
|
|
478
|
-
return buf
|
|
479
|
-
};
|
|
480
|
-
|
|
481
|
-
/* c8 ignore next */
|
|
482
|
-
const utf8TextEncoder = /** @type {TextEncoder} */ (typeof TextEncoder !== 'undefined' ? new TextEncoder() : null);
|
|
483
|
-
|
|
484
|
-
/**
|
|
485
|
-
* @param {string} str
|
|
486
|
-
* @return {Uint8Array<ArrayBuffer>}
|
|
487
|
-
*/
|
|
488
|
-
const _encodeUtf8Native = str => utf8TextEncoder.encode(str);
|
|
489
|
-
|
|
490
|
-
/**
|
|
491
|
-
* @param {string} str
|
|
492
|
-
* @return {Uint8Array}
|
|
493
|
-
*/
|
|
494
|
-
/* c8 ignore next */
|
|
495
|
-
const encodeUtf8 = utf8TextEncoder ? _encodeUtf8Native : _encodeUtf8Polyfill;
|
|
496
|
-
|
|
497
|
-
/* c8 ignore next */
|
|
498
|
-
let utf8TextDecoder = typeof TextDecoder === 'undefined' ? null : new TextDecoder('utf-8', { fatal: true, ignoreBOM: true });
|
|
499
|
-
|
|
500
|
-
/* c8 ignore start */
|
|
501
|
-
if (utf8TextDecoder && utf8TextDecoder.decode(new Uint8Array()).length === 1) {
|
|
502
|
-
// Safari doesn't handle BOM correctly.
|
|
503
|
-
// This fixes a bug in Safari 13.0.5 where it produces a BOM the first time it is called.
|
|
504
|
-
// utf8TextDecoder.decode(new Uint8Array()).length === 1 on the first call and
|
|
505
|
-
// utf8TextDecoder.decode(new Uint8Array()).length === 1 on the second call
|
|
506
|
-
// Another issue is that from then on no BOM chars are recognized anymore
|
|
507
|
-
/* c8 ignore next */
|
|
508
|
-
utf8TextDecoder = null;
|
|
509
|
-
}
|
|
510
|
-
|
|
511
|
-
/**
|
|
512
|
-
* @param {string} source
|
|
513
|
-
* @param {number} n
|
|
514
|
-
*/
|
|
515
|
-
const repeat = (source, n) => unfold(n, () => source).join('');
|
|
516
|
-
|
|
517
|
-
/**
|
|
518
|
-
* Efficient schema-less binary encoding with support for variable length encoding.
|
|
519
|
-
*
|
|
520
|
-
* Use [lib0/encoding] with [lib0/decoding]. Every encoding function has a corresponding decoding function.
|
|
521
|
-
*
|
|
522
|
-
* Encodes numbers in little-endian order (least to most significant byte order)
|
|
523
|
-
* and is compatible with Golang's binary encoding (https://golang.org/pkg/encoding/binary/)
|
|
524
|
-
* which is also used in Protocol Buffers.
|
|
525
|
-
*
|
|
526
|
-
* ```js
|
|
527
|
-
* // encoding step
|
|
528
|
-
* const encoder = encoding.createEncoder()
|
|
529
|
-
* encoding.writeVarUint(encoder, 256)
|
|
530
|
-
* encoding.writeVarString(encoder, 'Hello world!')
|
|
531
|
-
* const buf = encoding.toUint8Array(encoder)
|
|
532
|
-
* ```
|
|
533
|
-
*
|
|
534
|
-
* ```js
|
|
535
|
-
* // decoding step
|
|
536
|
-
* const decoder = decoding.createDecoder(buf)
|
|
537
|
-
* decoding.readVarUint(decoder) // => 256
|
|
538
|
-
* decoding.readVarString(decoder) // => 'Hello world!'
|
|
539
|
-
* decoding.hasContent(decoder) // => false - all data is read
|
|
540
|
-
* ```
|
|
541
|
-
*
|
|
542
|
-
* @module encoding
|
|
543
|
-
*/
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
/**
|
|
547
|
-
* A BinaryEncoder handles the encoding to an Uint8Array.
|
|
548
|
-
*/
|
|
549
|
-
class Encoder {
|
|
550
|
-
constructor () {
|
|
551
|
-
this.cpos = 0;
|
|
552
|
-
this.cbuf = new Uint8Array(100);
|
|
553
|
-
/**
|
|
554
|
-
* @type {Array<Uint8Array>}
|
|
555
|
-
*/
|
|
556
|
-
this.bufs = [];
|
|
557
|
-
}
|
|
558
|
-
}
|
|
559
|
-
|
|
560
|
-
/**
|
|
561
|
-
* @function
|
|
562
|
-
* @return {Encoder}
|
|
563
|
-
*/
|
|
564
|
-
const createEncoder = () => new Encoder();
|
|
565
|
-
|
|
566
|
-
/**
|
|
567
|
-
* @param {function(Encoder):void} f
|
|
568
|
-
*/
|
|
569
|
-
const encode = (f) => {
|
|
570
|
-
const encoder = createEncoder();
|
|
571
|
-
f(encoder);
|
|
572
|
-
return toUint8Array(encoder)
|
|
573
|
-
};
|
|
574
|
-
|
|
575
|
-
/**
|
|
576
|
-
* The current length of the encoded data.
|
|
577
|
-
*
|
|
578
|
-
* @function
|
|
579
|
-
* @param {Encoder} encoder
|
|
580
|
-
* @return {number}
|
|
581
|
-
*/
|
|
582
|
-
const length = encoder => {
|
|
583
|
-
let len = encoder.cpos;
|
|
584
|
-
for (let i = 0; i < encoder.bufs.length; i++) {
|
|
585
|
-
len += encoder.bufs[i].length;
|
|
586
|
-
}
|
|
587
|
-
return len
|
|
588
|
-
};
|
|
589
|
-
|
|
590
|
-
/**
|
|
591
|
-
* Transform to Uint8Array.
|
|
592
|
-
*
|
|
593
|
-
* @function
|
|
594
|
-
* @param {Encoder} encoder
|
|
595
|
-
* @return {Uint8Array<ArrayBuffer>} The created ArrayBuffer.
|
|
596
|
-
*/
|
|
597
|
-
const toUint8Array = encoder => {
|
|
598
|
-
const uint8arr = new Uint8Array(length(encoder));
|
|
599
|
-
let curPos = 0;
|
|
600
|
-
for (let i = 0; i < encoder.bufs.length; i++) {
|
|
601
|
-
const d = encoder.bufs[i];
|
|
602
|
-
uint8arr.set(d, curPos);
|
|
603
|
-
curPos += d.length;
|
|
604
|
-
}
|
|
605
|
-
uint8arr.set(new Uint8Array(encoder.cbuf.buffer, 0, encoder.cpos), curPos);
|
|
606
|
-
return uint8arr
|
|
607
|
-
};
|
|
608
|
-
|
|
609
|
-
/**
|
|
610
|
-
* Verify that it is possible to write `len` bytes wtihout checking. If
|
|
611
|
-
* necessary, a new Buffer with the required length is attached.
|
|
612
|
-
*
|
|
613
|
-
* @param {Encoder} encoder
|
|
614
|
-
* @param {number} len
|
|
615
|
-
*/
|
|
616
|
-
const verifyLen = (encoder, len) => {
|
|
617
|
-
const bufferLen = encoder.cbuf.length;
|
|
618
|
-
if (bufferLen - encoder.cpos < len) {
|
|
619
|
-
encoder.bufs.push(new Uint8Array(encoder.cbuf.buffer, 0, encoder.cpos));
|
|
620
|
-
encoder.cbuf = new Uint8Array(max(bufferLen, len) * 2);
|
|
621
|
-
encoder.cpos = 0;
|
|
622
|
-
}
|
|
623
|
-
};
|
|
624
|
-
|
|
625
|
-
/**
|
|
626
|
-
* Write one byte to the encoder.
|
|
627
|
-
*
|
|
628
|
-
* @function
|
|
629
|
-
* @param {Encoder} encoder
|
|
630
|
-
* @param {number} num The byte that is to be encoded.
|
|
631
|
-
*/
|
|
632
|
-
const write = (encoder, num) => {
|
|
633
|
-
const bufferLen = encoder.cbuf.length;
|
|
634
|
-
if (encoder.cpos === bufferLen) {
|
|
635
|
-
encoder.bufs.push(encoder.cbuf);
|
|
636
|
-
encoder.cbuf = new Uint8Array(bufferLen * 2);
|
|
637
|
-
encoder.cpos = 0;
|
|
638
|
-
}
|
|
639
|
-
encoder.cbuf[encoder.cpos++] = num;
|
|
640
|
-
};
|
|
641
|
-
|
|
642
|
-
/**
|
|
643
|
-
* Write one byte as an unsigned integer.
|
|
644
|
-
*
|
|
645
|
-
* @function
|
|
646
|
-
* @param {Encoder} encoder
|
|
647
|
-
* @param {number} num The number that is to be encoded.
|
|
648
|
-
*/
|
|
649
|
-
const writeUint8 = write;
|
|
650
|
-
|
|
651
|
-
/**
|
|
652
|
-
* Write a variable length unsigned integer. Max encodable integer is 2^53.
|
|
653
|
-
*
|
|
654
|
-
* @function
|
|
655
|
-
* @param {Encoder} encoder
|
|
656
|
-
* @param {number} num The number that is to be encoded.
|
|
657
|
-
*/
|
|
658
|
-
const writeVarUint = (encoder, num) => {
|
|
659
|
-
while (num > BITS7) {
|
|
660
|
-
write(encoder, BIT8 | (BITS7 & num));
|
|
661
|
-
num = floor(num / 128); // shift >>> 7
|
|
662
|
-
}
|
|
663
|
-
write(encoder, BITS7 & num);
|
|
664
|
-
};
|
|
665
|
-
|
|
666
|
-
/**
|
|
667
|
-
* Write a variable length integer.
|
|
668
|
-
*
|
|
669
|
-
* We use the 7th bit instead for signaling that this is a negative number.
|
|
670
|
-
*
|
|
671
|
-
* @function
|
|
672
|
-
* @param {Encoder} encoder
|
|
673
|
-
* @param {number} num The number that is to be encoded.
|
|
674
|
-
*/
|
|
675
|
-
const writeVarInt = (encoder, num) => {
|
|
676
|
-
const isNegative = isNegativeZero(num);
|
|
677
|
-
if (isNegative) {
|
|
678
|
-
num = -num;
|
|
679
|
-
}
|
|
680
|
-
// |- whether to continue reading |- whether is negative |- number
|
|
681
|
-
write(encoder, (num > BITS6 ? BIT8 : 0) | (isNegative ? BIT7 : 0) | (BITS6 & num));
|
|
682
|
-
num = floor(num / 64); // shift >>> 6
|
|
683
|
-
// We don't need to consider the case of num === 0 so we can use a different
|
|
684
|
-
// pattern here than above.
|
|
685
|
-
while (num > 0) {
|
|
686
|
-
write(encoder, (num > BITS7 ? BIT8 : 0) | (BITS7 & num));
|
|
687
|
-
num = floor(num / 128); // shift >>> 7
|
|
688
|
-
}
|
|
689
|
-
};
|
|
690
|
-
|
|
691
|
-
/**
|
|
692
|
-
* A cache to store strings temporarily
|
|
693
|
-
*/
|
|
694
|
-
const _strBuffer = new Uint8Array(30000);
|
|
695
|
-
const _maxStrBSize = _strBuffer.length / 3;
|
|
696
|
-
|
|
697
|
-
/**
|
|
698
|
-
* Write a variable length string.
|
|
699
|
-
*
|
|
700
|
-
* @function
|
|
701
|
-
* @param {Encoder} encoder
|
|
702
|
-
* @param {String} str The string that is to be encoded.
|
|
703
|
-
*/
|
|
704
|
-
const _writeVarStringNative = (encoder, str) => {
|
|
705
|
-
if (str.length < _maxStrBSize) {
|
|
706
|
-
// We can encode the string into the existing buffer
|
|
707
|
-
/* c8 ignore next */
|
|
708
|
-
const written = utf8TextEncoder.encodeInto(str, _strBuffer).written || 0;
|
|
709
|
-
writeVarUint(encoder, written);
|
|
710
|
-
for (let i = 0; i < written; i++) {
|
|
711
|
-
write(encoder, _strBuffer[i]);
|
|
712
|
-
}
|
|
713
|
-
} else {
|
|
714
|
-
writeVarUint8Array(encoder, encodeUtf8(str));
|
|
715
|
-
}
|
|
716
|
-
};
|
|
717
|
-
|
|
718
|
-
/**
|
|
719
|
-
* Write a variable length string.
|
|
720
|
-
*
|
|
721
|
-
* @function
|
|
722
|
-
* @param {Encoder} encoder
|
|
723
|
-
* @param {String} str The string that is to be encoded.
|
|
724
|
-
*/
|
|
725
|
-
const _writeVarStringPolyfill = (encoder, str) => {
|
|
726
|
-
const encodedString = unescape(encodeURIComponent(str));
|
|
727
|
-
const len = encodedString.length;
|
|
728
|
-
writeVarUint(encoder, len);
|
|
729
|
-
for (let i = 0; i < len; i++) {
|
|
730
|
-
write(encoder, /** @type {number} */ (encodedString.codePointAt(i)));
|
|
731
|
-
}
|
|
732
|
-
};
|
|
733
|
-
|
|
734
|
-
/**
|
|
735
|
-
* Write a variable length string.
|
|
736
|
-
*
|
|
737
|
-
* @function
|
|
738
|
-
* @param {Encoder} encoder
|
|
739
|
-
* @param {String} str The string that is to be encoded.
|
|
740
|
-
*/
|
|
741
|
-
/* c8 ignore next */
|
|
742
|
-
const writeVarString = (utf8TextEncoder && /** @type {any} */ (utf8TextEncoder).encodeInto) ? _writeVarStringNative : _writeVarStringPolyfill;
|
|
743
|
-
|
|
744
|
-
/**
|
|
745
|
-
* Append fixed-length Uint8Array to the encoder.
|
|
746
|
-
*
|
|
747
|
-
* @function
|
|
748
|
-
* @param {Encoder} encoder
|
|
749
|
-
* @param {Uint8Array} uint8Array
|
|
750
|
-
*/
|
|
751
|
-
const writeUint8Array = (encoder, uint8Array) => {
|
|
752
|
-
const bufferLen = encoder.cbuf.length;
|
|
753
|
-
const cpos = encoder.cpos;
|
|
754
|
-
const leftCopyLen = min(bufferLen - cpos, uint8Array.length);
|
|
755
|
-
const rightCopyLen = uint8Array.length - leftCopyLen;
|
|
756
|
-
encoder.cbuf.set(uint8Array.subarray(0, leftCopyLen), cpos);
|
|
757
|
-
encoder.cpos += leftCopyLen;
|
|
758
|
-
if (rightCopyLen > 0) {
|
|
759
|
-
// Still something to write, write right half..
|
|
760
|
-
// Append new buffer
|
|
761
|
-
encoder.bufs.push(encoder.cbuf);
|
|
762
|
-
// must have at least size of remaining buffer
|
|
763
|
-
encoder.cbuf = new Uint8Array(max(bufferLen * 2, rightCopyLen));
|
|
764
|
-
// copy array
|
|
765
|
-
encoder.cbuf.set(uint8Array.subarray(leftCopyLen));
|
|
766
|
-
encoder.cpos = rightCopyLen;
|
|
767
|
-
}
|
|
768
|
-
};
|
|
769
|
-
|
|
770
|
-
/**
|
|
771
|
-
* Append an Uint8Array to Encoder.
|
|
772
|
-
*
|
|
773
|
-
* @function
|
|
774
|
-
* @param {Encoder} encoder
|
|
775
|
-
* @param {Uint8Array} uint8Array
|
|
776
|
-
*/
|
|
777
|
-
const writeVarUint8Array = (encoder, uint8Array) => {
|
|
778
|
-
writeVarUint(encoder, uint8Array.byteLength);
|
|
779
|
-
writeUint8Array(encoder, uint8Array);
|
|
780
|
-
};
|
|
781
|
-
|
|
782
|
-
/**
|
|
783
|
-
* Create an DataView of the next `len` bytes. Use it to write data after
|
|
784
|
-
* calling this function.
|
|
785
|
-
*
|
|
786
|
-
* ```js
|
|
787
|
-
* // write float32 using DataView
|
|
788
|
-
* const dv = writeOnDataView(encoder, 4)
|
|
789
|
-
* dv.setFloat32(0, 1.1)
|
|
790
|
-
* // read float32 using DataView
|
|
791
|
-
* const dv = readFromDataView(encoder, 4)
|
|
792
|
-
* dv.getFloat32(0) // => 1.100000023841858 (leaving it to the reader to find out why this is the correct result)
|
|
793
|
-
* ```
|
|
794
|
-
*
|
|
795
|
-
* @param {Encoder} encoder
|
|
796
|
-
* @param {number} len
|
|
797
|
-
* @return {DataView}
|
|
798
|
-
*/
|
|
799
|
-
const writeOnDataView = (encoder, len) => {
|
|
800
|
-
verifyLen(encoder, len);
|
|
801
|
-
const dview = new DataView(encoder.cbuf.buffer, encoder.cpos, len);
|
|
802
|
-
encoder.cpos += len;
|
|
803
|
-
return dview
|
|
804
|
-
};
|
|
805
|
-
|
|
806
|
-
/**
|
|
807
|
-
* @param {Encoder} encoder
|
|
808
|
-
* @param {number} num
|
|
809
|
-
*/
|
|
810
|
-
const writeFloat32 = (encoder, num) => writeOnDataView(encoder, 4).setFloat32(0, num, false);
|
|
811
|
-
|
|
812
|
-
/**
|
|
813
|
-
* @param {Encoder} encoder
|
|
814
|
-
* @param {number} num
|
|
815
|
-
*/
|
|
816
|
-
const writeFloat64 = (encoder, num) => writeOnDataView(encoder, 8).setFloat64(0, num, false);
|
|
817
|
-
|
|
818
|
-
/**
|
|
819
|
-
* @param {Encoder} encoder
|
|
820
|
-
* @param {bigint} num
|
|
821
|
-
*/
|
|
822
|
-
const writeBigInt64 = (encoder, num) => /** @type {any} */ (writeOnDataView(encoder, 8)).setBigInt64(0, num, false);
|
|
823
|
-
|
|
824
|
-
const floatTestBed = new DataView(new ArrayBuffer(4));
|
|
825
|
-
/**
|
|
826
|
-
* Check if a number can be encoded as a 32 bit float.
|
|
827
|
-
*
|
|
828
|
-
* @param {number} num
|
|
829
|
-
* @return {boolean}
|
|
830
|
-
*/
|
|
831
|
-
const isFloat32 = num => {
|
|
832
|
-
floatTestBed.setFloat32(0, num);
|
|
833
|
-
return floatTestBed.getFloat32(0) === num
|
|
834
|
-
};
|
|
835
|
-
|
|
836
|
-
/**
|
|
837
|
-
* @typedef {Array<AnyEncodable>} AnyEncodableArray
|
|
838
|
-
*/
|
|
839
|
-
|
|
840
|
-
/**
|
|
841
|
-
* @typedef {undefined|null|number|bigint|boolean|string|{[k:string]:AnyEncodable}|AnyEncodableArray|Uint8Array} AnyEncodable
|
|
842
|
-
*/
|
|
843
|
-
|
|
844
|
-
/**
|
|
845
|
-
* Encode data with efficient binary format.
|
|
846
|
-
*
|
|
847
|
-
* Differences to JSON:
|
|
848
|
-
* • Transforms data to a binary format (not to a string)
|
|
849
|
-
* • Encodes undefined, NaN, and ArrayBuffer (these can't be represented in JSON)
|
|
850
|
-
* • Numbers are efficiently encoded either as a variable length integer, as a
|
|
851
|
-
* 32 bit float, as a 64 bit float, or as a 64 bit bigint.
|
|
852
|
-
*
|
|
853
|
-
* Encoding table:
|
|
854
|
-
*
|
|
855
|
-
* | Data Type | Prefix | Encoding Method | Comment |
|
|
856
|
-
* | ------------------- | -------- | ------------------ | ------- |
|
|
857
|
-
* | undefined | 127 | | Functions, symbol, and everything that cannot be identified is encoded as undefined |
|
|
858
|
-
* | null | 126 | | |
|
|
859
|
-
* | integer | 125 | writeVarInt | Only encodes 32 bit signed integers |
|
|
860
|
-
* | float32 | 124 | writeFloat32 | |
|
|
861
|
-
* | float64 | 123 | writeFloat64 | |
|
|
862
|
-
* | bigint | 122 | writeBigInt64 | |
|
|
863
|
-
* | boolean (false) | 121 | | True and false are different data types so we save the following byte |
|
|
864
|
-
* | boolean (true) | 120 | | - 0b01111000 so the last bit determines whether true or false |
|
|
865
|
-
* | string | 119 | writeVarString | |
|
|
866
|
-
* | object<string,any> | 118 | custom | Writes {length} then {length} key-value pairs |
|
|
867
|
-
* | array<any> | 117 | custom | Writes {length} then {length} json values |
|
|
868
|
-
* | Uint8Array | 116 | writeVarUint8Array | We use Uint8Array for any kind of binary data |
|
|
869
|
-
*
|
|
870
|
-
* Reasons for the decreasing prefix:
|
|
871
|
-
* We need the first bit for extendability (later we may want to encode the
|
|
872
|
-
* prefix with writeVarUint). The remaining 7 bits are divided as follows:
|
|
873
|
-
* [0-30] the beginning of the data range is used for custom purposes
|
|
874
|
-
* (defined by the function that uses this library)
|
|
875
|
-
* [31-127] the end of the data range is used for data encoding by
|
|
876
|
-
* lib0/encoding.js
|
|
877
|
-
*
|
|
878
|
-
* @param {Encoder} encoder
|
|
879
|
-
* @param {AnyEncodable} data
|
|
880
|
-
*/
|
|
881
|
-
const writeAny = (encoder, data) => {
|
|
882
|
-
switch (typeof data) {
|
|
883
|
-
case 'string':
|
|
884
|
-
// TYPE 119: STRING
|
|
885
|
-
write(encoder, 119);
|
|
886
|
-
writeVarString(encoder, data);
|
|
887
|
-
break
|
|
888
|
-
case 'number':
|
|
889
|
-
if (isInteger(data) && abs(data) <= BITS31) {
|
|
890
|
-
// TYPE 125: INTEGER
|
|
891
|
-
write(encoder, 125);
|
|
892
|
-
writeVarInt(encoder, data);
|
|
893
|
-
} else if (isFloat32(data)) {
|
|
894
|
-
// TYPE 124: FLOAT32
|
|
895
|
-
write(encoder, 124);
|
|
896
|
-
writeFloat32(encoder, data);
|
|
897
|
-
} else {
|
|
898
|
-
// TYPE 123: FLOAT64
|
|
899
|
-
write(encoder, 123);
|
|
900
|
-
writeFloat64(encoder, data);
|
|
901
|
-
}
|
|
902
|
-
break
|
|
903
|
-
case 'bigint':
|
|
904
|
-
// TYPE 122: BigInt
|
|
905
|
-
write(encoder, 122);
|
|
906
|
-
writeBigInt64(encoder, data);
|
|
907
|
-
break
|
|
908
|
-
case 'object':
|
|
909
|
-
if (data === null) {
|
|
910
|
-
// TYPE 126: null
|
|
911
|
-
write(encoder, 126);
|
|
912
|
-
} else if (isArray(data)) {
|
|
913
|
-
// TYPE 117: Array
|
|
914
|
-
write(encoder, 117);
|
|
915
|
-
writeVarUint(encoder, data.length);
|
|
916
|
-
for (let i = 0; i < data.length; i++) {
|
|
917
|
-
writeAny(encoder, data[i]);
|
|
918
|
-
}
|
|
919
|
-
} else if (data instanceof Uint8Array) {
|
|
920
|
-
// TYPE 116: ArrayBuffer
|
|
921
|
-
write(encoder, 116);
|
|
922
|
-
writeVarUint8Array(encoder, data);
|
|
923
|
-
} else {
|
|
924
|
-
// TYPE 118: Object
|
|
925
|
-
write(encoder, 118);
|
|
926
|
-
const keys = Object.keys(data);
|
|
927
|
-
writeVarUint(encoder, keys.length);
|
|
928
|
-
for (let i = 0; i < keys.length; i++) {
|
|
929
|
-
const key = keys[i];
|
|
930
|
-
writeVarString(encoder, key);
|
|
931
|
-
writeAny(encoder, data[key]);
|
|
932
|
-
}
|
|
933
|
-
}
|
|
934
|
-
break
|
|
935
|
-
case 'boolean':
|
|
936
|
-
// TYPE 120/121: boolean (true/false)
|
|
937
|
-
write(encoder, data ? 120 : 121);
|
|
938
|
-
break
|
|
939
|
-
default:
|
|
940
|
-
// TYPE 127: undefined
|
|
941
|
-
write(encoder, 127);
|
|
942
|
-
}
|
|
943
|
-
};
|
|
944
|
-
|
|
945
|
-
/**
|
|
946
|
-
* Now come a few stateful encoder that have their own classes.
|
|
947
|
-
*/
|
|
948
|
-
|
|
949
|
-
/**
|
|
950
|
-
* Basic Run Length Encoder - a basic compression implementation.
|
|
951
|
-
*
|
|
952
|
-
* Encodes [1,1,1,7] to [1,3,7,1] (3 times 1, 1 time 7). This encoder might do more harm than good if there are a lot of values that are not repeated.
|
|
953
|
-
*
|
|
954
|
-
* It was originally used for image compression. Cool .. article http://csbruce.com/cbm/transactor/pdfs/trans_v7_i06.pdf
|
|
955
|
-
*
|
|
956
|
-
* @note T must not be null!
|
|
957
|
-
*
|
|
958
|
-
* @template T
|
|
959
|
-
*/
|
|
960
|
-
class RleEncoder extends Encoder {
|
|
961
|
-
/**
|
|
962
|
-
* @param {function(Encoder, T):void} writer
|
|
963
|
-
*/
|
|
964
|
-
constructor (writer) {
|
|
965
|
-
super();
|
|
966
|
-
/**
|
|
967
|
-
* The writer
|
|
968
|
-
*/
|
|
969
|
-
this.w = writer;
|
|
970
|
-
/**
|
|
971
|
-
* Current state
|
|
972
|
-
* @type {T|null}
|
|
973
|
-
*/
|
|
974
|
-
this.s = null;
|
|
975
|
-
this.count = 0;
|
|
976
|
-
}
|
|
977
|
-
|
|
978
|
-
/**
|
|
979
|
-
* @param {T} v
|
|
980
|
-
*/
|
|
981
|
-
write (v) {
|
|
982
|
-
if (this.s === v) {
|
|
983
|
-
this.count++;
|
|
984
|
-
} else {
|
|
985
|
-
if (this.count > 0) {
|
|
986
|
-
// flush counter, unless this is the first value (count = 0)
|
|
987
|
-
writeVarUint(this, this.count - 1); // since count is always > 0, we can decrement by one. non-standard encoding ftw
|
|
988
|
-
}
|
|
989
|
-
this.count = 1;
|
|
990
|
-
// write first value
|
|
991
|
-
this.w(this, v);
|
|
992
|
-
this.s = v;
|
|
993
|
-
}
|
|
994
|
-
}
|
|
995
|
-
}
|
|
996
|
-
|
|
997
|
-
/**
|
|
998
|
-
* @param {UintOptRleEncoder} encoder
|
|
999
|
-
*/
|
|
1000
|
-
const flushUintOptRleEncoder = encoder => {
|
|
1001
|
-
if (encoder.count > 0) {
|
|
1002
|
-
// flush counter, unless this is the first value (count = 0)
|
|
1003
|
-
// case 1: just a single value. set sign to positive
|
|
1004
|
-
// case 2: write several values. set sign to negative to indicate that there is a length coming
|
|
1005
|
-
writeVarInt(encoder.encoder, encoder.count === 1 ? encoder.s : -encoder.s);
|
|
1006
|
-
if (encoder.count > 1) {
|
|
1007
|
-
writeVarUint(encoder.encoder, encoder.count - 2); // since count is always > 1, we can decrement by one. non-standard encoding ftw
|
|
1008
|
-
}
|
|
1009
|
-
}
|
|
1010
|
-
};
|
|
1011
|
-
|
|
1012
|
-
/**
|
|
1013
|
-
* Optimized Rle encoder that does not suffer from the mentioned problem of the basic Rle encoder.
|
|
1014
|
-
*
|
|
1015
|
-
* Internally uses VarInt encoder to write unsigned integers. If the input occurs multiple times, we write
|
|
1016
|
-
* write it as a negative number. The UintOptRleDecoder then understands that it needs to read a count.
|
|
1017
|
-
*
|
|
1018
|
-
* Encodes [1,2,3,3,3] as [1,2,-3,3] (once 1, once 2, three times 3)
|
|
1019
|
-
*/
|
|
1020
|
-
class UintOptRleEncoder {
|
|
1021
|
-
constructor () {
|
|
1022
|
-
this.encoder = new Encoder();
|
|
1023
|
-
/**
|
|
1024
|
-
* @type {number}
|
|
1025
|
-
*/
|
|
1026
|
-
this.s = 0;
|
|
1027
|
-
this.count = 0;
|
|
1028
|
-
}
|
|
1029
|
-
|
|
1030
|
-
/**
|
|
1031
|
-
* @param {number} v
|
|
1032
|
-
*/
|
|
1033
|
-
write (v) {
|
|
1034
|
-
if (this.s === v) {
|
|
1035
|
-
this.count++;
|
|
1036
|
-
} else {
|
|
1037
|
-
flushUintOptRleEncoder(this);
|
|
1038
|
-
this.count = 1;
|
|
1039
|
-
this.s = v;
|
|
1040
|
-
}
|
|
1041
|
-
}
|
|
1042
|
-
|
|
1043
|
-
/**
|
|
1044
|
-
* Flush the encoded state and transform this to a Uint8Array.
|
|
1045
|
-
*
|
|
1046
|
-
* Note that this should only be called once.
|
|
1047
|
-
*/
|
|
1048
|
-
toUint8Array () {
|
|
1049
|
-
flushUintOptRleEncoder(this);
|
|
1050
|
-
return toUint8Array(this.encoder)
|
|
1051
|
-
}
|
|
1052
|
-
}
|
|
1053
|
-
|
|
1054
|
-
/**
|
|
1055
|
-
* @param {IntDiffOptRleEncoder} encoder
|
|
1056
|
-
*/
|
|
1057
|
-
const flushIntDiffOptRleEncoder = encoder => {
|
|
1058
|
-
if (encoder.count > 0) {
|
|
1059
|
-
// 31 bit making up the diff | wether to write the counter
|
|
1060
|
-
// const encodedDiff = encoder.diff << 1 | (encoder.count === 1 ? 0 : 1)
|
|
1061
|
-
const encodedDiff = encoder.diff * 2 + (encoder.count === 1 ? 0 : 1);
|
|
1062
|
-
// flush counter, unless this is the first value (count = 0)
|
|
1063
|
-
// case 1: just a single value. set first bit to positive
|
|
1064
|
-
// case 2: write several values. set first bit to negative to indicate that there is a length coming
|
|
1065
|
-
writeVarInt(encoder.encoder, encodedDiff);
|
|
1066
|
-
if (encoder.count > 1) {
|
|
1067
|
-
writeVarUint(encoder.encoder, encoder.count - 2); // since count is always > 1, we can decrement by one. non-standard encoding ftw
|
|
1068
|
-
}
|
|
1069
|
-
}
|
|
1070
|
-
};
|
|
1071
|
-
|
|
1072
|
-
/**
|
|
1073
|
-
* A combination of the IntDiffEncoder and the UintOptRleEncoder.
|
|
1074
|
-
*
|
|
1075
|
-
* The count approach is similar to the UintDiffOptRleEncoder, but instead of using the negative bitflag, it encodes
|
|
1076
|
-
* in the LSB whether a count is to be read. Therefore this Encoder only supports 31 bit integers!
|
|
1077
|
-
*
|
|
1078
|
-
* Encodes [1, 2, 3, 2] as [3, 1, 6, -1] (more specifically [(1 << 1) | 1, (3 << 0) | 0, -1])
|
|
1079
|
-
*
|
|
1080
|
-
* Internally uses variable length encoding. Contrary to normal UintVar encoding, the first byte contains:
|
|
1081
|
-
* * 1 bit that denotes whether the next value is a count (LSB)
|
|
1082
|
-
* * 1 bit that denotes whether this value is negative (MSB - 1)
|
|
1083
|
-
* * 1 bit that denotes whether to continue reading the variable length integer (MSB)
|
|
1084
|
-
*
|
|
1085
|
-
* Therefore, only five bits remain to encode diff ranges.
|
|
1086
|
-
*
|
|
1087
|
-
* Use this Encoder only when appropriate. In most cases, this is probably a bad idea.
|
|
1088
|
-
*/
|
|
1089
|
-
class IntDiffOptRleEncoder {
|
|
1090
|
-
constructor () {
|
|
1091
|
-
this.encoder = new Encoder();
|
|
1092
|
-
/**
|
|
1093
|
-
* @type {number}
|
|
1094
|
-
*/
|
|
1095
|
-
this.s = 0;
|
|
1096
|
-
this.count = 0;
|
|
1097
|
-
this.diff = 0;
|
|
1098
|
-
}
|
|
1099
|
-
|
|
1100
|
-
/**
|
|
1101
|
-
* @param {number} v
|
|
1102
|
-
*/
|
|
1103
|
-
write (v) {
|
|
1104
|
-
if (this.diff === v - this.s) {
|
|
1105
|
-
this.s = v;
|
|
1106
|
-
this.count++;
|
|
1107
|
-
} else {
|
|
1108
|
-
flushIntDiffOptRleEncoder(this);
|
|
1109
|
-
this.count = 1;
|
|
1110
|
-
this.diff = v - this.s;
|
|
1111
|
-
this.s = v;
|
|
1112
|
-
}
|
|
1113
|
-
}
|
|
1114
|
-
|
|
1115
|
-
/**
|
|
1116
|
-
* Flush the encoded state and transform this to a Uint8Array.
|
|
1117
|
-
*
|
|
1118
|
-
* Note that this should only be called once.
|
|
1119
|
-
*/
|
|
1120
|
-
toUint8Array () {
|
|
1121
|
-
flushIntDiffOptRleEncoder(this);
|
|
1122
|
-
return toUint8Array(this.encoder)
|
|
1123
|
-
}
|
|
1124
|
-
}
|
|
1125
|
-
|
|
1126
|
-
/**
|
|
1127
|
-
* Optimized String Encoder.
|
|
1128
|
-
*
|
|
1129
|
-
* Encoding many small strings in a simple Encoder is not very efficient. The function call to decode a string takes some time and creates references that must be eventually deleted.
|
|
1130
|
-
* In practice, when decoding several million small strings, the GC will kick in more and more often to collect orphaned string objects (or maybe there is another reason?).
|
|
1131
|
-
*
|
|
1132
|
-
* This string encoder solves the above problem. All strings are concatenated and written as a single string using a single encoding call.
|
|
1133
|
-
*
|
|
1134
|
-
* The lengths are encoded using a UintOptRleEncoder.
|
|
1135
|
-
*/
|
|
1136
|
-
class StringEncoder {
|
|
1137
|
-
constructor () {
|
|
1138
|
-
/**
|
|
1139
|
-
* @type {Array<string>}
|
|
1140
|
-
*/
|
|
1141
|
-
this.sarr = [];
|
|
1142
|
-
this.s = '';
|
|
1143
|
-
this.lensE = new UintOptRleEncoder();
|
|
1144
|
-
}
|
|
1145
|
-
|
|
1146
|
-
/**
|
|
1147
|
-
* @param {string} string
|
|
1148
|
-
*/
|
|
1149
|
-
write (string) {
|
|
1150
|
-
this.s += string;
|
|
1151
|
-
if (this.s.length > 19) {
|
|
1152
|
-
this.sarr.push(this.s);
|
|
1153
|
-
this.s = '';
|
|
1154
|
-
}
|
|
1155
|
-
this.lensE.write(string.length);
|
|
1156
|
-
}
|
|
1157
|
-
|
|
1158
|
-
toUint8Array () {
|
|
1159
|
-
const encoder = new Encoder();
|
|
1160
|
-
this.sarr.push(this.s);
|
|
1161
|
-
this.s = '';
|
|
1162
|
-
writeVarString(encoder, this.sarr.join(''));
|
|
1163
|
-
writeUint8Array(encoder, this.lensE.toUint8Array());
|
|
1164
|
-
return toUint8Array(encoder)
|
|
1165
|
-
}
|
|
1166
|
-
}
|
|
1167
|
-
|
|
1168
|
-
/**
|
|
1169
|
-
* Error helpers.
|
|
1170
|
-
*
|
|
1171
|
-
* @module error
|
|
1172
|
-
*/
|
|
1173
|
-
|
|
1174
|
-
/**
|
|
1175
|
-
* @param {string} s
|
|
1176
|
-
* @return {Error}
|
|
1177
|
-
*/
|
|
1178
|
-
/* c8 ignore next */
|
|
1179
|
-
const create = s => new Error(s);
|
|
1180
|
-
|
|
1181
|
-
/**
|
|
1182
|
-
* @throws {Error}
|
|
1183
|
-
* @return {never}
|
|
1184
|
-
*/
|
|
1185
|
-
/* c8 ignore next 3 */
|
|
1186
|
-
const methodUnimplemented = () => {
|
|
1187
|
-
throw create('Method unimplemented')
|
|
1188
|
-
};
|
|
1189
|
-
|
|
1190
|
-
/**
|
|
1191
|
-
* @throws {Error}
|
|
1192
|
-
* @return {never}
|
|
1193
|
-
*/
|
|
1194
|
-
/* c8 ignore next 3 */
|
|
1195
|
-
const unexpectedCase = () => {
|
|
1196
|
-
throw create('Unexpected case')
|
|
1197
|
-
};
|
|
1198
|
-
|
|
1199
|
-
/**
|
|
1200
|
-
* Efficient schema-less binary decoding with support for variable length encoding.
|
|
1201
|
-
*
|
|
1202
|
-
* Use [lib0/decoding] with [lib0/encoding]. Every encoding function has a corresponding decoding function.
|
|
1203
|
-
*
|
|
1204
|
-
* Encodes numbers in little-endian order (least to most significant byte order)
|
|
1205
|
-
* and is compatible with Golang's binary encoding (https://golang.org/pkg/encoding/binary/)
|
|
1206
|
-
* which is also used in Protocol Buffers.
|
|
1207
|
-
*
|
|
1208
|
-
* ```js
|
|
1209
|
-
* // encoding step
|
|
1210
|
-
* const encoder = encoding.createEncoder()
|
|
1211
|
-
* encoding.writeVarUint(encoder, 256)
|
|
1212
|
-
* encoding.writeVarString(encoder, 'Hello world!')
|
|
1213
|
-
* const buf = encoding.toUint8Array(encoder)
|
|
1214
|
-
* ```
|
|
1215
|
-
*
|
|
1216
|
-
* ```js
|
|
1217
|
-
* // decoding step
|
|
1218
|
-
* const decoder = decoding.createDecoder(buf)
|
|
1219
|
-
* decoding.readVarUint(decoder) // => 256
|
|
1220
|
-
* decoding.readVarString(decoder) // => 'Hello world!'
|
|
1221
|
-
* decoding.hasContent(decoder) // => false - all data is read
|
|
1222
|
-
* ```
|
|
1223
|
-
*
|
|
1224
|
-
* @module decoding
|
|
1225
|
-
*/
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
const errorUnexpectedEndOfArray = create('Unexpected end of array');
|
|
1229
|
-
const errorIntegerOutOfRange = create('Integer out of Range');
|
|
1230
|
-
|
|
1231
|
-
/**
|
|
1232
|
-
* A Decoder handles the decoding of an Uint8Array.
|
|
1233
|
-
* @template {ArrayBufferLike} [Buf=ArrayBufferLike]
|
|
1234
|
-
*/
|
|
1235
|
-
class Decoder {
|
|
1236
|
-
/**
|
|
1237
|
-
* @param {Uint8Array<Buf>} uint8Array Binary data to decode
|
|
1238
|
-
*/
|
|
1239
|
-
constructor (uint8Array) {
|
|
1240
|
-
/**
|
|
1241
|
-
* Decoding target.
|
|
1242
|
-
*
|
|
1243
|
-
* @type {Uint8Array<Buf>}
|
|
1244
|
-
*/
|
|
1245
|
-
this.arr = uint8Array;
|
|
1246
|
-
/**
|
|
1247
|
-
* Current decoding position.
|
|
1248
|
-
*
|
|
1249
|
-
* @type {number}
|
|
1250
|
-
*/
|
|
1251
|
-
this.pos = 0;
|
|
1252
|
-
}
|
|
1253
|
-
}
|
|
1254
|
-
|
|
1255
|
-
/**
|
|
1256
|
-
* @function
|
|
1257
|
-
* @template {ArrayBufferLike} Buf
|
|
1258
|
-
* @param {Uint8Array<Buf>} uint8Array
|
|
1259
|
-
* @return {Decoder<Buf>}
|
|
1260
|
-
*/
|
|
1261
|
-
const createDecoder = uint8Array => new Decoder(uint8Array);
|
|
1262
|
-
|
|
1263
|
-
/**
|
|
1264
|
-
* @function
|
|
1265
|
-
* @param {Decoder} decoder
|
|
1266
|
-
* @return {boolean}
|
|
1267
|
-
*/
|
|
1268
|
-
const hasContent = decoder => decoder.pos !== decoder.arr.length;
|
|
1269
|
-
|
|
1270
|
-
/**
|
|
1271
|
-
* Create an Uint8Array view of the next `len` bytes and advance the position by `len`.
|
|
1272
|
-
*
|
|
1273
|
-
* Important: The Uint8Array still points to the underlying ArrayBuffer. Make sure to discard the result as soon as possible to prevent any memory leaks.
|
|
1274
|
-
* Use `buffer.copyUint8Array` to copy the result into a new Uint8Array.
|
|
1275
|
-
*
|
|
1276
|
-
* @function
|
|
1277
|
-
* @template {ArrayBufferLike} Buf
|
|
1278
|
-
* @param {Decoder<Buf>} decoder The decoder instance
|
|
1279
|
-
* @param {number} len The length of bytes to read
|
|
1280
|
-
* @return {Uint8Array<Buf>}
|
|
1281
|
-
*/
|
|
1282
|
-
const readUint8Array = (decoder, len) => {
|
|
1283
|
-
const view = new Uint8Array(decoder.arr.buffer, decoder.pos + decoder.arr.byteOffset, len);
|
|
1284
|
-
decoder.pos += len;
|
|
1285
|
-
return view
|
|
1286
|
-
};
|
|
1287
|
-
|
|
1288
|
-
/**
|
|
1289
|
-
* Read variable length Uint8Array.
|
|
1290
|
-
*
|
|
1291
|
-
* Important: The Uint8Array still points to the underlying ArrayBuffer. Make sure to discard the result as soon as possible to prevent any memory leaks.
|
|
1292
|
-
* Use `buffer.copyUint8Array` to copy the result into a new Uint8Array.
|
|
1293
|
-
*
|
|
1294
|
-
* @function
|
|
1295
|
-
* @template {ArrayBufferLike} Buf
|
|
1296
|
-
* @param {Decoder<Buf>} decoder
|
|
1297
|
-
* @return {Uint8Array<Buf>}
|
|
1298
|
-
*/
|
|
1299
|
-
const readVarUint8Array = decoder => readUint8Array(decoder, readVarUint(decoder));
|
|
1300
|
-
|
|
1301
|
-
/**
|
|
1302
|
-
* Read one byte as unsigned integer.
|
|
1303
|
-
* @function
|
|
1304
|
-
* @param {Decoder} decoder The decoder instance
|
|
1305
|
-
* @return {number} Unsigned 8-bit integer
|
|
1306
|
-
*/
|
|
1307
|
-
const readUint8 = decoder => decoder.arr[decoder.pos++];
|
|
1308
|
-
|
|
1309
|
-
/**
|
|
1310
|
-
* Read unsigned integer (32bit) with variable length.
|
|
1311
|
-
* 1/8th of the storage is used as encoding overhead.
|
|
1312
|
-
* * numbers < 2^7 is stored in one bytlength
|
|
1313
|
-
* * numbers < 2^14 is stored in two bylength
|
|
1314
|
-
*
|
|
1315
|
-
* @function
|
|
1316
|
-
* @param {Decoder} decoder
|
|
1317
|
-
* @return {number} An unsigned integer.length
|
|
1318
|
-
*/
|
|
1319
|
-
const readVarUint = decoder => {
|
|
1320
|
-
let num = 0;
|
|
1321
|
-
let mult = 1;
|
|
1322
|
-
const len = decoder.arr.length;
|
|
1323
|
-
while (decoder.pos < len) {
|
|
1324
|
-
const r = decoder.arr[decoder.pos++];
|
|
1325
|
-
// num = num | ((r & binary.BITS7) << len)
|
|
1326
|
-
num = num + (r & BITS7) * mult; // shift $r << (7*#iterations) and add it to num
|
|
1327
|
-
mult *= 128; // next iteration, shift 7 "more" to the left
|
|
1328
|
-
if (r < BIT8) {
|
|
1329
|
-
return num
|
|
1330
|
-
}
|
|
1331
|
-
/* c8 ignore start */
|
|
1332
|
-
if (num > MAX_SAFE_INTEGER) {
|
|
1333
|
-
throw errorIntegerOutOfRange
|
|
1334
|
-
}
|
|
1335
|
-
/* c8 ignore stop */
|
|
1336
|
-
}
|
|
1337
|
-
throw errorUnexpectedEndOfArray
|
|
1338
|
-
};
|
|
1339
|
-
|
|
1340
|
-
/**
|
|
1341
|
-
* Read signed integer (32bit) with variable length.
|
|
1342
|
-
* 1/8th of the storage is used as encoding overhead.
|
|
1343
|
-
* * numbers < 2^7 is stored in one bytlength
|
|
1344
|
-
* * numbers < 2^14 is stored in two bylength
|
|
1345
|
-
* @todo This should probably create the inverse ~num if number is negative - but this would be a breaking change.
|
|
1346
|
-
*
|
|
1347
|
-
* @function
|
|
1348
|
-
* @param {Decoder} decoder
|
|
1349
|
-
* @return {number} An unsigned integer.length
|
|
1350
|
-
*/
|
|
1351
|
-
const readVarInt = decoder => {
|
|
1352
|
-
let r = decoder.arr[decoder.pos++];
|
|
1353
|
-
let num = r & BITS6;
|
|
1354
|
-
let mult = 64;
|
|
1355
|
-
const sign = (r & BIT7) > 0 ? -1 : 1;
|
|
1356
|
-
if ((r & BIT8) === 0) {
|
|
1357
|
-
// don't continue reading
|
|
1358
|
-
return sign * num
|
|
1359
|
-
}
|
|
1360
|
-
const len = decoder.arr.length;
|
|
1361
|
-
while (decoder.pos < len) {
|
|
1362
|
-
r = decoder.arr[decoder.pos++];
|
|
1363
|
-
// num = num | ((r & binary.BITS7) << len)
|
|
1364
|
-
num = num + (r & BITS7) * mult;
|
|
1365
|
-
mult *= 128;
|
|
1366
|
-
if (r < BIT8) {
|
|
1367
|
-
return sign * num
|
|
1368
|
-
}
|
|
1369
|
-
/* c8 ignore start */
|
|
1370
|
-
if (num > MAX_SAFE_INTEGER) {
|
|
1371
|
-
throw errorIntegerOutOfRange
|
|
1372
|
-
}
|
|
1373
|
-
/* c8 ignore stop */
|
|
1374
|
-
}
|
|
1375
|
-
throw errorUnexpectedEndOfArray
|
|
1376
|
-
};
|
|
1377
|
-
|
|
1378
|
-
/**
|
|
1379
|
-
* We don't test this function anymore as we use native decoding/encoding by default now.
|
|
1380
|
-
* Better not modify this anymore..
|
|
1381
|
-
*
|
|
1382
|
-
* Transforming utf8 to a string is pretty expensive. The code performs 10x better
|
|
1383
|
-
* when String.fromCodePoint is fed with all characters as arguments.
|
|
1384
|
-
* But most environments have a maximum number of arguments per functions.
|
|
1385
|
-
* For effiency reasons we apply a maximum of 10000 characters at once.
|
|
1386
|
-
*
|
|
1387
|
-
* @function
|
|
1388
|
-
* @param {Decoder} decoder
|
|
1389
|
-
* @return {String} The read String.
|
|
1390
|
-
*/
|
|
1391
|
-
/* c8 ignore start */
|
|
1392
|
-
const _readVarStringPolyfill = decoder => {
|
|
1393
|
-
let remainingLen = readVarUint(decoder);
|
|
1394
|
-
if (remainingLen === 0) {
|
|
1395
|
-
return ''
|
|
1396
|
-
} else {
|
|
1397
|
-
let encodedString = String.fromCodePoint(readUint8(decoder)); // remember to decrease remainingLen
|
|
1398
|
-
if (--remainingLen < 100) { // do not create a Uint8Array for small strings
|
|
1399
|
-
while (remainingLen--) {
|
|
1400
|
-
encodedString += String.fromCodePoint(readUint8(decoder));
|
|
1401
|
-
}
|
|
1402
|
-
} else {
|
|
1403
|
-
while (remainingLen > 0) {
|
|
1404
|
-
const nextLen = remainingLen < 10000 ? remainingLen : 10000;
|
|
1405
|
-
// this is dangerous, we create a fresh array view from the existing buffer
|
|
1406
|
-
const bytes = decoder.arr.subarray(decoder.pos, decoder.pos + nextLen);
|
|
1407
|
-
decoder.pos += nextLen;
|
|
1408
|
-
// Starting with ES5.1 we can supply a generic array-like object as arguments
|
|
1409
|
-
encodedString += String.fromCodePoint.apply(null, /** @type {any} */ (bytes));
|
|
1410
|
-
remainingLen -= nextLen;
|
|
1411
|
-
}
|
|
1412
|
-
}
|
|
1413
|
-
return decodeURIComponent(escape(encodedString))
|
|
1414
|
-
}
|
|
1415
|
-
};
|
|
1416
|
-
/* c8 ignore stop */
|
|
1417
|
-
|
|
1418
|
-
/**
|
|
1419
|
-
* @function
|
|
1420
|
-
* @param {Decoder} decoder
|
|
1421
|
-
* @return {String} The read String
|
|
1422
|
-
*/
|
|
1423
|
-
const _readVarStringNative = decoder =>
|
|
1424
|
-
/** @type any */ (utf8TextDecoder).decode(readVarUint8Array(decoder));
|
|
1425
|
-
|
|
1426
|
-
/**
|
|
1427
|
-
* Read string of variable length
|
|
1428
|
-
* * varUint is used to store the length of the string
|
|
1429
|
-
*
|
|
1430
|
-
* @function
|
|
1431
|
-
* @param {Decoder} decoder
|
|
1432
|
-
* @return {String} The read String
|
|
1433
|
-
*
|
|
1434
|
-
*/
|
|
1435
|
-
/* c8 ignore next */
|
|
1436
|
-
const readVarString = utf8TextDecoder ? _readVarStringNative : _readVarStringPolyfill;
|
|
1437
|
-
|
|
1438
|
-
/**
|
|
1439
|
-
* @param {Decoder} decoder
|
|
1440
|
-
* @param {number} len
|
|
1441
|
-
* @return {DataView}
|
|
1442
|
-
*/
|
|
1443
|
-
const readFromDataView = (decoder, len) => {
|
|
1444
|
-
const dv = new DataView(decoder.arr.buffer, decoder.arr.byteOffset + decoder.pos, len);
|
|
1445
|
-
decoder.pos += len;
|
|
1446
|
-
return dv
|
|
1447
|
-
};
|
|
1448
|
-
|
|
1449
|
-
/**
|
|
1450
|
-
* @param {Decoder} decoder
|
|
1451
|
-
*/
|
|
1452
|
-
const readFloat32 = decoder => readFromDataView(decoder, 4).getFloat32(0, false);
|
|
1453
|
-
|
|
1454
|
-
/**
|
|
1455
|
-
* @param {Decoder} decoder
|
|
1456
|
-
*/
|
|
1457
|
-
const readFloat64 = decoder => readFromDataView(decoder, 8).getFloat64(0, false);
|
|
1458
|
-
|
|
1459
|
-
/**
|
|
1460
|
-
* @param {Decoder} decoder
|
|
1461
|
-
*/
|
|
1462
|
-
const readBigInt64 = decoder => /** @type {any} */ (readFromDataView(decoder, 8)).getBigInt64(0, false);
|
|
1463
|
-
|
|
1464
|
-
/**
|
|
1465
|
-
* @type {Array<function(Decoder):any>}
|
|
1466
|
-
*/
|
|
1467
|
-
const readAnyLookupTable = [
|
|
1468
|
-
decoder => undefined, // CASE 127: undefined
|
|
1469
|
-
decoder => null, // CASE 126: null
|
|
1470
|
-
readVarInt, // CASE 125: integer
|
|
1471
|
-
readFloat32, // CASE 124: float32
|
|
1472
|
-
readFloat64, // CASE 123: float64
|
|
1473
|
-
readBigInt64, // CASE 122: bigint
|
|
1474
|
-
decoder => false, // CASE 121: boolean (false)
|
|
1475
|
-
decoder => true, // CASE 120: boolean (true)
|
|
1476
|
-
readVarString, // CASE 119: string
|
|
1477
|
-
decoder => { // CASE 118: object<string,any>
|
|
1478
|
-
const len = readVarUint(decoder);
|
|
1479
|
-
/**
|
|
1480
|
-
* @type {Object<string,any>}
|
|
1481
|
-
*/
|
|
1482
|
-
const obj = {};
|
|
1483
|
-
for (let i = 0; i < len; i++) {
|
|
1484
|
-
const key = readVarString(decoder);
|
|
1485
|
-
obj[key] = readAny(decoder);
|
|
1486
|
-
}
|
|
1487
|
-
return obj
|
|
1488
|
-
},
|
|
1489
|
-
decoder => { // CASE 117: array<any>
|
|
1490
|
-
const len = readVarUint(decoder);
|
|
1491
|
-
const arr = [];
|
|
1492
|
-
for (let i = 0; i < len; i++) {
|
|
1493
|
-
arr.push(readAny(decoder));
|
|
1494
|
-
}
|
|
1495
|
-
return arr
|
|
1496
|
-
},
|
|
1497
|
-
readVarUint8Array // CASE 116: Uint8Array
|
|
1498
|
-
];
|
|
1499
|
-
|
|
1500
|
-
/**
|
|
1501
|
-
* @param {Decoder} decoder
|
|
1502
|
-
*/
|
|
1503
|
-
const readAny = decoder => readAnyLookupTable[127 - readUint8(decoder)](decoder);
|
|
1504
|
-
|
|
1505
|
-
/**
|
|
1506
|
-
* T must not be null.
|
|
1507
|
-
*
|
|
1508
|
-
* @template T
|
|
1509
|
-
*/
|
|
1510
|
-
class RleDecoder extends Decoder {
|
|
1511
|
-
/**
|
|
1512
|
-
* @param {Uint8Array} uint8Array
|
|
1513
|
-
* @param {function(Decoder):T} reader
|
|
1514
|
-
*/
|
|
1515
|
-
constructor (uint8Array, reader) {
|
|
1516
|
-
super(uint8Array);
|
|
1517
|
-
/**
|
|
1518
|
-
* The reader
|
|
1519
|
-
*/
|
|
1520
|
-
this.reader = reader;
|
|
1521
|
-
/**
|
|
1522
|
-
* Current state
|
|
1523
|
-
* @type {T|null}
|
|
1524
|
-
*/
|
|
1525
|
-
this.s = null;
|
|
1526
|
-
this.count = 0;
|
|
1527
|
-
}
|
|
1528
|
-
|
|
1529
|
-
read () {
|
|
1530
|
-
if (this.count === 0) {
|
|
1531
|
-
this.s = this.reader(this);
|
|
1532
|
-
if (hasContent(this)) {
|
|
1533
|
-
this.count = readVarUint(this) + 1; // see encoder implementation for the reason why this is incremented
|
|
1534
|
-
} else {
|
|
1535
|
-
this.count = -1; // read the current value forever
|
|
1536
|
-
}
|
|
1537
|
-
}
|
|
1538
|
-
this.count--;
|
|
1539
|
-
return /** @type {T} */ (this.s)
|
|
1540
|
-
}
|
|
1541
|
-
}
|
|
1542
|
-
|
|
1543
|
-
class UintOptRleDecoder extends Decoder {
|
|
1544
|
-
/**
|
|
1545
|
-
* @param {Uint8Array} uint8Array
|
|
1546
|
-
*/
|
|
1547
|
-
constructor (uint8Array) {
|
|
1548
|
-
super(uint8Array);
|
|
1549
|
-
/**
|
|
1550
|
-
* @type {number}
|
|
1551
|
-
*/
|
|
1552
|
-
this.s = 0;
|
|
1553
|
-
this.count = 0;
|
|
1554
|
-
}
|
|
1555
|
-
|
|
1556
|
-
read () {
|
|
1557
|
-
if (this.count === 0) {
|
|
1558
|
-
this.s = readVarInt(this);
|
|
1559
|
-
// if the sign is negative, we read the count too, otherwise count is 1
|
|
1560
|
-
const isNegative = isNegativeZero(this.s);
|
|
1561
|
-
this.count = 1;
|
|
1562
|
-
if (isNegative) {
|
|
1563
|
-
this.s = -this.s;
|
|
1564
|
-
this.count = readVarUint(this) + 2;
|
|
1565
|
-
}
|
|
1566
|
-
}
|
|
1567
|
-
this.count--;
|
|
1568
|
-
return /** @type {number} */ (this.s)
|
|
1569
|
-
}
|
|
1570
|
-
}
|
|
1571
|
-
|
|
1572
|
-
class IntDiffOptRleDecoder extends Decoder {
|
|
1573
|
-
/**
|
|
1574
|
-
* @param {Uint8Array} uint8Array
|
|
1575
|
-
*/
|
|
1576
|
-
constructor (uint8Array) {
|
|
1577
|
-
super(uint8Array);
|
|
1578
|
-
/**
|
|
1579
|
-
* @type {number}
|
|
1580
|
-
*/
|
|
1581
|
-
this.s = 0;
|
|
1582
|
-
this.count = 0;
|
|
1583
|
-
this.diff = 0;
|
|
1584
|
-
}
|
|
1585
|
-
|
|
1586
|
-
/**
|
|
1587
|
-
* @return {number}
|
|
1588
|
-
*/
|
|
1589
|
-
read () {
|
|
1590
|
-
if (this.count === 0) {
|
|
1591
|
-
const diff = readVarInt(this);
|
|
1592
|
-
// if the first bit is set, we read more data
|
|
1593
|
-
const hasCount = diff & 1;
|
|
1594
|
-
this.diff = floor(diff / 2); // shift >> 1
|
|
1595
|
-
this.count = 1;
|
|
1596
|
-
if (hasCount) {
|
|
1597
|
-
this.count = readVarUint(this) + 2;
|
|
1598
|
-
}
|
|
1599
|
-
}
|
|
1600
|
-
this.s += this.diff;
|
|
1601
|
-
this.count--;
|
|
1602
|
-
return this.s
|
|
1603
|
-
}
|
|
1604
|
-
}
|
|
1605
|
-
|
|
1606
|
-
class StringDecoder {
|
|
1607
|
-
/**
|
|
1608
|
-
* @param {Uint8Array} uint8Array
|
|
1609
|
-
*/
|
|
1610
|
-
constructor (uint8Array) {
|
|
1611
|
-
this.decoder = new UintOptRleDecoder(uint8Array);
|
|
1612
|
-
this.str = readVarString(this.decoder);
|
|
1613
|
-
/**
|
|
1614
|
-
* @type {number}
|
|
1615
|
-
*/
|
|
1616
|
-
this.spos = 0;
|
|
1617
|
-
}
|
|
1618
|
-
|
|
1619
|
-
/**
|
|
1620
|
-
* @return {string}
|
|
1621
|
-
*/
|
|
1622
|
-
read () {
|
|
1623
|
-
const end = this.spos + this.decoder.read();
|
|
1624
|
-
const res = this.str.slice(this.spos, end);
|
|
1625
|
-
this.spos = end;
|
|
1626
|
-
return res
|
|
1627
|
-
}
|
|
1628
|
-
}
|
|
1629
|
-
|
|
1630
|
-
/**
|
|
1631
|
-
* Utility module to work with time.
|
|
1632
|
-
*
|
|
1633
|
-
* @module time
|
|
1634
|
-
*/
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
/**
|
|
1638
|
-
* Return current unix time.
|
|
1639
|
-
*
|
|
1640
|
-
* @return {number}
|
|
1641
|
-
*/
|
|
1642
|
-
const getUnixTime = Date.now;
|
|
1643
|
-
|
|
1644
|
-
const EqualityTraitSymbol = Symbol('Equality');
|
|
1645
|
-
|
|
1646
|
-
/**
|
|
1647
|
-
* @typedef {{ [EqualityTraitSymbol]:(other:EqualityTrait)=>boolean }} EqualityTrait
|
|
1648
|
-
*/
|
|
1649
|
-
|
|
1650
|
-
/**
|
|
1651
|
-
*
|
|
1652
|
-
* Utility function to compare any two objects.
|
|
1653
|
-
*
|
|
1654
|
-
* Note that it is expected that the first parameter is more specific than the latter one.
|
|
1655
|
-
*
|
|
1656
|
-
* @example js
|
|
1657
|
-
* class X { [traits.EqualityTraitSymbol] (other) { return other === this } }
|
|
1658
|
-
* class X2 { [traits.EqualityTraitSymbol] (other) { return other === this }, x2 () { return 2 } }
|
|
1659
|
-
* // this is fine
|
|
1660
|
-
* traits.equals(new X2(), new X())
|
|
1661
|
-
* // this is not, because the left type is less specific than the right one
|
|
1662
|
-
* traits.equals(new X(), new X2())
|
|
1663
|
-
*
|
|
1664
|
-
* @template {EqualityTrait} T
|
|
1665
|
-
* @param {NoInfer<T>} a
|
|
1666
|
-
* @param {T} b
|
|
1667
|
-
* @return {boolean}
|
|
1668
|
-
*/
|
|
1669
|
-
const equals = (a, b) => a === b || !!a?.[EqualityTraitSymbol]?.(b) || false;
|
|
1670
|
-
|
|
1671
|
-
/**
|
|
1672
|
-
* @param {any} o
|
|
1673
|
-
* @return {o is { [k:string]:any }}
|
|
1674
|
-
*/
|
|
1675
|
-
const isObject = o => typeof o === 'object';
|
|
1676
|
-
|
|
1677
|
-
/**
|
|
1678
|
-
* Object.assign
|
|
1679
|
-
*/
|
|
1680
|
-
const assign = Object.assign;
|
|
1681
|
-
|
|
1682
|
-
/**
|
|
1683
|
-
* @param {Object<string,any>} obj
|
|
1684
|
-
*/
|
|
1685
|
-
const keys = Object.keys;
|
|
1686
|
-
|
|
1687
|
-
/**
|
|
1688
|
-
* @template V
|
|
1689
|
-
* @param {{[k:string]:V}} obj
|
|
1690
|
-
* @param {function(V,string):any} f
|
|
1691
|
-
*/
|
|
1692
|
-
const forEach = (obj, f) => {
|
|
1693
|
-
for (const key in obj) {
|
|
1694
|
-
f(obj[key], key);
|
|
1695
|
-
}
|
|
1696
|
-
};
|
|
1697
|
-
|
|
1698
|
-
/**
|
|
1699
|
-
* @param {Object<string,any>} obj
|
|
1700
|
-
* @return {number}
|
|
1701
|
-
*/
|
|
1702
|
-
const size = obj => keys(obj).length;
|
|
1703
|
-
|
|
1704
|
-
/**
|
|
1705
|
-
* @param {Object|null|undefined} obj
|
|
1706
|
-
*/
|
|
1707
|
-
const isEmpty = obj => {
|
|
1708
|
-
// eslint-disable-next-line no-unreachable-loop
|
|
1709
|
-
for (const _k in obj) {
|
|
1710
|
-
return false
|
|
1711
|
-
}
|
|
1712
|
-
return true
|
|
1713
|
-
};
|
|
1714
|
-
|
|
1715
|
-
/**
|
|
1716
|
-
* @template {{ [key:string|number|symbol]: any }} T
|
|
1717
|
-
* @param {T} obj
|
|
1718
|
-
* @param {(v:T[keyof T],k:keyof T)=>boolean} f
|
|
1719
|
-
* @return {boolean}
|
|
1720
|
-
*/
|
|
1721
|
-
const every = (obj, f) => {
|
|
1722
|
-
for (const key in obj) {
|
|
1723
|
-
if (!f(obj[key], key)) {
|
|
1724
|
-
return false
|
|
1725
|
-
}
|
|
1726
|
-
}
|
|
1727
|
-
return true
|
|
1728
|
-
};
|
|
1729
|
-
|
|
1730
|
-
/**
|
|
1731
|
-
* Calls `Object.prototype.hasOwnProperty`.
|
|
1732
|
-
*
|
|
1733
|
-
* @param {any} obj
|
|
1734
|
-
* @param {string|number|symbol} key
|
|
1735
|
-
* @return {boolean}
|
|
1736
|
-
*/
|
|
1737
|
-
const hasProperty = (obj, key) => Object.prototype.hasOwnProperty.call(obj, key);
|
|
1738
|
-
|
|
1739
|
-
/**
|
|
1740
|
-
* @param {Object<string,any>} a
|
|
1741
|
-
* @param {Object<string,any>} b
|
|
1742
|
-
* @return {boolean}
|
|
1743
|
-
*/
|
|
1744
|
-
const equalFlat = (a, b) => a === b || (size(a) === size(b) && every(a, (val, key) => (val !== undefined || hasProperty(b, key)) && equals(b[key], val)));
|
|
1745
|
-
|
|
1746
|
-
/**
|
|
1747
|
-
* Make an object immutable. This hurts performance and is usually not needed if you perform good
|
|
1748
|
-
* coding practices.
|
|
1749
|
-
*/
|
|
1750
|
-
const freeze = Object.freeze;
|
|
1751
|
-
|
|
1752
|
-
/**
|
|
1753
|
-
* Make an object and all its children immutable.
|
|
1754
|
-
* This *really* hurts performance and is usually not needed if you perform good coding practices.
|
|
1755
|
-
*
|
|
1756
|
-
* @template {any} T
|
|
1757
|
-
* @param {T} o
|
|
1758
|
-
* @return {Readonly<T>}
|
|
1759
|
-
*/
|
|
1760
|
-
const deepFreeze = (o) => {
|
|
1761
|
-
for (const key in o) {
|
|
1762
|
-
const c = o[key];
|
|
1763
|
-
if (typeof c === 'object' || typeof c === 'function') {
|
|
1764
|
-
deepFreeze(o[key]);
|
|
1765
|
-
}
|
|
1766
|
-
}
|
|
1767
|
-
return freeze(o)
|
|
1768
|
-
};
|
|
1769
|
-
|
|
1770
|
-
/**
|
|
1771
|
-
* Common functions and function call helpers.
|
|
1772
|
-
*
|
|
1773
|
-
* @module function
|
|
1774
|
-
*/
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
/**
|
|
1778
|
-
* Calls all functions in `fs` with args. Only throws after all functions were called.
|
|
1779
|
-
*
|
|
1780
|
-
* @param {Array<function>} fs
|
|
1781
|
-
* @param {Array<any>} args
|
|
1782
|
-
*/
|
|
1783
|
-
const callAll = (fs, args, i = 0) => {
|
|
1784
|
-
try {
|
|
1785
|
-
for (; i < fs.length; i++) {
|
|
1786
|
-
fs[i](...args);
|
|
1787
|
-
}
|
|
1788
|
-
} finally {
|
|
1789
|
-
if (i < fs.length) {
|
|
1790
|
-
callAll(fs, args, i + 1);
|
|
1791
|
-
}
|
|
1792
|
-
}
|
|
1793
|
-
};
|
|
1794
|
-
|
|
1795
|
-
/**
|
|
1796
|
-
* @template A
|
|
1797
|
-
*
|
|
1798
|
-
* @param {A} a
|
|
1799
|
-
* @return {A}
|
|
1800
|
-
*/
|
|
1801
|
-
const id = a => a;
|
|
1802
|
-
|
|
1803
|
-
/* c8 ignore start */
|
|
1804
|
-
|
|
1805
|
-
/**
|
|
1806
|
-
* @param {any} a
|
|
1807
|
-
* @param {any} b
|
|
1808
|
-
* @return {boolean}
|
|
1809
|
-
*/
|
|
1810
|
-
const equalityDeep = (a, b) => {
|
|
1811
|
-
if (a === b) {
|
|
1812
|
-
return true
|
|
1813
|
-
}
|
|
1814
|
-
if (a == null || b == null || (a.constructor !== b.constructor && (a.constructor || Object) !== (b.constructor || Object))) {
|
|
1815
|
-
return false
|
|
1816
|
-
}
|
|
1817
|
-
if (a[EqualityTraitSymbol] != null) {
|
|
1818
|
-
return a[EqualityTraitSymbol](b)
|
|
1819
|
-
}
|
|
1820
|
-
switch (a.constructor) {
|
|
1821
|
-
case ArrayBuffer:
|
|
1822
|
-
a = new Uint8Array(a);
|
|
1823
|
-
b = new Uint8Array(b);
|
|
1824
|
-
// eslint-disable-next-line no-fallthrough
|
|
1825
|
-
case Uint8Array: {
|
|
1826
|
-
if (a.byteLength !== b.byteLength) {
|
|
1827
|
-
return false
|
|
1828
|
-
}
|
|
1829
|
-
for (let i = 0; i < a.length; i++) {
|
|
1830
|
-
if (a[i] !== b[i]) {
|
|
1831
|
-
return false
|
|
1832
|
-
}
|
|
1833
|
-
}
|
|
1834
|
-
break
|
|
1835
|
-
}
|
|
1836
|
-
case Set: {
|
|
1837
|
-
if (a.size !== b.size) {
|
|
1838
|
-
return false
|
|
1839
|
-
}
|
|
1840
|
-
for (const value of a) {
|
|
1841
|
-
if (!b.has(value)) {
|
|
1842
|
-
return false
|
|
1843
|
-
}
|
|
1844
|
-
}
|
|
1845
|
-
break
|
|
1846
|
-
}
|
|
1847
|
-
case Map: {
|
|
1848
|
-
if (a.size !== b.size) {
|
|
1849
|
-
return false
|
|
1850
|
-
}
|
|
1851
|
-
for (const key of a.keys()) {
|
|
1852
|
-
if (!b.has(key) || !equalityDeep(a.get(key), b.get(key))) {
|
|
1853
|
-
return false
|
|
1854
|
-
}
|
|
1855
|
-
}
|
|
1856
|
-
break
|
|
1857
|
-
}
|
|
1858
|
-
case undefined:
|
|
1859
|
-
case Object:
|
|
1860
|
-
if (size(a) !== size(b)) {
|
|
1861
|
-
return false
|
|
1862
|
-
}
|
|
1863
|
-
for (const key in a) {
|
|
1864
|
-
if (!hasProperty(a, key) || !equalityDeep(a[key], b[key])) {
|
|
1865
|
-
return false
|
|
1866
|
-
}
|
|
1867
|
-
}
|
|
1868
|
-
break
|
|
1869
|
-
case Array:
|
|
1870
|
-
if (a.length !== b.length) {
|
|
1871
|
-
return false
|
|
1872
|
-
}
|
|
1873
|
-
for (let i = 0; i < a.length; i++) {
|
|
1874
|
-
if (!equalityDeep(a[i], b[i])) {
|
|
1875
|
-
return false
|
|
1876
|
-
}
|
|
1877
|
-
}
|
|
1878
|
-
break
|
|
1879
|
-
default:
|
|
1880
|
-
return false
|
|
1881
|
-
}
|
|
1882
|
-
return true
|
|
1883
|
-
};
|
|
1884
|
-
|
|
1885
|
-
/**
|
|
1886
|
-
* @template V
|
|
1887
|
-
* @template {V} OPTS
|
|
1888
|
-
*
|
|
1889
|
-
* @param {V} value
|
|
1890
|
-
* @param {Array<OPTS>} options
|
|
1891
|
-
*/
|
|
1892
|
-
// @ts-ignore
|
|
1893
|
-
const isOneOf = (value, options) => options.includes(value);
|
|
1894
|
-
|
|
1895
|
-
export { max as $, hasProperty as A, MIN_SAFE_INTEGER as B, map as C, create$1 as D, EqualityTraitSymbol as E, ObservableV2 as F, from as G, setIfUndefined as H, forEach as I, IntDiffOptRleDecoder as J, readVarUint8Array as K, readUint8 as L, MAX_SAFE_INTEGER as M, readAny as N, Observable as O, IntDiffOptRleEncoder as P, UintOptRleEncoder as Q, RleDecoder as R, StringDecoder as S, RleEncoder as T, UintOptRleDecoder as U, writeUint8 as V, StringEncoder as W, writeVarUint8Array as X, writeUint8Array as Y, appendTo as Z, callAll as _, readVarString as a, isEmpty as a0, assign as a1, copy as a2, BITS5 as a3, BIT8 as a4, BIT7 as a5, BIT6 as a6, BIT2 as a7, BIT4 as a8, BIT1 as a9, BIT3 as aa, min as ab, any as ac, abs as ad, last as ae, equalFlat as af, deepFreeze as ag, id as ah, BIT30 as ai, keys as aj, writeVarString as b, createEncoder as c, createDecoder as d, equalityDeep as e, floor as f, getUnixTime as g, create$2 as h, isOneOf as i, fromCamelCase as j, encode as k, fromCharCode as l, writeAny as m, methodUnimplemented as n, equals as o, isArray as p, every$1 as q, readVarUint as r, isObject as s, toUint8Array as t, every as u, create as v, writeVarUint as w, some as x, unexpectedCase as y, repeat as z };
|