You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
A draft of how to treat extensions. The main challenge is that the decoder assumes to be at particular states when calling next_frame_info, read_next_frame and read_into_buffer. Futhermore, the descriptor is returned as a struct but the image data is written into a buffer whose size must obey the size given by the descriptor. This is motivated by having some constraints on the order of chunks as seen in the spec:
The Grammar.
<GIF Data Stream> ::= Header <Logical Screen> <Data>* Trailer
<Logical Screen> ::= Logical Screen Descriptor [Global Color Table]
<Data> ::= <Graphic Block> |
<Special-Purpose Block>
<Graphic Block> ::= [Graphic Control Extension] <Graphic-Rendering Block>
<Graphic-Rendering Block> ::= <Table-Based Image> |
Plain Text Extension
[note: these must be consecutive]
<Table-Based Image> ::= Image Descriptor [Local Color Table] Image Data
<Special-Purpose Block> ::= Application Extension |
Comment Extension
There must be some amount of code flow to the caller between returning the desciptor and writing the data. And considering Rust's borrowing system it must allow the caller to prepare a mutable reference to a buffer. That is, it must not be borrow by the decoder when the transfer takes place.
Buffer extensions
Currently the interface of StreamingDecoder, but not really implemented or supported, has an option to store extensions and retrieve them later. This requires allocating some additional memory but any other interface is unchanged. We might make this a bit more precise by allowing specifying which extension to save, or a list of application identifiers. This does not require any change in control flow.
An iterator style
Implemented by gift. An iterator yields each block individually. This needs to be reconciled with the high-level interface that reads images into a buffer. We also need to either a) ensure that the input buffer contains a block fully or b) expose the partial block in the iterator or c) allocate all blocks as gift does. This essentially transfers control to the caller after every single sub-block or block.
The awkward thing is that we can not both borrow the target buffer and have the iterator be 'static. This effectively means we need to allocate image data as well.
The cursor style
Instead of yielding an independent item on iteration, produce items that reference into the decoder. This wouldn't be able to implement Iterator hence I call it cursor for now. The advantage is that we need not clone and allocate all items. Also all color tables and graphic blocks might be handled internally. It's somewhat questionable how this relates to the code flow transfer though. As said before we must yield to the caller after the desciptor.
Basically, the next method must somehow temporarily borrow any buffer it wants to write to. This currently refers to the image buffer so that we can effectively decode interlacing and maps. But what if we want to internally validate comments? Or the plain text extension? Both should contain ascii data, and it's mandatory for the latter.
The callback style
Store a Weak<dyn CallbackTrait + Send + Sync + 'static> and invoke those callbacks on fitting blocks. We need weak to ensure that there are no unwanted cycles, and the additional marker bounds to keep the current Send and Sync marker impls on the main decoder interface. We might combine this with the adaptor interface in giving the option for a temporary non-send or non-sync callback. The immediate drawback is that this requires an allocation.
The text was updated successfully, but these errors were encountered:
The cursor style is the only for which I couldn't come up with any immediate drawbacks. It's also mostly compatible with existing interfaces as they could call it with or without an image buffer, and discard any unexpected result. That's what they currently do internally.
A draft of how to treat extensions. The main challenge is that the decoder assumes to be at particular states when calling
next_frame_info
,read_next_frame
andread_into_buffer
. Futhermore, the descriptor is returned as a struct but the image data is written into a buffer whose size must obey the size given by the descriptor. This is motivated by having some constraints on the order of chunks as seen in the spec:There must be some amount of code flow to the caller between returning the desciptor and writing the data. And considering Rust's borrowing system it must allow the caller to prepare a mutable reference to a buffer. That is, it must not be borrow by the decoder when the transfer takes place.
Buffer extensions
Currently the interface of
StreamingDecoder
, but not really implemented or supported, has an option to store extensions and retrieve them later. This requires allocating some additional memory but any other interface is unchanged. We might make this a bit more precise by allowing specifying which extension to save, or a list of application identifiers. This does not require any change in control flow.An iterator style
Implemented by
gift
. An iterator yields each block individually. This needs to be reconciled with the high-level interface that reads images into a buffer. We also need to either a) ensure that the input buffer contains a block fully or b) expose the partial block in the iterator or c) allocate all blocks as gift does. This essentially transfers control to the caller after every single sub-block or block.The awkward thing is that we can not both borrow the target buffer and have the iterator be
'static
. This effectively means we need to allocate image data as well.The cursor style
Instead of yielding an independent item on iteration, produce items that reference into the decoder. This wouldn't be able to implement
Iterator
hence I call it cursor for now. The advantage is that we need not clone and allocate all items. Also all color tables and graphic blocks might be handled internally. It's somewhat questionable how this relates to the code flow transfer though. As said before we must yield to the caller after the desciptor.Basically, the
next
method must somehow temporarily borrow any buffer it wants to write to. This currently refers to the image buffer so that we can effectively decode interlacing and maps. But what if we want to internally validate comments? Or the plain text extension? Both should contain ascii data, and it's mandatory for the latter.The callback style
Store a
Weak<dyn CallbackTrait + Send + Sync + 'static>
and invoke those callbacks on fitting blocks. We need weak to ensure that there are no unwanted cycles, and the additional marker bounds to keep the currentSend
andSync
marker impls on the main decoder interface. We might combine this with the adaptor interface in giving the option for a temporary non-send or non-sync callback. The immediate drawback is that this requires an allocation.The text was updated successfully, but these errors were encountered: