kevy_embedded/
ops_bitmap.rs1use std::io;
8
9#[cfg(not(target_arch = "wasm32"))]
10use crate::replica_glue::ensure_writable;
11use crate::store::{Store, commit_write, store_err};
12
13#[cfg(target_arch = "wasm32")]
14fn ensure_writable(_s: &Store) -> io::Result<()> { Ok(()) }
15
16impl Store {
17 pub fn getbit(&self, key: &[u8], offset: u64) -> io::Result<u8> {
20 self.wshard(key).store.getbit(key, offset).map_err(store_err)
21 }
22
23 pub fn setbit(&self, key: &[u8], offset: u64, value: u8) -> io::Result<u8> {
27 ensure_writable(self)?;
28 let mut g = self.wshard(key);
29 let prev = g.store.setbit(key, offset, value).map_err(store_err)?;
30 let off_str = format!("{offset}");
31 let val_str = format!("{value}");
32 commit_write(&mut g, &[b"SETBIT", key, off_str.as_bytes(), val_str.as_bytes()])?;
33 Ok(prev)
34 }
35
36 pub fn bitcount(&self, key: &[u8], range: Option<(i64, i64)>) -> io::Result<u64> {
40 self.wshard(key).store.bitcount(key, range).map_err(store_err)
41 }
42
43 pub fn bitpos(
47 &self,
48 key: &[u8],
49 bit: u8,
50 range: Option<(i64, i64)>,
51 ) -> io::Result<Option<u64>> {
52 self.wshard(key)
53 .store
54 .bitpos(key, bit, range)
55 .map_err(store_err)
56 }
57
58 pub fn getrange(&self, key: &[u8], start: i64, end: i64) -> io::Result<Vec<u8>> {
61 self.wshard(key)
62 .store
63 .getrange(key, start, end)
64 .map_err(store_err)
65 }
66
67 pub fn setrange(
71 &self,
72 key: &[u8],
73 offset: u64,
74 value: &[u8],
75 ) -> io::Result<usize> {
76 ensure_writable(self)?;
77 let mut g = self.wshard(key);
78 let new_len = g
79 .store
80 .setrange(key, offset, value)
81 .map_err(store_err)?;
82 let off_str = format!("{offset}");
83 commit_write(&mut g, &[b"SETRANGE", key, off_str.as_bytes(), value])?;
84 Ok(new_len)
85 }
86
87 pub fn bitop(
93 &self,
94 op: BitOp,
95 dst: &[u8],
96 srcs: &[&[u8]],
97 ) -> io::Result<usize> {
98 ensure_writable(self)?;
99 if srcs.is_empty() {
100 return Ok(0);
101 }
102 if matches!(op, BitOp::Not) && srcs.len() != 1 {
103 return Err(io::Error::other("BITOP NOT takes exactly one source key"));
104 }
105 let mut srcs_bytes: Vec<Vec<u8>> = Vec::with_capacity(srcs.len());
107 for k in srcs {
108 let v = self.get(k)?.unwrap_or_default();
109 srcs_bytes.push(v);
110 }
111 let max_len = srcs_bytes.iter().map(Vec::len).max().unwrap_or(0);
112 if max_len == 0 {
113 self.del(&[dst])?;
115 return Ok(0);
116 }
117 let out = bitop_combine(op, &srcs_bytes, max_len);
118 self.set(dst, &out)?;
120 Ok(max_len)
121 }
122
123 pub fn time(&self) -> (u64, u32) {
126 let now = std::time::SystemTime::now()
127 .duration_since(std::time::UNIX_EPOCH)
128 .unwrap_or_default();
129 (now.as_secs(), now.subsec_micros())
130 }
131}
132
133fn bitop_combine(op: BitOp, srcs_bytes: &[Vec<u8>], max_len: usize) -> Vec<u8> {
136 let mut out = vec![0u8; max_len];
137 match op {
138 BitOp::Not => {
139 let s = &srcs_bytes[0];
140 for (i, b) in s.iter().enumerate() {
141 out[i] = !b;
142 }
143 for byte in out.iter_mut().skip(s.len()) {
146 *byte = 0xff;
147 }
148 }
149 _ => {
150 let init = match op {
151 BitOp::And => 0xff,
152 BitOp::Or | BitOp::Xor => 0x00,
153 BitOp::Not => unreachable!(),
154 };
155 for byte in out.iter_mut() {
156 *byte = init;
157 }
158 for s in srcs_bytes {
159 for (i, b) in out.iter_mut().enumerate() {
160 let sb = s.get(i).copied().unwrap_or(0);
161 *b = match op {
162 BitOp::And => *b & sb,
163 BitOp::Or => *b | sb,
164 BitOp::Xor => *b ^ sb,
165 BitOp::Not => unreachable!(),
166 };
167 }
168 }
169 }
170 }
171 out
172}
173
174#[derive(Clone, Copy, Debug, PartialEq, Eq)]
176pub enum BitOp {
177 And,
179 Or,
181 Xor,
183 Not,
185}