Skip to main content

yo_kv/
bitmaps.rs

1//! The bitmap commands, which are string commands wearing a different hat.
2//!
3//! A bitmap in Redis is a string, and that is not an implementation detail a
4//! caller can ignore: `SET k "A"` then `GETBIT k 1` answers 1, because `A` is
5//! `0x41` and the second bit from the top of that byte is set. So there is no
6//! bitmap type here either, and everything in this file works on the same
7//! string records [`strings`](crate::strings) writes. The kernels are in
8//! [`bits`]; this is where a key turns into bytes, where a write
9//! is allowed to grow a value and where Redis's edges live.
10//!
11//! Three of those edges are worth stating up front, because all three have been
12//! measured on a real server rather than reasoned about.
13//!
14//! A write always leaves the value `raw`. `SET n 12345` reports `int` and a
15//! `SETBIT n 0 0` that changes nothing at all still reports `raw` afterwards,
16//! because Redis unshares the object before it looks at a bit. A read does not:
17//! `GETBIT n 3` on the same key leaves it `int`. That is why the in place fast
18//! path below only takes a record that is already raw.
19//!
20//! A write creates the key and pads it with zero bytes, even when the bit being
21//! written is zero and the byte is past the end. `SETBIT nokey 0 0` on an empty
22//! database leaves a one byte string behind.
23//!
24//! A `BITFIELD` is checked all the way through before any of it runs, so a bad
25//! field type in the last subcommand leaves the key untouched and, if it was not
26//! there, uncreated. That ordering is the wire layer's to keep, and it is why
27//! [`Keyspace::bitfield`] takes a list of already parsed subcommands rather than
28//! words to parse.
29
30use crate::bits::{self, Field, Op, Overflow};
31use crate::db::Db;
32use crate::keyspace::Keyspace;
33use crate::strings::{STRING_MAX, check_len};
34use crate::value::{self, Kind, Str};
35use yo_common::num::{self, DIGITS_MAX};
36use yo_common::{Code, Error, Result};
37use yo_index::RawMap;
38
39/// What Redis says about an offset that is not a number or is off the end.
40const BAD_BIT_OFFSET: &str = "bit offset is not an integer or out of range";
41/// What Redis says when a write would make a string too long.
42const TOO_LONG: &str = "string exceeds maximum allowed size (proto-max-bulk-len)";
43
44/// The highest bit `SETBIT` and `GETBIT` take.
45///
46/// It is 4 Gi bits, which is 512 MiB, which is Redis's string ceiling. Ours is a
47/// segment and smaller than that, so a write between the two limits is refused
48/// by the length check with the "string exceeds maximum allowed size" sentence
49/// rather than by this one. Both are Redis's own sentences and the boundary
50/// between them is where we diverge.
51pub const BIT_OFFSET_MAX: u64 = 4 * 1024 * 1024 * 1024 - 1;
52
53/// Whether a range's two ends count bytes or bits.
54///
55/// `BITCOUNT` and `BITPOS` both take an optional `BYTE` or `BIT` word after
56/// their two indexes, and both default to `BYTE`. The word is only allowed once
57/// both indexes are there: `BITPOS k 0 5 BIT` is not a bit ranged search from
58/// bit five, it is an error, because `BIT` is read as the end index.
59#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
60pub enum Unit {
61    /// Indexes count bytes. The default.
62    #[default]
63    Byte,
64    /// Indexes count bits.
65    Bit,
66}
67
68/// One `BITFIELD` subcommand.
69#[derive(Debug, Clone, Copy, PartialEq, Eq)]
70pub struct Sub {
71    /// Which of the three it is, and what it carries.
72    pub op: SubOp,
73    /// The width and signedness of the field.
74    pub field: Field,
75    /// Where the field starts, in bits.
76    ///
77    /// The `#n` form a client can send is `n` times the width, and multiplying
78    /// it out is the wire layer's job.
79    pub at: u64,
80    /// What to do if the value will not fit. Ignored by `GET`.
81    pub on: Overflow,
82}
83
84/// The three things a `BITFIELD` subcommand does.
85#[derive(Debug, Clone, Copy, PartialEq, Eq)]
86pub enum SubOp {
87    /// `GET`, which never writes and never creates the key.
88    Get,
89    /// `SET`, answering the value that was there before.
90    Set(i64),
91    /// `INCRBY`, answering the value afterwards.
92    Incr(i64),
93}
94
95impl SubOp {
96    /// Whether this one writes, which is what decides how far the value grows.
97    const fn writes(self) -> bool {
98        !matches!(self, SubOp::Get)
99    }
100}
101
102impl Keyspace {
103    /// `GETBIT key offset`.
104    ///
105    /// A missing key, and any offset past the end of a key that is there, read
106    /// as zero. Nothing is created and nothing is re-encoded.
107    pub fn getbit(&mut self, key: &[u8], offset: u64) -> Result<bool> {
108        if offset > BIT_OFFSET_MAX {
109            return Err(Error::new(Code::Invalid, BAD_BIT_OFFSET));
110        }
111        self.reap(key);
112        self.string_only(key)?;
113        // A bitmap is a string, so it can have been demoted like any other, and
114        // the bit being asked about is somewhere in it. Warmed rather than
115        // thawed: reading a bit out of a cold bitmap is a read like any other
116        // and the doorkeeper decides whether it earns its way back.
117        self.warm(key)?;
118        let mut digits = [0u8; DIGITS_MAX];
119        let bytes = self.bitmap(key, &mut digits);
120        let byte = (offset / 8) as usize;
121        Ok(bytes.get(byte).is_some_and(|b| b & mask(offset) != 0))
122    }
123
124    /// `SETBIT key offset value`, answering the bit that was there before.
125    ///
126    /// The value grows to hold the offset, padded with zero bytes, and keeps
127    /// whatever deadline it had. A key that was not there is created, even when
128    /// the bit being written is zero.
129    pub fn setbit(&mut self, key: &[u8], offset: u64, bit: bool) -> Result<bool> {
130        if offset > BIT_OFFSET_MAX {
131            return Err(Error::new(Code::Invalid, BAD_BIT_OFFSET));
132        }
133        let byte = (offset / 8) as usize;
134        check_len(key, byte + 1)?;
135        self.thaw(key)?;
136        let now = self.clock.now_ms();
137        let hash = RawMap::hash_of(key);
138
139        // The fast path: the key is there, it is raw already, and the byte is
140        // inside it, so the write is one probe and one byte. This is the shape a
141        // bitmap is used in, a fixed size map of ids that was sized once and is
142        // written to for the rest of its life, and it is the only path that does
143        // not touch the arena. The kind check sits inside the probe for the
144        // reason `INCR`'s does: the byte holding it is already loaded here.
145        let mut dead = false;
146        if let Some(rec) = self.map.value_mut_hashed(hash, key) {
147            if value::kind(rec) != Kind::String {
148                return Err(crate::keyspace::wrong_type());
149            }
150            if value::is_expired(rec, now) {
151                dead = true;
152            } else if let Some(b) = value::raw_in_place(rec).and_then(|it| it.get_mut(byte)) {
153                let had = *b & mask(offset) != 0;
154                if bit {
155                    *b |= mask(offset);
156                } else {
157                    *b &= !mask(offset);
158                }
159                return Ok(had);
160            }
161        }
162        if dead {
163            self.drop_key(key);
164            self.expired += 1;
165        }
166
167        // The slow path, which is every first write to a key and every write
168        // that makes it longer. Through the one scratch buffer, the way `APPEND`
169        // and `SETRANGE` go, since the old bytes are needed in hand while
170        // `store_raw` wants the database.
171        let mut bytes = std::mem::take(&mut self.scratch);
172        bytes.clear();
173        let deadline = match self.map.get(key) {
174            Some(rec) => {
175                value::read(rec).write_to(&mut bytes);
176                value::expire_at(rec)
177            }
178            None => None,
179        };
180        if bytes.len() <= byte {
181            bytes.resize(byte + 1, 0);
182        }
183        let had = bytes[byte] & mask(offset) != 0;
184        if bit {
185            bytes[byte] |= mask(offset);
186        } else {
187            bytes[byte] &= !mask(offset);
188        }
189        self.store_raw(key, &bytes, deadline);
190        self.scratch = bytes;
191        Ok(had)
192    }
193
194    /// `BITCOUNT key [start end [BYTE | BIT]]`.
195    ///
196    /// A missing key, an empty string and a range that ends before it starts all
197    /// answer zero. The two indexes may be negative, counting from the end, and
198    /// both are clamped rather than refused.
199    pub fn bitcount(&mut self, key: &[u8], range: Option<(i64, i64, Unit)>) -> Result<u64> {
200        self.reap(key);
201        self.string_only(key)?;
202        self.warm(key)?;
203        let mut digits = [0u8; DIGITS_MAX];
204        let bytes = self.bitmap(key, &mut digits);
205        let Some((start, end, unit)) = range else {
206            return Ok(bits::count(bytes));
207        };
208        match window(bytes.len(), start, end, unit) {
209            Some((from, to)) => Ok(bits::count_range(bytes, from, to)),
210            None => Ok(0),
211        }
212    }
213
214    /// `BITPOS key bit [start [end [BYTE | BIT]]]`.
215    ///
216    /// Answers minus one when there is no such bit, with the one exception Redis
217    /// carved out: looking for a zero with no end index given, over a range that
218    /// is all ones, answers the first bit past the end of the string. The idea is
219    /// that a string is followed by an infinity of zeros unless the caller said
220    /// where to stop. Giving an explicit end turns that back into minus one, and
221    /// so does asking about a range that is empty once it has been clamped.
222    pub fn bitpos(
223        &mut self,
224        key: &[u8],
225        bit: bool,
226        start: Option<i64>,
227        end: Option<i64>,
228        unit: Unit,
229    ) -> Result<i64> {
230        self.reap(key);
231        self.string_only(key)?;
232        self.warm(key)?;
233        let here = self.map.get(key).is_some();
234        let mut digits = [0u8; DIGITS_MAX];
235        let bytes = self.bitmap(key, &mut digits);
236        if bytes.is_empty() {
237            // A missing key is all zeros, so a zero is at bit nought and a one is
238            // nowhere. An empty string that is really there answers minus one
239            // either way, since there is no bit nought to point at.
240            return Ok(if !bit && !here { 0 } else { -1 });
241        }
242        let all = bytes.len() as u64 * 8;
243        let (from, to) = match (start, end) {
244            (None, _) => (0, all),
245            (Some(s), None) => match window(bytes.len(), s, -1, unit) {
246                Some(r) => r,
247                None => return Ok(-1),
248            },
249            (Some(s), Some(e)) => match window(bytes.len(), s, e, unit) {
250                Some(r) => r,
251                None => return Ok(-1),
252            },
253        };
254        match bits::find(bytes, bit, from, to) {
255            Some(at) => Ok(at as i64),
256            None if !bit && end.is_none() => Ok(all as i64),
257            None => Ok(-1),
258        }
259    }
260
261    /// `BITOP op dest src [src ...]`, answering the length of the result.
262    ///
263    /// A result with no bytes in it deletes the destination, and any other
264    /// result creates it whatever it holds, so a `BITOP AND` over sources that
265    /// share nothing leaves a destination full of zero bytes rather than no
266    /// destination at all. Sources that are shorter than the longest read as
267    /// zeros past their end, and a source that is not there reads as empty.
268    ///
269    /// # Panics
270    ///
271    /// If `srcs` is empty, or holds more than one key for [`Op::Not`]. Both are
272    /// refused with a message on the wire before this is called.
273    pub fn bitop<'k, I>(&mut self, op: Op, dest: &[u8], srcs: I) -> Result<usize>
274    where
275        I: Iterator<Item = &'k [u8]> + Clone,
276    {
277        for src in srcs.clone() {
278            self.reap(src);
279            self.string_only(src)?;
280            // Every source at once, so every one of them has to be in memory
281            // rather than in the one buffer a fault serves out of. `BITOP` over
282            // demoted sources brings them back, which is also what a client
283            // running it in a loop wants.
284            self.thaw(src)?;
285        }
286        // The sources have to be copied out before the destination can be
287        // written, since they are borrowed from the map and the write wants the
288        // database back. They go end to end into the scratch buffer with their
289        // boundaries in `rows`, and the result goes on the end of the same
290        // buffer, so a `BITOP` over any number of sources is one buffer and no
291        // allocation past whatever growing that buffer costs.
292        let mut flat = std::mem::take(&mut self.scratch);
293        let mut ends = std::mem::take(&mut self.rows);
294        flat.clear();
295        ends.clear();
296        let mut digits = [0u8; DIGITS_MAX];
297        for src in srcs.clone() {
298            let bytes = self.bitmap(src, &mut digits);
299            flat.extend_from_slice(bytes);
300            ends.push(flat.len());
301        }
302        // As long as the longest source, `NOT` included: complementing a source
303        // cannot make it longer, and there is only ever the one of them.
304        let len = bits::width(parts(&flat, &ends));
305        if len > STRING_MAX {
306            self.scratch = flat;
307            self.rows = ends;
308            return Err(Error::new(Code::Invalid, TOO_LONG));
309        }
310
311        let split = flat.len();
312        flat.resize(split + len, 0);
313        // The sources and the destination are in the same buffer, so they have
314        // to be split apart before one can be read while the other is written.
315        let (read, write) = flat.split_at_mut(split);
316        bits::combine(op, parts(read, &ends), write);
317
318        let outcome = if len == 0 {
319            self.del(dest);
320            Ok(0)
321        } else {
322            self.reap(dest);
323            match self.string_only(dest) {
324                Ok(()) => {
325                    self.store_raw(dest, &flat[split..], None);
326                    Ok(len)
327                }
328                Err(e) => Err(e),
329            }
330        };
331        self.scratch = flat;
332        self.rows = ends;
333        outcome
334    }
335
336    /// `BITFIELD key [subcommand ...]`, answering one reply per subcommand.
337    ///
338    /// A `None` in the answers is the nil an `OVERFLOW FAIL` subcommand gives
339    /// when its value would not fit; that one does not write and the ones around
340    /// it still do. The subcommands are expected to have been checked already,
341    /// which is what makes it safe for this to be the point of no return.
342    ///
343    /// The value grows once, before anything runs, to hold the last bit any
344    /// writing subcommand touches. That happens even if every one of those
345    /// writes then fails its overflow check, which is Redis's behaviour and
346    /// falls out of it growing the string before it looks at the values.
347    pub fn bitfield(&mut self, key: &[u8], ops: &[Sub]) -> Result<Vec<Option<i64>>> {
348        let grow = ops.iter().filter(|s| s.op.writes()).map(reach).max();
349        self.bitfield_with(key, grow, |bytes| {
350            ops.iter().map(|&sub| apply(bytes, sub)).collect()
351        })
352    }
353
354    /// `BITFIELD`, with the subcommands run against the value in place.
355    ///
356    /// This is the form the wire uses. It hands over the bytes and lets the
357    /// caller walk its own arguments a second time, calling [`apply`] on each,
358    /// which is what lets a `BITFIELD` with two hundred subcommands write two
359    /// hundred replies without a list of them existing anywhere.
360    ///
361    /// `grow` is how many bytes the value has to reach, which is the last byte
362    /// any writing subcommand touches, and `None` for a call that only reads.
363    /// The growing happens once and before anything runs, even if every one of
364    /// those writes then fails its overflow check, because that is what Redis
365    /// does: it makes the string long enough while it is looking up the key and
366    /// only then starts on the values. A call that only reads stores nothing,
367    /// which is what keeps `BITFIELD k GET u8 0` from turning an `embstr` into a
368    /// `raw`.
369    pub fn bitfield_with<T>(
370        &mut self,
371        key: &[u8],
372        grow: Option<usize>,
373        run: impl FnOnce(&mut [u8]) -> T,
374    ) -> Result<T> {
375        self.reap(key);
376        self.string_only(key)?;
377        // Every path here materialises the value and most of them write it
378        // back, so this thaws rather than asking the doorkeeper about a value
379        // that is going to be resident when the command ends anyway.
380        self.thaw(key)?;
381        let need = grow.unwrap_or(0);
382        check_len(key, need)?;
383
384        // Every path materialises the value, including the read only one, so
385        // that an int encoded key reads as the digits it prints as.
386        let mut bytes = std::mem::take(&mut self.scratch);
387        bytes.clear();
388        let deadline = match self.map.get(key) {
389            Some(rec) => {
390                value::read(rec).write_to(&mut bytes);
391                value::expire_at(rec)
392            }
393            None => None,
394        };
395        if bytes.len() < need {
396            bytes.resize(need, 0);
397        }
398        let out = run(&mut bytes);
399        if grow.is_some() {
400            self.store_raw(key, &bytes, deadline);
401        }
402        self.scratch = bytes;
403        Ok(out)
404    }
405
406    /// The bytes of a string key, as the bit commands want to see them.
407    ///
408    /// A missing key is empty, which is what every one of these commands treats
409    /// it as. An int encoded key is the digits it would print as, because that
410    /// is the string it is: `SET n 65` then `GETBIT n 1` is asking about the
411    /// character `6`. The digits are written into the caller's buffer so that the
412    /// ordinary case, a raw string, is still a borrow and not a copy.
413    fn bitmap<'a>(&'a self, key: &[u8], digits: &'a mut [u8; DIGITS_MAX]) -> &'a [u8] {
414        match self.peek(key) {
415            None => &[],
416            Some(Str::Bytes(b)) => b,
417            Some(Str::Int(n)) => num::i64_digits(digits, n),
418        }
419    }
420}
421
422impl Db {
423    /// `BITOP op dest src [src ...]` over a database of any width.
424    ///
425    /// Every key on one stripe is that one stripe's `BITOP`, which is every
426    /// `BITOP` on a database of one stripe and every `BITOP` whose keys were
427    /// hash tagged into the same place. That path is the old one, byte for byte.
428    ///
429    /// The rest is the same work with the reads spread out. Every stripe the
430    /// command names is held for the whole of it, the sources are copied into a
431    /// buffer this database owns rather than one a stripe owns, and they are
432    /// combined there and written to whichever stripe the destination is on.
433    /// Held together rather than one after the other, because an operand that
434    /// was written to after it had been read would leave a result that no
435    /// arrangement of these keys ever had.
436    ///
437    /// # Panics
438    ///
439    /// As [`Keyspace::bitop`].
440    pub fn bitop<'k, I>(&self, op: Op, dest: &'k [u8], srcs: I) -> Result<usize>
441    where
442        I: Iterator<Item = &'k [u8]> + Clone,
443    {
444        if let Some(home) = self.one_stripe(std::iter::once(dest).chain(srcs.clone())) {
445            return self.hold_stripe(home).bitop(op, dest, srcs);
446        }
447        // The buffers before the stripes, which is the order every command that
448        // wants both takes them in.
449        let mut spare = self.spare();
450        let spare = &mut *spare;
451        let (flat, ends) = (&mut spare.bytes, &mut spare.rows);
452        flat.clear();
453        ends.clear();
454        let onto = self.stripe_of(dest);
455        let mut held = self
456            .hold_many(std::iter::once(onto).chain(srcs.clone().map(|src| self.stripe_of(src))));
457        for src in srcs.clone() {
458            let stripe = held.stripe_mut(self.stripe_of(src));
459            stripe.reap(src);
460            stripe.string_only(src)?;
461            stripe.thaw(src)?;
462        }
463        let mut digits = [0u8; DIGITS_MAX];
464        for src in srcs.clone() {
465            let bytes = held.stripe(self.stripe_of(src)).bitmap(src, &mut digits);
466            flat.extend_from_slice(bytes);
467            ends.push(flat.len());
468        }
469        let len = bits::width(parts(flat, ends));
470        if len > STRING_MAX {
471            return Err(Error::new(Code::Invalid, TOO_LONG));
472        }
473
474        let split = flat.len();
475        flat.resize(split + len, 0);
476        let (read, write) = flat.split_at_mut(split);
477        bits::combine(op, parts(read, ends), write);
478
479        if len == 0 {
480            held.stripe_mut(onto).del(dest);
481            return Ok(0);
482        }
483        let stripe = held.stripe_mut(onto);
484        stripe.reap(dest);
485        stripe.string_only(dest)?;
486        stripe.store_raw(dest, &flat[split..], None);
487        Ok(len)
488    }
489}
490
491/// The sources of a `BITOP`, out of the buffer they were copied into.
492///
493/// The boundaries are the end of each source, so the first one starts at nought
494/// and each of the others starts where the one before it ended. Written as a
495/// zip over two views of the same list rather than as a running offset, because
496/// the iterator has to be cloneable and a clone of a running offset would carry
497/// whatever the original had reached.
498fn parts<'a>(flat: &'a [u8], ends: &'a [usize]) -> impl Iterator<Item = &'a [u8]> + Clone {
499    std::iter::once(0)
500        .chain(ends.iter().copied())
501        .zip(ends.iter().copied())
502        .map(|(from, to)| &flat[from..to])
503}
504
505/// Run one subcommand against a value, answering what the client is owed.
506///
507/// `None` is the nil an `OVERFLOW FAIL` subcommand gives when its value would
508/// not fit; that one writes nothing and the ones around it still do. A `SET`
509/// answers what was there before and an `INCRBY` answers what is there now,
510/// which is not symmetry anybody would have chosen but is what Redis does.
511///
512/// The bytes have to be long enough already, which is [`reach`]'s job.
513#[must_use]
514pub fn apply(bytes: &mut [u8], sub: Sub) -> Option<i64> {
515    let had = bits::get(bytes, sub.at, sub.field);
516    match sub.op {
517        SubOp::Get => Some(had),
518        SubOp::Set(val) => bits::setting(sub.field, val, sub.on).map(|next| {
519            bits::set(bytes, sub.at, sub.field, next);
520            had
521        }),
522        SubOp::Incr(by) => bits::adding(sub.field, had, by, sub.on).inspect(|&next| {
523            bits::set(bytes, sub.at, sub.field, next);
524        }),
525    }
526}
527
528/// How many bytes a value needs before `sub` can be written into it.
529#[must_use]
530pub const fn reach(sub: &Sub) -> usize {
531    (sub.field.last_bit(sub.at) / 8 + 1) as usize
532}
533
534/// The bit `offset` names inside its byte.
535///
536/// Bit zero is the top bit, which is the convention all of these commands use.
537#[inline]
538const fn mask(offset: u64) -> u8 {
539    0x80 >> (offset % 8)
540}
541
542/// A start and end index turned into a half open range of bits.
543///
544/// `None` for a range that holds nothing, which is what an empty value, an
545/// out of range start or a backwards range all come to. Negative indexes count
546/// from the end and both ends are clamped, so `BITCOUNT k -100 100` over a three
547/// byte string is the whole string rather than an error.
548fn window(len: usize, start: i64, end: i64, unit: Unit) -> Option<(u64, u64)> {
549    let items = match unit {
550        Unit::Byte => len as i64,
551        Unit::Bit => (len as i64).checked_mul(8)?,
552    };
553    if items == 0 {
554        return None;
555    }
556    // The two ends are not clamped the same way, and the difference is what
557    // makes `BITCOUNT k 10 20` over a three byte string answer zero rather than
558    // counting its last byte. A negative index counts back from the end and
559    // stops at the front, the end index is pulled back to the last item, and a
560    // start past the last item is left where it is so that the range comes out
561    // backwards and is thrown away below.
562    let back = |i: i64| if i < 0 { (items + i).max(0) } else { i };
563    let (from, to) = (back(start), back(end).min(items - 1));
564    if from > to {
565        return None;
566    }
567    let scale = match unit {
568        Unit::Byte => 8,
569        Unit::Bit => 1,
570    };
571    Some(((from * scale) as u64, ((to + 1) * scale) as u64))
572}
573
574/// The largest value a bit range can name, for a caller checking its own limit.
575///
576/// Nothing here uses it; it is the ceiling [`STRING_MAX`] imposes expressed in
577/// bits, which is what a client asking "how big can this bitmap be" wants.
578#[must_use]
579pub const fn max_bits() -> u64 {
580    STRING_MAX as u64 * 8
581}
582
583#[cfg(test)]
584mod tests {
585    use super::*;
586    use crate::keyspace::Keyspace;
587
588    fn db() -> Keyspace {
589        Keyspace::new()
590    }
591
592    /// The source list `bitop` takes, out of the keys a test wants to name.
593    fn keys<'k>(names: &'k [&'k [u8]]) -> impl Iterator<Item = &'k [u8]> + Clone {
594        names.iter().copied()
595    }
596
597    #[test]
598    fn a_bit_is_set_and_read_back() {
599        let mut db = db();
600        assert!(!db.setbit(b"k", 7, true).expect("a bit"));
601        assert!(db.getbit(b"k", 7).expect("a bit"));
602        assert!(!db.getbit(b"k", 6).expect("a bit"));
603        assert_eq!(db.strlen(b"k").expect("a length"), 1);
604        assert_eq!(
605            db.get(b"k").expect("a value").expect("bytes").to_vec(),
606            b"\x01"
607        );
608        // The answer is what was there, not what is there now.
609        assert!(db.setbit(b"k", 7, false).expect("a bit"));
610        assert!(!db.setbit(b"k", 7, false).expect("a bit"));
611    }
612
613    #[test]
614    fn a_write_creates_and_pads_even_when_the_bit_is_zero() {
615        let mut db = db();
616        assert!(!db.setbit(b"k", 0, false).expect("a bit"));
617        assert!(db.exists(b"k"));
618        assert_eq!(db.strlen(b"k").expect("a length"), 1);
619        db.setbit(b"k", 40, true).expect("a bit");
620        assert_eq!(db.strlen(b"k").expect("a length"), 6);
621    }
622
623    #[test]
624    fn a_write_leaves_the_value_raw_and_a_read_does_not() {
625        let mut db = db();
626        db.set_plain(b"n", b"12345").expect("a set");
627        assert_eq!(db.encoding(b"n"), Some(value::Encoding::Int));
628        // Reading a bit out of an int is reading a bit out of its digits.
629        assert!(db.getbit(b"n", 3).expect("a bit"));
630        assert_eq!(db.encoding(b"n"), Some(value::Encoding::Int));
631        // Writing one, even a write that changes nothing, does not leave an int.
632        assert!(!db.setbit(b"n", 0, false).expect("a bit"));
633        assert_eq!(db.encoding(b"n"), Some(value::Encoding::Raw));
634        assert_eq!(
635            db.get(b"n").expect("a value").expect("bytes").to_vec(),
636            b"12345"
637        );
638    }
639
640    #[test]
641    fn a_write_keeps_the_deadline() {
642        let mut db = db();
643        db.setex(b"k", 100, b"abc").expect("a set");
644        db.setbit(b"k", 40, true).expect("a bit");
645        assert_eq!(db.strlen(b"k").expect("a length"), 6);
646        assert!(db.expire_at(b"k").is_some());
647        // And so does the fast path, which does not go near the deadline.
648        db.setbit(b"k", 1, true).expect("a bit");
649        assert!(db.expire_at(b"k").is_some());
650    }
651
652    #[test]
653    fn counting_takes_the_ranges_a_real_server_takes() {
654        let mut db = db();
655        db.set_plain(b"k", b"foobar").expect("a set");
656        let count = |db: &mut Keyspace, r| db.bitcount(b"k", r).expect("a count");
657        assert_eq!(count(&mut db, None), 26);
658        assert_eq!(count(&mut db, Some((0, 0, Unit::Byte))), 4);
659        assert_eq!(count(&mut db, Some((1, 1, Unit::Byte))), 6);
660        assert_eq!(count(&mut db, Some((0, -5, Unit::Byte))), 10);
661        assert_eq!(count(&mut db, Some((5, 30, Unit::Bit))), 17);
662        // Redis's own documentation says 22 for this one. A real 8.10.1 says 25,
663        // and 25 is what counting the first 44 bits of `foobar` by hand gives,
664        // so the documentation is wrong and this is not a divergence.
665        assert_eq!(count(&mut db, Some((0, -5, Unit::Bit))), 25);
666        // Clamped at both ends, empty when it is backwards.
667        assert_eq!(count(&mut db, Some((-100, 100, Unit::Byte))), 26);
668        assert_eq!(count(&mut db, Some((2, 1, Unit::Byte))), 0);
669        assert_eq!(count(&mut db, Some((5, 3, Unit::Bit))), 0);
670        // A start past the end is nothing, not the whole string.
671        assert_eq!(count(&mut db, Some((10, 20, Unit::Byte))), 0);
672        assert_eq!(db.bitcount(b"gone", None).expect("a count"), 0);
673    }
674
675    #[test]
676    fn searching_takes_the_ranges_a_real_server_takes() {
677        let mut db = db();
678        db.set_plain(b"ones", b"\xff\xff\xff").expect("a set");
679        db.set_plain(b"mix", b"\x00\xff\x00").expect("a set");
680        let pos = |db: &mut Keyspace, k: &[u8], bit, s, e| {
681            db.bitpos(k, bit, s, e, Unit::Byte).expect("a position")
682        };
683        assert_eq!(pos(&mut db, b"mix", true, None, None), 8);
684        assert_eq!(pos(&mut db, b"mix", false, None, None), 0);
685        assert_eq!(pos(&mut db, b"mix", true, Some(2), None), -1);
686        assert_eq!(pos(&mut db, b"mix", true, Some(-1), Some(-1)), -1);
687        assert_eq!(pos(&mut db, b"mix", false, Some(-100), None), 0);
688        // The one exception: no end given, all ones, so the answer is the first
689        // bit past the end of the string.
690        assert_eq!(pos(&mut db, b"ones", false, None, None), 24);
691        assert_eq!(pos(&mut db, b"ones", false, Some(-1), None), 24);
692        // An explicit end takes that away again.
693        assert_eq!(pos(&mut db, b"ones", false, Some(0), Some(-1)), -1);
694        assert_eq!(pos(&mut db, b"ones", false, Some(0), Some(100)), -1);
695        // And so does a range that is empty once it has been clamped.
696        assert_eq!(pos(&mut db, b"ones", false, Some(10), None), -1);
697        assert_eq!(pos(&mut db, b"ones", false, Some(3), None), -1);
698        assert_eq!(pos(&mut db, b"ones", true, Some(10), None), -1);
699        assert_eq!(pos(&mut db, b"ones", false, Some(2), Some(1)), -1);
700        assert_eq!(
701            db.bitpos(b"ones", false, Some(5), Some(20), Unit::Bit)
702                .expect("a position"),
703            -1
704        );
705    }
706
707    #[test]
708    fn searching_an_absent_or_empty_key() {
709        let mut db = db();
710        let pos = |db: &mut Keyspace, k: &[u8], bit| {
711            db.bitpos(k, bit, None, None, Unit::Byte)
712                .expect("a position")
713        };
714        // A key that is not there is all zeros, so a zero is at the front.
715        assert_eq!(pos(&mut db, b"gone", false), 0);
716        assert_eq!(pos(&mut db, b"gone", true), -1);
717        // A key that is there and empty has no bits at all.
718        db.set_plain(b"empty", b"").expect("a set");
719        assert_eq!(pos(&mut db, b"empty", false), -1);
720        assert_eq!(pos(&mut db, b"empty", true), -1);
721        assert_eq!(
722            db.bitcount(b"empty", Some((0, -1, Unit::Byte)))
723                .expect("a count"),
724            0
725        );
726    }
727
728    #[test]
729    fn combining_writes_a_destination_and_deletes_an_empty_one() {
730        let mut db = db();
731        db.set_plain(b"a", b"\xf0\x0f\xff").expect("a set");
732        db.set_plain(b"b", b"\xff\x00").expect("a set");
733        let n = db
734            .bitop(Op::And, b"d", keys(&[b"a", b"b"]))
735            .expect("a length");
736        assert_eq!(n, 3);
737        assert_eq!(
738            db.get(b"d").expect("a value").expect("bytes").to_vec(),
739            b"\xf0\x00\x00"
740        );
741        // A destination full of nothing is still a destination.
742        db.set_plain(b"z", b"\x00\x00").expect("a set");
743        let n = db
744            .bitop(Op::And, b"d", keys(&[b"a", b"z"]))
745            .expect("a length");
746        assert_eq!(n, 3);
747        assert!(db.exists(b"d"));
748        // Sources that are all missing take the destination with them.
749        let n = db
750            .bitop(Op::Or, b"d", keys(&[b"no1", b"no2"]))
751            .expect("a length");
752        assert_eq!(n, 0);
753        assert!(!db.exists(b"d"));
754    }
755
756    #[test]
757    fn combining_reads_an_int_key_as_its_digits() {
758        let mut db = db();
759        db.set_plain(b"n", b"12345").expect("a set");
760        db.bitop(Op::Or, b"d", keys(&[b"n"])).expect("a length");
761        assert_eq!(
762            db.get(b"d").expect("a value").expect("bytes").to_vec(),
763            b"12345"
764        );
765    }
766
767    #[test]
768    fn a_field_is_read_written_and_incremented() {
769        let mut db = db();
770        let u8f = Field::new(false, 8).expect("a width");
771        let sub = |op, at| Sub {
772            op,
773            field: u8f,
774            at,
775            on: Overflow::Wrap,
776        };
777        let out = db
778            .bitfield(b"k", &[sub(SubOp::Set(255), 0), sub(SubOp::Get, 0)])
779            .expect("replies");
780        assert_eq!(out, vec![Some(0), Some(255)]);
781        assert_eq!(db.strlen(b"k").expect("a length"), 1);
782
783        let out = db
784            .bitfield(b"k", &[sub(SubOp::Incr(10), 0)])
785            .expect("replies");
786        assert_eq!(out, vec![Some(9)], "wrapped round");
787
788        // A failing write answers nothing and leaves the field alone, and the
789        // subcommands around it still run.
790        let fail = Sub {
791            on: Overflow::Fail,
792            ..sub(SubOp::Incr(250), 0)
793        };
794        let out = db
795            .bitfield(b"k", &[fail, sub(SubOp::Get, 0)])
796            .expect("replies");
797        assert_eq!(out, vec![None, Some(9)]);
798    }
799
800    #[test]
801    fn a_read_only_bitfield_creates_nothing_and_re_encodes_nothing() {
802        let mut db = db();
803        let f = Field::new(true, 16).expect("a width");
804        let get = Sub {
805            op: SubOp::Get,
806            field: f,
807            at: 0,
808            on: Overflow::Wrap,
809        };
810        assert_eq!(
811            db.bitfield(b"gone", &[get]).expect("replies"),
812            vec![Some(0)]
813        );
814        assert!(!db.exists(b"gone"));
815
816        db.set_plain(b"s", b"hello").expect("a set");
817        assert_eq!(db.encoding(b"s"), Some(value::Encoding::Embstr));
818        db.bitfield(b"s", &[get]).expect("replies");
819        assert_eq!(
820            db.encoding(b"s"),
821            Some(value::Encoding::Embstr),
822            "still short"
823        );
824    }
825
826    #[test]
827    fn a_write_grows_the_value_even_when_every_write_fails() {
828        let mut db = db();
829        let f = Field::new(false, 8).expect("a width");
830        let sub = Sub {
831            op: SubOp::Set(300),
832            field: f,
833            at: 64,
834            on: Overflow::Fail,
835        };
836        assert_eq!(db.bitfield(b"k", &[sub]).expect("replies"), vec![None]);
837        assert_eq!(db.strlen(b"k").expect("a length"), 9);
838    }
839
840    #[test]
841    fn a_bit_command_on_the_wrong_type_says_so() {
842        let mut db = db();
843        let member: &[u8] = b"x";
844        db.sadd(b"s", std::iter::once(member)).expect("a member");
845        assert!(db.getbit(b"s", 0).is_err());
846        assert!(db.setbit(b"s", 0, true).is_err());
847        assert!(db.bitcount(b"s", None).is_err());
848        assert!(db.bitpos(b"s", true, None, None, Unit::Byte).is_err());
849        assert!(db.bitop(Op::Or, b"d", keys(&[b"s"])).is_err());
850        let f = Field::new(false, 8).expect("a width");
851        let sub = Sub {
852            op: SubOp::Get,
853            field: f,
854            at: 0,
855            on: Overflow::Wrap,
856        };
857        assert!(db.bitfield(b"s", &[sub]).is_err());
858    }
859
860    #[test]
861    fn an_offset_past_the_end_of_the_world_is_refused() {
862        let mut db = db();
863        assert!(db.setbit(b"k", BIT_OFFSET_MAX + 1, true).is_err());
864        assert!(db.getbit(b"k", BIT_OFFSET_MAX + 1).is_err());
865        // And one inside Redis's limit but outside ours is refused too, with the
866        // other sentence. This is the divergence [`STRING_MAX`] is about.
867        assert!(db.setbit(b"k", BIT_OFFSET_MAX, true).is_err());
868        assert!(max_bits() < BIT_OFFSET_MAX);
869    }
870}