1use crate::cond::Compare;
19use crate::counter::{self, Counted, IncrEx, IncrExpire, Num};
20use crate::keyspace::{Keyspace, wrong_type};
21use crate::lcs;
22use crate::value::{self, Encoding, Kind, Str};
23use std::borrow::Cow;
24use yo_common::num::parse_f64;
25use yo_common::{Code, Error, Result};
26use yo_index::RawMap;
27
28const NOT_AN_INT: &str = "value is not an integer or out of range";
30const NOT_A_FLOAT: &str = "value is not a valid float";
32const WOULD_OVERFLOW: &str = "increment or decrement would overflow";
34const TOO_LONG: &str = "string exceeds maximum allowed size (proto-max-bulk-len)";
36const KEY_TOO_LONG: &str = "key exceeds maximum allowed size";
38const BAD_OFFSET: &str = "offset is out of range";
40
41pub const KEY_MAX: usize = 64 * 1024;
48
49pub const STRING_MAX: usize = RawMap::max_record() - RawMap::header_len() - KEY_MAX - 16;
57
58#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
60pub enum Exists {
61 #[default]
63 Always,
64 IfMissing,
66 IfPresent,
68}
69
70#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
72pub enum Expire {
73 #[default]
75 Clear,
76 Keep,
78 At(u64),
80}
81
82#[derive(Debug, Clone, Copy, Default)]
84pub struct SetOptions<'a> {
85 pub exists: Exists,
87 pub expire: Expire,
89 pub compare: Option<Compare<'a>>,
95 pub get: bool,
97}
98
99impl<'a> SetOptions<'a> {
100 pub const PLAIN: SetOptions<'static> = SetOptions {
102 exists: Exists::Always,
103 expire: Expire::Clear,
104 compare: None,
105 get: false,
106 };
107
108 #[must_use]
110 pub const fn if_missing(mut self) -> SetOptions<'a> {
111 self.exists = Exists::IfMissing;
112 self
113 }
114
115 #[must_use]
117 pub const fn if_present(mut self) -> SetOptions<'a> {
118 self.exists = Exists::IfPresent;
119 self
120 }
121
122 #[must_use]
124 pub const fn expiring(mut self, e: Expire) -> SetOptions<'a> {
125 self.expire = e;
126 self
127 }
128
129 #[must_use]
131 pub const fn if_equal(mut self, bytes: &'a [u8]) -> SetOptions<'a> {
132 self.compare = Some(Compare::Equal(bytes));
133 self
134 }
135
136 #[must_use]
138 pub const fn if_not_equal(mut self, bytes: &'a [u8]) -> SetOptions<'a> {
139 self.compare = Some(Compare::NotEqual(bytes));
140 self
141 }
142
143 #[must_use]
145 pub const fn if_digest(mut self, d: u64) -> SetOptions<'a> {
146 self.compare = Some(Compare::DigestEqual(d));
147 self
148 }
149
150 #[must_use]
152 pub const fn if_not_digest(mut self, d: u64) -> SetOptions<'a> {
153 self.compare = Some(Compare::DigestNotEqual(d));
154 self
155 }
156
157 #[must_use]
159 pub const fn returning(mut self) -> SetOptions<'a> {
160 self.get = true;
161 self
162 }
163}
164
165#[derive(Debug, Clone, PartialEq, Eq, Default)]
167pub struct SetOutcome {
168 pub stored: bool,
170 pub previous: Option<Vec<u8>>,
177}
178
179impl Keyspace {
185 pub fn get(&mut self, key: &[u8]) -> Result<Option<Str<'_>>> {
196 let Some(addr) = self.live_rec(key) else {
197 return Ok(None);
198 };
199 let rec = self.map.value_at(addr);
200 if value::kind(rec) != Kind::String {
201 return Err(wrong_type());
202 }
203 if value::cold(rec).is_some() {
207 return self.warmed(key);
208 }
209 Ok(Some(value::read(self.map.value_at(addr))))
210 }
211
212 pub fn mget<'a>(&'a mut self, keys: &[&[u8]]) -> Vec<Option<Str<'a>>> {
218 for k in keys {
219 let _ = self.thaw(k);
228 self.live_rec(k);
236 }
237 let me: &Keyspace = self;
238 keys.iter().map(|k| me.peek(k)).collect()
239 }
240
241 pub fn mget_one(&mut self, key: &[u8]) -> Option<Str<'_>> {
252 let addr = self.live_rec(key)?;
253 let rec = self.map.value_at(addr);
254 if value::kind(rec) != Kind::String {
255 return None;
256 }
257 if value::cold(rec).is_some() {
258 return self.warmed(key).ok().flatten();
262 }
263 Some(value::read(self.map.value_at(addr)))
264 }
265
266 pub fn strlen(&mut self, key: &[u8]) -> Result<usize> {
274 let Some(addr) = self.live_rec(key) else {
275 return Ok(0);
276 };
277 let rec = self.map.value_at(addr);
278 if value::kind(rec) != Kind::String {
279 return Err(wrong_type());
280 }
281 if let Some(c) = value::cold(rec) {
282 return Ok(c.len as usize);
283 }
284 Ok(value::read(rec).len())
285 }
286
287 pub fn exists(&mut self, key: &[u8]) -> bool {
294 self.live_rec_untouched(key).is_some()
295 }
296
297 pub fn encoding(&mut self, key: &[u8]) -> Option<Encoding> {
307 let addr = self.live_rec_untouched(key)?;
308 let rec = self.map.value_at(addr);
309 if value::kind(rec) != Kind::String {
310 return None;
311 }
312 Some(value::Meta::from_byte(rec[0]).encoding())
313 }
314
315 pub fn expire_at(&mut self, key: &[u8]) -> Option<u64> {
320 let addr = self.live_rec_untouched(key)?;
321 value::expire_at(self.map.value_at(addr))
322 }
323
324 pub fn getrange(&mut self, key: &[u8], start: i64, end: i64) -> Result<Cow<'_, [u8]>> {
334 let Some(v) = self.get(key)? else {
340 return Ok(Cow::Borrowed(&[]));
341 };
342 Ok(match v {
343 Str::Bytes(b) => match range_of(b.len(), start, end) {
344 Some((s, e)) => Cow::Borrowed(&b[s..e]),
345 None => Cow::Borrowed(&[]),
346 },
347 Str::Int(n) => {
348 let text = Str::Int(n).to_vec();
349 match range_of(text.len(), start, end) {
350 Some((s, e)) => Cow::Owned(text[s..e].to_vec()),
351 None => Cow::Owned(Vec::new()),
352 }
353 }
354 })
355 }
356
357 pub fn set(&mut self, key: &[u8], val: &[u8], opts: SetOptions<'_>) -> Result<SetOutcome> {
372 let mut previous = None;
373 let mut out = self.set_with(key, val, opts, |v| previous = Some(v.to_vec()))?;
374 out.previous = previous;
375 Ok(out)
376 }
377
378 pub fn set_with<F>(
390 &mut self,
391 key: &[u8],
392 val: &[u8],
393 opts: SetOptions<'_>,
394 previous: F,
395 ) -> Result<SetOutcome>
396 where
397 F: FnOnce(Str<'_>),
398 {
399 check_len(key, val.len())?;
400 self.reap(key);
401 if opts.get || opts.compare.is_some() {
402 self.string_only(key)?;
406 self.thaw(key)?;
410 }
411
412 let present = self.map.get(key);
413 let mut out = SetOutcome::default();
414 if opts.get
415 && let Some(rec) = present
416 {
417 previous(value::read(rec));
418 }
419 let allowed = match opts.exists {
420 Exists::Always => true,
421 Exists::IfMissing => present.is_none(),
422 Exists::IfPresent => present.is_some(),
423 };
424 let matches = match opts.compare {
425 Some(c) => c.holds(present.map(value::read)),
428 None => true,
429 };
430 if !allowed || !matches {
431 return Ok(out);
432 }
433
434 let deadline = match opts.expire {
435 Expire::Clear => None,
436 Expire::At(ms) => Some(ms),
437 Expire::Keep => present.and_then(value::expire_at),
438 };
439 self.store(key, val, deadline);
440 out.stored = true;
441 Ok(out)
442 }
443
444 pub fn set_plain(&mut self, key: &[u8], val: &[u8]) -> Result<()> {
446 check_len(key, val.len())?;
447 self.store(key, val, None);
448 Ok(())
449 }
450
451 pub fn setnx(&mut self, key: &[u8], val: &[u8]) -> Result<bool> {
453 Ok(self.set(key, val, SetOptions::PLAIN.if_missing())?.stored)
454 }
455
456 pub fn setex(&mut self, key: &[u8], seconds: i64, val: &[u8]) -> Result<()> {
461 let ms = seconds
462 .checked_mul(1000)
463 .ok_or_else(|| invalid_expire("setex"))?;
464 self.set_expiring(key, ms, val, "setex")
465 }
466
467 pub fn psetex(&mut self, key: &[u8], millis: i64, val: &[u8]) -> Result<()> {
469 self.set_expiring(key, millis, val, "psetex")
470 }
471
472 fn set_expiring(&mut self, key: &[u8], millis: i64, val: &[u8], what: &str) -> Result<()> {
479 if millis <= 0 {
480 return Err(invalid_expire(what));
481 }
482 let at = self.deadline_in(millis, what)?;
483 self.set(key, val, SetOptions::PLAIN.expiring(Expire::At(at)))?;
484 Ok(())
485 }
486
487 pub fn getset(&mut self, key: &[u8], val: &[u8]) -> Result<Option<Vec<u8>>> {
489 Ok(self.set(key, val, SetOptions::PLAIN.returning())?.previous)
490 }
491
492 pub fn getdel(&mut self, key: &[u8]) -> Result<Option<Vec<u8>>> {
494 let mut had = None;
495 self.getdel_with(key, |v| had = Some(v.to_vec()))?;
496 Ok(had)
497 }
498
499 pub fn getdel_with<F>(&mut self, key: &[u8], f: F) -> Result<bool>
506 where
507 F: FnOnce(Str<'_>),
508 {
509 self.reap(key);
510 self.string_only(key)?;
511 self.warm(key)?;
515 let Some(v) = self.peek(key) else {
516 return Ok(false);
517 };
518 f(v);
519 self.drop_key(key);
520 Ok(true)
521 }
522
523 pub fn getex(&mut self, key: &[u8], expire: Expire) -> Result<Option<Str<'_>>> {
528 self.reap(key);
529 self.string_only(key)?;
530 if expire == Expire::Keep {
536 self.warm(key)?;
537 } else {
538 self.thaw(key)?;
539 }
540 if expire != Expire::Keep {
541 let current = self.map.get(key).and_then(value::expire_at);
542 let wanted = match expire {
543 Expire::At(ms) => Some(ms),
544 _ => None,
545 };
546 if current != wanted && self.map.get(key).is_some() {
547 let rec = self.map.get(key).expect("checked just above");
557 let mut bytes = std::mem::take(&mut self.scratch);
558 bytes.clear();
559 value::read(rec).write_to(&mut bytes);
560 self.store(key, &bytes, wanted);
561 self.scratch = bytes;
562 }
563 }
564 Ok(self.peek(key))
565 }
566
567 pub fn del(&mut self, key: &[u8]) -> bool {
572 self.reap(key);
573 self.drop_key(key)
574 }
575
576 pub fn mset<'k>(
589 &mut self,
590 pairs: impl Iterator<Item = (&'k [u8], &'k [u8])> + Clone,
591 ) -> Result<()> {
592 for (k, v) in pairs.clone() {
593 check_len(k, v.len())?;
594 }
595 for (k, v) in pairs {
596 self.store(k, v, None);
597 }
598 Ok(())
599 }
600
601 pub fn msetnx<'k>(
606 &mut self,
607 pairs: impl Iterator<Item = (&'k [u8], &'k [u8])> + Clone,
608 ) -> Result<bool> {
609 for (k, v) in pairs.clone() {
610 check_len(k, v.len())?;
611 }
612 for (k, _) in pairs.clone() {
613 self.reap(k);
614 if self.map.contains(k) {
615 return Ok(false);
616 }
617 }
618 for (k, v) in pairs {
619 self.store(k, v, None);
620 }
621 Ok(true)
622 }
623
624 pub fn append(&mut self, key: &[u8], tail: &[u8]) -> Result<usize> {
630 self.reap(key);
631 self.string_only(key)?;
632 self.thaw(key)?;
633 let Some(rec) = self.map.get(key) else {
634 check_len(key, tail.len())?;
635 self.store(key, tail, None);
636 return Ok(tail.len());
637 };
638 let deadline = value::expire_at(rec);
639 let mut joined = std::mem::take(&mut self.scratch);
645 joined.clear();
646 value::read(rec).write_to(&mut joined);
647 if let Err(e) = check_len(key, joined.len() + tail.len()) {
648 self.scratch = joined;
649 return Err(e);
650 }
651 joined.extend_from_slice(tail);
652 let len = joined.len();
653 self.store_raw(key, &joined, deadline);
654 self.scratch = joined;
655 Ok(len)
656 }
657
658 pub fn setrange(&mut self, key: &[u8], offset: usize, val: &[u8]) -> Result<usize> {
665 self.reap(key);
666 self.string_only(key)?;
667 if val.is_empty() {
671 return Ok(self.strlen(key).unwrap_or(0));
672 }
673 self.thaw(key)?;
674 let end = offset
675 .checked_add(val.len())
676 .ok_or_else(|| Error::new(Code::Invalid, BAD_OFFSET))?;
677 check_len(key, end)?;
678
679 let mut bytes = std::mem::take(&mut self.scratch);
683 bytes.clear();
684 let deadline = match self.map.get(key) {
685 Some(rec) => {
686 value::read(rec).write_to(&mut bytes);
687 value::expire_at(rec)
688 }
689 None => None,
690 };
691 if bytes.len() < end {
692 bytes.resize(end, 0);
693 }
694 bytes[offset..end].copy_from_slice(val);
695 let len = bytes.len();
696 self.store_raw(key, &bytes, deadline);
697 self.scratch = bytes;
698 Ok(len)
699 }
700
701 #[inline]
705 pub fn incr(&mut self, key: &[u8]) -> Result<i64> {
706 self.incrby(key, 1)
707 }
708
709 #[inline]
711 pub fn decr(&mut self, key: &[u8]) -> Result<i64> {
712 self.decrby(key, 1)
713 }
714
715 pub fn decrby(&mut self, key: &[u8], by: i64) -> Result<i64> {
720 self.count(key, by, true)
721 }
722
723 #[inline]
732 pub fn incrby(&mut self, key: &[u8], by: i64) -> Result<i64> {
733 self.count(key, by, false)
734 }
735
736 fn count(&mut self, key: &[u8], by: i64, subtract: bool) -> Result<i64> {
737 check_len(key, 0)?;
738 self.thaw(key)?;
744 let hash = RawMap::hash_of(key);
745 let now = self.clock.now_ms();
746
747 let mut current: Option<i64> = None;
750 let mut deadline: Option<u64> = None;
751 let mut dead = false;
752 if let Some(rec) = self.map.value_mut_hashed(hash, key) {
753 if value::kind(rec) != Kind::String {
761 return Err(wrong_type());
762 }
763 if value::is_expired(rec, now) {
764 dead = true;
765 } else {
766 deadline = value::expire_at(rec);
767 match value::read_int_in_place(rec) {
768 Some((n, at)) => {
769 let next = step(n, by, subtract)?;
770 value::write_int_in_place(rec, at, next);
771 return Ok(next);
772 }
773 None => {
774 current = Some(
775 value::read(rec)
776 .as_int()
777 .ok_or_else(|| Error::new(Code::Invalid, NOT_AN_INT))?,
778 );
779 }
780 }
781 }
782 }
783
784 if dead {
785 self.drop_key(key);
786 self.expired += 1;
787 deadline = None;
788 }
789 let next = step(current.unwrap_or(0), by, subtract)?;
790 self.store_int(key, next, deadline);
791 Ok(next)
792 }
793
794 pub fn incrbyfloat(&mut self, key: &[u8], by: f64) -> Result<f64> {
800 check_len(key, 0)?;
801 self.reap(key);
807 self.string_only(key)?;
808 self.thaw(key)?;
809 let (current, deadline) = match self.map.get(key) {
810 Some(rec) => {
811 let n = match value::read(rec) {
817 Str::Int(n) => n as f64,
818 Str::Bytes(b) => {
819 parse_f64(b).ok_or_else(|| Error::new(Code::Invalid, NOT_A_FLOAT))?
820 }
821 };
822 (n, value::expire_at(rec))
823 }
824 None => (0.0, None),
825 };
826 let next = current + by;
827 if !next.is_finite() {
828 return Err(Error::new(
829 Code::Invalid,
830 "increment would produce NaN or Infinity",
831 ));
832 }
833 let mut buf = [0u8; yo_common::num::DOUBLE_MAX];
834 let text = yo_common::num::write_double(&mut buf, next);
835 self.store_text(key, text, deadline);
836 Ok(next)
837 }
838
839 pub fn msetex<'k>(
853 &mut self,
854 pairs: impl Iterator<Item = (&'k [u8], &'k [u8])> + Clone,
855 exists: Exists,
856 expire: Expire,
857 ) -> Result<bool> {
858 for (k, v) in pairs.clone() {
859 check_len(k, v.len())?;
860 }
861 for (k, _) in pairs.clone() {
862 self.reap(k);
863 }
864 let allowed = match exists {
865 Exists::Always => true,
866 Exists::IfMissing => pairs.clone().all(|(k, _)| !self.map.contains(k)),
867 Exists::IfPresent => pairs.clone().all(|(k, _)| self.map.contains(k)),
868 };
869 if !allowed {
870 return Ok(false);
871 }
872 for (k, v) in pairs {
873 let deadline = match expire {
874 Expire::Clear => None,
875 Expire::At(ms) => Some(ms),
876 Expire::Keep => self.map.get(k).and_then(value::expire_at),
877 };
878 self.store(k, v, deadline);
879 }
880 Ok(true)
881 }
882
883 pub fn delex(&mut self, key: &[u8], compare: Option<Compare<'_>>) -> bool {
896 self.reap(key);
897 let matches = match compare {
902 Some(c) => {
903 if self.warm(key).is_err() {
904 return false;
905 }
906 c.holds(self.peek(key))
907 }
908 None => true,
909 };
910 matches && self.drop_key(key)
911 }
912
913 pub fn digest(&mut self, key: &[u8]) -> Result<Option<u64>> {
919 self.reap(key);
920 self.string_only(key)?;
921 self.warm(key)?;
925 Ok(self.peek(key).map(|v| v.digest()))
926 }
927
928 pub fn increx(&mut self, key: &[u8], opts: IncrEx) -> Result<Counted> {
946 check_len(key, 0)?;
947 self.reap(key);
948 self.string_only(key)?;
949 self.thaw(key)?;
950
951 let (current, had_deadline) = match self.map.get(key) {
952 Some(rec) => {
953 let v = value::read(rec);
954 let now = if opts.by.is_int() {
955 Num::Int(
956 v.as_int()
957 .ok_or_else(|| Error::new(Code::Invalid, NOT_AN_INT))?,
958 )
959 } else {
960 let text = v.to_vec();
961 Num::Float(
962 parse_f64(&text).ok_or_else(|| Error::new(Code::Invalid, NOT_A_FLOAT))?,
963 )
964 };
965 (now, value::expire_at(rec))
966 }
967 None => (
968 if opts.by.is_int() {
969 Num::Int(0)
970 } else {
971 Num::Float(0.0)
972 },
973 None,
974 ),
975 };
976
977 let out = counter::apply(current, &opts)?;
978 if !out.stored {
979 return Ok(out);
980 }
981
982 let deadline = match opts.expire {
983 IncrExpire::Keep => had_deadline,
984 IncrExpire::Persist => None,
985 IncrExpire::At(ms) => Some(ms),
986 IncrExpire::AtIfNone(ms) => had_deadline.or(Some(ms)),
987 };
988 match out.value {
989 Num::Int(n) => self.store_int(key, n, deadline),
990 Num::Float(f) => {
991 let mut buf = [0u8; yo_common::num::DOUBLE_MAX];
995 let text = yo_common::num::write_double(&mut buf, f);
996 self.store_text(key, text, deadline);
997 }
998 }
999 Ok(out)
1000 }
1001
1002 pub fn lcs(&mut self, a: &[u8], b: &[u8]) -> Result<Vec<u8>> {
1007 let (x, y) = self.both(a, b)?;
1008 lcs::string(&x, &y)
1009 }
1010
1011 pub fn lcs_len(&mut self, a: &[u8], b: &[u8]) -> Result<usize> {
1013 let (x, y) = self.both(a, b)?;
1014 lcs::len(&x, &y)
1015 }
1016
1017 pub fn lcs_idx(&mut self, a: &[u8], b: &[u8], minmatchlen: u32) -> Result<lcs::Idx> {
1023 let (x, y) = self.both(a, b)?;
1024 lcs::idx(&x, &y, minmatchlen)
1025 }
1026
1027 fn both(&mut self, a: &[u8], b: &[u8]) -> Result<(Vec<u8>, Vec<u8>)> {
1035 self.reap(a);
1036 self.reap(b);
1037 self.string_only(a)?;
1038 self.string_only(b)?;
1039 self.warm(a)?;
1044 let x = self.peek(a).map(|v| v.to_vec()).unwrap_or_default();
1045 self.warm(b)?;
1046 let y = self.peek(b).map(|v| v.to_vec()).unwrap_or_default();
1047 Ok((x, y))
1048 }
1049
1050 #[inline]
1071 pub(crate) fn peek(&self, key: &[u8]) -> Option<Str<'_>> {
1072 let rec = self.map.get(key)?;
1073 if value::kind(rec) != Kind::String {
1074 return None;
1075 }
1076 Some(self.value_of(key, rec))
1077 }
1078
1079 #[inline]
1098 pub(crate) fn string_only(&self, key: &[u8]) -> Result<()> {
1099 if self.bodies == 0 {
1100 return Ok(());
1101 }
1102 match self.map.get(key) {
1103 Some(rec) if value::kind(rec) != Kind::String => Err(wrong_type()),
1104 _ => Ok(()),
1105 }
1106 }
1107
1108 pub(crate) fn store(&mut self, key: &[u8], val: &[u8], deadline: Option<u64>) {
1110 let enc = Encoding::of(val);
1111 let len = value::record_len(enc, val.len(), deadline.is_some());
1112 self.free_body(key);
1113 self.write_rec(key, len, |out| {
1114 value::write_record(out, enc, val, deadline);
1115 });
1116 }
1117
1118 fn store_text(&mut self, key: &[u8], val: &[u8], deadline: Option<u64>) {
1126 let enc = if val.len() <= value::EMBSTR_MAX {
1127 Encoding::Embstr
1128 } else {
1129 Encoding::Raw
1130 };
1131 let len = value::record_len(enc, val.len(), deadline.is_some());
1132 self.free_body(key);
1133 self.write_rec(key, len, |out| {
1134 value::write_record(out, enc, val, deadline);
1135 });
1136 }
1137
1138 pub(crate) fn store_raw(&mut self, key: &[u8], val: &[u8], deadline: Option<u64>) {
1145 let len = value::record_len(Encoding::Raw, val.len(), deadline.is_some());
1146 self.free_body(key);
1147 self.write_rec(key, len, |out| {
1148 value::write_record(out, Encoding::Raw, val, deadline);
1149 });
1150 }
1151
1152 fn store_int(&mut self, key: &[u8], n: i64, deadline: Option<u64>) {
1154 let len = value::record_len(Encoding::Int, 0, deadline.is_some());
1155 self.free_body(key);
1156 self.write_rec(key, len, |out| {
1157 value::write_int_record(out, n, deadline);
1158 });
1159 }
1160
1161 fn deadline_in(&self, millis: i64, what: &str) -> Result<u64> {
1163 u64::try_from(millis)
1164 .ok()
1165 .and_then(|ms| self.clock.now_ms().checked_add(ms))
1166 .ok_or_else(|| invalid_expire(what))
1167 }
1168}
1169
1170#[inline]
1172fn step(n: i64, by: i64, subtract: bool) -> Result<i64> {
1173 let r = if subtract {
1174 n.checked_sub(by)
1175 } else {
1176 n.checked_add(by)
1177 };
1178 r.ok_or_else(|| Error::new(Code::Invalid, WOULD_OVERFLOW))
1179}
1180
1181#[inline]
1187pub(crate) fn check_len(key: &[u8], len: usize) -> Result<()> {
1188 if key.len() > KEY_MAX {
1189 return Err(Error::new(Code::Full, KEY_TOO_LONG));
1190 }
1191 if len > STRING_MAX {
1192 return Err(Error::new(Code::Full, TOO_LONG));
1193 }
1194 Ok(())
1195}
1196
1197fn invalid_expire(what: &str) -> Error {
1198 Error::fmt(
1199 Code::Invalid,
1200 format_args!("invalid expire time in '{what}' command"),
1201 )
1202}
1203
1204fn range_of(len: usize, start: i64, end: i64) -> Option<(usize, usize)> {
1209 if len == 0 {
1210 return None;
1211 }
1212 let n = len as i64;
1213 let clamp = |i: i64| -> i64 { if i < 0 { (n + i).max(0) } else { i.min(n) } };
1214 let s = clamp(start);
1215 let e = if end < 0 {
1217 (n + end + 1).max(0)
1218 } else {
1219 (end + 1).min(n)
1220 };
1221 if s >= e {
1222 None
1223 } else {
1224 Some((s as usize, e as usize))
1225 }
1226}
1227
1228#[cfg(test)]
1229mod tests {
1230 use super::*;
1231 use crate::clock::Clock;
1232 use crate::value::EMBSTR_MAX;
1233
1234 fn store() -> Keyspace {
1237 Keyspace::with_clock(Clock::fixed(1_000))
1238 }
1239
1240 fn got(s: &mut Keyspace, key: &[u8]) -> Option<Vec<u8>> {
1241 s.get(key)
1242 .expect("a string in these tests")
1243 .map(|v| v.to_vec())
1244 }
1245
1246 #[test]
1247 fn set_and_get_round_trip() {
1248 let mut s = store();
1249 assert_eq!(got(&mut s, b"k"), None);
1250 s.set_plain(b"k", b"hello").unwrap();
1251 assert_eq!(got(&mut s, b"k").as_deref(), Some(&b"hello"[..]));
1252 assert_eq!(s.strlen(b"k").expect("a string"), 5);
1253 assert_eq!(s.len(), 1);
1254 s.set_plain(b"k", b"bye").unwrap();
1255 assert_eq!(got(&mut s, b"k").as_deref(), Some(&b"bye"[..]));
1256 assert_eq!(s.len(), 1, "overwriting made a second key");
1257 }
1258
1259 #[test]
1260 fn a_value_comes_back_exactly_as_it_went_in() {
1261 let mut s = store();
1262 for text in [&b""[..], b"0", b"007", b"-0", b"+1", b"9223372036854775808"] {
1263 s.set_plain(b"k", text).unwrap();
1264 assert_eq!(got(&mut s, b"k").as_deref(), Some(text), "{text:?}");
1265 }
1266 }
1267
1268 #[test]
1269 fn object_encoding_matches_redis() {
1270 let mut s = store();
1271 s.set_plain(b"n", b"42").unwrap();
1272 assert_eq!(s.encoding(b"n"), Some(Encoding::Int));
1273 s.set_plain(b"z", b"007").unwrap();
1274 assert_eq!(s.encoding(b"z"), Some(Encoding::Embstr));
1275 s.set_plain(b"e", &[b'x'; EMBSTR_MAX]).unwrap();
1276 assert_eq!(s.encoding(b"e"), Some(Encoding::Embstr));
1277 s.set_plain(b"r", &[b'x'; EMBSTR_MAX + 1]).unwrap();
1278 assert_eq!(s.encoding(b"r"), Some(Encoding::Raw));
1279 assert_eq!(s.encoding(b"missing"), None);
1280 s.set_plain(b"a", b"1").unwrap();
1282 s.append(b"a", b"2").unwrap();
1283 assert_eq!(s.encoding(b"a"), Some(Encoding::Raw));
1284 }
1285
1286 #[test]
1287 fn nx_and_xx_decide_against_what_is_there() {
1288 let mut s = store();
1289 assert!(
1290 !s.set(b"k", b"v", SetOptions::PLAIN.if_present())
1291 .unwrap()
1292 .stored
1293 );
1294 assert_eq!(got(&mut s, b"k"), None);
1295 assert!(
1296 s.set(b"k", b"v", SetOptions::PLAIN.if_missing())
1297 .unwrap()
1298 .stored
1299 );
1300 assert!(
1301 !s.set(b"k", b"w", SetOptions::PLAIN.if_missing())
1302 .unwrap()
1303 .stored
1304 );
1305 assert_eq!(got(&mut s, b"k").as_deref(), Some(&b"v"[..]));
1306 assert!(
1307 s.set(b"k", b"w", SetOptions::PLAIN.if_present())
1308 .unwrap()
1309 .stored
1310 );
1311 assert_eq!(got(&mut s, b"k").as_deref(), Some(&b"w"[..]));
1312 assert!(s.setnx(b"fresh", b"1").unwrap());
1313 assert!(!s.setnx(b"fresh", b"2").unwrap());
1314 }
1315
1316 #[test]
1317 fn ifeq_compares_against_the_string_the_client_would_have_read() {
1318 let mut s = store();
1319 assert!(
1321 !s.set(b"k", b"v", SetOptions::PLAIN.if_equal(b""))
1322 .unwrap()
1323 .stored
1324 );
1325 s.set_plain(b"k", b"42").unwrap();
1326 assert!(
1327 !s.set(b"k", b"v", SetOptions::PLAIN.if_equal(b"43"))
1328 .unwrap()
1329 .stored
1330 );
1331 assert!(
1334 !s.set(b"k", b"v", SetOptions::PLAIN.if_equal(b"042"))
1335 .unwrap()
1336 .stored
1337 );
1338 assert!(
1339 s.set(b"k", b"v", SetOptions::PLAIN.if_equal(b"42"))
1340 .unwrap()
1341 .stored
1342 );
1343 assert_eq!(got(&mut s, b"k").as_deref(), Some(&b"v"[..]));
1344 }
1345
1346 #[test]
1347 fn get_reports_the_old_value_whether_or_not_the_write_happened() {
1348 let mut s = store();
1349 assert_eq!(
1350 s.set(b"k", b"a", SetOptions::PLAIN.returning())
1351 .unwrap()
1352 .previous,
1353 None
1354 );
1355 let out = s.set(b"k", b"b", SetOptions::PLAIN.returning()).unwrap();
1356 assert!(out.stored);
1357 assert_eq!(out.previous.as_deref(), Some(&b"a"[..]));
1358 let out = s
1360 .set(b"k", b"c", SetOptions::PLAIN.if_missing().returning())
1361 .unwrap();
1362 assert!(!out.stored);
1363 assert_eq!(out.previous.as_deref(), Some(&b"b"[..]));
1364 assert_eq!(s.getset(b"k", b"d").unwrap().as_deref(), Some(&b"b"[..]));
1365 }
1366
1367 #[test]
1368 fn a_key_is_gone_the_millisecond_its_deadline_arrives() {
1369 let mut s = store();
1370 s.set(b"k", b"v", SetOptions::PLAIN.expiring(Expire::At(1_500)))
1371 .unwrap();
1372 assert_eq!(s.expire_at(b"k"), Some(1_500));
1373 s.clock_mut().set(1_499);
1374 assert_eq!(got(&mut s, b"k").as_deref(), Some(&b"v"[..]));
1375 s.clock_mut().set(1_500);
1376 assert_eq!(got(&mut s, b"k"), None);
1377 assert_eq!(s.len(), 0, "the dead key was not reclaimed");
1378 assert_eq!(s.expired_keys(), 1);
1379 }
1380
1381 #[test]
1382 fn keepttl_keeps_the_deadline_and_a_plain_set_clears_it() {
1383 let mut s = store();
1384 s.set(b"k", b"v", SetOptions::PLAIN.expiring(Expire::At(9_000)))
1385 .unwrap();
1386 s.set(b"k", b"w", SetOptions::PLAIN.expiring(Expire::Keep))
1387 .unwrap();
1388 assert_eq!(s.expire_at(b"k"), Some(9_000));
1389 s.set_plain(b"k", b"x").unwrap();
1390 assert_eq!(s.expire_at(b"k"), None);
1391 }
1392
1393 #[test]
1394 fn setex_refuses_a_time_to_live_that_is_not_one() {
1395 let mut s = store();
1396 assert_eq!(
1400 s.setex(b"k", 0, b"v").unwrap_err().message(),
1401 "invalid expire time in 'setex' command"
1402 );
1403 assert_eq!(
1404 s.psetex(b"k", 0, b"v").unwrap_err().message(),
1405 "invalid expire time in 'psetex' command"
1406 );
1407 assert!(s.setex(b"k", -1, b"v").is_err());
1408 assert_eq!(got(&mut s, b"k"), None);
1409 s.setex(b"k", 10, b"v").unwrap();
1410 assert_eq!(s.expire_at(b"k"), Some(11_000));
1411 s.psetex(b"p", 250, b"v").unwrap();
1412 assert_eq!(s.expire_at(b"p"), Some(1_250));
1413 }
1414
1415 #[test]
1416 fn getex_reads_and_retimes_in_one_go() {
1417 let mut s = store();
1418 s.set(b"k", b"v", SetOptions::PLAIN.expiring(Expire::At(5_000)))
1419 .unwrap();
1420 assert_eq!(
1422 s.getex(b"k", Expire::Keep)
1423 .expect("a string")
1424 .map(|v| v.to_vec())
1425 .as_deref(),
1426 Some(&b"v"[..])
1427 );
1428 assert_eq!(s.expire_at(b"k"), Some(5_000));
1429 assert!(s.getex(b"k", Expire::Clear).expect("a string").is_some());
1431 assert_eq!(s.expire_at(b"k"), None);
1432 assert!(
1434 s.getex(b"k", Expire::At(7_000))
1435 .expect("a string")
1436 .is_some()
1437 );
1438 assert_eq!(s.expire_at(b"k"), Some(7_000));
1439 assert_eq!(got(&mut s, b"k").as_deref(), Some(&b"v"[..]));
1440 assert!(
1441 s.getex(b"missing", Expire::At(7_000))
1442 .expect("a string")
1443 .is_none()
1444 );
1445 }
1446
1447 #[test]
1448 fn getdel_hands_the_value_over_and_keeps_nothing() {
1449 let mut s = store();
1450 s.set_plain(b"k", b"v").unwrap();
1451 assert_eq!(
1452 s.getdel(b"k").expect("a string").as_deref(),
1453 Some(&b"v"[..])
1454 );
1455 assert_eq!(s.getdel(b"k").expect("a string"), None);
1456 assert_eq!(s.len(), 0);
1457 s.set_plain(b"k", b"v").unwrap();
1458 assert!(s.del(b"k"));
1459 assert!(!s.del(b"k"));
1460 }
1461
1462 #[test]
1463 fn mset_writes_every_pair_and_msetnx_writes_none_of_them() {
1464 let mut s = store();
1465 s.mset([(&b"a"[..], &b"1"[..]), (&b"b"[..], &b"2"[..])].into_iter())
1466 .unwrap();
1467 let vals = s.mget(&[&b"a"[..], &b"b"[..], &b"missing"[..]]);
1468 let vals: Vec<_> = vals.iter().map(|v| v.map(|v| v.to_vec())).collect();
1469 assert_eq!(vals[0].as_deref(), Some(&b"1"[..]));
1470 assert_eq!(vals[1].as_deref(), Some(&b"2"[..]));
1471 assert_eq!(vals[2], None);
1472
1473 assert!(
1474 !s.msetnx([(&b"b"[..], &b"9"[..]), (&b"c"[..], &b"3"[..])].into_iter())
1475 .unwrap()
1476 );
1477 assert_eq!(got(&mut s, b"c"), None, "msetnx wrote part of the set");
1478 assert_eq!(got(&mut s, b"b").as_deref(), Some(&b"2"[..]));
1479 assert!(
1480 s.msetnx([(&b"c"[..], &b"3"[..]), (&b"d"[..], &b"4"[..])].into_iter())
1481 .unwrap()
1482 );
1483 assert_eq!(got(&mut s, b"d").as_deref(), Some(&b"4"[..]));
1484 }
1485
1486 #[test]
1487 fn mget_reaps_before_it_reads() {
1488 let mut s = store();
1489 s.set(b"a", b"1", SetOptions::PLAIN.expiring(Expire::At(1_100)))
1490 .unwrap();
1491 s.set_plain(b"b", b"2").unwrap();
1492 s.clock_mut().set(1_100);
1493 let vals = s.mget(&[&b"a"[..], &b"b"[..]]);
1494 assert!(vals[0].is_none(), "a dead key came back from mget");
1495 assert!(vals[1].is_some());
1496 assert_eq!(s.len(), 1);
1497 }
1498
1499 #[test]
1500 fn append_creates_extends_and_keeps_the_deadline() {
1501 let mut s = store();
1502 assert_eq!(s.append(b"k", b"one").unwrap(), 3);
1503 assert_eq!(s.append(b"k", b" two").unwrap(), 7);
1504 assert_eq!(got(&mut s, b"k").as_deref(), Some(&b"one two"[..]));
1505 s.set(b"t", b"a", SetOptions::PLAIN.expiring(Expire::At(4_000)))
1506 .unwrap();
1507 s.append(b"t", b"b").unwrap();
1508 assert_eq!(s.expire_at(b"t"), Some(4_000));
1509 assert_eq!(got(&mut s, b"t").as_deref(), Some(&b"ab"[..]));
1510 }
1511
1512 #[test]
1518 fn append_reuses_its_buffer_instead_of_allocating_per_call() {
1519 let mut s = store();
1520 s.append(b"k", b"start").expect("room");
1521 let (_, allocs) = crate::tally::counted(|| {
1522 for _ in 0..100 {
1523 s.append(b"k", b"0123456789").expect("room");
1524 }
1525 });
1526 assert!(
1527 allocs < 20,
1528 "append allocated {allocs} times in a hundred, so it is still copying into a new Vec"
1529 );
1530 assert_eq!(got(&mut s, b"k").map(|v| v.len()), Some(1005));
1531 }
1532
1533 #[test]
1537 fn setrange_stops_allocating_once_its_buffer_is_grown() {
1538 let mut s = store();
1539 s.set_plain(b"k", b"Hello World").expect("room");
1540 s.setrange(b"k", 6, b"Redis").expect("room");
1541 let (_, allocs) = crate::tally::counted(|| {
1542 for _ in 0..100 {
1543 s.setrange(b"k", 6, b"Redis").expect("room");
1544 }
1545 });
1546 assert_eq!(allocs, 0, "setrange allocated {allocs} times in a hundred");
1547 assert_eq!(got(&mut s, b"k").as_deref(), Some(&b"Hello Redis"[..]));
1548 }
1549
1550 #[test]
1554 fn expiry_on_a_string_stops_allocating_once_its_buffer_is_grown() {
1555 let mut s = store();
1556 s.set_plain(b"k", b"a value of some length").expect("room");
1557 const FUTURE: u64 = 4_000_000_000_000;
1560 s.set_expiry(b"k", Some(FUTURE));
1561 let (_, allocs) = crate::tally::counted(|| {
1562 for i in 0..100 {
1563 s.set_expiry(b"k", Some(FUTURE + i));
1566 }
1567 });
1568 assert_eq!(
1569 allocs, 0,
1570 "set_expiry allocated {allocs} times in a hundred"
1571 );
1572 assert_eq!(
1573 got(&mut s, b"k").as_deref(),
1574 Some(&b"a value of some length"[..])
1575 );
1576 }
1577
1578 #[test]
1579 fn setrange_pads_with_zero_bytes() {
1580 let mut s = store();
1581 assert_eq!(s.setrange(b"k", 0, b"").unwrap(), 0);
1582 assert_eq!(got(&mut s, b"k"), None, "an empty write created a key");
1583 assert_eq!(s.setrange(b"k", 3, b"xy").unwrap(), 5);
1584 assert_eq!(got(&mut s, b"k").as_deref(), Some(&b"\0\0\0xy"[..]));
1585 s.set_plain(b"h", b"Hello World").unwrap();
1586 assert_eq!(s.setrange(b"h", 6, b"Redis").unwrap(), 11);
1587 assert_eq!(got(&mut s, b"h").as_deref(), Some(&b"Hello Redis"[..]));
1588 }
1589
1590 #[test]
1591 fn getrange_counts_from_both_ends_and_clamps() {
1592 let mut s = store();
1593 s.set_plain(b"k", b"This is a string").unwrap();
1594 assert_eq!(&*s.getrange(b"k", 0, 3).expect("a string"), b"This");
1595 assert_eq!(&*s.getrange(b"k", -3, -1).expect("a string"), b"ing");
1596 assert_eq!(
1597 &*s.getrange(b"k", 0, -1).expect("a string"),
1598 b"This is a string"
1599 );
1600 assert_eq!(&*s.getrange(b"k", 10, 100).expect("a string"), b"string");
1601 assert_eq!(&*s.getrange(b"k", 100, 200).expect("a string"), b"");
1603 assert_eq!(&*s.getrange(b"k", 5, 2).expect("a string"), b"");
1604 assert_eq!(&*s.getrange(b"missing", 0, -1).expect("a string"), b"");
1605 s.set_plain(b"n", b"12345").unwrap();
1607 assert_eq!(&*s.getrange(b"n", 1, 3).expect("a string"), b"234");
1608 assert_eq!(&*s.getrange(b"n", 9, 9).expect("a string"), b"");
1609 }
1610
1611 #[test]
1612 fn incr_counts_and_refuses_what_is_not_a_number() {
1613 let mut s = store();
1614 assert_eq!(s.incr(b"k").unwrap(), 1);
1615 assert_eq!(s.incr(b"k").unwrap(), 2);
1616 assert_eq!(s.incrby(b"k", 40).unwrap(), 42);
1617 assert_eq!(s.decr(b"k").unwrap(), 41);
1618 assert_eq!(s.decrby(b"k", 41).unwrap(), 0);
1619 assert_eq!(got(&mut s, b"k").as_deref(), Some(&b"0"[..]));
1620 assert_eq!(s.encoding(b"k"), Some(Encoding::Int));
1621
1622 s.set_plain(b"t", b"hello").unwrap();
1623 let e = s.incr(b"t").unwrap_err();
1624 assert_eq!(e.code(), Code::Invalid);
1625 assert_eq!(e.message(), NOT_AN_INT);
1626 assert_eq!(got(&mut s, b"t").as_deref(), Some(&b"hello"[..]));
1628 }
1629
1630 #[test]
1631 fn incr_works_on_a_number_that_is_stored_as_text() {
1632 let mut s = store();
1633 s.append(b"k", b"1").unwrap();
1637 assert_eq!(s.encoding(b"k"), Some(Encoding::Int));
1638 s.append(b"k", b"0").unwrap();
1639 assert_eq!(s.encoding(b"k"), Some(Encoding::Raw));
1640 assert_eq!(s.incr(b"k").unwrap(), 11);
1641 assert_eq!(
1642 s.encoding(b"k"),
1643 Some(Encoding::Int),
1644 "INCR did not re-encode"
1645 );
1646 s.set_plain(b"z", b"007").unwrap();
1648 assert!(s.incr(b"z").is_err());
1649 }
1650
1651 #[test]
1652 fn a_counter_refuses_to_wrap() {
1653 let mut s = store();
1654 s.set_plain(b"k", b"9223372036854775807").unwrap();
1655 let e = s.incr(b"k").unwrap_err();
1656 assert_eq!(e.code(), Code::Invalid);
1657 assert_eq!(e.message(), WOULD_OVERFLOW);
1658 assert_eq!(
1659 got(&mut s, b"k").as_deref(),
1660 Some(&b"9223372036854775807"[..])
1661 );
1662 s.set_plain(b"m", b"-9223372036854775808").unwrap();
1663 assert!(s.decr(b"m").is_err());
1664 s.set_plain(b"d", b"0").unwrap();
1666 assert!(s.decrby(b"d", i64::MIN).is_err());
1667 }
1668
1669 #[test]
1670 fn incr_keeps_the_deadline_and_reaps_a_dead_key_first() {
1671 let mut s = store();
1672 s.set(b"k", b"5", SetOptions::PLAIN.expiring(Expire::At(2_000)))
1673 .unwrap();
1674 assert_eq!(s.incr(b"k").unwrap(), 6);
1675 assert_eq!(s.expire_at(b"k"), Some(2_000), "the deadline was dropped");
1676 s.clock_mut().set(2_000);
1679 assert_eq!(s.incr(b"k").unwrap(), 1);
1680 assert_eq!(s.expire_at(b"k"), None);
1681 assert_eq!(s.expired_keys(), 1);
1682 }
1683
1684 #[test]
1687 fn incr_on_an_int_does_not_allocate() {
1688 let mut s = store();
1689 s.set_plain(b"k", b"1").unwrap();
1690 let before = s.map().arena().live_bytes();
1691 for want in 2..1_000 {
1692 assert_eq!(s.incr(b"k").unwrap(), want);
1693 }
1694 assert_eq!(
1695 s.map().arena().live_bytes(),
1696 before,
1697 "INCR moved the record"
1698 );
1699 assert_eq!(got(&mut s, b"k").as_deref(), Some(&b"999"[..]));
1700 }
1701
1702 #[test]
1703 fn incrbyfloat_formats_the_way_redis_does() {
1704 let mut s = store();
1705 assert_eq!(s.incrbyfloat(b"k", 10.5).unwrap(), 10.5);
1706 assert_eq!(got(&mut s, b"k").as_deref(), Some(&b"10.5"[..]));
1707 assert_eq!(s.incrbyfloat(b"k", 0.1).unwrap(), 10.6);
1708 s.set_plain(b"n", b"5").unwrap();
1710 assert_eq!(s.incrbyfloat(b"n", 1.0).unwrap(), 6.0);
1711 assert_eq!(got(&mut s, b"n").as_deref(), Some(&b"6"[..]));
1712 assert_eq!(s.encoding(b"n"), Some(Encoding::Embstr));
1713
1714 s.set_plain(b"t", b"hello").unwrap();
1715 let e = s.incrbyfloat(b"t", 1.0).unwrap_err();
1716 assert_eq!(e.message(), NOT_A_FLOAT);
1717 assert_eq!(
1721 s.incrbyfloat(b"k", f64::INFINITY).unwrap_err().message(),
1722 "increment would produce NaN or Infinity"
1723 );
1724 assert_eq!(
1725 s.incrbyfloat(b"k", f64::NAN).unwrap_err().message(),
1726 "increment would produce NaN or Infinity"
1727 );
1728 assert_eq!(got(&mut s, b"k").as_deref(), Some(&b"10.6"[..]));
1730 }
1731
1732 #[test]
1737 fn incrbyfloat_reads_an_int_encoded_value_the_same_as_its_digits() {
1738 for n in [0i64, 6, -6, 1 << 40, -(1 << 40), i64::MAX, i64::MIN] {
1739 let mut s = store();
1740 s.set_plain(b"i", n.to_string().as_bytes()).unwrap();
1741 s.set_plain(b"t", n.to_string().as_bytes()).unwrap();
1745 s.append(b"t", b"").unwrap();
1746 assert_eq!(s.encoding(b"i"), Some(Encoding::Int));
1747 assert_ne!(s.encoding(b"t"), Some(Encoding::Int));
1748 assert_eq!(
1749 s.incrbyfloat(b"i", 0.5).unwrap(),
1750 s.incrbyfloat(b"t", 0.5).unwrap(),
1751 "the two encodings of {n} do not increment alike"
1752 );
1753 }
1754 }
1755
1756 #[test]
1759 fn incrbyfloat_does_not_allocate() {
1760 let mut s = store();
1761 for _ in 0..4 {
1762 s.incrbyfloat(b"f", 1.5).unwrap();
1763 }
1764 let (_, allocs) = crate::tally::counted(|| {
1765 for _ in 0..50 {
1766 s.incrbyfloat(b"f", 1.5).unwrap();
1767 }
1768 });
1769 assert_eq!(allocs, 0, "incrbyfloat allocated {allocs} times in fifty");
1770 }
1771
1772 #[test]
1775 fn set_with_does_not_allocate_to_report_the_old_value() {
1776 let mut s = store();
1777 let opts = SetOptions::PLAIN.returning();
1778 let mut seen = Vec::with_capacity(64);
1779 for _ in 0..4 {
1780 s.set_with(b"k", b"a-value", opts, |v| v.write_to(&mut seen))
1781 .unwrap();
1782 }
1783 let (_, allocs) = crate::tally::counted(|| {
1784 for _ in 0..50 {
1785 seen.clear();
1786 s.set_with(b"k", b"a-value", opts, |v| v.write_to(&mut seen))
1787 .unwrap();
1788 }
1789 });
1790 assert_eq!(allocs, 0, "set with GET allocated {allocs} times in fifty");
1791 assert_eq!(seen, b"a-value");
1792 let done = s.set(b"k", b"next", opts).unwrap();
1794 assert_eq!(done.previous.as_deref(), Some(&b"a-value"[..]));
1795 assert!(done.stored);
1796 }
1797
1798 #[test]
1799 fn a_value_that_is_too_long_is_an_error_and_not_a_panic() {
1800 let mut s = store();
1801 let huge = vec![b'x'; STRING_MAX + 1];
1802 let e = s.set_plain(b"k", &huge).unwrap_err();
1803 assert_eq!(e.code(), Code::Full);
1804 assert_eq!(e.message(), TOO_LONG);
1805 assert!(s.append(b"k", &huge).is_err());
1806 assert!(s.setrange(b"k", STRING_MAX, b"x").is_err());
1807 let long_key = vec![b'k'; KEY_MAX + 1];
1808 assert_eq!(s.set_plain(&long_key, b"v").unwrap_err().code(), Code::Full);
1809 assert_eq!(s.len(), 0);
1810 }
1811
1812 #[test]
1813 fn exists_and_strlen_agree_with_get() {
1814 let mut s = store();
1815 assert!(!s.exists(b"k"));
1816 assert_eq!(s.strlen(b"k").expect("a string"), 0);
1817 s.set(
1818 b"k",
1819 b"12345",
1820 SetOptions::PLAIN.expiring(Expire::At(2_000)),
1821 )
1822 .unwrap();
1823 assert!(s.exists(b"k"));
1824 assert_eq!(s.strlen(b"k").expect("a string"), 5);
1825 s.clock_mut().set(2_000);
1826 assert!(!s.exists(b"k"));
1827 assert_eq!(s.strlen(b"k").expect("a string"), 0);
1828 }
1829
1830 #[test]
1831 fn msetex_writes_all_of_them_or_none() {
1832 let mut s = store();
1833 let pairs = [(&b"a"[..], &b"1"[..]), (&b"b"[..], &b"2"[..])];
1834 assert!(
1835 s.msetex(pairs.iter().copied(), Exists::Always, Expire::At(3_000))
1836 .unwrap()
1837 );
1838 assert_eq!(s.expire_at(b"a"), Some(3_000));
1839 assert_eq!(s.expire_at(b"b"), Some(3_000));
1840
1841 assert!(
1845 !s.msetex(pairs.iter().copied(), Exists::IfMissing, Expire::Clear)
1846 .unwrap()
1847 );
1848 assert_eq!(s.expire_at(b"a"), Some(3_000), "a failed NX still wrote");
1849 s.del(b"b");
1850 assert!(
1851 !s.msetex(pairs.iter().copied(), Exists::IfPresent, Expire::Clear)
1852 .unwrap()
1853 );
1854 assert!(!s.exists(b"b"), "a failed XX still wrote");
1855 assert!(
1856 s.msetex(pairs.iter().copied(), Exists::IfMissing, Expire::Clear)
1857 .is_ok()
1858 );
1859
1860 s.set(b"a", b"1", SetOptions::PLAIN.expiring(Expire::At(9_000)))
1863 .unwrap();
1864 assert!(
1865 s.msetex(pairs.iter().copied(), Exists::Always, Expire::Keep)
1866 .unwrap()
1867 );
1868 assert_eq!(s.expire_at(b"a"), Some(9_000));
1869 assert_eq!(s.expire_at(b"b"), None);
1870 assert!(
1872 s.msetex(pairs.iter().copied(), Exists::Always, Expire::Clear)
1873 .unwrap()
1874 );
1875 assert_eq!(s.expire_at(b"a"), None);
1876 }
1877
1878 #[test]
1879 fn msetex_lets_the_last_of_a_duplicated_key_win() {
1880 let mut s = store();
1881 let pairs = [(&b"k"[..], &b"1"[..]), (&b"k"[..], &b"2"[..])];
1882 assert!(
1883 s.msetex(pairs.iter().copied(), Exists::Always, Expire::Clear)
1884 .unwrap()
1885 );
1886 assert_eq!(got(&mut s, b"k").as_deref(), Some(&b"2"[..]));
1887 }
1888
1889 #[test]
1890 fn delex_deletes_only_what_it_was_told_to() {
1891 let mut s = store();
1892 s.set_plain(b"k", b"v").unwrap();
1893 assert!(!s.delex(b"k", Some(Compare::Equal(b"other"))));
1894 assert!(s.exists(b"k"), "a failed compare deleted the key");
1895 assert!(s.delex(b"k", Some(Compare::Equal(b"v"))));
1896 assert!(!s.exists(b"k"));
1897 assert!(!s.delex(b"k", Some(Compare::Equal(b"v"))));
1900 assert!(!s.delex(b"k", Some(Compare::NotEqual(b"v"))));
1901 assert!(!s.delex(b"k", None));
1902 s.set_plain(b"k", b"v").unwrap();
1903 assert!(s.delex(b"k", None));
1904 s.set_plain(b"n", b"42").unwrap();
1906 assert!(!s.delex(b"n", Some(Compare::Equal(b"042"))));
1907 assert!(s.delex(b"n", Some(Compare::Equal(b"42"))));
1908 }
1909
1910 #[test]
1911 fn the_four_conditions_agree_with_a_real_server() {
1912 let mut s = store();
1913 assert!(
1916 s.set(b"m", b"v", SetOptions::PLAIN.if_not_equal(b"other"))
1917 .unwrap()
1918 .stored
1919 );
1920 let d = s.digest(b"m").expect("a string").expect("just written");
1922 assert_eq!(d, yo_common::xxh3::hash64(b"v"));
1923 assert!(
1924 !s.set(b"m", b"x", SetOptions::PLAIN.if_not_digest(d))
1925 .unwrap()
1926 .stored
1927 );
1928 assert!(
1929 s.set(b"m", b"x", SetOptions::PLAIN.if_digest(d))
1930 .unwrap()
1931 .stored
1932 );
1933 assert_eq!(got(&mut s, b"m").as_deref(), Some(&b"x"[..]));
1934 assert_eq!(s.digest(b"gone").expect("a string"), None);
1935 let d = s.digest(b"m").expect("a string").expect("still there");
1936 assert!(s.delex(b"m", Some(Compare::DigestEqual(d))));
1937 }
1938
1939 #[test]
1940 fn increx_counts_and_leaves_the_deadline_alone() {
1941 let mut s = store();
1942 let c = s.increx(b"k", IncrEx::PLAIN).unwrap();
1943 assert_eq!(
1944 (c.value, c.applied, c.stored),
1945 (Num::Int(1), Num::Int(1), true)
1946 );
1947 assert_eq!(s.expire_at(b"k"), None, "a plain INCREX set a deadline");
1948 assert_eq!(s.encoding(b"k"), Some(Encoding::Int));
1949
1950 s.increx(b"k", IncrEx::PLAIN.expiring(IncrExpire::At(2_000)))
1952 .unwrap();
1953 assert_eq!(s.expire_at(b"k"), Some(2_000));
1954 s.increx(b"k", IncrEx::PLAIN).unwrap();
1955 assert_eq!(s.expire_at(b"k"), Some(2_000));
1956 s.increx(b"k", IncrEx::PLAIN.expiring(IncrExpire::Persist))
1958 .unwrap();
1959 assert_eq!(s.expire_at(b"k"), None);
1960 }
1961
1962 #[test]
1963 fn increx_with_enx_is_the_rate_limiter() {
1964 let mut s = store();
1965 let c = s
1968 .increx(b"k", IncrEx::PLAIN.expiring(IncrExpire::AtIfNone(1_500)))
1969 .unwrap();
1970 assert_eq!(c.value, Num::Int(1));
1971 assert_eq!(s.expire_at(b"k"), Some(1_500));
1972 s.clock_mut().set(1_200);
1973 let c = s
1974 .increx(b"k", IncrEx::PLAIN.expiring(IncrExpire::AtIfNone(1_700)))
1975 .unwrap();
1976 assert_eq!(c.value, Num::Int(2));
1977 assert_eq!(s.expire_at(b"k"), Some(1_500), "the window was pushed out");
1978 s.clock_mut().set(1_500);
1980 let c = s
1981 .increx(b"k", IncrEx::PLAIN.expiring(IncrExpire::AtIfNone(2_000)))
1982 .unwrap();
1983 assert_eq!(c.value, Num::Int(1));
1984 assert_eq!(s.expire_at(b"k"), Some(2_000));
1985 assert_eq!(s.expired_keys(), 1);
1986 }
1987
1988 #[test]
1989 fn a_refused_increx_writes_nothing_at_all() {
1990 let mut s = store();
1991 let quota = IncrEx::PLAIN
1992 .by(Num::Int(10))
1993 .between(None, Some(Num::Int(5)));
1994 let c = s.increx(b"k", quota).unwrap();
1995 assert_eq!(
1996 (c.value, c.applied, c.stored),
1997 (Num::Int(0), Num::Int(0), false)
1998 );
1999 assert!(!s.exists(b"k"), "a refused increment created the key");
2000
2001 let c = s.increx(b"k", quota.saturating()).unwrap();
2004 assert_eq!((c.value, c.applied), (Num::Int(5), Num::Int(5)));
2005 assert!(s.exists(b"k"));
2006
2007 s.set(b"q", b"1", SetOptions::PLAIN.expiring(Expire::At(4_000)))
2009 .unwrap();
2010 let c = s
2011 .increx(b"q", quota.expiring(IncrExpire::At(9_000)))
2012 .unwrap();
2013 assert!(!c.stored);
2014 assert_eq!(s.expire_at(b"q"), Some(4_000));
2015 assert_eq!(got(&mut s, b"q").as_deref(), Some(&b"1"[..]));
2016 }
2017
2018 #[test]
2019 fn increx_by_float_stores_text_the_way_incrbyfloat_does() {
2020 let mut s = store();
2021 let c = s.increx(b"f", IncrEx::PLAIN.by(Num::Float(1.5))).unwrap();
2022 assert_eq!((c.value, c.applied), (Num::Float(1.5), Num::Float(1.5)));
2023 assert_eq!(got(&mut s, b"f").as_deref(), Some(&b"1.5"[..]));
2024 s.set_plain(b"n", b"5").unwrap();
2027 assert_eq!(s.encoding(b"n"), Some(Encoding::Int));
2028 s.increx(b"n", IncrEx::PLAIN.by(Num::Float(0.5))).unwrap();
2029 assert_eq!(s.encoding(b"n"), Some(Encoding::Embstr));
2030 assert_eq!(got(&mut s, b"n").as_deref(), Some(&b"5.5"[..]));
2031 }
2032
2033 #[test]
2034 fn increx_refuses_a_value_that_is_not_a_number() {
2035 let mut s = store();
2036 s.set_plain(b"t", b"hello").unwrap();
2037 assert!(s.increx(b"t", IncrEx::PLAIN).is_err());
2038 assert!(s.increx(b"t", IncrEx::PLAIN.by(Num::Float(1.0))).is_err());
2039 }
2040
2041 #[test]
2042 fn lcs_reads_two_keys_and_treats_a_missing_one_as_empty() {
2043 let mut s = store();
2044 s.set_plain(b"a", b"ohmytext").unwrap();
2045 s.set_plain(b"b", b"mynewtext").unwrap();
2046 assert_eq!(s.lcs(b"a", b"b").unwrap(), b"mytext");
2047 assert_eq!(s.lcs_len(b"a", b"b").unwrap(), 6);
2048 assert_eq!(s.lcs_idx(b"a", b"b", 4).unwrap().matches.len(), 1);
2049 assert_eq!(s.lcs(b"a", b"missing").unwrap(), b"");
2050 assert_eq!(s.lcs_len(b"missing", b"gone").unwrap(), 0);
2051 s.set_plain(b"n", b"12345").unwrap();
2053 s.set_plain(b"m", b"13579").unwrap();
2054 assert_eq!(s.lcs(b"n", b"m").unwrap(), b"135");
2055 }
2056
2057 #[test]
2058 fn lcs_does_not_see_a_key_that_has_expired() {
2059 let mut s = store();
2060 s.set(
2061 b"a",
2062 b"hello",
2063 SetOptions::PLAIN.expiring(Expire::At(1_100)),
2064 )
2065 .unwrap();
2066 s.set_plain(b"b", b"hello").unwrap();
2067 assert_eq!(s.lcs(b"a", b"b").unwrap(), b"hello");
2068 s.clock_mut().set(1_100);
2069 assert_eq!(s.lcs(b"a", b"b").unwrap(), b"");
2070 }
2071
2072 #[test]
2073 fn the_store_reports_what_it_is_holding() {
2074 let mut s = Keyspace::new();
2075 assert!(s.is_empty());
2076 assert!(s.memory_bytes() > 0, "an empty index still has buckets");
2077 s.set_plain(b"k", b"v").unwrap();
2078 assert!(!s.is_empty());
2079 assert_eq!(s.len(), 1);
2080 assert!(s.clock().now_ms() > 1_577_836_800_000);
2082 s.prefetch(Keyspace::hash_of(b"k"));
2083 assert_eq!(got(&mut s, b"k").as_deref(), Some(&b"v"[..]));
2084 }
2085
2086 #[test]
2087 fn clearing_hands_the_memory_back_and_not_only_the_keys() {
2088 let mut s = store();
2089 let empty = s.memory_bytes();
2090 let big = vec![b'x'; 4_096];
2091 for i in 0..2_000u32 {
2092 s.set_plain(format!("k{i}").as_bytes(), &big).unwrap();
2093 }
2094 assert_eq!(s.len(), 2_000);
2095 assert!(s.memory_bytes() > empty * 4, "the store should have grown");
2096
2097 s.setex(b"gone", 1, b"v").unwrap();
2099 s.clock_mut().set(3_000);
2100 assert!(got(&mut s, b"gone").is_none());
2101 assert_eq!(s.expired_keys(), 1);
2102
2103 s.clear();
2104 assert!(s.is_empty());
2105 assert_eq!(s.len(), 0);
2106 assert_eq!(got(&mut s, b"k0"), None);
2107 assert_eq!(s.memory_bytes(), empty);
2110 assert_eq!(s.expired_keys(), 1);
2113
2114 s.set_plain(b"after", b"v").unwrap();
2116 assert_eq!(got(&mut s, b"after").as_deref(), Some(&b"v"[..]));
2117 }
2118}