/// <inheritdoc />
        public async Task <TTypeToDeserializeTo> DeserializeAsync <TTypeToDeserializeTo>(IBytesReadable bytesReadable, CancellationToken token)
        {
            //TODO: Implement no prefixing support
            if (PrefixStyle == PrefixStyle.None)
            {
                throw new NotSupportedException("Protobuf-Net deserialization without length prefixing is not yet supported.");
            }

            //To do the async read operation with Protobuf-Net we need to do some manual buffering
            int prefixSize = checked ((int)await ReadLongLengthPrefix(bytesReadable, PrefixStyle, token).ConfigureAwait(false));

            //TODO: Reduce allocations somehow
            byte[] bytes = new byte[prefixSize];

            int count = await bytesReadable.ReadAsync(bytes, 0, prefixSize, token)
                        .ConfigureAwait(false);

            //0 means that the socket disconnected
            if (count == 0)
            {
                return(default(TTypeToDeserializeTo));
            }

            return(Serializer.Deserialize <TTypeToDeserializeTo>(new MemoryStream(bytes)));
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Reads <see cref="count"/> many bytes from the reader.
        /// </summary>
        /// <param name="readable"></param>
        /// <param name="count">How many bytes to read.</param>
        /// <returns>The read bytes.</returns>
        public static byte[] Read(this IBytesReadable readable, int count)
        {
            if (readable == null)
            {
                throw new ArgumentNullException(nameof(readable));
            }

            return(readable.ReadAsync(count, 0).WaitAndUnwrapException());
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Reads asyncronously <see cref="count"/> many bytes from the reader.
        /// </summary>
        /// <param name="buffer">The buffer to store the bytes into.</param>
        /// <param name="start">The start position in the buffer to start reading into.</param>
        /// <param name="count">How many bytes to read.</param>
        /// <param name="timeoutInMilliseconds">How many milliseconds to wait before canceling the operation.</param>
        /// <returns>A future for the read bytes.</returns>
        public static Task <int> ReadAsync(this IBytesReadable readable, byte[] buffer, int start, int count, int timeoutInMilliseconds)
        {
            if (readable == null)
            {
                throw new ArgumentNullException(nameof(readable));
            }

            //TODO: DO we need to check the timeout?
            return(readable.ReadAsync(buffer, 0, count, timeoutInMilliseconds > 0 ? new CancellationTokenSource(timeoutInMilliseconds).Token : CancellationToken.None));
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Reads asyncronously <see cref="count"/> many bytes from the reader.
        /// </summary>
        /// <param name="readable"></param>
        /// <param name="count">How many bytes to read.</param>
        /// <param name="timeoutInMilliseconds">How many milliseconds to wait before canceling the operation.</param>
        /// <returns>A future for the read bytes.</returns>
        public static async Task <byte[]> ReadAsync(this IBytesReadable readable, int count, int timeoutInMilliseconds)
        {
            if (readable == null)
            {
                throw new ArgumentNullException(nameof(readable));
            }

            byte[] bytes = new byte[count];

            int resultCount = await readable.ReadAsync(bytes, 0, count, timeoutInMilliseconds)
                              .ConfigureAwait(false);

            if (resultCount != count)
            {
                throw new InvalidOperationException($"Failed to read {count} many bytes form {nameof(IBytesReadable)}. Read {resultCount} many bytes.");
            }

            return(bytes);
        }
        //TODO: Doc
        /// <summary>
        /// Asyncly reads a byte chunk from the <see cref="bytesReadable"/>
        /// or throws if unable.
        /// </summary>
        /// <param name="bytesReadable"></param>
        /// <param name="style"></param>
        /// <param name="token"></param>
        /// <returns></returns>
        private static async Task <byte[]> ReadFixed4Byte(IBytesReadable bytesReadable, PrefixStyle style, CancellationToken token)
        {
            byte[] bytes = new byte[4];
            int    count = await bytesReadable.ReadAsync(bytes, 0, 4, token)
                           .ConfigureAwait(false);

            //0 means the socket disconnected
            if (count == 0)
            {
                return(null);
            }

            if (count < 4)
            {
                throw new InvalidOperationException($"Protobuf-Net could not read length prefix: {style}");
            }

            return(bytes);
        }
        /// <returns>The number of bytes consumed; 0 if no data available</returns>
        private static async Task <ulong> TryReadUInt64Variant(IBytesReadable bytesReadable, CancellationToken token)
        {
            //TODO: Reuse-share buffer to reduce allocations
            byte[] tempBuffer = new byte[9];

            ulong value = 0;
            int   count = await bytesReadable.ReadAsync(tempBuffer, 0, 1, token)
                          .ConfigureAwait(false);

            //0 means that the socket disconnected
            if (count == 0)
            {
                return(0);
            }

            int b = tempBuffer[0];

            if (b < 0)
            {
                return(0);
            }

            value = (uint)b;

            if ((value & 0x80) == 0)
            {
                return(1);
            }

            value &= 0x7F;

            int bytesRead = 1, shift = 7;

            while (bytesRead < 9)
            {
                count = await bytesReadable.ReadAsync(tempBuffer, bytesRead, 1, token)
                        .ConfigureAwait(false);

                //0 means the underlying socket disconnected
                if (count == 0)
                {
                    return(0);
                }

                b = tempBuffer[bytesRead];

                if (b < 0)
                {
                    throw EoF(null);
                }

                value |= ((ulong)b & 0x7F) << shift;
                shift += 7;

                if ((b & 0x80) == 0)
                {
                    return(value);
                }

                bytesRead++;
            }

            count = await bytesReadable.ReadAsync(tempBuffer, bytesRead, 1, token)
                    .ConfigureAwait(false);

            if (count == 0)
            {
                return(0);
            }

            b = tempBuffer[bytesRead];

            if (b < 0)
            {
                throw EoF(null);
            }

            if ((b & 1) == 0)            // only use 1 bit from the last byte
            {
                value |= ((ulong)b & 0x7F) << shift;
            }

            return(value);
        }