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.free_body(key);
653        let len = set.len();
654        let at = self.sets.insert(set);
655        let record = value::slot_record_len(false);
656        self.write_rec(key, record, |out| {
657            value::write_slot_record(out, Kind::Set, at, None);
658        });
659        self.bodies += 1;
660        len
661    }
662
663    /// Hand the set under `key` to `f`, or hand it `None` if there is no key.
664    ///
665    /// This is what the wire layer reaches for when one command wants the body
666    /// more than once. `SMEMBERS` needs the count for the reply header and then
667    /// the members, and `SMISMEMBER` needs one membership test per argument, and
668    /// going back through [`Keyspace::scard`] and [`Keyspace::sismember`] for
669    /// each of those is a key lookup a piece. One lookup, then a borrow of the
670    /// body for as long as the caller needs it.
671    ///
672    /// It is a callback rather than a returned `&Set` because the reap has to
673    /// happen under `&mut self` and the borrow checker will not let a `&Set`
674    /// carved out of that outlive the call.
675    pub fn with_set<R>(&mut self, key: &[u8], f: impl FnOnce(Option<&Set>) -> R) -> Result<R> {
676        let at = self.set_slot(key)?;
677        Ok(f(at.map(|at| self.set_at(at))))
678    }
679
680    /// The slot holding the set under `key`, having reaped a dead key first.
681    ///
682    /// `None` for a key that is not there, an error for a key holding something
683    /// that is not a set. Every command above starts here, so the three cases a
684    /// key can be in are decided once.
685    fn set_slot(&mut self, key: &[u8]) -> Result<Option<u32>> {
686        self.live_slot(key, Kind::Set)
687    }
688
689    /// The body in a slot the record pointed at.
690    ///
691    /// Panicking here means a record outlived its body, which is the one bug the
692    /// slab deliberately does not carry a generation counter to catch, so this
693    /// is where it would be caught instead.
694    #[inline]
695    fn set_at(&self, at: u32) -> &Set {
696        self.sets.get(at).expect("the record points at its body")
697    }
698
699    /// Make an empty set under `key` and answer which slot it went in.
700    ///
701    /// `first` and `hint` only pick the representation to start in, following
702    /// Redis's `setTypeCreate`, so that a `SADD` with a thousand arguments
703    /// builds a table once instead of converting twice on the way there.
704    fn new_set(&mut self, key: &[u8], first: &[u8], hint: usize) -> u32 {
705        // The body and, every so often, the slab that holds it. See
706        // `yo_alloc::first_touch` for why this is the one allocation a command
707        // is allowed to make.
708        let at =
709            yo_alloc::first_touch(|| self.sets.insert(Set::with_hint(first, hint, &self.limits)));
710        let len = value::slot_record_len(false);
711        self.write_rec(key, len, |out| {
712            value::write_slot_record(out, Kind::Set, at, None);
713        });
714        self.bodies += 1;
715        at
716    }
717}
718
719/// Where a set body is, when the search for it covered a whole database.
720///
721/// The stripe and then the slot in that stripe's slab. A slot number means
722/// nothing without the stripe it came from, since every stripe numbers its own
723/// from zero.
724type Home = (usize, u32);
725
726impl Db {
727    /// `SMOVE source destination member` over a database of any width.
728    ///
729    /// The two keys on one stripe are that stripe's `SMOVE`, which is the whole
730    /// command on a database of one. Otherwise the member is taken out of one
731    /// stripe and put into another, in the order the single stripe version
732    /// moves it: the destination is filled before the source is emptied, and the
733    /// source is only deleted once it is known to be empty.
734    ///
735    /// The checks are in Redis's order, which is not the order they look like
736    /// they should be in. A source that is not there answers zero without ever
737    /// looking at the destination, so a destination holding a string is not a
738    /// `WRONGTYPE` until the source turns out to be a set.
739    pub fn smove(&self, source: &[u8], destination: &[u8], member: &[u8]) -> Result<bool> {
740        let (from, onto) = (self.stripe_of(source), self.stripe_of(destination));
741        if from == onto {
742            return self.hold_stripe(from).smove(source, destination, member);
743        }
744        // Both at once and in stripe order, so the member is never in neither
745        // set and never in both. It was in neither for as long as it took to
746        // let go of the source and reach for the destination before this.
747        let mut held = self.hold_many([from, onto].into_iter());
748        let Some(at) = held.stripe_mut(from).set_slot(source)? else {
749            return Ok(false);
750        };
751        let there = held.stripe_mut(onto).set_slot(destination)?;
752        if !held
753            .stripe_mut(from)
754            .sets
755            .get_mut(at)
756            .expect("the record points at its body")
757            .remove(member)
758        {
759            return Ok(false);
760        }
761
762        let dest = held.stripe_mut(onto);
763        let limits = dest.limits;
764        let into = match there {
765            Some(into) => into,
766            None => dest.new_set(destination, member, 1),
767        };
768        dest.sets
769            .get_mut(into)
770            .expect("the record points at its body")
771            .add(member, &limits);
772
773        let src = held.stripe_mut(from);
774        if src.set_at(at).is_empty() {
775            src.drop_key(source);
776        }
777        Ok(true)
778    }
779
780    /// `SINTER key [key ...]`, and `SINTERCARD`'s limit.
781    pub fn sinter<'k, F>(
782        &self,
783        keys: impl Iterator<Item = &'k [u8]> + Clone,
784        limit: usize,
785        f: F,
786    ) -> Result<usize>
787    where
788        F: FnMut(&[u8]),
789    {
790        if let Some(home) = self.one_stripe(keys.clone()) {
791            return self.hold_stripe(home).sinter(keys, limit, f);
792        }
793        // The buffers before the stripes, which is the order every command
794        // that wants both takes them in.
795        let mut spare = self.spare();
796        let scratch = &mut spare.setops;
797        let mut held = self.hold_sets(keys.clone(), None);
798        let slots = self.set_slots(&mut held, keys)?;
799        if slots.is_empty() || slots.iter().any(Option::is_none) {
800            return Ok(0);
801        }
802        let sets = bodies_of(&held, &slots);
803        Ok(setops::inter(scratch, &sets, limit, f))
804    }
805
806    /// `SINTERCARD numkeys key [key ...] [LIMIT limit]`.
807    pub fn sintercard<'k>(
808        &self,
809        keys: impl Iterator<Item = &'k [u8]> + Clone,
810        limit: usize,
811    ) -> Result<usize> {
812        self.sinter(keys, limit, |_| {})
813    }
814
815    /// `SUNION key [key ...]`, and `SUNIONCARD`'s limit.
816    pub fn sunion<'k, F>(
817        &self,
818        keys: impl Iterator<Item = &'k [u8]> + Clone,
819        limit: usize,
820        f: F,
821    ) -> Result<usize>
822    where
823        F: FnMut(&[u8]),
824    {
825        if let Some(home) = self.one_stripe(keys.clone()) {
826            return self.hold_stripe(home).sunion(keys, limit, f);
827        }
828        // The buffers before the stripes, which is the order every command
829        // that wants both takes them in.
830        let mut spare = self.spare();
831        let scratch = &mut spare.setops;
832        let mut held = self.hold_sets(keys.clone(), None);
833        let slots = self.set_slots(&mut held, keys)?;
834        let sets = bodies_of(&held, &slots);
835        Ok(setops::union(scratch, &sets, limit, f))
836    }
837
838    /// `SUNIONCARD numkeys key [key ...] [LIMIT limit]`.
839    pub fn sunioncard<'k>(
840        &self,
841        keys: impl Iterator<Item = &'k [u8]> + Clone,
842        limit: usize,
843    ) -> Result<usize> {
844        self.sunion(keys, limit, |_| {})
845    }
846
847    /// `SDIFF key [key ...]`, and `SDIFFCARD`'s limit.
848    pub fn sdiff<'k, F>(
849        &self,
850        keys: impl Iterator<Item = &'k [u8]> + Clone,
851        limit: usize,
852        f: F,
853    ) -> Result<usize>
854    where
855        F: FnMut(&[u8]),
856    {
857        if let Some(home) = self.one_stripe(keys.clone()) {
858            return self.hold_stripe(home).sdiff(keys, limit, f);
859        }
860        let mut held = self.hold_sets(keys.clone(), None);
861        let slots = self.set_slots(&mut held, keys)?;
862        let Some(Some(_)) = slots.first() else {
863            return Ok(0);
864        };
865        let sets = bodies_of(&held, &slots);
866        Ok(setops::diff(&sets, limit, f))
867    }
868
869    /// `SDIFFCARD numkeys key [key ...] [LIMIT limit]`.
870    pub fn sdiffcard<'k>(
871        &self,
872        keys: impl Iterator<Item = &'k [u8]> + Clone,
873        limit: usize,
874    ) -> Result<usize> {
875        self.sdiff(keys, limit, |_| {})
876    }
877
878    /// `SINTERSTORE destination key [key ...]`. Answers the size of the result.
879    ///
880    /// The result is built whole before the destination is touched, exactly as
881    /// it is on one stripe, which is what makes a destination that is also a
882    /// source work. The limits and the slab the answer goes into are the
883    /// destination's stripe's, since that is where the set is going to live.
884    pub fn sinterstore<'k>(
885        &self,
886        destination: &'k [u8],
887        keys: impl Iterator<Item = &'k [u8]> + Clone,
888    ) -> Result<usize> {
889        if let Some(home) = self.one_stripe(std::iter::once(destination).chain(keys.clone())) {
890            return self.hold_stripe(home).sinterstore(destination, keys);
891        }
892        // The buffers before the stripes, which is the order every command
893        // that wants both takes them in.
894        let mut spare = self.spare();
895        let scratch = &mut spare.setops;
896        let onto = self.stripe_of(destination);
897        let mut held = self.hold_sets(keys.clone(), Some(destination));
898        let slots = self.set_slots(&mut held, keys)?;
899        let built = if slots.is_empty() || slots.iter().any(Option::is_none) {
900            None
901        } else {
902            let limits = held.stripe(onto).limits;
903            let sets = bodies_of(&held, &slots);
904            let upper = sets.iter().map(|s| s.len()).min().unwrap_or(0);
905            setops::collect(upper, &limits, |f| {
906                setops::inter(scratch, &sets, 0, f);
907            })
908        };
909        Ok(held.stripe_mut(onto).put_set(destination, built))
910    }
911
912    /// `SUNIONSTORE destination key [key ...]`.
913    pub fn sunionstore<'k>(
914        &self,
915        destination: &'k [u8],
916        keys: impl Iterator<Item = &'k [u8]> + Clone,
917    ) -> Result<usize> {
918        if let Some(home) = self.one_stripe(std::iter::once(destination).chain(keys.clone())) {
919            return self.hold_stripe(home).sunionstore(destination, keys);
920        }
921        // The buffers before the stripes, which is the order every command
922        // that wants both takes them in.
923        let mut spare = self.spare();
924        let scratch = &mut spare.setops;
925        let onto = self.stripe_of(destination);
926        let mut held = self.hold_sets(keys.clone(), Some(destination));
927        let slots = self.set_slots(&mut held, keys)?;
928        let built = {
929            let limits = held.stripe(onto).limits;
930            let sets = bodies_of(&held, &slots);
931            let upper = sets.iter().map(|s| s.len()).sum();
932            setops::collect(upper, &limits, |f| {
933                setops::union(scratch, &sets, 0, f);
934            })
935        };
936        Ok(held.stripe_mut(onto).put_set(destination, built))
937    }
938
939    /// `SDIFFSTORE destination key [key ...]`.
940    pub fn sdiffstore<'k>(
941        &self,
942        destination: &'k [u8],
943        keys: impl Iterator<Item = &'k [u8]> + Clone,
944    ) -> Result<usize> {
945        if let Some(home) = self.one_stripe(std::iter::once(destination).chain(keys.clone())) {
946            return self.hold_stripe(home).sdiffstore(destination, keys);
947        }
948        let onto = self.stripe_of(destination);
949        let mut held = self.hold_sets(keys.clone(), Some(destination));
950        let slots = self.set_slots(&mut held, keys)?;
951        let built = match slots.first() {
952            Some(Some(_)) => {
953                let limits = held.stripe(onto).limits;
954                let sets = bodies_of(&held, &slots);
955                let upper = sets[0].len();
956                setops::collect(upper, &limits, |f| {
957                    setops::diff(&sets, 0, f);
958                })
959            }
960            _ => None,
961        };
962        Ok(held.stripe_mut(onto).put_set(destination, built))
963    }
964
965    /// Every stripe a set operation names, held at once, in stripe order.
966    ///
967    /// Before anything is resolved rather than after, because a slot number is
968    /// only good while the stripe it came from is held: let go of it and the key
969    /// can be deleted and the slot handed to something else, and what was read
970    /// back would be a different set under the same number. Taken in stripe
971    /// order, which is what keeps two of these from waiting on each other.
972    #[inline]
973    fn hold_sets<'k>(
974        &self,
975        keys: impl Iterator<Item = &'k [u8]>,
976        destination: Option<&[u8]>,
977    ) -> Holds<'_> {
978        let named = keys.map(|key| self.stripe_of(key));
979        self.hold_many(named.chain(destination.map(|d| self.stripe_of(d))))
980    }
981
982    /// Reap and resolve every key, in order, to the stripe and slot its set is
983    /// in.
984    ///
985    /// As [`Keyspace::set_slots`], including the part that matters most: the
986    /// first key holding something that is not a set stops the whole command
987    /// before anything has been written. Each key is resolved on the stripe it
988    /// is on, out of the ones already held, which is the only difference.
989    fn set_slots<'k>(
990        &self,
991        held: &mut Holds<'_>,
992        keys: impl Iterator<Item = &'k [u8]>,
993    ) -> Result<PerSet<Option<Home>>> {
994        let mut out = PerSet::new();
995        for key in keys {
996            let stripe = self.stripe_of(key);
997            let at = held.stripe_mut(stripe).set_slot(key)?;
998            out.push(at.map(|at| (stripe, at)));
999        }
1000        Ok(out)
1001    }
1002}
1003
1004/// The bodies those slots point at, with the keys that were not there gone.
1005#[inline]
1006fn bodies_of<'h>(held: &'h Holds<'_>, slots: &[Option<Home>]) -> PerSet<&'h Set> {
1007    slots
1008        .iter()
1009        .flatten()
1010        .map(|&(stripe, at)| held.stripe(stripe).set_at(at))
1011        .collect()
1012}
1013
1014#[cfg(test)]
1015mod tests {
1016    use super::*;
1017    use crate::Clock;
1018    use crate::set::Encoding;
1019    use yo_common::Code;
1020
1021    fn db() -> Keyspace {
1022        Keyspace::with_clock(Clock::fixed(1_000))
1023    }
1024
1025    fn add(d: &mut Keyspace, key: &[u8], members: &[&[u8]]) -> usize {
1026        d.sadd(key, members.iter().copied()).expect("a set")
1027    }
1028
1029    fn members(d: &mut Keyspace, key: &[u8]) -> Vec<String> {
1030        let mut v: Vec<String> = d
1031            .smembers(key)
1032            .expect("a set")
1033            .expect("a key")
1034            .map(|m| String::from_utf8(m.to_vec()).expect("utf8 in these tests"))
1035            .collect();
1036        v.sort();
1037        v
1038    }
1039
1040    /// `SUNION` built a hash table out of the allocator on every call, and over
1041    /// text sets that table was most of what the command did.
1042    #[test]
1043    fn a_union_over_text_sets_does_not_allocate_once_its_table_is_warm() {
1044        let mut d = db();
1045        add(&mut d, b"a", &[b"alpha", b"beta", b"gamma", b"delta"]);
1046        add(&mut d, b"b", &[b"gamma", b"delta", b"epsilon", b"zeta"]);
1047        // One call to grow the table to the size of this union. Everything
1048        // after it reuses what that one bought.
1049        assert_eq!(
1050            d.sunion([b"a".as_slice(), b"b"].into_iter(), 0, |_| {}),
1051            Ok(6)
1052        );
1053        let (_, allocs) = crate::tally::counted(|| {
1054            for _ in 0..50 {
1055                assert_eq!(
1056                    d.sunion([b"a".as_slice(), b"b"].into_iter(), 0, |_| {}),
1057                    Ok(6)
1058                );
1059            }
1060        });
1061        assert_eq!(allocs, 0, "sunion allocated {allocs} times in fifty");
1062    }
1063
1064    /// And it still answers when the union is bigger than any before it, which
1065    /// is the case the reserve is there for.
1066    #[test]
1067    fn a_union_larger_than_the_last_one_grows_the_table_and_is_still_right() {
1068        let mut d = db();
1069        add(&mut d, b"a", &[b"one", b"two"]);
1070        add(&mut d, b"b", &[b"two", b"three"]);
1071        assert_eq!(
1072            d.sunion([b"a".as_slice(), b"b"].into_iter(), 0, |_| {}),
1073            Ok(3)
1074        );
1075
1076        let many: Vec<Vec<u8>> = (0..500).map(|i| format!("m{i}").into_bytes()).collect();
1077        let refs: Vec<&[u8]> = many.iter().map(Vec::as_slice).collect();
1078        add(&mut d, b"c", &refs);
1079        let mut seen = Vec::new();
1080        assert_eq!(
1081            d.sunion([b"a".as_slice(), b"c"].into_iter(), 0, |m: &[u8]| seen
1082                .push(m.to_vec())),
1083            Ok(502)
1084        );
1085        seen.sort();
1086        seen.dedup();
1087        assert_eq!(seen.len(), 502, "every member came back once");
1088
1089        // And back down again, which is the direction that would break if the
1090        // table were only ever grown and not cleared.
1091        assert_eq!(
1092            d.sunion([b"a".as_slice(), b"b"].into_iter(), 0, |_| {}),
1093            Ok(3)
1094        );
1095    }
1096
1097    #[test]
1098    fn adding_to_a_key_that_is_not_there_makes_it() {
1099        let mut d = db();
1100        assert_eq!(add(&mut d, b"s", &[b"a", b"b", b"c"]), 3);
1101        assert_eq!(d.scard(b"s").expect("a set"), 3);
1102        assert_eq!(d.kind_of(b"s"), Some(Kind::Set));
1103        assert_eq!(members(&mut d, b"s"), ["a", "b", "c"]);
1104        assert_eq!(d.len(), 1, "one key, whatever the set holds");
1105    }
1106
1107    #[test]
1108    fn adding_answers_how_many_were_new_and_not_how_many_arrived() {
1109        let mut d = db();
1110        assert_eq!(add(&mut d, b"s", &[b"a", b"b"]), 2);
1111        assert_eq!(add(&mut d, b"s", &[b"b", b"c"]), 1);
1112        assert_eq!(
1113            add(&mut d, b"s", &[b"x", b"x", b"x"]),
1114            1,
1115            "the same member three times in one call is one member"
1116        );
1117        assert_eq!(d.scard(b"s").expect("a set"), 4);
1118    }
1119
1120    #[test]
1121    fn everything_answers_for_a_key_that_is_not_there() {
1122        let mut d = db();
1123        assert_eq!(d.scard(b"nope").expect("missing is fine"), 0);
1124        assert!(!d.sismember(b"nope", b"a").expect("missing is fine"));
1125        assert!(d.smembers(b"nope").expect("missing is fine").is_none());
1126        assert_eq!(
1127            d.srem(b"nope", [b"a".as_slice()].into_iter()).expect("ok"),
1128            0
1129        );
1130        assert_eq!(
1131            d.smismember(b"nope", [b"a".as_slice(), b"b"].into_iter())
1132                .expect("ok"),
1133            [false, false]
1134        );
1135        assert_eq!(d.len(), 0, "and none of that created anything");
1136    }
1137
1138    #[test]
1139    fn membership_answers_for_members_and_strangers() {
1140        let mut d = db();
1141        add(&mut d, b"s", &[b"a", b"b"]);
1142        assert!(d.sismember(b"s", b"a").expect("a set"));
1143        assert!(!d.sismember(b"s", b"z").expect("a set"));
1144        assert_eq!(
1145            d.smismember(b"s", [b"a".as_slice(), b"z", b"b"].into_iter())
1146                .expect("a set"),
1147            [true, false, true]
1148        );
1149    }
1150
1151    #[test]
1152    fn removing_the_last_member_removes_the_key() {
1153        // An empty set does not exist in Redis and it does not exist here.
1154        let mut d = db();
1155        add(&mut d, b"s", &[b"a", b"b"]);
1156        assert_eq!(d.srem(b"s", [b"a".as_slice()].into_iter()).expect("ok"), 1);
1157        assert!(d.exists(b"s"), "one member left");
1158
1159        assert_eq!(
1160            d.srem(b"s", [b"b".as_slice(), b"gone"].into_iter())
1161                .expect("ok"),
1162            1,
1163            "one of the two was there"
1164        );
1165        assert!(!d.exists(b"s"), "and now the key is gone with it");
1166        assert_eq!(d.kind_of(b"s"), None);
1167        assert_eq!(d.len(), 0);
1168    }
1169
1170    #[test]
1171    fn a_set_is_deleted_body_and_all() {
1172        // The leak this guards against is invisible from the outside: the key
1173        // goes, the slot does not, and nothing ever notices. So the test asks
1174        // the slab directly, because that is the only place the answer shows.
1175        let mut d = db();
1176        add(&mut d, b"s", &[b"a", b"b"]);
1177        assert_eq!(d.sets.len(), 1);
1178
1179        assert!(d.del(b"s"));
1180        assert_eq!(d.sets.len(), 0, "the body went with the key");
1181        assert_eq!(d.bodies, 0);
1182
1183        // And the slot is reused rather than abandoned.
1184        add(&mut d, b"t", &[b"x"]);
1185        assert_eq!(d.sets.len(), 1);
1186    }
1187
1188    #[test]
1189    fn writing_a_string_over_a_set_takes_the_body_with_it() {
1190        // SET is allowed to overwrite any type, so this is not WRONGTYPE. What
1191        // it must not be is a set left in the slab with nothing pointing at it.
1192        let mut d = db();
1193        add(&mut d, b"k", &[b"a", b"b"]);
1194        assert_eq!(d.sets.len(), 1);
1195
1196        d.set_plain(b"k", b"now a string").expect("room");
1197        assert_eq!(d.sets.len(), 0, "the set went when it was written over");
1198        assert_eq!(d.bodies, 0);
1199        assert_eq!(d.kind_of(b"k"), Some(Kind::String));
1200        assert_eq!(
1201            d.get(b"k").expect("a string").map(|v| v.to_vec()),
1202            Some(b"now a string".to_vec())
1203        );
1204    }
1205
1206    #[test]
1207    fn a_set_that_expires_takes_its_body_with_it() {
1208        let mut d = db();
1209        add(&mut d, b"s", &[b"a"]);
1210        assert!(d.set_expiry(b"s", Some(1_100)));
1211        assert_eq!(d.expire_at(b"s"), Some(1_100));
1212        assert_eq!(d.sets.len(), 1);
1213        assert_eq!(d.scard(b"s").expect("a set"), 1, "still alive at 1000");
1214
1215        d.clock().advance(100);
1216        assert_eq!(d.scard(b"s").expect("gone is not an error"), 0);
1217        assert_eq!(d.sets.len(), 0, "reaping freed the body");
1218        assert_eq!(d.bodies, 0);
1219        assert_eq!(d.expired_keys(), 1);
1220    }
1221
1222    #[test]
1223    fn flushing_takes_every_body_with_it() {
1224        let mut d = db();
1225        for i in 0..10 {
1226            add(&mut d, format!("s{i}").as_bytes(), &[b"a", b"b"]);
1227        }
1228        assert_eq!(d.sets.len(), 10);
1229
1230        d.clear();
1231        assert_eq!(d.sets.len(), 0);
1232        assert_eq!(d.bodies, 0);
1233        assert_eq!(d.len(), 0);
1234    }
1235
1236    #[test]
1237    fn a_set_command_at_a_string_is_wrongtype() {
1238        let mut d = db();
1239        d.set_plain(b"k", b"v").expect("room");
1240
1241        let err = d.sadd(b"k", [b"a".as_slice()].into_iter()).expect_err("no");
1242        assert_eq!(err.code(), Code::WrongType);
1243        assert_eq!(
1244            err.message(),
1245            "Operation against a key holding the wrong kind of value"
1246        );
1247        assert!(d.scard(b"k").is_err());
1248        assert!(d.sismember(b"k", b"a").is_err());
1249        assert!(d.smembers(b"k").is_err());
1250        assert!(d.srem(b"k", [b"a".as_slice()].into_iter()).is_err());
1251        assert!(d.smismember(b"k", [b"a".as_slice()].into_iter()).is_err());
1252        assert_eq!(
1253            d.get(b"k").expect("still a string").map(|v| v.to_vec()),
1254            Some(b"v".to_vec()),
1255            "and none of that damaged it"
1256        );
1257    }
1258
1259    #[test]
1260    fn a_string_command_at_a_set_is_wrongtype() {
1261        let mut d = db();
1262        add(&mut d, b"s", &[b"a"]);
1263
1264        assert_eq!(d.get(b"s").expect_err("no").code(), Code::WrongType);
1265        assert!(d.strlen(b"s").is_err());
1266        assert!(d.getrange(b"s", 0, -1).is_err());
1267        assert!(d.getdel(b"s").is_err());
1268        assert!(d.incr(b"s").is_err());
1269        assert!(d.append(b"s", b"x").is_err());
1270        assert_eq!(d.scard(b"s").expect("a set"), 1, "and it is still a set");
1271    }
1272
1273    #[test]
1274    fn the_commands_that_do_not_care_still_do_not_care() {
1275        // EXISTS, DEL, TYPE and the TTL commands work on any type in Redis, and
1276        // a WRONGTYPE from one of them would be a bug and not a strictness.
1277        let mut d = db();
1278        add(&mut d, b"s", &[b"a"]);
1279
1280        assert!(d.exists(b"s"));
1281        assert_eq!(d.kind_of(b"s"), Some(Kind::Set));
1282        assert_eq!(d.encoding_name(b"s"), Some("listpack"));
1283        assert!(d.set_expiry(b"s", Some(6_000)));
1284        assert_eq!(d.expire_at(b"s"), Some(6_000));
1285        assert!(d.set_expiry(b"s", None), "and PERSIST takes it off again");
1286        assert_eq!(d.expire_at(b"s"), None);
1287        assert_eq!(d.scard(b"s").expect("a set"), 1, "through all of that");
1288        assert!(d.del(b"s"));
1289    }
1290
1291    #[test]
1292    fn mget_says_nil_for_a_set_rather_than_failing() {
1293        // The one string command that does not answer WRONGTYPE. Redis
1294        // documents MGET as giving nil for a key of the wrong type, because the
1295        // alternative is one bad key failing a hundred good ones.
1296        let mut d = db();
1297        d.set_plain(b"a", b"1").expect("room");
1298        add(&mut d, b"s", &[b"x"]);
1299        d.set_plain(b"z", b"2").expect("room");
1300
1301        let got: Vec<Option<Vec<u8>>> = d
1302            .mget(&[b"a", b"s", b"z", b"nope"])
1303            .into_iter()
1304            .map(|v| v.map(|s| s.to_vec()))
1305            .collect();
1306        assert_eq!(got, [Some(b"1".to_vec()), None, Some(b"2".to_vec()), None]);
1307    }
1308
1309    #[test]
1310    fn the_representation_follows_the_members_through_the_keyspace() {
1311        // The same ladder set.rs tests, but reached the way a client reaches it,
1312        // to prove the body that gets promoted is the body the record points at
1313        // and not a copy that was left behind.
1314        let mut d = db();
1315        add(&mut d, b"s", &[b"1", b"2", b"3"]);
1316        assert_eq!(d.set_encoding(b"s"), Some(Encoding::Intset));
1317
1318        add(&mut d, b"s", &[b"hello"]);
1319        assert_eq!(d.set_encoding(b"s"), Some(Encoding::Listpack));
1320        assert_eq!(members(&mut d, b"s"), ["1", "2", "3", "hello"]);
1321
1322        let long: Vec<u8> = vec![b'z'; 100];
1323        add(&mut d, b"s", &[&long]);
1324        assert_eq!(d.set_encoding(b"s"), Some(Encoding::Hashtable));
1325        assert_eq!(d.scard(b"s").expect("a set"), 5);
1326        assert!(d.sismember(b"s", b"1").expect("a set"), "nothing was lost");
1327        assert!(d.sismember(b"s", &long).expect("a set"));
1328    }
1329
1330    #[test]
1331    fn a_thousand_members_at_once_builds_a_table_without_converting() {
1332        let mut d = db();
1333        let owned: Vec<Vec<u8>> = (0..1000).map(|i| format!("m{i}").into_bytes()).collect();
1334        let refs: Vec<&[u8]> = owned.iter().map(Vec::as_slice).collect();
1335        assert_eq!(d.sadd(b"s", refs.iter().copied()).expect("a set"), 1000);
1336        assert_eq!(d.set_encoding(b"s"), Some(Encoding::Hashtable));
1337        assert_eq!(d.scard(b"s").expect("a set"), 1000);
1338    }
1339
1340    /// A set of `n` members named `m0` up, which is a table past 128.
1341    fn many(d: &mut Keyspace, key: &[u8], n: usize) {
1342        let owned: Vec<Vec<u8>> = (0..n).map(|i| format!("m{i}").into_bytes()).collect();
1343        let refs: Vec<&[u8]> = owned.iter().map(Vec::as_slice).collect();
1344        d.sadd(key, refs.iter().copied()).expect("a set");
1345    }
1346
1347    /// `many`, and integers instead of names when asked, so a test can reach
1348    /// the intset band as well as the other two.
1349    fn fill(d: &mut Keyspace, key: &[u8], n: usize, ints: bool) {
1350        let owned: Vec<Vec<u8>> = (0..n)
1351            .map(|i| {
1352                if ints {
1353                    i.to_string().into_bytes()
1354                } else {
1355                    format!("m{i}").into_bytes()
1356                }
1357            })
1358            .collect();
1359        let refs: Vec<&[u8]> = owned.iter().map(Vec::as_slice).collect();
1360        d.sadd(key, refs.iter().copied()).expect("a set");
1361    }
1362
1363    fn drawn(d: &mut Keyspace, key: &[u8], count: i64) -> Vec<String> {
1364        let mut out = Vec::new();
1365        d.srandmember_n(key, count, |m| {
1366            out.push(String::from_utf8(m.to_vec()).expect("utf8 in these tests"));
1367        })
1368        .expect("a set");
1369        out
1370    }
1371
1372    #[test]
1373    fn popping_takes_a_member_out_and_the_key_with_the_last_one() {
1374        let mut d = db();
1375        add(&mut d, b"s", &[b"a", b"b"]);
1376        let first = d.spop(b"s").expect("a set").expect("two members");
1377        assert_eq!(d.scard(b"s").expect("a set"), 1);
1378
1379        let second = d.spop(b"s").expect("a set").expect("one member");
1380        assert_ne!(first, second, "the same member came back twice");
1381        assert!(!d.exists(b"s"), "the last member took the key");
1382        assert_eq!(d.sets.len(), 0, "and the body");
1383        assert_eq!(d.spop(b"s").expect("gone is not an error"), None);
1384    }
1385
1386    #[test]
1387    fn popping_a_count_empties_a_set_without_repeating_itself() {
1388        // In all three representations, because the table moves its last row
1389        // into the hole and the other two shift, and a draw that assumed either
1390        // one would repeat a member or run off the end.
1391        for n in [4usize, 100, 300] {
1392            let mut d = db();
1393            many(&mut d, b"s", n);
1394            let got = d.spop_n(b"s", n + 10).expect("a set");
1395            assert_eq!(got.len(), n, "asked for more than there was");
1396            let mut sorted = got.clone();
1397            sorted.sort();
1398            sorted.dedup();
1399            assert_eq!(sorted.len(), n, "a member came back twice");
1400            assert!(!d.exists(b"s"));
1401            assert_eq!(d.sets.len(), 0);
1402        }
1403    }
1404
1405    #[test]
1406    fn popping_part_of_a_set_leaves_the_rest_of_it() {
1407        let mut d = db();
1408        many(&mut d, b"s", 10);
1409        let got = d.spop_n(b"s", 4).expect("a set");
1410        assert_eq!(got.len(), 4);
1411        assert_eq!(d.scard(b"s").expect("a set"), 6);
1412        for m in &got {
1413            assert!(!d.sismember(b"s", m).expect("a set"), "still there");
1414        }
1415        assert_eq!(
1416            d.spop_n(b"s", 0).expect("a set").len(),
1417            0,
1418            "and zero is none"
1419        );
1420        assert_eq!(d.scard(b"s").expect("a set"), 6);
1421    }
1422
1423    #[test]
1424    fn the_borrowing_draw_pops_the_same_set_the_copying_one_does() {
1425        // Same seed, same set, same members in the same order. If the two ever
1426        // disagree then the wire and the embedded API answer differently for
1427        // the same command, which is the one thing there is no excuse for.
1428        for n in [4usize, 100, 300] {
1429            let mut a = db();
1430            a.seed(20_260_829);
1431            many(&mut a, b"s", n);
1432            let copied = a.spop_n(b"s", n).expect("a set");
1433
1434            let mut b = db();
1435            b.seed(20_260_829);
1436            many(&mut b, b"s", n);
1437            let mut borrowed = Vec::new();
1438            b.spop_into(b"s", n, |m| borrowed.push(m.to_vec()))
1439                .expect("a set");
1440
1441            assert_eq!(copied, borrowed, "{n} members drew differently");
1442            assert!(!b.exists(b"s"), "the last member took the key");
1443            assert_eq!(b.sets.len(), 0, "and the body");
1444        }
1445    }
1446
1447    #[test]
1448    fn the_borrowing_draw_allocates_nothing() {
1449        // Every representation, because each takes a member out its own way:
1450        // the intset shifts an array of integers, the listpack shifts bytes,
1451        // and the table moves its last row into the hole. Also the whole set
1452        // rather than part of it, so the key deletion at the end is inside the
1453        // measurement and not just the draw.
1454        for n in [4usize, 100, 300] {
1455            for ints in [false, true] {
1456                let mut d = db();
1457                fill(&mut d, b"s", n, ints);
1458                let (drawn, allocs) = crate::tally::counted(|| {
1459                    let mut bytes = 0;
1460                    let mut count = 0;
1461                    d.spop_into(b"s", n, |m| {
1462                        // Read the member here rather than keep it, which is
1463                        // what the reply buffer does with it on the wire.
1464                        bytes += m.byte_len();
1465                        count += 1;
1466                    })
1467                    .expect("a set");
1468                    (bytes, count)
1469                });
1470                assert_eq!(drawn.1, n, "{n} members, ints {ints}");
1471                assert!(drawn.0 > 0, "the members came back empty");
1472                assert_eq!(
1473                    allocs, 0,
1474                    "{n} members, ints {ints}: {allocs} allocations on the way out"
1475                );
1476            }
1477        }
1478    }
1479
1480    /// The `k` sized bookkeeping a set operation does before it starts is gone.
1481    /// It used to be five vectors across `set_slots`, `bodies_of` and `setops`,
1482    /// each a malloc and a free, on a command whose real work over three eight
1483    /// member sets is a couple of hundred nanoseconds.
1484    ///
1485    /// On integer sets that leaves nothing at all, because the merge walks the
1486    /// sorted arrays and needs no table. On the other representations `SUNION`
1487    /// and `SDIFF` still build one hash table each to dedupe with, which is
1488    /// sized by the members rather than by the number of keys and is the
1489    /// algorithm rather than the bookkeeping.
1490    #[test]
1491    fn a_small_set_operation_stops_paying_per_key() {
1492        for (ints, want) in [(true, 0), (false, 6)] {
1493            let mut d = db();
1494            fill(&mut d, b"a", 8, ints);
1495            fill(&mut d, b"b", 8, ints);
1496            fill(&mut d, b"c", 8, ints);
1497            let keys: [&[u8]; 3] = [b"a", b"b", b"c"];
1498
1499            let (found, allocs) = crate::tally::counted(|| {
1500                let mut n = 0;
1501                d.sinter(keys.iter().copied(), 0, |_| n += 1).expect("sets");
1502                d.sunion(keys.iter().copied(), 0, |_| n += 1).expect("sets");
1503                d.sdiff(keys.iter().copied(), 0, |_| n += 1).expect("sets");
1504                n
1505            });
1506            assert!(found > 0, "ints {ints}: the operations found nothing");
1507            assert_eq!(
1508                allocs, want,
1509                "ints {ints}: {allocs} allocations for three ops, wanted {want}"
1510            );
1511        }
1512    }
1513
1514    /// And past the inline room it still works, which is the half of `Small`
1515    /// that only the rare command reaches.
1516    #[test]
1517    fn a_wide_set_operation_still_answers() {
1518        let wide = crate::setops::INLINE_KEYS + 3;
1519        let mut d = db();
1520        let names: Vec<Vec<u8>> = (0..wide).map(|i| format!("k{i}").into_bytes()).collect();
1521        for name in &names {
1522            fill(&mut d, name, 8, true);
1523        }
1524        let keys = || names.iter().map(|k| k.as_slice());
1525        let mut inter = 0;
1526        d.sinter(keys(), 0, |_| inter += 1).expect("sets");
1527        // Every set holds the same eight members, so they all survive.
1528        assert_eq!(inter, 8);
1529        let mut union = 0;
1530        d.sunion(keys(), 0, |_| union += 1).expect("sets");
1531        assert_eq!(union, 8);
1532    }
1533
1534    #[test]
1535    fn the_copying_draw_allocates_a_member_at_a_time() {
1536        // The other half of it. `spop_n` stays for the embedded caller who
1537        // wants the answer in one piece, and this is what that shape costs,
1538        // which is the whole reason the borrowing draw exists.
1539        let mut d = db();
1540        many(&mut d, b"s", 100);
1541        let (got, allocs) = crate::tally::counted(|| d.spop_n(b"s", 100).expect("a set"));
1542        assert_eq!(got.len(), 100);
1543        assert!(allocs >= 100, "only {allocs} allocations for a hundred");
1544    }
1545
1546    #[test]
1547    fn a_pinned_seed_draws_the_same_members_twice() {
1548        // The one input that makes a result unrepeatable, handed in rather than
1549        // reached for. Without this there is nothing to assert about a draw
1550        // except that something came back.
1551        let mut runs = Vec::new();
1552        for _ in 0..2 {
1553            let mut d = db();
1554            d.seed(20_260_828);
1555            many(&mut d, b"s", 50);
1556            runs.push(d.spop_n(b"s", 10).expect("a set"));
1557        }
1558        assert_eq!(runs[0], runs[1]);
1559    }
1560
1561    #[test]
1562    fn a_single_draw_reaches_every_member_and_removes_none() {
1563        let mut d = db();
1564        d.seed(7);
1565        add(&mut d, b"s", &[b"a", b"b", b"c"]);
1566        let mut seen = std::collections::HashSet::new();
1567        for _ in 0..200 {
1568            let got = d
1569                .srandmember(b"s", |m| m.map(|m| m.to_vec()))
1570                .expect("a set")
1571                .expect("a member");
1572            seen.insert(got);
1573        }
1574        assert_eq!(seen.len(), 3, "a draw that never reaches a member");
1575        assert_eq!(d.scard(b"s").expect("a set"), 3, "and nothing was taken");
1576
1577        assert!(
1578            d.srandmember(b"nope", |m| m.map(|m| m.to_vec()))
1579                .expect("missing is fine")
1580                .is_none()
1581        );
1582    }
1583
1584    #[test]
1585    fn a_negative_count_repeats_itself_and_a_positive_one_does_not() {
1586        let mut d = db();
1587        d.seed(11);
1588        add(&mut d, b"s", &[b"a", b"b", b"c"]);
1589
1590        let with_repeats = drawn(&mut d, b"s", -20);
1591        assert_eq!(with_repeats.len(), 20, "more members than the set holds");
1592
1593        let mut distinct = drawn(&mut d, b"s", 2);
1594        distinct.sort();
1595        distinct.dedup();
1596        assert_eq!(distinct.len(), 2);
1597    }
1598
1599    #[test]
1600    fn asking_for_more_than_the_set_holds_answers_all_of_it_once() {
1601        let mut d = db();
1602        d.seed(3);
1603        add(&mut d, b"s", &[b"a", b"b", b"c"]);
1604        let mut got = drawn(&mut d, b"s", 99);
1605        got.sort();
1606        assert_eq!(got, ["a", "b", "c"]);
1607        assert_eq!(drawn(&mut d, b"s", 0).len(), 0);
1608        assert_eq!(drawn(&mut d, b"nope", 5).len(), 0);
1609        assert_eq!(drawn(&mut d, b"nope", -5).len(), 0);
1610    }
1611
1612    #[test]
1613    fn both_ways_of_drawing_distinct_members_are_distinct_and_uniform() {
1614        // The two branches of `srandmember_n`, either side of the third. A
1615        // thousand members and a draw of two hits the rejection branch, and the
1616        // same set with a draw of nine hundred hits the selection walk.
1617        let mut d = db();
1618        d.seed(99);
1619        many(&mut d, b"s", 1000);
1620
1621        for count in [2, 100, 400, 900] {
1622            let got = drawn(&mut d, b"s", count);
1623            let mut sorted = got.clone();
1624            sorted.sort();
1625            sorted.dedup();
1626            assert_eq!(
1627                sorted.len(),
1628                got.len(),
1629                "a draw of {count} repeated a member"
1630            );
1631            assert_eq!(got.len(), count as usize);
1632        }
1633
1634        // And every member is reachable by both, which a walk that stopped
1635        // early or a draw that never reached the top would not manage.
1636        let mut seen = std::collections::HashSet::new();
1637        for _ in 0..40 {
1638            seen.extend(drawn(&mut d, b"s", 900));
1639            seen.extend(drawn(&mut d, b"s", 2));
1640        }
1641        assert_eq!(seen.len(), 1000, "some member is never drawn");
1642        assert_eq!(d.scard(b"s").expect("a set"), 1000, "and none were taken");
1643    }
1644
1645    #[test]
1646    fn a_scan_walks_a_set_of_any_size_exactly_once() {
1647        for n in [3usize, 100, 500] {
1648            let mut d = db();
1649            many(&mut d, b"s", n);
1650            let mut seen = Vec::new();
1651            let mut c = Cursor::START;
1652            let mut turns = 0;
1653            loop {
1654                c = d
1655                    .sscan(b"s", c, 10, |m| seen.push(m.to_vec()))
1656                    .expect("a set");
1657                turns += 1;
1658                assert!(turns < 200, "the scan did not finish for {n} members");
1659                if c.is_end() {
1660                    break;
1661                }
1662            }
1663            seen.sort();
1664            seen.dedup();
1665            assert_eq!(seen.len(), n, "a scan of {n} members missed one");
1666        }
1667    }
1668
1669    #[test]
1670    fn a_scan_of_a_key_that_is_not_there_is_a_finished_scan() {
1671        let mut d = db();
1672        let mut hit = 0;
1673        let c = d
1674            .sscan(b"nope", Cursor::START, 10, |_| hit += 1)
1675            .expect("ok");
1676        assert!(c.is_end());
1677        assert_eq!(hit, 0);
1678    }
1679
1680    #[test]
1681    fn a_scan_returns_everything_that_was_there_the_whole_time() {
1682        // The guarantee, tested the way it is written: members removed during
1683        // the walk may or may not come back, but the ones that never moved have
1684        // to. The table band is the only one that walks in windows, so this is
1685        // five hundred members.
1686        let mut d = db();
1687        many(&mut d, b"s", 500);
1688        let mut seen = Vec::new();
1689        let mut c = Cursor::START;
1690        let mut turns = 0;
1691        loop {
1692            c = d
1693                .sscan(b"s", c, 10, |m| seen.push(m.to_vec()))
1694                .expect("a set");
1695            // Take one out every turn, from the half of the set this test has
1696            // promised nothing about.
1697            let victim = format!("m{}", 400 + turns).into_bytes();
1698            d.srem(b"s", [victim.as_slice()].into_iter())
1699                .expect("a set");
1700            turns += 1;
1701            if c.is_end() {
1702                break;
1703            }
1704        }
1705        seen.sort();
1706        seen.dedup();
1707        for i in 0..400 {
1708            let m = format!("m{i}").into_bytes();
1709            assert!(seen.binary_search(&m).is_ok(), "m{i} was never returned");
1710        }
1711    }
1712
1713    #[test]
1714    fn moving_a_member_takes_it_off_one_set_and_puts_it_on_another() {
1715        let mut d = db();
1716        add(&mut d, b"a", &[b"x", b"y"]);
1717        add(&mut d, b"b", &[b"z"]);
1718
1719        assert!(d.smove(b"a", b"b", b"x").expect("two sets"));
1720        assert_eq!(members(&mut d, b"a"), ["y"]);
1721        assert_eq!(members(&mut d, b"b"), ["x", "z"]);
1722
1723        assert!(
1724            !d.smove(b"a", b"b", b"gone").expect("two sets"),
1725            "a member that is not in the source does not move"
1726        );
1727        assert!(
1728            d.smove(b"a", b"b", b"y").expect("two sets"),
1729            "and the last one still moves"
1730        );
1731        assert!(!d.exists(b"a"), "the source went with its last member");
1732        assert_eq!(d.sets.len(), 1, "and so did its body");
1733        assert_eq!(members(&mut d, b"b"), ["x", "y", "z"]);
1734    }
1735
1736    #[test]
1737    fn moving_onto_a_destination_that_is_not_there_makes_it() {
1738        let mut d = db();
1739        add(&mut d, b"a", &[b"x", b"y"]);
1740        assert!(d.smove(b"a", b"b", b"x").expect("a set"));
1741        assert_eq!(d.kind_of(b"b"), Some(Kind::Set));
1742        assert_eq!(members(&mut d, b"b"), ["x"]);
1743        assert_eq!(d.sets.len(), 2);
1744    }
1745
1746    #[test]
1747    fn moving_a_member_onto_its_own_set_changes_nothing() {
1748        let mut d = db();
1749        add(&mut d, b"a", &[b"x", b"y"]);
1750        assert!(d.smove(b"a", b"a", b"x").expect("a set"), "it is there");
1751        assert!(!d.smove(b"a", b"a", b"z").expect("a set"), "it is not");
1752        assert_eq!(members(&mut d, b"a"), ["x", "y"]);
1753    }
1754
1755    #[test]
1756    fn moving_checks_the_types_in_the_order_redis_checks_them() {
1757        let mut d = db();
1758        d.set_plain(b"str", b"v").expect("room");
1759        add(&mut d, b"s", &[b"x"]);
1760
1761        assert!(
1762            !d.smove(b"nope", b"str", b"x").expect("no source, no error"),
1763            "a missing source answers zero without looking at the destination"
1764        );
1765        assert_eq!(
1766            d.smove(b"str", b"s", b"x").expect_err("no").code(),
1767            Code::WrongType
1768        );
1769        assert_eq!(
1770            d.smove(b"s", b"str", b"x").expect_err("no").code(),
1771            Code::WrongType
1772        );
1773        assert_eq!(
1774            members(&mut d, b"s"),
1775            ["x"],
1776            "and the failed move left the source alone"
1777        );
1778    }
1779
1780    #[test]
1781    fn the_new_commands_answer_wrongtype_at_a_string() {
1782        let mut d = db();
1783        d.set_plain(b"k", b"v").expect("room");
1784        assert!(d.spop(b"k").is_err());
1785        assert!(d.spop_n(b"k", 2).is_err());
1786        assert!(d.srandmember(b"k", |m| m.is_some()).is_err());
1787        assert!(d.srandmember_n(b"k", 2, |_| ()).is_err());
1788        assert!(d.sscan(b"k", Cursor::START, 10, |_| ()).is_err());
1789        assert_eq!(
1790            d.get(b"k").expect("still a string").map(|v| v.to_vec()),
1791            Some(b"v".to_vec())
1792        );
1793    }
1794
1795    /// Every algebra command, collected and sorted, so a test says what came
1796    /// back rather than what order it came back in.
1797    fn algebra(d: &mut Keyspace, op: &str, keys: &[&[u8]]) -> Vec<String> {
1798        let mut got = Vec::new();
1799        let mut take = |m: &[u8]| got.push(String::from_utf8_lossy(m).into_owned());
1800        let n = match op {
1801            "inter" => d.sinter(keys.iter().copied(), 0, &mut take),
1802            "union" => d.sunion(keys.iter().copied(), 0, &mut take),
1803            "diff" => d.sdiff(keys.iter().copied(), 0, &mut take),
1804            other => unreachable!("{other}"),
1805        }
1806        .expect("sets");
1807        assert_eq!(n, got.len(), "the count and the members disagree");
1808        got.sort();
1809        got
1810    }
1811
1812    #[test]
1813    fn the_algebra_answers_what_the_sets_share_and_do_not() {
1814        let mut d = db();
1815        add(&mut d, b"a", &[b"1", b"2", b"3"]);
1816        add(&mut d, b"b", &[b"2", b"3", b"4"]);
1817        add(&mut d, b"c", &[b"3", b"4", b"5"]);
1818
1819        assert_eq!(algebra(&mut d, "inter", &[b"a", b"b", b"c"]), ["3"]);
1820        assert_eq!(
1821            algebra(&mut d, "union", &[b"a", b"b", b"c"]),
1822            ["1", "2", "3", "4", "5"]
1823        );
1824        assert_eq!(algebra(&mut d, "diff", &[b"a", b"b"]), ["1"]);
1825        assert_eq!(
1826            algebra(&mut d, "diff", &[b"a"]),
1827            ["1", "2", "3"],
1828            "one set is that set"
1829        );
1830        assert_eq!(
1831            d.sintercard([b"a".as_slice(), b"b"].into_iter(), 0)
1832                .expect("sets"),
1833            2
1834        );
1835        assert_eq!(
1836            d.sintercard([b"a".as_slice(), b"b"].into_iter(), 1)
1837                .expect("sets"),
1838            1,
1839            "and a limit stops it early"
1840        );
1841    }
1842
1843    /// A key that is not there is an empty set, and an empty set does three
1844    /// different things to the three operations.
1845    #[test]
1846    fn a_key_that_is_not_there_is_an_empty_set_everywhere() {
1847        let mut d = db();
1848        add(&mut d, b"a", &[b"1", b"2"]);
1849
1850        assert!(algebra(&mut d, "inter", &[b"a", b"nope"]).is_empty());
1851        assert!(algebra(&mut d, "inter", &[b"nope", b"a"]).is_empty());
1852        assert_eq!(algebra(&mut d, "union", &[b"a", b"nope"]), ["1", "2"]);
1853        assert_eq!(algebra(&mut d, "diff", &[b"a", b"nope"]), ["1", "2"]);
1854        assert!(
1855            algebra(&mut d, "diff", &[b"nope", b"a"]).is_empty(),
1856            "nothing minus anything is nothing"
1857        );
1858        assert!(algebra(&mut d, "union", &[b"nope"]).is_empty());
1859        assert_eq!(d.len(), 1, "and none of that made a key");
1860    }
1861
1862    #[test]
1863    fn a_store_form_writes_the_answer_and_says_how_big_it_is() {
1864        let mut d = db();
1865        add(&mut d, b"a", &[b"1", b"2", b"3"]);
1866        add(&mut d, b"b", &[b"2", b"3", b"4"]);
1867
1868        assert_eq!(
1869            d.sinterstore(b"d", [b"a".as_slice(), b"b"].into_iter())
1870                .expect("sets"),
1871            2
1872        );
1873        assert_eq!(members(&mut d, b"d"), ["2", "3"]);
1874        assert_eq!(
1875            d.sunionstore(b"d", [b"a".as_slice(), b"b"].into_iter())
1876                .expect("sets"),
1877            4
1878        );
1879        assert_eq!(members(&mut d, b"d"), ["1", "2", "3", "4"]);
1880        assert_eq!(
1881            d.sdiffstore(b"d", [b"a".as_slice(), b"b"].into_iter())
1882                .expect("sets"),
1883            1
1884        );
1885        assert_eq!(members(&mut d, b"d"), ["1"]);
1886        // An all integer answer stores as an intset, because the destination
1887        // picks its representation from what actually went into it.
1888        assert_eq!(d.encoding_name(b"d"), Some(Encoding::Intset.name()));
1889    }
1890
1891    /// The rule that makes an empty answer different from an empty set: the
1892    /// destination is deleted rather than left holding nothing.
1893    #[test]
1894    fn a_store_form_of_nothing_deletes_the_destination() {
1895        let mut d = db();
1896        add(&mut d, b"a", &[b"1"]);
1897        add(&mut d, b"b", &[b"2"]);
1898        add(&mut d, b"d", &[b"old"]);
1899
1900        assert_eq!(
1901            d.sinterstore(b"d", [b"a".as_slice(), b"b"].into_iter())
1902                .expect("sets"),
1903            0
1904        );
1905        assert_eq!(d.kind_of(b"d"), None, "the destination went, not emptied");
1906        assert!(!d.exists(b"d"));
1907
1908        // And the same for a difference that takes everything away, and for a
1909        // source that is not there at all.
1910        add(&mut d, b"d", &[b"old"]);
1911        assert_eq!(
1912            d.sdiffstore(b"d", [b"a".as_slice(), b"a"].into_iter())
1913                .expect("sets"),
1914            0
1915        );
1916        assert!(!d.exists(b"d"));
1917        add(&mut d, b"d", &[b"old"]);
1918        assert_eq!(
1919            d.sunionstore(b"d", [b"nope".as_slice()].into_iter())
1920                .expect("sets"),
1921            0
1922        );
1923        assert!(!d.exists(b"d"));
1924    }
1925
1926    /// The destination is allowed to be one of the sources, which only works
1927    /// because the answer is built whole before anything is written.
1928    #[test]
1929    fn a_store_form_can_write_over_one_of_its_own_sources() {
1930        let mut d = db();
1931        add(&mut d, b"a", &[b"1", b"2", b"3"]);
1932        add(&mut d, b"b", &[b"2", b"3", b"4"]);
1933
1934        assert_eq!(
1935            d.sinterstore(b"a", [b"a".as_slice(), b"b"].into_iter())
1936                .expect("sets"),
1937            2
1938        );
1939        assert_eq!(members(&mut d, b"a"), ["2", "3"]);
1940
1941        // The same key named twice is not a special case either.
1942        assert_eq!(
1943            d.sunionstore(b"a", [b"a".as_slice(), b"a"].into_iter())
1944                .expect("sets"),
1945            2
1946        );
1947        assert_eq!(members(&mut d, b"a"), ["2", "3"]);
1948    }
1949
1950    /// A destination that held something else is overwritten rather than
1951    /// refused, which is what Redis does and is the same rule `SET` follows.
1952    #[test]
1953    fn a_store_form_overwrites_whatever_the_destination_held() {
1954        let mut d = db();
1955        add(&mut d, b"a", &[b"1", b"2"]);
1956        d.set_plain(b"d", b"a string").expect("room");
1957        assert!(d.set_expiry(b"d", Some(9_999_999)));
1958
1959        assert_eq!(
1960            d.sunionstore(b"d", [b"a".as_slice()].into_iter())
1961                .expect("sets"),
1962            2
1963        );
1964        assert_eq!(d.kind_of(b"d"), Some(Kind::Set));
1965        assert_eq!(members(&mut d, b"d"), ["1", "2"]);
1966        assert_eq!(d.expire_at(b"d"), None, "and the deadline went with it");
1967    }
1968
1969    /// A bad key anywhere in the list fails the whole command, and it fails
1970    /// before the destination is touched rather than after.
1971    #[test]
1972    fn the_algebra_answers_wrongtype_before_it_writes_anything() {
1973        let mut d = db();
1974        add(&mut d, b"a", &[b"1"]);
1975        d.set_plain(b"str", b"v").expect("room");
1976        add(&mut d, b"d", &[b"old"]);
1977
1978        assert!(
1979            d.sinter([b"a".as_slice(), b"str"].into_iter(), 0, |_| ())
1980                .is_err()
1981        );
1982        assert!(
1983            d.sunion([b"str".as_slice()].into_iter(), 0, |_| ())
1984                .is_err()
1985        );
1986        assert!(
1987            d.sdiff([b"a".as_slice(), b"str"].into_iter(), 0, |_| ())
1988                .is_err()
1989        );
1990        assert!(
1991            d.sinterstore(b"d", [b"a".as_slice(), b"str"].into_iter())
1992                .is_err()
1993        );
1994        assert_eq!(members(&mut d, b"d"), ["old"], "and left it alone");
1995    }
1996
1997    /// Sets across all three representations, since the algebra is the only
1998    /// place where members have to cross from one to another.
1999    #[test]
2000    fn the_algebra_works_across_the_representations() {
2001        let mut d = db();
2002        let big: Vec<Vec<u8>> = (0..600).map(|i| i.to_string().into_bytes()).collect();
2003        let refs: Vec<&[u8]> = big.iter().map(Vec::as_slice).collect();
2004        d.sadd(b"table", refs.iter().copied()).expect("a set");
2005        add(&mut d, b"ints", &[b"1", b"2", b"999"]);
2006        add(&mut d, b"packed", &[b"2", b"3", b"x"]);
2007        assert_eq!(d.encoding_name(b"table"), Some(Encoding::Hashtable.name()));
2008        assert_eq!(d.encoding_name(b"ints"), Some(Encoding::Intset.name()));
2009        assert_eq!(d.encoding_name(b"packed"), Some(Encoding::Listpack.name()));
2010
2011        // A member of the intset is a number that has no digits anywhere and
2012        // the table holds that same member as its digits, so this only finds
2013        // anything if the two agree about what a member is.
2014        assert_eq!(algebra(&mut d, "inter", &[b"ints", b"table"]), ["1", "2"]);
2015        assert_eq!(algebra(&mut d, "inter", &[b"packed", b"table"]), ["2", "3"]);
2016        assert_eq!(algebra(&mut d, "inter", &[b"ints", b"packed"]), ["2"]);
2017        assert_eq!(algebra(&mut d, "diff", &[b"ints", b"table"]), ["999"]);
2018        assert_eq!(
2019            algebra(&mut d, "union", &[b"ints", b"packed"]),
2020            ["1", "2", "3", "999", "x"]
2021        );
2022    }
2023
2024    #[test]
2025    fn a_set_is_counted_in_what_the_database_is_holding() {
2026        let mut d = db();
2027        let before = d.memory_bytes();
2028        let owned: Vec<Vec<u8>> = (0..500).map(|i| i.to_string().into_bytes()).collect();
2029        let refs: Vec<&[u8]> = owned.iter().map(Vec::as_slice).collect();
2030        d.sadd(b"s", refs.iter().copied()).expect("a set");
2031
2032        let after = d.memory_bytes();
2033        assert!(
2034            after > before + 500,
2035            "five hundred members have to show up somewhere: {before} then {after}"
2036        );
2037        d.del(b"s");
2038        assert!(d.memory_bytes() < after, "and go away again");
2039    }
2040
2041    /// The sharp version of the memo hazard. `a` is resolved and remembered, so
2042    /// something is holding a slab slot number for it. Deleting `a` frees that
2043    /// slot and the next set created takes it, so a memo that survived the
2044    /// delete would answer questions about `a` with `b`'s members. It is not a
2045    /// stale count, it is another key's data under the name of a key that is
2046    /// gone.
2047    #[test]
2048    fn a_deleted_key_does_not_answer_with_whatever_took_its_slot() {
2049        let mut d = db();
2050        add(&mut d, b"a", &[b"x", b"y", b"z"]);
2051        assert_eq!(d.scard(b"a").expect("a set"), 3);
2052
2053        d.del(b"a");
2054        add(&mut d, b"b", &[b"one"]);
2055
2056        assert_eq!(d.scard(b"a").expect("gone"), 0);
2057        assert!(!d.sismember(b"a", b"x").expect("gone"));
2058        assert_eq!(d.scard(b"b").expect("a set"), 1);
2059    }
2060
2061    /// Same shape, one step further: the name comes back holding another type.
2062    /// A memo that answered from what it remembered would say the set is still
2063    /// there and hand back a slot that now belongs to a hash.
2064    #[test]
2065    fn a_key_that_comes_back_as_another_type_is_wrongtype() {
2066        let mut d = db();
2067        add(&mut d, b"k", &[b"x"]);
2068        assert_eq!(d.scard(b"k").expect("a set"), 1);
2069
2070        d.del(b"k");
2071        d.hset(b"k", [(&b"f"[..], &b"v"[..])].into_iter())
2072            .expect("a hash");
2073
2074        let err = d.scard(b"k").expect_err("a hash is not a set");
2075        assert_eq!(err.code(), Code::WrongType);
2076    }
2077
2078    /// A deadline passes without anyone writing to the map, so it is the one
2079    /// thing a write counter cannot see. The answer is that a dated key is
2080    /// never remembered in the first place, and this is what says so.
2081    #[test]
2082    fn a_key_with_a_deadline_still_expires_after_it_has_been_read() {
2083        let mut d = db();
2084        add(&mut d, b"k", &[b"x", b"y"]);
2085        assert_eq!(d.scard(b"k").expect("a set"), 2);
2086
2087        assert!(d.set_expiry(b"k", Some(1_500)));
2088        assert_eq!(d.scard(b"k").expect("still alive"), 2);
2089
2090        d.clock().advance(600);
2091        assert_eq!(d.scard(b"k").expect("past its deadline"), 0);
2092        assert!(!d.sismember(b"k", b"x").expect("past its deadline"));
2093    }
2094
2095    /// Two keys alternating, which is what a pipeline that is not on one key
2096    /// looks like. Each one has to answer for itself, so the comparison is the
2097    /// key bytes and not the hash.
2098    #[test]
2099    fn two_keys_in_a_row_do_not_answer_for_each_other() {
2100        let mut d = db();
2101        add(&mut d, b"a", &[b"1"]);
2102        add(&mut d, b"b", &[b"1", b"2", b"3"]);
2103        for _ in 0..8 {
2104            assert_eq!(d.scard(b"a").expect("a set"), 1);
2105            assert_eq!(d.scard(b"b").expect("a set"), 3);
2106        }
2107    }
2108
2109    /// `FLUSHDB` throws the map away and builds a fresh one, and a fresh one
2110    /// starts its write counter over. Nothing may survive that.
2111    #[test]
2112    fn a_flush_does_not_leave_the_last_key_behind() {
2113        let mut d = db();
2114        add(&mut d, b"k", &[b"x"]);
2115        assert_eq!(d.scard(b"k").expect("a set"), 1);
2116
2117        d.clear();
2118        assert_eq!(d.scard(b"k").expect("flushed"), 0);
2119    }
2120
2121    /// A key too long to remember is a key that is looked up every time, which
2122    /// is the old behaviour and has to keep working rather than fall through a
2123    /// branch that assumes something was written down.
2124    #[test]
2125    fn a_key_longer_than_the_memo_still_works() {
2126        let mut d = db();
2127        let long = vec![b'k'; 200];
2128        add(&mut d, &long, &[b"x", b"y"]);
2129        for _ in 0..4 {
2130            assert_eq!(d.scard(&long).expect("a set"), 2);
2131        }
2132        d.del(&long);
2133        assert_eq!(d.scard(&long).expect("gone"), 0);
2134    }
2135}