Skip to main content

yo_kv/
strings.rs

1//! The string type and its commands.
2//!
3//! The commands are an `impl` block on [`Keyspace`] rather than methods on some
4//! per type object, because a key belongs to the database and not to a type.
5//! Everything in this file is about strings; everything that is about the
6//! database whatever it holds is in [`keyspace`](crate::keyspace).
7//!
8//! One method per Redis command, taking and returning ordinary Rust values.
9//! There is no command enum here and no dispatch: this is the layer the wire
10//! calls into and the layer the embedded API calls into, and Y23 says those two
11//! have to be the same code rather than two implementations of the same idea.
12//! Anything that is about parsing arguments or writing a reply lives above.
13//!
14//! Errors carry Redis's own message text, because it ends up on the wire
15//! verbatim, and a [`Code`] alongside it, because the embedded caller should be
16//! matching on a value rather than on a string (P5).
17
18use 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
28/// What Redis says when a value should have been a number and was not.
29const NOT_AN_INT: &str = "value is not an integer or out of range";
30/// What Redis says when a value should have been a float and was not.
31const NOT_A_FLOAT: &str = "value is not a valid float";
32/// What Redis says when the result of a counter would leave the range.
33const WOULD_OVERFLOW: &str = "increment or decrement would overflow";
34/// What Redis says when a write would make a string too long.
35const TOO_LONG: &str = "string exceeds maximum allowed size (proto-max-bulk-len)";
36/// What we say when a key is longer than this band holds.
37const KEY_TOO_LONG: &str = "key exceeds maximum allowed size";
38/// What Redis says when an offset is negative or past the end of the world.
39const BAD_OFFSET: &str = "offset is out of range";
40
41/// The longest key this band stores.
42///
43/// Redis's limit is 512 MiB for a key as well as for a value. A key that long is
44/// not a key, it is a value in the wrong place, and holding the ceiling down
45/// here is what lets [`STRING_MAX`] be a constant rather than a function of the
46/// key in hand.
47pub const KEY_MAX: usize = 64 * 1024;
48
49/// The largest string this band stores.
50///
51/// Redis's limit is 512 MiB. Ours is a segment, because a string lives in the
52/// arena and the arena hands out at most one segment's worth in one piece. The
53/// band above this is the log region (`06` section 2) and lands with tiering in
54/// M5, at which point this constant goes up to Redis's. It is a divergence and
55/// it is listed as one rather than left for somebody to discover.
56pub const STRING_MAX: usize = RawMap::max_record() - RawMap::header_len() - KEY_MAX - 16;
57
58/// Whether a `SET` should go ahead given what is already there.
59#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
60pub enum Exists {
61    /// Store whatever is there. Plain `SET`.
62    #[default]
63    Always,
64    /// Only if the key is absent. `SET NX`, and `SETNX`.
65    IfMissing,
66    /// Only if the key is present. `SET XX`.
67    IfPresent,
68}
69
70/// What a write should do with the key's deadline.
71#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
72pub enum Expire {
73    /// Leave the key with no deadline. Plain `SET`, and `GETEX PERSIST`.
74    #[default]
75    Clear,
76    /// Leave whatever deadline was there. `SET KEEPTTL`, and plain `GETEX`.
77    Keep,
78    /// Expire at this absolute unix millisecond. `EX`, `PX`, `EXAT`, `PXAT`.
79    At(u64),
80}
81
82/// Everything `SET` can be asked to do beyond storing the value.
83#[derive(Debug, Clone, Copy, Default)]
84pub struct SetOptions<'a> {
85    /// `NX` or `XX`.
86    pub exists: Exists,
87    /// `EX`, `PX`, `EXAT`, `PXAT` or `KEEPTTL`.
88    pub expire: Expire,
89    /// `IFEQ`, `IFNE`, `IFDEQ` or `IFDNE`.
90    ///
91    /// Redis 8.4's compare and set. A missing key never compares equal, so
92    /// `IFEQ` on a key that is not there does not store, and `IFNE` on one
93    /// does.
94    pub compare: Option<Compare<'a>>,
95    /// `GET`: hand back what was there, whether or not the write happened.
96    pub get: bool,
97}
98
99impl<'a> SetOptions<'a> {
100    /// No options at all, which is plain `SET`.
101    pub const PLAIN: SetOptions<'static> = SetOptions {
102        exists: Exists::Always,
103        expire: Expire::Clear,
104        compare: None,
105        get: false,
106    };
107
108    /// This, but only if the key is missing.
109    #[must_use]
110    pub const fn if_missing(mut self) -> SetOptions<'a> {
111        self.exists = Exists::IfMissing;
112        self
113    }
114
115    /// This, but only if the key is present.
116    #[must_use]
117    pub const fn if_present(mut self) -> SetOptions<'a> {
118        self.exists = Exists::IfPresent;
119        self
120    }
121
122    /// This, with a deadline.
123    #[must_use]
124    pub const fn expiring(mut self, e: Expire) -> SetOptions<'a> {
125        self.expire = e;
126        self
127    }
128
129    /// This, but only if the current value is exactly `bytes`. `IFEQ`.
130    #[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    /// This, but only if the current value is not exactly `bytes`. `IFNE`.
137    #[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    /// This, but only against a value whose digest is `d`. `IFDEQ`.
144    #[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    /// This, but only against a value whose digest is not `d`. `IFDNE`.
151    #[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    /// This, returning the previous value.
158    #[must_use]
159    pub const fn returning(mut self) -> SetOptions<'a> {
160        self.get = true;
161        self
162    }
163}
164
165/// What a `SET` did.
166#[derive(Debug, Clone, PartialEq, Eq, Default)]
167pub struct SetOutcome {
168    /// Whether the value was written. `NX`, `XX` and `IFEQ` can all say no.
169    pub stored: bool,
170    /// The previous value, when `GET` was asked for and there was one.
171    ///
172    /// Owned, because the record it lived in has been written over by the time
173    /// this is handed back, and only ever filled in by [`Keyspace::set`]. A
174    /// caller that does not want the copy calls [`Keyspace::set_with`] and gets
175    /// the old value where it still lives, which is what the wire does.
176    pub previous: Option<Vec<u8>>,
177}
178
179/// The string commands.
180///
181/// These hang off the database rather than off a per type object, because a
182/// key belongs to the database: `GET` against a set has to be able to see that
183/// it is a set.
184impl Keyspace {
185    // ---------------------------------------------------------------- reading
186
187    /// `GET key`.
188    ///
189    /// One probe of the map for the whole command. It used to be three, because
190    /// the reap looked the key up to see whether it was dead, the type check
191    /// looked it up to see whether it was a string, and the read looked it up
192    /// again to read it, and all three walked a bucket for the same record.
193    /// `Keyspace::live_rec` hands back where that record is and the rest is
194    /// two arena reads at a known address.
195    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        // One more bit of the byte the kind came out of, and on a database with
204        // no file behind it no record ever has it set. See
205        // [`Keyspace::warmed`].
206        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    /// `MGET key [key ...]`.
213    ///
214    /// Every dead key is reaped first and the whole answer is then read from a
215    /// store nobody is going to mutate, which is what lets all of the returned
216    /// values borrow from it at once instead of being copied out one at a time.
217    pub fn mget<'a>(&'a mut self, keys: &[&[u8]]) -> Vec<Option<Str<'a>>> {
218        for k in keys {
219            // A demoted value is brought back into memory here rather than
220            // served from the buffer, because this form hands back every value
221            // at once and there is one buffer. The wire does not come through
222            // here, it calls [`Keyspace::mget_one`] per key, and that one asks
223            // the doorkeeper properly. An error is dropped: this returns a
224            // `Vec` with no room in it to say that one key would not read back,
225            // and the key then reads as nil, which is what a key holding the
226            // wrong type does two lines below.
227            let _ = self.thaw(k);
228            // `live_rec` rather than `reap`, which does the same reap and also
229            // stamps the eviction clock. The reading pass below cannot, because
230            // it holds a shared borrow of the whole database so that every value
231            // it returns can borrow from it at once. The wire does not come
232            // through here at all, it walks the keys itself and calls
233            // [`Keyspace::mget_one`], so without this the same command would
234            // stamp from one entry point and not from the other.
235            self.live_rec(k);
236        }
237        let me: &Keyspace = self;
238        keys.iter().map(|k| me.peek(k)).collect()
239    }
240
241    /// One key of an `MGET`, which is nil rather than an error for a key that
242    /// holds another type.
243    ///
244    /// [`Keyspace::mget`] collects the whole answer into a `Vec` for a caller
245    /// that wants it in one piece. The wire wants the keys one at a time and in
246    /// order, and a `Vec` there would be an allocation per call on a thread that
247    /// must not allocate, so the dispatcher walks the keys itself and calls this
248    /// for each. It is not `get`, because `MGET` does not answer `WRONGTYPE`:
249    /// Redis gives nil for the odd key out rather than failing the ninety nine
250    /// good ones alongside it.
251    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            // A key whose value will not read back is nil here rather than an
259            // error, the same as a key holding a set is. `MGET` has no way to
260            // report one bad key out of a hundred and Redis does not try.
261            return self.warmed(key).ok().flatten();
262        }
263        Some(value::read(self.map.value_at(addr)))
264    }
265
266    /// `STRLEN key`, which is zero for a key that is not there.
267    ///
268    /// Answered out of the record even when the value is on the file, because a
269    /// demoted record carries the length next to the address. Going to the
270    /// device for a number that is already in memory would be a device read
271    /// spent on nothing, and it would be one that a client could use to pull a
272    /// whole database back into memory a key at a time.
273    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    /// `EXISTS key`, for one key.
288    ///
289    /// Asking whether a key is there does not count as using it, which is
290    /// Redis's rule and not a nicety. A health check that runs `EXISTS` over a
291    /// list of keys every second would otherwise be enough on its own to make
292    /// all of them look like the hottest keys in the database.
293    pub fn exists(&mut self, key: &[u8]) -> bool {
294        self.live_rec_untouched(key).is_some()
295    }
296
297    /// How a string is stored, which is `OBJECT ENCODING` for a string key.
298    ///
299    /// `None` for a key that is not there and for a key holding another type,
300    /// because the two encoding bits in a record only mean anything when the
301    /// record is the value. A set keeps its representation in its body, so
302    /// [`Keyspace::set_encoding`] asks the body, and
303    /// [`Keyspace::encoding_name`] is the command that routes between them.
304    ///
305    /// Every `OBJECT` subcommand looks without touching, so this does too.
306    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    /// The key's deadline as an absolute unix millisecond, if it has one.
316    ///
317    /// `EXPIRETIME` and `PEXPIRETIME`, which do not count as using the key. See
318    /// [`Keyspace::deadline_of`].
319    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    /// `GETRANGE key start end`, and `SUBSTR`, which is the same command.
325    ///
326    /// Both ends are inclusive and both may be negative, counting back from the
327    /// end. Everything out of range clamps, and a start past the end gives the
328    /// empty string rather than an error, which is Redis's behaviour and not an
329    /// oversight in it.
330    ///
331    /// Borrowed for a string, owned for an integer, because an integer's digits
332    /// do not exist anywhere until somebody asks for them.
333    pub fn getrange(&mut self, key: &[u8], start: i64, end: i64) -> Result<Cow<'_, [u8]>> {
334        // A range of a demoted value still reads the whole value back, because
335        // a chunk is 64 KiB and the range is usually smaller than one. The
336        // chunked band can serve a range out of the chunks it covers, and
337        // wiring that in here is worth doing once there is a workload asking
338        // for windows into large cold values. See [`cold::Reader::range`].
339        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    // ---------------------------------------------------------------- writing
358
359    /// `SET key value [NX|XX] [GET] [IFEQ v|IFNE v|IFDEQ d|IFDNE d]
360    /// [EX s|PX ms|EXAT s|PXAT ms|KEEPTTL]`.
361    ///
362    /// The order the conditions are tested in is Redis's: the key is looked at
363    /// once, `NX`, `XX` and the four `IF` forms all decide against that one
364    /// look, and `GET` reports what was there whether or not the write went
365    /// ahead.
366    ///
367    /// The old value comes back owned, which costs a copy of it. On the wire
368    /// that copy is pure waste, because the reply is written and the bytes are
369    /// never looked at again, so the wire calls [`Keyspace::set_with`] instead
370    /// and this is that with a `to_vec` on the end.
371    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    /// `SET`, handing the old value to `previous` rather than copying it out.
379    ///
380    /// [`Keyspace::set`] with the allocation taken off it. `previous` is called
381    /// with the value as it lies in the record, before the write goes over it,
382    /// and only when `GET` was asked for and there was something there. Nothing
383    /// after that point can fail, so a caller that writes the value straight
384    /// into a reply is not going to have to take it back out again.
385    ///
386    /// [`SetOutcome::previous`] is always `None` here. The value went to the
387    /// closure, and putting it in both places would be the copy this exists to
388    /// avoid.
389    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            // Plain `SET` overwrites whatever was there, but the forms that read
403            // the old value first cannot: there is nothing to hand back and
404            // nothing to compare against. Redis answers WRONGTYPE for both.
405            self.string_only(key)?;
406            // And a value on the file has to come back before it can be handed
407            // over or compared against. Plain `SET` does not do this, and that
408            // is the point: overwriting a demoted key costs no device read.
409            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            // A key that is not there is not equal to anything, including the
426            // empty string, and the `NE` forms read that the other way round.
427            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    /// `SET key value`, with nothing else asked for.
445    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    /// `SETNX key value`, which answers whether it stored.
452    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    /// `SETEX key seconds value`.
457    ///
458    /// A zero or negative time to live is an error and not a delete, which is
459    /// what Redis does: `SETEX k 0 v` returns `ERR invalid expire time`.
460    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    /// `PSETEX key milliseconds value`.
468    pub fn psetex(&mut self, key: &[u8], millis: i64, val: &[u8]) -> Result<()> {
469        self.set_expiring(key, millis, val, "psetex")
470    }
471
472    /// The body both of those share.
473    ///
474    /// The command name is carried in rather than taken from whichever method
475    /// does the work, because the message is the caller's: a `SETEX` with a bad
476    /// time to live says `setex` even though the milliseconds are handled here,
477    /// and a client that matches on the text gets the command it sent.
478    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    /// `GETSET key value`, which is `SET key value GET` without the options.
488    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    /// `GETDEL key`.
493    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    /// `GETDEL`, handing the value to `f` rather than copying it out.
500    ///
501    /// [`Keyspace::getdel`] with the allocation taken off it, the same pair
502    /// [`Keyspace::set`] and [`Keyspace::set_with`] are. `f` is called with the
503    /// value where it still lies, before the key goes, and the answer says
504    /// whether there was one.
505    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        // Warmed and not thawed. The key is about to be deleted, so putting its
512        // value back in memory on the way past would be work done for a record
513        // that is not going to exist a line later.
514        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    /// `GETEX key [EX s|PX ms|EXAT s|PXAT ms|PERSIST]`.
524    ///
525    /// [`Expire::Keep`] is plain `GETEX`, which reads without touching the
526    /// deadline, and [`Expire::Clear`] is `GETEX PERSIST`.
527    pub fn getex(&mut self, key: &[u8], expire: Expire) -> Result<Option<Str<'_>>> {
528        self.reap(key);
529        self.string_only(key)?;
530        // Thawed rather than warmed, because a deadline that changes rewrites
531        // the whole record: the value does not move but the header in front of
532        // it changes length, so the bytes have to be in hand either way. Plain
533        // `GETEX` with no expiry argument is the read that the doorkeeper
534        // should get a vote on, and it takes the branch below instead.
535        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                // The value does not change, only the header in front of it, so
548                // this reads the value out and writes the whole record back. A
549                // deadline that is added or removed changes the record's length,
550                // so there is nothing to overwrite in place.
551                //
552                // Through the database's scratch buffer rather than a fresh
553                // `Vec`, for the reason `RENAME` does the same thing: the
554                // borrow of the map has to end before the write can begin, and
555                // a value carried three lines is not worth a malloc and a free.
556                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    /// `DEL key`, for one key. Answers whether it was there.
568    ///
569    /// Any type, and it takes the body with it. `DEL` is the one command that
570    /// genuinely does not care what it is deleting.
571    pub fn del(&mut self, key: &[u8]) -> bool {
572        self.reap(key);
573        self.drop_key(key)
574    }
575
576    /// `MSET key value [key value ...]`.
577    ///
578    /// Always succeeds, always overwrites, and always clears any deadline the
579    /// keys had, which is `SET` without options applied to each pair in turn.
580    ///
581    /// The pairs arrive as an iterator rather than a slice because the wire
582    /// layer has them as positions in the connection's read buffer, and a
583    /// slice would mean collecting them into a `Vec` first. `MSET` is on the
584    /// list of four commands M2 is measured on, and a shard thread that
585    /// allocates aborts, so an API that forces an allocation to call it is the
586    /// wrong API. The iterator is walked twice, which is why it has to be
587    /// `Clone`, and an iterator over borrowed slices is two words to copy.
588    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    /// `MSETNX key value [key value ...]`, which stores all of them or none.
602    ///
603    /// The whole set of keys is checked before anything is written, so a
604    /// duplicate key inside one call does not defeat itself.
605    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    /// `APPEND key value`, answering the new length.
625    ///
626    /// Appending to a key that is not there creates it, which makes `APPEND` on
627    /// an empty key the same as `SET`. Any deadline the key had is kept, which
628    /// is Redis's behaviour: `APPEND` is not a fresh `SET`.
629    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        // The database's one scratch buffer, for the reason `LMOVE` uses it:
640        // building the new value needs the old bytes in hand while `store_raw`
641        // wants `&mut self`, and a `Vec` per call is a malloc and a free on the
642        // command a log writer sends in a loop. Taken out and put back on every
643        // path, so an early return leaves it as it was found.
644        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    /// `SETRANGE key offset value`, answering the new length.
659    ///
660    /// A write past the end pads with zero bytes, and a write of nothing to a
661    /// key that is not there creates nothing and answers zero. Both of those are
662    /// Redis's, and both are the kind of edge a client library's test suite
663    /// checks.
664    pub fn setrange(&mut self, key: &[u8], offset: usize, val: &[u8]) -> Result<usize> {
665        self.reap(key);
666        self.string_only(key)?;
667        // `SETRANGE key n ""` writes nothing and answers the length, which the
668        // record already knows, so that form does not touch the device. See
669        // [`Keyspace::strlen`], which is the same argument.
670        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        // The same scratch buffer [`Keyspace::append`] uses, for the same
680        // reason. `SETRANGE` in a loop is how a client keeps a fixed layout
681        // record in one key.
682        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    // --------------------------------------------------------------- counters
702
703    /// `INCR key`.
704    #[inline]
705    pub fn incr(&mut self, key: &[u8]) -> Result<i64> {
706        self.incrby(key, 1)
707    }
708
709    /// `DECR key`.
710    #[inline]
711    pub fn decr(&mut self, key: &[u8]) -> Result<i64> {
712        self.decrby(key, 1)
713    }
714
715    /// `DECRBY key decrement`.
716    ///
717    /// Negating first would overflow on `i64::MIN`, which is why the decrement
718    /// is carried through as a subtraction rather than turned into an addition.
719    pub fn decrby(&mut self, key: &[u8], by: i64) -> Result<i64> {
720        self.count(key, by, true)
721    }
722
723    /// `INCRBY key increment`, and with an increment of one, `INCR`.
724    ///
725    /// This is the command the milestone's gate is about, so the path it takes
726    /// is worth stating. A key that is already int encoded is one probe, an add
727    /// and an eight byte store back into the record the probe landed on. No
728    /// arena allocation, no free, no second record, and no rehash. Every other
729    /// case falls through to a rewrite, which is what `INCR` on a string that
730    /// happens to look like a number costs.
731    #[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        // A demoted value is never int encoded, so a counter that is being
739        // counted on is never on the file and this costs one branch on a null
740        // field. It is here for the key that was a long string, got demoted,
741        // and is now being incremented, which answers an error rather than
742        // reading twelve bytes of address as a number.
743        self.thaw(key)?;
744        let hash = RawMap::hash_of(key);
745        let now = self.clock.now_ms();
746
747        // One probe, and the mutable borrow ends inside this block whichever way
748        // it goes, so the slow paths below are free to reallocate.
749        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            // The type check is inside the probe rather than in front of it,
754            // which is what the other writers do with `string_only`. The kind is
755            // three bits of the same byte the expiry flag is in, and that byte
756            // has already been loaded by the time this is asked, so here it is
757            // free. In front of the probe it measured at one and a half
758            // nanoseconds on a command that runs in eighteen, which is eight per
759            // cent of the number M2's gate is written against.
760            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    /// `INCRBYFLOAT key increment`.
795    ///
796    /// The result is stored as a string, never as an integer, because Redis
797    /// stores it with its own formatting and `OBJECT ENCODING` reports `embstr`
798    /// afterwards even when the number came out whole.
799    pub fn incrbyfloat(&mut self, key: &[u8], by: f64) -> Result<f64> {
800        check_len(key, 0)?;
801        // An infinite increment is not refused up front. Redis parses it,
802        // performs the addition and reports the sum, so `INCRBYFLOAT k inf`
803        // says the increment would produce infinity rather than that the
804        // increment is not a float, and the check below is the one that says
805        // it.
806        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                // Read out of the record rather than copied out of it. An int
812                // encoded value has no digits anywhere to borrow, so that arm
813                // converts instead of formatting and parsing, which is the same
814                // double either way: the decimal form of an `i64` rounds to the
815                // nearest double and so does the cast.
816                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    // ------------------------------------------------------------------- 8.4+
840
841    /// `MSETEX numkeys key value [key value ...] [NX|XX]
842    /// [EX s|PX ms|EXAT s|PXAT ms|KEEPTTL]`.
843    ///
844    /// Redis 8.4. `MSET` with a condition and a shared deadline, and the
845    /// condition is over the whole set rather than per key: `NX` needs every
846    /// key to be missing and `XX` needs every one to be present, and a partial
847    /// match writes nothing and answers false. Without an expiration option the
848    /// deadline is cleared, the same way plain `SET` clears it, and
849    /// [`Expire::Keep`] is `KEEPTTL`, which leaves each key its own.
850    ///
851    /// A duplicate key inside one call is not an error and the last value wins.
852    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    /// `DELEX key [IFEQ v|IFNE v|IFDEQ d|IFDNE d]`.
884    ///
885    /// Redis 8.4's compare and delete, the other half of `SET ... IFEQ`. The
886    /// point of it is the read modify write nobody was doing correctly: a client
887    /// that reads a value, decides it is stale and deletes it can be beaten to
888    /// the key by another client between the read and the delete, and `WATCH`
889    /// plus `MULTI` costs a round trip to avoid it.
890    ///
891    /// `None` compares against nothing and deletes unconditionally, which is
892    /// plain `DEL` for one key. A key that is not there answers false whatever
893    /// the condition says, including the `NE` forms that a missing key
894    /// satisfies, because there is still nothing to delete.
895    pub fn delex(&mut self, key: &[u8], compare: Option<Compare<'_>>) -> bool {
896        self.reap(key);
897        // Only the comparing form reads the value, and only that form pays for
898        // a demoted one. `DELEX` with no compare deletes a cold key without
899        // touching the file at all. An error faulting is a comparison that
900        // cannot be made, which is a comparison that does not hold.
901        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    /// `DIGEST key`, the XXH3 of the value.
914    ///
915    /// Redis 8.4, and the reason it exists is `IFDEQ`: a client that wants to
916    /// compare and swap against a large value sends eight bytes instead of the
917    /// value. `None` is a key that is not there, which is a nil reply.
918    pub fn digest(&mut self, key: &[u8]) -> Result<Option<u64>> {
919        self.reap(key);
920        self.string_only(key)?;
921        // The digest is over the value, so a demoted one has to be read back.
922        // Warmed and not thawed: a client polling a digest to see whether a
923        // large value has changed is exactly the read the doorkeeper is for.
924        self.warm(key)?;
925        Ok(self.peek(key).map(|v| v.digest()))
926    }
927
928    /// `INCREX key [BYINT n|BYFLOAT f] [SATURATE] [LBOUND l] [UBOUND u]
929    /// [EX s|PX ms|EXAT s|PXAT ms|PERSIST] [ENX]`.
930    ///
931    /// Redis 8.8, and the first Redis primitive that implements a workload
932    /// rather than a data structure. What it replaces is `INCR` followed by
933    /// `EXPIRE`, which is two round trips, or a Lua script, which is one round
934    /// trip and a script cache.
935    ///
936    /// The rate limiter is `INCREX key EX window ENX`: the counter goes up, and
937    /// the window is started only when the key had no deadline, so a burst
938    /// inside one window expires together at the deadline the first call set
939    /// rather than each call pushing it out. The quota counter is `UBOUND`
940    /// without `SATURATE`, which refuses rather than clamping and reports zero
941    /// applied. The stock level is `LBOUND 0 SATURATE`, which takes what it can.
942    ///
943    /// A refused increment writes nothing at all: it does not create the key and
944    /// it does not touch the deadline of a key that was there.
945    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                // Stored as text and never as an integer, for the same reason
992                // `INCRBYFLOAT` is: Redis reports `embstr` afterwards even when
993                // the number came out whole.
994                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    /// `LCS key1 key2`, the longest common subsequence itself.
1003    ///
1004    /// A key that is not there is the empty string, which is Redis's reading and
1005    /// not an error.
1006    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    /// `LCS key1 key2 LEN`.
1012    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    /// `LCS key1 key2 IDX [MINMATCHLEN n]`.
1018    ///
1019    /// `WITHMATCHLEN` is not a parameter here because every run comes back with
1020    /// its length attached. Whether that length reaches the client is the reply
1021    /// writer's decision and not the store's.
1022    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    /// Both values as bytes, for the one command that needs two keys at once.
1028    ///
1029    /// Copied rather than borrowed, which is the only place in this file that
1030    /// copies a value it did not have to. `LCS` builds a table the size of the
1031    /// product of the two lengths, so a pair of copies is not what makes it
1032    /// expensive, and borrowing both at once through a `&mut self` reap is a
1033    /// fight with the borrow checker for no measurable gain.
1034    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        // One key at a time, because there is one buffer and this needs two
1040        // values. Each is copied out before the next is faulted, which is the
1041        // one place in this file that copies a value it did not have to and it
1042        // was already copying before any of this.
1043        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    // ---------------------------------------------------------------- private
1051
1052    /// The string under `key` without reaping first.
1053    ///
1054    /// Every public read reaps before calling this, so a caller that skips the
1055    /// reap would be reading a value the clock says is gone.
1056    ///
1057    /// A key holding something else answers `None` and not the first few bytes
1058    /// of a slab number read as a string. That is the right answer for `MGET`,
1059    /// which Redis documents as giving nil for a key of the wrong type rather
1060    /// than failing the whole command, and it is not the right answer for `GET`,
1061    /// which is why the readers that owe a `WRONGTYPE` ask
1062    /// [`Keyspace::string_only`] first.
1063    ///
1064    /// A key whose value is on the file has to have been through
1065    /// [`Keyspace::warm`] or [`Keyspace::thaw`] before this is called, because
1066    /// this reads a served value out of the database's one buffer and nothing
1067    /// in the buffer says whose value it is. A debug build asserts it. On a
1068    /// database with no file behind it there are no cold records and this is
1069    /// exactly what it always was.
1070    #[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    /// Fail with `WRONGTYPE` if `key` holds something that is not a string.
1080    ///
1081    /// A missing key passes, because every string command treats a missing key
1082    /// as an empty one and none of them care what type it is not.
1083    ///
1084    /// The early return is the point. A database with no sets, no hashes and no
1085    /// lists in it cannot be holding the wrong type under any key, so the check
1086    /// is one branch on a counter this struct already has in cache, and no
1087    /// lookup at all. Once one set exists every string command pays a lookup it
1088    /// did not pay before, which is the cost of being able to say no.
1089    ///
1090    /// [`Keyspace::count`] does not use this and reads the kind out of the
1091    /// record its own probe returned instead. Both are correct and the reason
1092    /// for the difference is measured rather than stylistic: `INCR` runs in
1093    /// eighteen nanoseconds and the branch here cost it one and a half of them,
1094    /// where inside the probe the byte is already loaded and it costs nothing.
1095    /// Every other writer is long enough that it does not show, so they take the
1096    /// version that reads as one line.
1097    #[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    /// Store `val` under `key`, choosing the encoding from the bytes.
1109    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    /// Store `val` under `key` as text, choosing `embstr` or `raw` by length
1119    /// but never int encoding it.
1120    ///
1121    /// This is what the float counters do. `INCRBYFLOAT k 1` on `5` leaves `6`,
1122    /// and a real server reports `embstr` for it and not `int`, because the
1123    /// result went through Redis's own formatter and straight into a string
1124    /// object without being offered to `tryObjectEncoding`.
1125    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    /// Store `val` under `key` as a `raw` string whatever its length.
1139    ///
1140    /// `APPEND` and `SETRANGE` both leave `raw` behind in Redis even for a four
1141    /// byte result, because they build the value with `sdscatlen` and the
1142    /// object never goes back through the encoder. `OBJECT ENCODING` is tested
1143    /// on exactly that.
1144    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    /// Store an integer the caller already has, without formatting it first.
1153    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    /// `millis` from now, as an absolute unix millisecond.
1162    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/// Add or subtract, refusing to wrap.
1171#[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/// Refuse a key or a value this band cannot hold.
1182///
1183/// Not string only. The key limit is the keyspace's and applies to every type,
1184/// and a set member is held the same way a string is, so [`crate::sets`] checks
1185/// against this rather than growing a second copy of the same two numbers.
1186#[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
1204/// Turn Redis's inclusive, possibly negative range into a half open one.
1205///
1206/// Returns `None` when the range selects nothing, which the caller answers with
1207/// the empty string.
1208fn 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    // The end is inclusive, so one past it is where the slice stops.
1216    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    /// A store on a fixed clock, so expiry is a function of what the test does
1235    /// and not of how long the test takes to run.
1236    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        // What APPEND leaves behind is raw even though it reads as a number.
1281        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        // A key that is not there is not equal to anything.
1320        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        // Int encoded, so the comparison is against the digits and not the bytes
1332        // in the record, and "042" is not "42".
1333        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        // Refused by NX, and still reports what is there.
1359        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        // The command in the message is the one that was called, lower cased,
1397        // even though `SETEX` hands the milliseconds to the same body `PSETEX`
1398        // uses.
1399        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        // Plain GETEX leaves the deadline alone.
1421        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        // PERSIST clears it.
1430        assert!(s.getex(b"k", Expire::Clear).expect("a string").is_some());
1431        assert_eq!(s.expire_at(b"k"), None);
1432        // And a new deadline replaces it.
1433        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    /// `APPEND` in a loop is how a client writes a log into one key, so the
1513    /// copy of the old value it has to make must not be a fresh `Vec` every
1514    /// time. The value keeps growing here, so the scratch buffer and the index
1515    /// are both still allowed to grow, which is why this counts a ceiling rather
1516    /// than zero. Before the scratch buffer it was a hundred and change.
1517    #[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    /// The same claim for `SETRANGE`, which is easier to state because the value
1534    /// does not grow: writing over the same five bytes of the same key a hundred
1535    /// times has nothing left to allocate for.
1536    #[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    /// `EXPIRE` on a string rewrites the record, which means holding the value
1551    /// while it does. A cache that sets a deadline on every write sends as many
1552    /// of these as it does `SET`.
1553    #[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        // Far enough out that the key is still there at the end. A deadline in
1558        // the past is reaped, and a reaped key is a different test.
1559        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                // A different deadline each time, because the same one is a no
1564                // op that never reaches the rewrite.
1565                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        // A start past the end, and a range that runs backwards, are both empty.
1602        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        // An int encoded value ranges over its digits.
1606        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        // The refused increment left the value alone.
1627        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        // Appending onto an existing key leaves a raw string, which INCR still
1634        // counts. Appending onto a key that is not there does not, because
1635        // Redis runs the new value through tryObjectEncoding on create.
1636        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        // A leading zero is not a number to string2ll, so it is not one here.
1647        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        // Subtracting i64::MIN is the case negating first would get wrong.
1665        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        // Past the deadline, the counter starts again from zero and the key has
1677        // no deadline any more.
1678        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    /// The gate is about this path, so it gets its own test: incrementing an int
1685    /// encoded value must not touch the arena at all.
1686    #[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        // A whole result is still stored as a string, never as an integer.
1709        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        // An increment that cannot land anywhere is reported as the sum it
1718        // would have produced, which is the sentence a real server sends and
1719        // not the one about the argument.
1720        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        // And the key it could not increment is left as it was.
1729        assert_eq!(got(&mut s, b"k").as_deref(), Some(&b"10.6"[..]));
1730    }
1731
1732    /// An int encoded value takes the other arm of the read in `incrbyfloat`,
1733    /// which converts rather than formatting the digits and parsing them back.
1734    /// Both arms have to reach the same double or the same command answers two
1735    /// different things depending on how the value happened to be stored.
1736    #[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            // `APPEND` of nothing leaves the same bytes in a record that is no
1742            // longer int encoded, which is the only way to get the two arms
1743            // looking at one value.
1744            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    /// `INCRBYFLOAT` used to copy the value out of the record so it could parse
1757    /// it, and then throw the copy away.
1758    #[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    /// `SET ... GET` used to hand the old value back as a `Vec` that the wire
1773    /// writes once and drops.
1774    #[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        // And the owning version still answers what it always did.
1793        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        // The condition is over the whole set. One key present is enough to
1842        // stop NX, and one key missing is enough to stop XX, and neither
1843        // writes anything on the way to finding out.
1844        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        // KEEPTTL leaves each key whatever it had, which here is one with a
1861        // deadline and one without.
1862        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        // With no expiration option at all it clears, the way plain SET does.
1871        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        // A key that is not there has nothing to delete, including under the
1898        // conditions a missing key satisfies.
1899        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        // Int encoded, so the compare is against the digits.
1905        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        // SET IFNE on a key that is not there stores, because a key that is
1914        // not there is not equal to anything.
1915        assert!(
1916            s.set(b"m", b"v", SetOptions::PLAIN.if_not_equal(b"other"))
1917                .unwrap()
1918                .stored
1919        );
1920        // The digest forms are the value forms with the value hashed.
1921        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        // An expiration option sets one, and a later plain call keeps it.
1951        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        // PERSIST drops it.
1957        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        // The window starts on the call that found no deadline, and every call
1966        // inside it leaves the deadline where the first one put it.
1967        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        // Past the deadline the counter and the window both start again.
1979        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        // The same increment with SATURATE lands on the bound and does create
2002        // it, which is the difference a client tells by the second number.
2003        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        // A refusal on a key that was already there leaves its deadline alone.
2008        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        // An int encoded key counted in floats stops being int encoded, which
2025        // is what a real server reports afterwards.
2026        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        // An int encoded value is compared as its digits.
2052        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        // The clock is the system one, so it is somewhere after 2020.
2081        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        // One key expires, so the counter has something in it to check.
2098        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        // Back to what a fresh store costs, rather than an arena still the size
2108        // of what used to be in it.
2109        assert_eq!(s.memory_bytes(), empty);
2110        // The expiry counter is not reset, because Redis does not reset it
2111        // either. Emptying a database is not expiring anything.
2112        assert_eq!(s.expired_keys(), 1);
2113
2114        // And it still works afterwards.
2115        s.set_plain(b"after", b"v").unwrap();
2116        assert_eq!(got(&mut s, b"after").as_deref(), Some(&b"v"[..]));
2117    }
2118}