Std

Mainly a port of Rust's std.
git clone https://git.philomathiclife.com/repos/Std
Log | Files | Refs | README

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