github dahomey-technologies/rustis 0.24.0

5 hours ago

BREAKING CHANGES

The upgrade checklist. Each item is stated fully, with the reason it moved, in the
section it belongs to below.

  • A text reply that is not entirely an integer is now an error. Code reading a
    field into an integer target got the numeric prefix of whatever the field held
    -- 1.75 as 1, 12abc as 12 -- and now gets CannotParseInteger. Nothing
    changes for a value that is an integer; what changes is that a value that is not
    one stops being silently narrowed into one.

Added

  • i128 and u128 serialize as command arguments. A struct field of either
    type could be read out of a reply but not written into a command: the argument
    serializer had no 128-bit arm, so serde fell back to its default, which fails.
    hset on a struct holding a u128 returned an error naming a type the
    deserializer accepts, and the round trip a caller expects to be symmetric was
    not. All three writers -- the serializer, the argument counter, and the
    fast-path builder -- now format them through itoa like every other width.

Fixed

  • A text reply read as an integer is read whole or rejected. The wire
    deserializer parsed integers with atoi::atoi, which stops at the first byte
    that is not a digit and returns what it read: HGET on a field holding 1.75
    answered 1 for a u32 target, 12abc answered 12, and 0x10 answered 0
    -- a value the server never sent, indistinguishable from one it did. The crate
    rejects exactly this elsewhere, deliberately: double_to_int refuses to
    truncate a RESP3 double, and the ValueDeserializer parses through
    str::parse, so the two deserializers disagreed on every such reply and the
    path a caller took decided the answer. Integers now come from int_from_text,
    which requires every byte to be consumed and the last one to be a digit, so a
    leading remainder ( 12), a trailing one (12abc) and a lone sign (-) are
    all CannotParseInteger. An explicit + stays accepted, as RESP3 allows on an
    integer reply, and overflow was already rejected. The same rule now covers the
    digits behind a :, where a malformed integer frame was read as its prefix too.

  • The test suite builds on Windows. keep_alive_and_no_delay_are_applied
    read the keep-alive time back with socket2::SockRef::tcp_keepalive_time,
    which Windows has no equivalent for and socket2 therefore compiles only on the
    platforms that expose a getter. The whole lib test target failed to build
    with E0599, so no test ran at all -- cargo test on Windows was unusable,
    and every job in CI runs on ubuntu-latest, which is why nothing reported it.
    The assertion is now guarded by #[cfg(not(windows))]; the value is still set
    on Windows, and still asserted everywhere it can be read.

Added

  • A struct maps onto a hash, and the tests say so. hset takes any
    Serialize and hgetall returns any Deserialize, so a struct round-trips
    through a hash in two calls -- the argument serializer flattens it into
    field/value pairs, taking the field names from the struct's own, and the
    deserializer reads the reply back as a map. Nothing in the suite covered that
    path, which is the reason to write a hash from a struct at all, and nothing
    covered the details a caller trips on either: rename/rename_all decide the
    field names on the wire, an unknown field in the hash is skipped rather than
    fatal, a nested struct needs #[serde(flatten)] or a field of its own, and an
    Option field must carry skip_serializing_if -- a None serializes to no
    argument at all, leaving its field name paired with the next field's value.
    hset_hgetall_struct_of_primitives pins the wire text a hash actually holds
    (1 for a bool, 1.75 for an f32), since another client reads that text,
    and a_bulk_string_reads_into_every_primitive pins the other direction: every
    integer width, f32/f64 including inf and exponent notation, bool,
    char, String, Option, plus the eleven values that are rejected -- out of
    range, empty, or not that type -- because a hash field is a bulk string
    whatever it holds, and that single wire form has to reach every target.

Don't miss a new rustis release

NewReleases is sending notifications on new releases.