Skip to content

Commit 1dd2d6e

Browse files
Better error handling in action wrapper
1 parent bd6e58c commit 1dd2d6e

File tree

1 file changed

+33
-13
lines changed

1 file changed

+33
-13
lines changed

src/ImageSharp/Formats/ImageDecoder.cs

Lines changed: 33 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,7 @@ T PeformActionAndResetPosition(Stream s, long position)
181181
return action(memoryStream);
182182
}
183183

184-
internal static async Task<T> WithSeekableMemoryStreamAsync<T>(
184+
internal static Task<T> WithSeekableMemoryStreamAsync<T>(
185185
DecoderOptions options,
186186
Stream stream,
187187
Func<Stream, CancellationToken, T> action,
@@ -195,20 +195,31 @@ internal static async Task<T> WithSeekableMemoryStreamAsync<T>(
195195
throw new NotSupportedException("Cannot read from the stream.");
196196
}
197197

198-
T PeformActionAndResetPosition(Stream s, long position, CancellationToken ct)
198+
Task<T> PeformActionAndResetPosition(Stream s, long position, CancellationToken ct)
199199
{
200-
T result = action(s, ct);
201-
202-
// Issue #2259. Our buffered reads may have left the stream in an incorrect non-zero position.
203-
// Reset the position of the seekable stream if we did not read to the end to allow additional reads.
204-
// We check here that the input stream is seekable because it is not guaranteed to be so since
205-
// we always copy input streams of unknown type.
206-
if (stream.CanSeek && stream.Position != s.Position && s.Position != s.Length)
200+
try
207201
{
208-
stream.Position = position + s.Position;
202+
T result = action(s, ct);
203+
204+
// Issue #2259. Our buffered reads may have left the stream in an incorrect non-zero position.
205+
// Reset the position of the seekable stream if we did not read to the end to allow additional reads.
206+
// We check here that the input stream is seekable because it is not guaranteed to be so since
207+
// we always copy input streams of unknown type.
208+
if (stream.CanSeek && stream.Position != s.Position && s.Position != s.Length)
209+
{
210+
stream.Position = position + s.Position;
211+
}
212+
213+
return Task.FromResult(result);
214+
}
215+
catch (OperationCanceledException)
216+
{
217+
return Task.FromCanceled<T>(cancellationToken);
218+
}
219+
catch (Exception ex)
220+
{
221+
return Task.FromException<T>(ex);
209222
}
210-
211-
return result;
212223
}
213224

214225
// NOTE: We are explicitly not executing the action against the stream here as we do in WithSeekableStream() because that
@@ -224,11 +235,20 @@ T PeformActionAndResetPosition(Stream s, long position, CancellationToken ct)
224235
return PeformActionAndResetPosition(cms, cms.Position, cancellationToken);
225236
}
226237

238+
return CopyToMemoryStreamAndActionAsync(options, stream, PeformActionAndResetPosition, cancellationToken);
239+
}
240+
241+
private static async Task<T> CopyToMemoryStreamAndActionAsync<T>(
242+
DecoderOptions options,
243+
Stream stream,
244+
Func<Stream, long, CancellationToken, Task<T>> action,
245+
CancellationToken cancellationToken)
246+
{
227247
long position = stream.CanSeek ? stream.Position : 0;
228248
Configuration configuration = options.Configuration;
229249
using ChunkedMemoryStream memoryStream = new(configuration.MemoryAllocator);
230250
await stream.CopyToAsync(memoryStream, configuration.StreamProcessingBufferSize, cancellationToken).ConfigureAwait(false);
231251
memoryStream.Position = 0;
232-
return PeformActionAndResetPosition(memoryStream, position, cancellationToken);
252+
return await action(memoryStream, position, cancellationToken).ConfigureAwait(false);
233253
}
234254
}

0 commit comments

Comments
 (0)