-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Rewrite ChunkedMemoryStream #6
base: release/3.1.x
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
5 file(s) reviewed, 9 comment(s)
Edit PR Review Bot Settings | Greptile
int offset = 0; | ||
int count = buffer.Length; | ||
while (count > 0) | ||
while (bytesToRead != 0 && this.currentChunk != this.memoryChunkBuffer.Length) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
logic: potential infinite loop if currentChunk reaches memoryChunkBuffer.Length but bytesToRead is still non-zero
int copyCount = Math.Min(count, chunkSize - this.writeOffset); | ||
buffer.Slice(offset, copyCount).CopyTo(chunkBuffer[this.writeOffset..]); | ||
// Write n bytes to the current chunk | ||
buffer.Slice(offset, n).CopyTo(chunk.Buffer.Slice(this.currentChunkIndex, n)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
logic: Buffer.Slice() may throw if currentChunkIndex + n exceeds the buffer length
// If the new position is greater than the length of the stream, set the position to the end of the stream | ||
if (offset > 0 && offset >= this.memoryChunkBuffer.Length) | ||
{ | ||
if (this.readOffset == chunkSize) | ||
{ | ||
// Exit if no more chunks are currently available | ||
if (this.readChunk.Next is null) | ||
{ | ||
break; | ||
} | ||
this.currentChunk = this.memoryChunkBuffer.ChunkCount - 1; | ||
this.currentChunkIndex = this.memoryChunkBuffer[this.currentChunk].Length - 1; | ||
return; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
logic: setting position to Length-1 when seeking beyond stream end differs from standard Stream behavior which allows seeking beyond end
while (offset != 0) | ||
{ | ||
int chunkLength = this.memoryChunkBuffer[currentChunkIndex].Length; | ||
if (offset < chunkLength) | ||
{ | ||
// Found the correct chunk and the corresponding index | ||
break; | ||
} | ||
|
||
int writeCount = chunkSize - this.readOffset; | ||
stream.Write(chunkBuffer.GetSpan(), this.readOffset, writeCount); | ||
this.readOffset = chunkSize; | ||
offset -= chunkLength; | ||
currentChunkIndex++; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
logic: will throw IndexOutOfRangeException if offset is larger than total chunk lengths
Prerequisites
Description
Fixes SixLabors#2806
ChunkedMemoryStream contained multiple writing bugs and was too costly to fix/maintain relative to performance benefits so I'm just ditching it.
Greptile Summary
Complete rewrite of ChunkedMemoryStream to fix critical bugs and improve non-seekable stream handling in ImageSharp's encoding pipeline.
ChunkedMemoryStream
to use a simpler List-based chunk management system instead of linked listsImageEncoder
to properly use chunked memory stream for non-seekable stream encodingawait using
inEncodeWithSeekableStreamAsync
NonSeekableStream
to correctly delegate write operations to underlying stream