@colyseus/schema 2.0.31 → 3.0.0-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (159) hide show
  1. package/build/cjs/index.js +3614 -2634
  2. package/build/cjs/index.js.map +1 -1
  3. package/build/esm/index.mjs +3324 -2445
  4. package/build/esm/index.mjs.map +1 -1
  5. package/build/umd/index.js +3614 -2634
  6. package/lib/Decoder.d.ts +16 -0
  7. package/lib/Decoder.js +182 -0
  8. package/lib/Decoder.js.map +1 -0
  9. package/lib/Encoder.d.ts +13 -0
  10. package/lib/Encoder.js +79 -0
  11. package/lib/Encoder.js.map +1 -0
  12. package/lib/Metadata.d.ts +36 -0
  13. package/lib/Metadata.js +91 -0
  14. package/lib/Metadata.js.map +1 -0
  15. package/lib/Reflection.d.ts +7 -5
  16. package/lib/Reflection.js +62 -58
  17. package/lib/Reflection.js.map +1 -1
  18. package/lib/Schema.d.ts +39 -51
  19. package/lib/Schema.js +189 -731
  20. package/lib/Schema.js.map +1 -1
  21. package/lib/annotations.d.ts +26 -45
  22. package/lib/annotations.js +363 -194
  23. package/lib/annotations.js.map +1 -1
  24. package/lib/changes/ChangeSet.d.ts +12 -0
  25. package/lib/changes/ChangeSet.js +35 -0
  26. package/lib/changes/ChangeSet.js.map +1 -0
  27. package/lib/changes/DecodeOperation.d.ts +15 -0
  28. package/lib/changes/DecodeOperation.js +186 -0
  29. package/lib/changes/DecodeOperation.js.map +1 -0
  30. package/lib/changes/EncodeOperation.d.ts +18 -0
  31. package/lib/changes/EncodeOperation.js +130 -0
  32. package/lib/changes/EncodeOperation.js.map +1 -0
  33. package/lib/changes/consts.d.ts +14 -0
  34. package/lib/changes/consts.js +18 -0
  35. package/lib/changes/consts.js.map +1 -0
  36. package/lib/decoder/DecodeOperation.d.ts +24 -0
  37. package/lib/decoder/DecodeOperation.js +256 -0
  38. package/lib/decoder/DecodeOperation.js.map +1 -0
  39. package/lib/decoder/Decoder.d.ts +21 -0
  40. package/lib/decoder/Decoder.js +114 -0
  41. package/lib/decoder/Decoder.js.map +1 -0
  42. package/lib/decoder/ReferenceTracker.d.ts +26 -0
  43. package/lib/decoder/ReferenceTracker.js +131 -0
  44. package/lib/decoder/ReferenceTracker.js.map +1 -0
  45. package/lib/decoder/strategy/RawChanges.d.ts +3 -0
  46. package/lib/decoder/strategy/RawChanges.js +8 -0
  47. package/lib/decoder/strategy/RawChanges.js.map +1 -0
  48. package/lib/decoder/strategy/StateCallbacks.d.ts +20 -0
  49. package/lib/decoder/strategy/StateCallbacks.js +240 -0
  50. package/lib/decoder/strategy/StateCallbacks.js.map +1 -0
  51. package/lib/decoding/decode.d.ts +48 -0
  52. package/lib/decoding/decode.js +267 -0
  53. package/lib/decoding/decode.js.map +1 -0
  54. package/lib/ecs.d.ts +11 -0
  55. package/lib/ecs.js +160 -0
  56. package/lib/ecs.js.map +1 -0
  57. package/lib/encoder/ChangeTree.d.ts +72 -0
  58. package/lib/encoder/ChangeTree.js +384 -0
  59. package/lib/encoder/ChangeTree.js.map +1 -0
  60. package/lib/encoder/EncodeOperation.d.ts +25 -0
  61. package/lib/encoder/EncodeOperation.js +156 -0
  62. package/lib/encoder/EncodeOperation.js.map +1 -0
  63. package/lib/encoder/Encoder.d.ts +23 -0
  64. package/lib/encoder/Encoder.js +192 -0
  65. package/lib/encoder/Encoder.js.map +1 -0
  66. package/lib/encoder/StateView.d.ts +21 -0
  67. package/lib/encoder/StateView.js +196 -0
  68. package/lib/encoder/StateView.js.map +1 -0
  69. package/lib/encoding/assert.d.ts +9 -0
  70. package/lib/encoding/assert.js +47 -0
  71. package/lib/encoding/assert.js.map +1 -0
  72. package/lib/encoding/decode.js +1 -1
  73. package/lib/encoding/decode.js.map +1 -1
  74. package/lib/encoding/encode.d.ts +17 -16
  75. package/lib/encoding/encode.js +88 -81
  76. package/lib/encoding/encode.js.map +1 -1
  77. package/lib/encoding/spec.d.ts +25 -0
  78. package/lib/encoding/spec.js +30 -0
  79. package/lib/encoding/spec.js.map +1 -0
  80. package/lib/index.d.ts +18 -10
  81. package/lib/index.js +39 -17
  82. package/lib/index.js.map +1 -1
  83. package/lib/symbol.shim.d.ts +6 -0
  84. package/lib/symbol.shim.js +4 -0
  85. package/lib/symbol.shim.js.map +1 -0
  86. package/lib/types/ArraySchema.js +0 -7
  87. package/lib/types/ArraySchema.js.map +1 -1
  88. package/lib/types/HelperTypes.d.ts +10 -2
  89. package/lib/types/HelperTypes.js.map +1 -1
  90. package/lib/types/custom/ArraySchema.d.ts +245 -0
  91. package/lib/types/custom/ArraySchema.js +659 -0
  92. package/lib/types/custom/ArraySchema.js.map +1 -0
  93. package/lib/types/custom/CollectionSchema.d.ts +42 -0
  94. package/lib/types/custom/CollectionSchema.js +165 -0
  95. package/lib/types/custom/CollectionSchema.js.map +1 -0
  96. package/lib/types/custom/MapSchema.d.ts +43 -0
  97. package/lib/types/custom/MapSchema.js +200 -0
  98. package/lib/types/custom/MapSchema.js.map +1 -0
  99. package/lib/types/custom/SetSchema.d.ts +39 -0
  100. package/lib/types/custom/SetSchema.js +177 -0
  101. package/lib/types/custom/SetSchema.js.map +1 -0
  102. package/lib/types/registry.d.ts +6 -0
  103. package/lib/types/registry.js +19 -0
  104. package/lib/types/registry.js.map +1 -0
  105. package/lib/types/symbols.d.ts +29 -0
  106. package/lib/types/symbols.js +33 -0
  107. package/lib/types/symbols.js.map +1 -0
  108. package/lib/types/utils.d.ts +0 -8
  109. package/lib/types/utils.js +1 -33
  110. package/lib/types/utils.js.map +1 -1
  111. package/lib/usage.d.ts +1 -0
  112. package/lib/usage.js +22 -0
  113. package/lib/usage.js.map +1 -0
  114. package/lib/utils.d.ts +13 -2
  115. package/lib/utils.js +36 -15
  116. package/lib/utils.js.map +1 -1
  117. package/lib/v3.d.ts +1 -0
  118. package/lib/v3.js +427 -0
  119. package/lib/v3.js.map +1 -0
  120. package/lib/v3_bench.d.ts +1 -0
  121. package/lib/v3_bench.js +130 -0
  122. package/lib/v3_bench.js.map +1 -0
  123. package/lib/v3_experiment.d.ts +1 -0
  124. package/lib/v3_experiment.js +407 -0
  125. package/lib/v3_experiment.js.map +1 -0
  126. package/package.json +5 -5
  127. package/src/Metadata.ts +135 -0
  128. package/src/Reflection.ts +75 -66
  129. package/src/Schema.ts +213 -931
  130. package/src/annotations.ts +430 -243
  131. package/src/decoder/DecodeOperation.ts +372 -0
  132. package/src/decoder/Decoder.ts +155 -0
  133. package/src/decoder/ReferenceTracker.ts +151 -0
  134. package/src/decoder/strategy/RawChanges.ts +9 -0
  135. package/src/decoder/strategy/StateCallbacks.ts +326 -0
  136. package/src/encoder/ChangeTree.ts +492 -0
  137. package/src/encoder/EncodeOperation.ts +237 -0
  138. package/src/encoder/Encoder.ts +246 -0
  139. package/src/encoder/StateView.ts +229 -0
  140. package/src/encoding/assert.ts +58 -0
  141. package/src/encoding/decode.ts +1 -1
  142. package/src/encoding/encode.ts +88 -82
  143. package/src/encoding/spec.ts +29 -0
  144. package/src/index.ts +22 -19
  145. package/src/symbol.shim.ts +12 -0
  146. package/src/types/HelperTypes.ts +16 -2
  147. package/src/types/{ArraySchema.ts → custom/ArraySchema.ts} +345 -251
  148. package/src/types/{CollectionSchema.ts → custom/CollectionSchema.ts} +56 -46
  149. package/src/types/{MapSchema.ts → custom/MapSchema.ts} +88 -115
  150. package/src/types/{SetSchema.ts → custom/SetSchema.ts} +58 -47
  151. package/src/types/{typeRegistry.ts → registry.ts} +6 -6
  152. package/src/types/symbols.ts +36 -0
  153. package/src/types/utils.ts +0 -46
  154. package/src/utils.ts +50 -21
  155. package/src/v3_bench.ts +107 -0
  156. package/src/changes/ChangeTree.ts +0 -295
  157. package/src/changes/ReferenceTracker.ts +0 -91
  158. package/src/filters/index.ts +0 -23
  159. package/src/spec.ts +0 -49
@@ -0,0 +1,23 @@
1
+ /// <reference types="node" />
2
+ import type { Schema } from "../Schema";
3
+ import { TypeContext } from "../annotations";
4
+ import type { Iterator } from "../encoding/decode";
5
+ import { OPERATION } from '../encoding/spec';
6
+ import { Root } from "./ChangeTree";
7
+ import { StateView } from "./StateView";
8
+ export declare class Encoder<T extends Schema = any> {
9
+ static BUFFER_SIZE: number;
10
+ sharedBuffer: Buffer;
11
+ context: TypeContext;
12
+ state: T;
13
+ $root: Root;
14
+ constructor(root: T);
15
+ protected setRoot(state: T): void;
16
+ encode(it?: Iterator, view?: StateView, bytes?: Buffer, changeTrees?: Map<import("./ChangeTree").ChangeTree<any>, Map<number, OPERATION>>): Buffer;
17
+ encodeAll(it?: Iterator): Buffer;
18
+ encodeAllView(view: StateView, sharedOffset: number, it: Iterator, bytes?: Buffer): Buffer;
19
+ encodeView(view: StateView, sharedOffset: number, it: Iterator, bytes?: Buffer): Buffer;
20
+ onEndEncode(changeTrees?: Map<import("./ChangeTree").ChangeTree<any>, Map<number, OPERATION>>): void;
21
+ discardChanges(): void;
22
+ tryEncodeTypeId(bytes: Buffer, baseType: typeof Schema, targetType: typeof Schema, it: Iterator): void;
23
+ }
@@ -0,0 +1,192 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Encoder = void 0;
4
+ const annotations_1 = require("../annotations");
5
+ const symbols_1 = require("../types/symbols");
6
+ const encode = require("../encoding/encode");
7
+ const spec_1 = require("../encoding/spec");
8
+ const ChangeTree_1 = require("./ChangeTree");
9
+ const utils_1 = require("../utils");
10
+ class Encoder {
11
+ static { this.BUFFER_SIZE = 8 * 1024; } // 8KB
12
+ constructor(root) {
13
+ this.sharedBuffer = Buffer.allocUnsafeSlow(Encoder.BUFFER_SIZE);
14
+ this.setRoot(root);
15
+ //
16
+ // TODO: cache and restore "Context" based on root schema
17
+ // (to avoid creating a new context for every new room)
18
+ //
19
+ this.context = new annotations_1.TypeContext(root.constructor);
20
+ // console.log(">>>>>>>>>>>>>>>> Encoder types");
21
+ // this.context.schemas.forEach((id, schema) => {
22
+ // console.log("type:", id, schema.name, Object.keys(schema[Symbol.metadata]));
23
+ // });
24
+ }
25
+ setRoot(state) {
26
+ this.$root = new ChangeTree_1.Root();
27
+ this.state = state;
28
+ state[symbols_1.$changes].setRoot(this.$root);
29
+ }
30
+ encode(it = { offset: 0 }, view, bytes = this.sharedBuffer, changeTrees = this.$root.changes) {
31
+ const initialOffset = it.offset; // cache current offset in case we need to resize the buffer
32
+ const isEncodeAll = this.$root.allChanges === changeTrees;
33
+ const hasView = (view !== undefined);
34
+ const rootChangeTree = this.state[symbols_1.$changes];
35
+ const changeTreesIterator = changeTrees.entries();
36
+ for (const [changeTree, changes] of changeTreesIterator) {
37
+ const ref = changeTree.ref;
38
+ const ctor = ref['constructor'];
39
+ const encoder = ctor[symbols_1.$encoder];
40
+ const filter = ctor[symbols_1.$filter];
41
+ if (hasView) {
42
+ if (!view.items.has(changeTree)) {
43
+ view.invisible.add(changeTree);
44
+ continue; // skip this change tree
45
+ }
46
+ else if (view.invisible.has(changeTree)) {
47
+ view.invisible.delete(changeTree); // remove from invisible list
48
+ }
49
+ }
50
+ // skip root `refId` if it's the first change tree
51
+ if (it.offset !== initialOffset || changeTree !== rootChangeTree) {
52
+ bytes[it.offset++] = spec_1.SWITCH_TO_STRUCTURE & 255;
53
+ encode.number(bytes, changeTree.refId, it);
54
+ }
55
+ const changesIterator = changes.entries();
56
+ for (const [fieldIndex, operation] of changesIterator) {
57
+ //
58
+ // first pass (encodeAll), identify "filtered" operations without encoding them
59
+ // they will be encoded per client, based on their view.
60
+ //
61
+ // TODO: how can we optimize filtering out "encode all" operations?
62
+ // TODO: avoid checking if no view tags were defined
63
+ //
64
+ if (filter && !filter(ref, fieldIndex, view)) {
65
+ // console.log("SKIP FIELD:", { ref: changeTree.ref.constructor.name, fieldIndex, })
66
+ // console.log("ADD AS INVISIBLE:", fieldIndex, changeTree.ref.constructor.name)
67
+ // view?.invisible.add(changeTree);
68
+ continue;
69
+ }
70
+ // console.log("WILL ENCODE", {
71
+ // ref: changeTree.ref.constructor.name,
72
+ // fieldIndex,
73
+ // operation: OPERATION[operation],
74
+ // });
75
+ encoder(this, bytes, changeTree, fieldIndex, operation, it, isEncodeAll, hasView);
76
+ }
77
+ }
78
+ if (it.offset > bytes.byteLength) {
79
+ const newSize = (0, utils_1.getNextPowerOf2)(this.sharedBuffer.byteLength * 2);
80
+ console.warn("@colyseus/schema encode buffer overflow. Current buffer size: " + bytes.byteLength + ", encoding offset: " + it.offset + ", new size: " + newSize);
81
+ //
82
+ // resize buffer and re-encode (TODO: can we avoid re-encoding here?)
83
+ //
84
+ this.sharedBuffer = Buffer.allocUnsafeSlow(newSize);
85
+ return this.encode({ offset: initialOffset }, view);
86
+ }
87
+ else {
88
+ //
89
+ // only clear changes after making sure buffer resize is not required.
90
+ //
91
+ if (!isEncodeAll && !hasView) {
92
+ //
93
+ // FIXME: avoid iterating over change trees twice.
94
+ //
95
+ this.onEndEncode(changeTrees);
96
+ }
97
+ // return bytes;
98
+ return bytes.slice(0, it.offset);
99
+ }
100
+ }
101
+ encodeAll(it = { offset: 0 }) {
102
+ // console.log(`encodeAll(), this.$root.allChanges (${this.$root.allChanges.size})`);
103
+ // Array.from(this.$root.allChanges.entries()).map((item) => {
104
+ // console.log("->", item[0].refId, item[0].ref.toJSON());
105
+ // });
106
+ return this.encode(it, undefined, this.sharedBuffer, this.$root.allChanges);
107
+ }
108
+ encodeAllView(view, sharedOffset, it, bytes = this.sharedBuffer) {
109
+ const viewOffset = it.offset;
110
+ // console.log(`encodeAllView(), this.$root.allFilteredChanges (${this.$root.allFilteredChanges.size})`);
111
+ // this.debugAllFilteredChanges();
112
+ // try to encode "filtered" changes
113
+ this.encode(it, view, bytes, this.$root.allFilteredChanges);
114
+ return Buffer.concat([
115
+ bytes.slice(0, sharedOffset),
116
+ bytes.slice(viewOffset, it.offset)
117
+ ]);
118
+ }
119
+ // debugAllFilteredChanges() {
120
+ // Array.from(this.$root.allFilteredChanges.entries()).map((item) => {
121
+ // console.log("->", { refId: item[0].refId }, item[0].ref.toJSON());
122
+ // if (Array.isArray(item[0].ref.toJSON())) {
123
+ // item[1].forEach((op, key) => {
124
+ // console.log(" ->", { key, op: OPERATION[op] });
125
+ // })
126
+ // }
127
+ // });
128
+ // }
129
+ encodeView(view, sharedOffset, it, bytes = this.sharedBuffer) {
130
+ const viewOffset = it.offset;
131
+ // try to encode "filtered" changes
132
+ this.encode(it, view, bytes, this.$root.filteredChanges);
133
+ // encode visibility changes (add/remove for this view)
134
+ const viewChangesIterator = view.changes.entries();
135
+ for (const [changeTree, changes] of viewChangesIterator) {
136
+ if (changes.size === 0) {
137
+ // FIXME: avoid having empty changes if no changes were made
138
+ // console.log("changes.size === 0", changeTree.ref.constructor.name);
139
+ continue;
140
+ }
141
+ const ref = changeTree.ref;
142
+ const ctor = ref['constructor'];
143
+ const encoder = ctor[symbols_1.$encoder];
144
+ bytes[it.offset++] = spec_1.SWITCH_TO_STRUCTURE & 255;
145
+ encode.number(bytes, changeTree.refId, it);
146
+ const changesIterator = changes.entries();
147
+ for (const [fieldIndex, operation] of changesIterator) {
148
+ // isEncodeAll = false
149
+ // hasView = true
150
+ encoder(this, bytes, changeTree, fieldIndex, operation, it, false, true);
151
+ }
152
+ }
153
+ //
154
+ // TODO: only clear view changes after all views are encoded
155
+ // (to allow re-using StateView's for multiple clients)
156
+ //
157
+ // clear "view" changes after encoding
158
+ view.changes.clear();
159
+ return Buffer.concat([
160
+ bytes.slice(0, sharedOffset),
161
+ bytes.slice(viewOffset, it.offset)
162
+ ]);
163
+ }
164
+ onEndEncode(changeTrees = this.$root.changes) {
165
+ const changeTreesIterator = changeTrees.entries();
166
+ for (const [changeTree, _] of changeTreesIterator) {
167
+ changeTree.endEncode();
168
+ }
169
+ }
170
+ discardChanges() {
171
+ // discard shared changes
172
+ if (this.$root.changes.size > 0) {
173
+ this.onEndEncode(this.$root.changes);
174
+ this.$root.changes.clear();
175
+ }
176
+ // discard filtered changes
177
+ if (this.$root.filteredChanges.size > 0) {
178
+ this.onEndEncode(this.$root.filteredChanges);
179
+ this.$root.filteredChanges.clear();
180
+ }
181
+ }
182
+ tryEncodeTypeId(bytes, baseType, targetType, it) {
183
+ const baseTypeId = this.context.getTypeId(baseType);
184
+ const targetTypeId = this.context.getTypeId(targetType);
185
+ if (baseTypeId !== targetTypeId) {
186
+ bytes[it.offset++] = spec_1.TYPE_ID & 255;
187
+ encode.number(bytes, targetTypeId, it);
188
+ }
189
+ }
190
+ }
191
+ exports.Encoder = Encoder;
192
+ //# sourceMappingURL=Encoder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Encoder.js","sourceRoot":"","sources":["../../src/encoder/Encoder.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Schema } from \"../Schema\";\nimport { TypeContext } from \"../annotations\";\nimport { $changes, $encoder, $filter } from \"../types/symbols\";\n\nimport * as encode from \"../encoding/encode\";\nimport type { Iterator } from \"../encoding/decode\";\n\nimport { OPERATION, SWITCH_TO_STRUCTURE, TYPE_ID } from '../encoding/spec';\nimport { Root } from \"./ChangeTree\";\nimport { getNextPowerOf2 } from \"../utils\";\nimport { StateView } from \"./StateView\";\nimport { Metadata } from \"../Metadata\";\n\nexport class Encoder<T extends Schema = any> {\n static BUFFER_SIZE = 8 * 1024;// 8KB\n sharedBuffer = Buffer.allocUnsafeSlow(Encoder.BUFFER_SIZE);\n\n context: TypeContext;\n state: T;\n\n $root: Root;\n\n constructor(root: T) {\n this.setRoot(root);\n\n //\n // TODO: cache and restore \"Context\" based on root schema\n // (to avoid creating a new context for every new room)\n //\n this.context = new TypeContext(root.constructor as typeof Schema);\n\n // console.log(\">>>>>>>>>>>>>>>> Encoder types\");\n // this.context.schemas.forEach((id, schema) => {\n // console.log(\"type:\", id, schema.name, Object.keys(schema[Symbol.metadata]));\n // });\n }\n\n protected setRoot(state: T) {\n this.$root = new Root();\n this.state = state;\n state[$changes].setRoot(this.$root);\n }\n\n encode(\n it: Iterator = { offset: 0 },\n view?: StateView,\n bytes = this.sharedBuffer,\n changeTrees = this.$root.changes\n ): Buffer {\n const initialOffset = it.offset; // cache current offset in case we need to resize the buffer\n\n const isEncodeAll = this.$root.allChanges === changeTrees;\n const hasView = (view !== undefined);\n const rootChangeTree = this.state[$changes];\n\n const changeTreesIterator = changeTrees.entries();\n\n for (const [changeTree, changes] of changeTreesIterator) {\n const ref = changeTree.ref;\n\n const ctor = ref['constructor'];\n const encoder = ctor[$encoder];\n const filter = ctor[$filter];\n\n if (hasView) {\n if (!view.items.has(changeTree)) {\n view.invisible.add(changeTree);\n continue; // skip this change tree\n\n } else if (view.invisible.has(changeTree)) {\n view.invisible.delete(changeTree); // remove from invisible list\n }\n }\n\n // skip root `refId` if it's the first change tree\n if (it.offset !== initialOffset || changeTree !== rootChangeTree) {\n bytes[it.offset++] = SWITCH_TO_STRUCTURE & 255;\n encode.number(bytes, changeTree.refId, it);\n }\n\n const changesIterator = changes.entries();\n\n for (const [fieldIndex, operation] of changesIterator) {\n //\n // first pass (encodeAll), identify \"filtered\" operations without encoding them\n // they will be encoded per client, based on their view.\n //\n // TODO: how can we optimize filtering out \"encode all\" operations?\n // TODO: avoid checking if no view tags were defined\n //\n if (filter && !filter(ref, fieldIndex, view)) {\n // console.log(\"SKIP FIELD:\", { ref: changeTree.ref.constructor.name, fieldIndex, })\n\n // console.log(\"ADD AS INVISIBLE:\", fieldIndex, changeTree.ref.constructor.name)\n // view?.invisible.add(changeTree);\n continue;\n }\n\n // console.log(\"WILL ENCODE\", {\n // ref: changeTree.ref.constructor.name,\n // fieldIndex,\n // operation: OPERATION[operation],\n // });\n\n encoder(this, bytes, changeTree, fieldIndex, operation, it, isEncodeAll, hasView);\n }\n }\n\n if (it.offset > bytes.byteLength) {\n const newSize = getNextPowerOf2(this.sharedBuffer.byteLength * 2);\n console.warn(\"@colyseus/schema encode buffer overflow. Current buffer size: \" + bytes.byteLength + \", encoding offset: \" + it.offset + \", new size: \" + newSize);\n\n //\n // resize buffer and re-encode (TODO: can we avoid re-encoding here?)\n //\n this.sharedBuffer = Buffer.allocUnsafeSlow(newSize);\n return this.encode({ offset: initialOffset }, view);\n\n } else {\n //\n // only clear changes after making sure buffer resize is not required.\n //\n if (!isEncodeAll && !hasView) {\n //\n // FIXME: avoid iterating over change trees twice.\n //\n this.onEndEncode(changeTrees);\n }\n\n // return bytes;\n return bytes.slice(0, it.offset);\n }\n }\n\n encodeAll(it: Iterator = { offset: 0 }) {\n // console.log(`encodeAll(), this.$root.allChanges (${this.$root.allChanges.size})`);\n\n // Array.from(this.$root.allChanges.entries()).map((item) => {\n // console.log(\"->\", item[0].refId, item[0].ref.toJSON());\n // });\n\n return this.encode(it, undefined, this.sharedBuffer, this.$root.allChanges);\n }\n\n encodeAllView(view: StateView, sharedOffset: number, it: Iterator, bytes = this.sharedBuffer) {\n const viewOffset = it.offset;\n\n // console.log(`encodeAllView(), this.$root.allFilteredChanges (${this.$root.allFilteredChanges.size})`);\n // this.debugAllFilteredChanges();\n\n // try to encode \"filtered\" changes\n this.encode(it, view, bytes, this.$root.allFilteredChanges);\n\n return Buffer.concat([\n bytes.slice(0, sharedOffset),\n bytes.slice(viewOffset, it.offset)\n ]);\n }\n\n\n // debugAllFilteredChanges() {\n // Array.from(this.$root.allFilteredChanges.entries()).map((item) => {\n // console.log(\"->\", { refId: item[0].refId }, item[0].ref.toJSON());\n // if (Array.isArray(item[0].ref.toJSON())) {\n // item[1].forEach((op, key) => {\n // console.log(\" ->\", { key, op: OPERATION[op] });\n // })\n // }\n // });\n // }\n\n encodeView(view: StateView, sharedOffset: number, it: Iterator, bytes = this.sharedBuffer) {\n const viewOffset = it.offset;\n\n // try to encode \"filtered\" changes\n this.encode(it, view, bytes, this.$root.filteredChanges);\n\n // encode visibility changes (add/remove for this view)\n const viewChangesIterator = view.changes.entries();\n for (const [changeTree, changes] of viewChangesIterator) {\n if (changes.size === 0) {\n // FIXME: avoid having empty changes if no changes were made\n // console.log(\"changes.size === 0\", changeTree.ref.constructor.name);\n continue;\n }\n\n const ref = changeTree.ref;\n\n const ctor = ref['constructor'];\n const encoder = ctor[$encoder];\n\n bytes[it.offset++] = SWITCH_TO_STRUCTURE & 255;\n encode.number(bytes, changeTree.refId, it);\n\n const changesIterator = changes.entries();\n\n for (const [fieldIndex, operation] of changesIterator) {\n // isEncodeAll = false\n // hasView = true\n encoder(this, bytes, changeTree, fieldIndex, operation, it, false, true);\n }\n }\n\n //\n // TODO: only clear view changes after all views are encoded\n // (to allow re-using StateView's for multiple clients)\n //\n // clear \"view\" changes after encoding\n view.changes.clear();\n\n return Buffer.concat([\n bytes.slice(0, sharedOffset),\n bytes.slice(viewOffset, it.offset)\n ]);\n }\n\n onEndEncode(changeTrees = this.$root.changes) {\n const changeTreesIterator = changeTrees.entries();\n for (const [changeTree, _] of changeTreesIterator) {\n changeTree.endEncode();\n }\n }\n\n discardChanges() {\n // discard shared changes\n if (this.$root.changes.size > 0) {\n this.onEndEncode(this.$root.changes);\n this.$root.changes.clear();\n }\n // discard filtered changes\n if (this.$root.filteredChanges.size > 0) {\n this.onEndEncode(this.$root.filteredChanges);\n this.$root.filteredChanges.clear();\n }\n }\n\n tryEncodeTypeId (bytes: Buffer, baseType: typeof Schema, targetType: typeof Schema, it: Iterator) {\n const baseTypeId = this.context.getTypeId(baseType);\n const targetTypeId = this.context.getTypeId(targetType);\n\n if (baseTypeId !== targetTypeId) {\n bytes[it.offset++] = TYPE_ID & 255;\n encode.number(bytes, targetTypeId, it);\n }\n }\n}"]}
@@ -0,0 +1,21 @@
1
+ import { ChangeTree, Ref } from "./ChangeTree";
2
+ import { OPERATION } from "../encoding/spec";
3
+ export declare class StateView {
4
+ /**
5
+ * List of ChangeTree's that are visible to this view
6
+ */
7
+ items: WeakSet<ChangeTree>;
8
+ /**
9
+ * List of ChangeTree's that are invisible to this view
10
+ */
11
+ invisible: WeakSet<ChangeTree>;
12
+ tags?: WeakMap<ChangeTree, Set<number>>;
13
+ /**
14
+ * Manual "ADD" operations for changes per ChangeTree, specific to this view.
15
+ * (This is used to force encoding a property, even if it was not changed)
16
+ */
17
+ changes: Map<ChangeTree<any>, Map<number, OPERATION>>;
18
+ add(obj: Ref, tag?: number): this;
19
+ protected addParent(changeTree: ChangeTree, tag: number): void;
20
+ remove(obj: Ref, tag?: number): this;
21
+ }
@@ -0,0 +1,196 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.StateView = void 0;
4
+ const symbols_1 = require("../types/symbols");
5
+ const annotations_1 = require("../annotations");
6
+ const spec_1 = require("../encoding/spec");
7
+ const Metadata_1 = require("../Metadata");
8
+ class StateView {
9
+ constructor() {
10
+ /**
11
+ * List of ChangeTree's that are visible to this view
12
+ */
13
+ this.items = new WeakSet();
14
+ /**
15
+ * List of ChangeTree's that are invisible to this view
16
+ */
17
+ this.invisible = new WeakSet();
18
+ /**
19
+ * Manual "ADD" operations for changes per ChangeTree, specific to this view.
20
+ * (This is used to force encoding a property, even if it was not changed)
21
+ */
22
+ this.changes = new Map();
23
+ }
24
+ // TODO: allow to set multiple tags at once
25
+ add(obj, tag = annotations_1.DEFAULT_VIEW_TAG) {
26
+ if (!obj[symbols_1.$changes]) {
27
+ console.warn("StateView#add(), invalid object:", obj);
28
+ return this;
29
+ }
30
+ let changeTree = obj[symbols_1.$changes];
31
+ this.items.add(changeTree);
32
+ // Add children of this ChangeTree to this view
33
+ changeTree.forEachChild((change, _) => this.add(change.ref, tag));
34
+ // FIXME: ArraySchema/MapSchema does not have metadata
35
+ const metadata = obj.constructor[Symbol.metadata];
36
+ // add parent ChangeTree's, if they are invisible to this view
37
+ // TODO: REFACTOR addParent()
38
+ this.addParent(changeTree, tag);
39
+ //
40
+ // TODO: when adding an item of a MapSchema, the changes may not
41
+ // be set (only the parent's changes are set)
42
+ //
43
+ let changes = this.changes.get(changeTree);
44
+ if (changes === undefined) {
45
+ changes = new Map();
46
+ this.changes.set(changeTree, changes);
47
+ }
48
+ // set tag
49
+ if (tag !== annotations_1.DEFAULT_VIEW_TAG) {
50
+ if (!this.tags) {
51
+ this.tags = new WeakMap();
52
+ }
53
+ let tags;
54
+ if (!this.tags.has(changeTree)) {
55
+ tags = new Set();
56
+ this.tags.set(changeTree, tags);
57
+ }
58
+ else {
59
+ tags = this.tags.get(changeTree);
60
+ }
61
+ tags.add(tag);
62
+ // console.log("BY TAG:", tag);
63
+ // Ref: add tagged properties
64
+ metadata?.[-3]?.[tag]?.forEach((index) => {
65
+ if (changeTree.getChange(index) !== spec_1.OPERATION.DELETE) {
66
+ changes.set(index, spec_1.OPERATION.ADD);
67
+ }
68
+ });
69
+ }
70
+ else {
71
+ // console.log("DEFAULT TAG", changeTree.allChanges);
72
+ // // add default tag properties
73
+ // metadata?.[-3]?.[DEFAULT_VIEW_TAG]?.forEach((index) => {
74
+ // if (changeTree.getChange(index) !== OPERATION.DELETE) {
75
+ // changes.set(index, OPERATION.ADD);
76
+ // }
77
+ // });
78
+ const allChangesSet = (changeTree.isFiltered || changeTree.isPartiallyFiltered)
79
+ ? changeTree.allFilteredChanges
80
+ : changeTree.allChanges;
81
+ const it = allChangesSet.keys();
82
+ const isInvisible = this.invisible.has(changeTree);
83
+ for (const index of it) {
84
+ if ((isInvisible || metadata?.[metadata?.[index]].tag === tag) &&
85
+ changeTree.getChange(index) !== spec_1.OPERATION.DELETE) {
86
+ changes.set(index, spec_1.OPERATION.ADD);
87
+ }
88
+ }
89
+ }
90
+ // TODO: avoid unnecessary iteration here
91
+ while (changeTree.parent &&
92
+ (changeTree = changeTree.parent[symbols_1.$changes]) &&
93
+ (changeTree.isFiltered || changeTree.isPartiallyFiltered)) {
94
+ this.items.add(changeTree);
95
+ }
96
+ return this;
97
+ }
98
+ addParent(changeTree, tag) {
99
+ const parentRef = changeTree.parent;
100
+ if (!parentRef) {
101
+ return;
102
+ }
103
+ const parentChangeTree = parentRef[symbols_1.$changes];
104
+ const parentIndex = changeTree.parentIndex;
105
+ if (!this.invisible.has(parentChangeTree)) {
106
+ // parent is already available, no need to add it!
107
+ return;
108
+ }
109
+ this.addParent(parentChangeTree, tag);
110
+ // add parent's tag properties
111
+ if (parentChangeTree.getChange(parentIndex) !== spec_1.OPERATION.DELETE) {
112
+ let parentChanges = this.changes.get(parentChangeTree);
113
+ if (parentChanges === undefined) {
114
+ parentChanges = new Map();
115
+ this.changes.set(parentChangeTree, parentChanges);
116
+ }
117
+ // console.log("add parent change", {
118
+ // parentIndex,
119
+ // parentChanges,
120
+ // parentChange: (
121
+ // parentChangeTree.getChange(parentIndex) &&
122
+ // OPERATION[parentChangeTree.getChange(parentIndex)]
123
+ // ),
124
+ // })
125
+ if (!this.tags) {
126
+ this.tags = new WeakMap();
127
+ }
128
+ let tags;
129
+ if (!this.tags.has(parentChangeTree)) {
130
+ tags = new Set();
131
+ this.tags.set(parentChangeTree, tags);
132
+ }
133
+ else {
134
+ tags = this.tags.get(parentChangeTree);
135
+ }
136
+ tags.add(tag);
137
+ parentChanges.set(parentIndex, spec_1.OPERATION.ADD);
138
+ }
139
+ }
140
+ remove(obj, tag = annotations_1.DEFAULT_VIEW_TAG) {
141
+ const changeTree = obj[symbols_1.$changes];
142
+ if (!changeTree) {
143
+ console.warn("StateView#remove(), invalid object:", obj);
144
+ return this;
145
+ }
146
+ this.items.delete(changeTree);
147
+ const ref = changeTree.ref;
148
+ const metadata = ref.constructor[Symbol.metadata];
149
+ let changes = this.changes.get(changeTree);
150
+ if (changes === undefined) {
151
+ changes = new Map();
152
+ this.changes.set(changeTree, changes);
153
+ }
154
+ if (tag === annotations_1.DEFAULT_VIEW_TAG) {
155
+ // parent is collection (Map/Array)
156
+ const parent = changeTree.parent;
157
+ if (!Metadata_1.Metadata.isValidInstance(parent)) {
158
+ const parentChangeTree = parent[symbols_1.$changes];
159
+ let changes = this.changes.get(parentChangeTree);
160
+ if (changes === undefined) {
161
+ changes = new Map();
162
+ this.changes.set(parentChangeTree, changes);
163
+ }
164
+ // DELETE / DELETE BY REF ID
165
+ changes.set(changeTree.parentIndex, spec_1.OPERATION.DELETE);
166
+ }
167
+ else {
168
+ // delete all "tagged" properties.
169
+ metadata[-2].forEach((index) => changes.set(index, spec_1.OPERATION.DELETE));
170
+ }
171
+ }
172
+ else {
173
+ // delete only tagged properties
174
+ metadata[-3][tag].forEach((index) => changes.set(index, spec_1.OPERATION.DELETE));
175
+ }
176
+ // remove tag
177
+ if (this.tags && this.tags.has(changeTree)) {
178
+ const tags = this.tags.get(changeTree);
179
+ if (tag === undefined) {
180
+ // delete all tags
181
+ this.tags.delete(changeTree);
182
+ }
183
+ else {
184
+ // delete specific tag
185
+ tags.delete(tag);
186
+ // if tag set is empty, delete it entirely
187
+ if (tags.size === 0) {
188
+ this.tags.delete(changeTree);
189
+ }
190
+ }
191
+ }
192
+ return this;
193
+ }
194
+ }
195
+ exports.StateView = StateView;
196
+ //# sourceMappingURL=StateView.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"StateView.js","sourceRoot":"","sources":["../../src/encoder/StateView.ts"],"names":[],"mappings":"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","sourcesContent":["import { ChangeTree, Ref } from \"./ChangeTree\";\nimport { $changes } from \"../types/symbols\";\nimport { DEFAULT_VIEW_TAG } from \"../annotations\";\nimport { OPERATION } from \"../encoding/spec\";\nimport { Metadata } from \"../Metadata\";\n\nexport class StateView {\n /**\n * List of ChangeTree's that are visible to this view\n */\n items: WeakSet<ChangeTree> = new WeakSet<ChangeTree>();\n\n /**\n * List of ChangeTree's that are invisible to this view\n */\n invisible: WeakSet<ChangeTree> = new WeakSet<ChangeTree>();\n\n tags?: WeakMap<ChangeTree, Set<number>>; // TODO: use bit manipulation instead of Set<number> ()\n\n /**\n * Manual \"ADD\" operations for changes per ChangeTree, specific to this view.\n * (This is used to force encoding a property, even if it was not changed)\n */\n changes = new Map<ChangeTree, Map<number, OPERATION>>();\n\n // TODO: allow to set multiple tags at once\n add(obj: Ref, tag: number = DEFAULT_VIEW_TAG) {\n if (!obj[$changes]) {\n console.warn(\"StateView#add(), invalid object:\", obj);\n return this;\n }\n\n let changeTree: ChangeTree = obj[$changes];\n this.items.add(changeTree);\n\n // Add children of this ChangeTree to this view\n changeTree.forEachChild((change, _) =>\n this.add(change.ref, tag));\n\n // FIXME: ArraySchema/MapSchema does not have metadata\n const metadata: Metadata = obj.constructor[Symbol.metadata];\n\n // add parent ChangeTree's, if they are invisible to this view\n // TODO: REFACTOR addParent()\n this.addParent(changeTree, tag);\n\n //\n // TODO: when adding an item of a MapSchema, the changes may not\n // be set (only the parent's changes are set)\n //\n let changes = this.changes.get(changeTree);\n if (changes === undefined) {\n changes = new Map<number, OPERATION>();\n this.changes.set(changeTree, changes)\n }\n\n // set tag\n if (tag !== DEFAULT_VIEW_TAG) {\n if (!this.tags) {\n this.tags = new WeakMap<ChangeTree, Set<number>>();\n }\n let tags: Set<number>;\n if (!this.tags.has(changeTree)) {\n tags = new Set<number>();\n this.tags.set(changeTree, tags);\n } else {\n tags = this.tags.get(changeTree);\n }\n tags.add(tag);\n\n // console.log(\"BY TAG:\", tag);\n\n // Ref: add tagged properties\n metadata?.[-3]?.[tag]?.forEach((index) => {\n if (changeTree.getChange(index) !== OPERATION.DELETE) {\n changes.set(index, OPERATION.ADD)\n }\n });\n\n } else {\n\n // console.log(\"DEFAULT TAG\", changeTree.allChanges);\n\n // // add default tag properties\n // metadata?.[-3]?.[DEFAULT_VIEW_TAG]?.forEach((index) => {\n // if (changeTree.getChange(index) !== OPERATION.DELETE) {\n // changes.set(index, OPERATION.ADD);\n // }\n // });\n\n const allChangesSet = (changeTree.isFiltered || changeTree.isPartiallyFiltered)\n ? changeTree.allFilteredChanges\n : changeTree.allChanges;\n const it = allChangesSet.keys();\n const isInvisible = this.invisible.has(changeTree);\n\n for (const index of it) {\n if (\n (isInvisible || metadata?.[metadata?.[index]].tag === tag) &&\n changeTree.getChange(index) !== OPERATION.DELETE\n ) {\n changes.set(index, OPERATION.ADD);\n }\n }\n }\n\n // TODO: avoid unnecessary iteration here\n while (\n changeTree.parent &&\n (changeTree = changeTree.parent[$changes]) &&\n (changeTree.isFiltered || changeTree.isPartiallyFiltered)\n ) {\n this.items.add(changeTree);\n }\n\n return this;\n }\n\n protected addParent(changeTree: ChangeTree, tag: number) {\n const parentRef = changeTree.parent;\n if (!parentRef) { return; }\n\n const parentChangeTree = parentRef[$changes];\n const parentIndex = changeTree.parentIndex;\n\n if (!this.invisible.has(parentChangeTree)) {\n // parent is already available, no need to add it!\n return;\n }\n\n this.addParent(parentChangeTree, tag);\n\n // add parent's tag properties\n if (parentChangeTree.getChange(parentIndex) !== OPERATION.DELETE) {\n\n let parentChanges = this.changes.get(parentChangeTree);\n if (parentChanges === undefined) {\n parentChanges = new Map<number, OPERATION>();\n this.changes.set(parentChangeTree, parentChanges);\n }\n\n // console.log(\"add parent change\", {\n // parentIndex,\n // parentChanges,\n // parentChange: (\n // parentChangeTree.getChange(parentIndex) &&\n // OPERATION[parentChangeTree.getChange(parentIndex)]\n // ),\n // })\n\n if (!this.tags) { this.tags = new WeakMap<ChangeTree, Set<number>>(); }\n let tags: Set<number>;\n if (!this.tags.has(parentChangeTree)) {\n tags = new Set<number>();\n this.tags.set(parentChangeTree, tags);\n } else {\n tags = this.tags.get(parentChangeTree);\n }\n tags.add(tag);\n\n parentChanges.set(parentIndex, OPERATION.ADD);\n }\n\n }\n\n remove(obj: Ref, tag: number = DEFAULT_VIEW_TAG) {\n const changeTree = obj[$changes];\n if (!changeTree) {\n console.warn(\"StateView#remove(), invalid object:\", obj);\n return this;\n }\n\n this.items.delete(changeTree);\n\n const ref = changeTree.ref;\n const metadata: Metadata = ref.constructor[Symbol.metadata];\n\n let changes = this.changes.get(changeTree);\n if (changes === undefined) {\n changes = new Map<number, OPERATION>();\n this.changes.set(changeTree, changes)\n }\n\n if (tag === DEFAULT_VIEW_TAG) {\n // parent is collection (Map/Array)\n const parent = changeTree.parent;\n if (!Metadata.isValidInstance(parent)) {\n const parentChangeTree = parent[$changes];\n let changes = this.changes.get(parentChangeTree);\n if (changes === undefined) {\n changes = new Map<number, OPERATION>();\n this.changes.set(parentChangeTree, changes)\n }\n // DELETE / DELETE BY REF ID\n changes.set(changeTree.parentIndex, OPERATION.DELETE);\n\n } else {\n // delete all \"tagged\" properties.\n metadata[-2].forEach((index) =>\n changes.set(index, OPERATION.DELETE));\n }\n\n\n } else {\n // delete only tagged properties\n metadata[-3][tag].forEach((index) =>\n changes.set(index, OPERATION.DELETE));\n }\n\n // remove tag\n if (this.tags && this.tags.has(changeTree)) {\n const tags = this.tags.get(changeTree);\n if (tag === undefined) {\n // delete all tags\n this.tags.delete(changeTree);\n } else {\n // delete specific tag\n tags.delete(tag);\n\n // if tag set is empty, delete it entirely\n if (tags.size === 0) {\n this.tags.delete(changeTree);\n }\n }\n }\n\n return this;\n }\n}"]}
@@ -0,0 +1,9 @@
1
+ import { Schema } from "../Schema";
2
+ import { CollectionSchema } from "../types/custom/CollectionSchema";
3
+ import { MapSchema } from "../types/custom/MapSchema";
4
+ import { SetSchema } from "../types/custom/SetSchema";
5
+ import { ArraySchema } from "../types/custom/ArraySchema";
6
+ export declare class EncodeSchemaError extends Error {
7
+ }
8
+ export declare function assertType(value: any, type: string, klass: Schema, field: string | number): void;
9
+ export declare function assertInstanceType(value: Schema, type: typeof Schema | typeof ArraySchema | typeof MapSchema | typeof CollectionSchema | typeof SetSchema, klass: Schema, field: string | number): void;
@@ -0,0 +1,47 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.assertInstanceType = exports.assertType = exports.EncodeSchemaError = void 0;
4
+ class EncodeSchemaError extends Error {
5
+ }
6
+ exports.EncodeSchemaError = EncodeSchemaError;
7
+ function assertType(value, type, klass, field) {
8
+ let typeofTarget;
9
+ let allowNull = false;
10
+ switch (type) {
11
+ case "number":
12
+ case "int8":
13
+ case "uint8":
14
+ case "int16":
15
+ case "uint16":
16
+ case "int32":
17
+ case "uint32":
18
+ case "int64":
19
+ case "uint64":
20
+ case "float32":
21
+ case "float64":
22
+ typeofTarget = "number";
23
+ if (isNaN(value)) {
24
+ console.log(`trying to encode "NaN" in ${klass.constructor.name}#${field}`);
25
+ }
26
+ break;
27
+ case "string":
28
+ typeofTarget = "string";
29
+ allowNull = true;
30
+ break;
31
+ case "boolean":
32
+ // boolean is always encoded as true/false based on truthiness
33
+ return;
34
+ }
35
+ if (typeof (value) !== typeofTarget && (!allowNull || (allowNull && value !== null))) {
36
+ let foundValue = `'${JSON.stringify(value)}'${(value && value.constructor && ` (${value.constructor.name})`) || ''}`;
37
+ throw new EncodeSchemaError(`a '${typeofTarget}' was expected, but ${foundValue} was provided in ${klass.constructor.name}#${field}`);
38
+ }
39
+ }
40
+ exports.assertType = assertType;
41
+ function assertInstanceType(value, type, klass, field) {
42
+ if (!(value instanceof type)) {
43
+ throw new EncodeSchemaError(`a '${type.name}' was expected, but '${value && value.constructor.name}' was provided in ${klass.constructor.name}#${field}`);
44
+ }
45
+ }
46
+ exports.assertInstanceType = assertInstanceType;
47
+ //# sourceMappingURL=assert.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"assert.js","sourceRoot":"","sources":["../../src/encoding/assert.ts"],"names":[],"mappings":";;;AAMA,MAAa,iBAAkB,SAAQ,KAAK;CAAG;AAA/C,8CAA+C;AAE/C,SAAgB,UAAU,CAAC,KAAU,EAAE,IAAY,EAAE,KAAa,EAAE,KAAsB;IACtF,IAAI,YAAoB,CAAC;IACzB,IAAI,SAAS,GAAY,KAAK,CAAC;IAE/B,QAAQ,IAAI,EAAE,CAAC;QACX,KAAK,QAAQ,CAAC;QACd,KAAK,MAAM,CAAC;QACZ,KAAK,OAAO,CAAC;QACb,KAAK,OAAO,CAAC;QACb,KAAK,QAAQ,CAAC;QACd,KAAK,OAAO,CAAC;QACb,KAAK,QAAQ,CAAC;QACd,KAAK,OAAO,CAAC;QACb,KAAK,QAAQ,CAAC;QACd,KAAK,SAAS,CAAC;QACf,KAAK,SAAS;YACV,YAAY,GAAG,QAAQ,CAAC;YACxB,IAAI,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC;gBACf,OAAO,CAAC,GAAG,CAAC,6BAA6B,KAAK,CAAC,WAAW,CAAC,IAAI,IAAI,KAAK,EAAE,CAAC,CAAC;YAChF,CAAC;YACD,MAAM;QACV,KAAK,QAAQ;YACT,YAAY,GAAG,QAAQ,CAAC;YACxB,SAAS,GAAG,IAAI,CAAC;YACjB,MAAM;QACV,KAAK,SAAS;YACV,8DAA8D;YAC9D,OAAO;IACf,CAAC;IAED,IAAI,OAAO,CAAC,KAAK,CAAC,KAAK,YAAY,IAAI,CAAC,CAAC,SAAS,IAAI,CAAC,SAAS,IAAI,KAAK,KAAK,IAAI,CAAC,CAAC,EAAE,CAAC;QACnF,IAAI,UAAU,GAAG,IAAI,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,WAAW,IAAI,KAAK,KAAK,CAAC,WAAW,CAAC,IAAI,GAAG,CAAC,IAAI,EAAE,EAAE,CAAC;QACrH,MAAM,IAAI,iBAAiB,CAAC,MAAM,YAAY,uBAAuB,UAAU,oBAAoB,KAAK,CAAC,WAAW,CAAC,IAAI,IAAI,KAAK,EAAE,CAAC,CAAC;IAC1I,CAAC;AACL,CAAC;AAlCD,gCAkCC;AAED,SAAgB,kBAAkB,CAC9B,KAAa,EACb,IAIsB,EACtB,KAAa,EACb,KAAsB;IAEtB,IAAI,CAAC,CAAC,KAAK,YAAY,IAAI,CAAC,EAAE,CAAC;QAC3B,MAAM,IAAI,iBAAiB,CAAC,MAAM,IAAI,CAAC,IAAI,wBAAwB,KAAK,IAAK,KAAa,CAAC,WAAW,CAAC,IAAI,qBAAqB,KAAK,CAAC,WAAW,CAAC,IAAI,IAAI,KAAK,EAAE,CAAC,CAAC;IACvK,CAAC;AACL,CAAC;AAbD,gDAaC","sourcesContent":["import { Schema } from \"../Schema\";\nimport { CollectionSchema } from \"../types/custom/CollectionSchema\";\nimport { MapSchema } from \"../types/custom/MapSchema\";\nimport { SetSchema } from \"../types/custom/SetSchema\";\nimport { ArraySchema } from \"../types/custom/ArraySchema\";\n\nexport class EncodeSchemaError extends Error {}\n\nexport function assertType(value: any, type: string, klass: Schema, field: string | number) {\n let typeofTarget: string;\n let allowNull: boolean = false;\n\n switch (type) {\n case \"number\":\n case \"int8\":\n case \"uint8\":\n case \"int16\":\n case \"uint16\":\n case \"int32\":\n case \"uint32\":\n case \"int64\":\n case \"uint64\":\n case \"float32\":\n case \"float64\":\n typeofTarget = \"number\";\n if (isNaN(value)) {\n console.log(`trying to encode \"NaN\" in ${klass.constructor.name}#${field}`);\n }\n break;\n case \"string\":\n typeofTarget = \"string\";\n allowNull = true;\n break;\n case \"boolean\":\n // boolean is always encoded as true/false based on truthiness\n return;\n }\n\n if (typeof (value) !== typeofTarget && (!allowNull || (allowNull && value !== null))) {\n let foundValue = `'${JSON.stringify(value)}'${(value && value.constructor && ` (${value.constructor.name})`) || ''}`;\n throw new EncodeSchemaError(`a '${typeofTarget}' was expected, but ${foundValue} was provided in ${klass.constructor.name}#${field}`);\n }\n}\n\nexport function assertInstanceType(\n value: Schema,\n type: typeof Schema\n | typeof ArraySchema\n | typeof MapSchema\n | typeof CollectionSchema\n | typeof SetSchema,\n klass: Schema,\n field: string | number,\n) {\n if (!(value instanceof type)) {\n throw new EncodeSchemaError(`a '${type.name}' was expected, but '${value && (value as any).constructor.name}' was provided in ${klass.constructor.name}#${field}`);\n }\n}"]}
@@ -23,7 +23,7 @@
23
23
  */
24
24
  Object.defineProperty(exports, "__esModule", { value: true });
25
25
  exports.switchStructureCheck = exports.arrayCheck = exports.numberCheck = exports.number = exports.stringCheck = exports.string = exports.boolean = exports.readFloat64 = exports.readFloat32 = exports.uint64 = exports.int64 = exports.float64 = exports.float32 = exports.uint32 = exports.int32 = exports.uint16 = exports.int16 = exports.uint8 = exports.int8 = void 0;
26
- const spec_1 = require("../spec");
26
+ const spec_1 = require("./spec");
27
27
  function utf8Read(bytes, offset, length) {
28
28
  var string = '', chr = 0;
29
29
  for (var i = offset, end = offset + length; i < end; i++) {