Skip to main content

yo/
sets.rs

1//! Sets, from the embedded side.
2//!
3//! The same store `SADD` off a socket reaches (Y23), through two doors. [`Sets`]
4//! is the keyspace shape, one method per Redis command with the key as the first
5//! argument, which is what a program porting off a Redis client wants. [`Set`] is
6//! one key with a handle around it, which is what a program that was never going
7//! to use Redis wants: a set is a set, and the name of it gets spelled once
8//! rather than at every call site.
9//!
10//! A [`Set`] holds the [`Sets`] it goes through rather than building one per
11//! call, so reaching a set by its handle costs the key it already had and
12//! nothing else. There is no door here that is the slow one.
13//!
14//! # Owned or borrowed, per call
15//!
16//! Every read that hands back members comes in two forms. [`Set::members`]
17//! allocates a `Vec` per member, which is what most code wants and what every
18//! other embedded database gives you. [`Set::for_each`] hands each member over
19//! where it lies and allocates nothing, which is Y29's rule that zero copy is
20//! available and never mandatory.
21//!
22//! The difference is not decoration. A set stored as integers holds them as
23//! integers, so walking a million member set with `members` formats a million
24//! numbers into a million `Vec`s, and walking it with `for_each` formats none of
25//! them unless the closure asks. That is why the borrowed form hands over a
26//! [`Member`] and not a `&[u8]`: the choice of whether to spend the digits is
27//! the caller's.
28
29use yo_common::{Code, Error, Result};
30use yo_kv::Member;
31
32use crate::db::Handle;
33
34/// Every Redis set command, with the key as the first argument.
35///
36/// Keys and members are byte strings the way Redis's are, so anything that is
37/// bytes will do.
38///
39/// ```
40/// let db = yo::open(yo::MEMORY)?;
41/// let sets = db.sets();
42///
43/// sets.add_many("online", &["alice", "bob"])?;
44/// assert!(sets.contains("online", "alice")?);
45/// assert_eq!(sets.len_of("online")?, 2);
46/// # Ok::<(), yo::Error>(())
47/// ```
48#[derive(Clone)]
49pub struct Sets {
50    pub(crate) db: Handle,
51}
52
53impl core::fmt::Debug for Sets {
54    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
55        f.debug_struct("Sets").finish_non_exhaustive()
56    }
57}
58
59impl Sets {
60    /// Add one member, and say whether it was new. `SADD`.
61    ///
62    /// The key is created by the first member that goes into it, so there is no
63    /// step before this one.
64    ///
65    /// # Errors
66    ///
67    /// [`Code::WrongType`] when the key holds something that is not a set,
68    /// [`Code::Full`] for a member past the size limit, and [`Code::Invalid`] if
69    /// called from inside a callback that is already holding this database.
70    pub fn add(&self, key: impl AsRef<[u8]>, member: impl AsRef<[u8]>) -> Result<bool> {
71        self.add_many(key, &[member]).map(|n| n == 1)
72    }
73
74    /// Add several members, and say how many were new. `SADD` with a list.
75    ///
76    /// One key lookup for the whole call rather than one per member, which is
77    /// the only reason to prefer it over calling [`Sets::add`] in a loop.
78    ///
79    /// # Errors
80    ///
81    /// As [`Sets::add`]. Nothing is added if any member is too long, because the
82    /// lengths are all checked before the first one goes in.
83    pub fn add_many<M: AsRef<[u8]>>(&self, key: impl AsRef<[u8]>, members: &[M]) -> Result<usize> {
84        self.db.run(|inner| {
85            inner
86                .strings
87                .sadd(key.as_ref(), members.iter().map(AsRef::as_ref))
88        })
89    }
90
91    /// Remove one member, and say whether it was there. `SREM`.
92    ///
93    /// A set that loses its last member loses its key too, which is Redis's rule
94    /// and is why there is no such thing as an empty set in the keyspace.
95    ///
96    /// # Errors
97    ///
98    /// As [`Sets::add`].
99    pub fn remove(&self, key: impl AsRef<[u8]>, member: impl AsRef<[u8]>) -> Result<bool> {
100        self.remove_many(key, &[member]).map(|n| n == 1)
101    }
102
103    /// Remove several members, and say how many were there. `SREM` with a list.
104    ///
105    /// # Errors
106    ///
107    /// As [`Sets::add`].
108    pub fn remove_many<M: AsRef<[u8]>>(
109        &self,
110        key: impl AsRef<[u8]>,
111        members: &[M],
112    ) -> Result<usize> {
113        self.db.run(|inner| {
114            inner
115                .strings
116                .srem(key.as_ref(), members.iter().map(AsRef::as_ref))
117        })
118    }
119
120    /// Whether a member is in the set. `SISMEMBER`.
121    ///
122    /// False for a key that is not there, which is the same answer as an empty
123    /// set and is deliberate: a set nobody has added to and a set somebody
124    /// emptied are the same set.
125    ///
126    /// # Errors
127    ///
128    /// As [`Sets::add`].
129    pub fn contains(&self, key: impl AsRef<[u8]>, member: impl AsRef<[u8]>) -> Result<bool> {
130        self.db
131            .run(|inner| inner.strings.sismember(key.as_ref(), member.as_ref()))
132    }
133
134    /// Whether each of several members is in the set, in the order asked.
135    /// `SMISMEMBER`.
136    ///
137    /// # Errors
138    ///
139    /// As [`Sets::add`].
140    pub fn contains_many<M: AsRef<[u8]>>(
141        &self,
142        key: impl AsRef<[u8]>,
143        members: &[M],
144    ) -> Result<Vec<bool>> {
145        self.db.run(|inner| {
146            inner
147                .strings
148                .smismember(key.as_ref(), members.iter().map(AsRef::as_ref))
149        })
150    }
151
152    /// How many members the set holds, which is zero for a key that is not
153    /// there. `SCARD`.
154    ///
155    /// # Errors
156    ///
157    /// As [`Sets::add`].
158    pub fn len_of(&self, key: impl AsRef<[u8]>) -> Result<usize> {
159        self.db.run(|inner| inner.strings.scard(key.as_ref()))
160    }
161
162    /// Every member, owned. `SMEMBERS`.
163    ///
164    /// `None` for a key that is not there, which a caller who wants to tell that
165    /// apart from an empty answer can use. [`Sets::for_each`] is the same walk
166    /// without the allocations.
167    ///
168    /// # Errors
169    ///
170    /// As [`Sets::add`].
171    pub fn members(&self, key: impl AsRef<[u8]>) -> Result<Option<Vec<Vec<u8>>>> {
172        self.db.run(|inner| {
173            Ok(inner
174                .strings
175                .smembers(key.as_ref())?
176                .map(|it| it.map(|m| m.to_vec()).collect()))
177        })
178    }
179
180    /// Hand every member to `f` where it lies, and say whether the key was
181    /// there.
182    ///
183    /// Nothing is allocated and nothing is formatted. A set stored as integers
184    /// hands over [`Member::Int`] and the digits are only written if the closure
185    /// writes them.
186    ///
187    /// ```
188    /// let db = yo::open(yo::MEMORY)?;
189    /// let sets = db.sets();
190    /// sets.add_many("ids", &["1", "2", "3"])?;
191    ///
192    /// let mut total = 0i64;
193    /// sets.for_each("ids", |m| {
194    ///     if let yo::Member::Int(n) = m {
195    ///         total += n;
196    ///     }
197    /// })?;
198    /// assert_eq!(total, 6);
199    /// # Ok::<(), yo::Error>(())
200    /// ```
201    ///
202    /// # Errors
203    ///
204    /// As [`Sets::add`].
205    pub fn for_each(&self, key: impl AsRef<[u8]>, mut f: impl FnMut(Member<'_>)) -> Result<bool> {
206        self.db.run(|inner| {
207            inner.strings.with_set(key.as_ref(), |set| match set {
208                Some(set) => {
209                    for m in set.iter() {
210                        f(m);
211                    }
212                    true
213                }
214                None => false,
215            })
216        })
217    }
218
219    /// Take one member out at random and hand it back. `SPOP`.
220    ///
221    /// `None` for a key that is not there. The key goes when the last member
222    /// does.
223    ///
224    /// # Errors
225    ///
226    /// As [`Sets::add`].
227    pub fn pop(&self, key: impl AsRef<[u8]>) -> Result<Option<Vec<u8>>> {
228        self.db.run(|inner| inner.strings.spop(key.as_ref()))
229    }
230
231    /// Take up to `count` members out at random. `SPOP key count`.
232    ///
233    /// The members are distinct, and fewer than `count` come back when the set
234    /// holds fewer than that.
235    ///
236    /// # Errors
237    ///
238    /// As [`Sets::add`].
239    pub fn pop_n(&self, key: impl AsRef<[u8]>, count: usize) -> Result<Vec<Vec<u8>>> {
240        self.db
241            .run(|inner| inner.strings.spop_n(key.as_ref(), count))
242    }
243
244    /// Draw one member at random and leave it in the set. `SRANDMEMBER`.
245    ///
246    /// # Errors
247    ///
248    /// As [`Sets::add`].
249    pub fn pick(&self, key: impl AsRef<[u8]>) -> Result<Option<Vec<u8>>> {
250        self.db.run(|inner| {
251            inner
252                .strings
253                .srandmember(key.as_ref(), |m| m.map(|m| m.to_vec()))
254        })
255    }
256
257    /// Draw `count` members and leave them in the set. `SRANDMEMBER key count`.
258    ///
259    /// A positive `count` is distinct members, at most as many as the set holds.
260    /// A negative one is the with repeats form, which answers exactly that many
261    /// and can answer more members than the set has. That is one command with
262    /// two meanings in Redis and it stays one method here, because splitting it
263    /// would mean a caller holding a count from somewhere else has to branch on
264    /// its sign before choosing which method to call.
265    ///
266    /// # Errors
267    ///
268    /// As [`Sets::add`].
269    pub fn pick_n(&self, key: impl AsRef<[u8]>, count: i64) -> Result<Vec<Vec<u8>>> {
270        self.db.run(|inner| {
271            let mut out = Vec::new();
272            inner
273                .strings
274                .srandmember_n(key.as_ref(), count, |m| out.push(m.to_vec()))?;
275            Ok(out)
276        })
277    }
278
279    /// Move one member from one set to another, and say whether it moved.
280    /// `SMOVE`.
281    ///
282    /// False when the member was not in `from`, in which case `to` is untouched.
283    ///
284    /// # Errors
285    ///
286    /// As [`Sets::add`], for either key.
287    pub fn move_member(
288        &self,
289        from: impl AsRef<[u8]>,
290        to: impl AsRef<[u8]>,
291        member: impl AsRef<[u8]>,
292    ) -> Result<bool> {
293        self.db.run(|inner| {
294            inner
295                .strings
296                .smove(from.as_ref(), to.as_ref(), member.as_ref())
297        })
298    }
299
300    /// Everything in all of the sets. `SINTER`.
301    ///
302    /// A key that is not there is an empty set, and an empty set anywhere empties
303    /// the intersection.
304    ///
305    /// # Errors
306    ///
307    /// As [`Sets::add`], for any of the keys.
308    pub fn intersect<K: AsRef<[u8]>>(&self, keys: &[K]) -> Result<Vec<Vec<u8>>> {
309        self.collect(keys, Op::Intersect)
310    }
311
312    /// How big the intersection is, without building it. `SINTERCARD`.
313    ///
314    /// A `limit` of zero means no limit. Any other limit stops the walk once it
315    /// has counted that many, which is what makes "do these two sets share at
316    /// least one member" cost one member and not the whole intersection.
317    ///
318    /// # Errors
319    ///
320    /// As [`Sets::add`], for any of the keys.
321    pub fn intersect_len<K: AsRef<[u8]>>(&self, keys: &[K], limit: usize) -> Result<usize> {
322        self.db.run(|inner| {
323            inner
324                .strings
325                .sintercard(keys.iter().map(AsRef::as_ref), limit)
326        })
327    }
328
329    /// Everything in any of the sets. `SUNION`.
330    ///
331    /// A key that is not there contributes nothing and is dropped, which is the
332    /// opposite of what it does to an intersection and is right for the same
333    /// reason: an empty set adds no members and removes none.
334    ///
335    /// # Errors
336    ///
337    /// As [`Sets::add`], for any of the keys.
338    pub fn union<K: AsRef<[u8]>>(&self, keys: &[K]) -> Result<Vec<Vec<u8>>> {
339        self.collect(keys, Op::Union)
340    }
341
342    /// How big the union is, without building it. `SUNIONCARD`.
343    ///
344    /// A `limit` of zero means no limit, and is [`Sets::intersect_len`]'s in
345    /// every respect.
346    ///
347    /// # Errors
348    ///
349    /// As [`Sets::add`], for any of the keys.
350    pub fn union_len<K: AsRef<[u8]>>(&self, keys: &[K], limit: usize) -> Result<usize> {
351        self.db.run(|inner| {
352            inner
353                .strings
354                .sunioncard(keys.iter().map(AsRef::as_ref), limit)
355        })
356    }
357
358    /// Everything in the first set and in none of the others. `SDIFF`.
359    ///
360    /// # Errors
361    ///
362    /// As [`Sets::add`], for any of the keys.
363    pub fn difference<K: AsRef<[u8]>>(&self, keys: &[K]) -> Result<Vec<Vec<u8>>> {
364        self.collect(keys, Op::Difference)
365    }
366
367    /// How big the difference is, without building it. `SDIFFCARD`.
368    ///
369    /// A `limit` of zero means no limit, and is [`Sets::intersect_len`]'s in
370    /// every respect.
371    ///
372    /// # Errors
373    ///
374    /// As [`Sets::add`], for any of the keys.
375    pub fn difference_len<K: AsRef<[u8]>>(&self, keys: &[K], limit: usize) -> Result<usize> {
376        self.db.run(|inner| {
377            inner
378                .strings
379                .sdiffcard(keys.iter().map(AsRef::as_ref), limit)
380        })
381    }
382
383    /// Store the intersection under `destination` and say how big it is.
384    /// `SINTERSTORE`.
385    ///
386    /// An empty result removes `destination` rather than leaving an empty set
387    /// there, because there is no such thing as an empty set in the keyspace.
388    ///
389    /// # Errors
390    ///
391    /// As [`Sets::add`], for any of the keys.
392    pub fn intersect_into<K: AsRef<[u8]>>(
393        &self,
394        destination: impl AsRef<[u8]>,
395        keys: &[K],
396    ) -> Result<usize> {
397        self.db.run(|inner| {
398            inner
399                .strings
400                .sinterstore(destination.as_ref(), keys.iter().map(AsRef::as_ref))
401        })
402    }
403
404    /// Store the union under `destination` and say how big it is. `SUNIONSTORE`.
405    ///
406    /// # Errors
407    ///
408    /// As [`Sets::intersect_into`].
409    pub fn union_into<K: AsRef<[u8]>>(
410        &self,
411        destination: impl AsRef<[u8]>,
412        keys: &[K],
413    ) -> Result<usize> {
414        self.db.run(|inner| {
415            inner
416                .strings
417                .sunionstore(destination.as_ref(), keys.iter().map(AsRef::as_ref))
418        })
419    }
420
421    /// Store the difference under `destination` and say how big it is.
422    /// `SDIFFSTORE`.
423    ///
424    /// # Errors
425    ///
426    /// As [`Sets::intersect_into`].
427    pub fn difference_into<K: AsRef<[u8]>>(
428        &self,
429        destination: impl AsRef<[u8]>,
430        keys: &[K],
431    ) -> Result<usize> {
432        self.db.run(|inner| {
433            inner
434                .strings
435                .sdiffstore(destination.as_ref(), keys.iter().map(AsRef::as_ref))
436        })
437    }
438
439    /// The three algebra reads, which differ only in which one they call.
440    ///
441    /// They hand back owned members rather than borrowed ones, and that is not a
442    /// choice made here. An intersection has to compare members that are stored
443    /// three different ways, so by the time one is known to be in the answer it
444    /// has already been written out somewhere. There is nothing left to borrow.
445    fn collect<K: AsRef<[u8]>>(&self, keys: &[K], op: Op) -> Result<Vec<Vec<u8>>> {
446        self.db.run(|inner| {
447            let mut out = Vec::new();
448            let push = |m: &[u8]| out.push(m.to_vec());
449            let keys = keys.iter().map(AsRef::as_ref);
450            match op {
451                Op::Intersect => inner.strings.sinter(keys, 0, push)?,
452                Op::Union => inner.strings.sunion(keys, 0, push)?,
453                Op::Difference => inner.strings.sdiff(keys, 0, push)?,
454            };
455            Ok(out)
456        })
457    }
458}
459
460/// Which of the three set algebra reads [`Sets::collect`] is doing.
461#[derive(Clone, Copy)]
462enum Op {
463    Intersect,
464    Union,
465    Difference,
466}
467
468/// One set, with its key held for you.
469///
470/// This is `15` section 2's shape: the name is spelled where the handle is made
471/// and nowhere else, so a typo is one compile error at one line instead of a
472/// lookup that quietly misses at three call sites.
473///
474/// ```
475/// let db = yo::open(yo::MEMORY)?;
476/// let online = db.set("online");
477///
478/// online.add("alice")?;
479/// online.add("bob")?;
480/// assert!(online.contains("alice")?);
481/// assert_eq!(online.len()?, 2);
482///
483/// online.remove("alice")?;
484/// assert!(!online.contains("alice")?);
485/// # Ok::<(), yo::Error>(())
486/// ```
487#[derive(Clone)]
488pub struct Set {
489    pub(crate) sets: Sets,
490    pub(crate) key: Vec<u8>,
491}
492
493impl core::fmt::Debug for Set {
494    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
495        f.debug_struct("Set")
496            .field("key", &String::from_utf8_lossy(&self.key))
497            .field("len", &self.len().ok())
498            .finish()
499    }
500}
501
502impl Set {
503    /// The key this handle holds.
504    #[must_use]
505    pub fn key(&self) -> &[u8] {
506        &self.key
507    }
508
509    /// Add one member, and say whether it was new. `SADD`.
510    ///
511    /// # Errors
512    ///
513    /// As [`Sets::add`].
514    pub fn add(&self, member: impl AsRef<[u8]>) -> Result<bool> {
515        self.sets.add(&self.key, member)
516    }
517
518    /// Add several members, and say how many were new.
519    ///
520    /// # Errors
521    ///
522    /// As [`Sets::add`].
523    pub fn add_many<M: AsRef<[u8]>>(&self, members: &[M]) -> Result<usize> {
524        self.sets.add_many(&self.key, members)
525    }
526
527    /// Remove one member, and say whether it was there. `SREM`.
528    ///
529    /// # Errors
530    ///
531    /// As [`Sets::add`].
532    pub fn remove(&self, member: impl AsRef<[u8]>) -> Result<bool> {
533        self.sets.remove(&self.key, member)
534    }
535
536    /// Remove several members, and say how many were there.
537    ///
538    /// # Errors
539    ///
540    /// As [`Sets::add`].
541    pub fn remove_many<M: AsRef<[u8]>>(&self, members: &[M]) -> Result<usize> {
542        self.sets.remove_many(&self.key, members)
543    }
544
545    /// Whether a member is in the set. `SISMEMBER`.
546    ///
547    /// # Errors
548    ///
549    /// As [`Sets::add`].
550    pub fn contains(&self, member: impl AsRef<[u8]>) -> Result<bool> {
551        self.sets.contains(&self.key, member)
552    }
553
554    /// Whether each of several members is in the set, in the order asked.
555    /// `SMISMEMBER`.
556    ///
557    /// # Errors
558    ///
559    /// As [`Sets::add`].
560    pub fn contains_many<M: AsRef<[u8]>>(&self, members: &[M]) -> Result<Vec<bool>> {
561        self.sets.contains_many(&self.key, members)
562    }
563
564    /// How many members it holds. `SCARD`.
565    ///
566    /// # Errors
567    ///
568    /// As [`Sets::add`].
569    pub fn len(&self) -> Result<usize> {
570        self.sets.len_of(&self.key)
571    }
572
573    /// Whether it holds nothing, which is also true of a key that is not there.
574    ///
575    /// # Errors
576    ///
577    /// As [`Sets::add`].
578    pub fn is_empty(&self) -> Result<bool> {
579        self.len().map(|n| n == 0)
580    }
581
582    /// Every member, owned. `SMEMBERS`.
583    ///
584    /// An empty `Vec` for a key that is not there. [`Sets::members`] is the
585    /// version that tells the two apart, and this one does not because a handle
586    /// on a key that was never written to is the ordinary way to start.
587    ///
588    /// # Errors
589    ///
590    /// As [`Sets::add`].
591    pub fn members(&self) -> Result<Vec<Vec<u8>>> {
592        Ok(self.sets.members(&self.key)?.unwrap_or_default())
593    }
594
595    /// Hand every member to `f` where it lies, allocating nothing.
596    ///
597    /// # Errors
598    ///
599    /// As [`Sets::add`].
600    pub fn for_each(&self, f: impl FnMut(Member<'_>)) -> Result<()> {
601        self.sets.for_each(&self.key, f).map(|_| ())
602    }
603
604    /// Take one member out at random. `SPOP`.
605    ///
606    /// # Errors
607    ///
608    /// As [`Sets::add`].
609    pub fn pop(&self) -> Result<Option<Vec<u8>>> {
610        self.sets.pop(&self.key)
611    }
612
613    /// Take up to `count` distinct members out at random. `SPOP key count`.
614    ///
615    /// # Errors
616    ///
617    /// As [`Sets::add`].
618    pub fn pop_n(&self, count: usize) -> Result<Vec<Vec<u8>>> {
619        self.sets.pop_n(&self.key, count)
620    }
621
622    /// Draw one member and leave it in the set. `SRANDMEMBER`.
623    ///
624    /// # Errors
625    ///
626    /// As [`Sets::add`].
627    pub fn pick(&self) -> Result<Option<Vec<u8>>> {
628        self.sets.pick(&self.key)
629    }
630
631    /// Draw `count` members and leave them in the set. `SRANDMEMBER key count`.
632    ///
633    /// # Errors
634    ///
635    /// As [`Sets::add`].
636    pub fn pick_n(&self, count: i64) -> Result<Vec<Vec<u8>>> {
637        self.sets.pick_n(&self.key, count)
638    }
639
640    /// Move one member into another set, and say whether it moved. `SMOVE`.
641    ///
642    /// # Errors
643    ///
644    /// As [`Sets::add`], and [`Code::Invalid`] when `to` belongs to a different
645    /// database.
646    pub fn move_to(&self, to: &Set, member: impl AsRef<[u8]>) -> Result<bool> {
647        self.same_db(to)?;
648        self.sets.move_member(&self.key, &to.key, member)
649    }
650
651    /// Everything in this set and in all of `others`. `SINTER`.
652    ///
653    /// ```
654    /// let db = yo::open(yo::MEMORY)?;
655    /// let a = db.set("a");
656    /// let b = db.set("b");
657    /// a.add_many(&["x", "y"])?;
658    /// b.add_many(&["y", "z"])?;
659    ///
660    /// assert_eq!(a.intersect(&[&b])?, vec![b"y".to_vec()]);
661    /// # Ok::<(), yo::Error>(())
662    /// ```
663    ///
664    /// # Errors
665    ///
666    /// As [`Set::move_to`].
667    pub fn intersect(&self, others: &[&Set]) -> Result<Vec<Vec<u8>>> {
668        self.sets.intersect(&self.keys_with(others)?)
669    }
670
671    /// How many members this set shares with all of `others`. `SINTERCARD`.
672    ///
673    /// A `limit` of zero means no limit.
674    ///
675    /// # Errors
676    ///
677    /// As [`Set::move_to`].
678    pub fn intersect_len(&self, others: &[&Set], limit: usize) -> Result<usize> {
679        self.sets.intersect_len(&self.keys_with(others)?, limit)
680    }
681
682    /// Everything in this set or in any of `others`. `SUNION`.
683    ///
684    /// # Errors
685    ///
686    /// As [`Set::move_to`].
687    pub fn union(&self, others: &[&Set]) -> Result<Vec<Vec<u8>>> {
688        self.sets.union(&self.keys_with(others)?)
689    }
690
691    /// How many members this set and `others` have between them. `SUNIONCARD`.
692    ///
693    /// A `limit` of zero means no limit.
694    ///
695    /// # Errors
696    ///
697    /// As [`Set::move_to`].
698    pub fn union_len(&self, others: &[&Set], limit: usize) -> Result<usize> {
699        self.sets.union_len(&self.keys_with(others)?, limit)
700    }
701
702    /// Everything in this set and in none of `others`. `SDIFF`.
703    ///
704    /// # Errors
705    ///
706    /// As [`Set::move_to`].
707    pub fn difference(&self, others: &[&Set]) -> Result<Vec<Vec<u8>>> {
708        self.sets.difference(&self.keys_with(others)?)
709    }
710
711    /// How many members this set has that no set in `others` has. `SDIFFCARD`.
712    ///
713    /// A `limit` of zero means no limit.
714    ///
715    /// # Errors
716    ///
717    /// As [`Set::move_to`].
718    pub fn difference_len(&self, others: &[&Set], limit: usize) -> Result<usize> {
719        self.sets.difference_len(&self.keys_with(others)?, limit)
720    }
721
722    /// Store the intersection in `destination` and say how big it is.
723    /// `SINTERSTORE`.
724    ///
725    /// # Errors
726    ///
727    /// As [`Set::move_to`].
728    pub fn intersect_into(&self, destination: &Set, others: &[&Set]) -> Result<usize> {
729        self.same_db(destination)?;
730        self.sets
731            .intersect_into(&destination.key, &self.keys_with(others)?)
732    }
733
734    /// Store the union in `destination` and say how big it is. `SUNIONSTORE`.
735    ///
736    /// # Errors
737    ///
738    /// As [`Set::move_to`].
739    pub fn union_into(&self, destination: &Set, others: &[&Set]) -> Result<usize> {
740        self.same_db(destination)?;
741        self.sets
742            .union_into(&destination.key, &self.keys_with(others)?)
743    }
744
745    /// Store the difference in `destination` and say how big it is.
746    /// `SDIFFSTORE`.
747    ///
748    /// # Errors
749    ///
750    /// As [`Set::move_to`].
751    pub fn difference_into(&self, destination: &Set, others: &[&Set]) -> Result<usize> {
752        self.same_db(destination)?;
753        self.sets
754            .difference_into(&destination.key, &self.keys_with(others)?)
755    }
756
757    /// Remove the whole set, and say whether it was there. `DEL`.
758    ///
759    /// # Errors
760    ///
761    /// As [`Sets::add`].
762    pub fn clear(&self) -> Result<bool> {
763        self.sets.db.run(|inner| Ok(inner.strings.del(&self.key)))
764    }
765
766    /// This key followed by the others', once every one of them is checked to
767    /// belong here.
768    fn keys_with<'a>(&'a self, others: &[&'a Set]) -> Result<Vec<&'a [u8]>> {
769        let mut keys = Vec::with_capacity(others.len() + 1);
770        keys.push(&self.key[..]);
771        for other in others {
772            self.same_db(other)?;
773            keys.push(&other.key[..]);
774        }
775        Ok(keys)
776    }
777
778    /// The check that keeps two databases from being intersected with each
779    /// other.
780    ///
781    /// Without it, a handle from another database contributes its key and not
782    /// its contents, so the answer is computed against whatever this database
783    /// happens to hold under that name. That is not an empty answer or an error,
784    /// it is a plausible wrong one, and it would be a very hard afternoon.
785    fn same_db(&self, other: &Set) -> Result<()> {
786        if self.sets.db.is(&other.sets.db) {
787            return Ok(());
788        }
789        Err(Error::new(
790            Code::Invalid,
791            "those two sets are in different databases, and a set operation reads both of them out of one. Open both handles on the same Db",
792        ))
793    }
794}
795
796#[cfg(test)]
797mod tests {
798    use super::*;
799    use crate::{MEMORY, open};
800
801    #[test]
802    fn the_set_commands_are_the_ones_a_redis_client_would_send() {
803        let db = open(MEMORY).unwrap();
804        let sets = db.sets();
805
806        assert!(sets.add("online", "alice").unwrap());
807        assert!(!sets.add("online", "alice").unwrap());
808        assert_eq!(sets.add_many("online", &["bob", "carol"]).unwrap(), 2);
809
810        assert!(sets.contains("online", "bob").unwrap());
811        assert!(!sets.contains("online", "dave").unwrap());
812        assert_eq!(
813            sets.contains_many("online", &["alice", "dave"]).unwrap(),
814            vec![true, false]
815        );
816        assert_eq!(sets.len_of("online").unwrap(), 3);
817
818        assert!(sets.remove("online", "alice").unwrap());
819        assert_eq!(sets.remove_many("online", &["bob", "dave"]).unwrap(), 1);
820        assert_eq!(sets.len_of("online").unwrap(), 1);
821    }
822
823    /// A key that is not there answers the way an empty set answers, everywhere
824    /// it can, because a set nobody has added to and a set somebody emptied are
825    /// the same set.
826    #[test]
827    fn a_set_that_is_not_there_reads_as_an_empty_one() {
828        let db = open(MEMORY).unwrap();
829        let sets = db.sets();
830
831        assert_eq!(sets.len_of("nope").unwrap(), 0);
832        assert!(!sets.contains("nope", "x").unwrap());
833        assert_eq!(sets.pop("nope").unwrap(), None);
834        assert_eq!(sets.pick("nope").unwrap(), None);
835        assert!(sets.pop_n("nope", 5).unwrap().is_empty());
836        assert!(sets.pick_n("nope", 5).unwrap().is_empty());
837        // The one place it does not: SMEMBERS can say which it was.
838        assert_eq!(sets.members("nope").unwrap(), None);
839        assert!(!sets.for_each("nope", |_| {}).unwrap());
840    }
841
842    /// The point of the borrowed walk. A set of integers is stored as integers,
843    /// and this is the read that does not turn them back into text.
844    #[test]
845    fn walking_a_set_of_integers_never_formats_a_digit() {
846        let db = open(MEMORY).unwrap();
847        let ids = db.set("ids");
848        ids.add_many(&["1", "2", "3"]).unwrap();
849
850        let mut total = 0i64;
851        let mut ints = 0;
852        ids.for_each(|m| {
853            if let Member::Int(n) = m {
854                total += n;
855                ints += 1;
856            }
857        })
858        .unwrap();
859        assert_eq!(total, 6);
860        assert_eq!(ints, 3, "stored as integers, so handed over as integers");
861
862        // And the owned read gives back what a client would have seen.
863        let mut owned = ids.members().unwrap();
864        owned.sort();
865        assert_eq!(owned, vec![b"1".to_vec(), b"2".to_vec(), b"3".to_vec()]);
866    }
867
868    #[test]
869    fn a_handle_holds_the_key_so_the_caller_does_not() {
870        let db = open(MEMORY).unwrap();
871        let online = db.set("online");
872
873        online.add("alice").unwrap();
874        online.add_many(&["bob", "carol"]).unwrap();
875        assert_eq!(online.len().unwrap(), 3);
876        assert!(!online.is_empty().unwrap());
877        assert!(online.contains("bob").unwrap());
878        assert_eq!(online.key(), b"online");
879        assert!(format!("{online:?}").contains("online"));
880
881        // And it is the same key the keyspace door sees.
882        assert_eq!(db.sets().len_of("online").unwrap(), 3);
883    }
884
885    #[test]
886    fn a_set_that_loses_its_last_member_loses_its_key() {
887        let db = open(MEMORY).unwrap();
888        let only = db.set("only");
889
890        only.add("x").unwrap();
891        assert!(only.remove("x").unwrap());
892        assert!(only.is_empty().unwrap());
893        assert_eq!(db.sets().members("only").unwrap(), None);
894    }
895
896    #[test]
897    fn drawing_takes_members_out_and_picking_leaves_them() {
898        let db = open(MEMORY).unwrap();
899        let bag = db.set("bag");
900        bag.add_many(&["a", "b", "c", "d"]).unwrap();
901
902        assert!(bag.pick().unwrap().is_some());
903        assert_eq!(bag.len().unwrap(), 4, "picking leaves the set alone");
904        assert_eq!(bag.pick_n(3).unwrap().len(), 3);
905        assert_eq!(bag.len().unwrap(), 4);
906        // The with repeats form is the only one that can answer more members
907        // than the set holds.
908        assert_eq!(bag.pick_n(-9).unwrap().len(), 9);
909        assert_eq!(bag.len().unwrap(), 4);
910
911        assert!(bag.pop().unwrap().is_some());
912        assert_eq!(bag.len().unwrap(), 3, "popping takes one out");
913        assert_eq!(bag.pop_n(9).unwrap().len(), 3, "and never more than it has");
914        assert!(bag.is_empty().unwrap());
915    }
916
917    #[test]
918    fn the_three_set_operations_answer_what_they_are_named_after() {
919        let db = open(MEMORY).unwrap();
920        let a = db.set("a");
921        let b = db.set("b");
922        a.add_many(&["x", "y"]).unwrap();
923        b.add_many(&["y", "z"]).unwrap();
924
925        let sorted = |mut v: Vec<Vec<u8>>| {
926            v.sort();
927            v
928        };
929        assert_eq!(sorted(a.intersect(&[&b]).unwrap()), vec![b"y".to_vec()]);
930        assert_eq!(
931            sorted(a.union(&[&b]).unwrap()),
932            vec![b"x".to_vec(), b"y".to_vec(), b"z".to_vec()]
933        );
934        assert_eq!(sorted(a.difference(&[&b]).unwrap()), vec![b"x".to_vec()]);
935        assert_eq!(a.intersect_len(&[&b], 0).unwrap(), 1);
936        assert_eq!(a.union_len(&[&b], 0).unwrap(), 3);
937        assert_eq!(a.union_len(&[&b], 2).unwrap(), 2, "the limit stops it");
938        assert_eq!(a.difference_len(&[&b], 0).unwrap(), 1);
939        assert_eq!(b.difference_len(&[&a], 0).unwrap(), 1);
940
941        let out = db.set("out");
942        assert_eq!(a.union_into(&out, &[&b]).unwrap(), 3);
943        assert_eq!(out.len().unwrap(), 3);
944        assert_eq!(a.intersect_into(&out, &[&b]).unwrap(), 1);
945        assert_eq!(out.len().unwrap(), 1);
946        assert_eq!(a.difference_into(&out, &[&b]).unwrap(), 1);
947        assert_eq!(out.members().unwrap(), vec![b"x".to_vec()]);
948    }
949
950    /// An empty result removes the destination rather than leaving an empty set
951    /// behind, because there is no such thing as an empty set in the keyspace.
952    #[test]
953    fn storing_an_empty_result_removes_the_destination() {
954        let db = open(MEMORY).unwrap();
955        let a = db.set("a");
956        let b = db.set("b");
957        a.add("x").unwrap();
958        b.add("y").unwrap();
959
960        let out = db.set("out");
961        out.add("stale").unwrap();
962        assert_eq!(a.intersect_into(&out, &[&b]).unwrap(), 0);
963        assert_eq!(db.sets().members("out").unwrap(), None);
964    }
965
966    #[test]
967    fn a_member_moves_between_two_sets() {
968        let db = open(MEMORY).unwrap();
969        let from = db.set("from");
970        let to = db.set("to");
971        from.add_many(&["x", "y"]).unwrap();
972
973        assert!(from.move_to(&to, "x").unwrap());
974        assert!(!from.contains("x").unwrap());
975        assert!(to.contains("x").unwrap());
976        // A member that was not there does not move and does not create one.
977        assert!(!from.move_to(&to, "nope").unwrap());
978        assert_eq!(to.len().unwrap(), 1);
979    }
980
981    /// The failure this refuses to have. Two databases, both with a key called
982    /// `b`, and an intersection that reads the wrong one. It would not error and
983    /// it would not come back empty, it would come back plausible.
984    #[test]
985    fn two_databases_cannot_be_intersected_with_each_other() {
986        let one = open(MEMORY).unwrap();
987        let two = open(MEMORY).unwrap();
988
989        let a = one.set("a");
990        a.add_many(&["x", "y"]).unwrap();
991        // The decoy: `two` has a `b` that shares a member with `a`, so an
992        // unchecked intersection would answer `x` rather than fail.
993        one.set("b").add("z").unwrap();
994        let elsewhere = two.set("b");
995        elsewhere.add("x").unwrap();
996
997        let e = a.intersect(&[&elsewhere]).expect_err("different databases");
998        assert_eq!(e.code(), Code::Invalid);
999        assert!(e.message().contains("different databases"), "{e}");
1000
1001        // Every other door into another database is shut the same way.
1002        assert!(a.union(&[&elsewhere]).is_err());
1003        assert!(a.difference(&[&elsewhere]).is_err());
1004        assert!(a.intersect_len(&[&elsewhere], 0).is_err());
1005        assert!(a.move_to(&elsewhere, "x").is_err());
1006        assert!(a.intersect_into(&elsewhere, &[]).is_err());
1007        assert!(a.union_into(&elsewhere, &[]).is_err());
1008        assert!(a.difference_into(&elsewhere, &[]).is_err());
1009    }
1010
1011    /// The embedded door and the wire door are one store (Y23), so a set added
1012    /// here is a set the keyspace holds and a `DEL` here removes it.
1013    #[test]
1014    fn a_set_and_the_keyspace_are_the_same_store() {
1015        let db = open(MEMORY).unwrap();
1016        let tags = db.set("tags");
1017        tags.add("rust").unwrap();
1018
1019        // A string command on a key holding a set is the same WRONGTYPE a
1020        // client would get.
1021        let e = db.strings().get("tags").expect_err("that is a set");
1022        assert_eq!(e.code(), Code::WrongType);
1023        // And the other way round.
1024        db.strings().set("word", "nope").unwrap();
1025        assert_eq!(db.set("word").add("x").unwrap_err().code(), Code::WrongType);
1026
1027        assert!(tags.clear().unwrap());
1028        assert!(tags.is_empty().unwrap());
1029        assert!(!tags.clear().unwrap());
1030    }
1031
1032    #[test]
1033    fn a_member_is_bytes_and_not_only_text() {
1034        let db = open(MEMORY).unwrap();
1035        let raw = db.set("raw");
1036
1037        raw.add(vec![0u8, 0xff]).unwrap();
1038        assert!(raw.contains(b"\x00\xff").unwrap());
1039        assert_eq!(raw.members().unwrap(), vec![vec![0u8, 0xff]]);
1040    }
1041}