/// <summary>
        /// Reads a byte from the stream and advances the position within the stream by one byte,
        /// or returns -1 if at the end of the stream.
        /// </summary>
        ///
        /// <returns>
        /// The unsigned byte cast to an <see cref="int"/>, or -1 if at the end of the stream.
        /// </returns>
        ///
        /// <exception cref="NotSupportedException">
        /// If the stream does not support reading.
        /// </exception>
        ///
        /// <exception cref="ObjectDisposedException">
        /// Methods were called after the stream was closed.
        /// </exception>
        ///
        /// <exception cref="HealthServiceException">
        /// If there was a failure reading the data from HealthVault.
        /// </exception>
        ///
        public override int ReadByte()
        {
            if (!CanRead)
            {
                throw new NotSupportedException();
            }

            if (_disposed)
            {
                throw new ObjectDisposedException(nameof(BlobStream));
            }

            int result = -1;

            // Check to see if there is still something in the buffer
            if (_bufferList.Count > 0)
            {
                BufferRequest buffer = _bufferList[0];
                result = buffer.Buffer[buffer.Offset];
                buffer.Count--;
                buffer.Offset++;

                if (buffer.Count == 0)
                {
                    _bufferList.RemoveAt(0);
                }
            }
            else
            {
                // Get a new chunk

                int    bufferSize = (int)(_length ?? DefaultStreamBufferSize);
                byte[] newBuffer  = new byte[bufferSize];
                int    count      = Read(newBuffer, 0, bufferSize);

                if (count > 0)
                {
                    result = newBuffer[0];

                    // Note, this makes a copy of the buffer.
                    _bufferList.Add(
                        new BufferRequest(newBuffer, 1, count - 1));
                }
            }

            return(result);
        }
        private async Task WriteChunkAsync(int chunkSizeToWrite, bool uploadComplete)
        {
            int  bytesInWebRequest = 0;
            long start             = 0;

            byte[] webRequestBuffer = null;
            if (chunkSizeToWrite > 0)
            {
                int writeBufferOffset = 0;
                while (writeBufferOffset < chunkSizeToWrite)
                {
                    BufferRequest curRequestBuffer = _bufferList[_currentBufferRequestIndex];

                    // Get the number of bytes in the current request buffer up to a chunk.
                    int numBytesToCopy = Math.Min(curRequestBuffer.Count, chunkSizeToWrite);

                    // Ensure we don't write past the end of the chunk buffer.
                    numBytesToCopy = Math.Min(
                        numBytesToCopy,
                        _chunkBuffer.Length - writeBufferOffset);

                    // Copy the bytes to be sent over in to the chunk buffer;
                    Array.Copy(
                        curRequestBuffer.Buffer,
                        curRequestBuffer.Offset,
                        _chunkBuffer,
                        writeBufferOffset,
                        numBytesToCopy);

                    writeBufferOffset       += numBytesToCopy;
                    curRequestBuffer.Offset += numBytesToCopy;
                    curRequestBuffer.Count  -= numBytesToCopy;

                    if (curRequestBuffer.Count < 1)
                    {
                        _currentBufferRequestIndex++;
                    }
                }

                if (_currentBufferRequestIndex > 0)
                {
                    _bufferList.RemoveRange(0, _currentBufferRequestIndex);
                    _currentBufferRequestIndex = 0;
                }

                IList <byte[]> blockHashes =
                    _blobHasher.CalculateBlockHashes(_chunkBuffer, 0, chunkSizeToWrite);

                _blockHashes.AddRange(blockHashes);

                bytesInWebRequest = chunkSizeToWrite;
                start             = _position;
                webRequestBuffer  = _chunkBuffer;
            }

            if (webRequestBuffer != null)
            {
                HttpResponseMessage request = await ExecutePutRequestAsync(start, bytesInWebRequest, uploadComplete, webRequestBuffer).ConfigureAwait(false);

                if (!request.IsSuccessStatusCode)
                {
                    ThrowRequestFailedException(request);
                }

                _bytesInBuffer -= chunkSizeToWrite;
            }

            _position += chunkSizeToWrite;
        }
 private void AugmentBufferList(BufferRequest buffer)
 {
     _bufferList.Add(buffer);
     _bytesInBuffer += buffer.Count;
 }
 private void AugmentBufferList(BufferRequest buffer)
 {
     _bufferList.Add(buffer);
     _bytesInBuffer += buffer.Count;
 }