Skip to main content

yo_kv/
sets.rs

1//! The set commands.
2//!
3//! One method per Redis command on [`Keyspace`], the same arrangement the string
4//! commands use and for the same reason: a key belongs to the database and not
5//! to a type, so `SADD` against a string has to be able to see that it is a
6//! string. The set itself, and the choice between the three representations it
7//! can be in, is [`crate::set`]. This file is what the wire and the embedded API
8//! both call.
9//!
10//! # Where a set lives
11//!
12//! The record under the key holds a type tag and four bytes saying which slot of
13//! the database's slab the body is in, and that is all. Reaching a set is one
14//! key lookup and then one dependent load, and the dependent load is
15//! unavoidable because a set outgrows a record and outlives any one command.
16//!
17//! Two invariants hold this together and both of them are about not leaking.
18//! Every path that deletes a key goes through `drop_key` and every path that
19//! writes over one goes through `free_body`, so a set cannot lose its record
20//! while keeping its slot. And a set that loses its last member is deleted
21//! rather than stored empty, because an empty set does not exist in Redis:
22//! `SREM` taking the last member makes `EXISTS` answer zero.
23//!
24//! # Errors
25//!
26//! Every command here answers `WRONGTYPE` for a key holding something that is
27//! not a set, and treats a missing key as an empty one. That pair of rules is
28//! Redis's and between them they cover every case, because a key is a set, or
29//! another type, or absent.
30
31use std::collections::HashSet;
32
33use yo_common::Result;
34
35use crate::db::{Db, Holds};
36use crate::keyspace::Keyspace;
37use crate::scan::Cursor;
38use crate::set::{Member, Set};
39use crate::setops::{self, PerSet};
40use crate::strings;
41use crate::value::{self, Kind};
42
43impl Keyspace {
44    /// `SADD key member [member ...]`. Answers how many were new.
45    ///
46    /// The members arrive as an iterator and not a slice, the way `MSET`'s pairs
47    /// do, because the wire layer has them as positions in the connection's read
48    /// buffer and a slice would mean collecting them first. A shard thread that
49    /// allocates in order to call a command is the thing Y1 is trying to avoid.
50    /// The iterator is walked more than once, which is why it has to be `Clone`,
51    /// and an iterator over borrowed slices is two words to copy.
52    pub fn sadd<'m>(
53        &mut self,
54        key: &[u8],
55        members: impl Iterator<Item = &'m [u8]> + Clone,
56    ) -> Result<usize> {
57        for m in members.clone() {
58            strings::check_len(key, m.len())?;
59        }
60        let at = match self.set_slot(key)? {
61            Some(at) => at,
62            None => {
63                // Nothing to add to a key that does not exist yet is not a
64                // reason to create it. Redis's parser rejects `SADD k` before it
65                // gets this far, but the embedded API has no parser in front of
66                // it and an empty set left behind would be a key that exists and
67                // holds nothing.
68                let Some(first) = members.clone().next() else {
69                    return Ok(0);
70                };
71                let hint = members.clone().count();
72                self.new_set(key, first, hint)
73            }
74        };
75
76        // The limits are three numbers and copying them out is what lets the
77        // body be borrowed mutably for the whole loop instead of once a member.
78        let limits = self.limits;
79        let set = self
80            .sets
81            .get_mut(at)
82            .expect("the record points at its body");
83        let mut added = 0;
84        for m in members {
85            if set.add(m, &limits) {
86                added += 1;
87            }
88        }
89        Ok(added)
90    }
91
92    /// `SREM key member [member ...]`. Answers how many were there.
93    ///
94    /// A set that loses its last member loses its key too.
95    pub fn srem<'m>(
96        &mut self,
97        key: &[u8],
98        members: impl Iterator<Item = &'m [u8]>,
99    ) -> Result<usize> {
100        let Some(at) = self.set_slot(key)? else {
101            return Ok(0);
102        };
103        let set = self
104            .sets
105            .get_mut(at)
106            .expect("the record points at its body");
107        let mut gone = 0;
108        for m in members {
109            if set.remove(m) {
110                gone += 1;
111            }
112        }
113        if set.is_empty() {
114            self.drop_key(key);
115        }
116        Ok(gone)
117    }
118
119    /// `SISMEMBER key member`.
120    pub fn sismember(&mut self, key: &[u8], member: &[u8]) -> Result<bool> {
121        match self.set_slot(key)? {
122            Some(at) => Ok(self.set_at(at).contains(member)),
123            None => Ok(false),
124        }
125    }
126
127    /// `SMISMEMBER key member [member ...]`, which is `SISMEMBER` in bulk.
128    ///
129    /// One key lookup for the whole call rather than one per member, which is
130    /// the only reason the command exists.
131    pub fn smismember<'m>(
132        &mut self,
133        key: &[u8],
134        members: impl Iterator<Item = &'m [u8]>,
135    ) -> Result<Vec<bool>> {
136        let Some(at) = self.set_slot(key)? else {
137            return Ok(members.map(|_| false).collect());
138        };
139        let set = self.set_at(at);
140        Ok(members.map(|m| set.contains(m)).collect())
141    }
142
143    /// `SCARD key`, which is zero for a key that is not there.
144    pub fn scard(&mut self, key: &[u8]) -> Result<usize> {
145        match self.set_slot(key)? {
146            Some(at) => Ok(self.set_at(at).len()),
147            None => Ok(0),
148        }
149    }
150
151    /// `SMEMBERS key`, as a borrow of the set rather than a copy of it.
152    ///
153    /// The members come back as [`Member`]s, which are either the bytes where
154    /// they lie or an integer nobody has formatted yet, so a set of a thousand
155    /// integers becomes a thousand pieces of reply text and not a thousand
156    /// `Vec`s that are then copied into the reply and dropped. That is Y18, and
157    /// it is why this borrows the database for as long as the answer is alive.
158    pub fn smembers(&mut self, key: &[u8]) -> Result<Option<impl Iterator<Item = Member<'_>>>> {
159        let Some(at) = self.set_slot(key)? else {
160            return Ok(None);
161        };
162        Ok(Some(self.set_at(at).iter()))
163    }
164
165    /// `SPOP key`. Takes one member out at random and hands it back.
166    ///
167    /// This is the one set command that has to allocate, because the member it
168    /// answers with is the member it just took out of the structure holding it.
169    /// [`Keyspace::srandmember`] is the same draw without the removal and does
170    /// not allocate, which is why the two are not one method with a flag.
171    ///
172    /// The key goes when the last member does, the same as `SREM`.
173    pub fn spop(&mut self, key: &[u8]) -> Result<Option<Vec<u8>>> {
174        let Some(at) = self.set_slot(key)? else {
175            return Ok(None);
176        };
177        // A set in the keyspace is never empty, so there is always something to
178        // draw and the draw is always in range.
179        let len = self.set_at(at).len();
180        let pick = self.rng.below(len);
181        let got = self
182            .sets
183            .get_mut(at)
184            .expect("the record points at its body")
185            .remove_at(pick);
186        if self.set_at(at).is_empty() {
187            self.drop_key(key);
188        }
189        Ok(got)
190    }
191
192    /// `SPOP key count`. Takes `count` members out, or all of them if there are
193    /// fewer than that.
194    ///
195    /// Drawing from the length that is left rather than from the length it
196    /// started with is what makes the members distinct without a single test
197    /// for it. Each removal moves some other member into the hole it made and
198    /// shortens the set by one, so the next draw is over exactly the members
199    /// that are still there and every one of them is equally likely.
200    pub fn spop_n(&mut self, key: &[u8], count: usize) -> Result<Vec<Vec<u8>>> {
201        let Some(at) = self.set_slot(key)? else {
202            return Ok(Vec::new());
203        };
204        let take = count.min(self.set_at(at).len());
205        let mut out = Vec::with_capacity(take);
206        for _ in 0..take {
207            // The length is read again every turn rather than counted down,
208            // because the removal is what changed it and reading it twice is a
209            // load off a line that is already here.
210            let pick = self.rng.below(self.set_at(at).len());
211            out.push(
212                self.sets
213                    .get_mut(at)
214                    .expect("the record points at its body")
215                    .remove_at(pick)
216                    .expect("the draw was under the length"),
217            );
218        }
219        if self.set_at(at).is_empty() {
220            self.drop_key(key);
221        }
222        Ok(out)
223    }
224
225    /// `SPOP key [count]`, as a borrow rather than a copy. Answers how many.
226    ///
227    /// The same draw as [`Keyspace::spop_n`] and none of the allocating. Each
228    /// member is handed to `f` where it lies and taken out afterwards, so the
229    /// bytes go from the set into the reply buffer and nothing is built in
230    /// between. `spop_n` answers a `Vec` of `Vec`s, which is one allocation and
231    /// then one more per member, and that is the right shape for an embedded
232    /// caller who wants the answer in one piece and the wrong shape for a
233    /// thread that must not allocate.
234    ///
235    /// That garbage is the whole of `SPOP`'s gate row. aki came in at 0.58x at
236    /// P16 and 0.29x at P1 on this command, and the loss was never in the draw:
237    /// the draw is an index into an array and a swap with the last row. It was
238    /// in the allocation a member on the way out.
239    ///
240    /// Drawing from the length that is left rather than the length it started
241    /// with is what makes the members distinct with no test for it, the same
242    /// reason [`Keyspace::spop_n`] gives.
243    pub fn spop_into<F>(&mut self, key: &[u8], count: usize, mut f: F) -> Result<usize>
244    where
245        F: FnMut(Member<'_>),
246    {
247        let Some(at) = self.set_slot(key)? else {
248            return Ok(0);
249        };
250        let take = count.min(self.set_at(at).len());
251        for _ in 0..take {
252            // Borrowed apart rather than through `set_at`, for the reason
253            // `srandmember_n` gives: drawing and reading are alive at the same
254            // time and a method taking `&self` would hold the whole database.
255            let rng = &mut self.rng;
256            let set = self.sets.get(at).expect("the record points at its body");
257            let pick = rng.below(set.len());
258            f(set.at(pick).expect("the draw was under the length"));
259            self.sets
260                .get_mut(at)
261                .expect("the record points at its body")
262                .drop_at(pick);
263        }
264        if self.set_at(at).is_empty() {
265            self.drop_key(key);
266        }
267        Ok(take)
268    }
269
270    /// `SRANDMEMBER key`, as a borrow rather than a copy.
271    ///
272    /// The member is handed to `f` where it lies, so the single draw form
273    /// allocates nothing at all: the bytes go from the set into the reply
274    /// buffer and an integer member is never written as digits anywhere in
275    /// between. That is the whole of the gate row this command has on M3, where
276    /// the loss against Redis was in the garbage rather than in the draw.
277    ///
278    /// `f` is handed `None` when the key is not there, which is a nil reply and
279    /// not an empty one.
280    pub fn srandmember<R>(
281        &mut self,
282        key: &[u8],
283        f: impl FnOnce(Option<Member<'_>>) -> R,
284    ) -> Result<R> {
285        let Some(at) = self.set_slot(key)? else {
286            return Ok(f(None));
287        };
288        let pick = self.rng.below(self.sets.get(at).expect("a body").len());
289        Ok(f(self.set_at(at).at(pick)))
290    }
291
292    /// `SRANDMEMBER key count`, which is three different commands wearing one
293    /// name.
294    ///
295    /// A negative count is the with repeats form: exactly that many members,
296    /// drawn one at a time, and the same member can come back more than once.
297    /// It is the only form that can answer more members than the set holds.
298    ///
299    /// A positive count is distinct members, at most as many as the set holds,
300    /// and it is drawn two different ways depending on how much of the set is
301    /// being asked for. Wanting more than a third of it is a walk of the whole
302    /// set picking each member with the probability that leaves the right
303    /// number at the end, which is Knuth's selection sampling and needs no
304    /// memory at all. Wanting less than that is drawing positions and throwing
305    /// away the repeats, which needs somewhere to remember what has been drawn
306    /// and is the only thing here that allocates.
307    ///
308    /// Both are `O(count)`, which is the point of having two. Selection
309    /// sampling alone would walk a million members to answer `SRANDMEMBER key
310    /// 3`, and rejection alone would draw forever as the count approached the
311    /// size. Redis splits the same way at the same ratio.
312    pub fn srandmember_n<F>(&mut self, key: &[u8], count: i64, mut f: F) -> Result<()>
313    where
314        F: FnMut(Member<'_>),
315    {
316        let Some(at) = self.set_slot(key)? else {
317            return Ok(());
318        };
319        // The two fields are borrowed apart rather than through `set_at`,
320        // because drawing and reading have to be alive at the same time and a
321        // method taking `&self` would hold the whole database.
322        let rng = &mut self.rng;
323        let set = self.sets.get(at).expect("the record points at its body");
324        let len = set.len();
325
326        let Ok(want) = usize::try_from(count) else {
327            let repeats = usize::try_from(count.unsigned_abs()).unwrap_or(usize::MAX);
328            for _ in 0..repeats {
329                f(set
330                    .at(rng.below(len))
331                    .expect("the draw was under the length"));
332            }
333            return Ok(());
334        };
335        if want >= len {
336            for m in set.iter() {
337                f(m);
338            }
339            return Ok(());
340        }
341        if want.saturating_mul(3) > len {
342            let mut need = want;
343            for i in 0..len {
344                if rng.below(len - i) < need {
345                    f(set.at(i).expect("i is under the length"));
346                    need -= 1;
347                }
348            }
349            return Ok(());
350        }
351        let mut drawn = HashSet::with_capacity(want);
352        while drawn.len() < want {
353            let i = rng.below(len);
354            if drawn.insert(i) {
355                f(set.at(i).expect("the draw was under the length"));
356            }
357        }
358        Ok(())
359    }
360
361    /// `SSCAN key cursor`. Walks part of the set and says where to resume.
362    ///
363    /// A missing key is a finished scan and not an error, which is what lets a
364    /// client loop on the cursor without checking whether the key survived the
365    /// walk. `MATCH` is not here: filtering the members is the caller's, so
366    /// that the pattern is run against the member where it lies rather than
367    /// against a copy made to be filtered.
368    pub fn sscan<F>(&mut self, key: &[u8], cursor: Cursor, count: usize, f: F) -> Result<Cursor>
369    where
370        F: FnMut(Member<'_>),
371    {
372        let Some(at) = self.set_slot(key)? else {
373            return Ok(Cursor::END);
374        };
375        Ok(self.set_at(at).scan(cursor, count, f))
376    }
377
378    /// `SMOVE source destination member`. Answers whether it moved.
379    ///
380    /// The order of the checks is Redis's and it is not the order it looks like
381    /// it should be. A source that is not there answers zero without ever
382    /// looking at what the destination holds, so `SMOVE nothing a-string m` is
383    /// a zero and not a `WRONGTYPE`, and a source that is there checks both
384    /// types before it moves anything.
385    ///
386    /// Moving a member onto its own set is a no op that still answers whether
387    /// the member was there, which is the one case where a `1` means nothing
388    /// changed.
389    pub fn smove(&mut self, source: &[u8], destination: &[u8], member: &[u8]) -> Result<bool> {
390        let Some(from) = self.set_slot(source)? else {
391            return Ok(false);
392        };
393        let onto = self.set_slot(destination)?;
394        if source == destination {
395            return Ok(self.set_at(from).contains(member));
396        }
397        if !self
398            .sets
399            .get_mut(from)
400            .expect("the record points at its body")
401            .remove(member)
402        {
403            return Ok(false);
404        }
405        // The destination is filled before the source is emptied, so the slot
406        // the source is about to give back cannot be handed straight to the
407        // destination underneath the index this is holding.
408        let limits = self.limits;
409        let at = match onto {
410            Some(at) => at,
411            None => self.new_set(destination, member, 1),
412        };
413        self.sets
414            .get_mut(at)
415            .expect("the record points at its body")
416            .add(member, &limits);
417        if self.set_at(from).is_empty() {
418            self.drop_key(source);
419        }
420        Ok(true)
421    }
422
423    /// `SINTER key [key ...]`, and `SINTERCARD`'s limit.
424    ///
425    /// Zero for a limit means no limit. The count comes back whether or not the
426    /// caller collected anything, so [`Keyspace::sintercard`] is this with a
427    /// callback that throws its argument away.
428    pub fn sinter<'k, F>(
429        &mut self,
430        keys: impl Iterator<Item = &'k [u8]>,
431        limit: usize,
432        f: F,
433    ) -> Result<usize>
434    where
435        F: FnMut(&[u8]),
436    {
437        let slots = self.set_slots(keys)?;
438        // A key that is not there is an empty set, and an empty set anywhere is
439        // an empty intersection. That is the whole answer rather than a
440        // shortcut to it, and it is why a missing key is not an error.
441        if slots.is_empty() || slots.iter().any(Option::is_none) {
442            return Ok(0);
443        }
444        // Taken out and put back, so the tables the intersection fills in are
445        // the database's and not a pair the allocator hands out per call.
446        let mut scratch = std::mem::take(&mut self.setops);
447        let sets = self.bodies_of(&slots);
448        let n = setops::inter(&mut scratch, &sets, limit, f);
449        self.setops = scratch;
450        Ok(n)
451    }
452
453    /// `SINTERCARD numkeys key [key ...] [LIMIT limit]`.
454    pub fn sintercard<'k>(
455        &mut self,
456        keys: impl Iterator<Item = &'k [u8]>,
457        limit: usize,
458    ) -> Result<usize> {
459        self.sinter(keys, limit, |_| {})
460    }
461
462    /// `SUNION key [key ...]`, and `SUNIONCARD`'s limit.
463    ///
464    /// A key that is not there contributes nothing and is dropped rather than
465    /// emptying the answer, which is the opposite of what it does to an
466    /// intersection and is right for the same reason: an empty set adds no
467    /// members and removes none.
468    ///
469    /// Zero for a limit means no limit, as it does on [`Keyspace::sinter`].
470    pub fn sunion<'k, F>(
471        &mut self,
472        keys: impl Iterator<Item = &'k [u8]>,
473        limit: usize,
474        f: F,
475    ) -> Result<usize>
476    where
477        F: FnMut(&[u8]),
478    {
479        let slots = self.set_slots(keys)?;
480        // The database's table rather than one per call, for the reason in
481        // `setops::Scratch`: a union walks everything into a hash table, and
482        // building that table was most of what a `SUNION` over text sets did.
483        let mut scratch = std::mem::take(&mut self.setops);
484        let sets = self.bodies_of(&slots);
485        let n = setops::union(&mut scratch, &sets, limit, f);
486        self.setops = scratch;
487        Ok(n)
488    }
489
490    /// `SUNIONCARD numkeys key [key ...] [LIMIT limit]`.
491    pub fn sunioncard<'k>(
492        &mut self,
493        keys: impl Iterator<Item = &'k [u8]>,
494        limit: usize,
495    ) -> Result<usize> {
496        self.sunion(keys, limit, |_| {})
497    }
498
499    /// `SDIFF key [key ...]`, and `SDIFFCARD`'s limit.
500    ///
501    /// The first key is the one being walked, so a first key that is not there
502    /// is an empty answer whatever the rest hold. A later key that is not there
503    /// takes nothing away and is dropped.
504    pub fn sdiff<'k, F>(
505        &mut self,
506        keys: impl Iterator<Item = &'k [u8]>,
507        limit: usize,
508        f: F,
509    ) -> Result<usize>
510    where
511        F: FnMut(&[u8]),
512    {
513        let slots = self.set_slots(keys)?;
514        let Some(Some(_)) = slots.first() else {
515            return Ok(0);
516        };
517        let sets = self.bodies_of(&slots);
518        Ok(setops::diff(&sets, limit, f))
519    }
520
521    /// `SDIFFCARD numkeys key [key ...] [LIMIT limit]`.
522    pub fn sdiffcard<'k>(
523        &mut self,
524        keys: impl Iterator<Item = &'k [u8]>,
525        limit: usize,
526    ) -> Result<usize> {
527        self.sdiff(keys, limit, |_| {})
528    }
529
530    /// `SINTERSTORE destination key [key ...]`. Answers the size of the result.
531    pub fn sinterstore<'k>(
532        &mut self,
533        destination: &[u8],
534        keys: impl Iterator<Item = &'k [u8]>,
535    ) -> Result<usize> {
536        let slots = self.set_slots(keys)?;
537        let mut scratch = std::mem::take(&mut self.setops);
538        let built = if slots.is_empty() || slots.iter().any(Option::is_none) {
539            None
540        } else {
541            let sets = self.bodies_of(&slots);
542            // The smallest input, which is an upper bound on any intersection.
543            let upper = sets.iter().map(|s| s.len()).min().unwrap_or(0);
544            setops::collect(upper, &self.limits, |f| {
545                setops::inter(&mut scratch, &sets, 0, f);
546            })
547        };
548        self.setops = scratch;
549        Ok(self.put_set(destination, built))
550    }
551
552    /// `SUNIONSTORE destination key [key ...]`.
553    pub fn sunionstore<'k>(
554        &mut self,
555        destination: &[u8],
556        keys: impl Iterator<Item = &'k [u8]>,
557    ) -> Result<usize> {
558        let slots = self.set_slots(keys)?;
559        let mut scratch = std::mem::take(&mut self.setops);
560        let built = {
561            let sets = self.bodies_of(&slots);
562            // Everything, since a union of sets that share nothing is all of
563            // them. Presizing to that is right and being wrong about it costs a
564            // conversion rather than a wrong answer.
565            let upper = sets.iter().map(|s| s.len()).sum();
566            setops::collect(upper, &self.limits, |f| {
567                setops::union(&mut scratch, &sets, 0, f);
568            })
569        };
570        self.setops = scratch;
571        Ok(self.put_set(destination, built))
572    }
573
574    /// `SDIFFSTORE destination key [key ...]`.
575    pub fn sdiffstore<'k>(
576        &mut self,
577        destination: &[u8],
578        keys: impl Iterator<Item = &'k [u8]>,
579    ) -> Result<usize> {
580        let slots = self.set_slots(keys)?;
581        let built = match slots.first() {
582            Some(Some(_)) => {
583                let sets = self.bodies_of(&slots);
584                let upper = sets[0].len();
585                setops::collect(upper, &self.limits, |f| {
586                    setops::diff(&sets, 0, f);
587                })
588            }
589            _ => None,
590        };
591        Ok(self.put_set(destination, built))
592    }
593
594    /// Reap and resolve every key, in order, to the slot its set is in.
595    ///
596    /// `None` for a key that is not there, and an error the moment any key
597    /// holds something that is not a set. Failing on the first bad key rather
598    /// than at the end is what stops `SINTERSTORE d a not-a-set` from writing
599    /// the destination before it finds out.
600    ///
601    /// This is what makes the borrow work: reaping needs `&mut self` and reading
602    /// the bodies needs `&self`, so the keys have to be resolved before any body
603    /// is looked at.
604    ///
605    /// It used to be a `Vec` and therefore a malloc and a free on every one of
606    /// these commands, which is a real cost on the small end: a `SINTER` of two
607    /// eight member sets does a couple of hundred nanoseconds of work and was
608    /// paying for five allocations across this, [`Keyspace::bodies_of`] and
609    /// [`crate::setops`]'s own bookkeeping. `Small` keeps the usual `k` on the
610    /// stack and spills for the rare command that names more keys than that.
611    fn set_slots<'k>(
612        &mut self,
613        keys: impl Iterator<Item = &'k [u8]>,
614    ) -> Result<PerSet<Option<u32>>> {
615        // Pushed rather than collected, because `set_slot` can fail and the
616        // failure has to come out as an error rather than stop the walk quietly.
617        let mut out = PerSet::new();
618        for key in keys {
619            out.push(self.set_slot(key)?);
620        }
621        Ok(out)
622    }
623
624    /// The bodies those slots point at, with the keys that were not there gone.
625    #[inline]
626    fn bodies_of(&self, slots: &[Option<u32>]) -> PerSet<&Set> {
627        slots.iter().flatten().map(|&at| self.set_at(at)).collect()
628    }
629
630    /// Put a set under `key`, replacing whatever was there.
631    ///
632    /// No set means delete the key, because an empty set does not exist. That
633    /// is what makes `SINTERSTORE d a b` with an empty intersection delete `d`
634    /// and answer zero rather than leave an empty set that `EXISTS` says one
635    /// for, and it is why [`setops::collect`] hands back an `Option`.
636    ///
637    /// The destination is allowed to be one of the sources. It is safe because
638    /// the result was built whole before this was called, so nothing here can
639    /// touch a body that is still being read. Doing it the other way round,
640    /// clearing the destination first and filling it as the walk goes, is the
641    /// shape that makes `SINTERSTORE s s a` answer nothing.
642    ///
643    /// Whatever the key held is freed first, through the one funnel, and any
644    /// deadline it had goes with it. Redis's store forms clear the TTL for the
645    /// same reason `SET` does: the value under the key is not the value the
646    /// expiry was set on.
647    fn put_set(&mut self, key: &[u8], set: Option<Set>) -> usize {
648        let Some(set) = set else {
649            self.drop_key(key);
650            return 0;
651        };
652        self.replacing(key, Kind::Set);
653        self.free_body(key);
654        let len = set.len();
655        let at = self.sets.insert(set);
656        let record = value::slot_record_len(false);
657        self.write_rec(key, record, |out| {
658            value::write_slot_record(out, Kind::Set, at, None);
659        });
660        self.bodies += 1;
661        len
662    }
663
664    /// Hand the set under `key` to `f`, or hand it `None` if there is no key.
665    ///
666    /// This is what the wire layer reaches for when one command wants the body
667    /// more than once. `SMEMBERS` needs the count for the reply header and then
668    /// the members, and `SMISMEMBER` needs one membership test per argument, and
669    /// going back through [`Keyspace::scard`] and [`Keyspace::sismember`] for
670    /// each of those is a key lookup a piece. One lookup, then a borrow of the
671    /// body for as long as the caller needs it.
672    ///
673    /// It is a callback rather than a returned `&Set` because the reap has to
674    /// happen under `&mut self` and the borrow checker will not let a `&Set`
675    /// carved out of that outlive the call.
676    pub fn with_set<R>(&mut self, key: &[u8], f: impl FnOnce(Option<&Set>) -> R) -> Result<R> {
677        let at = self.set_slot(key)?;
678        Ok(f(at.map(|at| self.set_at(at))))
679    }
680
681    /// The slot holding the set under `key`, having reaped a dead key first.
682    ///
683    /// `None` for a key that is not there, an error for a key holding something
684    /// that is not a set. Every command above starts here, so the three cases a
685    /// key can be in are decided once.
686    fn set_slot(&mut self, key: &[u8]) -> Result<Option<u32>> {
687        self.live_slot(key, Kind::Set)
688    }
689
690    /// The body in a slot the record pointed at.
691    ///
692    /// Panicking here means a record outlived its body, which is the one bug the
693    /// slab deliberately does not carry a generation counter to catch, so this
694    /// is where it would be caught instead.
695    #[inline]
696    fn set_at(&self, at: u32) -> &Set {
697        self.sets.get(at).expect("the record points at its body")
698    }
699
700    /// Make an empty set under `key` and answer which slot it went in.
701    ///
702    /// `first` and `hint` only pick the representation to start in, following
703    /// Redis's `setTypeCreate`, so that a `SADD` with a thousand arguments
704    /// builds a table once instead of converting twice on the way there.
705    fn new_set(&mut self, key: &[u8], first: &[u8], hint: usize) -> u32 {
706        // The body and, every so often, the slab that holds it. See
707        // `yo_alloc::first_touch` for why this is the one allocation a command
708        // is allowed to make.
709        let at =
710            yo_alloc::first_touch(|| self.sets.insert(Set::with_hint(first, hint, &self.limits)));
711        let len = value::slot_record_len(false);
712        self.write_rec(key, len, |out| {
713            value::write_slot_record(out, Kind::Set, at, None);
714        });
715        self.bodies += 1;
716        at
717    }
718}
719
720/// Where a set body is, when the search for it covered a whole database.
721///
722/// The stripe and then the slot in that stripe's slab. A slot number means
723/// nothing without the stripe it came from, since every stripe numbers its own
724/// from zero.
725type Home = (usize, u32);
726
727impl Db {
728    /// `SMOVE source destination member` over a database of any width.
729    ///
730    /// The two keys on one stripe are that stripe's `SMOVE`, which is the whole
731    /// command on a database of one. Otherwise the member is taken out of one
732    /// stripe and put into another, in the order the single stripe version
733    /// moves it: the destination is filled before the source is emptied, and the
734    /// source is only deleted once it is known to be empty.
735    ///
736    /// The checks are in Redis's order, which is not the order they look like
737    /// they should be in. A source that is not there answers zero without ever
738    /// looking at the destination, so a destination holding a string is not a
739    /// `WRONGTYPE` until the source turns out to be a set.
740    pub fn smove(&self, source: &[u8], destination: &[u8], member: &[u8]) -> Result<bool> {
741        let (from, onto) = (self.stripe_of(source), self.stripe_of(destination));
742        if from == onto {
743            return self.hold_stripe(from).smove(source, destination, member);
744        }
745        // Both at once and in stripe order, so the member is never in neither
746        // set and never in both. It was in neither for as long as it took to
747        // let go of the source and reach for the destination before this.
748        let mut held = self.hold_many([from, onto].into_iter());
749        let Some(at) = held.stripe_mut(from).set_slot(source)? else {
750            return Ok(false);
751        };
752        let there = held.stripe_mut(onto).set_slot(destination)?;
753        if !held
754            .stripe_mut(from)
755            .sets
756            .get_mut(at)
757            .expect("the record points at its body")
758            .remove(member)
759        {
760            return Ok(false);
761        }
762
763        let dest = held.stripe_mut(onto);
764        let limits = dest.limits;
765        let into = match there {
766            Some(into) => into,
767            None => dest.new_set(destination, member, 1),
768        };
769        dest.sets
770            .get_mut(into)
771            .expect("the record points at its body")
772            .add(member, &limits);
773
774        let src = held.stripe_mut(from);
775        if src.set_at(at).is_empty() {
776            src.drop_key(source);
777        }
778        Ok(true)
779    }
780
781    /// `SINTER key [key ...]`, and `SINTERCARD`'s limit.
782    pub fn sinter<'k, F>(
783        &self,
784        keys: impl Iterator<Item = &'k [u8]> + Clone,
785        limit: usize,
786        f: F,
787    ) -> Result<usize>
788    where
789        F: FnMut(&[u8]),
790    {
791        if let Some(home) = self.one_stripe(keys.clone()) {
792            return self.hold_stripe(home).sinter(keys, limit, f);
793        }
794        // The buffers before the stripes, which is the order every command
795        // that wants both takes them in.
796        let mut spare = self.spare();
797        let scratch = &mut spare.setops;
798        let mut held = self.hold_sets(keys.clone(), None);
799        let slots = self.set_slots(&mut held, keys)?;
800        if slots.is_empty() || slots.iter().any(Option::is_none) {
801            return Ok(0);
802        }
803        let sets = bodies_of(&held, &slots);
804        Ok(setops::inter(scratch, &sets, limit, f))
805    }
806
807    /// `SINTERCARD numkeys key [key ...] [LIMIT limit]`.
808    pub fn sintercard<'k>(
809        &self,
810        keys: impl Iterator<Item = &'k [u8]> + Clone,
811        limit: usize,
812    ) -> Result<usize> {
813        self.sinter(keys, limit, |_| {})
814    }
815
816    /// `SUNION key [key ...]`, and `SUNIONCARD`'s limit.
817    pub fn sunion<'k, F>(
818        &self,
819        keys: impl Iterator<Item = &'k [u8]> + Clone,
820        limit: usize,
821        f: F,
822    ) -> Result<usize>
823    where
824        F: FnMut(&[u8]),
825    {
826        if let Some(home) = self.one_stripe(keys.clone()) {
827            return self.hold_stripe(home).sunion(keys, limit, f);
828        }
829        // The buffers before the stripes, which is the order every command
830        // that wants both takes them in.
831        let mut spare = self.spare();
832        let scratch = &mut spare.setops;
833        let mut held = self.hold_sets(keys.clone(), None);
834        let slots = self.set_slots(&mut held, keys)?;
835        let sets = bodies_of(&held, &slots);
836        Ok(setops::union(scratch, &sets, limit, f))
837    }
838
839    /// `SUNIONCARD numkeys key [key ...] [LIMIT limit]`.
840    pub fn sunioncard<'k>(
841        &self,
842        keys: impl Iterator<Item = &'k [u8]> + Clone,
843        limit: usize,
844    ) -> Result<usize> {
845        self.sunion(keys, limit, |_| {})
846    }
847
848    /// `SDIFF key [key ...]`, and `SDIFFCARD`'s limit.
849    pub fn sdiff<'k, F>(
850        &self,
851        keys: impl Iterator<Item = &'k [u8]> + Clone,
852        limit: usize,
853        f: F,
854    ) -> Result<usize>
855    where
856        F: FnMut(&[u8]),
857    {
858        if let Some(home) = self.one_stripe(keys.clone()) {
859            return self.hold_stripe(home).sdiff(keys, limit, f);
860        }
861        let mut held = self.hold_sets(keys.clone(), None);
862        let slots = self.set_slots(&mut held, keys)?;
863        let Some(Some(_)) = slots.first() else {
864            return Ok(0);
865        };
866        let sets = bodies_of(&held, &slots);
867        Ok(setops::diff(&sets, limit, f))
868    }
869
870    /// `SDIFFCARD numkeys key [key ...] [LIMIT limit]`.
871    pub fn sdiffcard<'k>(
872        &self,
873        keys: impl Iterator<Item = &'k [u8]> + Clone,
874        limit: usize,
875    ) -> Result<usize> {
876        self.sdiff(keys, limit, |_| {})
877    }
878
879    /// `SINTERSTORE destination key [key ...]`. Answers the size of the result.
880    ///
881    /// The result is built whole before the destination is touched, exactly as
882    /// it is on one stripe, which is what makes a destination that is also a
883    /// source work. The limits and the slab the answer goes into are the
884    /// destination's stripe's, since that is where the set is going to live.
885    pub fn sinterstore<'k>(
886        &self,
887        destination: &'k [u8],
888        keys: impl Iterator<Item = &'k [u8]> + Clone,
889    ) -> Result<usize> {
890        if let Some(home) = self.one_stripe(std::iter::once(destination).chain(keys.clone())) {
891            return self.hold_stripe(home).sinterstore(destination, keys);
892        }
893        // The buffers before the stripes, which is the order every command
894        // that wants both takes them in.
895        let mut spare = self.spare();
896        let scratch = &mut spare.setops;
897        let onto = self.stripe_of(destination);
898        let mut held = self.hold_sets(keys.clone(), Some(destination));
899        let slots = self.set_slots(&mut held, keys)?;
900        let built = if slots.is_empty() || slots.iter().any(Option::is_none) {
901            None
902        } else {
903            let limits = held.stripe(onto).limits;
904            let sets = bodies_of(&held, &slots);
905            let upper = sets.iter().map(|s| s.len()).min().unwrap_or(0);
906            setops::collect(upper, &limits, |f| {
907                setops::inter(scratch, &sets, 0, f);
908            })
909        };
910        Ok(held.stripe_mut(onto).put_set(destination, built))
911    }
912
913    /// `SUNIONSTORE destination key [key ...]`.
914    pub fn sunionstore<'k>(
915        &self,
916        destination: &'k [u8],
917        keys: impl Iterator<Item = &'k [u8]> + Clone,
918    ) -> Result<usize> {
919        if let Some(home) = self.one_stripe(std::iter::once(destination).chain(keys.clone())) {
920            return self.hold_stripe(home).sunionstore(destination, keys);
921        }
922        // The buffers before the stripes, which is the order every command
923        // that wants both takes them in.
924        let mut spare = self.spare();
925        let scratch = &mut spare.setops;
926        let onto = self.stripe_of(destination);
927        let mut held = self.hold_sets(keys.clone(), Some(destination));
928        let slots = self.set_slots(&mut held, keys)?;
929        let built = {
930            let limits = held.stripe(onto).limits;
931            let sets = bodies_of(&held, &slots);
932            let upper = sets.iter().map(|s| s.len()).sum();
933            setops::collect(upper, &limits, |f| {
934                setops::union(scratch, &sets, 0, f);
935            })
936        };
937        Ok(held.stripe_mut(onto).put_set(destination, built))
938    }
939
940    /// `SDIFFSTORE destination key [key ...]`.
941    pub fn sdiffstore<'k>(
942        &self,
943        destination: &'k [u8],
944        keys: impl Iterator<Item = &'k [u8]> + Clone,
945    ) -> Result<usize> {
946        if let Some(home) = self.one_stripe(std::iter::once(destination).chain(keys.clone())) {
947            return self.hold_stripe(home).sdiffstore(destination, keys);
948        }
949        let onto = self.stripe_of(destination);
950        let mut held = self.hold_sets(keys.clone(), Some(destination));
951        let slots = self.set_slots(&mut held, keys)?;
952        let built = match slots.first() {
953            Some(Some(_)) => {
954                let limits = held.stripe(onto).limits;
955                let sets = bodies_of(&held, &slots);
956                let upper = sets[0].len();
957                setops::collect(upper, &limits, |f| {
958                    setops::diff(&sets, 0, f);
959                })
960            }
961            _ => None,
962        };
963        Ok(held.stripe_mut(onto).put_set(destination, built))
964    }
965
966    /// Every stripe a set operation names, held at once, in stripe order.
967    ///
968    /// Before anything is resolved rather than after, because a slot number is
969    /// only good while the stripe it came from is held: let go of it and the key
970    /// can be deleted and the slot handed to something else, and what was read
971    /// back would be a different set under the same number. Taken in stripe
972    /// order, which is what keeps two of these from waiting on each other.
973    #[inline]
974    fn hold_sets<'k>(
975        &self,
976        keys: impl Iterator<Item = &'k [u8]>,
977        destination: Option<&[u8]>,
978    ) -> Holds<'_> {
979        let named = keys.map(|key| self.stripe_of(key));
980        self.hold_many(named.chain(destination.map(|d| self.stripe_of(d))))
981    }
982
983    /// Reap and resolve every key, in order, to the stripe and slot its set is
984    /// in.
985    ///
986    /// As [`Keyspace::set_slots`], including the part that matters most: the
987    /// first key holding something that is not a set stops the whole command
988    /// before anything has been written. Each key is resolved on the stripe it
989    /// is on, out of the ones already held, which is the only difference.
990    fn set_slots<'k>(
991        &self,
992        held: &mut Holds<'_>,
993        keys: impl Iterator<Item = &'k [u8]>,
994    ) -> Result<PerSet<Option<Home>>> {
995        let mut out = PerSet::new();
996        for key in keys {
997            let stripe = self.stripe_of(key);
998            let at = held.stripe_mut(stripe).set_slot(key)?;
999            out.push(at.map(|at| (stripe, at)));
1000        }
1001        Ok(out)
1002    }
1003}
1004
1005/// The bodies those slots point at, with the keys that were not there gone.
1006#[inline]
1007fn bodies_of<'h>(held: &'h Holds<'_>, slots: &[Option<Home>]) -> PerSet<&'h Set> {
1008    slots
1009        .iter()
1010        .flatten()
1011        .map(|&(stripe, at)| held.stripe(stripe).set_at(at))
1012        .collect()
1013}
1014
1015#[cfg(test)]
1016mod tests {
1017    use super::*;
1018    use crate::Clock;
1019    use crate::set::Encoding;
1020    use yo_common::Code;
1021
1022    fn db() -> Keyspace {
1023        Keyspace::with_clock(Clock::fixed(1_000))
1024    }
1025
1026    fn add(d: &mut Keyspace, key: &[u8], members: &[&[u8]]) -> usize {
1027        d.sadd(key, members.iter().copied()).expect("a set")
1028    }
1029
1030    fn members(d: &mut Keyspace, key: &[u8]) -> Vec<String> {
1031        let mut v: Vec<String> = d
1032            .smembers(key)
1033            .expect("a set")
1034            .expect("a key")
1035            .map(|m| String::from_utf8(m.to_vec()).expect("utf8 in these tests"))
1036            .collect();
1037        v.sort();
1038        v
1039    }
1040
1041    /// `SUNION` built a hash table out of the allocator on every call, and over
1042    /// text sets that table was most of what the command did.
1043    #[test]
1044    fn a_union_over_text_sets_does_not_allocate_once_its_table_is_warm() {
1045        let mut d = db();
1046        add(&mut d, b"a", &[b"alpha", b"beta", b"gamma", b"delta"]);
1047        add(&mut d, b"b", &[b"gamma", b"delta", b"epsilon", b"zeta"]);
1048        // One call to grow the table to the size of this union. Everything
1049        // after it reuses what that one bought.
1050        assert_eq!(
1051            d.sunion([b"a".as_slice(), b"b"].into_iter(), 0, |_| {}),
1052            Ok(6)
1053        );
1054        let (_, allocs) = crate::tally::counted(|| {
1055            for _ in 0..50 {
1056                assert_eq!(
1057                    d.sunion([b"a".as_slice(), b"b"].into_iter(), 0, |_| {}),
1058                    Ok(6)
1059                );
1060            }
1061        });
1062        assert_eq!(allocs, 0, "sunion allocated {allocs} times in fifty");
1063    }
1064
1065    /// And it still answers when the union is bigger than any before it, which
1066    /// is the case the reserve is there for.
1067    #[test]
1068    fn a_union_larger_than_the_last_one_grows_the_table_and_is_still_right() {
1069        let mut d = db();
1070        add(&mut d, b"a", &[b"one", b"two"]);
1071        add(&mut d, b"b", &[b"two", b"three"]);
1072        assert_eq!(
1073            d.sunion([b"a".as_slice(), b"b"].into_iter(), 0, |_| {}),
1074            Ok(3)
1075        );
1076
1077        let many: Vec<Vec<u8>> = (0..500).map(|i| format!("m{i}").into_bytes()).collect();
1078        let refs: Vec<&[u8]> = many.iter().map(Vec::as_slice).collect();
1079        add(&mut d, b"c", &refs);
1080        let mut seen = Vec::new();
1081        assert_eq!(
1082            d.sunion([b"a".as_slice(), b"c"].into_iter(), 0, |m: &[u8]| seen
1083                .push(m.to_vec())),
1084            Ok(502)
1085        );
1086        seen.sort();
1087        seen.dedup();
1088        assert_eq!(seen.len(), 502, "every member came back once");
1089
1090        // And back down again, which is the direction that would break if the
1091        // table were only ever grown and not cleared.
1092        assert_eq!(
1093            d.sunion([b"a".as_slice(), b"b"].into_iter(), 0, |_| {}),
1094            Ok(3)
1095        );
1096    }
1097
1098    #[test]
1099    fn adding_to_a_key_that_is_not_there_makes_it() {
1100        let mut d = db();
1101        assert_eq!(add(&mut d, b"s", &[b"a", b"b", b"c"]), 3);
1102        assert_eq!(d.scard(b"s").expect("a set"), 3);
1103        assert_eq!(d.kind_of(b"s"), Some(Kind::Set));
1104        assert_eq!(members(&mut d, b"s"), ["a", "b", "c"]);
1105        assert_eq!(d.len(), 1, "one key, whatever the set holds");
1106    }
1107
1108    #[test]
1109    fn adding_answers_how_many_were_new_and_not_how_many_arrived() {
1110        let mut d = db();
1111        assert_eq!(add(&mut d, b"s", &[b"a", b"b"]), 2);
1112        assert_eq!(add(&mut d, b"s", &[b"b", b"c"]), 1);
1113        assert_eq!(
1114            add(&mut d, b"s", &[b"x", b"x", b"x"]),
1115            1,
1116            "the same member three times in one call is one member"
1117        );
1118        assert_eq!(d.scard(b"s").expect("a set"), 4);
1119    }
1120
1121    #[test]
1122    fn everything_answers_for_a_key_that_is_not_there() {
1123        let mut d = db();
1124        assert_eq!(d.scard(b"nope").expect("missing is fine"), 0);
1125        assert!(!d.sismember(b"nope", b"a").expect("missing is fine"));
1126        assert!(d.smembers(b"nope").expect("missing is fine").is_none());
1127        assert_eq!(
1128            d.srem(b"nope", [b"a".as_slice()].into_iter()).expect("ok"),
1129            0
1130        );
1131        assert_eq!(
1132            d.smismember(b"nope", [b"a".as_slice(), b"b"].into_iter())
1133                .expect("ok"),
1134            [false, false]
1135        );
1136        assert_eq!(d.len(), 0, "and none of that created anything");
1137    }
1138
1139    #[test]
1140    fn membership_answers_for_members_and_strangers() {
1141        let mut d = db();
1142        add(&mut d, b"s", &[b"a", b"b"]);
1143        assert!(d.sismember(b"s", b"a").expect("a set"));
1144        assert!(!d.sismember(b"s", b"z").expect("a set"));
1145        assert_eq!(
1146            d.smismember(b"s", [b"a".as_slice(), b"z", b"b"].into_iter())
1147                .expect("a set"),
1148            [true, false, true]
1149        );
1150    }
1151
1152    #[test]
1153    fn removing_the_last_member_removes_the_key() {
1154        // An empty set does not exist in Redis and it does not exist here.
1155        let mut d = db();
1156        add(&mut d, b"s", &[b"a", b"b"]);
1157        assert_eq!(d.srem(b"s", [b"a".as_slice()].into_iter()).expect("ok"), 1);
1158        assert!(d.exists(b"s"), "one member left");
1159
1160        assert_eq!(
1161            d.srem(b"s", [b"b".as_slice(), b"gone"].into_iter())
1162                .expect("ok"),
1163            1,
1164            "one of the two was there"
1165        );
1166        assert!(!d.exists(b"s"), "and now the key is gone with it");
1167        assert_eq!(d.kind_of(b"s"), None);
1168        assert_eq!(d.len(), 0);
1169    }
1170
1171    #[test]
1172    fn a_set_is_deleted_body_and_all() {
1173        // The leak this guards against is invisible from the outside: the key
1174        // goes, the slot does not, and nothing ever notices. So the test asks
1175        // the slab directly, because that is the only place the answer shows.
1176        let mut d = db();
1177        add(&mut d, b"s", &[b"a", b"b"]);
1178        assert_eq!(d.sets.len(), 1);
1179
1180        assert!(d.del(b"s"));
1181        assert_eq!(d.sets.len(), 0, "the body went with the key");
1182        assert_eq!(d.bodies, 0);
1183
1184        // And the slot is reused rather than abandoned.
1185        add(&mut d, b"t", &[b"x"]);
1186        assert_eq!(d.sets.len(), 1);
1187    }
1188
1189    #[test]
1190    fn writing_a_string_over_a_set_takes_the_body_with_it() {
1191        // SET is allowed to overwrite any type, so this is not WRONGTYPE. What
1192        // it must not be is a set left in the slab with nothing pointing at it.
1193        let mut d = db();
1194        add(&mut d, b"k", &[b"a", b"b"]);
1195        assert_eq!(d.sets.len(), 1);
1196
1197        d.set_plain(b"k", b"now a string").expect("room");
1198        assert_eq!(d.sets.len(), 0, "the set went when it was written over");
1199        assert_eq!(d.bodies, 0);
1200        assert_eq!(d.kind_of(b"k"), Some(Kind::String));
1201        assert_eq!(
1202            d.get(b"k").expect("a string").map(|v| v.to_vec()),
1203            Some(b"now a string".to_vec())
1204        );
1205    }
1206
1207    #[test]
1208    fn a_set_that_expires_takes_its_body_with_it() {
1209        let mut d = db();
1210        add(&mut d, b"s", &[b"a"]);
1211        assert!(d.set_expiry(b"s", Some(1_100)));
1212        assert_eq!(d.expire_at(b"s"), Some(1_100));
1213        assert_eq!(d.sets.len(), 1);
1214        assert_eq!(d.scard(b"s").expect("a set"), 1, "still alive at 1000");
1215
1216        d.clock().advance(100);
1217        assert_eq!(d.scard(b"s").expect("gone is not an error"), 0);
1218        assert_eq!(d.sets.len(), 0, "reaping freed the body");
1219        assert_eq!(d.bodies, 0);
1220        assert_eq!(d.expired_keys(), 1);
1221    }
1222
1223    #[test]
1224    fn flushing_takes_every_body_with_it() {
1225        let mut d = db();
1226        for i in 0..10 {
1227            add(&mut d, format!("s{i}").as_bytes(), &[b"a", b"b"]);
1228        }
1229        assert_eq!(d.sets.len(), 10);
1230
1231        d.clear();
1232        assert_eq!(d.sets.len(), 0);
1233        assert_eq!(d.bodies, 0);
1234        assert_eq!(d.len(), 0);
1235    }
1236
1237    #[test]
1238    fn a_set_command_at_a_string_is_wrongtype() {
1239        let mut d = db();
1240        d.set_plain(b"k", b"v").expect("room");
1241
1242        let err = d.sadd(b"k", [b"a".as_slice()].into_iter()).expect_err("no");
1243        assert_eq!(err.code(), Code::WrongType);
1244        assert_eq!(
1245            err.message(),
1246            "Operation against a key holding the wrong kind of value"
1247        );
1248        assert!(d.scard(b"k").is_err());
1249        assert!(d.sismember(b"k", b"a").is_err());
1250        assert!(d.smembers(b"k").is_err());
1251        assert!(d.srem(b"k", [b"a".as_slice()].into_iter()).is_err());
1252        assert!(d.smismember(b"k", [b"a".as_slice()].into_iter()).is_err());
1253        assert_eq!(
1254            d.get(b"k").expect("still a string").map(|v| v.to_vec()),
1255            Some(b"v".to_vec()),
1256            "and none of that damaged it"
1257        );
1258    }
1259
1260    #[test]
1261    fn a_string_command_at_a_set_is_wrongtype() {
1262        let mut d = db();
1263        add(&mut d, b"s", &[b"a"]);
1264
1265        assert_eq!(d.get(b"s").expect_err("no").code(), Code::WrongType);
1266        assert!(d.strlen(b"s").is_err());
1267        assert!(d.getrange(b"s", 0, -1).is_err());
1268        assert!(d.getdel(b"s").is_err());
1269        assert!(d.incr(b"s").is_err());
1270        assert!(d.append(b"s", b"x").is_err());
1271        assert_eq!(d.scard(b"s").expect("a set"), 1, "and it is still a set");
1272    }
1273
1274    #[test]
1275    fn the_commands_that_do_not_care_still_do_not_care() {
1276        // EXISTS, DEL, TYPE and the TTL commands work on any type in Redis, and
1277        // a WRONGTYPE from one of them would be a bug and not a strictness.
1278        let mut d = db();
1279        add(&mut d, b"s", &[b"a"]);
1280
1281        assert!(d.exists(b"s"));
1282        assert_eq!(d.kind_of(b"s"), Some(Kind::Set));
1283        assert_eq!(d.encoding_name(b"s"), Some("listpack"));
1284        assert!(d.set_expiry(b"s", Some(6_000)));
1285        assert_eq!(d.expire_at(b"s"), Some(6_000));
1286        assert!(d.set_expiry(b"s", None), "and PERSIST takes it off again");
1287        assert_eq!(d.expire_at(b"s"), None);
1288        assert_eq!(d.scard(b"s").expect("a set"), 1, "through all of that");
1289        assert!(d.del(b"s"));
1290    }
1291
1292    #[test]
1293    fn mget_says_nil_for_a_set_rather_than_failing() {
1294        // The one string command that does not answer WRONGTYPE. Redis
1295        // documents MGET as giving nil for a key of the wrong type, because the
1296        // alternative is one bad key failing a hundred good ones.
1297        let mut d = db();
1298        d.set_plain(b"a", b"1").expect("room");
1299        add(&mut d, b"s", &[b"x"]);
1300        d.set_plain(b"z", b"2").expect("room");
1301
1302        let got: Vec<Option<Vec<u8>>> = d
1303            .mget(&[b"a", b"s", b"z", b"nope"])
1304            .into_iter()
1305            .map(|v| v.map(|s| s.to_vec()))
1306            .collect();
1307        assert_eq!(got, [Some(b"1".to_vec()), None, Some(b"2".to_vec()), None]);
1308    }
1309
1310    #[test]
1311    fn the_representation_follows_the_members_through_the_keyspace() {
1312        // The same ladder set.rs tests, but reached the way a client reaches it,
1313        // to prove the body that gets promoted is the body the record points at
1314        // and not a copy that was left behind.
1315        let mut d = db();
1316        add(&mut d, b"s", &[b"1", b"2", b"3"]);
1317        assert_eq!(d.set_encoding(b"s"), Some(Encoding::Intset));
1318
1319        add(&mut d, b"s", &[b"hello"]);
1320        assert_eq!(d.set_encoding(b"s"), Some(Encoding::Listpack));
1321        assert_eq!(members(&mut d, b"s"), ["1", "2", "3", "hello"]);
1322
1323        let long: Vec<u8> = vec![b'z'; 100];
1324        add(&mut d, b"s", &[&long]);
1325        assert_eq!(d.set_encoding(b"s"), Some(Encoding::Hashtable));
1326        assert_eq!(d.scard(b"s").expect("a set"), 5);
1327        assert!(d.sismember(b"s", b"1").expect("a set"), "nothing was lost");
1328        assert!(d.sismember(b"s", &long).expect("a set"));
1329    }
1330
1331    #[test]
1332    fn a_thousand_members_at_once_builds_a_table_without_converting() {
1333        let mut d = db();
1334        let owned: Vec<Vec<u8>> = (0..1000).map(|i| format!("m{i}").into_bytes()).collect();
1335        let refs: Vec<&[u8]> = owned.iter().map(Vec::as_slice).collect();
1336        assert_eq!(d.sadd(b"s", refs.iter().copied()).expect("a set"), 1000);
1337        assert_eq!(d.set_encoding(b"s"), Some(Encoding::Hashtable));
1338        assert_eq!(d.scard(b"s").expect("a set"), 1000);
1339    }
1340
1341    /// A set of `n` members named `m0` up, which is a table past 128.
1342    fn many(d: &mut Keyspace, key: &[u8], n: usize) {
1343        let owned: Vec<Vec<u8>> = (0..n).map(|i| format!("m{i}").into_bytes()).collect();
1344        let refs: Vec<&[u8]> = owned.iter().map(Vec::as_slice).collect();
1345        d.sadd(key, refs.iter().copied()).expect("a set");
1346    }
1347
1348    /// `many`, and integers instead of names when asked, so a test can reach
1349    /// the intset band as well as the other two.
1350    fn fill(d: &mut Keyspace, key: &[u8], n: usize, ints: bool) {
1351        let owned: Vec<Vec<u8>> = (0..n)
1352            .map(|i| {
1353                if ints {
1354                    i.to_string().into_bytes()
1355                } else {
1356                    format!("m{i}").into_bytes()
1357                }
1358            })
1359            .collect();
1360        let refs: Vec<&[u8]> = owned.iter().map(Vec::as_slice).collect();
1361        d.sadd(key, refs.iter().copied()).expect("a set");
1362    }
1363
1364    fn drawn(d: &mut Keyspace, key: &[u8], count: i64) -> Vec<String> {
1365        let mut out = Vec::new();
1366        d.srandmember_n(key, count, |m| {
1367            out.push(String::from_utf8(m.to_vec()).expect("utf8 in these tests"));
1368        })
1369        .expect("a set");
1370        out
1371    }
1372
1373    #[test]
1374    fn popping_takes_a_member_out_and_the_key_with_the_last_one() {
1375        let mut d = db();
1376        add(&mut d, b"s", &[b"a", b"b"]);
1377        let first = d.spop(b"s").expect("a set").expect("two members");
1378        assert_eq!(d.scard(b"s").expect("a set"), 1);
1379
1380        let second = d.spop(b"s").expect("a set").expect("one member");
1381        assert_ne!(first, second, "the same member came back twice");
1382        assert!(!d.exists(b"s"), "the last member took the key");
1383        assert_eq!(d.sets.len(), 0, "and the body");
1384        assert_eq!(d.spop(b"s").expect("gone is not an error"), None);
1385    }
1386
1387    #[test]
1388    fn popping_a_count_empties_a_set_without_repeating_itself() {
1389        // In all three representations, because the table moves its last row
1390        // into the hole and the other two shift, and a draw that assumed either
1391        // one would repeat a member or run off the end.
1392        for n in [4usize, 100, 300] {
1393            let mut d = db();
1394            many(&mut d, b"s", n);
1395            let got = d.spop_n(b"s", n + 10).expect("a set");
1396            assert_eq!(got.len(), n, "asked for more than there was");
1397            let mut sorted = got.clone();
1398            sorted.sort();
1399            sorted.dedup();
1400            assert_eq!(sorted.len(), n, "a member came back twice");
1401            assert!(!d.exists(b"s"));
1402            assert_eq!(d.sets.len(), 0);
1403        }
1404    }
1405
1406    #[test]
1407    fn popping_part_of_a_set_leaves_the_rest_of_it() {
1408        let mut d = db();
1409        many(&mut d, b"s", 10);
1410        let got = d.spop_n(b"s", 4).expect("a set");
1411        assert_eq!(got.len(), 4);
1412        assert_eq!(d.scard(b"s").expect("a set"), 6);
1413        for m in &got {
1414            assert!(!d.sismember(b"s", m).expect("a set"), "still there");
1415        }
1416        assert_eq!(
1417            d.spop_n(b"s", 0).expect("a set").len(),
1418            0,
1419            "and zero is none"
1420        );
1421        assert_eq!(d.scard(b"s").expect("a set"), 6);
1422    }
1423
1424    #[test]
1425    fn the_borrowing_draw_pops_the_same_set_the_copying_one_does() {
1426        // Same seed, same set, same members in the same order. If the two ever
1427        // disagree then the wire and the embedded API answer differently for
1428        // the same command, which is the one thing there is no excuse for.
1429        for n in [4usize, 100, 300] {
1430            let mut a = db();
1431            a.seed(20_260_829);
1432            many(&mut a, b"s", n);
1433            let copied = a.spop_n(b"s", n).expect("a set");
1434
1435            let mut b = db();
1436            b.seed(20_260_829);
1437            many(&mut b, b"s", n);
1438            let mut borrowed = Vec::new();
1439            b.spop_into(b"s", n, |m| borrowed.push(m.to_vec()))
1440                .expect("a set");
1441
1442            assert_eq!(copied, borrowed, "{n} members drew differently");
1443            assert!(!b.exists(b"s"), "the last member took the key");
1444            assert_eq!(b.sets.len(), 0, "and the body");
1445        }
1446    }
1447
1448    #[test]
1449    fn the_borrowing_draw_allocates_nothing() {
1450        // Every representation, because each takes a member out its own way:
1451        // the intset shifts an array of integers, the listpack shifts bytes,
1452        // and the table moves its last row into the hole. Also the whole set
1453        // rather than part of it, so the key deletion at the end is inside the
1454        // measurement and not just the draw.
1455        for n in [4usize, 100, 300] {
1456            for ints in [false, true] {
1457                let mut d = db();
1458                fill(&mut d, b"s", n, ints);
1459                let (drawn, allocs) = crate::tally::counted(|| {
1460                    let mut bytes = 0;
1461                    let mut count = 0;
1462                    d.spop_into(b"s", n, |m| {
1463                        // Read the member here rather than keep it, which is
1464                        // what the reply buffer does with it on the wire.
1465                        bytes += m.byte_len();
1466                        count += 1;
1467                    })
1468                    .expect("a set");
1469                    (bytes, count)
1470                });
1471                assert_eq!(drawn.1, n, "{n} members, ints {ints}");
1472                assert!(drawn.0 > 0, "the members came back empty");
1473                assert_eq!(
1474                    allocs, 0,
1475                    "{n} members, ints {ints}: {allocs} allocations on the way out"
1476                );
1477            }
1478        }
1479    }
1480
1481    /// The `k` sized bookkeeping a set operation does before it starts is gone.
1482    /// It used to be five vectors across `set_slots`, `bodies_of` and `setops`,
1483    /// each a malloc and a free, on a command whose real work over three eight
1484    /// member sets is a couple of hundred nanoseconds.
1485    ///
1486    /// On integer sets that leaves nothing at all, because the merge walks the
1487    /// sorted arrays and needs no table. On the other representations `SUNION`
1488    /// and `SDIFF` still build one hash table each to dedupe with, which is
1489    /// sized by the members rather than by the number of keys and is the
1490    /// algorithm rather than the bookkeeping.
1491    #[test]
1492    fn a_small_set_operation_stops_paying_per_key() {
1493        for (ints, want) in [(true, 0), (false, 6)] {
1494            let mut d = db();
1495            fill(&mut d, b"a", 8, ints);
1496            fill(&mut d, b"b", 8, ints);
1497            fill(&mut d, b"c", 8, ints);
1498            let keys: [&[u8]; 3] = [b"a", b"b", b"c"];
1499
1500            let (found, allocs) = crate::tally::counted(|| {
1501                let mut n = 0;
1502                d.sinter(keys.iter().copied(), 0, |_| n += 1).expect("sets");
1503                d.sunion(keys.iter().copied(), 0, |_| n += 1).expect("sets");
1504                d.sdiff(keys.iter().copied(), 0, |_| n += 1).expect("sets");
1505                n
1506            });
1507            assert!(found > 0, "ints {ints}: the operations found nothing");
1508            assert_eq!(
1509                allocs, want,
1510                "ints {ints}: {allocs} allocations for three ops, wanted {want}"
1511            );
1512        }
1513    }
1514
1515    /// And past the inline room it still works, which is the half of `Small`
1516    /// that only the rare command reaches.
1517    #[test]
1518    fn a_wide_set_operation_still_answers() {
1519        let wide = crate::setops::INLINE_KEYS + 3;
1520        let mut d = db();
1521        let names: Vec<Vec<u8>> = (0..wide).map(|i| format!("k{i}").into_bytes()).collect();
1522        for name in &names {
1523            fill(&mut d, name, 8, true);
1524        }
1525        let keys = || names.iter().map(|k| k.as_slice());
1526        let mut inter = 0;
1527        d.sinter(keys(), 0, |_| inter += 1).expect("sets");
1528        // Every set holds the same eight members, so they all survive.
1529        assert_eq!(inter, 8);
1530        let mut union = 0;
1531        d.sunion(keys(), 0, |_| union += 1).expect("sets");
1532        assert_eq!(union, 8);
1533    }
1534
1535    #[test]
1536    fn the_copying_draw_allocates_a_member_at_a_time() {
1537        // The other half of it. `spop_n` stays for the embedded caller who
1538        // wants the answer in one piece, and this is what that shape costs,
1539        // which is the whole reason the borrowing draw exists.
1540        let mut d = db();
1541        many(&mut d, b"s", 100);
1542        let (got, allocs) = crate::tally::counted(|| d.spop_n(b"s", 100).expect("a set"));
1543        assert_eq!(got.len(), 100);
1544        assert!(allocs >= 100, "only {allocs} allocations for a hundred");
1545    }
1546
1547    #[test]
1548    fn a_pinned_seed_draws_the_same_members_twice() {
1549        // The one input that makes a result unrepeatable, handed in rather than
1550        // reached for. Without this there is nothing to assert about a draw
1551        // except that something came back.
1552        let mut runs = Vec::new();
1553        for _ in 0..2 {
1554            let mut d = db();
1555            d.seed(20_260_828);
1556            many(&mut d, b"s", 50);
1557            runs.push(d.spop_n(b"s", 10).expect("a set"));
1558        }
1559        assert_eq!(runs[0], runs[1]);
1560    }
1561
1562    #[test]
1563    fn a_single_draw_reaches_every_member_and_removes_none() {
1564        let mut d = db();
1565        d.seed(7);
1566        add(&mut d, b"s", &[b"a", b"b", b"c"]);
1567        let mut seen = std::collections::HashSet::new();
1568        for _ in 0..200 {
1569            let got = d
1570                .srandmember(b"s", |m| m.map(|m| m.to_vec()))
1571                .expect("a set")
1572                .expect("a member");
1573            seen.insert(got);
1574        }
1575        assert_eq!(seen.len(), 3, "a draw that never reaches a member");
1576        assert_eq!(d.scard(b"s").expect("a set"), 3, "and nothing was taken");
1577
1578        assert!(
1579            d.srandmember(b"nope", |m| m.map(|m| m.to_vec()))
1580                .expect("missing is fine")
1581                .is_none()
1582        );
1583    }
1584
1585    #[test]
1586    fn a_negative_count_repeats_itself_and_a_positive_one_does_not() {
1587        let mut d = db();
1588        d.seed(11);
1589        add(&mut d, b"s", &[b"a", b"b", b"c"]);
1590
1591        let with_repeats = drawn(&mut d, b"s", -20);
1592        assert_eq!(with_repeats.len(), 20, "more members than the set holds");
1593
1594        let mut distinct = drawn(&mut d, b"s", 2);
1595        distinct.sort();
1596        distinct.dedup();
1597        assert_eq!(distinct.len(), 2);
1598    }
1599
1600    #[test]
1601    fn asking_for_more_than_the_set_holds_answers_all_of_it_once() {
1602        let mut d = db();
1603        d.seed(3);
1604        add(&mut d, b"s", &[b"a", b"b", b"c"]);
1605        let mut got = drawn(&mut d, b"s", 99);
1606        got.sort();
1607        assert_eq!(got, ["a", "b", "c"]);
1608        assert_eq!(drawn(&mut d, b"s", 0).len(), 0);
1609        assert_eq!(drawn(&mut d, b"nope", 5).len(), 0);
1610        assert_eq!(drawn(&mut d, b"nope", -5).len(), 0);
1611    }
1612
1613    #[test]
1614    fn both_ways_of_drawing_distinct_members_are_distinct_and_uniform() {
1615        // The two branches of `srandmember_n`, either side of the third. A
1616        // thousand members and a draw of two hits the rejection branch, and the
1617        // same set with a draw of nine hundred hits the selection walk.
1618        let mut d = db();
1619        d.seed(99);
1620        many(&mut d, b"s", 1000);
1621
1622        for count in [2, 100, 400, 900] {
1623            let got = drawn(&mut d, b"s", count);
1624            let mut sorted = got.clone();
1625            sorted.sort();
1626            sorted.dedup();
1627            assert_eq!(
1628                sorted.len(),
1629                got.len(),
1630                "a draw of {count} repeated a member"
1631            );
1632            assert_eq!(got.len(), count as usize);
1633        }
1634
1635        // And every member is reachable by both, which a walk that stopped
1636        // early or a draw that never reached the top would not manage.
1637        let mut seen = std::collections::HashSet::new();
1638        for _ in 0..40 {
1639            seen.extend(drawn(&mut d, b"s", 900));
1640            seen.extend(drawn(&mut d, b"s", 2));
1641        }
1642        assert_eq!(seen.len(), 1000, "some member is never drawn");
1643        assert_eq!(d.scard(b"s").expect("a set"), 1000, "and none were taken");
1644    }
1645
1646    #[test]
1647    fn a_scan_walks_a_set_of_any_size_exactly_once() {
1648        for n in [3usize, 100, 500] {
1649            let mut d = db();
1650            many(&mut d, b"s", n);
1651            let mut seen = Vec::new();
1652            let mut c = Cursor::START;
1653            let mut turns = 0;
1654            loop {
1655                c = d
1656                    .sscan(b"s", c, 10, |m| seen.push(m.to_vec()))
1657                    .expect("a set");
1658                turns += 1;
1659                assert!(turns < 200, "the scan did not finish for {n} members");
1660                if c.is_end() {
1661                    break;
1662                }
1663            }
1664            seen.sort();
1665            seen.dedup();
1666            assert_eq!(seen.len(), n, "a scan of {n} members missed one");
1667        }
1668    }
1669
1670    #[test]
1671    fn a_scan_of_a_key_that_is_not_there_is_a_finished_scan() {
1672        let mut d = db();
1673        let mut hit = 0;
1674        let c = d
1675            .sscan(b"nope", Cursor::START, 10, |_| hit += 1)
1676            .expect("ok");
1677        assert!(c.is_end());
1678        assert_eq!(hit, 0);
1679    }
1680
1681    #[test]
1682    fn a_scan_returns_everything_that_was_there_the_whole_time() {
1683        // The guarantee, tested the way it is written: members removed during
1684        // the walk may or may not come back, but the ones that never moved have
1685        // to. The table band is the only one that walks in windows, so this is
1686        // five hundred members.
1687        let mut d = db();
1688        many(&mut d, b"s", 500);
1689        let mut seen = Vec::new();
1690        let mut c = Cursor::START;
1691        let mut turns = 0;
1692        loop {
1693            c = d
1694                .sscan(b"s", c, 10, |m| seen.push(m.to_vec()))
1695                .expect("a set");
1696            // Take one out every turn, from the half of the set this test has
1697            // promised nothing about.
1698            let victim = format!("m{}", 400 + turns).into_bytes();
1699            d.srem(b"s", [victim.as_slice()].into_iter())
1700                .expect("a set");
1701            turns += 1;
1702            if c.is_end() {
1703                break;
1704            }
1705        }
1706        seen.sort();
1707        seen.dedup();
1708        for i in 0..400 {
1709            let m = format!("m{i}").into_bytes();
1710            assert!(seen.binary_search(&m).is_ok(), "m{i} was never returned");
1711        }
1712    }
1713
1714    #[test]
1715    fn moving_a_member_takes_it_off_one_set_and_puts_it_on_another() {
1716        let mut d = db();
1717        add(&mut d, b"a", &[b"x", b"y"]);
1718        add(&mut d, b"b", &[b"z"]);
1719
1720        assert!(d.smove(b"a", b"b", b"x").expect("two sets"));
1721        assert_eq!(members(&mut d, b"a"), ["y"]);
1722        assert_eq!(members(&mut d, b"b"), ["x", "z"]);
1723
1724        assert!(
1725            !d.smove(b"a", b"b", b"gone").expect("two sets"),
1726            "a member that is not in the source does not move"
1727        );
1728        assert!(
1729            d.smove(b"a", b"b", b"y").expect("two sets"),
1730            "and the last one still moves"
1731        );
1732        assert!(!d.exists(b"a"), "the source went with its last member");
1733        assert_eq!(d.sets.len(), 1, "and so did its body");
1734        assert_eq!(members(&mut d, b"b"), ["x", "y", "z"]);
1735    }
1736
1737    #[test]
1738    fn moving_onto_a_destination_that_is_not_there_makes_it() {
1739        let mut d = db();
1740        add(&mut d, b"a", &[b"x", b"y"]);
1741        assert!(d.smove(b"a", b"b", b"x").expect("a set"));
1742        assert_eq!(d.kind_of(b"b"), Some(Kind::Set));
1743        assert_eq!(members(&mut d, b"b"), ["x"]);
1744        assert_eq!(d.sets.len(), 2);
1745    }
1746
1747    #[test]
1748    fn moving_a_member_onto_its_own_set_changes_nothing() {
1749        let mut d = db();
1750        add(&mut d, b"a", &[b"x", b"y"]);
1751        assert!(d.smove(b"a", b"a", b"x").expect("a set"), "it is there");
1752        assert!(!d.smove(b"a", b"a", b"z").expect("a set"), "it is not");
1753        assert_eq!(members(&mut d, b"a"), ["x", "y"]);
1754    }
1755
1756    #[test]
1757    fn moving_checks_the_types_in_the_order_redis_checks_them() {
1758        let mut d = db();
1759        d.set_plain(b"str", b"v").expect("room");
1760        add(&mut d, b"s", &[b"x"]);
1761
1762        assert!(
1763            !d.smove(b"nope", b"str", b"x").expect("no source, no error"),
1764            "a missing source answers zero without looking at the destination"
1765        );
1766        assert_eq!(
1767            d.smove(b"str", b"s", b"x").expect_err("no").code(),
1768            Code::WrongType
1769        );
1770        assert_eq!(
1771            d.smove(b"s", b"str", b"x").expect_err("no").code(),
1772            Code::WrongType
1773        );
1774        assert_eq!(
1775            members(&mut d, b"s"),
1776            ["x"],
1777            "and the failed move left the source alone"
1778        );
1779    }
1780
1781    #[test]
1782    fn the_new_commands_answer_wrongtype_at_a_string() {
1783        let mut d = db();
1784        d.set_plain(b"k", b"v").expect("room");
1785        assert!(d.spop(b"k").is_err());
1786        assert!(d.spop_n(b"k", 2).is_err());
1787        assert!(d.srandmember(b"k", |m| m.is_some()).is_err());
1788        assert!(d.srandmember_n(b"k", 2, |_| ()).is_err());
1789        assert!(d.sscan(b"k", Cursor::START, 10, |_| ()).is_err());
1790        assert_eq!(
1791            d.get(b"k").expect("still a string").map(|v| v.to_vec()),
1792            Some(b"v".to_vec())
1793        );
1794    }
1795
1796    /// Every algebra command, collected and sorted, so a test says what came
1797    /// back rather than what order it came back in.
1798    fn algebra(d: &mut Keyspace, op: &str, keys: &[&[u8]]) -> Vec<String> {
1799        let mut got = Vec::new();
1800        let mut take = |m: &[u8]| got.push(String::from_utf8_lossy(m).into_owned());
1801        let n = match op {
1802            "inter" => d.sinter(keys.iter().copied(), 0, &mut take),
1803            "union" => d.sunion(keys.iter().copied(), 0, &mut take),
1804            "diff" => d.sdiff(keys.iter().copied(), 0, &mut take),
1805            other => unreachable!("{other}"),
1806        }
1807        .expect("sets");
1808        assert_eq!(n, got.len(), "the count and the members disagree");
1809        got.sort();
1810        got
1811    }
1812
1813    #[test]
1814    fn the_algebra_answers_what_the_sets_share_and_do_not() {
1815        let mut d = db();
1816        add(&mut d, b"a", &[b"1", b"2", b"3"]);
1817        add(&mut d, b"b", &[b"2", b"3", b"4"]);
1818        add(&mut d, b"c", &[b"3", b"4", b"5"]);
1819
1820        assert_eq!(algebra(&mut d, "inter", &[b"a", b"b", b"c"]), ["3"]);
1821        assert_eq!(
1822            algebra(&mut d, "union", &[b"a", b"b", b"c"]),
1823            ["1", "2", "3", "4", "5"]
1824        );
1825        assert_eq!(algebra(&mut d, "diff", &[b"a", b"b"]), ["1"]);
1826        assert_eq!(
1827            algebra(&mut d, "diff", &[b"a"]),
1828            ["1", "2", "3"],
1829            "one set is that set"
1830        );
1831        assert_eq!(
1832            d.sintercard([b"a".as_slice(), b"b"].into_iter(), 0)
1833                .expect("sets"),
1834            2
1835        );
1836        assert_eq!(
1837            d.sintercard([b"a".as_slice(), b"b"].into_iter(), 1)
1838                .expect("sets"),
1839            1,
1840            "and a limit stops it early"
1841        );
1842    }
1843
1844    /// A key that is not there is an empty set, and an empty set does three
1845    /// different things to the three operations.
1846    #[test]
1847    fn a_key_that_is_not_there_is_an_empty_set_everywhere() {
1848        let mut d = db();
1849        add(&mut d, b"a", &[b"1", b"2"]);
1850
1851        assert!(algebra(&mut d, "inter", &[b"a", b"nope"]).is_empty());
1852        assert!(algebra(&mut d, "inter", &[b"nope", b"a"]).is_empty());
1853        assert_eq!(algebra(&mut d, "union", &[b"a", b"nope"]), ["1", "2"]);
1854        assert_eq!(algebra(&mut d, "diff", &[b"a", b"nope"]), ["1", "2"]);
1855        assert!(
1856            algebra(&mut d, "diff", &[b"nope", b"a"]).is_empty(),
1857            "nothing minus anything is nothing"
1858        );
1859        assert!(algebra(&mut d, "union", &[b"nope"]).is_empty());
1860        assert_eq!(d.len(), 1, "and none of that made a key");
1861    }
1862
1863    #[test]
1864    fn a_store_form_writes_the_answer_and_says_how_big_it_is() {
1865        let mut d = db();
1866        add(&mut d, b"a", &[b"1", b"2", b"3"]);
1867        add(&mut d, b"b", &[b"2", b"3", b"4"]);
1868
1869        assert_eq!(
1870            d.sinterstore(b"d", [b"a".as_slice(), b"b"].into_iter())
1871                .expect("sets"),
1872            2
1873        );
1874        assert_eq!(members(&mut d, b"d"), ["2", "3"]);
1875        assert_eq!(
1876            d.sunionstore(b"d", [b"a".as_slice(), b"b"].into_iter())
1877                .expect("sets"),
1878            4
1879        );
1880        assert_eq!(members(&mut d, b"d"), ["1", "2", "3", "4"]);
1881        assert_eq!(
1882            d.sdiffstore(b"d", [b"a".as_slice(), b"b"].into_iter())
1883                .expect("sets"),
1884            1
1885        );
1886        assert_eq!(members(&mut d, b"d"), ["1"]);
1887        // An all integer answer stores as an intset, because the destination
1888        // picks its representation from what actually went into it.
1889        assert_eq!(d.encoding_name(b"d"), Some(Encoding::Intset.name()));
1890    }
1891
1892    /// The rule that makes an empty answer different from an empty set: the
1893    /// destination is deleted rather than left holding nothing.
1894    #[test]
1895    fn a_store_form_of_nothing_deletes_the_destination() {
1896        let mut d = db();
1897        add(&mut d, b"a", &[b"1"]);
1898        add(&mut d, b"b", &[b"2"]);
1899        add(&mut d, b"d", &[b"old"]);
1900
1901        assert_eq!(
1902            d.sinterstore(b"d", [b"a".as_slice(), b"b"].into_iter())
1903                .expect("sets"),
1904            0
1905        );
1906        assert_eq!(d.kind_of(b"d"), None, "the destination went, not emptied");
1907        assert!(!d.exists(b"d"));
1908
1909        // And the same for a difference that takes everything away, and for a
1910        // source that is not there at all.
1911        add(&mut d, b"d", &[b"old"]);
1912        assert_eq!(
1913            d.sdiffstore(b"d", [b"a".as_slice(), b"a"].into_iter())
1914                .expect("sets"),
1915            0
1916        );
1917        assert!(!d.exists(b"d"));
1918        add(&mut d, b"d", &[b"old"]);
1919        assert_eq!(
1920            d.sunionstore(b"d", [b"nope".as_slice()].into_iter())
1921                .expect("sets"),
1922            0
1923        );
1924        assert!(!d.exists(b"d"));
1925    }
1926
1927    /// The destination is allowed to be one of the sources, which only works
1928    /// because the answer is built whole before anything is written.
1929    #[test]
1930    fn a_store_form_can_write_over_one_of_its_own_sources() {
1931        let mut d = db();
1932        add(&mut d, b"a", &[b"1", b"2", b"3"]);
1933        add(&mut d, b"b", &[b"2", b"3", b"4"]);
1934
1935        assert_eq!(
1936            d.sinterstore(b"a", [b"a".as_slice(), b"b"].into_iter())
1937                .expect("sets"),
1938            2
1939        );
1940        assert_eq!(members(&mut d, b"a"), ["2", "3"]);
1941
1942        // The same key named twice is not a special case either.
1943        assert_eq!(
1944            d.sunionstore(b"a", [b"a".as_slice(), b"a"].into_iter())
1945                .expect("sets"),
1946            2
1947        );
1948        assert_eq!(members(&mut d, b"a"), ["2", "3"]);
1949    }
1950
1951    /// A destination that held something else is overwritten rather than
1952    /// refused, which is what Redis does and is the same rule `SET` follows.
1953    #[test]
1954    fn a_store_form_overwrites_whatever_the_destination_held() {
1955        let mut d = db();
1956        add(&mut d, b"a", &[b"1", b"2"]);
1957        d.set_plain(b"d", b"a string").expect("room");
1958        assert!(d.set_expiry(b"d", Some(9_999_999)));
1959
1960        assert_eq!(
1961            d.sunionstore(b"d", [b"a".as_slice()].into_iter())
1962                .expect("sets"),
1963            2
1964        );
1965        assert_eq!(d.kind_of(b"d"), Some(Kind::Set));
1966        assert_eq!(members(&mut d, b"d"), ["1", "2"]);
1967        assert_eq!(d.expire_at(b"d"), None, "and the deadline went with it");
1968    }
1969
1970    /// A bad key anywhere in the list fails the whole command, and it fails
1971    /// before the destination is touched rather than after.
1972    #[test]
1973    fn the_algebra_answers_wrongtype_before_it_writes_anything() {
1974        let mut d = db();
1975        add(&mut d, b"a", &[b"1"]);
1976        d.set_plain(b"str", b"v").expect("room");
1977        add(&mut d, b"d", &[b"old"]);
1978
1979        assert!(
1980            d.sinter([b"a".as_slice(), b"str"].into_iter(), 0, |_| ())
1981                .is_err()
1982        );
1983        assert!(
1984            d.sunion([b"str".as_slice()].into_iter(), 0, |_| ())
1985                .is_err()
1986        );
1987        assert!(
1988            d.sdiff([b"a".as_slice(), b"str"].into_iter(), 0, |_| ())
1989                .is_err()
1990        );
1991        assert!(
1992            d.sinterstore(b"d", [b"a".as_slice(), b"str"].into_iter())
1993                .is_err()
1994        );
1995        assert_eq!(members(&mut d, b"d"), ["old"], "and left it alone");
1996    }
1997
1998    /// Sets across all three representations, since the algebra is the only
1999    /// place where members have to cross from one to another.
2000    #[test]
2001    fn the_algebra_works_across_the_representations() {
2002        let mut d = db();
2003        let big: Vec<Vec<u8>> = (0..600).map(|i| i.to_string().into_bytes()).collect();
2004        let refs: Vec<&[u8]> = big.iter().map(Vec::as_slice).collect();
2005        d.sadd(b"table", refs.iter().copied()).expect("a set");
2006        add(&mut d, b"ints", &[b"1", b"2", b"999"]);
2007        add(&mut d, b"packed", &[b"2", b"3", b"x"]);
2008        assert_eq!(d.encoding_name(b"table"), Some(Encoding::Hashtable.name()));
2009        assert_eq!(d.encoding_name(b"ints"), Some(Encoding::Intset.name()));
2010        assert_eq!(d.encoding_name(b"packed"), Some(Encoding::Listpack.name()));
2011
2012        // A member of the intset is a number that has no digits anywhere and
2013        // the table holds that same member as its digits, so this only finds
2014        // anything if the two agree about what a member is.
2015        assert_eq!(algebra(&mut d, "inter", &[b"ints", b"table"]), ["1", "2"]);
2016        assert_eq!(algebra(&mut d, "inter", &[b"packed", b"table"]), ["2", "3"]);
2017        assert_eq!(algebra(&mut d, "inter", &[b"ints", b"packed"]), ["2"]);
2018        assert_eq!(algebra(&mut d, "diff", &[b"ints", b"table"]), ["999"]);
2019        assert_eq!(
2020            algebra(&mut d, "union", &[b"ints", b"packed"]),
2021            ["1", "2", "3", "999", "x"]
2022        );
2023    }
2024
2025    #[test]
2026    fn a_set_is_counted_in_what_the_database_is_holding() {
2027        let mut d = db();
2028        let before = d.memory_bytes();
2029        let owned: Vec<Vec<u8>> = (0..500).map(|i| i.to_string().into_bytes()).collect();
2030        let refs: Vec<&[u8]> = owned.iter().map(Vec::as_slice).collect();
2031        d.sadd(b"s", refs.iter().copied()).expect("a set");
2032
2033        let after = d.memory_bytes();
2034        assert!(
2035            after > before + 500,
2036            "five hundred members have to show up somewhere: {before} then {after}"
2037        );
2038        d.del(b"s");
2039        assert!(d.memory_bytes() < after, "and go away again");
2040    }
2041
2042    /// The sharp version of the memo hazard. `a` is resolved and remembered, so
2043    /// something is holding a slab slot number for it. Deleting `a` frees that
2044    /// slot and the next set created takes it, so a memo that survived the
2045    /// delete would answer questions about `a` with `b`'s members. It is not a
2046    /// stale count, it is another key's data under the name of a key that is
2047    /// gone.
2048    #[test]
2049    fn a_deleted_key_does_not_answer_with_whatever_took_its_slot() {
2050        let mut d = db();
2051        add(&mut d, b"a", &[b"x", b"y", b"z"]);
2052        assert_eq!(d.scard(b"a").expect("a set"), 3);
2053
2054        d.del(b"a");
2055        add(&mut d, b"b", &[b"one"]);
2056
2057        assert_eq!(d.scard(b"a").expect("gone"), 0);
2058        assert!(!d.sismember(b"a", b"x").expect("gone"));
2059        assert_eq!(d.scard(b"b").expect("a set"), 1);
2060    }
2061
2062    /// Same shape, one step further: the name comes back holding another type.
2063    /// A memo that answered from what it remembered would say the set is still
2064    /// there and hand back a slot that now belongs to a hash.
2065    #[test]
2066    fn a_key_that_comes_back_as_another_type_is_wrongtype() {
2067        let mut d = db();
2068        add(&mut d, b"k", &[b"x"]);
2069        assert_eq!(d.scard(b"k").expect("a set"), 1);
2070
2071        d.del(b"k");
2072        d.hset(b"k", [(&b"f"[..], &b"v"[..])].into_iter())
2073            .expect("a hash");
2074
2075        let err = d.scard(b"k").expect_err("a hash is not a set");
2076        assert_eq!(err.code(), Code::WrongType);
2077    }
2078
2079    /// A deadline passes without anyone writing to the map, so it is the one
2080    /// thing a write counter cannot see. The answer is that a dated key is
2081    /// never remembered in the first place, and this is what says so.
2082    #[test]
2083    fn a_key_with_a_deadline_still_expires_after_it_has_been_read() {
2084        let mut d = db();
2085        add(&mut d, b"k", &[b"x", b"y"]);
2086        assert_eq!(d.scard(b"k").expect("a set"), 2);
2087
2088        assert!(d.set_expiry(b"k", Some(1_500)));
2089        assert_eq!(d.scard(b"k").expect("still alive"), 2);
2090
2091        d.clock().advance(600);
2092        assert_eq!(d.scard(b"k").expect("past its deadline"), 0);
2093        assert!(!d.sismember(b"k", b"x").expect("past its deadline"));
2094    }
2095
2096    /// Two keys alternating, which is what a pipeline that is not on one key
2097    /// looks like. Each one has to answer for itself, so the comparison is the
2098    /// key bytes and not the hash.
2099    #[test]
2100    fn two_keys_in_a_row_do_not_answer_for_each_other() {
2101        let mut d = db();
2102        add(&mut d, b"a", &[b"1"]);
2103        add(&mut d, b"b", &[b"1", b"2", b"3"]);
2104        for _ in 0..8 {
2105            assert_eq!(d.scard(b"a").expect("a set"), 1);
2106            assert_eq!(d.scard(b"b").expect("a set"), 3);
2107        }
2108    }
2109
2110    /// `FLUSHDB` throws the map away and builds a fresh one, and a fresh one
2111    /// starts its write counter over. Nothing may survive that.
2112    #[test]
2113    fn a_flush_does_not_leave_the_last_key_behind() {
2114        let mut d = db();
2115        add(&mut d, b"k", &[b"x"]);
2116        assert_eq!(d.scard(b"k").expect("a set"), 1);
2117
2118        d.clear();
2119        assert_eq!(d.scard(b"k").expect("flushed"), 0);
2120    }
2121
2122    /// A key too long to remember is a key that is looked up every time, which
2123    /// is the old behaviour and has to keep working rather than fall through a
2124    /// branch that assumes something was written down.
2125    #[test]
2126    fn a_key_longer_than_the_memo_still_works() {
2127        let mut d = db();
2128        let long = vec![b'k'; 200];
2129        add(&mut d, &long, &[b"x", b"y"]);
2130        for _ in 0..4 {
2131            assert_eq!(d.scard(&long).expect("a set"), 2);
2132        }
2133        d.del(&long);
2134        assert_eq!(d.scard(&long).expect("gone"), 0);
2135    }
2136}