Std

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

VecStreamWriter.cs (8685B)


      1 using Std.Vec;
      2 using System;
      3 using System.IO;
      4 using System.Threading;
      5 using System.Threading.Tasks;
      6 #region Namespaces
      7 namespace Std.IO {
      8     #region Types
      9     // Write-only, non-seekable, stream based on Std.Vec.Vec<byte>.
     10     // This type is an even lighter-weight alternative to the default MemoryStream and has more strictly enforced behavior.
     11     // This type only implements I(Async)Disposable because it has to by virtue of being a subtype of System.IO.StreamIter.
     12     // This type does not dispose of anything, however, and calling dispose only suppresses the finalizer.
     13     // This type is a subtype of MemoryStream purely for performance reasons. There is a lot of code in the .NET SDK
     14     // that uses reflection to detect more specific subtypes to influence the behavior of a type or function.
     15     // We want this type to enjoy any potential benefits such code may have.
     16     // Note this type does not use the underlying data or implementation of MemoryStream in any way with exceptions of BeginWrite and EndWrite.
     17     [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 StreamIter. We have it do nothing.")]
     18     public sealed class VecStreamWriter: MemoryStream, IDisposable, IAsyncDisposable {
     19 
     20         #region Type-level Constructors
     21         #endregion
     22 
     23         #region Instance Constructors
     24         public VecStreamWriter() : base(Array.Empty<byte>(), 0, 0, false, false) => _buffer = new Vec<byte>();
     25         public VecStreamWriter(uint capacity) : base(Array.Empty<byte>(), 0, 0, false, false) => _buffer = Vec<byte>.WithCapacity(capacity);
     26         #endregion
     27 
     28         #region Type-level Fields
     29         #endregion
     30 
     31         #region Instance Fields
     32         Vec<byte> _buffer;
     33         #endregion
     34 
     35         #region Type-level Properties
     36         #endregion
     37 
     38         #region Instance Properties
     39         public sealed override bool CanRead => false;
     40         public sealed override bool CanSeek => false;
     41         public sealed override bool CanTimeout => false;
     42         public sealed override bool CanWrite => true;
     43         public sealed override int Capacity => (int)_buffer.Capacity;
     44         public ReadOnlySpan<byte> Data => _buffer.AsSlice();
     45         public uint Len => _buffer.Len;
     46         public sealed override long Length => Len;
     47         // The .NET SDK is littered with many terrible design decisions.
     48         // Instead of having dedicated interfaces, non-sealed classes, and non-sealed records that guarantee certain invariants,
     49         // many types have functions that are only sometimes valid. This in turn requires
     50         // many subtypes to throw exceptions for inapplicable functions.
     51         // The getter of this property should be fine to return, but the API documentation states that only seekable streams are allowed to return anything.
     52         public sealed override long Position {
     53             get => throw new NotSupportedException();
     54             set => throw new NotSupportedException();
     55         }
     56         public sealed override int ReadTimeout => throw new InvalidOperationException();
     57         public sealed override int WriteTimeout => throw new InvalidOperationException();
     58         #endregion
     59 
     60         #region Type-level Functions
     61         public static VecStreamWriter New() => new();
     62         public static VecStreamWriter NewWithCapacity(uint capacity) => new(capacity);
     63         #endregion
     64 
     65         #region Instance Functions
     66         public sealed override IAsyncResult BeginRead(byte[] _, int _1, int _2, AsyncCallback? _3, object? _4) => throw new NotSupportedException();
     67         // Due to complexity of doing this correctly, we defer to the base implementation.
     68         public sealed override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback? callback, object? state) => base.BeginWrite(buffer, offset, count, callback, state);
     69         public sealed override void Close() => Dispose();
     70         public sealed override void CopyTo(Stream _, int _1) => throw new NotSupportedException();
     71         public sealed override Task CopyToAsync(Stream _, int _1, CancellationToken _2) => throw new NotSupportedException();
     72         [Obsolete("System.Threading.ManualResetEvent should be used instead.", true)]
     73         protected sealed override WaitHandle CreateWaitHandle() => new ManualResetEvent(false);
     74         [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA1816:Dispose methods should call SuppressFinalize", Justification = "We don't want Dispose to do anything.")]
     75         public new void Dispose() => GC.SuppressFinalize(this);
     76         [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2215:Dispose methods should call base class dispose", Justification = "We don't want Dispose to do anything.")]
     77         protected sealed override void Dispose(bool disposing) {
     78             // This should mean Dispose on StreamIter or MemoryStream was called, so we redirect to Dispose which suppresses the finalizer.
     79             if (disposing) {
     80                 Dispose();
     81             }
     82         }
     83         [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2215:Dispose methods should call base class dispose", Justification = "We don't want DisposeAsync to do anything.")]
     84         public sealed override ValueTask DisposeAsync() { 
     85         
     86             Dispose();
     87             return ValueTask.CompletedTask;
     88         }
     89         public sealed override int EndRead(IAsyncResult _) => throw new NotSupportedException();
     90         // Due to complexity of doing this correctly, we defer to the base implementation.
     91         public sealed override void EndWrite(IAsyncResult asyncResult) => base.EndWrite(asyncResult);
     92         public sealed override bool Equals(object? _) => false;
     93         public sealed override void Flush() { }
     94         public sealed override Task FlushAsync(CancellationToken _) => Task.CompletedTask;
     95         public sealed override int GetHashCode() => 0;
     96         public Unit Reset() => _buffer.Clear();
     97         public Vec<byte> GetVecBuffer() => _buffer;
     98         public sealed override byte[] GetBuffer() => _buffer.AsArray();
     99         [Obsolete("Platform does not support this. A System.PlatformNotSupportedException will be thrown.", true)]
    100         public sealed override object InitializeLifetimeService() => throw new PlatformNotSupportedException();
    101         [Obsolete("Do not call this method.", true)]
    102         protected sealed override void ObjectInvariant() { }
    103         public sealed override int Read(byte[] _, int _1, int _2) => throw new NotSupportedException();
    104         public sealed override int Read(Span<byte> _) => throw new NotSupportedException();
    105         public sealed override Task<int> ReadAsync(byte[] _, int _1, int _2, CancellationToken _3) => throw new NotSupportedException();
    106         public sealed override ValueTask<int> ReadAsync(Memory<byte> _, CancellationToken _1) => throw new NotSupportedException();
    107         public sealed override int ReadByte() => throw new NotSupportedException();
    108         public sealed override long Seek(long _, SeekOrigin _1) => throw new NotSupportedException();
    109         public sealed override void SetLength(long _) => throw new NotSupportedException();
    110         public sealed override byte[] ToArray() {
    111 
    112             var arr = new byte[_buffer.Len];
    113             _buffer.AsSlice().CopyTo(arr.AsSpan());
    114             return arr;
    115         }
    116         public sealed override string ToString() => "VecStreamWriter";
    117         public Unit Truncate(uint len) => _buffer.Truncate(len);
    118         public sealed override bool TryGetBuffer(out ArraySegment<byte> buffer) {
    119 
    120             buffer = new(_buffer.AsArray(), 0, (int)_buffer.Len);
    121             return true;
    122         }
    123         public sealed override void Write(byte[] buffer, int offset, int count) => Write(buffer.AsSpan(offset, count));
    124         public sealed override void Write(ReadOnlySpan<byte> buffer) => _buffer.ExtendFromSlice(buffer);
    125         public sealed override Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken _) { Write(buffer.AsSpan(offset, count)); return Task.CompletedTask; }
    126         public sealed override ValueTask WriteAsync(ReadOnlyMemory<byte> buffer, CancellationToken _1) { Write(buffer.Span); return ValueTask.CompletedTask; }
    127         public sealed override void WriteByte(byte value) => _buffer.Push(value);
    128         public sealed override void WriteTo(Stream stream) => stream.Write(_buffer.AsSlice());
    129         #endregion
    130 
    131         #region Operators
    132         #endregion
    133 
    134         #region Types
    135         #endregion
    136     }
    137     #endregion
    138 
    139     #region Namespaces
    140     #endregion
    141 }
    142 #endregion