Exemple #1
0
 /// <summary>
 /// Method to read a fixed-size buffer from the <see cref="Stream"/>. The read must return all bytes
 /// in the buffer's length; or else the <see cref="IoResult.Result"/> is
 /// <see cref="IoResultState.BadData"/>. Note that this method catches all exceptions and will
 /// <see cref="IoResult.Fault"/> the result. The read operation updates the
 /// <see cref="IoResult.BytesReadOrWritten"/> property: if there is an incoming value, it is incremented.
 /// </summary>
 /// <param name="ioResult">Not null.</param>
 /// <param name="sourceStream">Not null.</param>
 /// <param name="fixedBuffer">Not null.</param>
 /// <returns>Completes when the read completes.</returns>
 /// <exception cref="ArgumentNullException"></exception>
 public static Task <IoResult> ReadAllAsync(this IoResult ioResult, Stream sourceStream, byte[] fixedBuffer)
 {
     if (ioResult == null)
     {
         throw new ArgumentNullException(nameof(ioResult));
     }
     return(IoHelper.ReadAllAsync(sourceStream, fixedBuffer, ioResult));
 }
Exemple #2
0
 /// <summary>
 /// Note: this method only changes the state if this is currently
 /// <see cref="IoResultState.Success"/>. This method will
 /// set this <see cref="Result"/> and <see cref="Error"/>
 /// from the given <paramref name="other"/> result; yet,
 /// if the <paramref name="other"/> <see cref="Error"/> is null,
 /// any currently-set error here will remain.
 /// </summary>
 /// <param name="other">Not null.</param>
 /// <returns>This instance for chaining.</returns>
 public IoResult SetResultFrom(IoResult other)
 {
     if (other == null)
     {
         throw new ArgumentNullException(nameof(other));
     }
     return(setResult(other.Result, other.Error));
 }
Exemple #3
0
 /// <summary>
 /// Method to read a fixed-size buffer from the <see cref="Stream"/>. The read must return all bytes
 /// in the buffer's length; or else the <see cref="IoResult.Result"/> is
 /// <see cref="IoResultState.BadData"/>. Note that this method catches all exceptions and will
 /// <see cref="IoResult.Fault"/> the result. The read operation updates the
 /// <see cref="IoResult.BytesReadOrWritten"/> property: if there is an incoming value, it is incremented.
 /// </summary>
 /// <param name="sourceStream">Not null.</param>
 /// <param name="fixedBuffer">Not null.</param>
 /// <param name="ioResult">Optional. If null, a new instance is created; with any given
 /// <see cref="CancellationToken"/>.</param>
 /// <param name="cancellationToken">Optional.</param>
 /// <returns>Not null. If you provided an argument, the same object is returned.</returns>
 /// <exception cref="ArgumentNullException"></exception>
 public static async Task <IoResult> ReadAllAsync(
     Stream sourceStream,
     byte[] fixedBuffer,
     IoResult ioResult = null,
     CancellationToken cancellationToken = default)
 => await IoHelper.ReadAllAsync(
     sourceStream,
     fixedBuffer,
     0,
     fixedBuffer.Length,
     ioResult,
     cancellationToken);
Exemple #4
0
        /// <summary>
        /// NOTICE: this method ALWAYS updates the <see cref="IoResult.BytesReadOrWritten"/> property by the given
        /// length if the stream does not support seeking. This writes from a buffer to the sink <see cref="Stream"/>.
        /// The write may write any length. Note that this method catches all exceptions and will
        /// <see cref="IoResult.Fault"/> the result. IF the stream supports seeking, this method updates the
        /// <see cref="IoResult.BytesReadOrWritten"/> property based on the change in the stream's Position. Otherwise
        /// the value is always explicitly updated by the given length: you must test the stream to know. If there is
        /// an incoming value, it is incremented.
        /// </summary>
        /// <param name="sinkStream">Not null.</param>
        /// <param name="buffer">Not null.</param>
        /// <param name="offset">Offset within <c>buffer</c> to begin writing.</param>
        /// <param name="length">Length within <c>buffer</c> to write.</param>
        /// <param name="ioResult">Optional. If null, a new instance is created; with any given
        /// <see cref="CancellationToken"/>.</param>
        /// <param name="cancellationToken">Optional.</param>
        /// <returns>Not null. If you provided an argument, the same object is returned.</returns>
        /// <exception cref="ArgumentNullException"></exception>
        /// <exception cref="ArgumentOutOfRangeException"></exception>
        public static async Task <IoResult> WriteAsync(
            Stream sinkStream,
            byte[] buffer,
            int offset,
            int length,
            IoResult ioResult = null,
            CancellationToken cancellationToken = default)
        {
            if (sinkStream == null)
            {
                throw new ArgumentNullException(nameof(sinkStream));
            }
            if (buffer == null)
            {
                throw new ArgumentNullException(nameof(buffer));
            }
            if ((offset < 0) ||
                (offset >= buffer.Length))
            {
                throw new ArgumentOutOfRangeException(nameof(offset));
            }
            if ((length < 0) ||
                (length > (buffer.Length - offset)))
            {
                throw new ArgumentOutOfRangeException(nameof(length));
            }
            if (ioResult == null)
            {
                ioResult = new IoResult(cancellationToken);
            }
            else if (!ioResult.IsSuccess)
            {
                return(ioResult);
            }
            try {
                long position = sinkStream.CanSeek
                                                ? sinkStream.Position
                                                : 0L;
                await sinkStream.WriteAsync(
                    buffer,
                    offset,
                    length,
                    ioResult.CancellationToken);

                long bytesWritten = sinkStream.CanSeek
                                                ? Math.Max(0L, sinkStream.Position - position)
                                                : length;
                ioResult.AddBytesReadOrWritten(bytesWritten);
            } catch (Exception exception) {
                ioResult.Fault(exception);
            }
            return(ioResult);
        }
Exemple #5
0
 /// <summary>
 /// Method to read from the source <see cref="Stream"/> and write to the sink. NOTICE: this method
 /// will ONLY update the <see cref="IoResult.BytesReadOrWritten"/> property if one of the given
 /// streams supports seeking. You must test <see cref="Stream.CanSeek"/> to know. Notice also that
 /// <see cref="IoResult.BytesReadOrWritten"/> may be 0 when the <see cref="IoResult.Result"/>
 /// is <see cref="IoResultState.Success"/>.
 /// </summary>
 /// <param name="ioResult">Not null.</param>
 /// <param name="sourceStream">Not null.</param>
 /// <param name="sinkStream">Not null.</param>
 /// <param name="bufferSize">Required.</param>
 /// <returns>Completes when the copy is coplete.</returns>
 /// <exception cref="ArgumentNullException"></exception>
 /// <exception cref="ArgumentOutOfRangeException"></exception>
 public static Task <IoResult> CopyToAsync(
     this IoResult ioResult,
     Stream sourceStream,
     Stream sinkStream,
     int bufferSize)
 {
     if (ioResult == null)
     {
         throw new ArgumentNullException(nameof(ioResult));
     }
     return(IoHelper.CopyToAsync(sourceStream, sinkStream, bufferSize, ioResult));
 }
Exemple #6
0
        /// <summary>
        /// Method to read from the source <see cref="Stream"/> and write to the sink. NOTICE: this method
        /// will ONLY update the <see cref="IoResult.BytesReadOrWritten"/> property if one of the given
        /// streams supports seeking. You must test <see cref="Stream.CanSeek"/> to know. Notice also that
        /// <see cref="IoResult.BytesReadOrWritten"/> may be 0 when the <see cref="IoResult.Result"/>
        /// is <see cref="IoResultState.Success"/>.
        /// </summary>
        /// <param name="sourceStream">Not null.</param>
        /// <param name="sinkStream">Not null.</param>
        /// <param name="bufferSize">Required.</param>
        /// <param name="ioResult">Optional. If null, a new instance is created; with any given
        /// <see cref="CancellationToken"/>.</param>
        /// <param name="cancellationToken">Optional.</param>
        /// <returns>Not null. If you provided an argument, the same object is returned.</returns>
        /// <exception cref="ArgumentNullException"></exception>
        /// <exception cref="ArgumentOutOfRangeException"></exception>
        public static async Task <IoResult> CopyToAsync(
            Stream sourceStream,
            Stream sinkStream,
            int bufferSize,
            IoResult ioResult = null,
            CancellationToken cancellationToken = default)
        {
            if (sourceStream == null)
            {
                throw new ArgumentNullException(nameof(sourceStream));
            }
            if (sinkStream == null)
            {
                throw new ArgumentNullException(nameof(sinkStream));
            }
            if (bufferSize <= 0)
            {
                throw new ArgumentOutOfRangeException(nameof(bufferSize), bufferSize.ToString());
            }
            if (ioResult == null)
            {
                ioResult = new IoResult(cancellationToken);
            }
            else if (!ioResult.IsSuccess)
            {
                return(ioResult);
            }
            try {
                long position = 0L;
                if (sourceStream.CanSeek)
                {
                    position = sourceStream.Position;
                }
                else if (sinkStream.CanSeek)
                {
                    position = sinkStream.Position;
                }
                await sourceStream.CopyToAsync(sinkStream, bufferSize, ioResult.CancellationToken);

                if (sourceStream.CanSeek)
                {
                    ioResult.AddBytesReadOrWritten(Math.Max(0L, sourceStream.Position - position));
                }
                else if (sinkStream.CanSeek)
                {
                    ioResult.AddBytesReadOrWritten(Math.Max(0L, sinkStream.Position - position));
                }
            } catch (Exception exception) {
                ioResult.Fault(exception);
            }
            return(ioResult);
        }
Exemple #7
0
 /// <summary>
 /// NOTICE: this method ALWAYS updates the <see cref="IoResult.BytesReadOrWritten"/> property by the given
 /// length if the stream does not support seeking. This writes from a buffer to the sink <see cref="Stream"/>.
 /// The write may write any length. Note that this method catches all exceptions and will
 /// <see cref="IoResult.Fault"/> the result. IF the stream supports seeking, this method updates the
 /// <see cref="IoResult.BytesReadOrWritten"/> property based on the change in the stream's Position. Otherwise
 /// the value is always explicitly updated by the given length: you must test the stream to know. If there is
 /// an incoming value, it is incremented.
 /// </summary>
 /// <param name="ioResult">Not null.</param>
 /// <param name="sinkStream">Not null.</param>
 /// <param name="buffer">Not null.</param>
 /// <param name="offset">Offset within <c>buffer</c> to begin writing.</param>
 /// <param name="length">Length within <c>buffer</c> to write.</param>
 /// <returns>Completes when the indicated write completes.</returns>
 /// <exception cref="ArgumentNullException"></exception>
 /// <exception cref="ArgumentOutOfRangeException"></exception>
 public static Task <IoResult> WriteAsync(
     this IoResult ioResult,
     Stream sinkStream,
     byte[] buffer,
     int offset,
     int length)
 {
     if (ioResult == null)
     {
         throw new ArgumentNullException(nameof(ioResult));
     }
     return(IoHelper.WriteAsync(sinkStream, buffer, offset, length, ioResult));
 }
Exemple #8
0
 /// <summary>
 /// Method to read to a buffer from the <see cref="Stream"/>. The read may return any length; and the
 /// result is updated by the the length. Note that this method catches all exceptions and will
 /// <see cref="IoResult.Fault"/> the result. This method updates the <see cref="IoResult.BytesReadOrWritten"/>
 /// property: notice that if there is an incoming value, it is incremented.
 /// </summary>
 /// <param name="sourceStream">Not null.</param>
 /// <param name="buffer">Not null.</param>
 /// <param name="offset">Offset within <c>buffer</c> to begin reading.</param>
 /// <param name="length">Length within <c>buffer</c> to read.</param>
 /// <param name="ioResult">Optional. If null, a new instance is created; with any given
 /// <see cref="CancellationToken"/>.</param>
 /// <param name="cancellationToken">Optional.</param>
 /// <returns>Not null. If you provided an argument, the same object is returned.</returns>
 /// <exception cref="ArgumentNullException"></exception>
 /// <exception cref="ArgumentOutOfRangeException"></exception>
 public static async Task <IoResult> ReadAsync(
     Stream sourceStream,
     byte[] buffer,
     int offset,
     int length,
     IoResult ioResult = null,
     CancellationToken cancellationToken = default)
 {
     if (sourceStream == null)
     {
         throw new ArgumentNullException(nameof(sourceStream));
     }
     if (buffer == null)
     {
         throw new ArgumentNullException(nameof(buffer));
     }
     if ((offset < 0) ||
         (offset >= buffer.Length))
     {
         throw new ArgumentOutOfRangeException(nameof(offset));
     }
     if ((length < 0) ||
         (length > (buffer.Length - offset)))
     {
         throw new ArgumentOutOfRangeException(nameof(length));
     }
     if (ioResult == null)
     {
         ioResult = new IoResult(cancellationToken);
     }
     else if (!ioResult.IsSuccess)
     {
         return(ioResult);
     }
     try {
         ioResult.AddBytesReadOrWritten(
             await sourceStream.ReadAsync(
                 buffer,
                 offset,
                 length,
                 ioResult.CancellationToken));
     } catch (Exception exception) {
         ioResult.Fault(exception);
     }
     return(ioResult);
 }
Exemple #9
0
        /// <summary>
        /// NOTICE: this method ALWAYS updates the <see cref="IoResult.BytesReadOrWritten"/> property by the given
        /// length if the stream does not support seeking. This writes a specified <c>length</c> from a buffer to the
        /// sink <see cref="Stream"/>. If the stream can seek, the write must write all bytes in the given length;
        /// or else the <see cref="IoResult.Result"/> is <see cref="IoResultState.BadData"/>. Note that this
        /// method catches all exceptions and will <see cref="IoResult.Fault"/> the result. If the stream supports
        /// seeking, This method updates the <see cref="IoResult.BytesReadOrWritten"/> property based on the change in
        /// the stream's Position. Otherwise the value is always explicitly updated by the given length: you must
        /// test the stream to know. If there is an incoming value, it is incremented. Otherwise, if the stream cannot
        /// seek, then one <see cref="Stream.WriteAsync(byte[],int,int,CancellationToken)"/> is invoked with the
        /// arguments; AND in this case, the <see cref="IoResult.Result"/> is never
        /// <see cref="IoResultState.BadData"/>.
        /// </summary>
        /// <param name="sinkStream">Not null.</param>
        /// <param name="buffer">Not null.</param>
        /// <param name="offset">Offset within <c>buffer</c> to begin writing.</param>
        /// <param name="length">Length within <c>buffer</c> to write.</param>
        /// <param name="ioResult">Optional. If null, a new instance is created; with any given
        /// <see cref="CancellationToken"/>.</param>
        /// <param name="cancellationToken">Optional.</param>
        /// <returns>Not null. If you provided an argument, the same object is returned.</returns>
        /// <exception cref="ArgumentNullException"></exception>
        /// <exception cref="ArgumentOutOfRangeException"></exception>
        public static async Task <IoResult> WriteAllAsync(
            Stream sinkStream,
            byte[] buffer,
            int offset,
            int length,
            IoResult ioResult = null,
            CancellationToken cancellationToken = default)
        {
            if (sinkStream == null)
            {
                throw new ArgumentNullException(nameof(sinkStream));
            }
            if (buffer == null)
            {
                throw new ArgumentNullException(nameof(buffer));
            }
            if ((offset < 0) ||
                (offset >= buffer.Length))
            {
                throw new ArgumentOutOfRangeException(nameof(offset));
            }
            if ((length < 0) ||
                (length > (buffer.Length - offset)))
            {
                throw new ArgumentOutOfRangeException(nameof(length));
            }
            if (ioResult == null)
            {
                ioResult = new IoResult(cancellationToken);
            }
            else if (!ioResult.IsSuccess)
            {
                return(ioResult);
            }
            long targetCount = ioResult.BytesReadOrWritten + length;

            try {
                while (ioResult.BytesReadOrWritten < targetCount)
                {
                    long position = sinkStream.CanSeek
                                                        ? sinkStream.Position
                                                        : targetCount;
                    await sinkStream.WriteAsync(
                        buffer,
                        offset,
                        (int)targetCount - (int)ioResult.BytesReadOrWritten,
                        ioResult.CancellationToken);

                    long bytesWritten = sinkStream.CanSeek
                                                        ? Math.Max(0L, sinkStream.Position - position)
                                                        : length;
                    ioResult.AddBytesReadOrWritten(bytesWritten);
                    if ((ioResult.BytesReadOrWritten == targetCount) ||
                        ioResult.IsCancelled)
                    {
                        break;
                    }
                    if (bytesWritten > 0L)
                    {
                        offset += (int)bytesWritten;
                        continue;
                    }
                    ioResult.BadData();
                    break;
                }
            } catch (Exception exception) {
                ioResult.Fault(exception);
            }
            return(ioResult);
        }
Exemple #10
0
        /// <summary>
        /// Method to read to a buffer from the <see cref="Stream"/>. The read must return all bytes in the
        /// given <c>length</c>; or else the <see cref="IoResult.Result"/> is
        /// <see cref="IoResultState.BadData"/>. Note that this method catches all exceptions and will
        /// <see cref="IoResult.Fault"/> the result. This method takes an <c>offset</c> and  <c>length</c> within
        /// the <c>buffer</c>; and updates the <see cref="IoResult.BytesReadOrWritten"/> property: notice that
        /// if there is an incoming value, it is incremented.
        /// </summary>
        /// <param name="sourceStream">Not null.</param>
        /// <param name="buffer">Not null.</param>
        /// <param name="offset">Offset within <c>buffer</c> to begin reading.</param>
        /// <param name="length">Length within <c>buffer</c> to read.</param>
        /// <param name="ioResult">Optional. If null, a new instance is created; with any given
        /// <see cref="CancellationToken"/>.</param>
        /// <param name="cancellationToken">Optional.</param>
        /// <returns>Not null. If you provided an argument, the same object is returned.</returns>
        /// <exception cref="ArgumentNullException"></exception>
        /// <exception cref="ArgumentOutOfRangeException"></exception>
        public static async Task <IoResult> ReadAllAsync(
            Stream sourceStream,
            byte[] buffer,
            int offset,
            int length,
            IoResult ioResult = null,
            CancellationToken cancellationToken = default)
        {
            if (sourceStream == null)
            {
                throw new ArgumentNullException(nameof(sourceStream));
            }
            if (buffer == null)
            {
                throw new ArgumentNullException(nameof(buffer));
            }
            if ((offset < 0) ||
                (offset >= buffer.Length))
            {
                throw new ArgumentOutOfRangeException(nameof(offset));
            }
            if ((length < 0) ||
                (length > (buffer.Length - offset)))
            {
                throw new ArgumentOutOfRangeException(nameof(length));
            }
            if (ioResult == null)
            {
                ioResult = new IoResult(cancellationToken);
            }
            else if (!ioResult.IsSuccess)
            {
                return(ioResult);
            }
            long targetCount = ioResult.BytesReadOrWritten + length;

            try {
                while (ioResult.BytesReadOrWritten < targetCount)
                {
                    int bytesRead
                        = await sourceStream.ReadAsync(
                              buffer,
                              offset,
                              (int)targetCount - (int)ioResult.BytesReadOrWritten,
                              ioResult.CancellationToken);

                    ioResult.AddBytesReadOrWritten(bytesRead);
                    if ((ioResult.BytesReadOrWritten == targetCount) ||
                        ioResult.IsCancelled)
                    {
                        break;
                    }
                    if (bytesRead > 0)
                    {
                        offset += Math.Max(0, bytesRead);
                        continue;
                    }
                    ioResult.BadData();
                    break;
                }
            } catch (Exception exception) {
                ioResult.Fault(exception);
            }
            return(ioResult);
        }