IterStream.cs (7232B)
1 using Std.Convert; 2 using Std.Iter; 3 using Std.Maybe; 4 using System; 5 using System.IO; 6 using System.Threading; 7 using System.Threading.Tasks; 8 #region Namespaces 9 namespace Std.IO { 10 #region Types 11 [System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1063:Implement IDisposable Correctly", Justification = "This type should not implement IDisposable to begin with, but it has to by being a subtype of Stream. We have it do nothing.")] 12 public sealed class IterStream<T, TIter>: Stream, IDisposable, IAsyncDisposable where T: notnull, IInto<ReadOnlyMemory<byte>> where TIter: notnull, IFusedIterator<T> { 13 14 #region Type-level Constructors 15 #endregion 16 17 #region Instance Constructors 18 public IterStream(TIter iter) => (Iter, _leftOver, _leftOverIndex) = (iter, ReadOnlyMemory<byte>.Empty, 0); 19 #endregion 20 21 #region Type-level Fields 22 #endregion 23 24 #region Instance Fields 25 public TIter Iter; 26 ReadOnlyMemory<byte> _leftOver; 27 int _leftOverIndex; 28 #endregion 29 30 #region Type-level Properties 31 #endregion 32 33 #region Instance Properties 34 public sealed override bool CanRead => true; 35 public sealed override bool CanSeek => false; 36 public sealed override bool CanTimeout => false; 37 public sealed override bool CanWrite => false; 38 public sealed override long Length => throw new NotSupportedException(); 39 public sealed override long Position { 40 get => throw new NotSupportedException(); 41 set => throw new NotSupportedException(); 42 } 43 public sealed override int ReadTimeout => throw new InvalidOperationException(); 44 public sealed override int WriteTimeout => throw new InvalidOperationException(); 45 #endregion 46 47 #region Type-level Functions 48 public static IterStream<T, TIter> New(TIter iter) => new(iter); 49 #endregion 50 51 #region Instance Functions 52 public sealed override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback? callback, object? state) => base.BeginRead(buffer, offset, count, callback, state); 53 public sealed override IAsyncResult BeginWrite(byte[] _, int _1, int _2, AsyncCallback? _3, object? _4) => throw new NotSupportedException(); 54 public sealed override void Close() => Dispose(); 55 public sealed override void CopyTo(Stream stream, int bufferSize) { 56 57 var bytes = new byte[bufferSize <= 0 ? throw new ArgumentOutOfRangeException(nameof(bufferSize), "bufferSize must be positive.") : bufferSize]; 58 int count; 59 while ((count = Read(bytes.AsSpan())) > 0) { stream.Write(bytes.AsSpan(0, count)); } 60 } 61 public sealed override Task CopyToAsync(Stream stream, int bufferSize, CancellationToken _2) { CopyTo(stream, bufferSize); return Task.CompletedTask; } 62 [Obsolete("System.Threading.ManualResetEvent should be used instead.", true)] 63 protected sealed override WaitHandle CreateWaitHandle() => new ManualResetEvent(false); 64 public new void Dispose() => GC.SuppressFinalize(this); 65 [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2215:Dispose methods should call base class dispose", Justification = "We don't want Dispose to do anything.")] 66 protected sealed override void Dispose(bool disposing) { 67 if (disposing) { 68 Dispose(); 69 } 70 } 71 [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2215:Dispose methods should call base class dispose", Justification = "We don't want DisposeAsync to do anything.")] 72 public sealed override ValueTask DisposeAsync() { 73 74 Dispose(); 75 return ValueTask.CompletedTask; 76 } 77 public sealed override int EndRead(IAsyncResult asyncResult) => base.EndRead(asyncResult); 78 public sealed override void EndWrite(IAsyncResult asyncResult) => throw new NotSupportedException(); 79 public sealed override bool Equals(object? _) => false; 80 public sealed override void Flush() { } 81 public sealed override Task FlushAsync(CancellationToken _) => Task.CompletedTask; 82 public sealed override int GetHashCode() => 0; 83 [Obsolete("Platform does not support this. A System.PlatformNotSupportedException will be thrown.", true)] 84 public sealed override object InitializeLifetimeService() => throw new PlatformNotSupportedException(); 85 [Obsolete("Do not call this method.", true)] 86 protected sealed override void ObjectInvariant() { } 87 public sealed override int Read(byte[] buffer, int offset, int count) => Read(buffer.AsSpan(offset, count)); 88 public sealed override int Read(Span<byte> buffer) { 89 90 if (_leftOverIndex == _leftOver.Length) { 91 Maybe<T> mbe; 92 ReadOnlyMemory<byte> bytes = default; 93 // Iterate until the first non-empty ReadOnlyMemory<byte>. 94 while ((mbe = Iter.Next()).IsSome && (bytes = mbe.Unwrap().Into()).IsEmpty){} 95 if (mbe.IsSome) { 96 var len = Math.Min(buffer.Length, bytes.Length); 97 bytes.Span[..len].CopyTo(buffer); 98 _leftOver = bytes; 99 _leftOverIndex = len; 100 return len; 101 } else { 102 return 0; 103 } 104 } else { 105 var leftOverLen = _leftOver.Length - _leftOverIndex; 106 var len = Math.Min(buffer.Length, leftOverLen); 107 _leftOver.Span.Slice(_leftOverIndex, len).CopyTo(buffer); 108 _leftOverIndex += len; 109 return len; 110 } 111 } 112 public sealed override Task<int> ReadAsync(byte[] buffer, int offset, int count, CancellationToken _) => Task.FromResult(Read(buffer.AsSpan(offset, count))); 113 public sealed override ValueTask<int> ReadAsync(Memory<byte> buffer, CancellationToken _1) => ValueTask.FromResult(Read(buffer.Span)); 114 public sealed override int ReadByte() { 115 116 Span<byte> span = stackalloc byte[1]; 117 return Read(span) == 0 ? -1 : span[0]; 118 } 119 public sealed override long Seek(long _, SeekOrigin _1) => throw new NotSupportedException(); 120 public sealed override void SetLength(long _) => throw new NotSupportedException(); 121 public sealed override string ToString() => string.Empty; 122 public sealed override void Write(byte[] _, int _1, int _2) => throw new NotSupportedException(); 123 public sealed override void Write(ReadOnlySpan<byte> _) => throw new NotSupportedException(); 124 public sealed override Task WriteAsync(byte[] _, int _1, int _2, CancellationToken _3) => throw new NotSupportedException(); 125 public sealed override ValueTask WriteAsync(ReadOnlyMemory<byte> _, CancellationToken _1) => throw new NotSupportedException(); 126 public sealed override void WriteByte(byte _) => throw new NotSupportedException(); 127 #endregion 128 129 #region Operators 130 #endregion 131 132 #region Types 133 #endregion 134 } 135 #endregion 136 137 #region Namespaces 138 #endregion 139 } 140 #endregion