Skip to main content

yo_kv/
zsets.rs

1//! The sorted set commands.
2//!
3//! One method per Redis command on [`Keyspace`], the same arrangement the string,
4//! set, hash and list commands use and for the same reason: a key belongs to the
5//! database and not to a type, so `ZADD` against a string has to be able to see
6//! that it is a string. The sorted set itself, and the choice between its two
7//! representations, is [`crate::zset`]. This file is what the wire and the
8//! embedded API both call.
9//!
10//! # Every range command is the same command
11//!
12//! There are nine ways to ask a sorted set for a run of members. `ZRANGE` alone
13//! has three, once `BYSCORE` and `BYLEX` are counted, and then `REV` doubles
14//! them and `ZREVRANGE`, `ZREVRANGEBYSCORE` and `ZREVRANGEBYLEX` exist as older
15//! spellings of the same thing. `ZRANGESTORE` is a tenth, and the three
16//! `ZREMRANGE` forms are three more, and `ZCOUNT` and `ZLEXCOUNT` are two of
17//! those with the walk left off.
18//!
19//! Writing fourteen of those separately is fourteen chances to get an exclusive
20//! bound or a negative index wrong in one of them. So there is one [`Query`],
21//! and every one of those commands is a `Query` turned into a [`Window`], which
22//! is a rank, a count and a direction. What a command does with the window is
23//! all that separates it from the others: walk it, count it, remove it, or walk
24//! it into another key.
25//!
26//! Two calls and not one, because the wire needs the count before it needs the
27//! members: a RESP array writes its length first, and a reply that collected the
28//! members into a `Vec` in order to count them would allocate on the read path,
29//! which is the thing `Y1` is about. So [`Keyspace::zwindow`] answers how many
30//! there are and [`Keyspace::zwalk`] hands them over one at a time. The memo in
31//! the keyspace means the second call does not resolve the key again.
32//!
33//! # The commands over more than one key
34//!
35//! `ZUNION`, `ZINTER`, `ZDIFF` and their three store forms all come through
36//! [`Keyspace::zsetop`] or [`Keyspace::zsetop_store`], because the only thing
37//! that separates them is which members survive and that is [`crate::zsetops`]'s
38//! decision, not this file's. What is decided here is which keys they are
39//! allowed to name. A plain set is a sorted set where every score is one, so
40//! `ZUNIONSTORE d 2 zs plain` is legal and every input resolves through
41//! `live_slot_either`. A key that is not there stays in place as
42//! [`Operand::Missing`] rather than being dropped, because `WEIGHTS` is
43//! positional and closing the gap would hand every later input the wrong
44//! weight.
45//!
46//! `ZINTERCARD` is not `ZINTER` with the members thrown away, because it can
47//! stop at its limit and never has to work out a single score.
48//!
49//! # Errors
50//!
51//! Every command here answers `WRONGTYPE` for a key holding something that is
52//! not a sorted set, and treats a missing key as an empty one, which between
53//! them cover every case because a key is a sorted set, or another type, or
54//! absent. The commands over several keys resolve every key before they build
55//! anything, so `ZUNIONSTORE d 2 z not-a-zset` leaves `d` alone rather than
56//! finding out too late.
57
58use yo_common::num::DIGITS_MAX;
59use yo_common::{Code, Error, Result};
60
61use crate::elem::Elements;
62use crate::keyspace::Keyspace;
63use crate::scan::Cursor;
64use crate::strings;
65use crate::value::{self, Kind};
66use crate::zset::{Added, Bound, Lex, Member, Zset};
67use crate::zsetops::{self, Aggregate, Op, Operand};
68
69/// Which members a `ZADD` is allowed to touch.
70#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
71pub enum Gate {
72    /// Add and update both. Plain `ZADD`.
73    #[default]
74    Always,
75    /// Only add members that are not there. `ZADD NX`.
76    IfMissing,
77    /// Only update members that are there. `ZADD XX`.
78    IfPresent,
79}
80
81/// Which way a `ZADD` is allowed to move a score it already has.
82#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
83pub enum Move {
84    /// Either way. Plain `ZADD`.
85    #[default]
86    Any,
87    /// Only up. `ZADD GT`.
88    Up,
89    /// Only down. `ZADD LT`.
90    Down,
91}
92
93/// What a `ZADD` was asked to do.
94///
95/// `NX` with `GT` or `LT` is refused by the parser rather than here, because a
96/// gate that only lets new members through and a rule about which way an
97/// existing score may move cannot both apply to the same member and Redis calls
98/// that a syntax error.
99#[derive(Debug, Clone, Copy, Default)]
100pub struct ZAdd {
101    /// `NX` or `XX`.
102    pub gate: Gate,
103    /// `GT` or `LT`.
104    pub only: Move,
105    /// `CH`, which counts changed scores as well as new members.
106    pub changed: bool,
107}
108
109/// Which end of a sorted set a command works from.
110#[derive(Debug, Clone, Copy, PartialEq, Eq)]
111pub enum From {
112    /// The lowest score. `ZPOPMIN`, and `ZMPOP MIN`.
113    Min,
114    /// The highest score. `ZPOPMAX`, and `ZMPOP MAX`.
115    Max,
116}
117
118/// What a range is measured in.
119#[derive(Debug, Clone, Copy)]
120pub enum By<'a> {
121    /// Positions, where a negative one counts from the end. `ZRANGE k 0 -1`.
122    Rank {
123        /// The first position, inclusive.
124        start: i64,
125        /// The last position, inclusive.
126        stop: i64,
127    },
128    /// Scores. `ZRANGEBYSCORE`, and `ZRANGE ... BYSCORE`.
129    Score {
130        /// The lowest score wanted.
131        min: Bound,
132        /// The highest score wanted.
133        max: Bound,
134    },
135    /// Members, which is only meaningful when every score is the same.
136    /// `ZRANGEBYLEX`, and `ZRANGE ... BYLEX`.
137    Lex {
138        /// The first member wanted.
139        min: Lex<'a>,
140        /// The last member wanted.
141        max: Lex<'a>,
142    },
143}
144
145/// A run of members, however it was asked for.
146///
147/// `min` and `max` are always the low end and the high end of the range itself,
148/// whichever order the command wrote them in. `REV` reverses the walk, it does
149/// not reverse the range, which is why `ZRANGEBYSCORE k 1 5` and
150/// `ZREVRANGEBYSCORE k 5 1` cover the same members.
151#[derive(Debug, Clone, Copy)]
152pub struct Query<'a> {
153    /// What the range is measured in.
154    pub by: By<'a>,
155    /// Walk from the high end down. `REV`, and the `ZREV` spellings.
156    pub rev: bool,
157    /// How many to skip once the range is found. `LIMIT`'s first number.
158    pub offset: usize,
159    /// How many to take, or all of them. `LIMIT`'s second number, where Redis's
160    /// negative count means all.
161    pub count: Option<usize>,
162}
163
164impl<'a> Query<'a> {
165    /// A plain `ZRANGE key start stop`.
166    #[must_use]
167    pub const fn rank(start: i64, stop: i64) -> Query<'a> {
168        Query {
169            by: By::Rank { start, stop },
170            rev: false,
171            offset: 0,
172            count: None,
173        }
174    }
175
176    /// A plain `ZRANGEBYSCORE key min max`.
177    #[must_use]
178    pub const fn score(min: Bound, max: Bound) -> Query<'a> {
179        Query {
180            by: By::Score { min, max },
181            rev: false,
182            offset: 0,
183            count: None,
184        }
185    }
186
187    /// A plain `ZRANGEBYLEX key min max`.
188    #[must_use]
189    pub const fn lex(min: Lex<'a>, max: Lex<'a>) -> Query<'a> {
190        Query {
191            by: By::Lex { min, max },
192            rev: false,
193            offset: 0,
194            count: None,
195        }
196    }
197
198    /// The same query walked from the other end.
199    #[must_use]
200    pub const fn rev(mut self, rev: bool) -> Query<'a> {
201        self.rev = rev;
202        self
203    }
204
205    /// The same query with a `LIMIT` on it.
206    #[must_use]
207    pub const fn limit(mut self, offset: usize, count: Option<usize>) -> Query<'a> {
208        self.offset = offset;
209        self.count = count;
210        self
211    }
212}
213
214/// Where a run of members starts, how long it is, and which way it goes.
215///
216/// This is what every range command reduces to, and it is a rank rather than a
217/// pair of members because the tree answers in ranks. `from` is the first member
218/// the walk hands over, so on a reverse walk it is the high end and the walk
219/// counts down.
220#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
221pub struct Window {
222    /// The rank the walk starts at.
223    pub from: usize,
224    /// How many members the walk hands over.
225    pub count: usize,
226    /// Whether the walk counts down.
227    pub rev: bool,
228}
229
230/// A score that is not a number, which no command may store.
231fn nan() -> Error {
232    Error::new(Code::Invalid, "resulting score is not a number (NaN)")
233}
234
235impl Keyspace {
236    /// `ZADD key [NX|XX] [GT|LT] [CH] score member [score member ...]`.
237    ///
238    /// Answers how many members were added, or how many were added or changed if
239    /// `CH` was given, which is the only thing `CH` does.
240    ///
241    /// The pairs arrive as an iterator and not a slice, the way `SADD`'s members
242    /// do, because the wire layer has them as positions in the connection's read
243    /// buffer and a slice would mean collecting them first. It is walked more
244    /// than once, which is why it has to be `Clone`.
245    pub fn zadd<'m, I>(&mut self, key: &[u8], pairs: I, opts: ZAdd) -> Result<usize>
246    where
247        I: Iterator<Item = (f64, &'m [u8])> + Clone,
248    {
249        for (score, m) in pairs.clone() {
250            strings::check_len(key, m.len())?;
251            if score.is_nan() {
252                return Err(nan());
253            }
254        }
255        let at = match self.zset_slot(key)? {
256            Some(at) => at,
257            None => {
258                // A key is not created for a `ZADD XX` that cannot add anything,
259                // and it is not created for an empty pair list either. Redis's
260                // parser rejects `ZADD k` before it gets this far, but the
261                // embedded API has no parser in front of it and an empty sorted
262                // set left behind would be a key that exists and holds nothing.
263                if opts.gate == Gate::IfPresent || pairs.clone().next().is_none() {
264                    return Ok(0);
265                }
266                self.new_zset(key)
267            }
268        };
269        let limits = self.zset_limits;
270        let z = self
271            .zsets
272            .get_mut(at)
273            .expect("the record points at its body");
274        let mut added = 0usize;
275        let mut changed = 0usize;
276        for (score, m) in pairs {
277            let Some(want) = gated(z, m, score, opts) else {
278                continue;
279            };
280            // The element table being full means twenty four million members in
281            // one key. Nothing was stored, so nothing is counted.
282            if z.add(m, score, &limits) == Added::Full {
283                continue;
284            }
285            match want {
286                Added::New => added += 1,
287                Added::Changed => changed += 1,
288                _ => {}
289            }
290        }
291        // A `ZADD XX` on a key that did not exist never got here, so the only
292        // way to be holding an empty sorted set is a pair list that turned out
293        // to be empty after the gate, and that key was ours to make.
294        if z.is_empty() {
295            self.drop_key(key);
296        }
297        Ok(if opts.changed { added + changed } else { added })
298    }
299
300    /// `ZADD key ... INCR score member`, and `ZINCRBY key increment member`.
301    ///
302    /// Answers the member's new score, or nothing at all if a gate refused it,
303    /// which is the nil `ZADD INCR` replies with and is why this is one method
304    /// rather than an `INCR` flag on [`Keyspace::zadd`] that would have to
305    /// return two different shapes.
306    ///
307    /// `ZINCRBY` is this with no gate, where the answer is never nil.
308    pub fn zincrby(
309        &mut self,
310        key: &[u8],
311        member: &[u8],
312        by: f64,
313        opts: ZAdd,
314    ) -> Result<Option<f64>> {
315        strings::check_len(key, member.len())?;
316        if by.is_nan() {
317            return Err(nan());
318        }
319        let at = match self.zset_slot(key)? {
320            Some(at) => at,
321            None => {
322                if opts.gate == Gate::IfPresent {
323                    return Ok(None);
324                }
325                self.new_zset(key)
326            }
327        };
328        let limits = self.zset_limits;
329        let z = self
330            .zsets
331            .get_mut(at)
332            .expect("the record points at its body");
333        let now = z.score(member);
334        let want = now.unwrap_or(0.0) + by;
335        // Infinity plus its opposite. Redis refuses this and leaves the score
336        // alone rather than storing a NaN nothing could ever compare against.
337        if want.is_nan() {
338            if z.is_empty() {
339                self.drop_key(key);
340            }
341            return Err(nan());
342        }
343        let allowed = match (now, opts.gate, opts.only) {
344            (Some(_), Gate::IfMissing, _) | (None, Gate::IfPresent, _) => false,
345            (Some(was), _, Move::Up) => want > was,
346            (Some(was), _, Move::Down) => want < was,
347            _ => true,
348        };
349        if !allowed || z.add(member, want, &limits) == Added::Full {
350            if z.is_empty() {
351                self.drop_key(key);
352            }
353            return Ok(None);
354        }
355        Ok(Some(want))
356    }
357
358    /// `ZCARD key`.
359    pub fn zcard(&mut self, key: &[u8]) -> Result<usize> {
360        Ok(match self.zset_slot(key)? {
361            Some(at) => self.zset_at(at).len(),
362            None => 0,
363        })
364    }
365
366    /// `ZSCORE key member`.
367    pub fn zscore(&mut self, key: &[u8], member: &[u8]) -> Result<Option<f64>> {
368        Ok(match self.zset_slot(key)? {
369            Some(at) => self.zset_at(at).score(member),
370            None => None,
371        })
372    }
373
374    /// `ZMSCORE key member [member ...]`, which is `ZSCORE` in bulk.
375    ///
376    /// One key lookup for the whole call rather than one per member, which is
377    /// the only reason the command exists.
378    pub fn zmscore<'m>(
379        &mut self,
380        key: &[u8],
381        members: impl Iterator<Item = &'m [u8]>,
382        out: &mut Vec<Option<f64>>,
383    ) -> Result<()> {
384        out.clear();
385        let Some(at) = self.zset_slot(key)? else {
386            out.extend(members.map(|_| None));
387            return Ok(());
388        };
389        let z = self.zset_at(at);
390        out.extend(members.map(|m| z.score(m)));
391        Ok(())
392    }
393
394    /// `ZREM key member [member ...]`. Answers how many were there.
395    ///
396    /// A sorted set that loses its last member loses its key too, because an
397    /// empty sorted set does not exist in Redis.
398    pub fn zrem<'m>(
399        &mut self,
400        key: &[u8],
401        members: impl Iterator<Item = &'m [u8]>,
402    ) -> Result<usize> {
403        let Some(at) = self.zset_slot(key)? else {
404            return Ok(0);
405        };
406        let z = self
407            .zsets
408            .get_mut(at)
409            .expect("the record points at its body");
410        let mut gone = 0;
411        for m in members {
412            if z.remove(m) {
413                gone += 1;
414            }
415        }
416        if z.is_empty() {
417            self.drop_key(key);
418        }
419        Ok(gone)
420    }
421
422    /// `ZRANK key member [WITHSCORE]`, and `ZREVRANK` with `rev` set.
423    ///
424    /// The score comes back whether it was asked for or not, because finding the
425    /// rank already read it and handing it over costs nothing.
426    pub fn zrank(&mut self, key: &[u8], member: &[u8], rev: bool) -> Result<Option<(usize, f64)>> {
427        let Some(at) = self.zset_slot(key)? else {
428            return Ok(None);
429        };
430        let z = self.zset_at(at);
431        let Some(rank) = z.rank(member) else {
432            return Ok(None);
433        };
434        let score = z.score(member).unwrap_or(0.0);
435        Ok(Some((if rev { z.len() - 1 - rank } else { rank }, score)))
436    }
437
438    /// How many members a query covers, and where they start.
439    ///
440    /// Every range command starts here. It is separate from [`Keyspace::zwalk`]
441    /// because a RESP array writes its length before its members, and a reply
442    /// that collected the members in order to count them would allocate on the
443    /// read path.
444    pub fn zwindow(&mut self, key: &[u8], q: &Query<'_>) -> Result<Window> {
445        let Some(at) = self.zset_slot(key)? else {
446            return Ok(Window::default());
447        };
448        Ok(window(self.zset_at(at), q))
449    }
450
451    /// Hand over the members a window covers, in order, without collecting them.
452    ///
453    /// The window is the caller's rather than the query's, so that a caller that
454    /// has already asked [`Keyspace::zwindow`] does not compute it twice, and so
455    /// that `ZRANGESTORE` can walk a window it has already narrowed.
456    pub fn zwalk<F>(&mut self, key: &[u8], w: Window, f: F) -> Result<()>
457    where
458        F: FnMut(Member<'_>, f64),
459    {
460        let Some(at) = self.zset_slot(key)? else {
461            return Ok(());
462        };
463        self.zset_at(at).walk(w.from, w.count, w.rev, f);
464        Ok(())
465    }
466
467    /// `ZCOUNT`, `ZLEXCOUNT`, and the count half of any other range command.
468    pub fn zcount(&mut self, key: &[u8], q: &Query<'_>) -> Result<usize> {
469        Ok(self.zwindow(key, q)?.count)
470    }
471
472    /// `ZREMRANGEBYRANK`, `ZREMRANGEBYSCORE` and `ZREMRANGEBYLEX`, which differ
473    /// only in what the query was measured in.
474    ///
475    /// Answers how many went. The window is taken out from its high end down, so
476    /// that every rank still to be removed is the rank it was when the window
477    /// was worked out.
478    pub fn zremrange(&mut self, key: &[u8], q: &Query<'_>) -> Result<usize> {
479        let Some(at) = self.zset_slot(key)? else {
480            return Ok(0);
481        };
482        let w = window(self.zset_at(at), q);
483        let z = self
484            .zsets
485            .get_mut(at)
486            .expect("the record points at its body");
487        // A reverse window starts at its high end, so normalise to the low one
488        // and then count down from the top of it either way.
489        let low = if w.rev { w.from + 1 - w.count } else { w.from };
490        for i in (0..w.count).rev() {
491            z.remove_at(low + i);
492        }
493        if z.is_empty() {
494            self.drop_key(key);
495        }
496        Ok(w.count)
497    }
498
499    /// `ZPOPMIN key [count]` and `ZPOPMAX key [count]`.
500    ///
501    /// Nothing is collected. The member at the end is handed to `f`, which
502    /// writes it wherever it is going, and only then is it removed, which is why
503    /// this does not allocate where `SPOP` has to.
504    pub fn zpop<F>(&mut self, key: &[u8], end: From, count: usize, mut f: F) -> Result<usize>
505    where
506        F: FnMut(Member<'_>, f64),
507    {
508        let Some(at) = self.zset_slot(key)? else {
509            return Ok(0);
510        };
511        let z = self
512            .zsets
513            .get_mut(at)
514            .expect("the record points at its body");
515        let count = count.min(z.len());
516        for _ in 0..count {
517            // Always rank zero or the last rank, because taking one out moves
518            // everything above it down and the next one to go is at the same
519            // place again.
520            let rank = if end == From::Min { 0 } else { z.len() - 1 };
521            let Some((m, s)) = z.at(rank) else { break };
522            f(m, s);
523            z.remove_at(rank);
524        }
525        if z.is_empty() {
526            self.drop_key(key);
527        }
528        Ok(count)
529    }
530
531    /// `ZPOPMIN key` and `ZPOPMAX key`, as an owned member for a caller that has
532    /// nowhere to write it yet.
533    ///
534    /// This is what `BZPOPMIN` needs: a worker that has been parked has no reply
535    /// buffer open at the moment the member becomes available, so this one has
536    /// to allocate where [`Keyspace::zpop`] does not.
537    pub fn zpop_one(&mut self, key: &[u8], end: From) -> Result<Option<(Vec<u8>, f64)>> {
538        let mut got = None;
539        let mut name = [0u8; yo_common::num::DIGITS_MAX];
540        self.zpop(key, end, 1, |m, s| {
541            got = Some((member_bytes(m, &mut name).to_vec(), s));
542        })?;
543        Ok(got)
544    }
545
546    /// `ZRANDMEMBER key [count]`.
547    ///
548    /// A positive count draws without replacement and answers at most as many as
549    /// there are, and a negative one draws with replacement and answers exactly
550    /// as many as asked for, which is Redis's rule and is why the count is
551    /// signed here rather than paired with a flag.
552    ///
553    /// The draw without replacement is a partial shuffle of the row numbers and
554    /// not a retry loop, because a retry loop on a count near the size of the set
555    /// spends most of its time drawing members it already has.
556    pub fn zrandmember<F>(&mut self, key: &[u8], count: i64, mut f: F) -> Result<usize>
557    where
558        F: FnMut(Member<'_>, f64),
559    {
560        let Some(at) = self.zset_slot(key)? else {
561            return Ok(0);
562        };
563        let len = self.zset_at(at).len();
564        if len == 0 || count == 0 {
565            return Ok(0);
566        }
567        if count < 0 {
568            let want = count.unsigned_abs() as usize;
569            for _ in 0..want {
570                let pick = self.rng.below(len);
571                let Some((m, s)) = self.zset_at(at).pick(pick) else {
572                    break;
573                };
574                f(m, s);
575            }
576            return Ok(want);
577        }
578        let want = (count as usize).min(len);
579        // Whole set, in storage order, which is what Redis does for a count at
580        // or over the size and which saves shuffling in order to hand back
581        // everything anyway.
582        if want == len {
583            for i in 0..len {
584                let Some((m, s)) = self.zset_at(at).pick(i) else {
585                    break;
586                };
587                f(m, s);
588            }
589            return Ok(len);
590        }
591        // The database's index buffer rather than a fresh `Vec`, for the reason
592        // the byte scratch exists: a partial shuffle needs somewhere to hold the
593        // permutation while it draws from it, and building that somewhere out of
594        // the allocator on every `ZRANDMEMBER` is a malloc and a free on a
595        // command a sampler sends in a loop. Taken out and put back, so an early
596        // return leaves it as it was found.
597        // `yo_alloc::high_water` because this is the buffer reaching a size it
598        // has not been asked for before, which happens once per largest sorted
599        // set the database has been sampled from and never again.
600        let mut rows = std::mem::take(&mut self.rows);
601        rows.clear();
602        yo_alloc::high_water(|| rows.extend(0..len));
603        for i in 0..want {
604            let pick = i + self.rng.below(len - i);
605            rows.swap(i, pick);
606            let Some((m, s)) = self.zset_at(at).pick(rows[i]) else {
607                break;
608            };
609            f(m, s);
610        }
611        self.rows = rows;
612        Ok(want)
613    }
614
615    /// `ZSCAN key cursor [COUNT count]`.
616    ///
617    /// A small sorted set comes back whole with a cursor of [`Cursor::END`], the
618    /// same guarantee `SSCAN` and `HSCAN` give, because a listpack has no stable
619    /// position to resume from and 128 members is not worth a resume.
620    pub fn zscan<F>(&mut self, key: &[u8], cursor: Cursor, count: usize, f: F) -> Result<Cursor>
621    where
622        F: FnMut(Member<'_>, f64),
623    {
624        let Some(at) = self.zset_slot(key)? else {
625            return Ok(Cursor::END);
626        };
627        Ok(self.zset_at(at).scan(cursor, count, f))
628    }
629
630    /// `ZUNION`, `ZINTER` and `ZDIFF`, which differ only in `op`.
631    ///
632    /// The members come out in rank order, which means the result has to be put
633    /// in order before any of it can be handed over, and that is what the return
634    /// value's ordering costs. `ZINTERCARD` exists precisely because counting
635    /// does not need any of that, and it does not come through here.
636    pub fn zsetop<'k, F>(
637        &mut self,
638        op: Op,
639        keys: impl Iterator<Item = &'k [u8]>,
640        weights: &[f64],
641        agg: Aggregate,
642        f: F,
643    ) -> Result<usize>
644    where
645        F: FnMut(Member<'_>, f64),
646    {
647        let slots = self.operand_slots(keys)?;
648        let got = zsetops::gather(op, &self.operands_of(&slots), weights, agg);
649        let limits = self.zset_limits;
650        let Some(z) = Zset::from_elements(got, &limits) else {
651            return Ok(0);
652        };
653        let len = z.len();
654        z.walk(0, len, false, f);
655        Ok(len)
656    }
657
658    /// `ZUNIONSTORE`, `ZINTERSTORE` and `ZDIFFSTORE`.
659    ///
660    /// The destination is allowed to be one of the sources, which is safe for
661    /// the reason `SINTERSTORE` gives: the result is built whole before the
662    /// destination is touched, so nothing here writes over a body that is still
663    /// being read.
664    pub fn zsetop_store<'k>(
665        &mut self,
666        op: Op,
667        destination: &[u8],
668        keys: impl Iterator<Item = &'k [u8]>,
669        weights: &[f64],
670        agg: Aggregate,
671    ) -> Result<usize> {
672        let slots = self.operand_slots(keys)?;
673        let got = zsetops::gather(op, &self.operands_of(&slots), weights, agg);
674        let limits = self.zset_limits;
675        Ok(self.put_zset(destination, Zset::from_elements(got, &limits)))
676    }
677
678    /// `ZINTERCARD numkeys key [key ...] [LIMIT limit]`.
679    ///
680    /// Nothing is stored and no score is worked out, and a limit stops the walk
681    /// as soon as it is reached, which is the only reason this is not `ZINTER`
682    /// with the members thrown away.
683    pub fn zintercard<'k>(
684        &mut self,
685        keys: impl Iterator<Item = &'k [u8]>,
686        limit: usize,
687    ) -> Result<usize> {
688        let slots = self.operand_slots(keys)?;
689        Ok(zsetops::intercard(&self.operands_of(&slots), limit))
690    }
691
692    /// `ZRANGESTORE destination source <the arguments of ZRANGE>`.
693    ///
694    /// The window is copied rather than moved, because the destination may be
695    /// the source and because the source keeps its members either way. An empty
696    /// window deletes the destination, which is what `ZRANGESTORE d s 5 1` does
697    /// and is the same rule every store form follows.
698    pub fn zrangestore(
699        &mut self,
700        destination: &[u8],
701        source: &[u8],
702        q: &Query<'_>,
703    ) -> Result<usize> {
704        let built = match self.zset_slot(source)? {
705            None => None,
706            Some(at) => {
707                let z = self.zset_at(at);
708                let w = window(z, q);
709                let mut got = Elements::with_capacity(w.count.max(16));
710                let mut digits = [0u8; DIGITS_MAX];
711                // In rank order whichever way the query walked, because the
712                // destination is a sorted set and puts them in score order
713                // regardless. `REV` decides which members are taken, not what
714                // order they end up in.
715                let from = if w.rev { w.from + 1 - w.count } else { w.from };
716                z.walk(from, w.count, false, |m, s| {
717                    let _ = got.insert(member_bytes(m, &mut digits), s);
718                });
719                let limits = self.zset_limits;
720                Zset::from_elements(got, &limits)
721            }
722        };
723        Ok(self.put_zset(destination, built))
724    }
725
726    /// Where each key is and what type it holds, keeping the ones that are not
727    /// there in place.
728    ///
729    /// In place and not dropped, because `WEIGHTS` is positional: a missing
730    /// second key still has a second weight, and closing the gap would hand
731    /// every later input the wrong one.
732    fn operand_slots<'k>(
733        &mut self,
734        keys: impl Iterator<Item = &'k [u8]>,
735    ) -> Result<Vec<Option<(Kind, u32)>>> {
736        let mut out = Vec::with_capacity(keys.size_hint().0);
737        for key in keys {
738            out.push(self.live_slot_either(key, Kind::Zset, Kind::Set)?);
739        }
740        Ok(out)
741    }
742
743    /// The bodies those slots point at, as things the algebra can ask questions
744    /// of.
745    fn operands_of(&self, slots: &[Option<(Kind, u32)>]) -> Vec<Operand<'_>> {
746        slots
747            .iter()
748            .map(|got| match got {
749                Some((Kind::Zset, at)) => Operand::Zset(self.zset_at(*at)),
750                Some((Kind::Set, at)) => {
751                    Operand::Set(self.sets.get(*at).expect("the record points at its body"))
752                }
753                _ => Operand::Missing,
754            })
755            .collect()
756    }
757
758    /// Put a sorted set under `key`, replacing whatever was there.
759    ///
760    /// Nothing means delete the key, because an empty sorted set does not exist.
761    /// That is what makes `ZINTERSTORE d a b` with an empty intersection delete
762    /// `d` and answer zero rather than leave something `EXISTS` says one for.
763    ///
764    /// Whatever the key held is freed first, through the one funnel, and any
765    /// deadline it had goes with it, because the value under the key is not the
766    /// value the expiry was set on.
767    pub(crate) fn put_zset(&mut self, key: &[u8], z: Option<Zset>) -> usize {
768        let Some(z) = z else {
769            self.drop_key(key);
770            return 0;
771        };
772        self.free_body(key);
773        let len = z.len();
774        let at = self.zsets.insert(z);
775        let record = value::slot_record_len(false);
776        self.write_rec(key, record, |out| {
777            value::write_slot_record(out, Kind::Zset, at, None);
778        });
779        self.bodies += 1;
780        len
781    }
782
783    /// The slot `key`'s sorted set is in, or `None` if there is no such key.
784    #[inline]
785    pub(crate) fn zset_slot(&mut self, key: &[u8]) -> Result<Option<u32>> {
786        self.live_slot(key, Kind::Zset)
787    }
788
789    /// The body in a slot the record pointed at.
790    ///
791    /// Panicking here means a record outlived its body, which is the bug the
792    /// two invariants in [`crate::sets`] are there to make impossible.
793    #[inline]
794    pub(crate) fn zset_at(&self, at: u32) -> &Zset {
795        self.zsets.get(at).expect("the record points at its body")
796    }
797
798    /// Make an empty sorted set under `key` and answer which slot it went in.
799    ///
800    /// No hint, unlike a set. A sorted set starts packed whatever is going into
801    /// it, and the first `ZADD` that crosses either threshold promotes it, so
802    /// counting the pairs in advance would only move the same work earlier.
803    fn new_zset(&mut self, key: &[u8]) -> u32 {
804        // The body and, every so often, the slab that holds it. See
805        // `yo_alloc::first_touch` for why this is the one allocation a command
806        // is allowed to make.
807        let at = yo_alloc::first_touch(|| self.zsets.insert(Zset::new()));
808        let len = value::slot_record_len(false);
809        self.write_rec(key, len, |out| {
810            value::write_slot_record(out, Kind::Zset, at, None);
811        });
812        self.bodies += 1;
813        at
814    }
815}
816
817/// What a `ZADD` of one pair would do, or nothing if a gate refuses it.
818///
819/// This is worked out before the add rather than from what the add answered,
820/// because `GT` and `LT` have to see the old score to know whether the new one
821/// is allowed at all, and by then the add has already stored it.
822fn gated(z: &Zset, member: &[u8], score: f64, opts: ZAdd) -> Option<Added> {
823    match z.score(member) {
824        None => match opts.gate {
825            Gate::IfPresent => None,
826            // A new member is added whatever `GT` or `LT` say, because there is
827            // no old score for them to be about.
828            _ => Some(Added::New),
829        },
830        Some(was) => {
831            if opts.gate == Gate::IfMissing {
832                return None;
833            }
834            let ok = match opts.only {
835                Move::Any => true,
836                Move::Up => score > was,
837                Move::Down => score < was,
838            };
839            if !ok {
840                return None;
841            }
842            // An unchanged score is not a change, which is what stops `CH` from
843            // counting a member that was written over with what it already had.
844            Some(if score == was {
845                Added::Same
846            } else {
847                Added::Changed
848            })
849        }
850    }
851}
852
853/// Turn a query into the run of ranks it covers.
854fn window(z: &Zset, q: &Query<'_>) -> Window {
855    let len = z.len();
856    let range = match q.by {
857        By::Rank { start, stop } => {
858            // A rank range is already in the direction it will be walked, so a
859            // reverse one counts its ends from the top rather than being found
860            // and then flipped.
861            let (from, count) = rank_span(start, stop, len);
862            if q.rev {
863                return apply_limit(
864                    Window {
865                        from: len - from - 1,
866                        count,
867                        rev: true,
868                    },
869                    q,
870                    true,
871                );
872            }
873            return apply_limit(
874                Window {
875                    from,
876                    count,
877                    rev: false,
878                },
879                q,
880                true,
881            );
882        }
883        By::Score { min, max } => z.window_by_score(min, max),
884        By::Lex { min, max } => z.window_by_lex(min, max),
885    };
886    let count = range.end - range.start;
887    let from = if q.rev {
888        range.end.saturating_sub(1)
889    } else {
890        range.start
891    };
892    apply_limit(
893        Window {
894            from,
895            count,
896            rev: q.rev,
897        },
898        q,
899        false,
900    )
901}
902
903/// Move a window along by `LIMIT`'s offset and cut it to its count.
904///
905/// `ZRANGE key 0 -1 REV LIMIT 1 2` is the second and third from the top, so the
906/// offset walks in the direction of the walk and not up the ranks.
907///
908/// A rank range has already had its ends clamped, and Redis does not accept a
909/// `LIMIT` on one anyway, so `skip` says to leave it alone rather than the
910/// caller passing an offset of zero and a count of none and hoping.
911fn apply_limit(w: Window, q: &Query<'_>, skip: bool) -> Window {
912    if skip {
913        return w;
914    }
915    let offset = q.offset.min(w.count);
916    let count = q.count.unwrap_or(usize::MAX).min(w.count - offset);
917    let from = if w.rev {
918        w.from.saturating_sub(offset)
919    } else {
920        w.from + offset
921    };
922    Window {
923        from,
924        count,
925        rev: w.rev,
926    }
927}
928
929/// Turn an inclusive `start` and `stop` into an offset from the front and a
930/// count, clamping every out of range case rather than erroring.
931///
932/// The same rule `LRANGE` uses, and the same reason: a start before the front is
933/// the front, a stop past the end is the end, and a start after the stop is
934/// nothing at all.
935fn rank_span(start: i64, stop: i64, len: usize) -> (usize, usize) {
936    if len == 0 {
937        return (0, 0);
938    }
939    let len = len as i64;
940    let from = if start < 0 {
941        (len + start).max(0)
942    } else {
943        start.min(len)
944    };
945    let to = if stop < 0 {
946        len + stop
947    } else {
948        stop.min(len - 1)
949    };
950    if to < from {
951        return (from as usize, 0);
952    }
953    (from as usize, (to - from + 1) as usize)
954}
955
956/// The bytes of a member, which for one the listpack stored as an integer are
957/// the caller's buffer.
958pub(crate) fn member_bytes<'a>(
959    m: Member<'a>,
960    digits: &'a mut [u8; yo_common::num::DIGITS_MAX],
961) -> &'a [u8] {
962    match m {
963        Member::Str(s) => s,
964        Member::Int(n) => yo_common::num::i64_digits(digits, n),
965    }
966}
967
968#[cfg(test)]
969mod tests {
970    use super::*;
971    use yo_common::num::DIGITS_MAX;
972
973    fn ks() -> Keyspace {
974        Keyspace::new()
975    }
976
977    /// Add a run of pairs the plain way.
978    fn add(k: &mut Keyspace, key: &[u8], pairs: &[(f64, &[u8])]) -> usize {
979        k.zadd(key, pairs.iter().copied(), ZAdd::default()).unwrap()
980    }
981
982    /// Every member a query covers, as names.
983    fn names(k: &mut Keyspace, key: &[u8], q: &Query<'_>) -> Vec<String> {
984        let w = k.zwindow(key, q).unwrap();
985        let mut out = Vec::new();
986        let mut digits = [0u8; DIGITS_MAX];
987        k.zwalk(key, w, |m, _| {
988            out.push(String::from_utf8(member_bytes(m, &mut digits).to_vec()).unwrap());
989        })
990        .unwrap();
991        assert_eq!(
992            out.len(),
993            w.count,
994            "the window said {} and the walk gave {}",
995            w.count,
996            out.len()
997        );
998        out
999    }
1000
1001    /// A positive count under the size of the set does a partial shuffle, and
1002    /// the permutation that needs used to be a fresh `Vec` every call. Sampling
1003    /// is a thing callers do in a loop, so the first call is allowed to grow the
1004    /// buffer and none after it may allocate at all.
1005    #[test]
1006    fn zrandmember_stops_allocating_once_its_buffer_is_grown() {
1007        let mut k = ks();
1008        add(
1009            &mut k,
1010            b"z",
1011            &[(1.0, b"a"), (2.0, b"b"), (3.0, b"c"), (4.0, b"d")],
1012        );
1013        k.zrandmember(b"z", 2, |_, _| {}).expect("a sorted set");
1014        let (_, allocs) = crate::tally::counted(|| {
1015            for _ in 0..100 {
1016                k.zrandmember(b"z", 2, |_, _| {}).expect("a sorted set");
1017            }
1018        });
1019        assert_eq!(
1020            allocs, 0,
1021            "zrandmember allocated {allocs} times in a hundred"
1022        );
1023    }
1024
1025    /// The buffer is put back on the way out, so the call after it sees a
1026    /// buffer rather than an empty one, and both answer with what they were
1027    /// asked for.
1028    #[test]
1029    fn zrandmember_hands_its_buffer_back() {
1030        let mut k = ks();
1031        add(&mut k, b"z", &[(1.0, b"a"), (2.0, b"b"), (3.0, b"c")]);
1032        for _ in 0..3 {
1033            let mut seen = Vec::new();
1034            let n = k
1035                .zrandmember(b"z", 2, |m, _| {
1036                    let mut digits = [0u8; DIGITS_MAX];
1037                    seen.push(String::from_utf8(member_bytes(m, &mut digits).to_vec()).unwrap());
1038                })
1039                .expect("a sorted set");
1040            assert_eq!(n, 2);
1041            assert_eq!(seen.len(), 2);
1042            assert_ne!(seen[0], seen[1], "a positive count draws without replacing");
1043        }
1044    }
1045
1046    #[test]
1047    fn a_missing_key_is_an_empty_sorted_set() {
1048        let mut k = ks();
1049        assert_eq!(k.zcard(b"nope").unwrap(), 0);
1050        assert_eq!(k.zscore(b"nope", b"m").unwrap(), None);
1051        assert_eq!(k.zrank(b"nope", b"m", false).unwrap(), None);
1052        assert_eq!(k.zrem(b"nope", [b"m".as_slice()].into_iter()).unwrap(), 0);
1053        assert_eq!(
1054            names(&mut k, b"nope", &Query::rank(0, -1)),
1055            Vec::<String>::new()
1056        );
1057        assert!(!k.exists(b"nope"));
1058    }
1059
1060    #[test]
1061    fn a_key_holding_something_else_is_a_wrongtype() {
1062        let mut k = ks();
1063        k.set(b"s", b"hello", strings::SetOptions::default())
1064            .unwrap();
1065        assert_eq!(k.zcard(b"s").unwrap_err().code(), Code::WrongType);
1066        assert_eq!(
1067            k.zadd(b"s", [(1.0, b"m".as_slice())].into_iter(), ZAdd::default())
1068                .unwrap_err()
1069                .code(),
1070            Code::WrongType
1071        );
1072        assert_eq!(k.zscore(b"s", b"m").unwrap_err().code(), Code::WrongType);
1073    }
1074
1075    #[test]
1076    fn adding_answers_how_many_were_new() {
1077        let mut k = ks();
1078        assert_eq!(add(&mut k, b"z", &[(1.0, b"a"), (2.0, b"b")]), 2);
1079        assert_eq!(add(&mut k, b"z", &[(1.0, b"a"), (3.0, b"c")]), 1);
1080        assert_eq!(k.zcard(b"z").unwrap(), 3);
1081        assert_eq!(k.zscore(b"z", b"c").unwrap(), Some(3.0));
1082        assert_eq!(k.kind_of(b"z").map(Kind::name), Some("zset"));
1083        assert_eq!(k.encoding_name(b"z"), Some("listpack"));
1084    }
1085
1086    #[test]
1087    fn the_ch_flag_counts_moved_scores_too() {
1088        let mut k = ks();
1089        add(&mut k, b"z", &[(1.0, b"a"), (2.0, b"b")]);
1090        let ch = ZAdd {
1091            changed: true,
1092            ..ZAdd::default()
1093        };
1094        // One score moved, one stayed, one member is new.
1095        let pairs = [
1096            (9.0, b"a".as_slice()),
1097            (2.0, b"b".as_slice()),
1098            (3.0, b"c".as_slice()),
1099        ];
1100        assert_eq!(k.zadd(b"z", pairs.into_iter(), ch).unwrap(), 2);
1101        assert_eq!(k.zadd(b"z", pairs.into_iter(), ZAdd::default()).unwrap(), 0);
1102    }
1103
1104    #[test]
1105    fn the_gates_let_the_right_members_through() {
1106        let mut k = ks();
1107        add(&mut k, b"z", &[(1.0, b"a")]);
1108        let nx = ZAdd {
1109            gate: Gate::IfMissing,
1110            ..ZAdd::default()
1111        };
1112        let xx = ZAdd {
1113            gate: Gate::IfPresent,
1114            ..ZAdd::default()
1115        };
1116        assert_eq!(
1117            k.zadd(b"z", [(5.0, b"a".as_slice())].into_iter(), nx)
1118                .unwrap(),
1119            0
1120        );
1121        assert_eq!(k.zscore(b"z", b"a").unwrap(), Some(1.0));
1122        assert_eq!(
1123            k.zadd(b"z", [(5.0, b"b".as_slice())].into_iter(), nx)
1124                .unwrap(),
1125            1
1126        );
1127        assert_eq!(
1128            k.zadd(b"z", [(7.0, b"c".as_slice())].into_iter(), xx)
1129                .unwrap(),
1130            0
1131        );
1132        assert_eq!(k.zscore(b"z", b"c").unwrap(), None);
1133        assert_eq!(
1134            k.zadd(b"z", [(7.0, b"a".as_slice())].into_iter(), xx)
1135                .unwrap(),
1136            0
1137        );
1138        assert_eq!(k.zscore(b"z", b"a").unwrap(), Some(7.0));
1139        // XX on a key that does not exist does not create it.
1140        assert_eq!(
1141            k.zadd(b"gone", [(1.0, b"a".as_slice())].into_iter(), xx)
1142                .unwrap(),
1143            0
1144        );
1145        assert!(!k.exists(b"gone"));
1146    }
1147
1148    #[test]
1149    fn gt_and_lt_only_move_a_score_one_way() {
1150        let mut k = ks();
1151        add(&mut k, b"z", &[(5.0, b"a")]);
1152        let gt = ZAdd {
1153            only: Move::Up,
1154            changed: true,
1155            ..ZAdd::default()
1156        };
1157        let lt = ZAdd {
1158            only: Move::Down,
1159            changed: true,
1160            ..ZAdd::default()
1161        };
1162        assert_eq!(
1163            k.zadd(b"z", [(3.0, b"a".as_slice())].into_iter(), gt)
1164                .unwrap(),
1165            0
1166        );
1167        assert_eq!(k.zscore(b"z", b"a").unwrap(), Some(5.0));
1168        assert_eq!(
1169            k.zadd(b"z", [(9.0, b"a".as_slice())].into_iter(), gt)
1170                .unwrap(),
1171            1
1172        );
1173        assert_eq!(k.zscore(b"z", b"a").unwrap(), Some(9.0));
1174        assert_eq!(
1175            k.zadd(b"z", [(9.0, b"a".as_slice())].into_iter(), lt)
1176                .unwrap(),
1177            0
1178        );
1179        assert_eq!(
1180            k.zadd(b"z", [(2.0, b"a".as_slice())].into_iter(), lt)
1181                .unwrap(),
1182            1
1183        );
1184        assert_eq!(k.zscore(b"z", b"a").unwrap(), Some(2.0));
1185        // A member that is not there is added whatever GT says.
1186        assert_eq!(
1187            k.zadd(b"z", [(1.0, b"new".as_slice())].into_iter(), gt)
1188                .unwrap(),
1189            1
1190        );
1191    }
1192
1193    #[test]
1194    fn incrementing_adds_to_what_is_there_or_to_nothing() {
1195        let mut k = ks();
1196        let plain = ZAdd::default();
1197        assert_eq!(k.zincrby(b"z", b"a", 5.0, plain).unwrap(), Some(5.0));
1198        assert_eq!(k.zincrby(b"z", b"a", -2.5, plain).unwrap(), Some(2.5));
1199        assert_eq!(k.zscore(b"z", b"a").unwrap(), Some(2.5));
1200        let nx = ZAdd {
1201            gate: Gate::IfMissing,
1202            ..ZAdd::default()
1203        };
1204        assert_eq!(k.zincrby(b"z", b"a", 1.0, nx).unwrap(), None);
1205        assert_eq!(k.zscore(b"z", b"a").unwrap(), Some(2.5));
1206        let xx = ZAdd {
1207            gate: Gate::IfPresent,
1208            ..ZAdd::default()
1209        };
1210        assert_eq!(k.zincrby(b"z", b"never", 1.0, xx).unwrap(), None);
1211        assert!(k.zscore(b"z", b"never").unwrap().is_none());
1212        let gt = ZAdd {
1213            only: Move::Up,
1214            ..ZAdd::default()
1215        };
1216        assert_eq!(k.zincrby(b"z", b"a", -1.0, gt).unwrap(), None);
1217        assert_eq!(k.zincrby(b"z", b"a", 1.0, gt).unwrap(), Some(3.5));
1218    }
1219
1220    #[test]
1221    fn a_score_that_is_not_a_number_is_refused() {
1222        let mut k = ks();
1223        let plain = ZAdd::default();
1224        assert_eq!(
1225            k.zadd(b"z", [(f64::NAN, b"a".as_slice())].into_iter(), plain)
1226                .unwrap_err()
1227                .code(),
1228            Code::Invalid
1229        );
1230        assert!(!k.exists(b"z"));
1231        k.zincrby(b"z", b"a", f64::INFINITY, plain).unwrap();
1232        let err = k.zincrby(b"z", b"a", f64::NEG_INFINITY, plain).unwrap_err();
1233        assert_eq!(err.code(), Code::Invalid);
1234        // The score is left exactly as it was rather than stored as a NaN.
1235        assert_eq!(k.zscore(b"z", b"a").unwrap(), Some(f64::INFINITY));
1236    }
1237
1238    #[test]
1239    fn a_sorted_set_that_loses_its_last_member_loses_its_key() {
1240        let mut k = ks();
1241        add(&mut k, b"z", &[(1.0, b"a"), (2.0, b"b")]);
1242        assert_eq!(
1243            k.zrem(b"z", [b"a".as_slice(), b"b".as_slice()].into_iter())
1244                .unwrap(),
1245            2
1246        );
1247        assert!(!k.exists(b"z"));
1248        assert_eq!(k.zcard(b"z").unwrap(), 0);
1249    }
1250
1251    #[test]
1252    fn ranks_count_from_both_ends() {
1253        let mut k = ks();
1254        add(&mut k, b"z", &[(1.0, b"a"), (2.0, b"b"), (3.0, b"c")]);
1255        assert_eq!(k.zrank(b"z", b"a", false).unwrap(), Some((0, 1.0)));
1256        assert_eq!(k.zrank(b"z", b"c", false).unwrap(), Some((2, 3.0)));
1257        assert_eq!(k.zrank(b"z", b"a", true).unwrap(), Some((2, 1.0)));
1258        assert_eq!(k.zrank(b"z", b"c", true).unwrap(), Some((0, 3.0)));
1259        assert_eq!(k.zrank(b"z", b"nope", false).unwrap(), None);
1260    }
1261
1262    #[test]
1263    fn a_rank_range_clamps_every_way_it_can_be_wrong() {
1264        let mut k = ks();
1265        add(&mut k, b"z", &[(1.0, b"a"), (2.0, b"b"), (3.0, b"c")]);
1266        assert_eq!(names(&mut k, b"z", &Query::rank(0, -1)), ["a", "b", "c"]);
1267        assert_eq!(names(&mut k, b"z", &Query::rank(1, 1)), ["b"]);
1268        assert_eq!(names(&mut k, b"z", &Query::rank(-2, -1)), ["b", "c"]);
1269        assert_eq!(names(&mut k, b"z", &Query::rank(-99, 99)), ["a", "b", "c"]);
1270        assert_eq!(
1271            names(&mut k, b"z", &Query::rank(2, 1)),
1272            Vec::<String>::new()
1273        );
1274        assert_eq!(
1275            names(&mut k, b"z", &Query::rank(5, 9)),
1276            Vec::<String>::new()
1277        );
1278        assert_eq!(
1279            names(&mut k, b"z", &Query::rank(0, -1).rev(true)),
1280            ["c", "b", "a"]
1281        );
1282        assert_eq!(
1283            names(&mut k, b"z", &Query::rank(0, 1).rev(true)),
1284            ["c", "b"]
1285        );
1286    }
1287
1288    #[test]
1289    fn a_score_range_walks_either_way_and_takes_a_limit() {
1290        let mut k = ks();
1291        add(
1292            &mut k,
1293            b"z",
1294            &[(1.0, b"a"), (2.0, b"b"), (3.0, b"c"), (4.0, b"d")],
1295        );
1296        let all = Query::score(
1297            Bound::closed(f64::NEG_INFINITY),
1298            Bound::closed(f64::INFINITY),
1299        );
1300        assert_eq!(names(&mut k, b"z", &all), ["a", "b", "c", "d"]);
1301        assert_eq!(names(&mut k, b"z", &all.rev(true)), ["d", "c", "b", "a"]);
1302        assert_eq!(
1303            names(
1304                &mut k,
1305                b"z",
1306                &Query::score(Bound::closed(2.0), Bound::closed(3.0))
1307            ),
1308            ["b", "c"]
1309        );
1310        assert_eq!(
1311            names(
1312                &mut k,
1313                b"z",
1314                &Query::score(Bound::open(2.0), Bound::open(4.0))
1315            ),
1316            ["c"]
1317        );
1318        // LIMIT walks in the direction of the walk, so the reverse one skips
1319        // from the top.
1320        assert_eq!(names(&mut k, b"z", &all.limit(1, Some(2))), ["b", "c"]);
1321        assert_eq!(
1322            names(&mut k, b"z", &all.rev(true).limit(1, Some(2))),
1323            ["c", "b"]
1324        );
1325        assert_eq!(
1326            names(&mut k, b"z", &all.limit(9, Some(2))),
1327            Vec::<String>::new()
1328        );
1329        assert_eq!(names(&mut k, b"z", &all.limit(2, None)), ["c", "d"]);
1330        assert_eq!(
1331            k.zcount(b"z", &Query::score(Bound::closed(2.0), Bound::closed(3.0)))
1332                .unwrap(),
1333            2
1334        );
1335    }
1336
1337    #[test]
1338    fn a_member_range_orders_by_member_when_every_score_is_the_same() {
1339        let mut k = ks();
1340        add(
1341            &mut k,
1342            b"z",
1343            &[(0.0, b"a"), (0.0, b"b"), (0.0, b"c"), (0.0, b"d")],
1344        );
1345        assert_eq!(
1346            names(&mut k, b"z", &Query::lex(Lex::Min, Lex::Max)),
1347            ["a", "b", "c", "d"]
1348        );
1349        assert_eq!(
1350            names(&mut k, b"z", &Query::lex(Lex::Incl(b"b"), Lex::Incl(b"c"))),
1351            ["b", "c"]
1352        );
1353        assert_eq!(
1354            names(&mut k, b"z", &Query::lex(Lex::Excl(b"a"), Lex::Excl(b"d"))),
1355            ["b", "c"]
1356        );
1357        assert_eq!(
1358            names(&mut k, b"z", &Query::lex(Lex::Min, Lex::Max).rev(true)),
1359            ["d", "c", "b", "a"]
1360        );
1361        assert_eq!(
1362            k.zcount(b"z", &Query::lex(Lex::Incl(b"b"), Lex::Max))
1363                .unwrap(),
1364            3
1365        );
1366    }
1367
1368    #[test]
1369    fn removing_a_range_takes_out_exactly_what_the_walk_would_have_given() {
1370        let mut k = ks();
1371        for (q, left) in [
1372            (Query::rank(0, 1), vec!["c", "d", "e"]),
1373            (Query::rank(-2, -1), vec!["a", "b", "c"]),
1374            (
1375                Query::score(Bound::closed(2.0), Bound::closed(4.0)),
1376                vec!["a", "e"],
1377            ),
1378            (
1379                Query::lex(Lex::Incl(b"b"), Lex::Excl(b"d")),
1380                vec!["a", "d", "e"],
1381            ),
1382            (Query::rank(0, -1).rev(true), vec![]),
1383        ] {
1384            k.del(b"z");
1385            add(
1386                &mut k,
1387                b"z",
1388                &[
1389                    (1.0, b"a"),
1390                    (2.0, b"b"),
1391                    (3.0, b"c"),
1392                    (4.0, b"d"),
1393                    (5.0, b"e"),
1394                ],
1395            );
1396            let want = names(&mut k, b"z", &q).len();
1397            assert_eq!(k.zremrange(b"z", &q).unwrap(), want, "{q:?}");
1398            assert_eq!(names(&mut k, b"z", &Query::rank(0, -1)), left, "{q:?}");
1399        }
1400        // The key went with the last member.
1401        assert!(!k.exists(b"z"));
1402    }
1403
1404    #[test]
1405    fn popping_takes_from_the_end_it_was_told_to() {
1406        let mut k = ks();
1407        add(&mut k, b"z", &[(1.0, b"a"), (2.0, b"b"), (3.0, b"c")]);
1408        let mut got = Vec::new();
1409        let mut digits = [0u8; DIGITS_MAX];
1410        k.zpop(b"z", From::Min, 2, |m, s| {
1411            got.push((
1412                String::from_utf8(member_bytes(m, &mut digits).to_vec()).unwrap(),
1413                s,
1414            ));
1415        })
1416        .unwrap();
1417        assert_eq!(got, [("a".to_string(), 1.0), ("b".to_string(), 2.0)]);
1418        assert_eq!(
1419            k.zpop_one(b"z", From::Max).unwrap(),
1420            Some((b"c".to_vec(), 3.0))
1421        );
1422        assert!(!k.exists(b"z"));
1423        // A count past the end takes what there is and no more.
1424        add(&mut k, b"z", &[(1.0, b"a")]);
1425        assert_eq!(k.zpop(b"z", From::Max, 99, |_, _| {}).unwrap(), 1);
1426        assert!(!k.exists(b"z"));
1427        assert_eq!(k.zpop_one(b"z", From::Min).unwrap(), None);
1428    }
1429
1430    #[test]
1431    fn a_random_draw_is_with_or_without_replacement_by_the_sign_of_the_count() {
1432        let mut k = ks();
1433        add(&mut k, b"z", &[(1.0, b"a"), (2.0, b"b"), (3.0, b"c")]);
1434        let mut digits = [0u8; DIGITS_MAX];
1435        let mut seen = Vec::new();
1436        k.zrandmember(b"z", 2, |m, _| {
1437            seen.push(String::from_utf8(member_bytes(m, &mut digits).to_vec()).unwrap());
1438        })
1439        .unwrap();
1440        assert_eq!(seen.len(), 2);
1441        seen.sort();
1442        seen.dedup();
1443        assert_eq!(seen.len(), 2, "a positive count does not repeat a member");
1444        // A count past the size is the whole set and not a repeat of it.
1445        let mut all = Vec::new();
1446        k.zrandmember(b"z", 99, |m, _| {
1447            all.push(String::from_utf8(member_bytes(m, &mut digits).to_vec()).unwrap());
1448        })
1449        .unwrap();
1450        all.sort();
1451        assert_eq!(all, ["a", "b", "c"]);
1452        // A negative count answers exactly as many as asked for and may repeat.
1453        let mut many = 0;
1454        k.zrandmember(b"z", -10, |_, _| many += 1).unwrap();
1455        assert_eq!(many, 10);
1456        assert_eq!(k.zrandmember(b"nope", 3, |_, _| {}).unwrap(), 0);
1457    }
1458
1459    #[test]
1460    fn a_scan_of_either_band_walks_every_member_once() {
1461        let mut k = ks();
1462        for entries in [8usize, 4096] {
1463            k.del(b"z");
1464            let pairs: Vec<(f64, Vec<u8>)> = (0..entries)
1465                .map(|i| (i as f64, format!("m{i:05}").into_bytes()))
1466                .collect();
1467            k.zadd(
1468                b"z",
1469                pairs.iter().map(|(s, m)| (*s, m.as_slice())),
1470                ZAdd::default(),
1471            )
1472            .unwrap();
1473            let mut seen = Vec::new();
1474            let mut digits = [0u8; DIGITS_MAX];
1475            let mut cursor = Cursor::START;
1476            loop {
1477                cursor = k
1478                    .zscan(b"z", cursor, 16, |m, _| {
1479                        seen.push(
1480                            String::from_utf8(member_bytes(m, &mut digits).to_vec()).unwrap(),
1481                        );
1482                    })
1483                    .unwrap();
1484                if cursor.is_end() {
1485                    break;
1486                }
1487            }
1488            seen.sort();
1489            seen.dedup();
1490            assert_eq!(seen.len(), entries, "{entries} members");
1491        }
1492    }
1493
1494    #[test]
1495    fn a_big_sorted_set_promotes_and_still_answers_every_rank() {
1496        let mut k = ks();
1497        let pairs: Vec<(f64, Vec<u8>)> = (0..5_000)
1498            .map(|i| (f64::from(i), format!("m{i:05}").into_bytes()))
1499            .collect();
1500        assert_eq!(
1501            k.zadd(
1502                b"z",
1503                pairs.iter().map(|(s, m)| (*s, m.as_slice())),
1504                ZAdd::default()
1505            )
1506            .unwrap(),
1507            5_000
1508        );
1509        assert_eq!(k.encoding_name(b"z"), Some("skiplist"));
1510        assert_eq!(k.zcard(b"z").unwrap(), 5_000);
1511        assert_eq!(
1512            k.zrank(b"z", b"m02500", false).unwrap(),
1513            Some((2_500, 2500.0))
1514        );
1515        let q = Query::score(Bound::closed(1000.0), Bound::open(1010.0));
1516        assert_eq!(k.zcount(b"z", &q).unwrap(), 10);
1517        assert_eq!(
1518            names(&mut k, b"z", &q).first().map(String::as_str),
1519            Some("m01000")
1520        );
1521        // Everything still lines up after a few thousand removals.
1522        assert_eq!(k.zremrange(b"z", &Query::rank(0, 2_499)).unwrap(), 2_500);
1523        assert_eq!(k.zcard(b"z").unwrap(), 2_500);
1524        assert_eq!(k.zrank(b"z", b"m02500", false).unwrap(), Some((0, 2500.0)));
1525        assert_eq!(k.zrank(b"z", b"m00000", false).unwrap(), None);
1526    }
1527
1528    #[test]
1529    fn a_deadline_on_a_sorted_set_leaves_its_members_alone() {
1530        let mut k = ks();
1531        add(&mut k, b"z", &[(1.0, b"a"), (2.0, b"b")]);
1532        assert!(k.set_expiry(b"z", Some(u64::MAX / 2)));
1533        assert_eq!(k.zcard(b"z").unwrap(), 2);
1534        assert_eq!(k.zscore(b"z", b"b").unwrap(), Some(2.0));
1535        assert!(k.set_expiry(b"z", None));
1536        assert_eq!(k.zcard(b"z").unwrap(), 2);
1537    }
1538
1539    #[test]
1540    fn writing_a_string_over_a_sorted_set_gives_its_body_back() {
1541        let mut k = ks();
1542        add(&mut k, b"z", &[(1.0, b"a")]);
1543        let held = k.memory_bytes();
1544        k.set(b"z", b"now a string", strings::SetOptions::default())
1545            .unwrap();
1546        assert_eq!(k.kind_of(b"z").map(Kind::name), Some("string"));
1547        assert!(
1548            k.memory_bytes() < held,
1549            "the sorted set's body was not freed"
1550        );
1551    }
1552
1553    /// Everything in a key, in rank order, as pairs.
1554    fn all(k: &mut Keyspace, key: &[u8]) -> Vec<(String, f64)> {
1555        let q = Query::rank(0, -1);
1556        let w = k.zwindow(key, &q).unwrap();
1557        let mut out = Vec::new();
1558        let mut digits = [0u8; DIGITS_MAX];
1559        k.zwalk(key, w, |m, s| {
1560            out.push((
1561                String::from_utf8(member_bytes(m, &mut digits).to_vec()).unwrap(),
1562                s,
1563            ));
1564        })
1565        .unwrap();
1566        out
1567    }
1568
1569    /// What one of the non storing forms answers, in the order it answered.
1570    fn got(
1571        k: &mut Keyspace,
1572        op: Op,
1573        keys: &[&[u8]],
1574        weights: &[f64],
1575        agg: Aggregate,
1576    ) -> Vec<(String, f64)> {
1577        let mut out = Vec::new();
1578        let mut digits = [0u8; DIGITS_MAX];
1579        let n = k
1580            .zsetop(op, keys.iter().copied(), weights, agg, |m, s| {
1581                out.push((
1582                    String::from_utf8(member_bytes(m, &mut digits).to_vec()).unwrap(),
1583                    s,
1584                ));
1585            })
1586            .unwrap();
1587        assert_eq!(out.len(), n, "the count and the walk disagree");
1588        out
1589    }
1590
1591    #[test]
1592    fn a_union_adds_the_scores_of_a_member_that_is_in_both() {
1593        let mut k = ks();
1594        add(&mut k, b"a", &[(1.0, b"x"), (2.0, b"y")]);
1595        add(&mut k, b"b", &[(10.0, b"y"), (3.0, b"z")]);
1596        assert_eq!(
1597            got(&mut k, Op::Union, &[b"a", b"b"], &[], Aggregate::Sum),
1598            [("x".into(), 1.0), ("z".into(), 3.0), ("y".into(), 12.0)]
1599        );
1600    }
1601
1602    #[test]
1603    fn an_intersection_keeps_only_what_every_input_has() {
1604        let mut k = ks();
1605        add(&mut k, b"a", &[(1.0, b"x"), (2.0, b"y"), (3.0, b"z")]);
1606        add(&mut k, b"b", &[(5.0, b"y"), (5.0, b"z")]);
1607        add(&mut k, b"c", &[(7.0, b"z")]);
1608        assert_eq!(
1609            got(&mut k, Op::Inter, &[b"a", b"b", b"c"], &[], Aggregate::Sum),
1610            [("z".into(), 15.0)]
1611        );
1612        assert_eq!(
1613            got(&mut k, Op::Inter, &[b"a", b"b", b"c"], &[], Aggregate::Min),
1614            [("z".into(), 3.0)]
1615        );
1616        assert_eq!(
1617            got(&mut k, Op::Inter, &[b"a", b"b", b"c"], &[], Aggregate::Max),
1618            [("z".into(), 7.0)]
1619        );
1620    }
1621
1622    #[test]
1623    fn a_difference_takes_the_first_input_and_removes_the_rest() {
1624        let mut k = ks();
1625        add(&mut k, b"a", &[(1.0, b"x"), (2.0, b"y"), (3.0, b"z")]);
1626        add(&mut k, b"b", &[(99.0, b"y")]);
1627        assert_eq!(
1628            got(&mut k, Op::Diff, &[b"a", b"b"], &[], Aggregate::Sum),
1629            [("x".into(), 1.0), ("z".into(), 3.0)]
1630        );
1631    }
1632
1633    #[test]
1634    fn a_missing_key_keeps_its_place_so_the_weights_stay_lined_up() {
1635        let mut k = ks();
1636        add(&mut k, b"a", &[(1.0, b"x")]);
1637        add(&mut k, b"c", &[(1.0, b"x")]);
1638        // The second weight belongs to the key that is not there, and the third
1639        // to `c`. Dropping the gap would give `c` the 10 and answer 11.
1640        let out = got(
1641            &mut k,
1642            Op::Union,
1643            &[b"a", b"gone", b"c"],
1644            &[2.0, 10.0, 3.0],
1645            Aggregate::Sum,
1646        );
1647        assert_eq!(out, [("x".into(), 5.0)]);
1648    }
1649
1650    #[test]
1651    fn a_plain_set_counts_as_every_score_being_one() {
1652        let mut k = ks();
1653        add(&mut k, b"z", &[(5.0, b"x")]);
1654        k.sadd(b"s", [b"x".as_slice(), b"y".as_slice()].into_iter())
1655            .unwrap();
1656        assert_eq!(
1657            got(&mut k, Op::Union, &[b"z", b"s"], &[], Aggregate::Sum),
1658            [("y".into(), 1.0), ("x".into(), 6.0)]
1659        );
1660        assert_eq!(
1661            got(&mut k, Op::Inter, &[b"z", b"s"], &[], Aggregate::Min),
1662            [("x".into(), 1.0)]
1663        );
1664    }
1665
1666    #[test]
1667    fn a_store_writes_the_result_and_answers_its_size() {
1668        let mut k = ks();
1669        add(&mut k, b"a", &[(1.0, b"x"), (2.0, b"y")]);
1670        add(&mut k, b"b", &[(10.0, b"y")]);
1671        assert_eq!(
1672            k.zsetop_store(
1673                Op::Union,
1674                b"d",
1675                [b"a".as_slice(), b"b".as_slice()].into_iter(),
1676                &[],
1677                Aggregate::Sum
1678            )
1679            .unwrap(),
1680            2
1681        );
1682        assert_eq!(all(&mut k, b"d"), [("x".into(), 1.0), ("y".into(), 12.0)]);
1683        assert_eq!(k.zscore(b"d", b"y").unwrap(), Some(12.0));
1684        assert_eq!(k.zrank(b"d", b"y", false).unwrap(), Some((1, 12.0)));
1685    }
1686
1687    #[test]
1688    fn a_store_onto_one_of_its_own_sources_still_reads_the_old_body() {
1689        let mut k = ks();
1690        add(&mut k, b"a", &[(1.0, b"x"), (2.0, b"y")]);
1691        add(&mut k, b"b", &[(10.0, b"y")]);
1692        assert_eq!(
1693            k.zsetop_store(
1694                Op::Union,
1695                b"a",
1696                [b"a".as_slice(), b"b".as_slice()].into_iter(),
1697                &[],
1698                Aggregate::Sum
1699            )
1700            .unwrap(),
1701            2
1702        );
1703        assert_eq!(all(&mut k, b"a"), [("x".into(), 1.0), ("y".into(), 12.0)]);
1704    }
1705
1706    #[test]
1707    fn a_store_with_nothing_in_it_deletes_the_destination() {
1708        let mut k = ks();
1709        add(&mut k, b"a", &[(1.0, b"x")]);
1710        add(&mut k, b"b", &[(1.0, b"y")]);
1711        add(&mut k, b"d", &[(1.0, b"old")]);
1712        assert_eq!(
1713            k.zsetop_store(
1714                Op::Inter,
1715                b"d",
1716                [b"a".as_slice(), b"b".as_slice()].into_iter(),
1717                &[],
1718                Aggregate::Sum
1719            )
1720            .unwrap(),
1721            0
1722        );
1723        assert!(!k.exists(b"d"));
1724    }
1725
1726    #[test]
1727    fn a_store_clears_the_deadline_the_destination_was_carrying() {
1728        let mut k = ks();
1729        add(&mut k, b"a", &[(1.0, b"x")]);
1730        add(&mut k, b"d", &[(1.0, b"old")]);
1731        assert!(k.set_expiry(b"d", Some(u64::MAX / 2)));
1732        k.zsetop_store(
1733            Op::Union,
1734            b"d",
1735            [b"a".as_slice()].into_iter(),
1736            &[],
1737            Aggregate::Sum,
1738        )
1739        .unwrap();
1740        assert_eq!(all(&mut k, b"d"), [("x".into(), 1.0)]);
1741        assert_eq!(k.expire_at(b"d"), None);
1742    }
1743
1744    #[test]
1745    fn the_algebra_refuses_a_key_holding_something_that_is_neither() {
1746        let mut k = ks();
1747        add(&mut k, b"a", &[(1.0, b"x")]);
1748        k.set(b"s", b"hello", strings::SetOptions::default())
1749            .unwrap();
1750        assert_eq!(
1751            k.zsetop(
1752                Op::Union,
1753                [b"a".as_slice(), b"s".as_slice()].into_iter(),
1754                &[],
1755                Aggregate::Sum,
1756                |_, _| {}
1757            )
1758            .unwrap_err()
1759            .code(),
1760            Code::WrongType
1761        );
1762        // And the destination is untouched, because the keys are all resolved
1763        // before anything is built.
1764        assert!(!k.exists(b"d"));
1765        assert_eq!(
1766            k.zsetop_store(
1767                Op::Union,
1768                b"d",
1769                [b"a".as_slice(), b"s".as_slice()].into_iter(),
1770                &[],
1771                Aggregate::Sum
1772            )
1773            .unwrap_err()
1774            .code(),
1775            Code::WrongType
1776        );
1777        assert!(!k.exists(b"d"));
1778    }
1779
1780    #[test]
1781    fn intercard_counts_without_building_anything_and_stops_at_the_limit() {
1782        let mut k = ks();
1783        add(
1784            &mut k,
1785            b"a",
1786            &[(1.0, b"w"), (2.0, b"x"), (3.0, b"y"), (4.0, b"z")],
1787        );
1788        add(&mut k, b"b", &[(1.0, b"x"), (1.0, b"y"), (1.0, b"z")]);
1789        assert_eq!(
1790            k.zintercard([b"a".as_slice(), b"b".as_slice()].into_iter(), 0)
1791                .unwrap(),
1792            3
1793        );
1794        assert_eq!(
1795            k.zintercard([b"a".as_slice(), b"b".as_slice()].into_iter(), 2)
1796                .unwrap(),
1797            2
1798        );
1799        assert_eq!(
1800            k.zintercard([b"a".as_slice(), b"gone".as_slice()].into_iter(), 0)
1801                .unwrap(),
1802            0
1803        );
1804    }
1805
1806    #[test]
1807    fn a_range_store_copies_a_window_and_leaves_the_source_alone() {
1808        let mut k = ks();
1809        add(
1810            &mut k,
1811            b"z",
1812            &[(1.0, b"a"), (2.0, b"b"), (3.0, b"c"), (4.0, b"d")],
1813        );
1814        assert_eq!(k.zrangestore(b"d", b"z", &Query::rank(1, 2)).unwrap(), 2);
1815        assert_eq!(all(&mut k, b"d"), [("b".into(), 2.0), ("c".into(), 3.0)]);
1816        assert_eq!(k.zcard(b"z").unwrap(), 4);
1817    }
1818
1819    #[test]
1820    fn a_reverse_range_store_picks_the_same_members_and_orders_them_the_same() {
1821        let mut k = ks();
1822        add(
1823            &mut k,
1824            b"z",
1825            &[(1.0, b"a"), (2.0, b"b"), (3.0, b"c"), (4.0, b"d")],
1826        );
1827        // REV picks which members, not what order they end up in, because the
1828        // destination is a sorted set and a sorted set has one order.
1829        assert_eq!(
1830            k.zrangestore(b"d", b"z", &Query::rank(0, 1).rev(true))
1831                .unwrap(),
1832            2
1833        );
1834        assert_eq!(all(&mut k, b"d"), [("c".into(), 3.0), ("d".into(), 4.0)]);
1835    }
1836
1837    #[test]
1838    fn a_range_store_by_score_takes_the_bounds_the_range_would_have() {
1839        let mut k = ks();
1840        add(
1841            &mut k,
1842            b"z",
1843            &[(1.0, b"a"), (2.0, b"b"), (3.0, b"c"), (4.0, b"d")],
1844        );
1845        let q = Query::score(Bound::closed(2.0), Bound::open(4.0));
1846        assert_eq!(k.zrangestore(b"d", b"z", &q).unwrap(), 2);
1847        assert_eq!(all(&mut k, b"d"), [("b".into(), 2.0), ("c".into(), 3.0)]);
1848    }
1849
1850    #[test]
1851    fn a_range_store_of_an_empty_window_deletes_the_destination() {
1852        let mut k = ks();
1853        add(&mut k, b"z", &[(1.0, b"a")]);
1854        add(&mut k, b"d", &[(1.0, b"old")]);
1855        assert_eq!(k.zrangestore(b"d", b"z", &Query::rank(5, 9)).unwrap(), 0);
1856        assert!(!k.exists(b"d"));
1857        assert_eq!(
1858            k.zrangestore(b"d", b"gone", &Query::rank(0, -1)).unwrap(),
1859            0
1860        );
1861        assert!(!k.exists(b"d"));
1862    }
1863
1864    #[test]
1865    fn a_range_store_onto_its_own_source_keeps_the_window() {
1866        let mut k = ks();
1867        add(
1868            &mut k,
1869            b"z",
1870            &[(1.0, b"a"), (2.0, b"b"), (3.0, b"c"), (4.0, b"d")],
1871        );
1872        assert_eq!(k.zrangestore(b"z", b"z", &Query::rank(1, 2)).unwrap(), 2);
1873        assert_eq!(all(&mut k, b"z"), [("b".into(), 2.0), ("c".into(), 3.0)]);
1874    }
1875
1876    #[test]
1877    fn a_big_result_comes_out_on_the_table_band_in_the_right_order() {
1878        let mut k = ks();
1879        let names: Vec<String> = (0..3000).map(|i| format!("member-{i:05}")).collect();
1880        for (i, name) in names.iter().enumerate() {
1881            add(&mut k, b"a", &[((i % 17) as f64, name.as_bytes())]);
1882        }
1883        for name in names.iter().step_by(3) {
1884            add(&mut k, b"b", &[(100.0, name.as_bytes())]);
1885        }
1886        let n = k
1887            .zsetop_store(
1888                Op::Union,
1889                b"d",
1890                [b"a".as_slice(), b"b".as_slice()].into_iter(),
1891                &[],
1892                Aggregate::Sum,
1893            )
1894            .unwrap();
1895        assert_eq!(n, 3000);
1896        assert_eq!(
1897            k.zset_encoding(b"d").map(crate::zset::Encoding::name),
1898            Some("skiplist")
1899        );
1900        let out = all(&mut k, b"d");
1901        assert_eq!(out.len(), 3000);
1902        let mut want = out.clone();
1903        want.sort_by(|x, y| x.1.partial_cmp(&y.1).unwrap().then_with(|| x.0.cmp(&y.0)));
1904        assert_eq!(out, want, "the result came out in the wrong order");
1905        for (i, name) in names.iter().enumerate() {
1906            let base = (i % 17) as f64;
1907            let want = if i % 3 == 0 { base + 100.0 } else { base };
1908            assert_eq!(k.zscore(b"d", name.as_bytes()).unwrap(), Some(want));
1909        }
1910    }
1911}