node-opcua-variant 2.76.0 → 2.76.2

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/variant.js CHANGED
@@ -1,930 +1,930 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.sameVariant = exports.buildVariantArray = exports.isValidVariant = exports.coerceVariantType = exports.decodeVariant = exports.encodeVariant = exports.VARIANT_TYPE_MASK = exports.VARIANT_ARRAY_DIMENSIONS_MASK = exports.VARIANT_ARRAY_MASK = exports.Variant = void 0;
4
- /**
5
- * @module node-opcua-variant
6
- */
7
- const node_opcua_assert_1 = require("node-opcua-assert");
8
- const node_opcua_nodeid_1 = require("node-opcua-nodeid");
9
- const node_opcua_basic_types_1 = require("node-opcua-basic-types");
10
- const node_opcua_data_model_1 = require("node-opcua-data-model");
11
- const node_opcua_factory_1 = require("node-opcua-factory");
12
- const utils = require("node-opcua-utils");
13
- const DataType_enum_1 = require("./DataType_enum");
14
- const VariantArrayType_enum_1 = require("./VariantArrayType_enum");
15
- // tslint:disable:no-bitwise
16
- const schemaVariant = (0, node_opcua_factory_1.buildStructuredType)({
17
- baseType: "BaseUAObject",
18
- fields: [
19
- {
20
- defaultValue: DataType_enum_1.DataType.Null,
21
- documentation: "the variant type.",
22
- fieldType: "DataType",
23
- name: "dataType"
24
- },
25
- {
26
- defaultValue: VariantArrayType_enum_1.VariantArrayType.Scalar,
27
- fieldType: "VariantArrayType",
28
- name: "arrayType"
29
- },
30
- {
31
- defaultValue: null,
32
- fieldType: "Any",
33
- name: "value"
34
- },
35
- {
36
- defaultValue: null,
37
- documentation: "the matrix dimensions",
38
- fieldType: "UInt32",
39
- isArray: true,
40
- name: "dimensions"
41
- }
42
- ],
43
- name: "Variant"
44
- });
45
- function _coerceVariant(variantLike) {
46
- const value = variantLike instanceof Variant ? variantLike : new Variant(variantLike);
47
- return value;
48
- }
49
- class Variant extends node_opcua_factory_1.BaseUAObject {
50
- constructor(options) {
51
- super();
52
- if (options === null) {
53
- this.dataType = DataType_enum_1.DataType.Null;
54
- this.arrayType = VariantArrayType_enum_1.VariantArrayType.Scalar;
55
- this.value = null;
56
- this.dimensions = null;
57
- return;
58
- }
59
- const options2 = constructHook(options || {});
60
- this.dataType = DataType_enum_1.DataType.Null;
61
- this.arrayType = VariantArrayType_enum_1.VariantArrayType.Scalar;
62
- const schema = schemaVariant;
63
- this.dataType = options2.dataType;
64
- this.arrayType = options2.arrayType;
65
- this.value = (0, node_opcua_factory_1.initialize_field)(schema.fields[2], options2.value);
66
- this.dimensions = options2.dimensions || null;
67
- if (this.dataType === DataType_enum_1.DataType.ExtensionObject) {
68
- if (this.arrayType === VariantArrayType_enum_1.VariantArrayType.Scalar) {
69
- /* istanbul ignore next */
70
- if (this.value && !(this.value instanceof node_opcua_factory_1.BaseUAObject)) {
71
- throw new Error(`A variant with DataType.ExtensionObject must have a ExtensionObject value.\nMake sure that you specify a valid ExtensionObject to the value options in the Variant Constructor`);
72
- }
73
- }
74
- else {
75
- if (this.value) {
76
- for (const e of this.value) {
77
- /* istanbul ignore next */
78
- if (e && !(e instanceof node_opcua_factory_1.BaseUAObject)) {
79
- throw new Error("A variant with DataType.ExtensionObject must have a ExtensionObject value\nMake sure that you specify a valid ExtensionObject for all element of the value array passed to the Variant Constructor`");
80
- }
81
- }
82
- }
83
- }
84
- }
85
- }
86
- encode(stream) {
87
- encodeVariant(this, stream);
88
- }
89
- decode(stream) {
90
- internalDecodeVariant(this, stream);
91
- }
92
- decodeDebug(stream, options) {
93
- decodeDebugVariant(this, stream, options);
94
- }
95
- toString() {
96
- return variantToString(this);
97
- }
98
- isValid() {
99
- return isValidVariant(this.arrayType, this.dataType, this.value, this.dimensions);
100
- }
101
- clone() {
102
- return new Variant(this);
103
- }
104
- }
105
- exports.Variant = Variant;
106
- Variant.maxTypedArrayLength = 16 * 1024 * 1024;
107
- Variant.maxArrayLength = 1 * 1024 * 1024;
108
- Variant.schema = schemaVariant;
109
- Variant.coerce = _coerceVariant;
110
- Variant.computer_default_value = () => new Variant({ dataType: DataType_enum_1.DataType.Null });
111
- Variant.prototype.schema = schemaVariant;
112
- function variantToString(self, options) {
113
- function toString(value) {
114
- switch (self.dataType) {
115
- case DataType_enum_1.DataType.ByteString:
116
- return value ? "0x" + value.toString("hex") : "<null>";
117
- case DataType_enum_1.DataType.NodeId:
118
- return value instanceof node_opcua_nodeid_1.NodeId ? value.displayText() : value ? value.toString(options) : "";
119
- case DataType_enum_1.DataType.Boolean:
120
- return value.toString();
121
- case DataType_enum_1.DataType.DateTime:
122
- return value ? (value.toISOString ? value.toISOString() : value.toString()) : "<null>";
123
- default:
124
- return value ? value.toString(options) : "0";
125
- }
126
- }
127
- function f(value) {
128
- if (value === undefined || (value === null && typeof value === "object")) {
129
- return "<null>";
130
- }
131
- return toString(value);
132
- }
133
- let data = VariantArrayType_enum_1.VariantArrayType[self.arrayType];
134
- if (self.dimensions && self.dimensions.length >= 0) {
135
- data += "[ " + self.dimensions.join(",") + " ]";
136
- }
137
- data += "<" + DataType_enum_1.DataType[self.dataType] + ">";
138
- if (self.arrayType === VariantArrayType_enum_1.VariantArrayType.Scalar) {
139
- data += ", value: " + f(self.value);
140
- }
141
- else if (self.arrayType === VariantArrayType_enum_1.VariantArrayType.Array || self.arrayType === VariantArrayType_enum_1.VariantArrayType.Matrix) {
142
- if (!self.value) {
143
- data += ", null";
144
- }
145
- else {
146
- const a = [];
147
- (0, node_opcua_assert_1.assert)(Array.isArray(self.value) || self.value.buffer instanceof ArrayBuffer);
148
- for (let i = 0; i < Math.min(10, self.value.length); i++) {
149
- a[i] = self.value[i];
150
- }
151
- if (self.value.length > 10) {
152
- a.push("...");
153
- }
154
- data += ", l= " + self.value.length + ", value=[" + a.map(f).join(",") + "]";
155
- }
156
- }
157
- return "Variant(" + data + ")";
158
- }
159
- /***
160
- * @private
161
- */
162
- exports.VARIANT_ARRAY_MASK = 0x80;
163
- /***
164
- * @private
165
- */
166
- exports.VARIANT_ARRAY_DIMENSIONS_MASK = 0x40;
167
- /***
168
- * @private
169
- */
170
- exports.VARIANT_TYPE_MASK = 0x3f;
171
- const nullVariant = new Variant({ dataType: DataType_enum_1.DataType.Null });
172
- /***
173
- * @private
174
- */
175
- function encodeVariant(variant, stream) {
176
- try {
177
- if (!variant) {
178
- variant = nullVariant;
179
- }
180
- let encodingByte = variant.dataType;
181
- if (variant.arrayType === VariantArrayType_enum_1.VariantArrayType.Array || variant.arrayType === VariantArrayType_enum_1.VariantArrayType.Matrix) {
182
- encodingByte |= exports.VARIANT_ARRAY_MASK;
183
- }
184
- if (variant.dimensions) {
185
- (0, node_opcua_assert_1.assert)(variant.arrayType === VariantArrayType_enum_1.VariantArrayType.Matrix);
186
- (0, node_opcua_assert_1.assert)(variant.dimensions.length >= 0);
187
- encodingByte |= exports.VARIANT_ARRAY_DIMENSIONS_MASK;
188
- }
189
- (0, node_opcua_basic_types_1.encodeUInt8)(encodingByte, stream);
190
- if (variant.arrayType === VariantArrayType_enum_1.VariantArrayType.Array || variant.arrayType === VariantArrayType_enum_1.VariantArrayType.Matrix) {
191
- encodeVariantArray(variant.dataType, stream, variant.value);
192
- }
193
- else {
194
- const encode = get_encoder(variant.dataType || DataType_enum_1.DataType.Null);
195
- encode(variant.value, stream);
196
- }
197
- if ((encodingByte & exports.VARIANT_ARRAY_DIMENSIONS_MASK) === exports.VARIANT_ARRAY_DIMENSIONS_MASK && variant.dimensions) {
198
- encodeDimension(variant.dimensions, stream);
199
- }
200
- }
201
- catch (err) {
202
- console.log("Error encoding variant", err);
203
- console.log(variant === null || variant === void 0 ? void 0 : variant.toString());
204
- throw err;
205
- }
206
- }
207
- exports.encodeVariant = encodeVariant;
208
- /***
209
- * @private
210
- */
211
- function decodeDebugVariant(self, stream, options) {
212
- const tracer = options.tracer;
213
- const encodingByte = (0, node_opcua_basic_types_1.decodeUInt8)(stream);
214
- const isArray = (encodingByte & exports.VARIANT_ARRAY_MASK) === exports.VARIANT_ARRAY_MASK;
215
- const hasDimension = (encodingByte & exports.VARIANT_ARRAY_DIMENSIONS_MASK) === exports.VARIANT_ARRAY_DIMENSIONS_MASK;
216
- self.dataType = (encodingByte & exports.VARIANT_TYPE_MASK);
217
- tracer.dump("dataType: ", self.dataType);
218
- tracer.dump("isArray: ", isArray ? "true" : "false");
219
- tracer.dump("dimension: ", hasDimension);
220
- const decode = (0, node_opcua_factory_1.findBuiltInType)(DataType_enum_1.DataType[self.dataType]).decode;
221
- /* istanbul ignore next */
222
- if (!decode) {
223
- throw new Error("Variant.decode : cannot find decoder for type " + DataType_enum_1.DataType[self.dataType]);
224
- }
225
- const cursorBefore = stream.length;
226
- if (isArray) {
227
- self.arrayType = hasDimension ? VariantArrayType_enum_1.VariantArrayType.Matrix : VariantArrayType_enum_1.VariantArrayType.Array;
228
- _decodeVariantArrayDebug(stream, decode, tracer, self.dataType);
229
- }
230
- else {
231
- self.arrayType = VariantArrayType_enum_1.VariantArrayType.Scalar;
232
- self.value = decode(stream);
233
- tracer.trace("member", "Variant", self.value, cursorBefore, stream.length, DataType_enum_1.DataType[self.dataType]);
234
- }
235
- // ArrayDimensions
236
- // Int32[]
237
- // The length of each dimension.
238
- // This field is only present if the array dimensions flag is set in the encoding mask.
239
- // The lower rank dimensions appear first in the array.
240
- // All dimensions shall be specified and shall be greater than zero.
241
- // If ArrayDimensions are inconsistent with the ArrayLength then the decoder shall
242
- // stop and raise a BadDecodingError.
243
- if (hasDimension) {
244
- self.dimensions = decodeDimension(stream);
245
- const verification = calculate_product(self.dimensions);
246
- }
247
- }
248
- function internalDecodeVariant(self, stream) {
249
- const encodingByte = (0, node_opcua_basic_types_1.decodeUInt8)(stream);
250
- const isArray = (encodingByte & exports.VARIANT_ARRAY_MASK) === exports.VARIANT_ARRAY_MASK;
251
- const hasDimension = (encodingByte & exports.VARIANT_ARRAY_DIMENSIONS_MASK) === exports.VARIANT_ARRAY_DIMENSIONS_MASK;
252
- self.dataType = (encodingByte & exports.VARIANT_TYPE_MASK);
253
- if (isArray) {
254
- self.arrayType = hasDimension ? VariantArrayType_enum_1.VariantArrayType.Matrix : VariantArrayType_enum_1.VariantArrayType.Array;
255
- self.value = decodeVariantArray(self.dataType, stream);
256
- }
257
- else {
258
- self.arrayType = VariantArrayType_enum_1.VariantArrayType.Scalar;
259
- const decode = get_decoder(self.dataType);
260
- self.value = decode(stream);
261
- }
262
- if (hasDimension) {
263
- self.dimensions = decodeDimension(stream);
264
- const verification = calculate_product(self.dimensions);
265
- /* istanbul ignore next */
266
- if (verification !== self.value.length) {
267
- throw new Error("BadDecodingError");
268
- }
269
- }
270
- }
271
- /***
272
- * @private
273
- */
274
- function decodeVariant(stream, value) {
275
- value = value || new Variant(null);
276
- value.decode(stream);
277
- return value;
278
- }
279
- exports.decodeVariant = decodeVariant;
280
- function constructHook(options) {
281
- let isArrayTypeUnspecified = options.arrayType === undefined;
282
- if (options instanceof Variant) {
283
- const opts = {
284
- arrayType: options.arrayType,
285
- dataType: options.dataType,
286
- dimensions: options.dimensions,
287
- value: options.value
288
- };
289
- if (opts.dataType === DataType_enum_1.DataType.ExtensionObject) {
290
- if (opts.arrayType === VariantArrayType_enum_1.VariantArrayType.Scalar) {
291
- if (opts.value && opts.value.constructor) {
292
- opts.value = new opts.value.constructor(opts.value);
293
- }
294
- }
295
- else {
296
- if (opts.value) {
297
- opts.value = opts.value.map((e) => {
298
- if (e && e.constructor) {
299
- return new e.constructor(e);
300
- }
301
- return null;
302
- });
303
- }
304
- }
305
- }
306
- else if (opts.arrayType !== VariantArrayType_enum_1.VariantArrayType.Scalar) {
307
- opts.value = coerceVariantArray(opts.dataType, options.value);
308
- }
309
- return opts;
310
- }
311
- options.dataType = options.dataType || DataType_enum_1.DataType.Null;
312
- // dataType could be a string
313
- if (typeof options.dataType === "string") {
314
- const d = (0, node_opcua_factory_1.findBuiltInType)(options.dataType);
315
- /* istanbul ignore next */
316
- if (!d) {
317
- throw new Error("Cannot find Built-In data type or any DataType resolving to " + options.dataType);
318
- }
319
- options.dataType = DataType_enum_1.DataType[d.name];
320
- }
321
- // array type could be a string
322
- if (typeof options.arrayType === "string") {
323
- const at = VariantArrayType_enum_1.VariantArrayType[options.arrayType];
324
- /* istanbul ignore next */
325
- if (at === undefined) {
326
- throw new Error("ArrayType: invalid " + options.arrayType);
327
- }
328
- options.arrayType = at;
329
- }
330
- if (isArrayTypeUnspecified && Array.isArray(options.value)) {
331
- // when using UInt64 ou Int64 arrayType must be specified , as automatic detection cannot be made
332
- /* istanbul ignore next */
333
- if (options.dataType === DataType_enum_1.DataType.UInt64 || options.dataType === DataType_enum_1.DataType.Int64) {
334
- // we do nothing here ....
335
- throw new Error("Variant#constructor : when using UInt64 ou Int64" +
336
- " arrayType must be specified , as automatic detection cannot be made");
337
- }
338
- else {
339
- options.arrayType = VariantArrayType_enum_1.VariantArrayType.Array;
340
- isArrayTypeUnspecified = false;
341
- }
342
- }
343
- if (options.arrayType !== VariantArrayType_enum_1.VariantArrayType.Scalar && !isArrayTypeUnspecified) {
344
- (0, node_opcua_assert_1.assert)(options.arrayType === VariantArrayType_enum_1.VariantArrayType.Array || options.arrayType === VariantArrayType_enum_1.VariantArrayType.Matrix);
345
- /* istanbul ignore else */
346
- if (options.arrayType === VariantArrayType_enum_1.VariantArrayType.Array) {
347
- const value1 = coerceVariantArray(options.dataType, options.value);
348
- (0, node_opcua_assert_1.assert)(value1 === null || value1 !== options.value);
349
- options.value = value1;
350
- }
351
- else {
352
- (0, node_opcua_assert_1.assert)(options.arrayType === VariantArrayType_enum_1.VariantArrayType.Matrix);
353
- options.value = options.value || [];
354
- options.value = coerceVariantArray(options.dataType, options.value);
355
- /* istanbul ignore next */
356
- if (!options.dimensions) {
357
- throw new Error("Matrix Variant : missing dimensions");
358
- }
359
- /* istanbul ignore next */
360
- if (options.value.length !== calculate_product(options.dimensions)) {
361
- throw new Error("Matrix Variant : invalid value size = options.value.length " +
362
- options.value.length +
363
- "!=" +
364
- calculate_product(options.dimensions) +
365
- " => " +
366
- JSON.stringify(options.dimensions));
367
- }
368
- }
369
- }
370
- else {
371
- (0, node_opcua_assert_1.assert)(options.arrayType === VariantArrayType_enum_1.VariantArrayType.Scalar || options.arrayType === undefined);
372
- options.arrayType = VariantArrayType_enum_1.VariantArrayType.Scalar;
373
- const tmp = options.value;
374
- // scalar
375
- options.value = coerceVariantType(options.dataType, options.value);
376
- /* istanbul ignore next */
377
- if (!isValidVariant(options.arrayType, options.dataType, options.value, null)) {
378
- throw new Error("Invalid variant arrayType: " +
379
- VariantArrayType_enum_1.VariantArrayType[options.arrayType] +
380
- " dataType: " +
381
- DataType_enum_1.DataType[options.dataType] +
382
- " value:" +
383
- options.value +
384
- " (javascript type = " +
385
- typeof options.value +
386
- " )");
387
- }
388
- }
389
- if (options.dimensions) {
390
- (0, node_opcua_assert_1.assert)(options.arrayType === VariantArrayType_enum_1.VariantArrayType.Matrix, "dimension can only provided if variant is a matrix");
391
- }
392
- return options;
393
- }
394
- function calculate_product(array) {
395
- /* istanbul ignore next */
396
- if (!array || array.length === 0) {
397
- return 0;
398
- }
399
- return array.reduce((n, p) => n * p, 1);
400
- }
401
- function get_encoder(dataType) {
402
- const dataTypeAsString = typeof dataType === "string" ? dataType : DataType_enum_1.DataType[dataType];
403
- /* istanbul ignore next */
404
- if (!dataTypeAsString) {
405
- throw new Error("invalid dataType " + dataType);
406
- }
407
- const encode = (0, node_opcua_factory_1.findBuiltInType)(dataTypeAsString).encode;
408
- /* istanbul ignore next */
409
- if (!encode) {
410
- throw new Error("Cannot find encode function for dataType " + dataTypeAsString);
411
- }
412
- return encode;
413
- }
414
- function get_decoder(dataType) {
415
- const dataTypeAsString = DataType_enum_1.DataType[dataType];
416
- const decode = (0, node_opcua_factory_1.findBuiltInType)(dataTypeAsString).decode;
417
- /* istanbul ignore next */
418
- if (!decode) {
419
- throw new Error("Variant.decode : cannot find decoder for type " + dataTypeAsString);
420
- }
421
- return decode;
422
- }
423
- const displayWarning = true;
424
- function convertTo(dataType, arrayTypeConstructor, value) {
425
- // istanbul ignore next
426
- if (value === undefined || value === null) {
427
- return null;
428
- }
429
- if (arrayTypeConstructor && value instanceof arrayTypeConstructor) {
430
- const newArray = new value.constructor(value.length); // deep copy
431
- /* istanbul ignore if */
432
- if (newArray instanceof Buffer) {
433
- // required for nodejs 4.x
434
- value.copy(newArray);
435
- }
436
- else {
437
- newArray.set(value);
438
- }
439
- return newArray;
440
- }
441
- const coerceFunc = coerceVariantType.bind(null, dataType);
442
- const n = value.length;
443
- const newArr = arrayTypeConstructor ? new arrayTypeConstructor(n) : new Array(n);
444
- for (let i = 0; i < n; i++) {
445
- newArr[i] = coerceFunc(value[i]);
446
- }
447
- // istanbul ignore next
448
- if (arrayTypeConstructor && displayWarning && n > 10) {
449
- // tslint:disable-next-line:no-console
450
- console.log("Warning ! an array containing " + DataType_enum_1.DataType[dataType] + " elements has been provided as a generic array. ");
451
- // tslint:disable-next-line:no-console
452
- console.log(" This is inefficient as every array value will " + "have to be coerced and verified against the expected type");
453
- // tslint:disable-next-line:no-console
454
- console.log(" It is highly recommended that you use a " + " typed array ", arrayTypeConstructor.constructor.name, " instead");
455
- }
456
- return newArr;
457
- }
458
- const typedArrayHelpers = {};
459
- function _getHelper(dataType) {
460
- return typedArrayHelpers[DataType_enum_1.DataType[dataType]];
461
- }
462
- function coerceVariantArray(dataType, value) {
463
- const helper = _getHelper(dataType);
464
- if (helper) {
465
- return helper.coerce(value);
466
- }
467
- else {
468
- return convertTo(dataType, null, value);
469
- }
470
- }
471
- function encodeTypedArray(arrayTypeConstructor, stream, value) {
472
- (0, node_opcua_assert_1.assert)(value instanceof arrayTypeConstructor);
473
- (0, node_opcua_assert_1.assert)(value.buffer instanceof ArrayBuffer);
474
- (0, node_opcua_basic_types_1.encodeUInt32)(value.length, stream);
475
- stream.writeArrayBuffer(value.buffer, value.byteOffset, value.byteLength);
476
- }
477
- function encodeGeneralArray(dataType, stream, value) {
478
- if (!value) {
479
- (0, node_opcua_assert_1.assert)(value === null);
480
- (0, node_opcua_basic_types_1.encodeUInt32)(0xffffffff, stream);
481
- return;
482
- }
483
- (0, node_opcua_basic_types_1.encodeUInt32)(value.length, stream);
484
- const encode = get_encoder(dataType);
485
- for (const e of value) {
486
- encode(e, stream);
487
- }
488
- }
489
- function encodeVariantArray(dataType, stream, value) {
490
- if (value && value.buffer) {
491
- return _getHelper(dataType).encode(stream, value);
492
- }
493
- return encodeGeneralArray(dataType, stream, value);
494
- }
495
- function decodeTypedArray(arrayTypeConstructor, stream) {
496
- const length = (0, node_opcua_basic_types_1.decodeUInt32)(stream);
497
- /* istanbul ignore next */
498
- if (length === 0xffffffff) {
499
- return null;
500
- }
501
- if (length > Variant.maxTypedArrayLength) {
502
- throw new Error(`maxTypedArrayLength(${Variant.maxTypedArrayLength}) has been exceeded in Variant.decodeArray (typed Array) len=${length}`);
503
- }
504
- const byteLength = length * arrayTypeConstructor.BYTES_PER_ELEMENT;
505
- const arr = stream.readArrayBuffer(byteLength);
506
- const value = new arrayTypeConstructor(arr.buffer);
507
- (0, node_opcua_assert_1.assert)(value.length === length);
508
- return value;
509
- }
510
- function decodeGeneralArray(dataType, stream) {
511
- const length = (0, node_opcua_basic_types_1.decodeUInt32)(stream);
512
- /* istanbul ignore next */
513
- if (length === 0xffffffff) {
514
- return null;
515
- }
516
- if (length > Variant.maxArrayLength) {
517
- throw new Error(`maxArrayLength(${Variant.maxArrayLength}) has been exceeded in Variant.decodeArray len=${length}`);
518
- }
519
- const decode = get_decoder(dataType);
520
- const arr = [];
521
- for (let i = 0; i < length; i++) {
522
- arr.push(decode(stream));
523
- }
524
- return arr;
525
- }
526
- function decodeVariantArray(dataType, stream) {
527
- const helper = _getHelper(dataType);
528
- if (helper) {
529
- return helper.decode(stream);
530
- }
531
- else {
532
- return decodeGeneralArray(dataType, stream);
533
- }
534
- }
535
- function _declareTypeArrayHelper(dataType, typedArrayConstructor) {
536
- typedArrayHelpers[DataType_enum_1.DataType[dataType]] = {
537
- coerce: convertTo.bind(null, dataType, typedArrayConstructor),
538
- decode: decodeTypedArray.bind(null, typedArrayConstructor),
539
- encode: encodeTypedArray.bind(null, typedArrayConstructor)
540
- };
541
- }
542
- _declareTypeArrayHelper(DataType_enum_1.DataType.Float, Float32Array);
543
- _declareTypeArrayHelper(DataType_enum_1.DataType.Double, Float64Array);
544
- _declareTypeArrayHelper(DataType_enum_1.DataType.SByte, Int8Array);
545
- _declareTypeArrayHelper(DataType_enum_1.DataType.Byte, Uint8Array);
546
- _declareTypeArrayHelper(DataType_enum_1.DataType.Int16, Int16Array);
547
- _declareTypeArrayHelper(DataType_enum_1.DataType.Int32, Int32Array);
548
- _declareTypeArrayHelper(DataType_enum_1.DataType.UInt16, Uint16Array);
549
- _declareTypeArrayHelper(DataType_enum_1.DataType.UInt32, Uint32Array);
550
- function _decodeVariantArrayDebug(stream, decode, tracer, dataType) {
551
- let cursorBefore = stream.length;
552
- const length = (0, node_opcua_basic_types_1.decodeUInt32)(stream);
553
- let i;
554
- let element;
555
- tracer.trace("start_array", "Variant", -1, cursorBefore, stream.length);
556
- if (length === 0xffffffff) {
557
- // empty array
558
- tracer.trace("end_array", "Variant", stream.length);
559
- return;
560
- }
561
- const n1 = Math.min(10, length);
562
- // display a maximum of 10 elements
563
- for (i = 0; i < n1; i++) {
564
- tracer.trace("start_element", "", i);
565
- cursorBefore = stream.length;
566
- element = decode(stream);
567
- // arr.push(element);
568
- tracer.trace("member", "Variant", element, cursorBefore, stream.length, DataType_enum_1.DataType[dataType]);
569
- tracer.trace("end_element", "", i);
570
- }
571
- // keep reading
572
- if (length >= n1) {
573
- for (i = n1; i < length; i++) {
574
- decode(stream);
575
- }
576
- tracer.trace("start_element", "", n1);
577
- tracer.trace("member", "Variant", "...", cursorBefore, stream.length, DataType_enum_1.DataType[dataType]);
578
- tracer.trace("end_element", "", n1);
579
- }
580
- tracer.trace("end_array", "Variant", stream.length);
581
- }
582
- function decodeDimension(stream) {
583
- return decodeGeneralArray(DataType_enum_1.DataType.UInt32, stream);
584
- }
585
- function encodeDimension(dimensions, stream) {
586
- return encodeGeneralArray(DataType_enum_1.DataType.UInt32, stream, dimensions);
587
- }
588
- function isEnumerationItem(value) {
589
- return (value instanceof Object &&
590
- Object.prototype.hasOwnProperty.call(value, "value") &&
591
- Object.prototype.hasOwnProperty.call(value, "key") &&
592
- value.constructor.name === "EnumValueType");
593
- }
594
- function coerceVariantType(dataType, value) {
595
- /* eslint max-statements: ["error",1000], complexity: ["error",1000]*/
596
- if (value === undefined) {
597
- value = null;
598
- }
599
- if (isEnumerationItem(value)) {
600
- // OPCUA Specification 1.0.3 5.8.2 encoding rules for various dataType:
601
- // [...]Enumeration are always encoded as Int32 on the wire [...]
602
- /* istanbul ignore next */
603
- if (dataType !== DataType_enum_1.DataType.Int32 && dataType !== DataType_enum_1.DataType.ExtensionObject) {
604
- throw new Error("expecting DataType.Int32 for enumeration values ;" + " got DataType." + dataType.toString() + " instead");
605
- }
606
- }
607
- switch (dataType) {
608
- case DataType_enum_1.DataType.Null:
609
- value = null;
610
- break;
611
- case DataType_enum_1.DataType.LocalizedText:
612
- if (!value || !value.schema || value.schema !== node_opcua_data_model_1.LocalizedText.schema) {
613
- value = new node_opcua_data_model_1.LocalizedText(value);
614
- }
615
- break;
616
- case DataType_enum_1.DataType.QualifiedName:
617
- if (!value || !value.schema || value.schema !== node_opcua_data_model_1.QualifiedName.schema) {
618
- value = new node_opcua_data_model_1.QualifiedName(value);
619
- }
620
- break;
621
- case DataType_enum_1.DataType.Int32:
622
- case DataType_enum_1.DataType.Int16:
623
- case DataType_enum_1.DataType.UInt32:
624
- case DataType_enum_1.DataType.UInt16:
625
- (0, node_opcua_assert_1.assert)(value !== undefined);
626
- value = parseInt(value, 10);
627
- /* istanbul ignore next */
628
- if (!isFinite(value)) {
629
- // xx console.log("xxx ", value, ttt);
630
- throw new Error("expecting a number " + value);
631
- }
632
- break;
633
- case DataType_enum_1.DataType.UInt64:
634
- value = (0, node_opcua_basic_types_1.coerceUInt64)(value);
635
- break;
636
- case DataType_enum_1.DataType.Int64:
637
- value = (0, node_opcua_basic_types_1.coerceInt64)(value);
638
- break;
639
- case DataType_enum_1.DataType.ExtensionObject:
640
- break;
641
- case DataType_enum_1.DataType.DateTime:
642
- (0, node_opcua_assert_1.assert)(value === null || value instanceof Date);
643
- break;
644
- case DataType_enum_1.DataType.String:
645
- (0, node_opcua_assert_1.assert)(typeof value === "string" || value === null);
646
- break;
647
- case DataType_enum_1.DataType.ByteString:
648
- value = typeof value === "string" ? Buffer.from(value) : value;
649
- // istanbul ignore next
650
- if (!(value === null || value instanceof Buffer)) {
651
- throw new Error("ByteString should be null or a Buffer");
652
- }
653
- (0, node_opcua_assert_1.assert)(value === null || value instanceof Buffer);
654
- break;
655
- default:
656
- (0, node_opcua_assert_1.assert)(dataType !== undefined && dataType !== null, "Invalid DataType");
657
- break;
658
- case DataType_enum_1.DataType.NodeId:
659
- break;
660
- }
661
- return value;
662
- }
663
- exports.coerceVariantType = coerceVariantType;
664
- function isValidScalarVariant(dataType, value) {
665
- (0, node_opcua_assert_1.assert)(value === null ||
666
- DataType_enum_1.DataType.Int64 === dataType ||
667
- DataType_enum_1.DataType.ByteString === dataType ||
668
- DataType_enum_1.DataType.UInt64 === dataType ||
669
- !(value instanceof Array));
670
- (0, node_opcua_assert_1.assert)(value === null || !(value instanceof Int32Array));
671
- (0, node_opcua_assert_1.assert)(value === null || !(value instanceof Uint32Array));
672
- switch (dataType) {
673
- case DataType_enum_1.DataType.NodeId:
674
- return (0, node_opcua_basic_types_1.isValidNodeId)(value);
675
- case DataType_enum_1.DataType.String:
676
- return typeof value === "string" || utils.isNullOrUndefined(value);
677
- case DataType_enum_1.DataType.Int64:
678
- return (0, node_opcua_basic_types_1.isValidInt64)(value);
679
- case DataType_enum_1.DataType.UInt64:
680
- return (0, node_opcua_basic_types_1.isValidUInt64)(value);
681
- case DataType_enum_1.DataType.UInt32:
682
- return (0, node_opcua_basic_types_1.isValidUInt32)(value);
683
- case DataType_enum_1.DataType.Int32:
684
- return (0, node_opcua_basic_types_1.isValidInt32)(value);
685
- case DataType_enum_1.DataType.UInt16:
686
- return (0, node_opcua_basic_types_1.isValidUInt16)(value);
687
- case DataType_enum_1.DataType.Int16:
688
- return (0, node_opcua_basic_types_1.isValidInt16)(value);
689
- case DataType_enum_1.DataType.Byte:
690
- return (0, node_opcua_basic_types_1.isValidUInt8)(value);
691
- case DataType_enum_1.DataType.SByte:
692
- return (0, node_opcua_basic_types_1.isValidInt8)(value);
693
- case DataType_enum_1.DataType.Boolean:
694
- return (0, node_opcua_basic_types_1.isValidBoolean)(value);
695
- case DataType_enum_1.DataType.ByteString:
696
- return (0, node_opcua_basic_types_1.isValidByteString)(value);
697
- default:
698
- return true;
699
- }
700
- }
701
- function isValidArrayVariant(dataType, value) {
702
- if (value === null) {
703
- return true;
704
- }
705
- if (dataType === DataType_enum_1.DataType.Float && value instanceof Float32Array) {
706
- return true;
707
- }
708
- else if (dataType === DataType_enum_1.DataType.Double && value instanceof Float64Array) {
709
- return true;
710
- }
711
- else if (dataType === DataType_enum_1.DataType.SByte && value instanceof Int8Array) {
712
- return true;
713
- }
714
- else if (dataType === DataType_enum_1.DataType.Byte && (value instanceof Buffer || value instanceof Uint8Array)) {
715
- return true;
716
- }
717
- else if (dataType === DataType_enum_1.DataType.Int16 && value instanceof Int16Array) {
718
- return true;
719
- }
720
- else if (dataType === DataType_enum_1.DataType.Int32 && value instanceof Int32Array) {
721
- return true;
722
- }
723
- else if (dataType === DataType_enum_1.DataType.UInt16 && value instanceof Uint16Array) {
724
- return true;
725
- }
726
- else if (dataType === DataType_enum_1.DataType.UInt32 && value instanceof Uint32Array) {
727
- return true;
728
- }
729
- // array values can be store in Buffer, Float32Array
730
- (0, node_opcua_assert_1.assert)(Array.isArray(value));
731
- for (const valueItem of value) {
732
- if (!isValidScalarVariant(dataType, valueItem)) {
733
- return false;
734
- }
735
- }
736
- return true;
737
- }
738
- /*istanbul ignore next*/
739
- function isValidMatrixVariant(dataType, value, dimensions) {
740
- if (!dimensions) {
741
- return false;
742
- }
743
- if (!isValidArrayVariant(dataType, value)) {
744
- return false;
745
- }
746
- return true;
747
- }
748
- function isValidVariant(arrayType, dataType, value, dimensions) {
749
- switch (arrayType) {
750
- case VariantArrayType_enum_1.VariantArrayType.Scalar:
751
- return isValidScalarVariant(dataType, value);
752
- case VariantArrayType_enum_1.VariantArrayType.Array:
753
- return isValidArrayVariant(dataType, value);
754
- default:
755
- (0, node_opcua_assert_1.assert)(arrayType === VariantArrayType_enum_1.VariantArrayType.Matrix);
756
- return isValidMatrixVariant(dataType, value, dimensions);
757
- }
758
- }
759
- exports.isValidVariant = isValidVariant;
760
- function buildVariantArray(dataType, nbElements, defaultValue) {
761
- let value;
762
- switch (dataType) {
763
- case DataType_enum_1.DataType.Float:
764
- value = new Float32Array(nbElements);
765
- break;
766
- case DataType_enum_1.DataType.Double:
767
- value = new Float64Array(nbElements);
768
- break;
769
- case DataType_enum_1.DataType.UInt32:
770
- value = new Uint32Array(nbElements);
771
- break;
772
- case DataType_enum_1.DataType.Int32:
773
- value = new Int32Array(nbElements);
774
- break;
775
- case DataType_enum_1.DataType.UInt16:
776
- value = new Uint16Array(nbElements);
777
- break;
778
- case DataType_enum_1.DataType.Int16:
779
- value = new Int16Array(nbElements);
780
- break;
781
- case DataType_enum_1.DataType.Byte:
782
- value = new Uint8Array(nbElements);
783
- break;
784
- case DataType_enum_1.DataType.SByte:
785
- value = new Int8Array(nbElements);
786
- break;
787
- default:
788
- value = new Array(nbElements);
789
- }
790
- if (defaultValue !== undefined) {
791
- for (let i = 0; i < nbElements; i++) {
792
- value[i] = defaultValue;
793
- }
794
- }
795
- return value;
796
- }
797
- exports.buildVariantArray = buildVariantArray;
798
- // old version of nodejs do not provide a Buffer#equals test
799
- const oldNodeVersion = typeof process === "object" && process.versions && process.versions.node && process.versions.node.substring(0, 1) === "0";
800
- function __type(a) {
801
- return Object.prototype.toString.call(a);
802
- }
803
- function __check_same_object(o1, o2) {
804
- var _a, _b;
805
- if (o1 === o2)
806
- return true;
807
- if ((!o1 && o2) || (!o2 && o1))
808
- return false;
809
- const t1 = __type(o1);
810
- const t2 = __type(o2);
811
- if (t1 !== t2)
812
- return false;
813
- switch (t1) {
814
- case "[object Array]":
815
- return __check_same_array(o1, o2);
816
- case "[object Object]": {
817
- if (((_a = o1.constructor) === null || _a === void 0 ? void 0 : _a.name) !== ((_b = o2.constructor) === null || _b === void 0 ? void 0 : _b.name)) {
818
- return false;
819
- }
820
- const keys1 = Object.keys(o1);
821
- const keys2 = Object.keys(o2);
822
- // istanbul ignore next
823
- if (keys1.length !== keys2.length) {
824
- return false;
825
- }
826
- for (const k of Object.keys(o1)) {
827
- if (!__check_same_object(o1[k], o2[k])) {
828
- return false;
829
- }
830
- }
831
- return true;
832
- }
833
- case "[object Float32Array]":
834
- case "[object Float64Array]":
835
- case "[object Int32Array]":
836
- case "[object Int16Array]":
837
- case "[object Int8Array]":
838
- case "[object Uint32Array]":
839
- case "[object Uint16Array]":
840
- case "[object Uint8Array]": {
841
- const b1 = Buffer.from(o1.buffer, o1.byteOffset, o1.byteLength);
842
- const b2 = Buffer.from(o2.buffer, o2.byteOffset, o2.byteLength);
843
- return b1.equals(b2);
844
- }
845
- default:
846
- return o1 === o2;
847
- }
848
- }
849
- function __check_same_array(arr1, arr2) {
850
- if (!arr1 || !arr2) {
851
- return !arr1 && !arr2;
852
- }
853
- if (arr1.length !== arr2.length) {
854
- return false;
855
- }
856
- if (arr1.length === 0 && 0 === arr2.length) {
857
- return true;
858
- }
859
- if (!oldNodeVersion && arr1.buffer) {
860
- // v1 and v2 are TypedArray (such as Int32Array...)
861
- // this is the most efficient way to compare 2 buffers but it doesn't work with node <= 0.12
862
- (0, node_opcua_assert_1.assert)(arr2.buffer && __type(arr2.buffer) === "[object ArrayBuffer]");
863
- // compare byte by byte
864
- const b1 = Buffer.from(arr1.buffer, arr1.byteOffset, arr1.byteLength);
865
- const b2 = Buffer.from(arr2.buffer, arr2.byteOffset, arr2.byteLength);
866
- return b1.equals(b2);
867
- }
868
- const n = arr1.length;
869
- for (let i = 0; i < n; i++) {
870
- if (!__check_same_object(arr1[i], arr2[i])) {
871
- return false;
872
- }
873
- }
874
- return true;
875
- }
876
- /***
877
- * returns true if the two variant represent the same value
878
- * @param v1 the first variant to compare
879
- * @param v2 the variant to compare with
880
- */
881
- function sameVariant(v1, v2) {
882
- if (v1 === v2) {
883
- return true;
884
- }
885
- if ((!v1 && v2) || (v1 && !v2)) {
886
- return false;
887
- }
888
- if (v1.arrayType !== v2.arrayType) {
889
- return false;
890
- }
891
- if (v1.dataType !== v2.dataType) {
892
- return false;
893
- }
894
- if (v1.value === v2.value) {
895
- return true;
896
- }
897
- if (v1.arrayType === VariantArrayType_enum_1.VariantArrayType.Scalar) {
898
- if (v1.dataType === DataType_enum_1.DataType.ExtensionObject) {
899
- // compare two extension objects
900
- return __check_same_object(v1.value, v2.value);
901
- }
902
- if (Array.isArray(v1.value) && Array.isArray(v2.value)) {
903
- return __check_same_array(v1.value, v2.value);
904
- }
905
- if (Buffer.isBuffer(v1.value) && Buffer.isBuffer(v2.value)) {
906
- return v1.value.equals(v2.value);
907
- }
908
- }
909
- if (v1.arrayType === VariantArrayType_enum_1.VariantArrayType.Array) {
910
- return __check_same_array(v1.value, v2.value);
911
- }
912
- else if (v1.arrayType === VariantArrayType_enum_1.VariantArrayType.Matrix) {
913
- if (!__check_same_array(v1.dimensions, v2.dimensions)) {
914
- return false;
915
- }
916
- return __check_same_array(v1.value, v2.value);
917
- }
918
- return false;
919
- }
920
- exports.sameVariant = sameVariant;
921
- // ---------------------------------------------------------------------------------------------------------
922
- (0, node_opcua_factory_1.registerSpecialVariantEncoder)(Variant);
923
- (0, node_opcua_factory_1.registerType)({
924
- name: "Variant",
925
- subType: "",
926
- coerce: _coerceVariant,
927
- encode: encodeVariant,
928
- decode: decodeVariant
929
- });
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.sameVariant = exports.buildVariantArray = exports.isValidVariant = exports.coerceVariantType = exports.decodeVariant = exports.encodeVariant = exports.VARIANT_TYPE_MASK = exports.VARIANT_ARRAY_DIMENSIONS_MASK = exports.VARIANT_ARRAY_MASK = exports.Variant = void 0;
4
+ /**
5
+ * @module node-opcua-variant
6
+ */
7
+ const node_opcua_assert_1 = require("node-opcua-assert");
8
+ const node_opcua_nodeid_1 = require("node-opcua-nodeid");
9
+ const node_opcua_basic_types_1 = require("node-opcua-basic-types");
10
+ const node_opcua_data_model_1 = require("node-opcua-data-model");
11
+ const node_opcua_factory_1 = require("node-opcua-factory");
12
+ const utils = require("node-opcua-utils");
13
+ const DataType_enum_1 = require("./DataType_enum");
14
+ const VariantArrayType_enum_1 = require("./VariantArrayType_enum");
15
+ // tslint:disable:no-bitwise
16
+ const schemaVariant = (0, node_opcua_factory_1.buildStructuredType)({
17
+ baseType: "BaseUAObject",
18
+ fields: [
19
+ {
20
+ defaultValue: DataType_enum_1.DataType.Null,
21
+ documentation: "the variant type.",
22
+ fieldType: "DataType",
23
+ name: "dataType"
24
+ },
25
+ {
26
+ defaultValue: VariantArrayType_enum_1.VariantArrayType.Scalar,
27
+ fieldType: "VariantArrayType",
28
+ name: "arrayType"
29
+ },
30
+ {
31
+ defaultValue: null,
32
+ fieldType: "Any",
33
+ name: "value"
34
+ },
35
+ {
36
+ defaultValue: null,
37
+ documentation: "the matrix dimensions",
38
+ fieldType: "UInt32",
39
+ isArray: true,
40
+ name: "dimensions"
41
+ }
42
+ ],
43
+ name: "Variant"
44
+ });
45
+ function _coerceVariant(variantLike) {
46
+ const value = variantLike instanceof Variant ? variantLike : new Variant(variantLike);
47
+ return value;
48
+ }
49
+ class Variant extends node_opcua_factory_1.BaseUAObject {
50
+ constructor(options) {
51
+ super();
52
+ if (options === null) {
53
+ this.dataType = DataType_enum_1.DataType.Null;
54
+ this.arrayType = VariantArrayType_enum_1.VariantArrayType.Scalar;
55
+ this.value = null;
56
+ this.dimensions = null;
57
+ return;
58
+ }
59
+ const options2 = constructHook(options || {});
60
+ this.dataType = DataType_enum_1.DataType.Null;
61
+ this.arrayType = VariantArrayType_enum_1.VariantArrayType.Scalar;
62
+ const schema = schemaVariant;
63
+ this.dataType = options2.dataType;
64
+ this.arrayType = options2.arrayType;
65
+ this.value = (0, node_opcua_factory_1.initialize_field)(schema.fields[2], options2.value);
66
+ this.dimensions = options2.dimensions || null;
67
+ if (this.dataType === DataType_enum_1.DataType.ExtensionObject) {
68
+ if (this.arrayType === VariantArrayType_enum_1.VariantArrayType.Scalar) {
69
+ /* istanbul ignore next */
70
+ if (this.value && !(this.value instanceof node_opcua_factory_1.BaseUAObject)) {
71
+ throw new Error(`A variant with DataType.ExtensionObject must have a ExtensionObject value.\nMake sure that you specify a valid ExtensionObject to the value options in the Variant Constructor`);
72
+ }
73
+ }
74
+ else {
75
+ if (this.value) {
76
+ for (const e of this.value) {
77
+ /* istanbul ignore next */
78
+ if (e && !(e instanceof node_opcua_factory_1.BaseUAObject)) {
79
+ throw new Error("A variant with DataType.ExtensionObject must have a ExtensionObject value\nMake sure that you specify a valid ExtensionObject for all element of the value array passed to the Variant Constructor`");
80
+ }
81
+ }
82
+ }
83
+ }
84
+ }
85
+ }
86
+ encode(stream) {
87
+ encodeVariant(this, stream);
88
+ }
89
+ decode(stream) {
90
+ internalDecodeVariant(this, stream);
91
+ }
92
+ decodeDebug(stream, options) {
93
+ decodeDebugVariant(this, stream, options);
94
+ }
95
+ toString() {
96
+ return variantToString(this);
97
+ }
98
+ isValid() {
99
+ return isValidVariant(this.arrayType, this.dataType, this.value, this.dimensions);
100
+ }
101
+ clone() {
102
+ return new Variant(this);
103
+ }
104
+ }
105
+ exports.Variant = Variant;
106
+ Variant.maxTypedArrayLength = 16 * 1024 * 1024;
107
+ Variant.maxArrayLength = 1 * 1024 * 1024;
108
+ Variant.schema = schemaVariant;
109
+ Variant.coerce = _coerceVariant;
110
+ Variant.computer_default_value = () => new Variant({ dataType: DataType_enum_1.DataType.Null });
111
+ Variant.prototype.schema = schemaVariant;
112
+ function variantToString(self, options) {
113
+ function toString(value) {
114
+ switch (self.dataType) {
115
+ case DataType_enum_1.DataType.ByteString:
116
+ return value ? "0x" + value.toString("hex") : "<null>";
117
+ case DataType_enum_1.DataType.NodeId:
118
+ return value instanceof node_opcua_nodeid_1.NodeId ? value.displayText() : value ? value.toString(options) : "";
119
+ case DataType_enum_1.DataType.Boolean:
120
+ return value.toString();
121
+ case DataType_enum_1.DataType.DateTime:
122
+ return value ? (value.toISOString ? value.toISOString() : value.toString()) : "<null>";
123
+ default:
124
+ return value ? value.toString(options) : "0";
125
+ }
126
+ }
127
+ function f(value) {
128
+ if (value === undefined || (value === null && typeof value === "object")) {
129
+ return "<null>";
130
+ }
131
+ return toString(value);
132
+ }
133
+ let data = VariantArrayType_enum_1.VariantArrayType[self.arrayType];
134
+ if (self.dimensions && self.dimensions.length >= 0) {
135
+ data += "[ " + self.dimensions.join(",") + " ]";
136
+ }
137
+ data += "<" + DataType_enum_1.DataType[self.dataType] + ">";
138
+ if (self.arrayType === VariantArrayType_enum_1.VariantArrayType.Scalar) {
139
+ data += ", value: " + f(self.value);
140
+ }
141
+ else if (self.arrayType === VariantArrayType_enum_1.VariantArrayType.Array || self.arrayType === VariantArrayType_enum_1.VariantArrayType.Matrix) {
142
+ if (!self.value) {
143
+ data += ", null";
144
+ }
145
+ else {
146
+ const a = [];
147
+ (0, node_opcua_assert_1.assert)(Array.isArray(self.value) || self.value.buffer instanceof ArrayBuffer);
148
+ for (let i = 0; i < Math.min(10, self.value.length); i++) {
149
+ a[i] = self.value[i];
150
+ }
151
+ if (self.value.length > 10) {
152
+ a.push("...");
153
+ }
154
+ data += ", l= " + self.value.length + ", value=[" + a.map(f).join(",") + "]";
155
+ }
156
+ }
157
+ return "Variant(" + data + ")";
158
+ }
159
+ /***
160
+ * @private
161
+ */
162
+ exports.VARIANT_ARRAY_MASK = 0x80;
163
+ /***
164
+ * @private
165
+ */
166
+ exports.VARIANT_ARRAY_DIMENSIONS_MASK = 0x40;
167
+ /***
168
+ * @private
169
+ */
170
+ exports.VARIANT_TYPE_MASK = 0x3f;
171
+ const nullVariant = new Variant({ dataType: DataType_enum_1.DataType.Null });
172
+ /***
173
+ * @private
174
+ */
175
+ function encodeVariant(variant, stream) {
176
+ try {
177
+ if (!variant) {
178
+ variant = nullVariant;
179
+ }
180
+ let encodingByte = variant.dataType;
181
+ if (variant.arrayType === VariantArrayType_enum_1.VariantArrayType.Array || variant.arrayType === VariantArrayType_enum_1.VariantArrayType.Matrix) {
182
+ encodingByte |= exports.VARIANT_ARRAY_MASK;
183
+ }
184
+ if (variant.dimensions) {
185
+ (0, node_opcua_assert_1.assert)(variant.arrayType === VariantArrayType_enum_1.VariantArrayType.Matrix);
186
+ (0, node_opcua_assert_1.assert)(variant.dimensions.length >= 0);
187
+ encodingByte |= exports.VARIANT_ARRAY_DIMENSIONS_MASK;
188
+ }
189
+ (0, node_opcua_basic_types_1.encodeUInt8)(encodingByte, stream);
190
+ if (variant.arrayType === VariantArrayType_enum_1.VariantArrayType.Array || variant.arrayType === VariantArrayType_enum_1.VariantArrayType.Matrix) {
191
+ encodeVariantArray(variant.dataType, stream, variant.value);
192
+ }
193
+ else {
194
+ const encode = get_encoder(variant.dataType || DataType_enum_1.DataType.Null);
195
+ encode(variant.value, stream);
196
+ }
197
+ if ((encodingByte & exports.VARIANT_ARRAY_DIMENSIONS_MASK) === exports.VARIANT_ARRAY_DIMENSIONS_MASK && variant.dimensions) {
198
+ encodeDimension(variant.dimensions, stream);
199
+ }
200
+ }
201
+ catch (err) {
202
+ console.log("Error encoding variant", err);
203
+ console.log(variant === null || variant === void 0 ? void 0 : variant.toString());
204
+ throw err;
205
+ }
206
+ }
207
+ exports.encodeVariant = encodeVariant;
208
+ /***
209
+ * @private
210
+ */
211
+ function decodeDebugVariant(self, stream, options) {
212
+ const tracer = options.tracer;
213
+ const encodingByte = (0, node_opcua_basic_types_1.decodeUInt8)(stream);
214
+ const isArray = (encodingByte & exports.VARIANT_ARRAY_MASK) === exports.VARIANT_ARRAY_MASK;
215
+ const hasDimension = (encodingByte & exports.VARIANT_ARRAY_DIMENSIONS_MASK) === exports.VARIANT_ARRAY_DIMENSIONS_MASK;
216
+ self.dataType = (encodingByte & exports.VARIANT_TYPE_MASK);
217
+ tracer.dump("dataType: ", self.dataType);
218
+ tracer.dump("isArray: ", isArray ? "true" : "false");
219
+ tracer.dump("dimension: ", hasDimension);
220
+ const decode = (0, node_opcua_factory_1.findBuiltInType)(DataType_enum_1.DataType[self.dataType]).decode;
221
+ /* istanbul ignore next */
222
+ if (!decode) {
223
+ throw new Error("Variant.decode : cannot find decoder for type " + DataType_enum_1.DataType[self.dataType]);
224
+ }
225
+ const cursorBefore = stream.length;
226
+ if (isArray) {
227
+ self.arrayType = hasDimension ? VariantArrayType_enum_1.VariantArrayType.Matrix : VariantArrayType_enum_1.VariantArrayType.Array;
228
+ _decodeVariantArrayDebug(stream, decode, tracer, self.dataType);
229
+ }
230
+ else {
231
+ self.arrayType = VariantArrayType_enum_1.VariantArrayType.Scalar;
232
+ self.value = decode(stream);
233
+ tracer.trace("member", "Variant", self.value, cursorBefore, stream.length, DataType_enum_1.DataType[self.dataType]);
234
+ }
235
+ // ArrayDimensions
236
+ // Int32[]
237
+ // The length of each dimension.
238
+ // This field is only present if the array dimensions flag is set in the encoding mask.
239
+ // The lower rank dimensions appear first in the array.
240
+ // All dimensions shall be specified and shall be greater than zero.
241
+ // If ArrayDimensions are inconsistent with the ArrayLength then the decoder shall
242
+ // stop and raise a BadDecodingError.
243
+ if (hasDimension) {
244
+ self.dimensions = decodeDimension(stream);
245
+ const verification = calculate_product(self.dimensions);
246
+ }
247
+ }
248
+ function internalDecodeVariant(self, stream) {
249
+ const encodingByte = (0, node_opcua_basic_types_1.decodeUInt8)(stream);
250
+ const isArray = (encodingByte & exports.VARIANT_ARRAY_MASK) === exports.VARIANT_ARRAY_MASK;
251
+ const hasDimension = (encodingByte & exports.VARIANT_ARRAY_DIMENSIONS_MASK) === exports.VARIANT_ARRAY_DIMENSIONS_MASK;
252
+ self.dataType = (encodingByte & exports.VARIANT_TYPE_MASK);
253
+ if (isArray) {
254
+ self.arrayType = hasDimension ? VariantArrayType_enum_1.VariantArrayType.Matrix : VariantArrayType_enum_1.VariantArrayType.Array;
255
+ self.value = decodeVariantArray(self.dataType, stream);
256
+ }
257
+ else {
258
+ self.arrayType = VariantArrayType_enum_1.VariantArrayType.Scalar;
259
+ const decode = get_decoder(self.dataType);
260
+ self.value = decode(stream);
261
+ }
262
+ if (hasDimension) {
263
+ self.dimensions = decodeDimension(stream);
264
+ const verification = calculate_product(self.dimensions);
265
+ /* istanbul ignore next */
266
+ if (verification !== self.value.length) {
267
+ throw new Error("BadDecodingError");
268
+ }
269
+ }
270
+ }
271
+ /***
272
+ * @private
273
+ */
274
+ function decodeVariant(stream, value) {
275
+ value = value || new Variant(null);
276
+ value.decode(stream);
277
+ return value;
278
+ }
279
+ exports.decodeVariant = decodeVariant;
280
+ function constructHook(options) {
281
+ let isArrayTypeUnspecified = options.arrayType === undefined;
282
+ if (options instanceof Variant) {
283
+ const opts = {
284
+ arrayType: options.arrayType,
285
+ dataType: options.dataType,
286
+ dimensions: options.dimensions,
287
+ value: options.value
288
+ };
289
+ if (opts.dataType === DataType_enum_1.DataType.ExtensionObject) {
290
+ if (opts.arrayType === VariantArrayType_enum_1.VariantArrayType.Scalar) {
291
+ if (opts.value && opts.value.constructor) {
292
+ opts.value = new opts.value.constructor(opts.value);
293
+ }
294
+ }
295
+ else {
296
+ if (opts.value) {
297
+ opts.value = opts.value.map((e) => {
298
+ if (e && e.constructor) {
299
+ return new e.constructor(e);
300
+ }
301
+ return null;
302
+ });
303
+ }
304
+ }
305
+ }
306
+ else if (opts.arrayType !== VariantArrayType_enum_1.VariantArrayType.Scalar) {
307
+ opts.value = coerceVariantArray(opts.dataType, options.value);
308
+ }
309
+ return opts;
310
+ }
311
+ options.dataType = options.dataType || DataType_enum_1.DataType.Null;
312
+ // dataType could be a string
313
+ if (typeof options.dataType === "string") {
314
+ const d = (0, node_opcua_factory_1.findBuiltInType)(options.dataType);
315
+ /* istanbul ignore next */
316
+ if (!d) {
317
+ throw new Error("Cannot find Built-In data type or any DataType resolving to " + options.dataType);
318
+ }
319
+ options.dataType = DataType_enum_1.DataType[d.name];
320
+ }
321
+ // array type could be a string
322
+ if (typeof options.arrayType === "string") {
323
+ const at = VariantArrayType_enum_1.VariantArrayType[options.arrayType];
324
+ /* istanbul ignore next */
325
+ if (at === undefined) {
326
+ throw new Error("ArrayType: invalid " + options.arrayType);
327
+ }
328
+ options.arrayType = at;
329
+ }
330
+ if (isArrayTypeUnspecified && Array.isArray(options.value)) {
331
+ // when using UInt64 ou Int64 arrayType must be specified , as automatic detection cannot be made
332
+ /* istanbul ignore next */
333
+ if (options.dataType === DataType_enum_1.DataType.UInt64 || options.dataType === DataType_enum_1.DataType.Int64) {
334
+ // we do nothing here ....
335
+ throw new Error("Variant#constructor : when using UInt64 ou Int64" +
336
+ " arrayType must be specified , as automatic detection cannot be made");
337
+ }
338
+ else {
339
+ options.arrayType = VariantArrayType_enum_1.VariantArrayType.Array;
340
+ isArrayTypeUnspecified = false;
341
+ }
342
+ }
343
+ if (options.arrayType !== VariantArrayType_enum_1.VariantArrayType.Scalar && !isArrayTypeUnspecified) {
344
+ (0, node_opcua_assert_1.assert)(options.arrayType === VariantArrayType_enum_1.VariantArrayType.Array || options.arrayType === VariantArrayType_enum_1.VariantArrayType.Matrix);
345
+ /* istanbul ignore else */
346
+ if (options.arrayType === VariantArrayType_enum_1.VariantArrayType.Array) {
347
+ const value1 = coerceVariantArray(options.dataType, options.value);
348
+ (0, node_opcua_assert_1.assert)(value1 === null || value1 !== options.value);
349
+ options.value = value1;
350
+ }
351
+ else {
352
+ (0, node_opcua_assert_1.assert)(options.arrayType === VariantArrayType_enum_1.VariantArrayType.Matrix);
353
+ options.value = options.value || [];
354
+ options.value = coerceVariantArray(options.dataType, options.value);
355
+ /* istanbul ignore next */
356
+ if (!options.dimensions) {
357
+ throw new Error("Matrix Variant : missing dimensions");
358
+ }
359
+ /* istanbul ignore next */
360
+ if (options.value.length !== calculate_product(options.dimensions)) {
361
+ throw new Error("Matrix Variant : invalid value size = options.value.length " +
362
+ options.value.length +
363
+ "!=" +
364
+ calculate_product(options.dimensions) +
365
+ " => " +
366
+ JSON.stringify(options.dimensions));
367
+ }
368
+ }
369
+ }
370
+ else {
371
+ (0, node_opcua_assert_1.assert)(options.arrayType === VariantArrayType_enum_1.VariantArrayType.Scalar || options.arrayType === undefined);
372
+ options.arrayType = VariantArrayType_enum_1.VariantArrayType.Scalar;
373
+ const tmp = options.value;
374
+ // scalar
375
+ options.value = coerceVariantType(options.dataType, options.value);
376
+ /* istanbul ignore next */
377
+ if (!isValidVariant(options.arrayType, options.dataType, options.value, null)) {
378
+ throw new Error("Invalid variant arrayType: " +
379
+ VariantArrayType_enum_1.VariantArrayType[options.arrayType] +
380
+ " dataType: " +
381
+ DataType_enum_1.DataType[options.dataType] +
382
+ " value:" +
383
+ options.value +
384
+ " (javascript type = " +
385
+ typeof options.value +
386
+ " )");
387
+ }
388
+ }
389
+ if (options.dimensions) {
390
+ (0, node_opcua_assert_1.assert)(options.arrayType === VariantArrayType_enum_1.VariantArrayType.Matrix, "dimension can only provided if variant is a matrix");
391
+ }
392
+ return options;
393
+ }
394
+ function calculate_product(array) {
395
+ /* istanbul ignore next */
396
+ if (!array || array.length === 0) {
397
+ return 0;
398
+ }
399
+ return array.reduce((n, p) => n * p, 1);
400
+ }
401
+ function get_encoder(dataType) {
402
+ const dataTypeAsString = typeof dataType === "string" ? dataType : DataType_enum_1.DataType[dataType];
403
+ /* istanbul ignore next */
404
+ if (!dataTypeAsString) {
405
+ throw new Error("invalid dataType " + dataType);
406
+ }
407
+ const encode = (0, node_opcua_factory_1.findBuiltInType)(dataTypeAsString).encode;
408
+ /* istanbul ignore next */
409
+ if (!encode) {
410
+ throw new Error("Cannot find encode function for dataType " + dataTypeAsString);
411
+ }
412
+ return encode;
413
+ }
414
+ function get_decoder(dataType) {
415
+ const dataTypeAsString = DataType_enum_1.DataType[dataType];
416
+ const decode = (0, node_opcua_factory_1.findBuiltInType)(dataTypeAsString).decode;
417
+ /* istanbul ignore next */
418
+ if (!decode) {
419
+ throw new Error("Variant.decode : cannot find decoder for type " + dataTypeAsString);
420
+ }
421
+ return decode;
422
+ }
423
+ const displayWarning = true;
424
+ function convertTo(dataType, arrayTypeConstructor, value) {
425
+ // istanbul ignore next
426
+ if (value === undefined || value === null) {
427
+ return null;
428
+ }
429
+ if (arrayTypeConstructor && value instanceof arrayTypeConstructor) {
430
+ const newArray = new value.constructor(value.length); // deep copy
431
+ /* istanbul ignore if */
432
+ if (newArray instanceof Buffer) {
433
+ // required for nodejs 4.x
434
+ value.copy(newArray);
435
+ }
436
+ else {
437
+ newArray.set(value);
438
+ }
439
+ return newArray;
440
+ }
441
+ const coerceFunc = coerceVariantType.bind(null, dataType);
442
+ const n = value.length;
443
+ const newArr = arrayTypeConstructor ? new arrayTypeConstructor(n) : new Array(n);
444
+ for (let i = 0; i < n; i++) {
445
+ newArr[i] = coerceFunc(value[i]);
446
+ }
447
+ // istanbul ignore next
448
+ if (arrayTypeConstructor && displayWarning && n > 10) {
449
+ // tslint:disable-next-line:no-console
450
+ console.log("Warning ! an array containing " + DataType_enum_1.DataType[dataType] + " elements has been provided as a generic array. ");
451
+ // tslint:disable-next-line:no-console
452
+ console.log(" This is inefficient as every array value will " + "have to be coerced and verified against the expected type");
453
+ // tslint:disable-next-line:no-console
454
+ console.log(" It is highly recommended that you use a " + " typed array ", arrayTypeConstructor.constructor.name, " instead");
455
+ }
456
+ return newArr;
457
+ }
458
+ const typedArrayHelpers = {};
459
+ function _getHelper(dataType) {
460
+ return typedArrayHelpers[DataType_enum_1.DataType[dataType]];
461
+ }
462
+ function coerceVariantArray(dataType, value) {
463
+ const helper = _getHelper(dataType);
464
+ if (helper) {
465
+ return helper.coerce(value);
466
+ }
467
+ else {
468
+ return convertTo(dataType, null, value);
469
+ }
470
+ }
471
+ function encodeTypedArray(arrayTypeConstructor, stream, value) {
472
+ (0, node_opcua_assert_1.assert)(value instanceof arrayTypeConstructor);
473
+ (0, node_opcua_assert_1.assert)(value.buffer instanceof ArrayBuffer);
474
+ (0, node_opcua_basic_types_1.encodeUInt32)(value.length, stream);
475
+ stream.writeArrayBuffer(value.buffer, value.byteOffset, value.byteLength);
476
+ }
477
+ function encodeGeneralArray(dataType, stream, value) {
478
+ if (!value) {
479
+ (0, node_opcua_assert_1.assert)(value === null);
480
+ (0, node_opcua_basic_types_1.encodeUInt32)(0xffffffff, stream);
481
+ return;
482
+ }
483
+ (0, node_opcua_basic_types_1.encodeUInt32)(value.length, stream);
484
+ const encode = get_encoder(dataType);
485
+ for (const e of value) {
486
+ encode(e, stream);
487
+ }
488
+ }
489
+ function encodeVariantArray(dataType, stream, value) {
490
+ if (value && value.buffer) {
491
+ return _getHelper(dataType).encode(stream, value);
492
+ }
493
+ return encodeGeneralArray(dataType, stream, value);
494
+ }
495
+ function decodeTypedArray(arrayTypeConstructor, stream) {
496
+ const length = (0, node_opcua_basic_types_1.decodeUInt32)(stream);
497
+ /* istanbul ignore next */
498
+ if (length === 0xffffffff) {
499
+ return null;
500
+ }
501
+ if (length > Variant.maxTypedArrayLength) {
502
+ throw new Error(`maxTypedArrayLength(${Variant.maxTypedArrayLength}) has been exceeded in Variant.decodeArray (typed Array) len=${length}`);
503
+ }
504
+ const byteLength = length * arrayTypeConstructor.BYTES_PER_ELEMENT;
505
+ const arr = stream.readArrayBuffer(byteLength);
506
+ const value = new arrayTypeConstructor(arr.buffer);
507
+ (0, node_opcua_assert_1.assert)(value.length === length);
508
+ return value;
509
+ }
510
+ function decodeGeneralArray(dataType, stream) {
511
+ const length = (0, node_opcua_basic_types_1.decodeUInt32)(stream);
512
+ /* istanbul ignore next */
513
+ if (length === 0xffffffff) {
514
+ return null;
515
+ }
516
+ if (length > Variant.maxArrayLength) {
517
+ throw new Error(`maxArrayLength(${Variant.maxArrayLength}) has been exceeded in Variant.decodeArray len=${length}`);
518
+ }
519
+ const decode = get_decoder(dataType);
520
+ const arr = [];
521
+ for (let i = 0; i < length; i++) {
522
+ arr.push(decode(stream));
523
+ }
524
+ return arr;
525
+ }
526
+ function decodeVariantArray(dataType, stream) {
527
+ const helper = _getHelper(dataType);
528
+ if (helper) {
529
+ return helper.decode(stream);
530
+ }
531
+ else {
532
+ return decodeGeneralArray(dataType, stream);
533
+ }
534
+ }
535
+ function _declareTypeArrayHelper(dataType, typedArrayConstructor) {
536
+ typedArrayHelpers[DataType_enum_1.DataType[dataType]] = {
537
+ coerce: convertTo.bind(null, dataType, typedArrayConstructor),
538
+ decode: decodeTypedArray.bind(null, typedArrayConstructor),
539
+ encode: encodeTypedArray.bind(null, typedArrayConstructor)
540
+ };
541
+ }
542
+ _declareTypeArrayHelper(DataType_enum_1.DataType.Float, Float32Array);
543
+ _declareTypeArrayHelper(DataType_enum_1.DataType.Double, Float64Array);
544
+ _declareTypeArrayHelper(DataType_enum_1.DataType.SByte, Int8Array);
545
+ _declareTypeArrayHelper(DataType_enum_1.DataType.Byte, Uint8Array);
546
+ _declareTypeArrayHelper(DataType_enum_1.DataType.Int16, Int16Array);
547
+ _declareTypeArrayHelper(DataType_enum_1.DataType.Int32, Int32Array);
548
+ _declareTypeArrayHelper(DataType_enum_1.DataType.UInt16, Uint16Array);
549
+ _declareTypeArrayHelper(DataType_enum_1.DataType.UInt32, Uint32Array);
550
+ function _decodeVariantArrayDebug(stream, decode, tracer, dataType) {
551
+ let cursorBefore = stream.length;
552
+ const length = (0, node_opcua_basic_types_1.decodeUInt32)(stream);
553
+ let i;
554
+ let element;
555
+ tracer.trace("start_array", "Variant", -1, cursorBefore, stream.length);
556
+ if (length === 0xffffffff) {
557
+ // empty array
558
+ tracer.trace("end_array", "Variant", stream.length);
559
+ return;
560
+ }
561
+ const n1 = Math.min(10, length);
562
+ // display a maximum of 10 elements
563
+ for (i = 0; i < n1; i++) {
564
+ tracer.trace("start_element", "", i);
565
+ cursorBefore = stream.length;
566
+ element = decode(stream);
567
+ // arr.push(element);
568
+ tracer.trace("member", "Variant", element, cursorBefore, stream.length, DataType_enum_1.DataType[dataType]);
569
+ tracer.trace("end_element", "", i);
570
+ }
571
+ // keep reading
572
+ if (length >= n1) {
573
+ for (i = n1; i < length; i++) {
574
+ decode(stream);
575
+ }
576
+ tracer.trace("start_element", "", n1);
577
+ tracer.trace("member", "Variant", "...", cursorBefore, stream.length, DataType_enum_1.DataType[dataType]);
578
+ tracer.trace("end_element", "", n1);
579
+ }
580
+ tracer.trace("end_array", "Variant", stream.length);
581
+ }
582
+ function decodeDimension(stream) {
583
+ return decodeGeneralArray(DataType_enum_1.DataType.UInt32, stream);
584
+ }
585
+ function encodeDimension(dimensions, stream) {
586
+ return encodeGeneralArray(DataType_enum_1.DataType.UInt32, stream, dimensions);
587
+ }
588
+ function isEnumerationItem(value) {
589
+ return (value instanceof Object &&
590
+ Object.prototype.hasOwnProperty.call(value, "value") &&
591
+ Object.prototype.hasOwnProperty.call(value, "key") &&
592
+ value.constructor.name === "EnumValueType");
593
+ }
594
+ function coerceVariantType(dataType, value) {
595
+ /* eslint max-statements: ["error",1000], complexity: ["error",1000]*/
596
+ if (value === undefined) {
597
+ value = null;
598
+ }
599
+ if (isEnumerationItem(value)) {
600
+ // OPCUA Specification 1.0.3 5.8.2 encoding rules for various dataType:
601
+ // [...]Enumeration are always encoded as Int32 on the wire [...]
602
+ /* istanbul ignore next */
603
+ if (dataType !== DataType_enum_1.DataType.Int32 && dataType !== DataType_enum_1.DataType.ExtensionObject) {
604
+ throw new Error("expecting DataType.Int32 for enumeration values ;" + " got DataType." + dataType.toString() + " instead");
605
+ }
606
+ }
607
+ switch (dataType) {
608
+ case DataType_enum_1.DataType.Null:
609
+ value = null;
610
+ break;
611
+ case DataType_enum_1.DataType.LocalizedText:
612
+ if (!value || !value.schema || value.schema !== node_opcua_data_model_1.LocalizedText.schema) {
613
+ value = new node_opcua_data_model_1.LocalizedText(value);
614
+ }
615
+ break;
616
+ case DataType_enum_1.DataType.QualifiedName:
617
+ if (!value || !value.schema || value.schema !== node_opcua_data_model_1.QualifiedName.schema) {
618
+ value = new node_opcua_data_model_1.QualifiedName(value);
619
+ }
620
+ break;
621
+ case DataType_enum_1.DataType.Int32:
622
+ case DataType_enum_1.DataType.Int16:
623
+ case DataType_enum_1.DataType.UInt32:
624
+ case DataType_enum_1.DataType.UInt16:
625
+ (0, node_opcua_assert_1.assert)(value !== undefined);
626
+ value = parseInt(value, 10);
627
+ /* istanbul ignore next */
628
+ if (!isFinite(value)) {
629
+ // xx console.log("xxx ", value, ttt);
630
+ throw new Error("expecting a number " + value);
631
+ }
632
+ break;
633
+ case DataType_enum_1.DataType.UInt64:
634
+ value = (0, node_opcua_basic_types_1.coerceUInt64)(value);
635
+ break;
636
+ case DataType_enum_1.DataType.Int64:
637
+ value = (0, node_opcua_basic_types_1.coerceInt64)(value);
638
+ break;
639
+ case DataType_enum_1.DataType.ExtensionObject:
640
+ break;
641
+ case DataType_enum_1.DataType.DateTime:
642
+ (0, node_opcua_assert_1.assert)(value === null || value instanceof Date);
643
+ break;
644
+ case DataType_enum_1.DataType.String:
645
+ (0, node_opcua_assert_1.assert)(typeof value === "string" || value === null);
646
+ break;
647
+ case DataType_enum_1.DataType.ByteString:
648
+ value = typeof value === "string" ? Buffer.from(value) : value;
649
+ // istanbul ignore next
650
+ if (!(value === null || value instanceof Buffer)) {
651
+ throw new Error("ByteString should be null or a Buffer");
652
+ }
653
+ (0, node_opcua_assert_1.assert)(value === null || value instanceof Buffer);
654
+ break;
655
+ default:
656
+ (0, node_opcua_assert_1.assert)(dataType !== undefined && dataType !== null, "Invalid DataType");
657
+ break;
658
+ case DataType_enum_1.DataType.NodeId:
659
+ break;
660
+ }
661
+ return value;
662
+ }
663
+ exports.coerceVariantType = coerceVariantType;
664
+ function isValidScalarVariant(dataType, value) {
665
+ (0, node_opcua_assert_1.assert)(value === null ||
666
+ DataType_enum_1.DataType.Int64 === dataType ||
667
+ DataType_enum_1.DataType.ByteString === dataType ||
668
+ DataType_enum_1.DataType.UInt64 === dataType ||
669
+ !(value instanceof Array));
670
+ (0, node_opcua_assert_1.assert)(value === null || !(value instanceof Int32Array));
671
+ (0, node_opcua_assert_1.assert)(value === null || !(value instanceof Uint32Array));
672
+ switch (dataType) {
673
+ case DataType_enum_1.DataType.NodeId:
674
+ return (0, node_opcua_basic_types_1.isValidNodeId)(value);
675
+ case DataType_enum_1.DataType.String:
676
+ return typeof value === "string" || utils.isNullOrUndefined(value);
677
+ case DataType_enum_1.DataType.Int64:
678
+ return (0, node_opcua_basic_types_1.isValidInt64)(value);
679
+ case DataType_enum_1.DataType.UInt64:
680
+ return (0, node_opcua_basic_types_1.isValidUInt64)(value);
681
+ case DataType_enum_1.DataType.UInt32:
682
+ return (0, node_opcua_basic_types_1.isValidUInt32)(value);
683
+ case DataType_enum_1.DataType.Int32:
684
+ return (0, node_opcua_basic_types_1.isValidInt32)(value);
685
+ case DataType_enum_1.DataType.UInt16:
686
+ return (0, node_opcua_basic_types_1.isValidUInt16)(value);
687
+ case DataType_enum_1.DataType.Int16:
688
+ return (0, node_opcua_basic_types_1.isValidInt16)(value);
689
+ case DataType_enum_1.DataType.Byte:
690
+ return (0, node_opcua_basic_types_1.isValidUInt8)(value);
691
+ case DataType_enum_1.DataType.SByte:
692
+ return (0, node_opcua_basic_types_1.isValidInt8)(value);
693
+ case DataType_enum_1.DataType.Boolean:
694
+ return (0, node_opcua_basic_types_1.isValidBoolean)(value);
695
+ case DataType_enum_1.DataType.ByteString:
696
+ return (0, node_opcua_basic_types_1.isValidByteString)(value);
697
+ default:
698
+ return true;
699
+ }
700
+ }
701
+ function isValidArrayVariant(dataType, value) {
702
+ if (value === null) {
703
+ return true;
704
+ }
705
+ if (dataType === DataType_enum_1.DataType.Float && value instanceof Float32Array) {
706
+ return true;
707
+ }
708
+ else if (dataType === DataType_enum_1.DataType.Double && value instanceof Float64Array) {
709
+ return true;
710
+ }
711
+ else if (dataType === DataType_enum_1.DataType.SByte && value instanceof Int8Array) {
712
+ return true;
713
+ }
714
+ else if (dataType === DataType_enum_1.DataType.Byte && (value instanceof Buffer || value instanceof Uint8Array)) {
715
+ return true;
716
+ }
717
+ else if (dataType === DataType_enum_1.DataType.Int16 && value instanceof Int16Array) {
718
+ return true;
719
+ }
720
+ else if (dataType === DataType_enum_1.DataType.Int32 && value instanceof Int32Array) {
721
+ return true;
722
+ }
723
+ else if (dataType === DataType_enum_1.DataType.UInt16 && value instanceof Uint16Array) {
724
+ return true;
725
+ }
726
+ else if (dataType === DataType_enum_1.DataType.UInt32 && value instanceof Uint32Array) {
727
+ return true;
728
+ }
729
+ // array values can be store in Buffer, Float32Array
730
+ (0, node_opcua_assert_1.assert)(Array.isArray(value));
731
+ for (const valueItem of value) {
732
+ if (!isValidScalarVariant(dataType, valueItem)) {
733
+ return false;
734
+ }
735
+ }
736
+ return true;
737
+ }
738
+ /*istanbul ignore next*/
739
+ function isValidMatrixVariant(dataType, value, dimensions) {
740
+ if (!dimensions) {
741
+ return false;
742
+ }
743
+ if (!isValidArrayVariant(dataType, value)) {
744
+ return false;
745
+ }
746
+ return true;
747
+ }
748
+ function isValidVariant(arrayType, dataType, value, dimensions) {
749
+ switch (arrayType) {
750
+ case VariantArrayType_enum_1.VariantArrayType.Scalar:
751
+ return isValidScalarVariant(dataType, value);
752
+ case VariantArrayType_enum_1.VariantArrayType.Array:
753
+ return isValidArrayVariant(dataType, value);
754
+ default:
755
+ (0, node_opcua_assert_1.assert)(arrayType === VariantArrayType_enum_1.VariantArrayType.Matrix);
756
+ return isValidMatrixVariant(dataType, value, dimensions);
757
+ }
758
+ }
759
+ exports.isValidVariant = isValidVariant;
760
+ function buildVariantArray(dataType, nbElements, defaultValue) {
761
+ let value;
762
+ switch (dataType) {
763
+ case DataType_enum_1.DataType.Float:
764
+ value = new Float32Array(nbElements);
765
+ break;
766
+ case DataType_enum_1.DataType.Double:
767
+ value = new Float64Array(nbElements);
768
+ break;
769
+ case DataType_enum_1.DataType.UInt32:
770
+ value = new Uint32Array(nbElements);
771
+ break;
772
+ case DataType_enum_1.DataType.Int32:
773
+ value = new Int32Array(nbElements);
774
+ break;
775
+ case DataType_enum_1.DataType.UInt16:
776
+ value = new Uint16Array(nbElements);
777
+ break;
778
+ case DataType_enum_1.DataType.Int16:
779
+ value = new Int16Array(nbElements);
780
+ break;
781
+ case DataType_enum_1.DataType.Byte:
782
+ value = new Uint8Array(nbElements);
783
+ break;
784
+ case DataType_enum_1.DataType.SByte:
785
+ value = new Int8Array(nbElements);
786
+ break;
787
+ default:
788
+ value = new Array(nbElements);
789
+ }
790
+ if (defaultValue !== undefined) {
791
+ for (let i = 0; i < nbElements; i++) {
792
+ value[i] = defaultValue;
793
+ }
794
+ }
795
+ return value;
796
+ }
797
+ exports.buildVariantArray = buildVariantArray;
798
+ // old version of nodejs do not provide a Buffer#equals test
799
+ const oldNodeVersion = typeof process === "object" && process.versions && process.versions.node && process.versions.node.substring(0, 1) === "0";
800
+ function __type(a) {
801
+ return Object.prototype.toString.call(a);
802
+ }
803
+ function __check_same_object(o1, o2) {
804
+ var _a, _b;
805
+ if (o1 === o2)
806
+ return true;
807
+ if ((!o1 && o2) || (!o2 && o1))
808
+ return false;
809
+ const t1 = __type(o1);
810
+ const t2 = __type(o2);
811
+ if (t1 !== t2)
812
+ return false;
813
+ switch (t1) {
814
+ case "[object Array]":
815
+ return __check_same_array(o1, o2);
816
+ case "[object Object]": {
817
+ if (((_a = o1.constructor) === null || _a === void 0 ? void 0 : _a.name) !== ((_b = o2.constructor) === null || _b === void 0 ? void 0 : _b.name)) {
818
+ return false;
819
+ }
820
+ const keys1 = Object.keys(o1);
821
+ const keys2 = Object.keys(o2);
822
+ // istanbul ignore next
823
+ if (keys1.length !== keys2.length) {
824
+ return false;
825
+ }
826
+ for (const k of Object.keys(o1)) {
827
+ if (!__check_same_object(o1[k], o2[k])) {
828
+ return false;
829
+ }
830
+ }
831
+ return true;
832
+ }
833
+ case "[object Float32Array]":
834
+ case "[object Float64Array]":
835
+ case "[object Int32Array]":
836
+ case "[object Int16Array]":
837
+ case "[object Int8Array]":
838
+ case "[object Uint32Array]":
839
+ case "[object Uint16Array]":
840
+ case "[object Uint8Array]": {
841
+ const b1 = Buffer.from(o1.buffer, o1.byteOffset, o1.byteLength);
842
+ const b2 = Buffer.from(o2.buffer, o2.byteOffset, o2.byteLength);
843
+ return b1.equals(b2);
844
+ }
845
+ default:
846
+ return o1 === o2;
847
+ }
848
+ }
849
+ function __check_same_array(arr1, arr2) {
850
+ if (!arr1 || !arr2) {
851
+ return !arr1 && !arr2;
852
+ }
853
+ if (arr1.length !== arr2.length) {
854
+ return false;
855
+ }
856
+ if (arr1.length === 0 && 0 === arr2.length) {
857
+ return true;
858
+ }
859
+ if (!oldNodeVersion && arr1.buffer) {
860
+ // v1 and v2 are TypedArray (such as Int32Array...)
861
+ // this is the most efficient way to compare 2 buffers but it doesn't work with node <= 0.12
862
+ (0, node_opcua_assert_1.assert)(arr2.buffer && __type(arr2.buffer) === "[object ArrayBuffer]");
863
+ // compare byte by byte
864
+ const b1 = Buffer.from(arr1.buffer, arr1.byteOffset, arr1.byteLength);
865
+ const b2 = Buffer.from(arr2.buffer, arr2.byteOffset, arr2.byteLength);
866
+ return b1.equals(b2);
867
+ }
868
+ const n = arr1.length;
869
+ for (let i = 0; i < n; i++) {
870
+ if (!__check_same_object(arr1[i], arr2[i])) {
871
+ return false;
872
+ }
873
+ }
874
+ return true;
875
+ }
876
+ /***
877
+ * returns true if the two variant represent the same value
878
+ * @param v1 the first variant to compare
879
+ * @param v2 the variant to compare with
880
+ */
881
+ function sameVariant(v1, v2) {
882
+ if (v1 === v2) {
883
+ return true;
884
+ }
885
+ if ((!v1 && v2) || (v1 && !v2)) {
886
+ return false;
887
+ }
888
+ if (v1.arrayType !== v2.arrayType) {
889
+ return false;
890
+ }
891
+ if (v1.dataType !== v2.dataType) {
892
+ return false;
893
+ }
894
+ if (v1.value === v2.value) {
895
+ return true;
896
+ }
897
+ if (v1.arrayType === VariantArrayType_enum_1.VariantArrayType.Scalar) {
898
+ if (v1.dataType === DataType_enum_1.DataType.ExtensionObject) {
899
+ // compare two extension objects
900
+ return __check_same_object(v1.value, v2.value);
901
+ }
902
+ if (Array.isArray(v1.value) && Array.isArray(v2.value)) {
903
+ return __check_same_array(v1.value, v2.value);
904
+ }
905
+ if (Buffer.isBuffer(v1.value) && Buffer.isBuffer(v2.value)) {
906
+ return v1.value.equals(v2.value);
907
+ }
908
+ }
909
+ if (v1.arrayType === VariantArrayType_enum_1.VariantArrayType.Array) {
910
+ return __check_same_array(v1.value, v2.value);
911
+ }
912
+ else if (v1.arrayType === VariantArrayType_enum_1.VariantArrayType.Matrix) {
913
+ if (!__check_same_array(v1.dimensions, v2.dimensions)) {
914
+ return false;
915
+ }
916
+ return __check_same_array(v1.value, v2.value);
917
+ }
918
+ return false;
919
+ }
920
+ exports.sameVariant = sameVariant;
921
+ // ---------------------------------------------------------------------------------------------------------
922
+ (0, node_opcua_factory_1.registerSpecialVariantEncoder)(Variant);
923
+ (0, node_opcua_factory_1.registerType)({
924
+ name: "Variant",
925
+ subType: "",
926
+ coerce: _coerceVariant,
927
+ encode: encodeVariant,
928
+ decode: decodeVariant
929
+ });
930
930
  //# sourceMappingURL=variant.js.map