@nice2dev/ui-graphics 1.0.4 → 1.0.5
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/dist/cjs/animation/AnimationEditor.js +1 -1
- package/dist/cjs/animation/Audience.js +1 -1
- package/dist/cjs/core/LocalUI.js +1 -1
- package/dist/cjs/core/yjsCollaboration.js +2 -2
- package/dist/cjs/core/yjsCollaboration.js.map +1 -1
- package/dist/cjs/game/GameAsset2dEditor.js +1 -1
- package/dist/cjs/node_modules/lib0/array.js +103 -0
- package/dist/cjs/node_modules/lib0/array.js.map +1 -0
- package/dist/cjs/node_modules/lib0/binary.js +42 -0
- package/dist/cjs/node_modules/lib0/binary.js.map +1 -0
- package/dist/cjs/node_modules/lib0/broadcastchannel.js +121 -0
- package/dist/cjs/node_modules/lib0/broadcastchannel.js.map +1 -0
- package/dist/cjs/node_modules/lib0/buffer.js +103 -0
- package/dist/cjs/node_modules/lib0/buffer.js.map +1 -0
- package/dist/cjs/node_modules/lib0/conditions.js +18 -0
- package/dist/cjs/node_modules/lib0/conditions.js.map +1 -0
- package/dist/cjs/node_modules/lib0/decoding.js +460 -0
- package/dist/cjs/node_modules/lib0/decoding.js.map +1 -0
- package/dist/cjs/node_modules/lib0/dom.js +55 -0
- package/dist/cjs/node_modules/lib0/dom.js.map +1 -0
- package/dist/cjs/node_modules/lib0/encoding.js +688 -0
- package/dist/cjs/node_modules/lib0/encoding.js.map +1 -0
- package/dist/cjs/node_modules/lib0/environment.js +129 -0
- package/dist/cjs/node_modules/lib0/environment.js.map +1 -0
- package/dist/cjs/node_modules/lib0/error.js +37 -0
- package/dist/cjs/node_modules/lib0/error.js.map +1 -0
- package/dist/cjs/node_modules/lib0/function.js +135 -0
- package/dist/cjs/node_modules/lib0/function.js.map +1 -0
- package/dist/cjs/node_modules/lib0/iterator.js +52 -0
- package/dist/cjs/node_modules/lib0/iterator.js.map +1 -0
- package/dist/cjs/node_modules/lib0/logging.common.js +63 -0
- package/dist/cjs/node_modules/lib0/logging.common.js.map +1 -0
- package/dist/cjs/node_modules/lib0/logging.js +128 -0
- package/dist/cjs/node_modules/lib0/logging.js.map +1 -0
- package/dist/cjs/node_modules/lib0/map.js +108 -0
- package/dist/cjs/node_modules/lib0/map.js.map +1 -0
- package/dist/cjs/node_modules/lib0/math.js +44 -0
- package/dist/cjs/node_modules/lib0/math.js.map +1 -0
- package/dist/cjs/node_modules/lib0/number.js +21 -0
- package/dist/cjs/node_modules/lib0/number.js.map +1 -0
- package/dist/cjs/node_modules/lib0/object.js +132 -0
- package/dist/cjs/node_modules/lib0/object.js.map +1 -0
- package/dist/cjs/node_modules/lib0/observable.js +168 -0
- package/dist/cjs/node_modules/lib0/observable.js.map +1 -0
- package/dist/cjs/node_modules/lib0/pair.js +33 -0
- package/dist/cjs/node_modules/lib0/pair.js.map +1 -0
- package/dist/cjs/node_modules/lib0/prng.js +95 -0
- package/dist/cjs/node_modules/lib0/prng.js.map +1 -0
- package/dist/cjs/node_modules/lib0/promise.js +33 -0
- package/dist/cjs/node_modules/lib0/promise.js.map +1 -0
- package/dist/cjs/node_modules/lib0/random.js +28 -0
- package/dist/cjs/node_modules/lib0/random.js.map +1 -0
- package/dist/cjs/node_modules/lib0/schema.js +1168 -0
- package/dist/cjs/node_modules/lib0/schema.js.map +1 -0
- package/dist/cjs/node_modules/lib0/set.js +12 -0
- package/dist/cjs/node_modules/lib0/set.js.map +1 -0
- package/dist/cjs/node_modules/lib0/storage.js +79 -0
- package/dist/cjs/node_modules/lib0/storage.js.map +1 -0
- package/dist/cjs/node_modules/lib0/string.js +94 -0
- package/dist/cjs/node_modules/lib0/string.js.map +1 -0
- package/dist/cjs/node_modules/lib0/symbol.js +15 -0
- package/dist/cjs/node_modules/lib0/symbol.js.map +1 -0
- package/dist/cjs/node_modules/lib0/time.js +18 -0
- package/dist/cjs/node_modules/lib0/time.js.map +1 -0
- package/dist/cjs/node_modules/lib0/trait/equality.js +32 -0
- package/dist/cjs/node_modules/lib0/trait/equality.js.map +1 -0
- package/dist/cjs/node_modules/lib0/url.js +20 -0
- package/dist/cjs/node_modules/lib0/url.js.map +1 -0
- package/dist/cjs/node_modules/lib0/webcrypto.js +8 -0
- package/dist/cjs/node_modules/lib0/webcrypto.js.map +1 -0
- package/dist/cjs/node_modules/y-protocols/auth.js +27 -0
- package/dist/cjs/node_modules/y-protocols/auth.js.map +1 -0
- package/dist/cjs/node_modules/y-protocols/awareness.js +277 -0
- package/dist/cjs/node_modules/y-protocols/awareness.js.map +1 -0
- package/dist/cjs/node_modules/y-protocols/sync.js +149 -0
- package/dist/cjs/node_modules/y-protocols/sync.js.map +1 -0
- package/dist/cjs/node_modules/y-websocket/src/y-websocket.js +521 -0
- package/dist/cjs/node_modules/y-websocket/src/y-websocket.js.map +1 -0
- package/dist/cjs/node_modules/yjs/dist/yjs.js +10399 -0
- package/dist/cjs/node_modules/yjs/dist/yjs.js.map +1 -0
- package/dist/cjs/packages/ui/dist/index.js +65997 -0
- package/dist/cjs/packages/ui/dist/index.js.map +1 -0
- package/dist/cjs/pixel/PixelEditor.js +1 -1
- package/dist/cjs/pixel/PixelEditorMenuBar.js +1 -1
- package/dist/cjs/pixel/PixelEditorRightPanel.js +1 -1
- package/dist/cjs/pixel/PixelEditorTimeline.js +1 -1
- package/dist/cjs/pixel/PixelEditorToolbar.js +1 -1
- package/dist/cjs/pixel/SpriteGeneratorPanel.js +1 -1
- package/dist/cjs/vector/VectorEditor.js +1 -1
- package/dist/cjs/vector/VectorEditorMenuBar.js +1 -1
- package/dist/cjs/vector/VectorEditorRightPanel.js +1 -1
- package/dist/esm/animation/AnimationEditor.js +5 -5
- package/dist/esm/animation/Audience.js +2 -2
- package/dist/esm/core/LocalUI.js +4 -4
- package/dist/esm/core/yjsCollaboration.js +2 -2
- package/dist/esm/core/yjsCollaboration.js.map +1 -1
- package/dist/esm/game/GameAsset2dEditor.js +19 -19
- package/dist/esm/node_modules/lib0/array.js +95 -0
- package/dist/esm/node_modules/lib0/array.js.map +1 -0
- package/dist/esm/node_modules/lib0/binary.js +30 -0
- package/dist/esm/node_modules/lib0/binary.js.map +1 -0
- package/dist/esm/node_modules/lib0/broadcastchannel.js +117 -0
- package/dist/esm/node_modules/lib0/broadcastchannel.js.map +1 -0
- package/dist/esm/node_modules/lib0/buffer.js +96 -0
- package/dist/esm/node_modules/lib0/buffer.js.map +1 -0
- package/dist/esm/node_modules/lib0/conditions.js +16 -0
- package/dist/esm/node_modules/lib0/conditions.js.map +1 -0
- package/dist/esm/node_modules/lib0/decoding.js +439 -0
- package/dist/esm/node_modules/lib0/decoding.js.map +1 -0
- package/dist/esm/node_modules/lib0/dom.js +48 -0
- package/dist/esm/node_modules/lib0/dom.js.map +1 -0
- package/dist/esm/node_modules/lib0/encoding.js +663 -0
- package/dist/esm/node_modules/lib0/encoding.js.map +1 -0
- package/dist/esm/node_modules/lib0/environment.js +121 -0
- package/dist/esm/node_modules/lib0/environment.js.map +1 -0
- package/dist/esm/node_modules/lib0/error.js +33 -0
- package/dist/esm/node_modules/lib0/error.js.map +1 -0
- package/dist/esm/node_modules/lib0/function.js +130 -0
- package/dist/esm/node_modules/lib0/function.js.map +1 -0
- package/dist/esm/node_modules/lib0/iterator.js +48 -0
- package/dist/esm/node_modules/lib0/iterator.js.map +1 -0
- package/dist/esm/node_modules/lib0/logging.common.js +52 -0
- package/dist/esm/node_modules/lib0/logging.common.js.map +1 -0
- package/dist/esm/node_modules/lib0/logging.js +115 -0
- package/dist/esm/node_modules/lib0/logging.js.map +1 -0
- package/dist/esm/node_modules/lib0/map.js +102 -0
- package/dist/esm/node_modules/lib0/map.js.map +1 -0
- package/dist/esm/node_modules/lib0/math.js +37 -0
- package/dist/esm/node_modules/lib0/math.js.map +1 -0
- package/dist/esm/node_modules/lib0/number.js +17 -0
- package/dist/esm/node_modules/lib0/number.js.map +1 -0
- package/dist/esm/node_modules/lib0/object.js +119 -0
- package/dist/esm/node_modules/lib0/object.js.map +1 -0
- package/dist/esm/node_modules/lib0/observable.js +165 -0
- package/dist/esm/node_modules/lib0/observable.js.map +1 -0
- package/dist/esm/node_modules/lib0/pair.js +30 -0
- package/dist/esm/node_modules/lib0/pair.js.map +1 -0
- package/dist/esm/node_modules/lib0/prng.js +87 -0
- package/dist/esm/node_modules/lib0/prng.js.map +1 -0
- package/dist/esm/node_modules/lib0/promise.js +31 -0
- package/dist/esm/node_modules/lib0/promise.js.map +1 -0
- package/dist/esm/node_modules/lib0/random.js +25 -0
- package/dist/esm/node_modules/lib0/random.js.map +1 -0
- package/dist/esm/node_modules/lib0/schema.js +1113 -0
- package/dist/esm/node_modules/lib0/schema.js.map +1 -0
- package/dist/esm/node_modules/lib0/set.js +10 -0
- package/dist/esm/node_modules/lib0/set.js.map +1 -0
- package/dist/esm/node_modules/lib0/storage.js +75 -0
- package/dist/esm/node_modules/lib0/storage.js.map +1 -0
- package/dist/esm/node_modules/lib0/string.js +85 -0
- package/dist/esm/node_modules/lib0/string.js.map +1 -0
- package/dist/esm/node_modules/lib0/symbol.js +13 -0
- package/dist/esm/node_modules/lib0/symbol.js.map +1 -0
- package/dist/esm/node_modules/lib0/time.js +16 -0
- package/dist/esm/node_modules/lib0/time.js.map +1 -0
- package/dist/esm/node_modules/lib0/trait/equality.js +29 -0
- package/dist/esm/node_modules/lib0/trait/equality.js.map +1 -0
- package/dist/esm/node_modules/lib0/url.js +18 -0
- package/dist/esm/node_modules/lib0/url.js.map +1 -0
- package/dist/esm/node_modules/lib0/webcrypto.js +6 -0
- package/dist/esm/node_modules/lib0/webcrypto.js.map +1 -0
- package/dist/esm/node_modules/y-protocols/auth.js +24 -0
- package/dist/esm/node_modules/y-protocols/auth.js.map +1 -0
- package/dist/esm/node_modules/y-protocols/awareness.js +271 -0
- package/dist/esm/node_modules/y-protocols/awareness.js.map +1 -0
- package/dist/esm/node_modules/y-protocols/sync.js +138 -0
- package/dist/esm/node_modules/y-protocols/sync.js.map +1 -0
- package/dist/esm/node_modules/y-websocket/src/y-websocket.js +515 -0
- package/dist/esm/node_modules/y-websocket/src/y-websocket.js.map +1 -0
- package/dist/esm/node_modules/yjs/dist/yjs.js +10295 -0
- package/dist/esm/node_modules/yjs/dist/yjs.js.map +1 -0
- package/dist/esm/packages/ui/dist/index.js +65571 -0
- package/dist/esm/packages/ui/dist/index.js.map +1 -0
- package/dist/esm/pixel/PixelEditor.js +3 -3
- package/dist/esm/pixel/PixelEditorMenuBar.js +2 -2
- package/dist/esm/pixel/PixelEditorRightPanel.js +3 -3
- package/dist/esm/pixel/PixelEditorTimeline.js +2 -2
- package/dist/esm/pixel/PixelEditorToolbar.js +2 -2
- package/dist/esm/pixel/SpriteGeneratorPanel.js +8 -8
- package/dist/esm/vector/VectorEditor.js +3 -3
- package/dist/esm/vector/VectorEditorMenuBar.js +3 -3
- package/dist/esm/vector/VectorEditorRightPanel.js +13 -13
- package/package.json +1 -1
|
@@ -0,0 +1,663 @@
|
|
|
1
|
+
import { floor, abs, min, max, isNegativeZero } from './math.js';
|
|
2
|
+
import { isInteger } from './number.js';
|
|
3
|
+
import { BITS7, BITS31, BITS6, BIT8, BIT7 } from './binary.js';
|
|
4
|
+
import { utf8TextEncoder, encodeUtf8 } from './string.js';
|
|
5
|
+
import { isArray } from './array.js';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Efficient schema-less binary encoding with support for variable length encoding.
|
|
9
|
+
*
|
|
10
|
+
* Use [lib0/encoding] with [lib0/decoding]. Every encoding function has a corresponding decoding function.
|
|
11
|
+
*
|
|
12
|
+
* Encodes numbers in little-endian order (least to most significant byte order)
|
|
13
|
+
* and is compatible with Golang's binary encoding (https://golang.org/pkg/encoding/binary/)
|
|
14
|
+
* which is also used in Protocol Buffers.
|
|
15
|
+
*
|
|
16
|
+
* ```js
|
|
17
|
+
* // encoding step
|
|
18
|
+
* const encoder = encoding.createEncoder()
|
|
19
|
+
* encoding.writeVarUint(encoder, 256)
|
|
20
|
+
* encoding.writeVarString(encoder, 'Hello world!')
|
|
21
|
+
* const buf = encoding.toUint8Array(encoder)
|
|
22
|
+
* ```
|
|
23
|
+
*
|
|
24
|
+
* ```js
|
|
25
|
+
* // decoding step
|
|
26
|
+
* const decoder = decoding.createDecoder(buf)
|
|
27
|
+
* decoding.readVarUint(decoder) // => 256
|
|
28
|
+
* decoding.readVarString(decoder) // => 'Hello world!'
|
|
29
|
+
* decoding.hasContent(decoder) // => false - all data is read
|
|
30
|
+
* ```
|
|
31
|
+
*
|
|
32
|
+
* @module encoding
|
|
33
|
+
*/
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* A BinaryEncoder handles the encoding to an Uint8Array.
|
|
38
|
+
*/
|
|
39
|
+
class Encoder {
|
|
40
|
+
constructor () {
|
|
41
|
+
this.cpos = 0;
|
|
42
|
+
this.cbuf = new Uint8Array(100);
|
|
43
|
+
/**
|
|
44
|
+
* @type {Array<Uint8Array>}
|
|
45
|
+
*/
|
|
46
|
+
this.bufs = [];
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* @function
|
|
52
|
+
* @return {Encoder}
|
|
53
|
+
*/
|
|
54
|
+
const createEncoder = () => new Encoder();
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* The current length of the encoded data.
|
|
58
|
+
*
|
|
59
|
+
* @function
|
|
60
|
+
* @param {Encoder} encoder
|
|
61
|
+
* @return {number}
|
|
62
|
+
*/
|
|
63
|
+
const length = encoder => {
|
|
64
|
+
let len = encoder.cpos;
|
|
65
|
+
for (let i = 0; i < encoder.bufs.length; i++) {
|
|
66
|
+
len += encoder.bufs[i].length;
|
|
67
|
+
}
|
|
68
|
+
return len
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Transform to Uint8Array.
|
|
73
|
+
*
|
|
74
|
+
* @function
|
|
75
|
+
* @param {Encoder} encoder
|
|
76
|
+
* @return {Uint8Array<ArrayBuffer>} The created ArrayBuffer.
|
|
77
|
+
*/
|
|
78
|
+
const toUint8Array = encoder => {
|
|
79
|
+
const uint8arr = new Uint8Array(length(encoder));
|
|
80
|
+
let curPos = 0;
|
|
81
|
+
for (let i = 0; i < encoder.bufs.length; i++) {
|
|
82
|
+
const d = encoder.bufs[i];
|
|
83
|
+
uint8arr.set(d, curPos);
|
|
84
|
+
curPos += d.length;
|
|
85
|
+
}
|
|
86
|
+
uint8arr.set(new Uint8Array(encoder.cbuf.buffer, 0, encoder.cpos), curPos);
|
|
87
|
+
return uint8arr
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Verify that it is possible to write `len` bytes wtihout checking. If
|
|
92
|
+
* necessary, a new Buffer with the required length is attached.
|
|
93
|
+
*
|
|
94
|
+
* @param {Encoder} encoder
|
|
95
|
+
* @param {number} len
|
|
96
|
+
*/
|
|
97
|
+
const verifyLen = (encoder, len) => {
|
|
98
|
+
const bufferLen = encoder.cbuf.length;
|
|
99
|
+
if (bufferLen - encoder.cpos < len) {
|
|
100
|
+
encoder.bufs.push(new Uint8Array(encoder.cbuf.buffer, 0, encoder.cpos));
|
|
101
|
+
encoder.cbuf = new Uint8Array(max(bufferLen, len) * 2);
|
|
102
|
+
encoder.cpos = 0;
|
|
103
|
+
}
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Write one byte to the encoder.
|
|
108
|
+
*
|
|
109
|
+
* @function
|
|
110
|
+
* @param {Encoder} encoder
|
|
111
|
+
* @param {number} num The byte that is to be encoded.
|
|
112
|
+
*/
|
|
113
|
+
const write = (encoder, num) => {
|
|
114
|
+
const bufferLen = encoder.cbuf.length;
|
|
115
|
+
if (encoder.cpos === bufferLen) {
|
|
116
|
+
encoder.bufs.push(encoder.cbuf);
|
|
117
|
+
encoder.cbuf = new Uint8Array(bufferLen * 2);
|
|
118
|
+
encoder.cpos = 0;
|
|
119
|
+
}
|
|
120
|
+
encoder.cbuf[encoder.cpos++] = num;
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Write one byte as an unsigned integer.
|
|
125
|
+
*
|
|
126
|
+
* @function
|
|
127
|
+
* @param {Encoder} encoder
|
|
128
|
+
* @param {number} num The number that is to be encoded.
|
|
129
|
+
*/
|
|
130
|
+
const writeUint8 = write;
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Write a variable length unsigned integer. Max encodable integer is 2^53.
|
|
134
|
+
*
|
|
135
|
+
* @function
|
|
136
|
+
* @param {Encoder} encoder
|
|
137
|
+
* @param {number} num The number that is to be encoded.
|
|
138
|
+
*/
|
|
139
|
+
const writeVarUint = (encoder, num) => {
|
|
140
|
+
while (num > BITS7) {
|
|
141
|
+
write(encoder, BIT8 | (BITS7 & num));
|
|
142
|
+
num = floor(num / 128); // shift >>> 7
|
|
143
|
+
}
|
|
144
|
+
write(encoder, BITS7 & num);
|
|
145
|
+
};
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Write a variable length integer.
|
|
149
|
+
*
|
|
150
|
+
* We use the 7th bit instead for signaling that this is a negative number.
|
|
151
|
+
*
|
|
152
|
+
* @function
|
|
153
|
+
* @param {Encoder} encoder
|
|
154
|
+
* @param {number} num The number that is to be encoded.
|
|
155
|
+
*/
|
|
156
|
+
const writeVarInt = (encoder, num) => {
|
|
157
|
+
const isNegative = isNegativeZero(num);
|
|
158
|
+
if (isNegative) {
|
|
159
|
+
num = -num;
|
|
160
|
+
}
|
|
161
|
+
// |- whether to continue reading |- whether is negative |- number
|
|
162
|
+
write(encoder, (num > BITS6 ? BIT8 : 0) | (isNegative ? BIT7 : 0) | (BITS6 & num));
|
|
163
|
+
num = floor(num / 64); // shift >>> 6
|
|
164
|
+
// We don't need to consider the case of num === 0 so we can use a different
|
|
165
|
+
// pattern here than above.
|
|
166
|
+
while (num > 0) {
|
|
167
|
+
write(encoder, (num > BITS7 ? BIT8 : 0) | (BITS7 & num));
|
|
168
|
+
num = floor(num / 128); // shift >>> 7
|
|
169
|
+
}
|
|
170
|
+
};
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* A cache to store strings temporarily
|
|
174
|
+
*/
|
|
175
|
+
const _strBuffer = new Uint8Array(30000);
|
|
176
|
+
const _maxStrBSize = _strBuffer.length / 3;
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* Write a variable length string.
|
|
180
|
+
*
|
|
181
|
+
* @function
|
|
182
|
+
* @param {Encoder} encoder
|
|
183
|
+
* @param {String} str The string that is to be encoded.
|
|
184
|
+
*/
|
|
185
|
+
const _writeVarStringNative = (encoder, str) => {
|
|
186
|
+
if (str.length < _maxStrBSize) {
|
|
187
|
+
// We can encode the string into the existing buffer
|
|
188
|
+
/* c8 ignore next */
|
|
189
|
+
const written = utf8TextEncoder.encodeInto(str, _strBuffer).written || 0;
|
|
190
|
+
writeVarUint(encoder, written);
|
|
191
|
+
for (let i = 0; i < written; i++) {
|
|
192
|
+
write(encoder, _strBuffer[i]);
|
|
193
|
+
}
|
|
194
|
+
} else {
|
|
195
|
+
writeVarUint8Array(encoder, encodeUtf8(str));
|
|
196
|
+
}
|
|
197
|
+
};
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* Write a variable length string.
|
|
201
|
+
*
|
|
202
|
+
* @function
|
|
203
|
+
* @param {Encoder} encoder
|
|
204
|
+
* @param {String} str The string that is to be encoded.
|
|
205
|
+
*/
|
|
206
|
+
const _writeVarStringPolyfill = (encoder, str) => {
|
|
207
|
+
const encodedString = unescape(encodeURIComponent(str));
|
|
208
|
+
const len = encodedString.length;
|
|
209
|
+
writeVarUint(encoder, len);
|
|
210
|
+
for (let i = 0; i < len; i++) {
|
|
211
|
+
write(encoder, /** @type {number} */ (encodedString.codePointAt(i)));
|
|
212
|
+
}
|
|
213
|
+
};
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* Write a variable length string.
|
|
217
|
+
*
|
|
218
|
+
* @function
|
|
219
|
+
* @param {Encoder} encoder
|
|
220
|
+
* @param {String} str The string that is to be encoded.
|
|
221
|
+
*/
|
|
222
|
+
/* c8 ignore next */
|
|
223
|
+
const writeVarString = (utf8TextEncoder && /** @type {any} */ (utf8TextEncoder).encodeInto) ? _writeVarStringNative : _writeVarStringPolyfill;
|
|
224
|
+
|
|
225
|
+
/**
|
|
226
|
+
* Write the content of another Encoder.
|
|
227
|
+
*
|
|
228
|
+
* @TODO: can be improved!
|
|
229
|
+
* - Note: Should consider that when appending a lot of small Encoders, we should rather clone than referencing the old structure.
|
|
230
|
+
* Encoders start with a rather big initial buffer.
|
|
231
|
+
*
|
|
232
|
+
* @function
|
|
233
|
+
* @param {Encoder} encoder The enUint8Arr
|
|
234
|
+
* @param {Encoder} append The BinaryEncoder to be written.
|
|
235
|
+
*/
|
|
236
|
+
const writeBinaryEncoder = (encoder, append) => writeUint8Array(encoder, toUint8Array(append));
|
|
237
|
+
|
|
238
|
+
/**
|
|
239
|
+
* Append fixed-length Uint8Array to the encoder.
|
|
240
|
+
*
|
|
241
|
+
* @function
|
|
242
|
+
* @param {Encoder} encoder
|
|
243
|
+
* @param {Uint8Array} uint8Array
|
|
244
|
+
*/
|
|
245
|
+
const writeUint8Array = (encoder, uint8Array) => {
|
|
246
|
+
const bufferLen = encoder.cbuf.length;
|
|
247
|
+
const cpos = encoder.cpos;
|
|
248
|
+
const leftCopyLen = min(bufferLen - cpos, uint8Array.length);
|
|
249
|
+
const rightCopyLen = uint8Array.length - leftCopyLen;
|
|
250
|
+
encoder.cbuf.set(uint8Array.subarray(0, leftCopyLen), cpos);
|
|
251
|
+
encoder.cpos += leftCopyLen;
|
|
252
|
+
if (rightCopyLen > 0) {
|
|
253
|
+
// Still something to write, write right half..
|
|
254
|
+
// Append new buffer
|
|
255
|
+
encoder.bufs.push(encoder.cbuf);
|
|
256
|
+
// must have at least size of remaining buffer
|
|
257
|
+
encoder.cbuf = new Uint8Array(max(bufferLen * 2, rightCopyLen));
|
|
258
|
+
// copy array
|
|
259
|
+
encoder.cbuf.set(uint8Array.subarray(leftCopyLen));
|
|
260
|
+
encoder.cpos = rightCopyLen;
|
|
261
|
+
}
|
|
262
|
+
};
|
|
263
|
+
|
|
264
|
+
/**
|
|
265
|
+
* Append an Uint8Array to Encoder.
|
|
266
|
+
*
|
|
267
|
+
* @function
|
|
268
|
+
* @param {Encoder} encoder
|
|
269
|
+
* @param {Uint8Array} uint8Array
|
|
270
|
+
*/
|
|
271
|
+
const writeVarUint8Array = (encoder, uint8Array) => {
|
|
272
|
+
writeVarUint(encoder, uint8Array.byteLength);
|
|
273
|
+
writeUint8Array(encoder, uint8Array);
|
|
274
|
+
};
|
|
275
|
+
|
|
276
|
+
/**
|
|
277
|
+
* Create an DataView of the next `len` bytes. Use it to write data after
|
|
278
|
+
* calling this function.
|
|
279
|
+
*
|
|
280
|
+
* ```js
|
|
281
|
+
* // write float32 using DataView
|
|
282
|
+
* const dv = writeOnDataView(encoder, 4)
|
|
283
|
+
* dv.setFloat32(0, 1.1)
|
|
284
|
+
* // read float32 using DataView
|
|
285
|
+
* const dv = readFromDataView(encoder, 4)
|
|
286
|
+
* dv.getFloat32(0) // => 1.100000023841858 (leaving it to the reader to find out why this is the correct result)
|
|
287
|
+
* ```
|
|
288
|
+
*
|
|
289
|
+
* @param {Encoder} encoder
|
|
290
|
+
* @param {number} len
|
|
291
|
+
* @return {DataView}
|
|
292
|
+
*/
|
|
293
|
+
const writeOnDataView = (encoder, len) => {
|
|
294
|
+
verifyLen(encoder, len);
|
|
295
|
+
const dview = new DataView(encoder.cbuf.buffer, encoder.cpos, len);
|
|
296
|
+
encoder.cpos += len;
|
|
297
|
+
return dview
|
|
298
|
+
};
|
|
299
|
+
|
|
300
|
+
/**
|
|
301
|
+
* @param {Encoder} encoder
|
|
302
|
+
* @param {number} num
|
|
303
|
+
*/
|
|
304
|
+
const writeFloat32 = (encoder, num) => writeOnDataView(encoder, 4).setFloat32(0, num, false);
|
|
305
|
+
|
|
306
|
+
/**
|
|
307
|
+
* @param {Encoder} encoder
|
|
308
|
+
* @param {number} num
|
|
309
|
+
*/
|
|
310
|
+
const writeFloat64 = (encoder, num) => writeOnDataView(encoder, 8).setFloat64(0, num, false);
|
|
311
|
+
|
|
312
|
+
/**
|
|
313
|
+
* @param {Encoder} encoder
|
|
314
|
+
* @param {bigint} num
|
|
315
|
+
*/
|
|
316
|
+
const writeBigInt64 = (encoder, num) => /** @type {any} */ (writeOnDataView(encoder, 8)).setBigInt64(0, num, false);
|
|
317
|
+
|
|
318
|
+
const floatTestBed = new DataView(new ArrayBuffer(4));
|
|
319
|
+
/**
|
|
320
|
+
* Check if a number can be encoded as a 32 bit float.
|
|
321
|
+
*
|
|
322
|
+
* @param {number} num
|
|
323
|
+
* @return {boolean}
|
|
324
|
+
*/
|
|
325
|
+
const isFloat32 = num => {
|
|
326
|
+
floatTestBed.setFloat32(0, num);
|
|
327
|
+
return floatTestBed.getFloat32(0) === num
|
|
328
|
+
};
|
|
329
|
+
|
|
330
|
+
/**
|
|
331
|
+
* @typedef {Array<AnyEncodable>} AnyEncodableArray
|
|
332
|
+
*/
|
|
333
|
+
|
|
334
|
+
/**
|
|
335
|
+
* @typedef {undefined|null|number|bigint|boolean|string|{[k:string]:AnyEncodable}|AnyEncodableArray|Uint8Array} AnyEncodable
|
|
336
|
+
*/
|
|
337
|
+
|
|
338
|
+
/**
|
|
339
|
+
* Encode data with efficient binary format.
|
|
340
|
+
*
|
|
341
|
+
* Differences to JSON:
|
|
342
|
+
* • Transforms data to a binary format (not to a string)
|
|
343
|
+
* • Encodes undefined, NaN, and ArrayBuffer (these can't be represented in JSON)
|
|
344
|
+
* • Numbers are efficiently encoded either as a variable length integer, as a
|
|
345
|
+
* 32 bit float, as a 64 bit float, or as a 64 bit bigint.
|
|
346
|
+
*
|
|
347
|
+
* Encoding table:
|
|
348
|
+
*
|
|
349
|
+
* | Data Type | Prefix | Encoding Method | Comment |
|
|
350
|
+
* | ------------------- | -------- | ------------------ | ------- |
|
|
351
|
+
* | undefined | 127 | | Functions, symbol, and everything that cannot be identified is encoded as undefined |
|
|
352
|
+
* | null | 126 | | |
|
|
353
|
+
* | integer | 125 | writeVarInt | Only encodes 32 bit signed integers |
|
|
354
|
+
* | float32 | 124 | writeFloat32 | |
|
|
355
|
+
* | float64 | 123 | writeFloat64 | |
|
|
356
|
+
* | bigint | 122 | writeBigInt64 | |
|
|
357
|
+
* | boolean (false) | 121 | | True and false are different data types so we save the following byte |
|
|
358
|
+
* | boolean (true) | 120 | | - 0b01111000 so the last bit determines whether true or false |
|
|
359
|
+
* | string | 119 | writeVarString | |
|
|
360
|
+
* | object<string,any> | 118 | custom | Writes {length} then {length} key-value pairs |
|
|
361
|
+
* | array<any> | 117 | custom | Writes {length} then {length} json values |
|
|
362
|
+
* | Uint8Array | 116 | writeVarUint8Array | We use Uint8Array for any kind of binary data |
|
|
363
|
+
*
|
|
364
|
+
* Reasons for the decreasing prefix:
|
|
365
|
+
* We need the first bit for extendability (later we may want to encode the
|
|
366
|
+
* prefix with writeVarUint). The remaining 7 bits are divided as follows:
|
|
367
|
+
* [0-30] the beginning of the data range is used for custom purposes
|
|
368
|
+
* (defined by the function that uses this library)
|
|
369
|
+
* [31-127] the end of the data range is used for data encoding by
|
|
370
|
+
* lib0/encoding.js
|
|
371
|
+
*
|
|
372
|
+
* @param {Encoder} encoder
|
|
373
|
+
* @param {AnyEncodable} data
|
|
374
|
+
*/
|
|
375
|
+
const writeAny = (encoder, data) => {
|
|
376
|
+
switch (typeof data) {
|
|
377
|
+
case 'string':
|
|
378
|
+
// TYPE 119: STRING
|
|
379
|
+
write(encoder, 119);
|
|
380
|
+
writeVarString(encoder, data);
|
|
381
|
+
break
|
|
382
|
+
case 'number':
|
|
383
|
+
if (isInteger(data) && abs(data) <= BITS31) {
|
|
384
|
+
// TYPE 125: INTEGER
|
|
385
|
+
write(encoder, 125);
|
|
386
|
+
writeVarInt(encoder, data);
|
|
387
|
+
} else if (isFloat32(data)) {
|
|
388
|
+
// TYPE 124: FLOAT32
|
|
389
|
+
write(encoder, 124);
|
|
390
|
+
writeFloat32(encoder, data);
|
|
391
|
+
} else {
|
|
392
|
+
// TYPE 123: FLOAT64
|
|
393
|
+
write(encoder, 123);
|
|
394
|
+
writeFloat64(encoder, data);
|
|
395
|
+
}
|
|
396
|
+
break
|
|
397
|
+
case 'bigint':
|
|
398
|
+
// TYPE 122: BigInt
|
|
399
|
+
write(encoder, 122);
|
|
400
|
+
writeBigInt64(encoder, data);
|
|
401
|
+
break
|
|
402
|
+
case 'object':
|
|
403
|
+
if (data === null) {
|
|
404
|
+
// TYPE 126: null
|
|
405
|
+
write(encoder, 126);
|
|
406
|
+
} else if (isArray(data)) {
|
|
407
|
+
// TYPE 117: Array
|
|
408
|
+
write(encoder, 117);
|
|
409
|
+
writeVarUint(encoder, data.length);
|
|
410
|
+
for (let i = 0; i < data.length; i++) {
|
|
411
|
+
writeAny(encoder, data[i]);
|
|
412
|
+
}
|
|
413
|
+
} else if (data instanceof Uint8Array) {
|
|
414
|
+
// TYPE 116: ArrayBuffer
|
|
415
|
+
write(encoder, 116);
|
|
416
|
+
writeVarUint8Array(encoder, data);
|
|
417
|
+
} else {
|
|
418
|
+
// TYPE 118: Object
|
|
419
|
+
write(encoder, 118);
|
|
420
|
+
const keys = Object.keys(data);
|
|
421
|
+
writeVarUint(encoder, keys.length);
|
|
422
|
+
for (let i = 0; i < keys.length; i++) {
|
|
423
|
+
const key = keys[i];
|
|
424
|
+
writeVarString(encoder, key);
|
|
425
|
+
writeAny(encoder, data[key]);
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
break
|
|
429
|
+
case 'boolean':
|
|
430
|
+
// TYPE 120/121: boolean (true/false)
|
|
431
|
+
write(encoder, data ? 120 : 121);
|
|
432
|
+
break
|
|
433
|
+
default:
|
|
434
|
+
// TYPE 127: undefined
|
|
435
|
+
write(encoder, 127);
|
|
436
|
+
}
|
|
437
|
+
};
|
|
438
|
+
|
|
439
|
+
/**
|
|
440
|
+
* Now come a few stateful encoder that have their own classes.
|
|
441
|
+
*/
|
|
442
|
+
|
|
443
|
+
/**
|
|
444
|
+
* Basic Run Length Encoder - a basic compression implementation.
|
|
445
|
+
*
|
|
446
|
+
* 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.
|
|
447
|
+
*
|
|
448
|
+
* It was originally used for image compression. Cool .. article http://csbruce.com/cbm/transactor/pdfs/trans_v7_i06.pdf
|
|
449
|
+
*
|
|
450
|
+
* @note T must not be null!
|
|
451
|
+
*
|
|
452
|
+
* @template T
|
|
453
|
+
*/
|
|
454
|
+
class RleEncoder extends Encoder {
|
|
455
|
+
/**
|
|
456
|
+
* @param {function(Encoder, T):void} writer
|
|
457
|
+
*/
|
|
458
|
+
constructor (writer) {
|
|
459
|
+
super();
|
|
460
|
+
/**
|
|
461
|
+
* The writer
|
|
462
|
+
*/
|
|
463
|
+
this.w = writer;
|
|
464
|
+
/**
|
|
465
|
+
* Current state
|
|
466
|
+
* @type {T|null}
|
|
467
|
+
*/
|
|
468
|
+
this.s = null;
|
|
469
|
+
this.count = 0;
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
/**
|
|
473
|
+
* @param {T} v
|
|
474
|
+
*/
|
|
475
|
+
write (v) {
|
|
476
|
+
if (this.s === v) {
|
|
477
|
+
this.count++;
|
|
478
|
+
} else {
|
|
479
|
+
if (this.count > 0) {
|
|
480
|
+
// flush counter, unless this is the first value (count = 0)
|
|
481
|
+
writeVarUint(this, this.count - 1); // since count is always > 0, we can decrement by one. non-standard encoding ftw
|
|
482
|
+
}
|
|
483
|
+
this.count = 1;
|
|
484
|
+
// write first value
|
|
485
|
+
this.w(this, v);
|
|
486
|
+
this.s = v;
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
/**
|
|
492
|
+
* @param {UintOptRleEncoder} encoder
|
|
493
|
+
*/
|
|
494
|
+
const flushUintOptRleEncoder = encoder => {
|
|
495
|
+
if (encoder.count > 0) {
|
|
496
|
+
// flush counter, unless this is the first value (count = 0)
|
|
497
|
+
// case 1: just a single value. set sign to positive
|
|
498
|
+
// case 2: write several values. set sign to negative to indicate that there is a length coming
|
|
499
|
+
writeVarInt(encoder.encoder, encoder.count === 1 ? encoder.s : -encoder.s);
|
|
500
|
+
if (encoder.count > 1) {
|
|
501
|
+
writeVarUint(encoder.encoder, encoder.count - 2); // since count is always > 1, we can decrement by one. non-standard encoding ftw
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
|
+
};
|
|
505
|
+
|
|
506
|
+
/**
|
|
507
|
+
* Optimized Rle encoder that does not suffer from the mentioned problem of the basic Rle encoder.
|
|
508
|
+
*
|
|
509
|
+
* Internally uses VarInt encoder to write unsigned integers. If the input occurs multiple times, we write
|
|
510
|
+
* write it as a negative number. The UintOptRleDecoder then understands that it needs to read a count.
|
|
511
|
+
*
|
|
512
|
+
* Encodes [1,2,3,3,3] as [1,2,-3,3] (once 1, once 2, three times 3)
|
|
513
|
+
*/
|
|
514
|
+
class UintOptRleEncoder {
|
|
515
|
+
constructor () {
|
|
516
|
+
this.encoder = new Encoder();
|
|
517
|
+
/**
|
|
518
|
+
* @type {number}
|
|
519
|
+
*/
|
|
520
|
+
this.s = 0;
|
|
521
|
+
this.count = 0;
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
/**
|
|
525
|
+
* @param {number} v
|
|
526
|
+
*/
|
|
527
|
+
write (v) {
|
|
528
|
+
if (this.s === v) {
|
|
529
|
+
this.count++;
|
|
530
|
+
} else {
|
|
531
|
+
flushUintOptRleEncoder(this);
|
|
532
|
+
this.count = 1;
|
|
533
|
+
this.s = v;
|
|
534
|
+
}
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
/**
|
|
538
|
+
* Flush the encoded state and transform this to a Uint8Array.
|
|
539
|
+
*
|
|
540
|
+
* Note that this should only be called once.
|
|
541
|
+
*/
|
|
542
|
+
toUint8Array () {
|
|
543
|
+
flushUintOptRleEncoder(this);
|
|
544
|
+
return toUint8Array(this.encoder)
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
/**
|
|
549
|
+
* @param {IntDiffOptRleEncoder} encoder
|
|
550
|
+
*/
|
|
551
|
+
const flushIntDiffOptRleEncoder = encoder => {
|
|
552
|
+
if (encoder.count > 0) {
|
|
553
|
+
// 31 bit making up the diff | wether to write the counter
|
|
554
|
+
// const encodedDiff = encoder.diff << 1 | (encoder.count === 1 ? 0 : 1)
|
|
555
|
+
const encodedDiff = encoder.diff * 2 + (encoder.count === 1 ? 0 : 1);
|
|
556
|
+
// flush counter, unless this is the first value (count = 0)
|
|
557
|
+
// case 1: just a single value. set first bit to positive
|
|
558
|
+
// case 2: write several values. set first bit to negative to indicate that there is a length coming
|
|
559
|
+
writeVarInt(encoder.encoder, encodedDiff);
|
|
560
|
+
if (encoder.count > 1) {
|
|
561
|
+
writeVarUint(encoder.encoder, encoder.count - 2); // since count is always > 1, we can decrement by one. non-standard encoding ftw
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
};
|
|
565
|
+
|
|
566
|
+
/**
|
|
567
|
+
* A combination of the IntDiffEncoder and the UintOptRleEncoder.
|
|
568
|
+
*
|
|
569
|
+
* The count approach is similar to the UintDiffOptRleEncoder, but instead of using the negative bitflag, it encodes
|
|
570
|
+
* in the LSB whether a count is to be read. Therefore this Encoder only supports 31 bit integers!
|
|
571
|
+
*
|
|
572
|
+
* Encodes [1, 2, 3, 2] as [3, 1, 6, -1] (more specifically [(1 << 1) | 1, (3 << 0) | 0, -1])
|
|
573
|
+
*
|
|
574
|
+
* Internally uses variable length encoding. Contrary to normal UintVar encoding, the first byte contains:
|
|
575
|
+
* * 1 bit that denotes whether the next value is a count (LSB)
|
|
576
|
+
* * 1 bit that denotes whether this value is negative (MSB - 1)
|
|
577
|
+
* * 1 bit that denotes whether to continue reading the variable length integer (MSB)
|
|
578
|
+
*
|
|
579
|
+
* Therefore, only five bits remain to encode diff ranges.
|
|
580
|
+
*
|
|
581
|
+
* Use this Encoder only when appropriate. In most cases, this is probably a bad idea.
|
|
582
|
+
*/
|
|
583
|
+
class IntDiffOptRleEncoder {
|
|
584
|
+
constructor () {
|
|
585
|
+
this.encoder = new Encoder();
|
|
586
|
+
/**
|
|
587
|
+
* @type {number}
|
|
588
|
+
*/
|
|
589
|
+
this.s = 0;
|
|
590
|
+
this.count = 0;
|
|
591
|
+
this.diff = 0;
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
/**
|
|
595
|
+
* @param {number} v
|
|
596
|
+
*/
|
|
597
|
+
write (v) {
|
|
598
|
+
if (this.diff === v - this.s) {
|
|
599
|
+
this.s = v;
|
|
600
|
+
this.count++;
|
|
601
|
+
} else {
|
|
602
|
+
flushIntDiffOptRleEncoder(this);
|
|
603
|
+
this.count = 1;
|
|
604
|
+
this.diff = v - this.s;
|
|
605
|
+
this.s = v;
|
|
606
|
+
}
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
/**
|
|
610
|
+
* Flush the encoded state and transform this to a Uint8Array.
|
|
611
|
+
*
|
|
612
|
+
* Note that this should only be called once.
|
|
613
|
+
*/
|
|
614
|
+
toUint8Array () {
|
|
615
|
+
flushIntDiffOptRleEncoder(this);
|
|
616
|
+
return toUint8Array(this.encoder)
|
|
617
|
+
}
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
/**
|
|
621
|
+
* Optimized String Encoder.
|
|
622
|
+
*
|
|
623
|
+
* 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.
|
|
624
|
+
* 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?).
|
|
625
|
+
*
|
|
626
|
+
* This string encoder solves the above problem. All strings are concatenated and written as a single string using a single encoding call.
|
|
627
|
+
*
|
|
628
|
+
* The lengths are encoded using a UintOptRleEncoder.
|
|
629
|
+
*/
|
|
630
|
+
class StringEncoder {
|
|
631
|
+
constructor () {
|
|
632
|
+
/**
|
|
633
|
+
* @type {Array<string>}
|
|
634
|
+
*/
|
|
635
|
+
this.sarr = [];
|
|
636
|
+
this.s = '';
|
|
637
|
+
this.lensE = new UintOptRleEncoder();
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
/**
|
|
641
|
+
* @param {string} string
|
|
642
|
+
*/
|
|
643
|
+
write (string) {
|
|
644
|
+
this.s += string;
|
|
645
|
+
if (this.s.length > 19) {
|
|
646
|
+
this.sarr.push(this.s);
|
|
647
|
+
this.s = '';
|
|
648
|
+
}
|
|
649
|
+
this.lensE.write(string.length);
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
toUint8Array () {
|
|
653
|
+
const encoder = new Encoder();
|
|
654
|
+
this.sarr.push(this.s);
|
|
655
|
+
this.s = '';
|
|
656
|
+
writeVarString(encoder, this.sarr.join(''));
|
|
657
|
+
writeUint8Array(encoder, this.lensE.toUint8Array());
|
|
658
|
+
return toUint8Array(encoder)
|
|
659
|
+
}
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
export { Encoder, IntDiffOptRleEncoder, RleEncoder, StringEncoder, UintOptRleEncoder, _writeVarStringNative, _writeVarStringPolyfill, createEncoder, length, toUint8Array, verifyLen, write, writeAny, writeBigInt64, writeBinaryEncoder, writeFloat32, writeFloat64, writeOnDataView, writeUint8, writeUint8Array, writeVarInt, writeVarString, writeVarUint, writeVarUint8Array };
|
|
663
|
+
//# sourceMappingURL=encoding.js.map
|