1use 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
33pub const BAD_INDEX: &str = "invalid array index";
39
40pub const INDEX_OVERFLOW: &str = "array index overflow";
42
43pub const GETRANGE_MAX: u64 = 1_000_000;
52
53pub fn parse_index(bytes: &[u8]) -> Result<u64> {
64 parse_ull(bytes, false)
65}
66
67pub 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 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#[derive(Debug, Clone, Copy, PartialEq, Eq)]
111pub enum Op {
112 Sum,
114 Min,
116 Max,
118 And,
120 Or,
122 Xor,
124 Match,
126 Used,
128}
129
130#[derive(Debug, Clone, Copy, PartialEq)]
132pub enum Aggregate {
133 Int(i64),
135 Num(f64),
138 None,
141}
142
143pub const GREP_MAX_PREDICATES: usize = 250;
150
151pub const GREP_MAX_RE_LEN: usize = 2048;
156
157#[derive(Debug, Clone, Copy, PartialEq, Eq)]
164pub enum Bound {
165 Index(u64),
167 First,
169 Last,
171}
172
173impl Bound {
174 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
184pub 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#[derive(Debug, Clone, Copy, PartialEq, Eq)]
199pub enum Test {
200 Exact,
202 Match,
204 Glob,
206 Re,
208}
209
210pub struct Grep<'a> {
225 tests: Vec<(Test, &'a [u8])>,
228 regexes: Vec<Regex>,
231 matcher: Matcher,
233 all: bool,
235 nocase: bool,
237}
238
239impl Default for Grep<'_> {
240 fn default() -> Self {
241 Grep::new()
242 }
243}
244
245impl<'a> Grep<'a> {
246 #[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 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 #[must_use]
287 pub fn len(&self) -> usize {
288 self.tests.len()
289 }
290
291 #[must_use]
293 pub fn is_empty(&self) -> bool {
294 self.tests.is_empty()
295 }
296
297 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 self.matcher.reserve(&re);
322 self.regexes.push(re);
323 }),
324 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 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 if hit != self.all {
360 return hit;
361 }
362 }
363 self.all
364 }
365}
366
367fn fold(b: u8) -> u8 {
373 b.to_ascii_lowercase()
374}
375
376fn 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
387fn 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 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
410fn 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
427fn 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
439fn 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 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 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 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 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 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 None => {
567 for _ in indices {
568 f(None);
569 }
570 }
571 }
572 Ok(())
573 }
574
575 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 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 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 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 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 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 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 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 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 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 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 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 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 hits < limit
882 });
883 Ok(hits)
884 }
885
886 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 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 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 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 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 #[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 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 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 #[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 #[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 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 #[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 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 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 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 #[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 #[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 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 #[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 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 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 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 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 #[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 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 #[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 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 #[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 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 #[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 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 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 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 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 #[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}