using System; using System.Buffers; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Remotely.Shared.Utilities; public class RewritableStream : Stream { private readonly Stream _underlyingStream; private readonly Dictionary _rewriteMap; public RewritableStream(Stream underlyingStream, Dictionary rewriteMap) { _underlyingStream = underlyingStream; _rewriteMap = rewriteMap; } public override bool CanRead => _underlyingStream.CanRead; public override bool CanSeek => _underlyingStream.CanSeek; public override bool CanTimeout => _underlyingStream.CanTimeout; public override bool CanWrite => _underlyingStream.CanWrite; public override long Length => _underlyingStream.Length; public override long Position { get => _underlyingStream.Position; set => _underlyingStream.Position = value; } public override int ReadTimeout { get => _underlyingStream.ReadTimeout; set => _underlyingStream.ReadTimeout = value; } public override int WriteTimeout { get => _underlyingStream.WriteTimeout; set => _underlyingStream.WriteTimeout = value; } public override void Close() { _underlyingStream.Close(); base.Close(); } public override ValueTask DisposeAsync() { GC.SuppressFinalize(this); return _underlyingStream.DisposeAsync(); } public override void Flush() { _underlyingStream.Flush(); } public override int Read(byte[] buffer, int offset, int count) { var i = 0; for (; i < count; i++) { if (_rewriteMap.TryGetValue(Position, out var newValue)) { buffer[offset + i] = newValue; Seek(1, SeekOrigin.Current); } else { var current = _underlyingStream.ReadByte(); if (current == -1) { break; } buffer[offset + i] = current == -1 ? (byte)0 : (byte)current; } } return i; } public override long Seek(long offset, SeekOrigin origin) { return _underlyingStream.Seek(offset, origin); } public override void SetLength(long value) { _underlyingStream.SetLength(value); } public override void Write(byte[] buffer, int offset, int count) { _underlyingStream.Write(buffer, offset, count); } protected override void Dispose(bool disposing) { _underlyingStream.Dispose(); base.Dispose(disposing); } }