using System.Threading.Channels;
using RioJoy.Core.Serial;
namespace RioJoy.Core.Tests.Serial;
///
/// In-memory for driving
/// in tests: enqueue inbound chunks, inspect outbound writes.
///
internal sealed class FakeTransport : IRioTransport
{
private readonly Channel _incoming = Channel.CreateUnbounded();
private readonly Channel _writes = Channel.CreateUnbounded();
public string Description => "fake";
/// Outbound writes, in order. Each call to WriteAsync yields one item.
public ChannelReader Writes => _writes.Reader;
/// Queue an inbound chunk for the receive loop to read.
public void Enqueue(params byte[] data) => _incoming.Writer.TryWrite(data);
/// Signal that no more inbound data will arrive (transport closed).
public void CompleteIncoming() => _incoming.Writer.TryComplete();
public async Task ReadAsync(byte[] buffer, CancellationToken cancellationToken)
{
while (await _incoming.Reader.WaitToReadAsync(cancellationToken).ConfigureAwait(false))
{
if (_incoming.Reader.TryRead(out byte[]? chunk))
{
Array.Copy(chunk, buffer, chunk.Length);
return chunk.Length;
}
}
return 0; // completed
}
public Task WriteAsync(byte[] data, CancellationToken cancellationToken)
{
_writes.Writer.TryWrite((byte[])data.Clone());
return Task.CompletedTask;
}
/// Read the next outbound write, failing if none arrives in time.
public async Task NextWriteAsync(TimeSpan? timeout = null)
{
using var cts = new CancellationTokenSource(timeout ?? TimeSpan.FromSeconds(5));
return await _writes.Reader.ReadAsync(cts.Token).ConfigureAwait(false);
}
public void Dispose() { }
}