Skip to main content

yo_kv/
arrays.rs

1//! The array commands.
2//!
3//! One method per Redis command on [`Keyspace`], the same arrangement the list
4//! and set commands use and for the same reason: a key belongs to the database
5//! and not to a type, so `ARSET` against a string has to be able to see that it
6//! is a string. The array itself is [`crate::array`]. This file is what the wire
7//! and the embedded API both call.
8//!
9//! # Indices are unsigned and that changes things
10//!
11//! Every other collection here takes a signed index and counts from the back
12//! when it is negative. An array does not: the index is a position in a space
13//! that runs to `2^64 - 2`, there is no back to count from, and `-1` is an error
14//! rather than the last element. The wire layer parses an index with
15//! [`parse_index`] rather than with the signed parser the list commands use, and
16//! the error it gives back is Redis's own wording.
17//!
18//! # An empty array is not an array
19//!
20//! The key goes when the last element does, which is the same rule every
21//! collection here follows and the reason `EXISTS` answers zero after the last
22//! `ARDEL`.
23
24use yo_common::num::{parse_f64, parse_i64};
25use yo_common::re::{self, Matcher, Regex};
26use yo_common::{Code, Error, Result, glob};
27
28use crate::array::{Array, ELEMENT_MAX, Element, INDEX_MAX, Info};
29use crate::keyspace::Keyspace;
30use crate::strings;
31use crate::value::{self, Kind};
32
33/// What every array command says about an index it cannot read.
34///
35/// Redis's words, because they go on the wire verbatim. It covers a negative
36/// number, a number with anything but digits in it, and `2^64 - 1`, which is
37/// reserved rather than addressable.
38pub const BAD_INDEX: &str = "invalid array index";
39
40/// What `ARSET` says when the last index it would write to does not exist.
41pub const INDEX_OVERFLOW: &str = "array index overflow";
42
43/// The most positions `ARGETRANGE` will answer for.
44///
45/// Redis's `ARGETRANGE_MAX_ITEMS`, and its comment says this "must be part of
46/// the Redis culture, so it should not be tuned in any way". The reason is
47/// worth keeping: the reply is one entry per position and not one per element,
48/// so without a limit `ARGETRANGE k 0 18446744073709551614` against a key that
49/// does not exist is a request for eighteen quintillion nulls, which is a way to
50/// stop a server with four short words.
51pub const GETRANGE_MAX: u64 = 1_000_000;
52
53/// Reads an index the way Redis reads one.
54///
55/// Unsigned, no leading plus, no leading zeros, and `2^64 - 1` refused because
56/// it is the "nothing has been inserted yet" marker in the cursor `ARINSERT`
57/// and `ARNEXT` share. Everything else in the range is a position, including
58/// zero.
59///
60/// # Errors
61///
62/// [`Code::Invalid`] with Redis's own message, for anything else.
63pub fn parse_index(bytes: &[u8]) -> Result<u64> {
64    parse_ull(bytes, false)
65}
66
67/// Reads the one index that may be `2^64 - 1`, which is `ARSEEK`'s.
68///
69/// Seeking to the top of the space is how the cursor gets into the state where
70/// the next append has nowhere to go, and that state has to be reachable from a
71/// command because the log that rebuilds a database is made of commands.
72///
73/// # Errors
74///
75/// [`Code::Invalid`] with Redis's own message, the same as [`parse_index`].
76pub fn parse_seek_index(bytes: &[u8]) -> Result<u64> {
77    parse_ull(bytes, true)
78}
79
80fn parse_ull(bytes: &[u8], allow_max: bool) -> Result<u64> {
81    let bad = || Error::new(Code::Invalid, BAD_INDEX);
82    if bytes.is_empty() || bytes.len() > 20 {
83        return Err(bad());
84    }
85    // Redis's `string2ull`: one zero on its own is fine, a leading zero in front
86    // of anything else is not, and nothing but digits is allowed.
87    if bytes[0] == b'0' && bytes.len() > 1 {
88        return Err(bad());
89    }
90    let mut n: u64 = 0;
91    for &c in bytes {
92        if !c.is_ascii_digit() {
93            return Err(bad());
94        }
95        n = n
96            .checked_mul(10)
97            .and_then(|n| n.checked_add(u64::from(c - b'0')))
98            .ok_or_else(bad)?;
99    }
100    if n > INDEX_MAX && !allow_max {
101        return Err(bad());
102    }
103    Ok(n)
104}
105
106/// The aggregations `AROP` knows how to do.
107///
108/// They are all order independent, which is why the walk can go whichever way
109/// the two ends point without the answer changing.
110#[derive(Debug, Clone, Copy, PartialEq, Eq)]
111pub enum Op {
112    /// Add up everything that is a number.
113    Sum,
114    /// The smallest of them.
115    Min,
116    /// The largest of them.
117    Max,
118    /// Bitwise and over everything that is a whole number.
119    And,
120    /// Bitwise or.
121    Or,
122    /// Bitwise exclusive or.
123    Xor,
124    /// How many elements are exactly these bytes.
125    Match,
126    /// How many positions in the range hold anything at all.
127    Used,
128}
129
130/// What an [`Op`] came to.
131#[derive(Debug, Clone, Copy, PartialEq)]
132pub enum Aggregate {
133    /// A count or a bitwise result, which goes back as an integer.
134    Int(i64),
135    /// A sum or an end of the range, which goes back as a string of digits
136    /// because it may not be a whole number.
137    Num(f64),
138    /// Nothing in the range was any use to the operation, which is a null. An
139    /// empty range and a range of nothing but words both land here.
140    None,
141}
142
143/// The most predicates one `ARGREP` will carry.
144///
145/// Redis's `ARGREP_MAX_PREDICATES`. The point of a ceiling is that every
146/// predicate is evaluated against every element the walk visits, so a command
147/// with a thousand of them is a way of asking one shard thread to do a thousand
148/// times the work for one reply.
149pub const GREP_MAX_PREDICATES: usize = 250;
150
151/// The longest regular expression `ARGREP` will compile.
152///
153/// Redis's `ARGREP_MAX_RE_LEN`, and the same reasoning: the compile happens on
154/// the thread that owns the keys.
155pub const GREP_MAX_RE_LEN: usize = 2048;
156
157/// One end of the range `ARGREP` searches.
158///
159/// `ARGREP` is the only array command that takes anything but a number here.
160/// `-` and `+` mean the two ends of the array as it is at the moment the
161/// command runs, which cannot be resolved while the arguments are being read
162/// because the key has not been looked at yet.
163#[derive(Debug, Clone, Copy, PartialEq, Eq)]
164pub enum Bound {
165    /// A position, read the way every other array index is read.
166    Index(u64),
167    /// `-`, which is index zero.
168    First,
169    /// `+`, which is the highest index the array has.
170    Last,
171}
172
173impl Bound {
174    /// The position this comes to for an array whose highest index is `max`.
175    fn resolve(self, max: u64) -> u64 {
176        match self {
177            Bound::Index(i) => i,
178            Bound::First => 0,
179            Bound::Last => max,
180        }
181    }
182}
183
184/// Reads one of `ARGREP`'s two bounds.
185///
186/// # Errors
187///
188/// [`BAD_INDEX`] for anything that is neither `-` nor `+` nor an index.
189pub fn parse_grep_bound(bytes: &[u8]) -> Result<Bound> {
190    match bytes {
191        b"-" => Ok(Bound::First),
192        b"+" => Ok(Bound::Last),
193        other => Ok(Bound::Index(parse_index(other)?)),
194    }
195}
196
197/// One test `ARGREP` applies to an element.
198#[derive(Debug, Clone, Copy, PartialEq, Eq)]
199pub enum Test {
200    /// `EXACT`, the whole element and nothing else.
201    Exact,
202    /// `MATCH`, the pattern anywhere inside the element.
203    Match,
204    /// `GLOB`, the pattern read as a glob.
205    Glob,
206    /// `RE`, the pattern read as an extended regular expression.
207    Re,
208}
209
210/// What one `ARGREP` was asked to look for.
211///
212/// Built once per command and then asked about every element the walk visits,
213/// which is why the compiled regexes and the matcher's scratch space live here
214/// rather than being made per element.
215///
216/// # This one allocates
217///
218/// Every other command path here is allocation free, and `ARGREP` cannot be:
219/// compiling a regular expression means building a program, and the plan holds
220/// up to two hundred and fifty predicates. Redis allocates in the same two
221/// places for the same reasons. The allocations are wrapped in
222/// [`yo_alloc::allow`] and they all happen while the command is being read, so
223/// the walk itself is still allocation free however many elements it visits.
224pub struct Grep<'a> {
225    /// The tests in the order they were given, since `OR` stops at the first
226    /// one that holds and the cheap ones are usually written first.
227    tests: Vec<(Test, &'a [u8])>,
228    /// The compiled form of every `RE` pattern, in the same order as the `Re`
229    /// entries in `tests`.
230    regexes: Vec<Regex>,
231    /// The scratch the regex engine walks with, kept across elements.
232    matcher: Matcher,
233    /// `AND` rather than the default `OR`.
234    all: bool,
235    /// `NOCASE`, which folds ASCII letters in all four tests.
236    nocase: bool,
237}
238
239impl Default for Grep<'_> {
240    fn default() -> Self {
241        Grep::new()
242    }
243}
244
245impl<'a> Grep<'a> {
246    /// An empty plan, which is not a usable one until it has been told what to
247    /// look for and then [`Grep::compile`]d.
248    #[must_use]
249    pub fn new() -> Grep<'a> {
250        Grep {
251            tests: Vec::new(),
252            regexes: Vec::new(),
253            matcher: Matcher::new(),
254            all: false,
255            nocase: false,
256        }
257    }
258
259    /// Adds one predicate in the order it was written.
260    ///
261    /// # Errors
262    ///
263    /// [`Code::Invalid`] once there are [`GREP_MAX_PREDICATES`] of them, or for
264    /// an `RE` pattern longer than [`GREP_MAX_RE_LEN`]. Both are checked here
265    /// rather than at the end because Redis checks them as it reads, so a
266    /// command that is wrong in two ways reports whichever comes first.
267    pub fn push(&mut self, test: Test, pattern: &'a [u8]) -> Result<()> {
268        if self.tests.len() >= GREP_MAX_PREDICATES {
269            return Err(Error::fmt(
270                Code::Invalid,
271                format_args!("too many predicates, maximum is {GREP_MAX_PREDICATES}"),
272            ));
273        }
274        if test == Test::Re && pattern.len() > GREP_MAX_RE_LEN {
275            return Err(Error::fmt(
276                Code::Invalid,
277                format_args!("regular expression is too long, maximum is {GREP_MAX_RE_LEN} bytes"),
278            ));
279        }
280        yo_alloc::allow(|| self.tests.push((test, pattern)));
281        Ok(())
282    }
283
284    /// How many predicates the plan carries, since none at all is a syntax
285    /// error and the caller is the one that says so.
286    #[must_use]
287    pub fn len(&self) -> usize {
288        self.tests.len()
289    }
290
291    /// Whether nothing has been asked for yet.
292    #[must_use]
293    pub fn is_empty(&self) -> bool {
294        self.tests.is_empty()
295    }
296
297    /// Settles the two global options and compiles the regular expressions.
298    ///
299    /// The compile is deliberately the last thing that happens while the command
300    /// is being read, because `NOCASE` is a global option that may come after
301    /// the pattern it applies to.
302    ///
303    /// # Errors
304    ///
305    /// [`Code::Invalid`] with the sentence Redis uses for an empty pattern, a
306    /// pattern that will not compile, or a pattern using a backreference.
307    pub fn compile(&mut self, all: bool, nocase: bool) -> Result<()> {
308        self.all = all;
309        self.nocase = nocase;
310        for (test, pattern) in &self.tests {
311            if *test != Test::Re {
312                continue;
313            }
314            if pattern.is_empty() {
315                return Err(Error::new(Code::Invalid, "regular expression is empty"));
316            }
317            match yo_alloc::allow(|| Regex::new(pattern, nocase)) {
318                Ok(re) => yo_alloc::allow(|| {
319                    // Grow the matcher's scratch to fit while allocating is
320                    // still allowed, so the walk over the elements does not.
321                    self.matcher.reserve(&re);
322                    self.regexes.push(re);
323                }),
324                // The one code that is Redis's own sentence rather than TRE's
325                // message, so it goes out on its own with nothing in front of
326                // it.
327                Err(re::Error::Unsupported) => {
328                    return Err(Error::new(Code::Invalid, re::Error::Unsupported.as_str()));
329                }
330                Err(e) => {
331                    return Err(Error::fmt(
332                        Code::Invalid,
333                        format_args!("invalid regular expression: {e}"),
334                    ));
335                }
336            }
337        }
338        Ok(())
339    }
340
341    /// Whether the element's bytes answer the plan.
342    fn holds(&mut self, data: &[u8]) -> bool {
343        let mut re = 0;
344        for i in 0..self.tests.len() {
345            let (test, pattern) = self.tests[i];
346            let hit = match test {
347                Test::Exact => equal(data, pattern, self.nocase),
348                Test::Match => contains(data, pattern, self.nocase),
349                Test::Glob => glob::matches_nocase(pattern, data, self.nocase),
350                Test::Re => {
351                    let at = re;
352                    re += 1;
353                    self.matcher.is_match(&self.regexes[at], data)
354                }
355            };
356            // `OR` is done as soon as one holds and `AND` as soon as one does
357            // not, which is what makes putting the cheap test first worth
358            // something.
359            if hit != self.all {
360                return hit;
361            }
362        }
363        self.all
364    }
365}
366
367/// One ASCII letter folded down, and every other byte left alone.
368///
369/// Redis folds ASCII and only ASCII here, deliberately, so that the answer does
370/// not depend on a locale and an element holding arbitrary bytes cannot be read
371/// as text by accident.
372fn fold(b: u8) -> u8 {
373    b.to_ascii_lowercase()
374}
375
376/// Whether two strings of bytes are the same, ASCII case aside.
377fn equal(a: &[u8], b: &[u8], nocase: bool) -> bool {
378    if a.len() != b.len() {
379        return false;
380    }
381    if !nocase {
382        return a == b;
383    }
384    a.iter().zip(b).all(|(x, y)| fold(*x) == fold(*y))
385}
386
387/// Whether `needle` appears anywhere in `haystack`, ASCII case aside.
388fn contains(haystack: &[u8], needle: &[u8], nocase: bool) -> bool {
389    if needle.is_empty() {
390        return true;
391    }
392    if needle.len() > haystack.len() {
393        return false;
394    }
395    // Redis walks every offset and compares from it, and so does this. The
396    // first byte is checked before the rest of the window is looked at, which
397    // is the whole of the difference on a haystack that does not hold the
398    // needle.
399    let first = needle[0];
400    for at in 0..=haystack.len() - needle.len() {
401        let head = haystack[at];
402        let same = head == first || (nocase && fold(head) == fold(first));
403        if same && equal(&haystack[at..at + needle.len()], needle, nocase) {
404            return true;
405        }
406    }
407    false
408}
409
410/// An element as a whole number, for the bitwise operations.
411///
412/// A float is truncated towards zero the way Redis does it, and one that will
413/// not fit is skipped rather than saturated, because a saturated value would
414/// quietly poison an `AND` with a row of ones.
415fn as_int(el: Element<'_>) -> Option<i64> {
416    match el {
417        Element::Int(n) => Some(n),
418        Element::Float(d) => whole(d),
419        _ => {
420            let mut buf = [0u8; ELEMENT_MAX];
421            let text = el.text(&mut buf);
422            parse_i64(text).or_else(|| whole(parse_f64(text)?))
423        }
424    }
425}
426
427/// An element as a number, for the arithmetic operations.
428fn as_num(el: Element<'_>) -> Option<f64> {
429    match el {
430        Element::Int(n) => Some(n as f64),
431        Element::Float(d) => Some(d),
432        _ => {
433            let mut buf = [0u8; ELEMENT_MAX];
434            parse_f64(el.text(&mut buf))
435        }
436    }
437}
438
439/// A double as the integer it truncates to, or nothing when it does not.
440fn whole(d: f64) -> Option<i64> {
441    if d.is_nan() || d < -(2f64.powi(63)) || d >= 2f64.powi(63) {
442        return None;
443    }
444    Some(d as i64)
445}
446
447impl Keyspace {
448    /// `ARSET key index value [value ...]`, which writes at consecutive indices.
449    ///
450    /// Answers how many of the positions were empty before, which is not the
451    /// same as how many values were written: `ARSET k 0 a b` twice answers 2 and
452    /// then 0.
453    ///
454    /// # Errors
455    ///
456    /// [`Code::Invalid`] when the last index the write would reach does not
457    /// exist, so that a write which would run off the top of the index space
458    /// fails before any of it lands rather than half way through.
459    pub fn arset<'v>(
460        &mut self,
461        key: &[u8],
462        index: u64,
463        values: impl Iterator<Item = &'v [u8]> + Clone,
464    ) -> Result<u64> {
465        let count = values.clone().count() as u64;
466        if count == 0 {
467            return Ok(0);
468        }
469        // The last index is `index + count - 1`, and both the overflow and
470        // landing on the reserved top of the space are the same error.
471        if index
472            .checked_add(count - 1)
473            .is_none_or(|last| last > INDEX_MAX)
474        {
475            return Err(Error::new(Code::Invalid, INDEX_OVERFLOW));
476        }
477        for v in values.clone() {
478            strings::check_len(key, v.len())?;
479        }
480
481        let at = match self.array_slot(key)? {
482            Some(at) => at,
483            None => self.new_array(key),
484        };
485        let array = self
486            .arrays
487            .get_mut(at)
488            .expect("the record points at its body");
489        let mut filled = 0;
490        for (i, v) in values.enumerate() {
491            if array.set(index + i as u64, v)? {
492                filled += 1;
493            }
494        }
495        Ok(filled)
496    }
497
498    /// `ARMSET key index value [index value ...]`, which writes scattered pairs.
499    ///
500    /// Answers how many of the positions were empty before, the same as
501    /// [`Keyspace::arset`]. The pairs arrive already parsed, because the wire
502    /// layer has to read every index before it writes any of them: a bad index
503    /// in the last pair fails the whole command and leaves the earlier pairs
504    /// unwritten.
505    pub fn armset<'v>(
506        &mut self,
507        key: &[u8],
508        pairs: impl Iterator<Item = (u64, &'v [u8])> + Clone,
509    ) -> Result<u64> {
510        if pairs.clone().next().is_none() {
511            return Ok(0);
512        }
513        for (_, v) in pairs.clone() {
514            strings::check_len(key, v.len())?;
515        }
516        let at = match self.array_slot(key)? {
517            Some(at) => at,
518            None => self.new_array(key),
519        };
520        let array = self
521            .arrays
522            .get_mut(at)
523            .expect("the record points at its body");
524        let mut filled = 0;
525        for (index, v) in pairs {
526            if array.set(index, v)? {
527                filled += 1;
528            }
529        }
530        Ok(filled)
531    }
532
533    /// `ARGET key index`. A hole and a missing key are the same answer.
534    pub fn arget(&mut self, key: &[u8], index: u64) -> Result<Option<Element<'_>>> {
535        let Some(at) = self.array_slot(key)? else {
536            return Ok(None);
537        };
538        Ok(self.array_at(at).get(index))
539    }
540
541    /// `ARMGET key index [index ...]`, straight into the reply.
542    ///
543    /// `f` is called once per index in the order they were asked for, with the
544    /// element or `None` for a hole, and it is called while the element is still
545    /// in the array so that nothing is copied on the way (Y18).
546    pub fn arget_into<F>(
547        &mut self,
548        key: &[u8],
549        indices: impl Iterator<Item = u64>,
550        mut f: F,
551    ) -> Result<()>
552    where
553        F: FnMut(Option<Element<'_>>),
554    {
555        let slot = self.array_slot(key)?;
556        match slot {
557            Some(at) => {
558                let array = self.array_at(at);
559                for index in indices {
560                    f(array.get(index));
561                }
562            }
563            // A key that is not there answers the same as an array of holes,
564            // which is Redis's rule and the reason this is not an early return
565            // with nothing written.
566            None => {
567                for _ in indices {
568                    f(None);
569                }
570            }
571        }
572        Ok(())
573    }
574
575    /// `ARGETRANGE key start end`, every position in the range and not every
576    /// element.
577    ///
578    /// `f` is called once per position, holes included, low to high or high to
579    /// low depending on which way round the two ends came in. The count is
580    /// answered first so that the caller can write the array header before the
581    /// first element.
582    ///
583    /// # Errors
584    ///
585    /// [`Code::Invalid`] when the range covers more than [`GETRANGE_MAX`]
586    /// positions.
587    pub fn argetrange<F>(&mut self, key: &[u8], start: u64, end: u64, mut f: F) -> Result<u64>
588    where
589        F: FnMut(Option<Element<'_>>),
590    {
591        let reverse = start > end;
592        let (lo, hi) = if reverse { (end, start) } else { (start, end) };
593        let len = hi - lo + 1;
594        if len > GETRANGE_MAX {
595            return Err(Error::fmt(
596                Code::Invalid,
597                format_args!("range exceeds maximum of {GETRANGE_MAX} items"),
598            ));
599        }
600        let slot = self.array_slot(key)?;
601        let Some(at) = slot else {
602            for _ in 0..len {
603                f(None);
604            }
605            return Ok(len);
606        };
607        let array = self.array_at(at);
608        if reverse {
609            for i in 0..len {
610                f(array.get(hi - i));
611            }
612        } else {
613            for i in 0..len {
614                f(array.get(lo + i));
615            }
616        }
617        Ok(len)
618    }
619
620    /// `ARLEN key`, the highest populated index plus one.
621    ///
622    /// Zero for a key that is not there, and note that this is not the number of
623    /// elements. [`Keyspace::arcount`] is that.
624    pub fn arlen(&mut self, key: &[u8]) -> Result<u64> {
625        Ok(match self.array_slot(key)? {
626            Some(at) => self.array_at(at).len(),
627            None => 0,
628        })
629    }
630
631    /// `ARCOUNT key`, how many indices hold something.
632    pub fn arcount(&mut self, key: &[u8]) -> Result<u64> {
633        Ok(match self.array_slot(key)? {
634            Some(at) => self.array_at(at).count(),
635            None => 0,
636        })
637    }
638
639    /// `ARDEL key index [index ...]`. Answers how many held something.
640    ///
641    /// The key goes when the last element does.
642    pub fn ardel(&mut self, key: &[u8], indices: impl Iterator<Item = u64>) -> Result<u64> {
643        let Some(at) = self.array_slot(key)? else {
644            return Ok(0);
645        };
646        let array = self
647            .arrays
648            .get_mut(at)
649            .expect("the record points at its body");
650        let mut gone = 0;
651        for index in indices {
652            if array.del(index) {
653                gone += 1;
654            }
655        }
656        if array.is_empty() {
657            self.drop_key(key);
658        }
659        Ok(gone)
660    }
661
662    /// `ARDELRANGE key start end [start end ...]`. Answers how many went.
663    ///
664    /// Each pair may come in either order. The cost is in the elements the
665    /// ranges touch and not in how wide they are, so clearing the whole index
666    /// space of a key holding three elements is three deletes.
667    pub fn ardelrange(
668        &mut self,
669        key: &[u8],
670        ranges: impl Iterator<Item = (u64, u64)>,
671    ) -> Result<u64> {
672        let Some(at) = self.array_slot(key)? else {
673            return Ok(0);
674        };
675        let array = self
676            .arrays
677            .get_mut(at)
678            .expect("the record points at its body");
679        let mut gone = 0;
680        for (start, end) in ranges {
681            let (lo, hi) = if start <= end {
682                (start, end)
683            } else {
684                (end, start)
685            };
686            gone += array.delete_range(lo, hi);
687        }
688        if array.is_empty() {
689            self.drop_key(key);
690        }
691        Ok(gone)
692    }
693
694    /// `ARINSERT key value [value ...]`, which appends at the cursor.
695    ///
696    /// Answers the index the last value landed on. The cursor starts at zero
697    /// and a plain `ARSET` never moves it, so an array somebody has written by
698    /// index and then appended to will have the first append land on top of
699    /// index zero. That is Redis's behaviour and it is the reason `ARSEEK`
700    /// exists.
701    ///
702    /// # Errors
703    ///
704    /// [`Code::Invalid`] when the batch would run off the top of the index
705    /// space, checked before any of it is written.
706    pub fn arinsert<'v>(
707        &mut self,
708        key: &[u8],
709        values: impl Iterator<Item = &'v [u8]> + Clone,
710    ) -> Result<u64> {
711        for v in values.clone() {
712            strings::check_len(key, v.len())?;
713        }
714        let at = match self.array_slot(key)? {
715            Some(at) => at,
716            // A new array has its cursor at zero, so the append below cannot
717            // fail on one and cannot leave an empty key behind.
718            None => self.new_array(key),
719        };
720        self.arrays
721            .get_mut(at)
722            .expect("the record points at its body")
723            .append(values)
724    }
725
726    /// `ARRING key size value [value ...]`, a ring buffer over the indices.
727    ///
728    /// Answers the index the last value landed on. `size` has to be at least
729    /// one, which the caller checks because Redis reports a bad size before it
730    /// has even looked at the key.
731    pub fn arring<'v>(
732        &mut self,
733        key: &[u8],
734        size: u64,
735        values: impl Iterator<Item = &'v [u8]> + Clone,
736    ) -> Result<u64> {
737        debug_assert!(size > 0, "the caller checks the size");
738        for v in values.clone() {
739            strings::check_len(key, v.len())?;
740        }
741        let at = match self.array_slot(key)? {
742            Some(at) => at,
743            None => self.new_array(key),
744        };
745        self.arrays
746            .get_mut(at)
747            .expect("the record points at its body")
748            .ring(size, values)
749    }
750
751    /// `ARNEXT key`, where the next append would go.
752    ///
753    /// Zero for a key that is not there and zero for a cursor nothing has moved
754    /// yet, which are the same answer because they mean the same thing. `None`
755    /// is the null a client sees when the cursor has run out of index space and
756    /// there is no honest answer to give.
757    pub fn arnext(&mut self, key: &[u8]) -> Result<Option<u64>> {
758        Ok(match self.array_slot(key)? {
759            Some(at) => self.array_at(at).next_index(),
760            None => Some(0),
761        })
762    }
763
764    /// `ARSEEK key index`, which points the cursor.
765    ///
766    /// Answers whether there was a key to point. A missing key answers false
767    /// and is not created, because an array with nothing in it is not a key
768    /// here and an error would be worse: the caller asked to move a cursor, and
769    /// the honest answer is that there was no cursor to move.
770    ///
771    /// `index` is the one place in the array commands where `2^64 - 1` is a
772    /// legal argument. It leaves the cursor in the terminal state, which is
773    /// what the rewritten command has to say to reproduce that state on load.
774    pub fn arseek(&mut self, key: &[u8], index: u64) -> Result<bool> {
775        let Some(at) = self.array_slot(key)? else {
776            return Ok(false);
777        };
778        self.arrays
779            .get_mut(at)
780            .expect("the record points at its body")
781            .seek(index);
782        Ok(true)
783    }
784
785    /// `ARLASTITEMS key count [REV]`, the newest positions from the cursor.
786    ///
787    /// `f` is called once per position, oldest first unless `newest_first`, and
788    /// a hole inside the window is a `None` rather than something skipped. The
789    /// count is answered so the caller can close its array header.
790    pub fn arlastitems<F>(
791        &mut self,
792        key: &[u8],
793        count: u64,
794        newest_first: bool,
795        f: F,
796    ) -> Result<u64>
797    where
798        F: FnMut(Option<Element<'_>>),
799    {
800        Ok(match self.array_slot(key)? {
801            Some(at) => self.array_at(at).last_items(count, newest_first, f),
802            None => 0,
803        })
804    }
805
806    /// `ARSCAN key start end [LIMIT count]`, the elements and not the positions.
807    ///
808    /// `f` is called with the index and the element for everything populated in
809    /// the range, low to high or high to low depending on which way round the
810    /// ends came in, and at most `limit` times. Answers how many that was.
811    ///
812    /// Unlike [`Keyspace::argetrange`] this has no ceiling on the range, and it
813    /// does not need one: holes cost nothing, so `ARSCAN k 0 18446744073709551614`
814    /// against a key holding three elements is three visits and not eighteen
815    /// quintillion.
816    pub fn arscan<F>(
817        &mut self,
818        key: &[u8],
819        start: u64,
820        end: u64,
821        limit: u64,
822        mut f: F,
823    ) -> Result<u64>
824    where
825        F: FnMut(u64, Element<'_>),
826    {
827        let Some(at) = self.array_slot(key)? else {
828            return Ok(0);
829        };
830        let mut seen = 0;
831        if limit > 0 {
832            self.array_at(at).scan(start, end, |index, el| {
833                f(index, el);
834                seen += 1;
835                seen < limit
836            });
837        }
838        Ok(seen)
839    }
840
841    /// `ARGREP key start end predicate ... [AND | OR] [LIMIT n] [WITHVALUES] [NOCASE]`.
842    ///
843    /// [`Keyspace::arscan`]'s walk with a test in front of the callback, so it
844    /// costs the elements in the range and not its width. `f` is called with the
845    /// index and the element for everything that answers `grep`, at most `limit`
846    /// times, and the count is what came back.
847    ///
848    /// The two bounds arrive as [`Bound`] rather than as numbers because `+`
849    /// means the end of the array as it is now, which is not known until the key
850    /// has been found.
851    pub fn argrep<F>(
852        &mut self,
853        key: &[u8],
854        start: Bound,
855        end: Bound,
856        limit: u64,
857        grep: &mut Grep<'_>,
858        mut f: F,
859    ) -> Result<u64>
860    where
861        F: FnMut(u64, Element<'_>),
862    {
863        let Some(at) = self.array_slot(key)? else {
864            return Ok(0);
865        };
866        let array = self.array_at(at);
867        let len = array.len();
868        if len == 0 || limit == 0 {
869            return Ok(0);
870        }
871        let max = len - 1;
872        let mut hits = 0;
873        array.scan(start.resolve(max), end.resolve(max), |index, el| {
874            let mut buf = [0u8; ELEMENT_MAX];
875            if grep.holds(el.text(&mut buf)) {
876                f(index, el);
877                hits += 1;
878            }
879            // The limit counts what matched and not what was looked at, so a
880            // range full of misses is walked to its end.
881            hits < limit
882        });
883        Ok(hits)
884    }
885
886    /// `AROP key start end OP [value]`, one number out of a whole range.
887    ///
888    /// The walk is [`Keyspace::arscan`]'s, so it costs the elements in the range
889    /// and not its width, and every operation here is order independent so the
890    /// direction the ends came in does not matter.
891    pub fn arop(
892        &mut self,
893        key: &[u8],
894        start: u64,
895        end: u64,
896        op: Op,
897        want: &[u8],
898    ) -> Result<Aggregate> {
899        let Some(at) = self.array_slot(key)? else {
900            // A count of nothing is zero and an aggregate of nothing is a null,
901            // which is the difference between asking how many and asking what.
902            return Ok(match op {
903                Op::Match | Op::Used => Aggregate::Int(0),
904                _ => Aggregate::None,
905            });
906        };
907        let mut counted = 0i64;
908        let mut bits: Option<i64> = None;
909        let mut num: Option<f64> = None;
910        self.array_at(at).scan(start, end, |_, el| {
911            match op {
912                Op::Used => counted += 1,
913                Op::Match => {
914                    let mut buf = [0u8; ELEMENT_MAX];
915                    if el.text(&mut buf) == want {
916                        counted += 1;
917                    }
918                }
919                Op::And | Op::Or | Op::Xor => {
920                    if let Some(i) = as_int(el) {
921                        bits = Some(match (bits, op) {
922                            (None, _) => i,
923                            (Some(acc), Op::And) => acc & i,
924                            (Some(acc), Op::Or) => acc | i,
925                            (Some(acc), _) => acc ^ i,
926                        });
927                    }
928                }
929                Op::Sum | Op::Min | Op::Max => {
930                    if let Some(d) = as_num(el) {
931                        num = Some(match (num, op) {
932                            (None, _) => d,
933                            (Some(acc), Op::Sum) => acc + d,
934                            (Some(acc), Op::Min) => acc.min(d),
935                            (Some(acc), _) => acc.max(d),
936                        });
937                    }
938                }
939            }
940            true
941        });
942        Ok(match op {
943            Op::Match | Op::Used => Aggregate::Int(counted),
944            Op::And | Op::Or | Op::Xor => bits.map_or(Aggregate::None, Aggregate::Int),
945            _ => num.map_or(Aggregate::None, Aggregate::Num),
946        })
947    }
948
949    /// `ARINFO key [FULL]`, the shape of the array.
950    ///
951    /// # Errors
952    ///
953    /// [`Code::Invalid`] carrying `no such key` for a key that is not there, which is the one array
954    /// command that treats a missing key as a mistake rather than as an empty
955    /// array. It is reporting on a structure, and there is no structure.
956    pub fn arinfo(&mut self, key: &[u8], full: bool) -> Result<Info> {
957        let Some(at) = self.array_slot(key)? else {
958            return Err(crate::keys::no_such_key());
959        };
960        Ok(self.array_at(at).info(full))
961    }
962
963    /// Where `key`'s array is, or `None` if there is no such key.
964    ///
965    /// # Errors
966    ///
967    /// [`Code::WrongType`] if the key holds something that is not an array.
968    fn array_slot(&mut self, key: &[u8]) -> Result<Option<u32>> {
969        self.live_slot(key, Kind::Array)
970    }
971
972    fn array_at(&self, at: u32) -> &Array {
973        self.arrays.get(at).expect("the record points at its body")
974    }
975
976    fn new_array(&mut self, key: &[u8]) -> u32 {
977        let at = self.arrays.insert(Array::new());
978        let len = value::slot_record_len(false);
979        self.write_rec(key, len, |out| {
980            value::write_slot_record(out, Kind::Array, at, None);
981        });
982        self.bodies += 1;
983        at
984    }
985}
986
987#[cfg(test)]
988mod tests {
989    use super::*;
990    use crate::array::ELEMENT_MAX;
991
992    fn db() -> Keyspace {
993        Keyspace::new()
994    }
995
996    /// The bytes a client would see at one index.
997    fn read(d: &mut Keyspace, key: &[u8], index: u64) -> Option<Vec<u8>> {
998        let el = d.arget(key, index).expect("an array")?;
999        let mut buf = [0u8; ELEMENT_MAX];
1000        Some(el.text(&mut buf).to_vec())
1001    }
1002
1003    fn set(d: &mut Keyspace, key: &[u8], index: u64, vals: &[&[u8]]) -> u64 {
1004        d.arset(key, index, vals.iter().copied()).expect("an array")
1005    }
1006
1007    #[test]
1008    fn a_write_makes_the_key_and_a_read_finds_it() {
1009        let mut d = db();
1010        assert_eq!(read(&mut d, b"a", 0), None, "no key yet");
1011        assert_eq!(set(&mut d, b"a", 5, &[b"x"]), 1);
1012        assert_eq!(d.kind_of(b"a"), Some(Kind::Array));
1013        assert_eq!(read(&mut d, b"a", 5).as_deref(), Some(&b"x"[..]));
1014        assert_eq!(read(&mut d, b"a", 4), None, "a hole");
1015        assert_eq!(d.arlen(b"a").expect("an array"), 6);
1016        assert_eq!(d.arcount(b"a").expect("an array"), 1);
1017    }
1018
1019    #[test]
1020    fn a_set_writes_consecutive_positions_and_counts_the_new_ones() {
1021        let mut d = db();
1022        assert_eq!(set(&mut d, b"a", 10, &[b"p", b"q", b"r"]), 3);
1023        assert_eq!(set(&mut d, b"a", 10, &[b"P", b"Q"]), 0, "already filled");
1024        assert_eq!(set(&mut d, b"a", 12, &[b"R", b"s"]), 1, "one of the two");
1025        assert_eq!(read(&mut d, b"a", 10).as_deref(), Some(&b"P"[..]));
1026        assert_eq!(read(&mut d, b"a", 13).as_deref(), Some(&b"s"[..]));
1027        assert_eq!(d.arcount(b"a").expect("an array"), 4);
1028        assert_eq!(d.arlen(b"a").expect("an array"), 14);
1029    }
1030
1031    /// A write that would run off the top of the index space fails before any
1032    /// of it lands.
1033    #[test]
1034    fn a_write_past_the_end_of_the_space_writes_nothing() {
1035        let mut d = db();
1036        let e = d
1037            .arset(b"a", INDEX_MAX, [b"x".as_ref(), b"y".as_ref()].into_iter())
1038            .unwrap_err();
1039        assert_eq!(e.code(), Code::Invalid);
1040        assert_eq!(e.message(), INDEX_OVERFLOW);
1041        assert_eq!(d.kind_of(b"a"), None, "and the key was never made");
1042
1043        // The last index on its own is fine.
1044        assert_eq!(set(&mut d, b"a", INDEX_MAX, &[b"x"]), 1);
1045        assert_eq!(d.arlen(b"a").expect("an array"), u64::MAX);
1046    }
1047
1048    #[test]
1049    fn scattered_pairs_go_in_one_command() {
1050        let mut d = db();
1051        let pairs = [
1052            (1u64, b"a".as_ref()),
1053            (1000, b"b".as_ref()),
1054            (1, b"c".as_ref()),
1055        ];
1056        assert_eq!(d.armset(b"k", pairs.into_iter()).expect("an array"), 2);
1057        assert_eq!(
1058            read(&mut d, b"k", 1).as_deref(),
1059            Some(&b"c"[..]),
1060            "the later one won"
1061        );
1062        assert_eq!(read(&mut d, b"k", 1000).as_deref(), Some(&b"b"[..]));
1063        assert_eq!(d.arcount(b"k").expect("an array"), 2);
1064    }
1065
1066    #[test]
1067    fn the_key_goes_when_the_last_element_does() {
1068        let mut d = db();
1069        set(&mut d, b"a", 0, &[b"x", b"y"]);
1070        assert_eq!(d.ardel(b"a", [0u64].into_iter()).expect("an array"), 1);
1071        assert_eq!(d.kind_of(b"a"), Some(Kind::Array), "still one left");
1072        assert_eq!(d.ardel(b"a", [1u64, 2].into_iter()).expect("an array"), 1);
1073        assert_eq!(d.kind_of(b"a"), None);
1074        assert_eq!(d.ardel(b"a", [0u64].into_iter()).expect("an array"), 0);
1075    }
1076
1077    #[test]
1078    fn a_range_delete_takes_both_ways_round() {
1079        let mut d = db();
1080        set(&mut d, b"a", 0, &[b"0", b"1", b"2", b"3", b"4"]);
1081        assert_eq!(
1082            d.ardelrange(b"a", [(3u64, 1u64)].into_iter())
1083                .expect("an array"),
1084            3,
1085            "given high to low"
1086        );
1087        assert_eq!(d.arcount(b"a").expect("an array"), 2);
1088        assert_eq!(read(&mut d, b"a", 0).as_deref(), Some(&b"0"[..]));
1089        assert_eq!(read(&mut d, b"a", 4).as_deref(), Some(&b"4"[..]));
1090
1091        assert_eq!(
1092            d.ardelrange(b"a", [(0u64, u64::MAX - 1)].into_iter())
1093                .expect("an array"),
1094            2
1095        );
1096        assert_eq!(d.kind_of(b"a"), None, "and the key went with them");
1097    }
1098
1099    #[test]
1100    fn a_range_read_answers_for_every_position_including_the_holes() {
1101        let mut d = db();
1102        set(&mut d, b"a", 1, &[b"x"]);
1103        let mut got = Vec::new();
1104        let len = d
1105            .argetrange(b"a", 0, 3, |el| {
1106                got.push(el.map(|e| {
1107                    let mut buf = [0u8; ELEMENT_MAX];
1108                    e.text(&mut buf).to_vec()
1109                }));
1110            })
1111            .expect("an array");
1112        assert_eq!(len, 4);
1113        assert_eq!(got, vec![None, Some(b"x".to_vec()), None, None]);
1114
1115        // And backwards, when the ends come in the other order.
1116        let mut back = Vec::new();
1117        d.argetrange(b"a", 3, 0, |el| back.push(el.is_some()))
1118            .expect("an array");
1119        assert_eq!(back, vec![false, false, true, false]);
1120    }
1121
1122    /// A missing key reads like an array of nothing but holes.
1123    #[test]
1124    fn a_range_read_of_a_missing_key_is_all_holes() {
1125        let mut d = db();
1126        let mut n = 0;
1127        let len = d
1128            .argetrange(b"nope", 5, 9, |el| {
1129                assert!(el.is_none());
1130                n += 1;
1131            })
1132            .expect("no key");
1133        assert_eq!(len, 5);
1134        assert_eq!(n, 5);
1135    }
1136
1137    /// The million position limit is an error and not a quiet trim, so that a
1138    /// client asking for too much finds out rather than getting a short answer
1139    /// it thinks is complete.
1140    #[test]
1141    fn a_range_read_over_the_limit_is_refused() {
1142        let mut d = db();
1143        let e = d.argetrange(b"a", 0, GETRANGE_MAX, |_| {}).unwrap_err();
1144        assert_eq!(e.code(), Code::Invalid);
1145        assert_eq!(e.message(), "range exceeds maximum of 1000000 items");
1146        // One under the line is fine, and it is the positions that are counted
1147        // and not the elements, so this walks a million holes.
1148        let mut n = 0u64;
1149        d.argetrange(b"a", 0, GETRANGE_MAX - 1, |_| n += 1)
1150            .expect("no key");
1151        assert_eq!(n, GETRANGE_MAX);
1152    }
1153
1154    #[test]
1155    fn every_command_refuses_a_key_holding_something_else() {
1156        let mut d = db();
1157        d.set_plain(b"s", b"v").expect("a string");
1158        assert_eq!(d.arlen(b"s").unwrap_err().code(), Code::WrongType);
1159        assert_eq!(d.arcount(b"s").unwrap_err().code(), Code::WrongType);
1160        assert_eq!(d.arget(b"s", 0).unwrap_err().code(), Code::WrongType);
1161        assert_eq!(
1162            d.arset(b"s", 0, [b"x".as_ref()].into_iter())
1163                .unwrap_err()
1164                .code(),
1165            Code::WrongType
1166        );
1167        assert_eq!(
1168            d.ardel(b"s", [0u64].into_iter()).unwrap_err().code(),
1169            Code::WrongType
1170        );
1171        assert_eq!(
1172            d.ardelrange(b"s", [(0u64, 1u64)].into_iter())
1173                .unwrap_err()
1174                .code(),
1175            Code::WrongType
1176        );
1177        assert_eq!(
1178            d.argetrange(b"s", 0, 1, |_| {}).unwrap_err().code(),
1179            Code::WrongType
1180        );
1181        let mut grep = Grep::new();
1182        grep.push(Test::Exact, b"v").expect("room for it");
1183        grep.compile(false, false).expect("nothing to compile");
1184        assert_eq!(
1185            d.argrep(b"s", Bound::First, Bound::Last, 1, &mut grep, |_, _| {})
1186                .unwrap_err()
1187                .code(),
1188            Code::WrongType
1189        );
1190    }
1191
1192    /// An index is unsigned, and the numbers a list would take are errors here.
1193    #[test]
1194    fn an_index_is_read_the_way_redis_reads_one() {
1195        for good in [
1196            (&b"0"[..], 0u64),
1197            (b"1", 1),
1198            (b"18446744073709551614", INDEX_MAX),
1199        ] {
1200            assert_eq!(parse_index(good.0).expect("an index"), good.1);
1201        }
1202        for bad in [
1203            &b"-1"[..],
1204            b"+1",
1205            b"01",
1206            b"",
1207            b" 1",
1208            b"1 ",
1209            b"1.0",
1210            b"one",
1211            // The top of the space is reserved for the insert cursor.
1212            b"18446744073709551615",
1213            b"18446744073709551616",
1214            b"99999999999999999999999",
1215        ] {
1216            let e = parse_index(bad).unwrap_err();
1217            assert_eq!(e.code(), Code::Invalid, "{}", String::from_utf8_lossy(bad));
1218            assert_eq!(e.message(), BAD_INDEX);
1219        }
1220    }
1221
1222    fn insert(d: &mut Keyspace, key: &[u8], vals: &[&[u8]]) -> u64 {
1223        d.arinsert(key, vals.iter().copied()).expect("an array")
1224    }
1225
1226    /// What a client would see back from `ARSCAN`.
1227    fn scan(d: &mut Keyspace, key: &[u8], start: u64, end: u64, limit: u64) -> Vec<(u64, Vec<u8>)> {
1228        let mut got = Vec::new();
1229        let n = d
1230            .arscan(key, start, end, limit, |i, el| {
1231                let mut buf = [0u8; ELEMENT_MAX];
1232                got.push((i, el.text(&mut buf).to_vec()));
1233            })
1234            .expect("an array");
1235        assert_eq!(n as usize, got.len(), "the count matches what it emitted");
1236        got
1237    }
1238
1239    /// What a client would see back from `ARLASTITEMS`, holes included.
1240    fn last(d: &mut Keyspace, key: &[u8], count: u64, rev: bool) -> Vec<Option<Vec<u8>>> {
1241        let mut got = Vec::new();
1242        let n = d
1243            .arlastitems(key, count, rev, |el| {
1244                got.push(el.map(|e| {
1245                    let mut buf = [0u8; ELEMENT_MAX];
1246                    e.text(&mut buf).to_vec()
1247                }));
1248            })
1249            .expect("an array");
1250        assert_eq!(n as usize, got.len());
1251        got
1252    }
1253
1254    #[test]
1255    fn an_insert_makes_the_key_and_walks_the_cursor_along() {
1256        let mut d = db();
1257        assert_eq!(d.arnext(b"a").expect("no key"), Some(0), "and nothing made");
1258        assert_eq!(d.kind_of(b"a"), None);
1259
1260        assert_eq!(insert(&mut d, b"a", &[b"x", b"y"]), 1);
1261        assert_eq!(d.kind_of(b"a"), Some(Kind::Array));
1262        assert_eq!(d.arnext(b"a").expect("an array"), Some(2));
1263        assert_eq!(insert(&mut d, b"a", &[b"z"]), 2);
1264        assert_eq!(read(&mut d, b"a", 2).as_deref(), Some(&b"z"[..]));
1265        assert_eq!(d.arcount(b"a").expect("an array"), 3);
1266    }
1267
1268    /// A seek says where the next append goes, and seeking to zero puts the
1269    /// cursor back to where it was before anything was appended.
1270    #[test]
1271    fn a_seek_moves_the_cursor_and_a_missing_key_has_none_to_move() {
1272        let mut d = db();
1273        assert!(!d.arseek(b"a", 10).expect("no key"), "and none was made");
1274        assert_eq!(d.kind_of(b"a"), None);
1275
1276        insert(&mut d, b"a", &[b"x"]);
1277        assert!(d.arseek(b"a", 10).expect("an array"));
1278        assert_eq!(d.arnext(b"a").expect("an array"), Some(10));
1279        assert_eq!(insert(&mut d, b"a", &[b"y"]), 10);
1280        assert!(d.arseek(b"a", 0).expect("an array"));
1281        assert_eq!(d.arnext(b"a").expect("an array"), Some(0));
1282        assert_eq!(insert(&mut d, b"a", &[b"Y"]), 0, "back over the first one");
1283    }
1284
1285    /// The top of the space is a state the cursor can be left in, and once it is
1286    /// there `ARNEXT` has no honest answer and an append has nowhere to go.
1287    #[test]
1288    fn the_cursor_can_be_parked_where_nothing_more_will_fit() {
1289        let mut d = db();
1290        insert(&mut d, b"a", &[b"x"]);
1291        assert!(d.arseek(b"a", u64::MAX).expect("an array"));
1292        assert_eq!(d.arnext(b"a").expect("an array"), None);
1293        let e = d.arinsert(b"a", [b"y".as_ref()].into_iter()).unwrap_err();
1294        assert_eq!(e.code(), Code::Invalid);
1295        assert_eq!(e.message(), "insert index overflow");
1296
1297        // And the top index itself is reachable, one below that.
1298        assert!(d.arseek(b"a", INDEX_MAX).expect("an array"));
1299        assert_eq!(insert(&mut d, b"a", &[b"y"]), INDEX_MAX);
1300        assert_eq!(d.arnext(b"a").expect("an array"), None);
1301    }
1302
1303    /// Only `ARSEEK` takes the reserved top of the index space, and it takes it
1304    /// because a rewritten command has to be able to say it.
1305    #[test]
1306    fn the_reserved_index_is_readable_for_one_command_only() {
1307        assert_eq!(
1308            parse_seek_index(b"18446744073709551615").expect("the top"),
1309            u64::MAX
1310        );
1311        assert_eq!(
1312            parse_index(b"18446744073709551615").unwrap_err().message(),
1313            BAD_INDEX
1314        );
1315        assert_eq!(
1316            parse_seek_index(b"18446744073709551616")
1317                .unwrap_err()
1318                .message(),
1319            BAD_INDEX
1320        );
1321        assert_eq!(parse_seek_index(b"-1").unwrap_err().message(), BAD_INDEX);
1322        assert_eq!(parse_seek_index(b"0").expect("zero"), 0);
1323    }
1324
1325    #[test]
1326    fn a_ring_wraps_and_the_key_holds_no_more_than_its_size() {
1327        let mut d = db();
1328        let vals: Vec<&[u8]> = vec![b"a", b"b", b"c", b"d", b"e"];
1329        assert_eq!(d.arring(b"r", 3, vals.into_iter()).expect("an array"), 1);
1330        assert_eq!(d.arlen(b"r").expect("an array"), 3);
1331        assert_eq!(d.arcount(b"r").expect("an array"), 3);
1332        assert_eq!(read(&mut d, b"r", 0).as_deref(), Some(&b"d"[..]));
1333        assert_eq!(read(&mut d, b"r", 1).as_deref(), Some(&b"e"[..]));
1334        assert_eq!(read(&mut d, b"r", 2).as_deref(), Some(&b"c"[..]));
1335
1336        // The three it holds, oldest first, which is what the ring is for.
1337        assert_eq!(
1338            last(&mut d, b"r", 3, false),
1339            vec![
1340                Some(b"c".to_vec()),
1341                Some(b"d".to_vec()),
1342                Some(b"e".to_vec())
1343            ]
1344        );
1345        assert_eq!(last(&mut d, b"r", 1, true), vec![Some(b"e".to_vec())]);
1346    }
1347
1348    #[test]
1349    fn the_last_items_of_a_missing_key_are_none_at_all() {
1350        let mut d = db();
1351        assert_eq!(last(&mut d, b"nope", 10, false), Vec::new());
1352        set(&mut d, b"a", 0, &[b"x"]);
1353        assert_eq!(last(&mut d, b"a", 0, false), Vec::new());
1354    }
1355
1356    #[test]
1357    fn a_scan_skips_the_holes_and_stops_at_the_limit() {
1358        let mut d = db();
1359        d.armset(
1360            b"a",
1361            [
1362                (0u64, b"x".as_ref()),
1363                (7, b"y".as_ref()),
1364                (1_000_000_000, b"z".as_ref()),
1365            ]
1366            .into_iter(),
1367        )
1368        .expect("an array");
1369
1370        let all = vec![
1371            (0, b"x".to_vec()),
1372            (7, b"y".to_vec()),
1373            (1_000_000_000, b"z".to_vec()),
1374        ];
1375        // The whole index space, which ARGETRANGE would refuse and this one
1376        // answers in three visits.
1377        assert_eq!(scan(&mut d, b"a", 0, INDEX_MAX, u64::MAX), all);
1378        let mut back = all.clone();
1379        back.reverse();
1380        assert_eq!(scan(&mut d, b"a", INDEX_MAX, 0, u64::MAX), back);
1381        assert_eq!(scan(&mut d, b"a", 0, INDEX_MAX, 2), all[..2].to_vec());
1382        assert_eq!(scan(&mut d, b"a", 1, 6, u64::MAX), Vec::new());
1383        assert_eq!(scan(&mut d, b"nope", 0, INDEX_MAX, u64::MAX), Vec::new());
1384    }
1385
1386    #[test]
1387    fn the_cursor_commands_refuse_a_key_holding_something_else() {
1388        let mut d = db();
1389        d.set_plain(b"s", b"v").expect("a string");
1390        assert_eq!(d.arnext(b"s").unwrap_err().code(), Code::WrongType);
1391        assert_eq!(d.arseek(b"s", 1).unwrap_err().code(), Code::WrongType);
1392        assert_eq!(
1393            d.arinsert(b"s", [b"x".as_ref()].into_iter())
1394                .unwrap_err()
1395                .code(),
1396            Code::WrongType
1397        );
1398        assert_eq!(
1399            d.arring(b"s", 4, [b"x".as_ref()].into_iter())
1400                .unwrap_err()
1401                .code(),
1402            Code::WrongType
1403        );
1404        assert_eq!(
1405            d.arlastitems(b"s", 1, false, |_| {}).unwrap_err().code(),
1406            Code::WrongType
1407        );
1408        assert_eq!(
1409            d.arscan(b"s", 0, 1, 1, |_, _| {}).unwrap_err().code(),
1410            Code::WrongType
1411        );
1412    }
1413
1414    fn op(d: &mut Keyspace, key: &[u8], op: Op, want: &[u8]) -> Aggregate {
1415        d.arop(key, 0, INDEX_MAX, op, want).expect("an array")
1416    }
1417
1418    #[test]
1419    fn the_arithmetic_ops_read_what_they_can_and_ignore_the_rest() {
1420        let mut d = db();
1421        set(&mut d, b"a", 0, &[b"1", b"2.5", b"word", b"-4"]);
1422        assert_eq!(op(&mut d, b"a", Op::Sum, b""), Aggregate::Num(-0.5));
1423        assert_eq!(op(&mut d, b"a", Op::Min, b""), Aggregate::Num(-4.0));
1424        assert_eq!(op(&mut d, b"a", Op::Max, b""), Aggregate::Num(2.5));
1425        assert_eq!(op(&mut d, b"a", Op::Used, b""), Aggregate::Int(4));
1426        assert_eq!(op(&mut d, b"a", Op::Match, b"word"), Aggregate::Int(1));
1427        assert_eq!(op(&mut d, b"a", Op::Match, b"1"), Aggregate::Int(1));
1428        assert_eq!(op(&mut d, b"a", Op::Match, b"1.0"), Aggregate::Int(0));
1429
1430        // A range holding nothing numeric is a null and not a zero, because
1431        // zero is an answer and there is no answer.
1432        set(&mut d, b"w", 0, &[b"word", b"other"]);
1433        assert_eq!(op(&mut d, b"w", Op::Sum, b""), Aggregate::None);
1434        assert_eq!(op(&mut d, b"w", Op::Used, b""), Aggregate::Int(2));
1435
1436        // A missing key counts as nothing, which is a number for the two that
1437        // count and a null for the ones that aggregate.
1438        assert_eq!(op(&mut d, b"nope", Op::Used, b""), Aggregate::Int(0));
1439        assert_eq!(op(&mut d, b"nope", Op::Match, b"x"), Aggregate::Int(0));
1440        assert_eq!(op(&mut d, b"nope", Op::Sum, b""), Aggregate::None);
1441        assert_eq!(op(&mut d, b"nope", Op::And, b""), Aggregate::None);
1442    }
1443
1444    /// The bitwise ops take the whole part of a float and skip anything that
1445    /// cannot be one, so a word in the middle of a range does not turn an AND
1446    /// into a zero.
1447    #[test]
1448    fn the_bitwise_ops_truncate_and_skip() {
1449        let mut d = db();
1450        set(&mut d, b"a", 0, &[b"12", b"10.9", b"word"]);
1451        assert_eq!(op(&mut d, b"a", Op::And, b""), Aggregate::Int(8));
1452        assert_eq!(op(&mut d, b"a", Op::Or, b""), Aggregate::Int(14));
1453        assert_eq!(op(&mut d, b"a", Op::Xor, b""), Aggregate::Int(6));
1454
1455        // Negative floats truncate towards zero and not downwards, and one that
1456        // will not fit an integer at all is left out.
1457        set(&mut d, b"b", 0, &[b"-2.7", b"1e30"]);
1458        assert_eq!(op(&mut d, b"b", Op::Xor, b""), Aggregate::Int(-2));
1459        set(&mut d, b"c", 0, &[b"1e30"]);
1460        assert_eq!(op(&mut d, b"c", Op::And, b""), Aggregate::None);
1461    }
1462
1463    /// The range is a range, so an op can be asked about part of an array.
1464    #[test]
1465    fn an_op_only_reads_the_range_it_was_given() {
1466        let mut d = db();
1467        set(&mut d, b"a", 0, &[b"1", b"2", b"3", b"4"]);
1468        assert_eq!(
1469            d.arop(b"a", 1, 2, Op::Sum, b"").expect("an array"),
1470            Aggregate::Num(5.0)
1471        );
1472        // And the ends may come either way round, because none of these care
1473        // which order they see the elements in.
1474        assert_eq!(
1475            d.arop(b"a", 2, 1, Op::Sum, b"").expect("an array"),
1476            Aggregate::Num(5.0)
1477        );
1478        assert_eq!(
1479            d.arop(b"a", 100, 200, Op::Used, b"").expect("an array"),
1480            Aggregate::Int(0)
1481        );
1482    }
1483
1484    /// The four tests and the two ways of combining them.
1485    #[test]
1486    fn a_grep_tests_each_element_and_stops_where_it_is_told() {
1487        let mut d = db();
1488        set(&mut d, b"a", 0, &[b"alpha", b"beta", b"gamma", b"ALPHA"]);
1489
1490        let found = |d: &mut Keyspace, tests: &[(Test, &[u8])], all, nocase, limit| {
1491            let mut grep = Grep::new();
1492            for (test, pattern) in tests {
1493                grep.push(*test, pattern).expect("room for it");
1494            }
1495            grep.compile(all, nocase).expect("a pattern that compiles");
1496            let mut hits = Vec::new();
1497            d.argrep(b"a", Bound::First, Bound::Last, limit, &mut grep, |i, _| {
1498                hits.push(i);
1499            })
1500            .expect("an array");
1501            hits
1502        };
1503
1504        let exact: &[(Test, &[u8])] = &[(Test::Exact, b"alpha")];
1505        assert_eq!(found(&mut d, exact, false, false, u64::MAX), [0]);
1506        assert_eq!(found(&mut d, exact, false, true, u64::MAX), [0, 3]);
1507        let inside: &[(Test, &[u8])] = &[(Test::Match, b"mm")];
1508        assert_eq!(found(&mut d, inside, false, false, u64::MAX), [2]);
1509        let glob: &[(Test, &[u8])] = &[(Test::Glob, b"*a")];
1510        assert_eq!(found(&mut d, glob, false, false, u64::MAX), [0, 1, 2]);
1511        let re: &[(Test, &[u8])] = &[(Test::Re, b"^[bg]")];
1512        assert_eq!(found(&mut d, re, false, false, u64::MAX), [1, 2]);
1513
1514        // OR takes the union and AND the intersection, and the limit counts
1515        // what matched rather than what was looked at.
1516        let two: &[(Test, &[u8])] = &[(Test::Glob, b"*a"), (Test::Exact, b"ALPHA")];
1517        assert_eq!(found(&mut d, two, false, false, u64::MAX), [0, 1, 2, 3]);
1518        assert_eq!(found(&mut d, two, true, false, u64::MAX), []);
1519        assert_eq!(found(&mut d, two, false, false, 2), [0, 1]);
1520    }
1521
1522    /// The patterns that are refused, in Redis's words.
1523    #[test]
1524    fn a_grep_says_why_a_pattern_is_no_good() {
1525        let mut grep = Grep::new();
1526        grep.push(Test::Re, b"").expect("room for it");
1527        assert_eq!(
1528            grep.compile(false, false).unwrap_err().message(),
1529            "regular expression is empty"
1530        );
1531
1532        let mut grep = Grep::new();
1533        grep.push(Test::Re, b"(a").expect("room for it");
1534        assert_eq!(
1535            grep.compile(false, false).unwrap_err().message(),
1536            "invalid regular expression: Missing ')'"
1537        );
1538
1539        // The one that is Redis's own sentence rather than TRE's message, so it
1540        // goes out without anything in front of it.
1541        let mut grep = Grep::new();
1542        grep.push(Test::Re, br"(a)\1").expect("room for it");
1543        assert_eq!(
1544            grep.compile(false, false).unwrap_err().message(),
1545            "regular expression backreferences are not supported"
1546        );
1547
1548        let long = vec![b'a'; GREP_MAX_RE_LEN + 1];
1549        assert_eq!(
1550            Grep::new().push(Test::Re, &long).unwrap_err().message(),
1551            "regular expression is too long, maximum is 2048 bytes"
1552        );
1553        // The same pattern is fine under any of the other three, which do not
1554        // compile anything.
1555        assert!(Grep::new().push(Test::Exact, &long).is_ok());
1556
1557        let mut grep = Grep::new();
1558        for _ in 0..GREP_MAX_PREDICATES {
1559            grep.push(Test::Exact, b"x").expect("room for it");
1560        }
1561        assert_eq!(
1562            grep.push(Test::Exact, b"x").unwrap_err().message(),
1563            "too many predicates, maximum is 250"
1564        );
1565    }
1566
1567    #[test]
1568    fn the_info_describes_the_shape_and_a_missing_key_is_an_error() {
1569        let mut d = db();
1570        assert_eq!(
1571            d.arinfo(b"nope", false).unwrap_err().message(),
1572            "no such key"
1573        );
1574
1575        // Forty consecutive positions is one dense slice, and one element far
1576        // away is a second slice holding a single entry.
1577        set(
1578            &mut d,
1579            b"a",
1580            0,
1581            &(0..40).map(|_| b"v".as_ref()).collect::<Vec<_>>(),
1582        );
1583        set(&mut d, b"a", 100_000, &[b"far"]);
1584        d.arinsert(b"a", [b"x".as_ref()].into_iter()).expect("room");
1585
1586        let info = d.arinfo(b"a", true).expect("an array");
1587        assert_eq!(info.count, 41);
1588        assert_eq!(info.len, 100_001);
1589        assert_eq!(info.next_insert, 1, "the append landed on zero");
1590        assert_eq!(info.slices, 2);
1591        assert_eq!(info.slice_size, 4096);
1592        assert!(info.directory_size >= info.slices);
1593        assert_eq!(info.dense_slices, 1);
1594        assert_eq!(info.sparse_slices, 1);
1595        assert_eq!(info.avg_dense_size, 40.0);
1596        assert_eq!(info.avg_dense_fill, 1.0);
1597        assert!(info.avg_sparse_size >= 1.0);
1598
1599        // Without FULL the per layout numbers are not walked for and read zero.
1600        let cheap = d.arinfo(b"a", false).expect("an array");
1601        assert_eq!(cheap.count, 41);
1602        assert_eq!(cheap.dense_slices, 0);
1603        assert_eq!(cheap.avg_dense_fill, 0.0);
1604    }
1605
1606    /// An array is a body like any other, so the shared key commands work on it.
1607    #[test]
1608    fn it_expires_and_copies_like_every_other_body() {
1609        let mut d = db();
1610        set(&mut d, b"a", 0, &[b"x"]);
1611        assert!(d.set_expiry(b"a", Some(d.clock.now_ms() + 10_000)));
1612        assert_eq!(read(&mut d, b"a", 0).as_deref(), Some(&b"x"[..]));
1613        assert!(d.persist(b"a"));
1614
1615        assert_eq!(d.copy(b"a", b"b", false), crate::Moved::Ok);
1616        assert_eq!(d.kind_of(b"b"), Some(Kind::Array));
1617        set(&mut d, b"b", 1, &[b"y"]);
1618        assert_eq!(
1619            d.arcount(b"a").expect("an array"),
1620            1,
1621            "the source is its own"
1622        );
1623        assert_eq!(d.arcount(b"b").expect("an array"), 2);
1624        assert_eq!(d.encoding_name(b"a"), Some("sliced-array"));
1625    }
1626}