1use super::*;
2
3impl Keyspace {
4 pub fn get(&mut self, key: &str) -> Result<Option<Value>, WrongType> {
13 let expired = match self.entries.get_mut(key) {
14 Some(e) if e.is_expired() => true,
15 Some(e) => {
16 return match &e.value {
17 Value::String(_) => {
18 e.touch(self.track_access);
19 self.keyspace_hits += 1;
20 Ok(Some(e.value.clone()))
21 }
22 _ => Err(WrongType),
23 };
24 }
25 None => {
26 self.keyspace_misses += 1;
27 return Ok(None);
28 }
29 };
30 if expired {
31 self.remove_expired_entry(key);
32 }
33 self.keyspace_misses += 1;
34 Ok(None)
35 }
36
37 pub fn get_string(&mut self, key: &str) -> Result<Option<Bytes>, WrongType> {
44 let expired = match self.entries.get_mut(key) {
45 Some(e) if e.is_expired() => true,
46 Some(e) => {
47 return match &e.value {
48 Value::String(b) => {
49 let data = b.clone();
50 e.touch(self.track_access);
51 Ok(Some(data))
52 }
53 _ => Err(WrongType),
54 };
55 }
56 None => return Ok(None),
57 };
58 if expired {
59 self.remove_expired_entry(key);
60 }
61 Ok(None)
62 }
63
64 pub fn encoding(&mut self, key: &str) -> Option<&'static str> {
66 if self.remove_if_expired(key) {
67 return None;
68 }
69 self.entries
70 .get(key)
71 .map(|e| types::encoding_name(&e.value))
72 }
73
74 pub fn value_type(&mut self, key: &str) -> &'static str {
76 if self.remove_if_expired(key) {
77 return "none";
78 }
79 match self.entries.get(key) {
80 Some(e) => types::type_name(&e.value),
81 None => "none",
82 }
83 }
84
85 pub fn set(
95 &mut self,
96 key: String,
97 value: Bytes,
98 expire: Option<Duration>,
99 nx: bool,
100 xx: bool,
101 ) -> SetResult {
102 let has_expiry = expire.is_some();
103 let new_value = Value::String(value);
104 let new_size = memory::entry_size(&key, &new_value);
105
106 let old_info = self.entries.get(key.as_str()).and_then(|e| {
110 if e.is_expired() {
111 None
112 } else {
113 Some((e.entry_size(&key), e.expires_at_ms != 0))
114 }
115 });
116
117 let key_exists = old_info.is_some();
119 if nx && key_exists {
120 return SetResult::Blocked;
121 }
122 if xx && !key_exists {
123 return SetResult::Blocked;
124 }
125
126 let old_size = old_info.map(|(size, _)| size).unwrap_or(0);
128 let net_increase = new_size.saturating_sub(old_size);
129 if !self.enforce_memory_limit(net_increase) {
130 return SetResult::OutOfMemory;
131 }
132
133 if let Some((_, had_expiry)) = old_info {
135 self.memory.adjust(old_size, new_size);
136 self.adjust_expiry_count(had_expiry, has_expiry);
137 } else {
138 self.remove_if_expired(&key);
140 self.memory.add(&key, &new_value);
141 if has_expiry {
142 self.expiry_count += 1;
143 }
144 }
145
146 let entry = Entry::new(new_value, expire);
147 self.entries.insert(CompactString::from(key.clone()), entry);
148 self.bump_version(&key);
149 SetResult::Ok
150 }
151
152 pub fn incr(&mut self, key: &str) -> Result<i64, IncrError> {
157 self.incr_by(key, 1)
158 }
159
160 pub fn decr(&mut self, key: &str) -> Result<i64, IncrError> {
165 self.incr_by(key, -1)
166 }
167
168 pub fn incr_by(&mut self, key: &str, delta: i64) -> Result<i64, IncrError> {
173 self.remove_if_expired(key);
174
175 let (current, existing_expire) = match self.entries.get(key) {
177 Some(entry) => {
178 let val = match &entry.value {
179 Value::String(data) => {
180 let s = std::str::from_utf8(data).map_err(|_| IncrError::NotAnInteger)?;
181 s.parse::<i64>().map_err(|_| IncrError::NotAnInteger)?
182 }
183 _ => return Err(IncrError::WrongType),
184 };
185 let expire = time::remaining_ms(entry.expires_at_ms).map(Duration::from_millis);
186 (val, expire)
187 }
188 None => (0, None),
189 };
190
191 let new_val = current.checked_add(delta).ok_or(IncrError::Overflow)?;
192 let new_bytes = Bytes::from(new_val.to_string());
193
194 match self.set(key.to_owned(), new_bytes, existing_expire, false, false) {
195 SetResult::Ok | SetResult::Blocked => Ok(new_val),
196 SetResult::OutOfMemory => Err(IncrError::OutOfMemory),
197 }
198 }
199
200 pub fn incr_by_float(&mut self, key: &str, delta: f64) -> Result<String, IncrFloatError> {
206 self.remove_if_expired(key);
207
208 let (current, existing_expire) = match self.entries.get(key) {
209 Some(entry) => {
210 let val = match &entry.value {
211 Value::String(data) => {
212 let s = std::str::from_utf8(data).map_err(|_| IncrFloatError::NotAFloat)?;
213 s.parse::<f64>().map_err(|_| IncrFloatError::NotAFloat)?
214 }
215 _ => return Err(IncrFloatError::WrongType),
216 };
217 let expire = time::remaining_ms(entry.expires_at_ms).map(Duration::from_millis);
218 (val, expire)
219 }
220 None => (0.0, None),
221 };
222
223 let new_val = current + delta;
224 if new_val.is_nan() || new_val.is_infinite() {
225 return Err(IncrFloatError::NanOrInfinity);
226 }
227
228 let formatted = format_float(new_val);
231 let new_bytes = Bytes::copy_from_slice(formatted.as_bytes());
232
233 match self.set(key.to_owned(), new_bytes, existing_expire, false, false) {
234 SetResult::Ok | SetResult::Blocked => Ok(formatted),
235 SetResult::OutOfMemory => Err(IncrFloatError::OutOfMemory),
236 }
237 }
238
239 pub fn getdel(&mut self, key: &str) -> Result<Option<Bytes>, WrongType> {
244 if self.remove_if_expired(key) {
245 return Ok(None);
246 }
247 match self.entries.get(key) {
248 None => return Ok(None),
249 Some(e) if !matches!(e.value, Value::String(_)) => return Err(WrongType),
250 _ => {}
251 }
252 let entry = self.entries.remove(key).expect("verified above");
253 let bytes = match entry.value {
254 Value::String(ref b) => b.clone(),
255 _ => unreachable!("type checked above"),
256 };
257 self.memory.remove_with_size(
258 entry.cached_value_size as usize + key.len() + memory::ENTRY_OVERHEAD,
259 );
260 self.decrement_expiry_if_set(&entry);
261 self.remove_version(key);
262 Ok(Some(bytes))
263 }
264
265 pub fn getset(&mut self, key: &str, value: Bytes) -> Result<Option<Bytes>, WrongType> {
274 if self.remove_if_expired(key) {
275 } else {
277 match self.entries.get(key) {
278 None => {}
279 Some(e) if !matches!(e.value, Value::String(_)) => return Err(WrongType),
280 _ => {}
281 }
282 }
283
284 let old = match self.entries.get(key) {
285 Some(e) => match &e.value {
286 Value::String(b) => Some(b.clone()),
287 _ => return Err(WrongType),
288 },
289 None => None,
290 };
291
292 self.set(key.to_owned(), value, None, false, false);
294 Ok(old)
295 }
296
297 pub fn msetnx(&mut self, pairs: &[(String, Bytes)]) -> bool {
304 for (key, _) in pairs {
306 self.remove_if_expired(key);
307 if self.entries.contains_key(key.as_str()) {
308 return false;
309 }
310 }
311 for (key, value) in pairs {
313 self.set(key.clone(), value.clone(), None, false, false);
314 }
315 true
316 }
317
318 pub fn getex(
328 &mut self,
329 key: &str,
330 expire: Option<Option<Duration>>,
331 ) -> Result<Option<Bytes>, WrongType> {
332 if self.remove_if_expired(key) {
333 return Ok(None);
334 }
335
336 let (bytes, had_expiry) = match self.entries.get(key) {
337 None => return Ok(None),
338 Some(e) => match &e.value {
339 Value::String(b) => (b.clone(), e.expires_at_ms != 0),
340 _ => return Err(WrongType),
341 },
342 };
343
344 if let Some(new_expire) = expire {
345 let entry = self.entries.get_mut(key).expect("verified above");
346 match new_expire {
347 Some(duration) => {
348 entry.expires_at_ms =
349 time::now_ms().saturating_add(duration.as_millis() as u64);
350 if !had_expiry {
351 self.expiry_count += 1;
352 }
353 }
354 None => {
355 entry.expires_at_ms = 0;
356 if had_expiry {
357 self.expiry_count = self.expiry_count.saturating_sub(1);
358 }
359 }
360 }
361 entry.touch(self.track_access);
362 self.bump_version(key);
363 }
364
365 Ok(Some(bytes))
366 }
367
368 pub fn append(&mut self, key: &str, value: &[u8]) -> Result<usize, WriteError> {
371 self.remove_if_expired(key);
372
373 match self.entries.get(key) {
374 Some(entry) => match &entry.value {
375 Value::String(existing) => {
376 let mut new_data = Vec::with_capacity(existing.len() + value.len());
377 new_data.extend_from_slice(existing);
378 new_data.extend_from_slice(value);
379 let new_len = new_data.len();
380 let expire = time::remaining_ms(entry.expires_at_ms).map(Duration::from_millis);
381 match self.set(key.to_owned(), Bytes::from(new_data), expire, false, false) {
382 SetResult::Ok | SetResult::Blocked => Ok(new_len),
383 SetResult::OutOfMemory => Err(WriteError::OutOfMemory),
384 }
385 }
386 _ => Err(WriteError::WrongType),
387 },
388 None => {
389 let new_len = value.len();
390 match self.set(
391 key.to_owned(),
392 Bytes::copy_from_slice(value),
393 None,
394 false,
395 false,
396 ) {
397 SetResult::Ok | SetResult::Blocked => Ok(new_len),
398 SetResult::OutOfMemory => Err(WriteError::OutOfMemory),
399 }
400 }
401 }
402 }
403
404 pub fn strlen(&mut self, key: &str) -> Result<usize, WrongType> {
407 self.remove_if_expired(key);
408
409 match self.entries.get(key) {
410 Some(entry) => match &entry.value {
411 Value::String(data) => Ok(data.len()),
412 _ => Err(WrongType),
413 },
414 None => Ok(0),
415 }
416 }
417
418 pub fn getrange(&mut self, key: &str, start: i64, end: i64) -> Result<Bytes, WrongType> {
425 let Some(entry) = self.get_live_entry(key) else {
426 return Ok(Bytes::new());
427 };
428 let data = match &entry.value {
429 Value::String(b) => b.clone(),
430 _ => return Err(WrongType),
431 };
432
433 let len = data.len() as i64;
434 let s = if start < 0 {
436 (len + start).max(0)
437 } else {
438 start.min(len)
439 } as usize;
440 let e = if end < 0 {
441 (len + end).max(0)
442 } else {
443 end.min(len - 1)
444 } as usize;
445
446 if s > e || s >= data.len() {
447 return Ok(Bytes::new());
448 }
449 Ok(data.slice(s..=e))
450 }
451
452 pub fn setrange(
459 &mut self,
460 key: &str,
461 offset: usize,
462 value: &[u8],
463 ) -> Result<usize, WriteError> {
464 self.remove_if_expired(key);
465
466 let (existing, expire) = match self.entries.get(key) {
467 Some(entry) => match &entry.value {
468 Value::String(data) => {
469 let expire = time::remaining_ms(entry.expires_at_ms).map(Duration::from_millis);
470 (data.clone(), expire)
471 }
472 _ => return Err(WriteError::WrongType),
473 },
474 None => (Bytes::new(), None),
475 };
476
477 let needed = offset.saturating_add(value.len());
479 let new_len = existing.len().max(needed);
480 let mut buf = Vec::with_capacity(new_len);
481
482 let copy_len = existing.len().min(offset);
484 buf.extend_from_slice(&existing[..copy_len]);
485
486 if offset > existing.len() {
488 buf.resize(offset, 0);
489 }
490
491 buf.extend_from_slice(value);
493
494 if offset + value.len() < existing.len() {
496 buf.extend_from_slice(&existing[offset + value.len()..]);
497 }
498
499 let result_len = buf.len();
500 match self.set(key.to_owned(), Bytes::from(buf), expire, false, false) {
501 SetResult::Ok | SetResult::Blocked => Ok(result_len),
502 SetResult::OutOfMemory => Err(WriteError::OutOfMemory),
503 }
504 }
505}
506
507#[cfg(test)]
508mod tests {
509 use super::*;
510 use std::thread;
511
512 #[test]
513 fn set_and_get() {
514 let mut ks = Keyspace::new();
515 ks.set("hello".into(), Bytes::from("world"), None, false, false);
516 assert_eq!(
517 ks.get("hello").unwrap(),
518 Some(Value::String(Bytes::from("world")))
519 );
520 }
521
522 #[test]
523 fn get_missing_key() {
524 let mut ks = Keyspace::new();
525 assert_eq!(ks.get("nope").unwrap(), None);
526 }
527
528 #[test]
529 fn overwrite_replaces_value() {
530 let mut ks = Keyspace::new();
531 ks.set("key".into(), Bytes::from("first"), None, false, false);
532 ks.set("key".into(), Bytes::from("second"), None, false, false);
533 assert_eq!(
534 ks.get("key").unwrap(),
535 Some(Value::String(Bytes::from("second")))
536 );
537 }
538
539 #[test]
540 fn overwrite_clears_old_ttl() {
541 let mut ks = Keyspace::new();
542 ks.set(
543 "key".into(),
544 Bytes::from("v1"),
545 Some(Duration::from_secs(100)),
546 false,
547 false,
548 );
549 ks.set("key".into(), Bytes::from("v2"), None, false, false);
551 assert_eq!(ks.ttl("key"), TtlResult::NoExpiry);
552 }
553
554 #[test]
555 fn expired_key_returns_none() {
556 let mut ks = Keyspace::new();
557 ks.set(
558 "temp".into(),
559 Bytes::from("gone"),
560 Some(Duration::from_millis(10)),
561 false,
562 false,
563 );
564 thread::sleep(Duration::from_millis(30));
566 assert_eq!(ks.get("temp").unwrap(), None);
567 assert!(!ks.exists("temp"));
569 }
570
571 #[test]
572 fn get_on_list_key_returns_wrongtype() {
573 let mut ks = Keyspace::new();
574 let mut list = std::collections::VecDeque::new();
575 list.push_back(Bytes::from("item"));
576 ks.restore("mylist".into(), Value::List(list), None);
577
578 assert!(ks.get("mylist").is_err());
579 }
580
581 #[test]
582 fn value_type_returns_correct_types() {
583 let mut ks = Keyspace::new();
584 assert_eq!(ks.value_type("missing"), "none");
585
586 ks.set("s".into(), Bytes::from("val"), None, false, false);
587 assert_eq!(ks.value_type("s"), "string");
588
589 let mut list = std::collections::VecDeque::new();
590 list.push_back(Bytes::from("item"));
591 ks.restore("l".into(), Value::List(list), None);
592 assert_eq!(ks.value_type("l"), "list");
593
594 ks.zadd("z", &[(1.0, "a".into())], &ZAddFlags::default())
595 .unwrap();
596 assert_eq!(ks.value_type("z"), "zset");
597 }
598
599 #[test]
600 fn incr_new_key_defaults_to_zero() {
601 let mut ks = Keyspace::new();
602 assert_eq!(ks.incr("counter").unwrap(), 1);
603 match ks.get("counter").unwrap() {
605 Some(Value::String(data)) => assert_eq!(data, Bytes::from("1")),
606 other => panic!("expected String(\"1\"), got {other:?}"),
607 }
608 }
609
610 #[test]
611 fn incr_existing_value() {
612 let mut ks = Keyspace::new();
613 ks.set("n".into(), Bytes::from("10"), None, false, false);
614 assert_eq!(ks.incr("n").unwrap(), 11);
615 }
616
617 #[test]
618 fn decr_new_key_defaults_to_zero() {
619 let mut ks = Keyspace::new();
620 assert_eq!(ks.decr("counter").unwrap(), -1);
621 }
622
623 #[test]
624 fn decr_existing_value() {
625 let mut ks = Keyspace::new();
626 ks.set("n".into(), Bytes::from("10"), None, false, false);
627 assert_eq!(ks.decr("n").unwrap(), 9);
628 }
629
630 #[test]
631 fn incr_non_integer_returns_error() {
632 let mut ks = Keyspace::new();
633 ks.set("s".into(), Bytes::from("notanum"), None, false, false);
634 assert_eq!(ks.incr("s").unwrap_err(), IncrError::NotAnInteger);
635 }
636
637 #[test]
638 fn incr_on_list_returns_wrongtype() {
639 let mut ks = Keyspace::new();
640 ks.lpush("list", &[Bytes::from("a")]).unwrap();
641 assert_eq!(ks.incr("list").unwrap_err(), IncrError::WrongType);
642 }
643
644 #[test]
645 fn incr_overflow_returns_error() {
646 let mut ks = Keyspace::new();
647 ks.set(
648 "max".into(),
649 Bytes::from(i64::MAX.to_string()),
650 None,
651 false,
652 false,
653 );
654 assert_eq!(ks.incr("max").unwrap_err(), IncrError::Overflow);
655 }
656
657 #[test]
658 fn decr_overflow_returns_error() {
659 let mut ks = Keyspace::new();
660 ks.set(
661 "min".into(),
662 Bytes::from(i64::MIN.to_string()),
663 None,
664 false,
665 false,
666 );
667 assert_eq!(ks.decr("min").unwrap_err(), IncrError::Overflow);
668 }
669
670 #[test]
671 fn incr_preserves_ttl() {
672 let mut ks = Keyspace::new();
673 ks.set(
674 "n".into(),
675 Bytes::from("5"),
676 Some(Duration::from_secs(60)),
677 false,
678 false,
679 );
680 ks.incr("n").unwrap();
681 match ks.ttl("n") {
682 TtlResult::Seconds(s) => assert!((58..=60).contains(&s)),
683 other => panic!("expected TTL preserved, got {other:?}"),
684 }
685 }
686
687 #[test]
688 fn incr_at_max_value_overflows() {
689 let mut ks = Keyspace::new();
690 ks.set(
691 "counter".into(),
692 Bytes::from(i64::MAX.to_string()),
693 None,
694 false,
695 false,
696 );
697
698 let result = ks.incr("counter");
699 assert!(matches!(result, Err(IncrError::Overflow)));
700 }
701
702 #[test]
703 fn decr_at_min_value_underflows() {
704 let mut ks = Keyspace::new();
705 ks.set(
706 "counter".into(),
707 Bytes::from(i64::MIN.to_string()),
708 None,
709 false,
710 false,
711 );
712
713 let result = ks.decr("counter");
714 assert!(matches!(result, Err(IncrError::Overflow)));
715 }
716
717 #[test]
718 fn incr_by_float_basic() {
719 let mut ks = Keyspace::new();
720 ks.set("n".into(), Bytes::from("10.5"), None, false, false);
721 let result = ks.incr_by_float("n", 2.3).unwrap();
722 let f: f64 = result.parse().unwrap();
723 assert!((f - 12.8).abs() < 0.001);
724 }
725
726 #[test]
727 fn incr_by_float_new_key() {
728 let mut ks = Keyspace::new();
729 let result = ks.incr_by_float("new", 2.72).unwrap();
730 let f: f64 = result.parse().unwrap();
731 assert!((f - 2.72).abs() < 0.001);
732 }
733
734 #[test]
735 fn incr_by_float_negative() {
736 let mut ks = Keyspace::new();
737 ks.set("n".into(), Bytes::from("10"), None, false, false);
738 let result = ks.incr_by_float("n", -3.5).unwrap();
739 let f: f64 = result.parse().unwrap();
740 assert!((f - 6.5).abs() < 0.001);
741 }
742
743 #[test]
744 fn incr_by_float_wrong_type() {
745 let mut ks = Keyspace::new();
746 ks.lpush("mylist", &[Bytes::from("a")]).unwrap();
747 let err = ks.incr_by_float("mylist", 1.0).unwrap_err();
748 assert_eq!(err, IncrFloatError::WrongType);
749 }
750
751 #[test]
752 fn incr_by_float_not_a_float() {
753 let mut ks = Keyspace::new();
754 ks.set("s".into(), Bytes::from("hello"), None, false, false);
755 let err = ks.incr_by_float("s", 1.0).unwrap_err();
756 assert_eq!(err, IncrFloatError::NotAFloat);
757 }
758
759 #[test]
760 fn append_to_existing_key() {
761 let mut ks = Keyspace::new();
762 ks.set("key".into(), Bytes::from("hello"), None, false, false);
763 let len = ks.append("key", b" world").unwrap();
764 assert_eq!(len, 11);
765 assert_eq!(
766 ks.get("key").unwrap(),
767 Some(Value::String(Bytes::from("hello world")))
768 );
769 }
770
771 #[test]
772 fn append_to_new_key() {
773 let mut ks = Keyspace::new();
774 let len = ks.append("new", b"value").unwrap();
775 assert_eq!(len, 5);
776 assert_eq!(
777 ks.get("new").unwrap(),
778 Some(Value::String(Bytes::from("value")))
779 );
780 }
781
782 #[test]
783 fn append_wrong_type() {
784 let mut ks = Keyspace::new();
785 ks.lpush("mylist", &[Bytes::from("a")]).unwrap();
786 let err = ks.append("mylist", b"value").unwrap_err();
787 assert_eq!(err, WriteError::WrongType);
788 }
789
790 #[test]
791 fn strlen_existing_key() {
792 let mut ks = Keyspace::new();
793 ks.set("key".into(), Bytes::from("hello"), None, false, false);
794 assert_eq!(ks.strlen("key").unwrap(), 5);
795 }
796
797 #[test]
798 fn strlen_missing_key() {
799 let mut ks = Keyspace::new();
800 assert_eq!(ks.strlen("missing").unwrap(), 0);
801 }
802
803 #[test]
804 fn strlen_wrong_type() {
805 let mut ks = Keyspace::new();
806 ks.lpush("mylist", &[Bytes::from("a")]).unwrap();
807 let err = ks.strlen("mylist").unwrap_err();
808 assert_eq!(err, WrongType);
809 }
810
811 #[test]
812 fn empty_string_key_works() {
813 let mut ks = Keyspace::new();
814 ks.set("".into(), Bytes::from("value"), None, false, false);
815 assert_eq!(
816 ks.get("").unwrap(),
817 Some(Value::String(Bytes::from("value")))
818 );
819 assert!(ks.exists(""));
820 }
821
822 #[test]
823 fn empty_value_works() {
824 let mut ks = Keyspace::new();
825 ks.set("key".into(), Bytes::from(""), None, false, false);
826 assert_eq!(ks.get("key").unwrap(), Some(Value::String(Bytes::from(""))));
827 }
828
829 #[test]
830 fn binary_data_in_value() {
831 let mut ks = Keyspace::new();
832 let binary = Bytes::from(vec![0u8, 1, 2, 255, 0, 128]);
834 ks.set("binary".into(), binary.clone(), None, false, false);
835 assert_eq!(ks.get("binary").unwrap(), Some(Value::String(binary)));
836 }
837
838 #[test]
841 fn getrange_basic() {
842 let mut ks = Keyspace::new();
843 ks.set(
844 "key".into(),
845 Bytes::from("Hello, World!"),
846 None,
847 false,
848 false,
849 );
850 assert_eq!(ks.getrange("key", 0, 4).unwrap(), Bytes::from("Hello"));
851 assert_eq!(ks.getrange("key", 7, 11).unwrap(), Bytes::from("World"));
852 }
853
854 #[test]
855 fn getrange_negative_indices() {
856 let mut ks = Keyspace::new();
857 ks.set("key".into(), Bytes::from("Hello"), None, false, false);
858 assert_eq!(ks.getrange("key", -3, -1).unwrap(), Bytes::from("llo"));
860 assert_eq!(ks.getrange("key", 0, -2).unwrap(), Bytes::from("Hell"));
862 }
863
864 #[test]
865 fn getrange_out_of_bounds() {
866 let mut ks = Keyspace::new();
867 ks.set("key".into(), Bytes::from("Hello"), None, false, false);
868 assert_eq!(ks.getrange("key", 0, 100).unwrap(), Bytes::from("Hello"));
870 assert_eq!(ks.getrange("key", 3, 1).unwrap(), Bytes::new());
872 }
873
874 #[test]
875 fn getrange_missing_key() {
876 let mut ks = Keyspace::new();
877 assert_eq!(ks.getrange("nope", 0, 10).unwrap(), Bytes::new());
878 }
879
880 #[test]
881 fn getrange_wrong_type() {
882 let mut ks = Keyspace::new();
883 ks.lpush("list", &[Bytes::from("a")]).unwrap();
884 assert!(ks.getrange("list", 0, 1).is_err());
885 }
886
887 #[test]
888 fn getrange_empty_string() {
889 let mut ks = Keyspace::new();
890 ks.set("key".into(), Bytes::from(""), None, false, false);
891 assert_eq!(ks.getrange("key", 0, 0).unwrap(), Bytes::new());
892 }
893
894 #[test]
897 fn setrange_basic() {
898 let mut ks = Keyspace::new();
899 ks.set("key".into(), Bytes::from("Hello World"), None, false, false);
900 let len = ks.setrange("key", 6, b"Redis").unwrap();
901 assert_eq!(len, 11);
902 assert_eq!(
903 ks.get("key").unwrap(),
904 Some(Value::String(Bytes::from("Hello Redis")))
905 );
906 }
907
908 #[test]
909 fn setrange_zero_padding() {
910 let mut ks = Keyspace::new();
911 let len = ks.setrange("key", 5, b"Hi").unwrap();
912 assert_eq!(len, 7);
913 let val = match ks.get("key").unwrap() {
914 Some(Value::String(b)) => b,
915 other => panic!("expected String, got {other:?}"),
916 };
917 assert_eq!(&val[..5], &[0, 0, 0, 0, 0]);
918 assert_eq!(&val[5..], b"Hi");
919 }
920
921 #[test]
922 fn setrange_extends_string() {
923 let mut ks = Keyspace::new();
924 ks.set("key".into(), Bytes::from("abc"), None, false, false);
925 let len = ks.setrange("key", 3, b"def").unwrap();
926 assert_eq!(len, 6);
927 assert_eq!(
928 ks.get("key").unwrap(),
929 Some(Value::String(Bytes::from("abcdef")))
930 );
931 }
932
933 #[test]
934 fn setrange_preserves_ttl() {
935 let mut ks = Keyspace::new();
936 ks.set(
937 "key".into(),
938 Bytes::from("hello"),
939 Some(Duration::from_secs(60)),
940 false,
941 false,
942 );
943 ks.setrange("key", 0, b"jello").unwrap();
944 match ks.ttl("key") {
945 TtlResult::Seconds(s) => assert!((58..=60).contains(&s)),
946 other => panic!("expected TTL preserved, got {other:?}"),
947 }
948 }
949
950 #[test]
951 fn setrange_wrong_type() {
952 let mut ks = Keyspace::new();
953 ks.lpush("list", &[Bytes::from("a")]).unwrap();
954 let err = ks.setrange("list", 0, b"val").unwrap_err();
955 assert_eq!(err, WriteError::WrongType);
956 }
957
958 #[test]
961 fn encoding_int() {
962 let mut ks = Keyspace::new();
963 ks.set("n".into(), Bytes::from("42"), None, false, false);
964 assert_eq!(ks.encoding("n"), Some("int"));
965 }
966
967 #[test]
968 fn encoding_embstr() {
969 let mut ks = Keyspace::new();
970 ks.set("s".into(), Bytes::from("short"), None, false, false);
971 assert_eq!(ks.encoding("s"), Some("embstr"));
972 }
973
974 #[test]
975 fn encoding_raw() {
976 let mut ks = Keyspace::new();
977 let long = "a".repeat(30);
978 ks.set("s".into(), Bytes::from(long), None, false, false);
979 assert_eq!(ks.encoding("s"), Some("raw"));
980 }
981
982 #[test]
983 fn encoding_missing_key() {
984 let mut ks = Keyspace::new();
985 assert_eq!(ks.encoding("nope"), None);
986 }
987
988 #[test]
989 fn encoding_list() {
990 let mut ks = Keyspace::new();
991 ks.lpush("l", &[Bytes::from("a")]).unwrap();
992 assert_eq!(ks.encoding("l"), Some("listpack"));
993 }
994
995 #[test]
996 fn encoding_set() {
997 let mut ks = Keyspace::new();
998 ks.sadd("s", &["member".into()]).unwrap();
999 assert_eq!(ks.encoding("s"), Some("hashtable"));
1000 }
1001
1002 #[test]
1003 fn encoding_sorted_set() {
1004 let mut ks = Keyspace::new();
1005 ks.zadd("z", &[(1.0, "a".into())], &ZAddFlags::default())
1006 .unwrap();
1007 assert_eq!(ks.encoding("z"), Some("skiplist"));
1008 }
1009
1010 #[test]
1011 fn encoding_hash_compact() {
1012 let mut ks = Keyspace::new();
1013 ks.hset("h", &[("field".into(), Bytes::from("val"))])
1014 .unwrap();
1015 assert_eq!(ks.encoding("h"), Some("listpack"));
1016 }
1017
1018 #[test]
1019 fn format_float_integers() {
1020 assert_eq!(super::format_float(10.0), "10");
1021 assert_eq!(super::format_float(0.0), "0");
1022 assert_eq!(super::format_float(-5.0), "-5");
1023 }
1024
1025 #[test]
1026 fn format_float_decimals() {
1027 assert_eq!(super::format_float(2.72), "2.72");
1028 assert_eq!(super::format_float(10.5), "10.5");
1029 }
1030
1031 #[test]
1032 fn getdel_returns_value_and_removes_key() {
1033 let mut ks = Keyspace::new();
1034 ks.set("k".into(), Bytes::from("hello"), None, false, false);
1035 let val = ks.getdel("k").unwrap();
1036 assert_eq!(val, Some(Bytes::from("hello")));
1037 assert!(!ks.exists("k"));
1038 assert_eq!(ks.stats().used_bytes, 0);
1039 }
1040
1041 #[test]
1042 fn getdel_missing_key_returns_none() {
1043 let mut ks = Keyspace::new();
1044 assert_eq!(ks.getdel("nope").unwrap(), None);
1045 }
1046
1047 #[test]
1048 fn getdel_wrong_type_returns_error() {
1049 let mut ks = Keyspace::new();
1050 ks.zadd("z", &[(1.0, "a".into())], &ZAddFlags::default())
1051 .unwrap();
1052 assert!(ks.getdel("z").is_err());
1053 }
1054
1055 #[test]
1056 fn getex_no_option_leaves_ttl_unchanged() {
1057 let mut ks = Keyspace::new();
1058 ks.set(
1059 "k".into(),
1060 Bytes::from("v"),
1061 Some(Duration::from_secs(60)),
1062 false,
1063 false,
1064 );
1065 let ttl_before = ks.ttl("k");
1066 let val = ks.getex("k", None).unwrap();
1067 assert_eq!(val, Some(Bytes::from("v")));
1068 let ttl_after = ks.ttl("k");
1069 assert!(matches!(ttl_before, TtlResult::Seconds(_)));
1071 assert!(matches!(ttl_after, TtlResult::Seconds(_)));
1072 }
1073
1074 #[test]
1075 fn getex_persist_clears_ttl() {
1076 let mut ks = Keyspace::new();
1077 ks.set(
1078 "k".into(),
1079 Bytes::from("v"),
1080 Some(Duration::from_secs(60)),
1081 false,
1082 false,
1083 );
1084 let val = ks.getex("k", Some(None)).unwrap();
1085 assert_eq!(val, Some(Bytes::from("v")));
1086 assert!(matches!(ks.ttl("k"), TtlResult::NoExpiry));
1087 }
1088
1089 #[test]
1090 fn getex_set_new_ttl() {
1091 let mut ks = Keyspace::new();
1092 ks.set("k".into(), Bytes::from("v"), None, false, false);
1093 let val = ks.getex("k", Some(Some(Duration::from_secs(30)))).unwrap();
1094 assert_eq!(val, Some(Bytes::from("v")));
1095 assert!(matches!(ks.ttl("k"), TtlResult::Seconds(_)));
1096 }
1097
1098 #[test]
1099 fn getex_missing_key_returns_none() {
1100 let mut ks = Keyspace::new();
1101 assert_eq!(ks.getex("nope", None).unwrap(), None);
1102 }
1103
1104 #[test]
1107 fn getset_returns_old_value_and_sets_new() {
1108 let mut ks = Keyspace::new();
1109 ks.set("k".into(), Bytes::from("old"), None, false, false);
1110 let old = ks.getset("k", Bytes::from("new")).unwrap();
1111 assert_eq!(old, Some(Bytes::from("old")));
1112 assert_eq!(
1113 ks.get("k").unwrap(),
1114 Some(Value::String(Bytes::from("new")))
1115 );
1116 }
1117
1118 #[test]
1119 fn getset_missing_key_returns_none_and_sets_value() {
1120 let mut ks = Keyspace::new();
1121 let old = ks.getset("k", Bytes::from("v")).unwrap();
1122 assert_eq!(old, None);
1123 assert_eq!(ks.get("k").unwrap(), Some(Value::String(Bytes::from("v"))));
1124 }
1125
1126 #[test]
1127 fn getset_clears_existing_ttl() {
1128 let mut ks = Keyspace::new();
1129 ks.set(
1130 "k".into(),
1131 Bytes::from("old"),
1132 Some(Duration::from_secs(60)),
1133 false,
1134 false,
1135 );
1136 assert!(matches!(ks.ttl("k"), TtlResult::Seconds(_)));
1137 let _ = ks.getset("k", Bytes::from("new")).unwrap();
1138 assert!(matches!(ks.ttl("k"), TtlResult::NoExpiry));
1139 }
1140
1141 #[test]
1142 fn getset_wrong_type_returns_error() {
1143 let mut ks = Keyspace::new();
1144 ks.zadd("z", &[(1.0, "a".into())], &ZAddFlags::default())
1145 .unwrap();
1146 assert!(ks.getset("z", Bytes::from("v")).is_err());
1147 }
1148
1149 #[test]
1152 fn msetnx_all_new_keys_returns_true_and_sets() {
1153 let mut ks = Keyspace::new();
1154 let pairs = vec![
1155 ("a".to_owned(), Bytes::from("1")),
1156 ("b".to_owned(), Bytes::from("2")),
1157 ];
1158 assert!(ks.msetnx(&pairs));
1159 assert_eq!(ks.get("a").unwrap(), Some(Value::String(Bytes::from("1"))));
1160 assert_eq!(ks.get("b").unwrap(), Some(Value::String(Bytes::from("2"))));
1161 }
1162
1163 #[test]
1164 fn msetnx_any_existing_returns_false_and_no_changes() {
1165 let mut ks = Keyspace::new();
1166 ks.set("a".into(), Bytes::from("existing"), None, false, false);
1167 let pairs = vec![
1168 ("a".to_owned(), Bytes::from("new")),
1169 ("b".to_owned(), Bytes::from("2")),
1170 ];
1171 assert!(!ks.msetnx(&pairs));
1172 assert_eq!(
1174 ks.get("a").unwrap(),
1175 Some(Value::String(Bytes::from("existing")))
1176 );
1177 assert_eq!(ks.get("b").unwrap(), None);
1178 }
1179
1180 #[test]
1181 fn msetnx_empty_pairs_returns_true() {
1182 let mut ks = Keyspace::new();
1183 assert!(ks.msetnx(&[]));
1184 }
1185}