5internal sealed class ImageSliceStream : Stream
8 private readonly IImageDataSource _source;
10 private readonly NdsRegion _region;
12 private long _position;
17 public ImageSliceStream(IImageDataSource source, NdsRegion region)
24 public override bool CanRead =>
true;
27 public override bool CanSeek =>
true;
30 public override bool CanWrite =>
false;
33 public override long Length => _region.Length;
36 public override long Position
39 set => _position = ValidatePosition(value);
43 public override int Read(
byte[] buffer,
int offset,
int count) =>
44 Read(buffer.AsSpan(offset, count));
47 public override int Read(Span<byte> buffer)
49 int requested = (int)Math.Min(buffer.Length, Length - _position);
50 int count = _source.Read(_region.Offset + _position, buffer[..requested]);
56 public override async ValueTask<int> ReadAsync(
58 CancellationToken cancellationToken =
default)
60 int requested = (int)Math.Min(buffer.Length, Length - _position);
61 int count = await _source.ReadAsync(
62 _region.Offset + _position,
64 cancellationToken).ConfigureAwait(
false);
70 public override long Seek(
long offset, SeekOrigin origin)
72 long position = origin
switch
74 SeekOrigin.Begin => offset,
75 SeekOrigin.Current => checked(_position + offset),
76 SeekOrigin.End => checked(Length + offset),
77 _ =>
throw new ArgumentOutOfRangeException(nameof(origin)),
80 return _position = ValidatePosition(position);
84 public override void Flush()
89 public override void SetLength(
long value) =>
throw new NotSupportedException();
92 public override void Write(
byte[] buffer,
int offset,
int count) =>
throw new NotSupportedException();
97 private long ValidatePosition(
long value)
99 ArgumentOutOfRangeException.ThrowIfNegative(value);
102 throw new IOException(
"Cannot seek beyond the end of an image region.");