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

3 years ago
  1. using System;
  2. using System.Collections.Generic;
  3. using System.IO;
  4. using System.Text;
  5. namespace Apewer.Web
  6. {
  7. internal sealed class MiniWriter : Stream
  8. {
  9. bool _disposed = false;
  10. MiniConnection _conn;
  11. Stream _stream;
  12. bool _chunked;
  13. internal MiniWriter(MiniConnection conn)
  14. {
  15. _conn = conn;
  16. _stream = conn.Stream;
  17. _chunked = conn.Chunked;
  18. }
  19. #region
  20. public bool Disposed { get => _disposed; }
  21. public override bool CanRead { get => false; }
  22. public override bool CanWrite { get => true; }
  23. public override bool CanSeek { get => false; }
  24. public override long Length { get => throw new NotSupportedException(); }
  25. public override long Position { get => throw new NotSupportedException(); set => throw new NotSupportedException(); }
  26. public override void Close() => _disposed = true;
  27. public override void Flush() { }
  28. public override long Seek(long offset, SeekOrigin origin) => throw new NotSupportedException();
  29. public override void SetLength(long value) => throw new NotSupportedException();
  30. public override int Read(byte[] buffer, int offset, int count) => throw new NotSupportedException();
  31. public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback cback, object state) => throw new NotSupportedException();
  32. public override int EndRead(IAsyncResult ar) => throw new NotSupportedException();
  33. #endregion
  34. #region write
  35. static readonly byte[] CRLF = BytesUtility.CRLF;
  36. byte[] Pack(byte[] buffer, int offset, int count)
  37. {
  38. if (_disposed) throw new ObjectDisposedException(typeof(Stream).FullName);
  39. // 检查参数。
  40. if (buffer == null) throw new ArgumentNullException("参数 buffer 无效。");
  41. if (offset < 0) throw new ArgumentOutOfRangeException("offset", "参数 offset 小于 0。");
  42. if (count < 0) throw new ArgumentOutOfRangeException("count", "参数 count 小于 0。");
  43. int bufferLength = buffer.Length;
  44. if (offset > bufferLength) throw new ArgumentOutOfRangeException("offset", "指定的 offset 的值超出了 buffer 数组的容量。");
  45. if (offset + count > bufferLength) throw new ArgumentException("指定的 offset 和 count 超出了 buffer 数组的容量。");
  46. // 分块。
  47. if (_chunked)
  48. {
  49. var ab = new ArrayBuilder<byte>(1024);
  50. ab.Add(count.ToString().Bytes());
  51. ab.Add(CRLF);
  52. ab.Add(buffer, offset, count);
  53. ab.Add(CRLF);
  54. ab.Add(CRLF);
  55. var block = ab.Export();
  56. return block;
  57. }
  58. else
  59. {
  60. var block = new byte[count];
  61. Buffer.BlockCopy(buffer, offset, block, 0, count);
  62. return block;
  63. }
  64. }
  65. public override void Write(byte[] buffer, int offset, int count)
  66. {
  67. var block = Pack(buffer, offset, count);
  68. if (_conn.Server.SynchronousIO)
  69. {
  70. _stream.Write(block, 0, block.Length);
  71. }
  72. else
  73. {
  74. var async = _stream.BeginWrite(block, 0, block.Length, null, null);
  75. _stream.EndWrite(async);
  76. }
  77. }
  78. public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, object state)
  79. {
  80. var block = Pack(buffer, offset, count);
  81. return _stream.BeginWrite(buffer, offset, count, callback, state);
  82. }
  83. public override void EndWrite(IAsyncResult ar)
  84. {
  85. if (_disposed) throw new ObjectDisposedException(typeof(Stream).FullName);
  86. _stream.EndWrite(ar);
  87. }
  88. #endregion
  89. }
  90. }