Esempio n. 1
0
        /// <summary>
        /// Receives the message.
        /// </summary>
        private static byte[] ReceiveMessage(Socket sock)
        {
            var buf = new byte[4];

            sock.Receive(buf);

            using (var stream = new BinaryHeapStream(buf))
            {
                var size = stream.ReadInt();
                buf = new byte[size];
                sock.Receive(buf);
                return(buf);
            }
        }
Esempio n. 2
0
        /// <summary>
        /// Receives the message.
        /// </summary>
        private static byte[] ReceiveMessage(Stream sock)
        {
            var buf  = new byte[4];
            var read = sock.Read(buf, 0, 4);

            Assert.AreEqual(4, read);

            using (var stream = new BinaryHeapStream(buf))
            {
                var size = stream.ReadInt();
                buf = new byte[size];
                sock.Read(buf, 0, size);
                return(buf);
            }
        }
Esempio n. 3
0
        /// <summary>
        /// Decodes the response that we got from <see cref="HandleResponse"/>.
        /// </summary>
        private static T DecodeResponse <T>(BinaryHeapStream stream, Func <IBinaryStream, T> readFunc,
                                            Func <ClientStatusCode, string, T> errorFunc)
        {
            var statusCode = (ClientStatusCode)stream.ReadInt();

            if (statusCode == ClientStatusCode.Success)
            {
                return(readFunc != null?readFunc(stream) : default(T));
            }

            var msg = BinaryUtils.Marshaller.StartUnmarshal(stream).ReadString();

            if (errorFunc != null)
            {
                return(errorFunc(statusCode, msg));
            }

            throw new IgniteClientException(msg, null, statusCode);
        }
Esempio n. 4
0
        /// <summary>
        /// Performs a send-receive operation.
        /// </summary>
        public T DoOutInOp <T>(ClientOp opId, Action <IBinaryStream> writeAction,
                               Func <IBinaryStream, T> readFunc, Func <ClientStatus, string, T> errorFunc = null)
        {
            var requestId = Interlocked.Increment(ref _requestId);

            var resBytes = SendReceive(_socket, stream =>
            {
                stream.WriteShort((short)opId);
                stream.WriteLong(requestId);

                if (writeAction != null)
                {
                    writeAction(stream);
                }
            });

            using (var stream = new BinaryHeapStream(resBytes))
            {
                var resRequestId = stream.ReadLong();
                Debug.Assert(requestId == resRequestId);

                var statusCode = (ClientStatus)stream.ReadInt();

                if (statusCode == ClientStatus.Success)
                {
                    return(readFunc != null?readFunc(stream) : default(T));
                }

                var msg = BinaryUtils.Marshaller.StartUnmarshal(stream).ReadString();

                if (errorFunc != null)
                {
                    return(errorFunc(statusCode, msg));
                }

                throw new IgniteClientException(msg, null, (int)statusCode);
            }
        }
Esempio n. 5
0
        /// <summary>
        /// Performs client protocol handshake.
        /// </summary>
        private void Handshake(IgniteClientConfiguration clientConfiguration, ClientProtocolVersion version)
        {
            bool auth = version.CompareTo(Ver110) >= 0 && clientConfiguration.UserName != null;

            // Send request.
            int messageLen;
            var buf = WriteMessage(stream =>
            {
                // Handshake.
                stream.WriteByte(OpHandshake);

                // Protocol version.
                stream.WriteShort(version.Major);
                stream.WriteShort(version.Minor);
                stream.WriteShort(version.Maintenance);

                // Client type: platform.
                stream.WriteByte(ClientType);

                // Authentication data.
                if (auth)
                {
                    var writer = BinaryUtils.Marshaller.StartMarshal(stream);

                    writer.WriteString(clientConfiguration.UserName);
                    writer.WriteString(clientConfiguration.Password);

                    BinaryUtils.Marshaller.FinishMarshal(writer);
                }
            }, 12, out messageLen);

            SocketWrite(buf, messageLen);

            // Decode response.
            var res = ReceiveMessage();

            using (var stream = new BinaryHeapStream(res))
            {
                // Read input.
                var success = stream.ReadBool();

                if (success)
                {
                    if (version.CompareTo(Ver140) >= 0)
                    {
                        ServerNodeId = BinaryUtils.Marshaller.Unmarshal <Guid>(stream);
                    }

                    ServerVersion = version;

                    return;
                }

                ServerVersion =
                    new ClientProtocolVersion(stream.ReadShort(), stream.ReadShort(), stream.ReadShort());

                var errMsg = BinaryUtils.Marshaller.Unmarshal <string>(stream);

                ClientStatusCode errCode = ClientStatusCode.Fail;

                if (stream.Remaining > 0)
                {
                    errCode = (ClientStatusCode)stream.ReadInt();
                }

                // Authentication error is handled immediately.
                if (errCode == ClientStatusCode.AuthenticationFailed)
                {
                    throw new IgniteClientException(errMsg, null, ClientStatusCode.AuthenticationFailed);
                }

                // Re-try if possible.
                bool retry = ServerVersion.CompareTo(version) < 0 && ServerVersion.Equals(Ver100);

                if (retry)
                {
                    Handshake(clientConfiguration, ServerVersion);
                }
                else
                {
                    throw new IgniteClientException(string.Format(
                                                        "Client handshake failed: '{0}'. Client version: {1}. Server version: {2}",
                                                        errMsg, version, ServerVersion), null, errCode);
                }
            }
        }
Esempio n. 6
0
        /// <summary>
        /// Write object as a predefined type if possible.
        /// </summary>
        /// <param name="hdr">Header.</param>
        /// <param name="inStream">Input stream.</param>
        /// <param name="outStream">Output stream.</param>
        /// <param name="ctx">Context.</param>
        /// <returns><c>True</c> if was written.</returns>
        private bool WriteAsPredefined(byte hdr, BinaryHeapStream inStream, IBinaryStream outStream,
                                       Context ctx)
        {
            switch (hdr)
            {
            case BinaryTypeId.Byte:
                TransferBytes(inStream, outStream, 1);

                break;

            case BinaryTypeId.Short:
                TransferBytes(inStream, outStream, 2);

                break;

            case BinaryTypeId.Int:
                TransferBytes(inStream, outStream, 4);

                break;

            case BinaryTypeId.Long:
                TransferBytes(inStream, outStream, 8);

                break;

            case BinaryTypeId.Float:
                TransferBytes(inStream, outStream, 4);

                break;

            case BinaryTypeId.Double:
                TransferBytes(inStream, outStream, 8);

                break;

            case BinaryTypeId.Char:
                TransferBytes(inStream, outStream, 2);

                break;

            case BinaryTypeId.Bool:
                TransferBytes(inStream, outStream, 1);

                break;

            case BinaryTypeId.Decimal:
                TransferBytes(inStream, outStream, 4); // Transfer scale

                int magLen = inStream.ReadInt();       // Transfer magnitude length.

                outStream.WriteInt(magLen);

                TransferBytes(inStream, outStream, magLen);     // Transfer magnitude.

                break;

            case BinaryTypeId.String:
                BinaryUtils.WriteString(BinaryUtils.ReadString(inStream), outStream);

                break;

            case BinaryTypeId.Guid:
                TransferBytes(inStream, outStream, 16);

                break;

            case BinaryTypeId.Timestamp:
                TransferBytes(inStream, outStream, 12);

                break;

            case BinaryTypeId.ArrayByte:
                TransferArray(inStream, outStream, 1);

                break;

            case BinaryTypeId.ArrayShort:
                TransferArray(inStream, outStream, 2);

                break;

            case BinaryTypeId.ArrayInt:
                TransferArray(inStream, outStream, 4);

                break;

            case BinaryTypeId.ArrayLong:
                TransferArray(inStream, outStream, 8);

                break;

            case BinaryTypeId.ArrayFloat:
                TransferArray(inStream, outStream, 4);

                break;

            case BinaryTypeId.ArrayDouble:
                TransferArray(inStream, outStream, 8);

                break;

            case BinaryTypeId.ArrayChar:
                TransferArray(inStream, outStream, 2);

                break;

            case BinaryTypeId.ArrayBool:
                TransferArray(inStream, outStream, 1);

                break;

            case BinaryTypeId.ArrayDecimal:
            case BinaryTypeId.ArrayString:
            case BinaryTypeId.ArrayGuid:
            case BinaryTypeId.ArrayTimestamp:
                int arrLen = inStream.ReadInt();

                outStream.WriteInt(arrLen);

                for (int i = 0; i < arrLen; i++)
                {
                    Mutate0(ctx, inStream, outStream, false, null);
                }

                break;

            case BinaryTypeId.ArrayEnum:
            case BinaryTypeId.Array:
                int type = inStream.ReadInt();

                outStream.WriteInt(type);

                if (type == BinaryTypeId.Unregistered)
                {
                    outStream.WriteByte(inStream.ReadByte());                             // String header.

                    BinaryUtils.WriteString(BinaryUtils.ReadString(inStream), outStream); // String data.
                }

                arrLen = inStream.ReadInt();

                outStream.WriteInt(arrLen);

                for (int i = 0; i < arrLen; i++)
                {
                    Mutate0(ctx, inStream, outStream, false, EmptyVals);
                }

                break;

            case BinaryTypeId.Collection:
                int colLen = inStream.ReadInt();

                outStream.WriteInt(colLen);

                outStream.WriteByte(inStream.ReadByte());

                for (int i = 0; i < colLen; i++)
                {
                    Mutate0(ctx, inStream, outStream, false, EmptyVals);
                }

                break;

            case BinaryTypeId.Dictionary:
                int dictLen = inStream.ReadInt();

                outStream.WriteInt(dictLen);

                outStream.WriteByte(inStream.ReadByte());

                for (int i = 0; i < dictLen; i++)
                {
                    Mutate0(ctx, inStream, outStream, false, EmptyVals);
                    Mutate0(ctx, inStream, outStream, false, EmptyVals);
                }

                break;

            case BinaryTypeId.Binary:
                TransferArray(inStream, outStream, 1);     // Data array.
                TransferBytes(inStream, outStream, 4);     // Offset in array.

                break;

            case BinaryTypeId.Enum:
                TransferBytes(inStream, outStream, 8);     // int typeId, int value.

                break;

            default:
                return(false);
            }

            return(true);
        }
Esempio n. 7
0
        /// <summary>
        /// Internal mutation routine.
        /// </summary>
        /// <param name="inStream">Input stream.</param>
        /// <param name="outStream">Output stream.</param>
        /// <param name="ctx">Context.</param>
        /// <param name="changeHash">WHether hash should be changed.</param>
        /// <param name="vals">Values to be replaced.</param>
        /// <returns>Mutated object.</returns>
        private void Mutate0(Context ctx, BinaryHeapStream inStream, IBinaryStream outStream,
                             bool changeHash, IDictionary <int, BinaryBuilderField> vals)
        {
            int inStartPos  = inStream.Position;
            int outStartPos = outStream.Position;

            byte inHdr = inStream.ReadByte();

            if (inHdr == BinaryUtils.HdrNull)
            {
                outStream.WriteByte(BinaryUtils.HdrNull);
            }
            else if (inHdr == BinaryUtils.HdrHnd)
            {
                int inHnd = inStream.ReadInt();

                int oldPos = inStartPos - inHnd;
                int newPos;

                if (ctx.OldToNew(oldPos, out newPos))
                {
                    // Handle is still valid.
                    outStream.WriteByte(BinaryUtils.HdrHnd);
                    outStream.WriteInt(outStartPos - newPos);
                }
                else
                {
                    // Handle is invalid, write full object.
                    int inRetPos = inStream.Position;

                    inStream.Seek(oldPos, SeekOrigin.Begin);

                    Mutate0(ctx, inStream, outStream, false, EmptyVals);

                    inStream.Seek(inRetPos, SeekOrigin.Begin);
                }
            }
            else if (inHdr == BinaryUtils.HdrFull)
            {
                var inHeader = BinaryObjectHeader.Read(inStream, inStartPos);

                BinaryUtils.ValidateProtocolVersion(inHeader.Version);

                int hndPos;

                if (ctx.AddOldToNew(inStartPos, outStartPos, out hndPos))
                {
                    // Object could be cached in parent builder.
                    BinaryBuilderField cachedVal;

                    if (_parent._cache != null && _parent._cache.TryGetValue(inStartPos, out cachedVal))
                    {
                        WriteField(ctx, cachedVal);
                    }
                    else
                    {
                        // New object, write in full form.
                        var inSchema = BinaryObjectSchemaSerializer.ReadSchema(inStream, inStartPos, inHeader,
                                                                               _desc.Schema, _binary.Marshaller.Ignite);

                        var outSchema = BinaryObjectSchemaHolder.Current;
                        var schemaIdx = outSchema.PushSchema();

                        try
                        {
                            // Skip header as it is not known at this point.
                            outStream.Seek(BinaryObjectHeader.Size, SeekOrigin.Current);

                            if (inSchema != null)
                            {
                                foreach (var inField in inSchema)
                                {
                                    BinaryBuilderField fieldVal;

                                    var fieldFound = vals.TryGetValue(inField.Id, out fieldVal);

                                    if (fieldFound && fieldVal == BinaryBuilderField.RmvMarker)
                                    {
                                        continue;
                                    }

                                    outSchema.PushField(inField.Id, outStream.Position - outStartPos);

                                    if (!fieldFound)
                                    {
                                        fieldFound = _parent._cache != null &&
                                                     _parent._cache.TryGetValue(inField.Offset + inStartPos,
                                                                                out fieldVal);
                                    }

                                    if (fieldFound)
                                    {
                                        WriteField(ctx, fieldVal);

                                        vals.Remove(inField.Id);
                                    }
                                    else
                                    {
                                        // Field is not tracked, re-write as is.
                                        inStream.Seek(inField.Offset + inStartPos, SeekOrigin.Begin);

                                        Mutate0(ctx, inStream, outStream, false, EmptyVals);
                                    }
                                }
                            }

                            // Write remaining new fields.
                            foreach (var valEntry in vals)
                            {
                                if (valEntry.Value == BinaryBuilderField.RmvMarker)
                                {
                                    continue;
                                }

                                outSchema.PushField(valEntry.Key, outStream.Position - outStartPos);

                                WriteField(ctx, valEntry.Value);
                            }

                            var flags = inHeader.IsUserType
                                ? BinaryObjectHeader.Flag.UserType
                                : BinaryObjectHeader.Flag.None;

                            if (inHeader.IsCustomDotNetType)
                            {
                                flags |= BinaryObjectHeader.Flag.CustomDotNetType;
                            }

                            // Write raw data.
                            int outRawOff = outStream.Position - outStartPos;

                            if (inHeader.HasRaw)
                            {
                                var inRawOff = inHeader.GetRawOffset(inStream, inStartPos);
                                var inRawLen = inHeader.SchemaOffset - inRawOff;

                                flags |= BinaryObjectHeader.Flag.HasRaw;

                                outStream.Write(inStream.InternalArray, inStartPos + inRawOff, inRawLen);
                            }

                            // Write schema
                            int outSchemaOff = outRawOff;
                            var schemaPos    = outStream.Position;
                            int outSchemaId;

                            if (inHeader.IsCompactFooter)
                            {
                                flags |= BinaryObjectHeader.Flag.CompactFooter;
                            }

                            var hasSchema = outSchema.WriteSchema(outStream, schemaIdx, out outSchemaId, ref flags);

                            if (hasSchema)
                            {
                                outSchemaOff = schemaPos - outStartPos;

                                flags |= BinaryObjectHeader.Flag.HasSchema;

                                if (inHeader.HasRaw)
                                {
                                    outStream.WriteInt(outRawOff);
                                }

                                if (_desc.Schema.Get(outSchemaId) == null)
                                {
                                    _desc.Schema.Add(outSchemaId, outSchema.GetSchema(schemaIdx));
                                }
                            }

                            var outLen = outStream.Position - outStartPos;

                            var outHash = inHeader.HashCode;

                            if (changeHash)
                            {
                                // Get from identity resolver.
                                outHash = BinaryArrayEqualityComparer.GetHashCode(outStream,
                                                                                  outStartPos + BinaryObjectHeader.Size,
                                                                                  schemaPos - outStartPos - BinaryObjectHeader.Size);
                            }

                            var outHeader = new BinaryObjectHeader(inHeader.TypeId, outHash, outLen,
                                                                   outSchemaId, outSchemaOff, flags);

                            BinaryObjectHeader.Write(outHeader, outStream, outStartPos);

                            outStream.Seek(outStartPos + outLen, SeekOrigin.Begin);  // seek to the end of the object
                        }
                        finally
                        {
                            outSchema.PopSchema(schemaIdx);
                        }
                    }
                }
                else
                {
                    // Object has already been written, write as handle.
                    outStream.WriteByte(BinaryUtils.HdrHnd);
                    outStream.WriteInt(outStartPos - hndPos);
                }

                // Synchronize input stream position.
                inStream.Seek(inStartPos + inHeader.Length, SeekOrigin.Begin);
            }
            else
            {
                // Try writing as well-known type with fixed size.
                outStream.WriteByte(inHdr);

                if (!WriteAsPredefined(inHdr, inStream, outStream, ctx))
                {
                    throw new IgniteException("Unexpected header [position=" + (inStream.Position - 1) +
                                              ", header=" + inHdr + ']');
                }
            }
        }
Esempio n. 8
0
        /// <summary>
        /// Performs client protocol handshake.
        /// </summary>
        private ClientFeatures Handshake(IgniteClientConfiguration clientConfiguration, ClientProtocolVersion version)
        {
            var hasAuth     = version >= Ver110 && clientConfiguration.UserName != null;
            var hasFeatures = version >= Ver170;

            // Send request.
            int messageLen;
            var buf = WriteMessage(stream =>
            {
                // Handshake.
                stream.WriteByte(OpHandshake);

                // Protocol version.
                stream.WriteShort(version.Major);
                stream.WriteShort(version.Minor);
                stream.WriteShort(version.Maintenance);

                // Client type: platform.
                stream.WriteByte(ClientType);

                // Writing features.
                if (hasFeatures)
                {
                    BinaryUtils.Marshaller.Marshal(stream,
                                                   w => w.WriteByteArray(ClientFeatures.AllFeatures));
                }

                // Authentication data.
                if (hasAuth)
                {
                    BinaryUtils.Marshaller.Marshal(stream, writer =>
                    {
                        writer.WriteString(clientConfiguration.UserName);
                        writer.WriteString(clientConfiguration.Password);
                    });
                }
            }, 12, out messageLen);

            SocketWrite(buf, messageLen);

            // Decode response.
            var res = ReceiveMessage();

            using (var stream = new BinaryHeapStream(res))
            {
                // Read input.
                var success = stream.ReadBool();

                if (success)
                {
                    BitArray featureBits = null;

                    if (hasFeatures)
                    {
                        featureBits = new BitArray(BinaryUtils.Marshaller.Unmarshal <byte[]>(stream));
                    }

                    if (version >= Ver140)
                    {
                        ServerNodeId = BinaryUtils.Marshaller.Unmarshal <Guid>(stream);
                    }

                    ServerVersion = version;

                    _logger.Debug("Handshake completed on {0}, protocol version = {1}",
                                  _socket.RemoteEndPoint, version);

                    return(new ClientFeatures(version, featureBits));
                }

                ServerVersion =
                    new ClientProtocolVersion(stream.ReadShort(), stream.ReadShort(), stream.ReadShort());

                var errMsg = BinaryUtils.Marshaller.Unmarshal <string>(stream);

                ClientStatusCode errCode = ClientStatusCode.Fail;

                if (stream.Remaining > 0)
                {
                    errCode = (ClientStatusCode)stream.ReadInt();
                }

                _logger.Debug("Handshake failed on {0}, requested protocol version = {1}, " +
                              "server protocol version = {2}, status = {3}, message = {4}",
                              _socket.RemoteEndPoint, version, ServerVersion, errCode, errMsg);

                // Authentication error is handled immediately.
                if (errCode == ClientStatusCode.AuthenticationFailed)
                {
                    throw new IgniteClientException(errMsg, null, ClientStatusCode.AuthenticationFailed);
                }

                // Retry if server version is different and falls within supported version range.
                var retry = ServerVersion != version &&
                            ServerVersion >= Ver100 &&
                            ServerVersion <= CurrentProtocolVersion;

                if (retry)
                {
                    _logger.Debug("Retrying handshake on {0} with protocol version {1}",
                                  _socket.RemoteEndPoint, ServerVersion);

                    return(Handshake(clientConfiguration, ServerVersion));
                }

                throw new IgniteClientException(string.Format(
                                                    "Client handshake failed: '{0}'. Client version: {1}. Server version: {2}",
                                                    errMsg, version, ServerVersion), null, errCode);
            }
        }
Esempio n. 9
0
        /// <summary>
        /// Write object as a predefined type if possible.
        /// </summary>
        /// <param name="hdr">Header.</param>
        /// <param name="inStream">Input stream.</param>
        /// <param name="outStream">Output stream.</param>
        /// <param name="ctx">Context.</param>
        /// <returns><c>True</c> if was written.</returns>
        private bool WriteAsPredefined(byte hdr, BinaryHeapStream inStream, IBinaryStream outStream,
                                       Context ctx)
        {
            switch (hdr)
            {
            case BinaryUtils.TypeByte:
                TransferBytes(inStream, outStream, 1);

                break;

            case BinaryUtils.TypeShort:
                TransferBytes(inStream, outStream, 2);

                break;

            case BinaryUtils.TypeInt:
                TransferBytes(inStream, outStream, 4);

                break;

            case BinaryUtils.TypeLong:
                TransferBytes(inStream, outStream, 8);

                break;

            case BinaryUtils.TypeFloat:
                TransferBytes(inStream, outStream, 4);

                break;

            case BinaryUtils.TypeDouble:
                TransferBytes(inStream, outStream, 8);

                break;

            case BinaryUtils.TypeChar:
                TransferBytes(inStream, outStream, 2);

                break;

            case BinaryUtils.TypeBool:
                TransferBytes(inStream, outStream, 1);

                break;

            case BinaryUtils.TypeDecimal:
                TransferBytes(inStream, outStream, 4); // Transfer scale

                int magLen = inStream.ReadInt();       // Transfer magnitude length.

                outStream.WriteInt(magLen);

                TransferBytes(inStream, outStream, magLen);     // Transfer magnitude.

                break;

            case BinaryUtils.TypeString:
                BinaryUtils.WriteString(BinaryUtils.ReadString(inStream), outStream);

                break;

            case BinaryUtils.TypeGuid:
                TransferBytes(inStream, outStream, 16);

                break;

            case BinaryUtils.TypeTimestamp:
                TransferBytes(inStream, outStream, 12);

                break;

            case BinaryUtils.TypeArrayByte:
                TransferArray(inStream, outStream, 1);

                break;

            case BinaryUtils.TypeArrayShort:
                TransferArray(inStream, outStream, 2);

                break;

            case BinaryUtils.TypeArrayInt:
                TransferArray(inStream, outStream, 4);

                break;

            case BinaryUtils.TypeArrayLong:
                TransferArray(inStream, outStream, 8);

                break;

            case BinaryUtils.TypeArrayFloat:
                TransferArray(inStream, outStream, 4);

                break;

            case BinaryUtils.TypeArrayDouble:
                TransferArray(inStream, outStream, 8);

                break;

            case BinaryUtils.TypeArrayChar:
                TransferArray(inStream, outStream, 2);

                break;

            case BinaryUtils.TypeArrayBool:
                TransferArray(inStream, outStream, 1);

                break;

            case BinaryUtils.TypeArrayDecimal:
            case BinaryUtils.TypeArrayString:
            case BinaryUtils.TypeArrayGuid:
            case BinaryUtils.TypeArrayTimestamp:
            case BinaryUtils.TypeArrayEnum:
            case BinaryUtils.TypeArray:
                int arrLen = inStream.ReadInt();

                outStream.WriteInt(arrLen);

                for (int i = 0; i < arrLen; i++)
                {
                    Mutate0(ctx, inStream, outStream, false, 0, null);
                }

                break;

            case BinaryUtils.TypeCollection:
                int colLen = inStream.ReadInt();

                outStream.WriteInt(colLen);

                outStream.WriteByte(inStream.ReadByte());

                for (int i = 0; i < colLen; i++)
                {
                    Mutate0(ctx, inStream, outStream, false, 0, EmptyVals);
                }

                break;

            case BinaryUtils.TypeDictionary:
                int dictLen = inStream.ReadInt();

                outStream.WriteInt(dictLen);

                outStream.WriteByte(inStream.ReadByte());

                for (int i = 0; i < dictLen; i++)
                {
                    Mutate0(ctx, inStream, outStream, false, 0, EmptyVals);
                    Mutate0(ctx, inStream, outStream, false, 0, EmptyVals);
                }

                break;

            case BinaryUtils.TypeMapEntry:
                Mutate0(ctx, inStream, outStream, false, 0, EmptyVals);
                Mutate0(ctx, inStream, outStream, false, 0, EmptyVals);

                break;

            case BinaryUtils.TypeBinary:
                TransferArray(inStream, outStream, 1);     // Data array.
                TransferBytes(inStream, outStream, 4);     // Offset in array.

                break;

            case BinaryUtils.TypeEnum:
                TransferBytes(inStream, outStream, 4);     // Integer ordinal.

                break;

            default:
                return(false);
            }

            return(true);
        }