using CliWrap; using InnovEnergy.Lib.Utils; namespace InnovEnergy.Lib.Channels.V2; public class CommandChannel : IChannel> { private UInt32 _BufferSize; private Command Command { get; } private readonly MemoryStream _StdIn = new MemoryStream(); private readonly MemoryStream _StdOut = new MemoryStream(); private CommandTask? _CommandTask; public CommandChannel(Command command, UInt32 bufferSize = 64) { _BufferSize = bufferSize; Command = command .WithStandardInputPipe(PipeSource.FromStream(_StdIn)) .WithStandardOutputPipe(PipeTarget.ToStream(_StdOut, true)); } private void Open() { if (_CommandTask is null || _CommandTask.Task.IsCompleted) { Close(); _CommandTask = Command.ExecuteAsync(); // TODO: support cancellation } } private void Close() { _StdIn.Seek(0, SeekOrigin.Begin); _StdOut.Seek(0, SeekOrigin.Begin); _CommandTask?.Dispose(); _CommandTask = null; } public async Task> Read() { try { Open(); var buffer = new Byte[_BufferSize]; var nRead = await _StdOut.ReadAsync(buffer, 0, buffer.Length); if (nRead >= buffer.Length) _BufferSize *= 2; else if (nRead <= 0) throw new IOException("Broken pipe (StdOut)"); return new ArraySegment(buffer, 0, nRead); } catch { Close(); throw; } } public async Task Write(IReadOnlyList tx) { try { Open(); await _StdIn.WriteAsync(tx as Byte[] ?? tx.ToArray(), 0, tx.Count); } catch { Close(); throw; } } }