BREAKING CHANGES
- A batch of one reply read as a sequence is now the batch, not the reply.
Vec<T>and tuples over a pipeline or a transaction retaining exactly one
command used to read that command's own reply; they now read a one-element
batch, as they already did above one retained command. A caller who queued a
single collection-returning command --pipeline.lrange(..).queue()read as
Vec<String>, or aBLPOPread as(String, String)-- now asks for
Vec<Vec<String>>and((String, String),), or keeps the old reading by
naming the reply's own type. Every non-sequence form is unchanged.
Fixed
- A pipeline or a transaction retaining exactly one reply reads as a collection.
Pipeline::execute::<Vec<T>>()failed withCannotParseSequencewhen the
forgetflags left a single reply, while the same code with two surviving
replies succeeded -- so a caller looping over a variable number of commands had
to special-case the count. A batch of one carries two readings, the sequence of
one and the reply itself, and the batch deserializer resolved them by picking
the reply unconditionally. It now resolves them the way serde already tells them
apart: the sequence forms answer for the batch, every other form is answered by
the lone reply.Transaction::executecarried the same shortcut and now goes
through the very same deserializer, so the two agree on every type. The same
defect also made(String,)unreadable on a one-command pipeline, which is
whatexamples/pipelining.rsshows; it now works.
Internal
-
EXEC's reply is read by the pipeline's batch deserializer. The transaction
had its ownDeserializeSeedandSeqAccessdeserializer duplicating what
RespBatchDeserializerdoes;EXEC's elements are now handed out as responses
of their own -- a refcount bump each, no byte copied -- and read as a batch.
A forgotten reply is dropped unread there as it already was in a pipeline,
errors included. -
into_collection_iterstates its bounds without an#[expect]. The head
increment is asaturating_add, so noarithmetic_side_effectswarning is
raised for the expectation to catch and the reasoning stays where the index is
computed. -
tape_memoryreads its nodes withas_chunks.chunks_exactwith a
constant size is whatclippy::chunks_exact_to_as_chunksnames; the array
chunks it yields also drop thetry_into().unwrap()each word went through.