static async Task <byte[]> readExactAsync (int count, Func <byte[], int, int, object> readFunc, ReadExactInfo info) { var timeouter = new Timeouter(info.MethodTimeout); var buffer = new byte[count]; var offset = 0; var totalBytesRead = 0; var remain = count; while (totalBytesRead != count) { var bytesRead = 0; var readInfo = readFunc(buffer, offset, remain); if (readInfo is Task <int> task) { bytesRead = await task; } else if (readInfo is int read) { bytesRead = read; } else { throw new NotSupportedException(); } totalBytesRead += bytesRead; offset = totalBytesRead; remain = count - totalBytesRead; if (bytesRead == 0 && info.ThrowIfZeroReceived) { throw new ReadExactZeroReceivedException(); } if (info.RetryDelay != 0) { await Task.Delay(info.RetryDelay).ConfigureAwait(false); } if ((info.TimeoutOnlyIfNothingWasRead && totalBytesRead == 0) || (!info.TimeoutOnlyIfNothingWasRead)) { timeouter.ThrowIfTimeout(() => new ReadExactTimeoutException(buffer.Take(totalBytesRead), count)); } } return(buffer); }
public static async Task <byte[]> ReadExactAsync(this Stream stream, int count, ReadExactInfo info, CancellationToken cancellation) { return(await readExactAsync(count, (a, b, c) => stream.ReadAsync(a, b, c, cancellation), info)); }