using System; using System.Collections.Generic; using System.IO; using System.Text; namespace Apewer.Web { internal sealed class MiniReader : Stream { bool _disposed = false; MiniConnection _connection; Stream _stream; long _remaining; internal byte[] RemainsBytes = null; int _offset = 0; long _total = 0L; internal MiniReader(MiniConnection connection, long remaining = -1) { _connection = connection; _stream = connection.Stream; _remaining = remaining; } public bool Disposed { get => _disposed; } public override bool CanRead { get => true; } public override bool CanWrite { get => false; } public override bool CanSeek { get => false; } public override long Length { get => throw new NotSupportedException(); } public override long Position { get => throw new NotSupportedException(); set => throw new NotSupportedException(); } public override void Close() => _disposed = true; public override void Flush() { } public override long Seek(long offset, SeekOrigin origin) => throw new NotSupportedException(); public override void SetLength(long value) => throw new NotSupportedException(); #region read int ReadRemins(byte[] buffer, int offset, int count) { // 返回 0,读取 Remains 已经完成,由外层继续读取。 if (RemainsBytes == null) return 0; var length = RemainsBytes.Length; if (length < 1) return 0; // Remains 中剩余的长度,并根据 count 参数限制读取数量。 var result = length - offset; if (result < 1) return 0; if (result > count) result = count; // Content-Length 指定的剩余长度。 if (_remaining > 0 && result > _remaining) result = (int)_remaining; // RemainsBytes 长度溢出限制。 if (result + _offset > length) result = length - _offset; // 从 Remains 中读取,返回具体的字节数。 Buffer.BlockCopy(RemainsBytes, _offset, buffer, offset, result); _offset += result; _remaining -= result; _total += result; // 已完成 Remains 的读取。 if (_offset >= length) RemainsBytes = null; return result; } public override int Read(byte[] buffer, int offset, int count) { if (_connection.Server.SynchronousIO) { if (_disposed) throw new ObjectDisposedException(typeof(Stream).FullName); // 检查参数。 if (buffer == null) throw new ArgumentNullException("参数 buffer 无效。"); if (offset < 0) throw new ArgumentOutOfRangeException("offset", "参数 offset 小于 0。"); if (count < 0) throw new ArgumentOutOfRangeException("count", "参数 count 小于 0。"); int bufferLength = buffer.Length; if (offset > bufferLength) throw new ArgumentOutOfRangeException("offset", "指定的 offset 的值超出了 buffer 数组的容量。"); if (offset + count > bufferLength) throw new ArgumentException("指定的 offset 和 count 超出了 buffer 数组的容量。"); if (count == 0) return 0; // 检查剩余读取量。 if (_remaining == 0) return 0; // 从 Remains 中读取。 var nread = ReadRemins(buffer, offset, count); if (nread > 0) return nread; // 根据 Content-Length 限定长度。 if (_remaining > 0 && _remaining < count) count = (int)_remaining; var read = _stream.Read(buffer, offset, count); if (read > 0 && _remaining > 0) _remaining -= read; return read; } else { var async = BeginRead(buffer, offset, count, null, null); var result = EndRead(async); return result; } } public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback cback, object state) { #if DEBUG if (_disposed) throw new ObjectDisposedException(typeof(Stream).FullName); // 检查参数。 if (buffer == null) throw new ArgumentNullException("参数 buffer 无效。"); if (offset < 0) throw new ArgumentOutOfRangeException("offset", "参数 offset 小于 0。"); if (count < 0) throw new ArgumentOutOfRangeException("count", "参数 count 小于 0。"); int bufferLength = buffer.Length; if (offset > bufferLength) throw new ArgumentOutOfRangeException("offset", "指定的 offset 的值超出了 buffer 数组的容量。"); if (offset + count > bufferLength) throw new ArgumentException("指定的 offset 和 count 超出了 buffer 数组的容量。"); // Content-Length if (_remaining == 0) { var ares = new MiniStreamAsyncResult(); ares.Buffer = buffer; ares.Offset = offset; ares.Count = count; ares.Callback = cback; ares.State = state; ares.SynchRead = 0; ares.Complete(); return ares; } if (_remaining > 0 && _remaining < count) count = (int)_remaining; return _stream.BeginRead(buffer, offset, count, cback, state); #else throw new NotSupportedException(); #endif } public override int EndRead(IAsyncResult ar) { #if DEBUG if (_disposed) throw new ObjectDisposedException(typeof(Stream).FullName); if (ar == null) throw new ArgumentNullException(nameof(ar)); if (ar is MiniStreamAsyncResult) { var r = (MiniStreamAsyncResult)ar; if (!ar.IsCompleted) ar.AsyncWaitHandle.WaitOne(); return r.SynchRead; } int nread = _stream.EndRead(ar); if (_remaining > 0 && nread > 0) _remaining -= nread; return nread; #else throw new NotSupportedException(); #endif } #endregion #region write public override void Write(byte[] buffer, int offset, int count) => throw new NotSupportedException(); public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, object state) => throw new NotSupportedException(); public override void EndWrite(IAsyncResult ar) => throw new NotSupportedException(); #endregion } }