4internal sealed class StreamImageDataSource : IImageDataSource
7 private readonly Stream _stream;
9 private readonly
bool _leaveOpen;
11 private readonly SemaphoreSlim _gate =
new(1, 1);
13 private bool _disposed;
18 public StreamImageDataSource(Stream stream,
bool leaveOpen)
20 ArgumentNullException.ThrowIfNull(stream);
21 if (!stream.CanRead || !stream.CanSeek)
23 throw new ArgumentException(
"An image stream must be readable and seekable.", nameof(stream));
27 _leaveOpen = leaveOpen;
28 Length = stream.Length;
32 public long Length {
get; }
35 public int Read(
long offset, Span<byte> destination)
37 ObjectDisposedException.ThrowIf(_disposed,
this);
41 _stream.Position = offset;
42 return _stream.Read(destination);
51 public async ValueTask<int> ReadAsync(
53 Memory<byte> destination,
54 CancellationToken cancellationToken)
56 ObjectDisposedException.ThrowIf(_disposed,
this);
57 await _gate.WaitAsync(cancellationToken).ConfigureAwait(
false);
60 _stream.Position = offset;
61 return await _stream.ReadAsync(destination, cancellationToken).ConfigureAwait(
false);
87 public async ValueTask DisposeAsync()
96 await _stream.DisposeAsync().ConfigureAwait(
false);