private Array DecodeArray <type>(IBinaryDecoder decoder, Func <type> readValue, bool arrayDimensionsPresents)
        {
            int length = decoder.ReadInt32();

            if (length < 0)
            {
                throw new ArgumentOutOfRangeException(nameof(length));
            }
            Array _ret;

            type[] values = new type[length];
            for (int ii = 0; ii < length; ii++)
            {
                values[ii] = readValue();
            }
            int[] _dimensions = null;
            if (arrayDimensionsPresents)
            {
                _dimensions = ReadDimensions(decoder);
                _ret        = Array.CreateInstance(typeof(type), _dimensions);
                CopyValues(_ret, values);
            }
            else
            {
                _ret = values;
            }
            return(_ret);
        }
        /// <summary>
        /// Reads the string od bytes from UA Binary encoded as a 16-element byte array that contains the value.
        /// </summary>
        /// <param name="decoder">The decoder <see cref="IBinaryDecoder" /> to be used to read form the stream.</param>
        /// <returns>The <see cref="System.Byte" /> array decoded from the UA binary stream of bytes.</returns>
        public byte[] ReadByteString(IBinaryDecoder decoder)
        {
            Int32 _length = decoder.ReadInt32();

            if (_length < 0)
            {
                return(null);
            }
            return(decoder.ReadBytes(_length));
        }
        private int[] ReadDimensions(IBinaryDecoder decoder)
        {
            int length = decoder.ReadInt32();

            if (length < 0)
            {
                return(null);
            }
            if (MaxArrayLength > 0 && MaxArrayLength < length)
            {
                throw new ArgumentOutOfRangeException(nameof(MaxArrayLength), $"Unsupported array length {length}");
            }
            List <Int32> values = new List <Int32>(length);

            for (int ii = 0; ii < length; ii++)
            {
                values.Add(decoder.ReadInt32());
            }
            return(values.ToArray());
        }
        /// <summary>
        /// Reads the <see cref="string" /> from UA binary encoded stream of bytes encoded as a sequence of UTF8 characters without a null terminator and preceded by the length in bytes.
        /// The length in bytes is encoded as Int32. A value of −1 is used to indicate a ‘null’ string.
        /// </summary>
        /// <param name="decoder">The decoder <see cref="IBinaryDecoder" /> to be used to read form the stream.</param>
        /// <returns>The <see cref="string" /> decoded from the UA binary stream of bytes.</returns>
        /// <exception cref="System.NotImplementedException"></exception>
        public string ReadString(IBinaryDecoder decoder)
        {
            int length = decoder.ReadInt32();

            if (length == -1)
            {
                return(null);
            }
            byte[] bytes = decoder.ReadBytes(length);
            return(new UTF8Encoding().GetString(bytes, 0, bytes.Length));
        }
        //methods
        private Variant ReadValue(IBinaryDecoder encoder, BuiltInType encodingByte)
        {
            switch (encodingByte)
            {
            case BuiltInType.Boolean:
                return(new Variant(encoder.ReadBoolean(), encodingByte));

            case BuiltInType.SByte:
                return(new Variant(encoder.ReadSByte(), encodingByte));

            case BuiltInType.Byte:
                return(new Variant(encoder.ReadByte(), encodingByte));

            case BuiltInType.Int16:
                return(new Variant(encoder.ReadInt16(), encodingByte));

            case BuiltInType.UInt16:
                return(new Variant(encoder.ReadUInt16(), encodingByte));

            case BuiltInType.Int32:
            case BuiltInType.Enumeration:
                return(new Variant(encoder.ReadInt32(), encodingByte));

            case BuiltInType.UInt32:
                return(new Variant(encoder.ReadUInt32(), encodingByte));

            case BuiltInType.Int64:
                return(new Variant(encoder.ReadInt64(), encodingByte));

            case BuiltInType.UInt64:
                return(new Variant(encoder.ReadUInt64(), encodingByte));

            case BuiltInType.Float:
                return(new Variant(encoder.ReadSingle(), encodingByte));

            case BuiltInType.Double:
                return(new Variant(encoder.ReadDouble(), encodingByte));

            case BuiltInType.String:
                return(new Variant(ReadString(encoder), encodingByte));

            case BuiltInType.DateTime:
                return(new Variant(ReadDateTime(encoder), encodingByte));

            case BuiltInType.Guid:
                return(new Variant(ReadGuid(encoder), encodingByte));

            case BuiltInType.ByteString:
                return(new Variant(ReadByteString(encoder), encodingByte));

            case BuiltInType.XmlElement:
                return(new Variant(ReadXmlElement(encoder), encodingByte));

            case BuiltInType.NodeId:
                return(new Variant(ReadNodeId(encoder), encodingByte));

            case BuiltInType.ExpandedNodeId:
                return(new Variant(ReadExpandedNodeId(encoder), encodingByte));

            case BuiltInType.StatusCode:
                return(new Variant(ReadStatusCode(encoder), encodingByte));

            case BuiltInType.QualifiedName:
                return(new Variant(ReadQualifiedName(encoder), encodingByte));

            case BuiltInType.LocalizedText:
                return(new Variant(ReadLocalizedText(encoder), encodingByte));

            case BuiltInType.ExtensionObject:
                return(new Variant(ReadExtensionObject(encoder), encodingByte));

            case BuiltInType.DataValue:
                return(new Variant(ReadDataValue(encoder), encodingByte));

            default:
                throw new ArgumentOutOfRangeException($"Cannot decode unknown type in Variant object (0x{encodingByte:X}).");
            }
        }