@colyseus/schema 3.0.0-alpha.2 → 3.0.0-alpha.23

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.
Files changed (103) hide show
  1. package/README.md +131 -61
  2. package/build/cjs/index.js +476 -150
  3. package/build/cjs/index.js.map +1 -1
  4. package/build/esm/index.mjs +475 -149
  5. package/build/esm/index.mjs.map +1 -1
  6. package/build/umd/index.js +476 -150
  7. package/lib/Metadata.d.ts +2 -0
  8. package/lib/Metadata.js +39 -0
  9. package/lib/Metadata.js.map +1 -1
  10. package/lib/Reflection.d.ts +1 -2
  11. package/lib/Reflection.js +28 -22
  12. package/lib/Reflection.js.map +1 -1
  13. package/lib/Schema.d.ts +1 -1
  14. package/lib/annotations.js +12 -10
  15. package/lib/annotations.js.map +1 -1
  16. package/lib/bench_encode.d.ts +1 -0
  17. package/lib/bench_encode.js +93 -0
  18. package/lib/bench_encode.js.map +1 -0
  19. package/lib/codegen/api.js +1 -2
  20. package/lib/codegen/api.js.map +1 -1
  21. package/lib/codegen/languages/cpp.js +1 -2
  22. package/lib/codegen/languages/cpp.js.map +1 -1
  23. package/lib/codegen/languages/csharp.js +1 -2
  24. package/lib/codegen/languages/csharp.js.map +1 -1
  25. package/lib/codegen/languages/haxe.js +1 -2
  26. package/lib/codegen/languages/haxe.js.map +1 -1
  27. package/lib/codegen/languages/java.js +1 -2
  28. package/lib/codegen/languages/java.js.map +1 -1
  29. package/lib/codegen/languages/js.js +1 -2
  30. package/lib/codegen/languages/js.js.map +1 -1
  31. package/lib/codegen/languages/lua.js +1 -2
  32. package/lib/codegen/languages/lua.js.map +1 -1
  33. package/lib/codegen/languages/ts.js +1 -2
  34. package/lib/codegen/languages/ts.js.map +1 -1
  35. package/lib/codegen/parser.js +2 -3
  36. package/lib/codegen/parser.js.map +1 -1
  37. package/lib/codegen/types.js +3 -3
  38. package/lib/codegen/types.js.map +1 -1
  39. package/lib/debug.d.ts +1 -0
  40. package/lib/debug.js +52 -0
  41. package/lib/debug.js.map +1 -0
  42. package/lib/decoder/DecodeOperation.d.ts +0 -1
  43. package/lib/decoder/DecodeOperation.js +22 -7
  44. package/lib/decoder/DecodeOperation.js.map +1 -1
  45. package/lib/decoder/Decoder.d.ts +4 -5
  46. package/lib/decoder/Decoder.js +4 -4
  47. package/lib/decoder/Decoder.js.map +1 -1
  48. package/lib/decoder/strategy/RawChanges.js +1 -2
  49. package/lib/decoder/strategy/RawChanges.js.map +1 -1
  50. package/lib/decoder/strategy/StateCallbacks.d.ts +36 -7
  51. package/lib/decoder/strategy/StateCallbacks.js +39 -46
  52. package/lib/decoder/strategy/StateCallbacks.js.map +1 -1
  53. package/lib/encoder/ChangeTree.js +2 -5
  54. package/lib/encoder/ChangeTree.js.map +1 -1
  55. package/lib/encoder/EncodeOperation.d.ts +0 -1
  56. package/lib/encoder/EncodeOperation.js +29 -13
  57. package/lib/encoder/EncodeOperation.js.map +1 -1
  58. package/lib/encoder/Encoder.d.ts +5 -4
  59. package/lib/encoder/Encoder.js +60 -38
  60. package/lib/encoder/Encoder.js.map +1 -1
  61. package/lib/encoder/StateView.js +11 -6
  62. package/lib/encoder/StateView.js.map +1 -1
  63. package/lib/encoding/assert.js +3 -3
  64. package/lib/encoding/assert.js.map +1 -1
  65. package/lib/encoding/decode.d.ts +21 -19
  66. package/lib/encoding/decode.js +24 -25
  67. package/lib/encoding/decode.js.map +1 -1
  68. package/lib/encoding/encode.d.ts +2 -2
  69. package/lib/encoding/encode.js +40 -39
  70. package/lib/encoding/encode.js.map +1 -1
  71. package/lib/encoding/spec.d.ts +2 -1
  72. package/lib/encoding/spec.js +1 -0
  73. package/lib/encoding/spec.js.map +1 -1
  74. package/lib/index.d.ts +3 -0
  75. package/lib/index.js +5 -1
  76. package/lib/index.js.map +1 -1
  77. package/lib/types/custom/ArraySchema.d.ts +2 -2
  78. package/lib/types/custom/ArraySchema.js +0 -8
  79. package/lib/types/custom/ArraySchema.js.map +1 -1
  80. package/lib/types/registry.js +3 -4
  81. package/lib/types/registry.js.map +1 -1
  82. package/lib/types/utils.js +1 -2
  83. package/lib/types/utils.js.map +1 -1
  84. package/lib/utils.js +3 -4
  85. package/lib/utils.js.map +1 -1
  86. package/package.json +5 -5
  87. package/src/Metadata.ts +47 -0
  88. package/src/Reflection.ts +31 -22
  89. package/src/annotations.ts +6 -2
  90. package/src/bench_encode.ts +66 -0
  91. package/src/debug.ts +56 -0
  92. package/src/decoder/DecodeOperation.ts +26 -6
  93. package/src/decoder/Decoder.ts +8 -8
  94. package/src/decoder/strategy/StateCallbacks.ts +93 -53
  95. package/src/encoder/ChangeTree.ts +2 -5
  96. package/src/encoder/EncodeOperation.ts +29 -12
  97. package/src/encoder/Encoder.ts +71 -42
  98. package/src/encoder/StateView.ts +10 -7
  99. package/src/encoding/decode.ts +24 -25
  100. package/src/encoding/encode.ts +25 -22
  101. package/src/encoding/spec.ts +1 -0
  102. package/src/index.ts +5 -0
  103. package/src/types/custom/ArraySchema.ts +2 -1
@@ -5,10 +5,11 @@ import { $changes, $encoder, $filter } from "../types/symbols";
5
5
  import * as encode from "../encoding/encode";
6
6
  import type { Iterator } from "../encoding/decode";
7
7
 
8
- import { SWITCH_TO_STRUCTURE, TYPE_ID } from '../encoding/spec';
8
+ import { OPERATION, SWITCH_TO_STRUCTURE, TYPE_ID } from '../encoding/spec';
9
9
  import { Root } from "./ChangeTree";
10
10
  import { getNextPowerOf2 } from "../utils";
11
11
  import type { StateView } from "./StateView";
12
+ import { Metadata } from "../Metadata";
12
13
 
13
14
  export class Encoder<T extends Schema = any> {
14
15
  static BUFFER_SIZE = 8 * 1024;// 8KB
@@ -37,18 +38,24 @@ export class Encoder<T extends Schema = any> {
37
38
  protected setRoot(state: T) {
38
39
  this.root = new Root();
39
40
  this.state = state;
41
+
42
+ // Workaround to allow using an empty Schema.
43
+ if (state.constructor[Symbol.metadata] === undefined) {
44
+ Metadata.init(state);
45
+ }
46
+
40
47
  state[$changes].setRoot(this.root);
41
48
  }
42
49
 
43
50
  encode(
44
51
  it: Iterator = { offset: 0 },
45
52
  view?: StateView,
46
- bytes = this.sharedBuffer,
47
- changeTrees = this.root.changes
53
+ buffer = this.sharedBuffer,
54
+ changeTrees = this.root.changes,
55
+ isEncodeAll = this.root.allChanges === changeTrees,
48
56
  ): Buffer {
49
57
  const initialOffset = it.offset; // cache current offset in case we need to resize the buffer
50
58
 
51
- const isEncodeAll = this.root.allChanges === changeTrees;
52
59
  const hasView = (view !== undefined);
53
60
  const rootChangeTree = this.state[$changes];
54
61
 
@@ -61,6 +68,13 @@ export class Encoder<T extends Schema = any> {
61
68
  const encoder = ctor[$encoder];
62
69
  const filter = ctor[$filter];
63
70
 
71
+ // try { throw new Error(); } catch (e) {
72
+ // // only print if not coming from Reflection.ts
73
+ // if (!e.stack.includes("src/Reflection.ts")) {
74
+ // console.log("ChangeTree:", { ref: ref.constructor.name, });
75
+ // }
76
+ // }
77
+
64
78
  if (hasView) {
65
79
  if (!view.items.has(changeTree)) {
66
80
  view.invisible.add(changeTree);
@@ -73,8 +87,8 @@ export class Encoder<T extends Schema = any> {
73
87
 
74
88
  // skip root `refId` if it's the first change tree
75
89
  if (it.offset !== initialOffset || changeTree !== rootChangeTree) {
76
- bytes[it.offset++] = SWITCH_TO_STRUCTURE & 255;
77
- encode.number(bytes, changeTree.refId, it);
90
+ buffer[it.offset++] = SWITCH_TO_STRUCTURE & 255;
91
+ encode.number(buffer, changeTree.refId, it);
78
92
  }
79
93
 
80
94
  const changesIterator = changes.entries();
@@ -95,25 +109,41 @@ export class Encoder<T extends Schema = any> {
95
109
  continue;
96
110
  }
97
111
 
98
- // console.log("WILL ENCODE", {
99
- // ref: changeTree.ref.constructor.name,
100
- // fieldIndex,
101
- // operation: OPERATION[operation],
102
- // });
103
-
104
- encoder(this, bytes, changeTree, fieldIndex, operation, it, isEncodeAll, hasView);
112
+ // try { throw new Error(); } catch (e) {
113
+ // // only print if not coming from Reflection.ts
114
+ // if (!e.stack.includes("src/Reflection.ts")) {
115
+ // console.log("WILL ENCODE", {
116
+ // ref: changeTree.ref.constructor.name,
117
+ // fieldIndex,
118
+ // operation: OPERATION[operation],
119
+ // });
120
+ // }
121
+ // }
122
+
123
+ encoder(this, buffer, changeTree, fieldIndex, operation, it, isEncodeAll, hasView);
105
124
  }
106
125
  }
107
126
 
108
- if (it.offset > bytes.byteLength) {
109
- const newSize = getNextPowerOf2(this.sharedBuffer.byteLength * 2);
110
- console.warn("@colyseus/schema encode buffer overflow. Current buffer size: " + bytes.byteLength + ", encoding offset: " + it.offset + ", new size: " + newSize);
127
+ if (it.offset > buffer.byteLength) {
128
+ const newSize = getNextPowerOf2(buffer.byteLength * 2);
129
+ console.warn(`@colyseus/schema buffer overflow. Encoded state is higher than default BUFFER_SIZE. Use the following to increase default BUFFER_SIZE:
130
+
131
+ import { Encoder } from "@colyseus/schema";
132
+ Encoder.BUFFER_SIZE = ${Math.round(newSize / 1024)} * 1024; // ${Math.round(newSize / 1024)} KB
133
+ `);
134
+
111
135
 
112
136
  //
113
137
  // resize buffer and re-encode (TODO: can we avoid re-encoding here?)
114
138
  //
115
- this.sharedBuffer = Buffer.allocUnsafeSlow(newSize);
116
- return this.encode({ offset: initialOffset }, view);
139
+ buffer = Buffer.allocUnsafeSlow(newSize);
140
+
141
+ // assign resized buffer to local sharedBuffer
142
+ if (buffer === this.sharedBuffer) {
143
+ this.sharedBuffer = buffer;
144
+ }
145
+
146
+ return this.encode({ offset: initialOffset }, view, buffer, changeTrees, isEncodeAll);
117
147
 
118
148
  } else {
119
149
  //
@@ -126,47 +156,46 @@ export class Encoder<T extends Schema = any> {
126
156
  this.onEndEncode(changeTrees);
127
157
  }
128
158
 
129
- // return bytes;
130
- return bytes.slice(0, it.offset);
159
+ return buffer.subarray(0, it.offset);
131
160
  }
132
161
  }
133
162
 
134
- encodeAll(it: Iterator = { offset: 0 }) {
135
- // console.log(`encodeAll(), this.$root.allChanges (${this.$root.allChanges.size})`);
163
+ encodeAll(it: Iterator = { offset: 0 }, buffer: Buffer = this.sharedBuffer) {
164
+ // console.log(`encodeAll(), this.root.allChanges (${this.root.allChanges.size})`);
136
165
 
137
- // Array.from(this.$root.allChanges.entries()).map((item) => {
138
- // console.log("->", item[0].refId, item[0].ref.toJSON());
166
+ // Array.from(this.root.allChanges.entries()).map((item) => {
167
+ // console.log("->", { ref: item[0].ref.constructor.name, refId: item[0].refId, changes: item[1].size });
139
168
  // });
140
169
 
141
- return this.encode(it, undefined, this.sharedBuffer, this.root.allChanges);
170
+ return this.encode(it, undefined, buffer, this.root.allChanges, true);
142
171
  }
143
172
 
144
173
  encodeAllView(view: StateView, sharedOffset: number, it: Iterator, bytes = this.sharedBuffer) {
145
174
  const viewOffset = it.offset;
146
175
 
147
- // console.log(`encodeAllView(), this.$root.allFilteredChanges (${this.$root.allFilteredChanges.size})`);
176
+ // console.log(`encodeAllView(), this.root.allFilteredChanges (${this.root.allFilteredChanges.size})`);
148
177
  // this.debugAllFilteredChanges();
149
178
 
150
179
  // try to encode "filtered" changes
151
- this.encode(it, view, bytes, this.root.allFilteredChanges);
180
+ this.encode(it, view, bytes, this.root.allFilteredChanges, true);
152
181
 
153
182
  return Buffer.concat([
154
- bytes.slice(0, sharedOffset),
155
- bytes.slice(viewOffset, it.offset)
183
+ bytes.subarray(0, sharedOffset),
184
+ bytes.subarray(viewOffset, it.offset)
156
185
  ]);
157
186
  }
158
187
 
159
188
 
160
- // debugAllFilteredChanges() {
161
- // Array.from(this.$root.allFilteredChanges.entries()).map((item) => {
162
- // console.log("->", { refId: item[0].refId }, item[0].ref.toJSON());
163
- // if (Array.isArray(item[0].ref.toJSON())) {
164
- // item[1].forEach((op, key) => {
165
- // console.log(" ->", { key, op: OPERATION[op] });
166
- // })
167
- // }
168
- // });
169
- // }
189
+ debugAllFilteredChanges() {
190
+ Array.from(this.root.allFilteredChanges.entries()).map((item) => {
191
+ console.log("->", { refId: item[0].refId, changes: item[1].size }, item[0].ref.toJSON());
192
+ if (Array.isArray(item[0].ref.toJSON())) {
193
+ item[1].forEach((op, key) => {
194
+ console.log(" ->", { key, op: OPERATION[op] });
195
+ })
196
+ }
197
+ });
198
+ }
170
199
 
171
200
  encodeView(view: StateView, sharedOffset: number, it: Iterator, bytes = this.sharedBuffer) {
172
201
  const viewOffset = it.offset;
@@ -208,8 +237,8 @@ export class Encoder<T extends Schema = any> {
208
237
  view.changes.clear();
209
238
 
210
239
  return Buffer.concat([
211
- bytes.slice(0, sharedOffset),
212
- bytes.slice(viewOffset, it.offset)
240
+ bytes.subarray(0, sharedOffset),
241
+ bytes.subarray(viewOffset, it.offset)
213
242
  ]);
214
243
  }
215
244
 
@@ -242,4 +271,4 @@ export class Encoder<T extends Schema = any> {
242
271
  encode.number(bytes, targetTypeId, it);
243
272
  }
244
273
  }
245
- }
274
+ }
@@ -34,15 +34,20 @@ export class StateView {
34
34
  return this;
35
35
  }
36
36
 
37
+ // FIXME: ArraySchema/MapSchema does not have metadata
38
+ const metadata: Metadata = obj.constructor[Symbol.metadata];
39
+
37
40
  let changeTree: ChangeTree = obj[$changes];
38
41
  this.items.add(changeTree);
39
42
 
40
43
  // Add children of this ChangeTree to this view
41
- changeTree.forEachChild((change, _) =>
42
- this.add(change.ref, tag));
43
-
44
- // FIXME: ArraySchema/MapSchema does not have metadata
45
- const metadata: Metadata = obj.constructor[Symbol.metadata];
44
+ changeTree.forEachChild((change, index) => {
45
+ // Do not ADD children that don't have the same tag
46
+ if (metadata && metadata[metadata[index]].tag !== tag) {
47
+ return;
48
+ }
49
+ this.add(change.ref, tag);
50
+ });
46
51
 
47
52
  // add parent ChangeTree's, if they are invisible to this view
48
53
  // TODO: REFACTOR addParent()
@@ -72,8 +77,6 @@ export class StateView {
72
77
  }
73
78
  tags.add(tag);
74
79
 
75
- // console.log("BY TAG:", tag);
76
-
77
80
  // Ref: add tagged properties
78
81
  metadata?.[-3]?.[tag]?.forEach((index) => {
79
82
  if (changeTree.getChange(index) !== OPERATION.DELETE) {
@@ -22,6 +22,7 @@
22
22
  */
23
23
 
24
24
  import { SWITCH_TO_STRUCTURE } from "./spec";
25
+ import type { BufferLike } from "./encode";
25
26
 
26
27
  /**
27
28
  * msgpack implementation highly based on notepack.io
@@ -30,9 +31,9 @@ import { SWITCH_TO_STRUCTURE } from "./spec";
30
31
 
31
32
  export interface Iterator { offset: number; }
32
33
 
33
- function utf8Read(bytes, offset, length) {
34
+ export function utf8Read(bytes: BufferLike, it: Iterator, length: number) {
34
35
  var string = '', chr = 0;
35
- for (var i = offset, end = offset + length; i < end; i++) {
36
+ for (var i = it.offset, end = it.offset + length; i < end; i++) {
36
37
  var byte = bytes[i];
37
38
  if ((byte & 0x80) === 0x00) {
38
39
  string += String.fromCharCode(byte);
@@ -71,48 +72,49 @@ function utf8Read(bytes, offset, length) {
71
72
  // (do not throw error to avoid server/client from crashing due to hack attemps)
72
73
  // throw new Error('Invalid byte ' + byte.toString(16));
73
74
  }
75
+ it.offset += length;
74
76
  return string;
75
77
  }
76
78
 
77
- export function int8 (bytes: number[], it: Iterator) {
79
+ export function int8 (bytes: BufferLike, it: Iterator) {
78
80
  return uint8(bytes, it) << 24 >> 24;
79
81
  };
80
82
 
81
- export function uint8 (bytes: number[], it: Iterator) {
83
+ export function uint8 (bytes: BufferLike, it: Iterator) {
82
84
  return bytes[it.offset++];
83
85
  };
84
86
 
85
- export function int16 (bytes: number[], it: Iterator) {
87
+ export function int16 (bytes: BufferLike, it: Iterator) {
86
88
  return uint16(bytes, it) << 16 >> 16;
87
89
  };
88
90
 
89
- export function uint16 (bytes: number[], it: Iterator) {
91
+ export function uint16 (bytes: BufferLike, it: Iterator) {
90
92
  return bytes[it.offset++] | bytes[it.offset++] << 8;
91
93
  };
92
94
 
93
- export function int32 (bytes: number[], it: Iterator) {
95
+ export function int32 (bytes: BufferLike, it: Iterator) {
94
96
  return bytes[it.offset++] | bytes[it.offset++] << 8 | bytes[it.offset++] << 16 | bytes[it.offset++] << 24;
95
97
  };
96
98
 
97
- export function uint32 (bytes: number[], it: Iterator) {
99
+ export function uint32 (bytes: BufferLike, it: Iterator) {
98
100
  return int32(bytes, it) >>> 0;
99
101
  };
100
102
 
101
- export function float32(bytes: number[], it: Iterator) {
103
+ export function float32(bytes: BufferLike, it: Iterator) {
102
104
  return readFloat32(bytes, it);
103
105
  }
104
106
 
105
- export function float64(bytes: number[], it: Iterator) {
107
+ export function float64(bytes: BufferLike, it: Iterator) {
106
108
  return readFloat64(bytes, it);
107
109
  }
108
110
 
109
- export function int64(bytes: number[], it: Iterator) {
111
+ export function int64(bytes: BufferLike, it: Iterator) {
110
112
  const low = uint32(bytes, it);
111
113
  const high = int32(bytes, it) * Math.pow(2, 32);
112
114
  return high + low;
113
115
  };
114
116
 
115
- export function uint64(bytes: number[], it: Iterator) {
117
+ export function uint64(bytes: BufferLike, it: Iterator) {
116
118
  const low = uint32(bytes, it);
117
119
  const high = uint32(bytes, it) * Math.pow(2, 32);
118
120
  return high + low;
@@ -124,22 +126,22 @@ const _int32 = new Int32Array(2);
124
126
  const _float32 = new Float32Array(_int32.buffer);
125
127
  const _float64 = new Float64Array(_int32.buffer);
126
128
 
127
- export function readFloat32 (bytes: number[], it: Iterator) {
129
+ export function readFloat32 (bytes: BufferLike, it: Iterator) {
128
130
  _int32[0] = int32(bytes, it);
129
131
  return _float32[0];
130
132
  };
131
133
 
132
- export function readFloat64 (bytes: number[], it: Iterator) {
134
+ export function readFloat64 (bytes: BufferLike, it: Iterator) {
133
135
  _int32[_isLittleEndian ? 0 : 1] = int32(bytes, it);
134
136
  _int32[_isLittleEndian ? 1 : 0] = int32(bytes, it);
135
137
  return _float64[0];
136
138
  };
137
139
 
138
- export function boolean (bytes: number[], it: Iterator) {
140
+ export function boolean (bytes: BufferLike, it: Iterator) {
139
141
  return uint8(bytes, it) > 0;
140
142
  };
141
143
 
142
- export function string (bytes, it: Iterator) {
144
+ export function string (bytes: BufferLike, it: Iterator) {
143
145
  const prefix = bytes[it.offset++];
144
146
  let length: number;
145
147
 
@@ -157,13 +159,10 @@ export function string (bytes, it: Iterator) {
157
159
  length = uint32(bytes, it);
158
160
  }
159
161
 
160
- const value = utf8Read(bytes, it.offset, length);
161
- it.offset += length;
162
-
163
- return value;
162
+ return utf8Read(bytes, it, length);
164
163
  }
165
164
 
166
- export function stringCheck(bytes, it: Iterator) {
165
+ export function stringCheck(bytes: BufferLike, it: Iterator) {
167
166
  const prefix = bytes[it.offset];
168
167
  return (
169
168
  // fixstr
@@ -177,7 +176,7 @@ export function stringCheck(bytes, it: Iterator) {
177
176
  );
178
177
  }
179
178
 
180
- export function number (bytes, it: Iterator) {
179
+ export function number (bytes: BufferLike, it: Iterator) {
181
180
  const prefix = bytes[it.offset++];
182
181
 
183
182
  if (prefix < 0x80) {
@@ -230,7 +229,7 @@ export function number (bytes, it: Iterator) {
230
229
  }
231
230
  };
232
231
 
233
- export function numberCheck (bytes, it: Iterator) {
232
+ export function numberCheck (bytes: BufferLike, it: Iterator) {
234
233
  const prefix = bytes[it.offset];
235
234
  // positive fixint - 0x00 - 0x7f
236
235
  // float 32 - 0xca
@@ -249,7 +248,7 @@ export function numberCheck (bytes, it: Iterator) {
249
248
  );
250
249
  }
251
250
 
252
- export function arrayCheck (bytes, it: Iterator) {
251
+ export function arrayCheck (bytes: BufferLike, it: Iterator) {
253
252
  return bytes[it.offset] < 0xa0;
254
253
 
255
254
  // const prefix = bytes[it.offset] ;
@@ -268,7 +267,7 @@ export function arrayCheck (bytes, it: Iterator) {
268
267
  // return prefix;
269
268
  }
270
269
 
271
- export function switchStructureCheck(bytes, it: Iterator) {
270
+ export function switchStructureCheck(bytes: BufferLike, it: Iterator) {
272
271
  return (
273
272
  // previous byte should be `SWITCH_TO_STRUCTURE`
274
273
  bytes[it.offset - 1] === SWITCH_TO_STRUCTURE &&
@@ -35,28 +35,32 @@ let textEncoder: TextEncoder;
35
35
  // @ts-ignore
36
36
  try { textEncoder = new TextEncoder(); } catch (e) { }
37
37
 
38
- export function utf8Length(str) {
39
- var c = 0, length = 0;
40
- for (var i = 0, l = str.length; i < l; i++) {
41
- c = str.charCodeAt(i);
42
- if (c < 0x80) {
43
- length += 1;
44
- }
45
- else if (c < 0x800) {
46
- length += 2;
47
- }
48
- else if (c < 0xd800 || c >= 0xe000) {
49
- length += 3;
50
- }
51
- else {
52
- i++;
53
- length += 4;
38
+ const hasBufferByteLength = (typeof Buffer !== 'undefined' && Buffer.byteLength);
39
+
40
+ export const utf8Length = (hasBufferByteLength)
41
+ ? Buffer.byteLength // node
42
+ : function (str: string, _?: any) {
43
+ var c = 0, length = 0;
44
+ for (var i = 0, l = str.length; i < l; i++) {
45
+ c = str.charCodeAt(i);
46
+ if (c < 0x80) {
47
+ length += 1;
48
+ }
49
+ else if (c < 0x800) {
50
+ length += 2;
51
+ }
52
+ else if (c < 0xd800 || c >= 0xe000) {
53
+ length += 3;
54
+ }
55
+ else {
56
+ i++;
57
+ length += 4;
58
+ }
59
+ }
60
+ return length;
54
61
  }
55
- }
56
- return length;
57
- }
58
62
 
59
- export function utf8Write(view, str, it) {
63
+ export function utf8Write(view: BufferLike, str: string, it: Iterator) {
60
64
  var c = 0;
61
65
  for (var i = 0, l = str.length; i < l; i++) {
62
66
  c = str.charCodeAt(i);
@@ -166,8 +170,7 @@ export function string(bytes: BufferLike, value: string, it: Iterator) {
166
170
  // encode `null` strings as empty.
167
171
  if (!value) { value = ""; }
168
172
 
169
- // let length = utf8Length(value);
170
- let length = Buffer.byteLength(value, "utf8");
173
+ let length = utf8Length(value, "utf8");
171
174
  let size = 0;
172
175
 
173
176
  // fixstr
@@ -25,5 +25,6 @@ export enum OPERATION {
25
25
  REVERSE = 15,
26
26
  MOVE = 32,
27
27
  DELETE_BY_REFID = 33, // This operation is only used at ENCODING time. During DECODING, DELETE_BY_REFID is converted to DELETE
28
+ ADD_BY_REFID = 129,
28
29
 
29
30
  }
package/src/index.ts CHANGED
@@ -4,6 +4,8 @@ export type { DataChange } from "./decoder/DecodeOperation";
4
4
  import { $track, $encoder, $decoder, $filter, $getByIndex, $deleteByIndex, $changes, $childType } from "./types/symbols";
5
5
  export { $track, $encoder, $decoder, $filter, $getByIndex, $deleteByIndex, $changes, $childType };
6
6
 
7
+ export type { ToJSON } from "./types/HelperTypes";
8
+
7
9
  import { MapSchema } from "./types/custom/MapSchema"
8
10
  export { MapSchema };
9
11
 
@@ -56,6 +58,9 @@ export {
56
58
  // Annotation types
57
59
  export type { DefinitionType, PrimitiveType, Definition, } from "./annotations";
58
60
 
61
+ export { getDecoderStateCallbacks, CallbackProxy, GetCallbackProxy } from "./decoder/strategy/StateCallbacks";
62
+ export { getRawChangesCallback } from "./decoder/strategy/RawChanges";
63
+
59
64
  export { Encoder } from "./encoder/Encoder";
60
65
  export { encodeSchemaOperation, encodeArray as encodeKeyValueOperation } from "./encoder/EncodeOperation";
61
66
  export { ChangeTree, Ref } from "./encoder/ChangeTree";
@@ -471,6 +471,7 @@ export class ArraySchema<V = any> implements Array<V>, Collection<number, V> {
471
471
  * @param thisArg An object to which the this keyword can refer in the callbackfn function.
472
472
  * If thisArg is omitted, undefined is used as the this value.
473
473
  */
474
+ every<S extends V>(predicate: (value: V, index: number, array: V[]) => value is S, thisArg?: any): this is S[];
474
475
  every(callbackfn: (value: V, index: number, array: V[]) => unknown, thisArg?: any): boolean {
475
476
  return this.items.every(callbackfn, thisArg);
476
477
  }
@@ -690,7 +691,7 @@ export class ArraySchema<V = any> implements Array<V>, Collection<number, V> {
690
691
  //
691
692
  // ES2023
692
693
  //
693
- with(index: number, value: V): V[] {
694
+ with(index: number, value: V): ArraySchema<V> {
694
695
  const copy = this.items.slice();
695
696
  copy[index] = value;
696
697
  return new ArraySchema(...copy);