NdsForge.NET 1.0.1
Read, validate, edit, compare, and build Nintendo DS and DSi images from .NET
Loading...
Searching...
No Matches
ImageSliceStream.cs
1namespace NdsForge;
2
5internal sealed class ImageSliceStream : Stream
6{
8 private readonly IImageDataSource _source;
10 private readonly NdsRegion _region;
12 private long _position;
13
17 public ImageSliceStream(IImageDataSource source, NdsRegion region)
18 {
19 _source = source;
20 _region = region;
21 }
22
24 public override bool CanRead => true;
25
27 public override bool CanSeek => true;
28
30 public override bool CanWrite => false;
31
33 public override long Length => _region.Length;
34
36 public override long Position
37 {
38 get => _position;
39 set => _position = ValidatePosition(value);
40 }
41
43 public override int Read(byte[] buffer, int offset, int count) =>
44 Read(buffer.AsSpan(offset, count));
45
47 public override int Read(Span<byte> buffer)
48 {
49 int requested = (int)Math.Min(buffer.Length, Length - _position);
50 int count = _source.Read(_region.Offset + _position, buffer[..requested]);
51 _position += count;
52 return count;
53 }
54
56 public override async ValueTask<int> ReadAsync(
57 Memory<byte> buffer,
58 CancellationToken cancellationToken = default)
59 {
60 int requested = (int)Math.Min(buffer.Length, Length - _position);
61 int count = await _source.ReadAsync(
62 _region.Offset + _position,
63 buffer[..requested],
64 cancellationToken).ConfigureAwait(false);
65 _position += count;
66 return count;
67 }
68
70 public override long Seek(long offset, SeekOrigin origin)
71 {
72 long position = origin switch
73 {
74 SeekOrigin.Begin => offset,
75 SeekOrigin.Current => checked(_position + offset),
76 SeekOrigin.End => checked(Length + offset),
77 _ => throw new ArgumentOutOfRangeException(nameof(origin)),
78 };
79
80 return _position = ValidatePosition(position);
81 }
82
84 public override void Flush()
85 {
86 }
87
89 public override void SetLength(long value) => throw new NotSupportedException();
90
92 public override void Write(byte[] buffer, int offset, int count) => throw new NotSupportedException();
93
97 private long ValidatePosition(long value)
98 {
99 ArgumentOutOfRangeException.ThrowIfNegative(value);
100 if (value > Length)
101 {
102 throw new IOException("Cannot seek beyond the end of an image region.");
103 }
104
105 return value;
106 }
107}