You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

122 lines
3.9 KiB

using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
namespace Apewer.Web
{
internal sealed class MiniWriter : Stream
{
bool _disposed = false;
MiniConnection _conn;
Stream _stream;
bool _chunked;
internal MiniWriter(MiniConnection conn)
{
_conn = conn;
_stream = conn.Stream;
_chunked = conn.Chunked;
}
#region
public bool Disposed { get => _disposed; }
public override bool CanRead { get => false; }
public override bool CanWrite { get => true; }
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();
public override int Read(byte[] buffer, int offset, int count) => throw new NotSupportedException();
public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback cback, object state) => throw new NotSupportedException();
public override int EndRead(IAsyncResult ar) => throw new NotSupportedException();
#endregion
#region write
static readonly byte[] CRLF = BytesUtility.CRLF;
byte[] Pack(byte[] buffer, int offset, int count)
{
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 (_chunked)
{
var ab = new ArrayBuilder<byte>(1024);
ab.Add(count.ToString().Bytes());
ab.Add(CRLF);
ab.Add(buffer, offset, count);
ab.Add(CRLF);
ab.Add(CRLF);
var block = ab.Export();
return block;
}
else
{
var block = new byte[count];
Buffer.BlockCopy(buffer, offset, block, 0, count);
return block;
}
}
public override void Write(byte[] buffer, int offset, int count)
{
var block = Pack(buffer, offset, count);
if (_conn.Server.SynchronousIO)
{
_stream.Write(block, 0, block.Length);
}
else
{
var async = _stream.BeginWrite(block, 0, block.Length, null, null);
_stream.EndWrite(async);
}
}
public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, object state)
{
var block = Pack(buffer, offset, count);
return _stream.BeginWrite(buffer, offset, count, callback, state);
}
public override void EndWrite(IAsyncResult ar)
{
if (_disposed) throw new ObjectDisposedException(typeof(Stream).FullName);
_stream.EndWrite(ar);
}
#endregion
}
}