1use crate::util::{parse_i64, parse_f64, fmt_num};
4use crate::value::{Value, SmallBytes};
5use crate::{Entry, Store, StoreError, deadline_at, now_ns};
6use std::time::Duration;
7
8impl Store {
9 pub fn set(
17 &mut self,
18 key: &[u8],
19 value: Vec<u8>,
20 expire: Option<Duration>,
21 nx: bool,
22 xx: bool,
23 ) -> bool {
24 self.set_value(key, Value::Str(SmallBytes::from_vec(value)), expire, nx, xx)
25 }
26
27 pub fn set_slice(
33 &mut self,
34 key: &[u8],
35 value: &[u8],
36 expire: Option<Duration>,
37 nx: bool,
38 xx: bool,
39 ) -> bool {
40 self.set_value(key, Value::Str(SmallBytes::from_slice(value)), expire, nx, xx)
41 }
42
43 fn set_value(
44 &mut self,
45 key: &[u8],
46 new_value: Value,
47 expire: Option<Duration>,
48 nx: bool,
49 xx: bool,
50 ) -> bool {
51 let expire_at = expire.map(|d| deadline_at(now_ns(), d));
54 let key_heap = crate::key_heap_bytes_for(key);
55 #[allow(clippy::single_match_else)]
59 let outcome = match self.live_entry_mut(key) {
60 Some(e) => {
67 if nx {
68 return false;
69 }
70 let had_ttl = e.expire_at_ns.is_some();
73 e.value = new_value;
74 e.expire_at_ns = expire_at.and_then(crate::pack_deadline);
75 let new_w = key_heap + e.value.weight();
76 let delta = new_w as i64 - e.weight() as i64;
77 let ttl_delta = i64::from(e.expire_at_ns.is_some()) - i64::from(had_ttl);
78 e.set_weight(new_w);
79 Ok((delta, ttl_delta))
80 }
81 None => {
83 if xx {
84 return false;
85 }
86 Err(Entry::new(new_value, expire_at))
87 }
88 };
89 match outcome {
90 Ok((delta, ttl_delta)) => {
91 self.apply_weight_delta(delta);
92 self.adjust_expires(ttl_delta);
93 }
94 Err(entry) => {
96 self.insert_entry(SmallBytes::from_slice(key), entry);
97 }
98 }
99 true
100 }
101
102 pub fn get(&mut self, key: &[u8]) -> Result<Option<&[u8]>, StoreError> {
103 match self.live_entry(key) {
104 None => Ok(None),
105 Some(e) => match &e.value {
106 Value::Str(v) => Ok(Some(v.as_slice())),
107 _ => Err(StoreError::WrongType),
108 },
109 }
110 }
111
112 pub fn get_shared(&self, key: &[u8]) -> Result<Option<&[u8]>, StoreError> {
120 match self.map.get(key) {
121 None => Ok(None),
122 Some(e) if e.is_expired(self.cached_clock, self.cached_ns) => Ok(None),
123 Some(e) => match &e.value {
124 Value::Str(v) => Ok(Some(v.as_slice())),
125 _ => Err(StoreError::WrongType),
126 },
127 }
128 }
129
130 pub fn strlen(&mut self, key: &[u8]) -> Result<usize, StoreError> {
131 Ok(self.get(key)?.map_or(0, <[u8]>::len))
132 }
133
134 pub fn append(&mut self, key: &[u8], data: &[u8]) -> Result<usize, StoreError> {
135 let outcome = match self.live_entry_mut(key) {
136 Some(e) => match &mut e.value {
137 Value::Str(v) => {
138 let mut owned = std::mem::take(v).into_vec();
140 owned.extend_from_slice(data);
141 let new_len = owned.len();
142 *v = SmallBytes::from_vec(owned);
143 AppendOutcome::Reweigh(new_len)
144 }
145 _ => return Err(StoreError::WrongType),
146 },
147 None => AppendOutcome::Insert,
148 };
149 match outcome {
150 AppendOutcome::Reweigh(new_len) => {
151 self.reweigh_entry(key);
152 Ok(new_len)
153 }
154 AppendOutcome::Insert => {
155 self.insert_entry(
156 SmallBytes::from_slice(key),
157 Entry::new(Value::Str(SmallBytes::from_slice(data)), None),
158 );
159 Ok(data.len())
160 }
161 }
162 }
163
164 pub fn incr_by(&mut self, key: &[u8], delta: i64) -> Result<i64, StoreError> {
166 let outcome = match self.live_entry_mut(key) {
167 Some(e) => match &mut e.value {
168 Value::Str(v) => {
169 let next = parse_i64(v.as_slice())
170 .ok_or(StoreError::NotInteger)?
171 .checked_add(delta)
172 .ok_or(StoreError::Overflow)?;
173 *v = SmallBytes::from_vec(next.to_string().into_bytes());
174 IncrOutcome::Reweigh(next)
175 }
176 _ => return Err(StoreError::WrongType),
177 },
178 None => IncrOutcome::Insert(delta),
180 };
181 match outcome {
182 IncrOutcome::Reweigh(next) => {
183 self.reweigh_entry(key);
184 Ok(next)
185 }
186 IncrOutcome::Insert(next) => {
187 self.insert_entry(
188 SmallBytes::from_slice(key),
189 Entry::new(
190 Value::Str(SmallBytes::from_vec(next.to_string().into_bytes())),
191 None,
192 ),
193 );
194 Ok(next)
195 }
196 }
197 }
198
199 pub fn getset(&mut self, key: &[u8], val: Vec<u8>) -> Result<Option<Vec<u8>>, StoreError> {
202 let old = match self.live_entry(key) {
203 Some(e) => match &e.value {
204 Value::Str(v) => Some(v.to_vec()),
205 _ => return Err(StoreError::WrongType),
206 },
207 None => None,
208 };
209 self.insert_entry(
210 SmallBytes::from_slice(key),
211 Entry::new(Value::Str(SmallBytes::from_vec(val)), None),
212 );
213 Ok(old)
214 }
215
216 pub fn getdel(&mut self, key: &[u8]) -> Result<Option<Vec<u8>>, StoreError> {
218 let is_str = match self.live_entry(key) {
219 None => return Ok(None),
220 Some(e) => matches!(e.value, Value::Str(_)),
221 };
222 if !is_str {
223 return Err(StoreError::WrongType);
224 }
225 match self.remove_entry(key) {
226 Some(Entry {
227 value: Value::Str(v),
228 ..
229 }) => Ok(Some(v.into_vec())),
230 _ => Ok(None),
231 }
232 }
233
234 pub fn incr_by_float(&mut self, key: &[u8], delta: f64) -> Result<Vec<u8>, StoreError> {
236 let outcome = if let Some(e) = self.live_entry_mut(key) { match &mut e.value {
237 Value::Str(v) => {
238 let next = parse_f64(v.as_slice()).ok_or(StoreError::NotFloat)? + delta;
239 if !next.is_finite() {
240 return Err(StoreError::NotFloat);
241 }
242 let bytes = fmt_num(next);
243 *v = SmallBytes::from_slice(&bytes);
244 FloatOutcome::Reweigh(bytes)
245 }
246 _ => return Err(StoreError::WrongType),
247 } } else {
248 if !delta.is_finite() {
250 return Err(StoreError::NotFloat);
251 }
252 FloatOutcome::Insert(fmt_num(delta))
253 };
254 match outcome {
255 FloatOutcome::Reweigh(bytes) => {
256 self.reweigh_entry(key);
257 Ok(bytes)
258 }
259 FloatOutcome::Insert(bytes) => {
260 self.insert_entry(
261 SmallBytes::from_slice(key),
262 Entry::new(Value::Str(SmallBytes::from_slice(&bytes)), None),
263 );
264 Ok(bytes)
265 }
266 }
267 }
268}
269
270enum AppendOutcome {
271 Reweigh(usize),
272 Insert,
273}
274
275enum IncrOutcome {
276 Reweigh(i64),
277 Insert(i64),
278}
279
280enum FloatOutcome {
281 Reweigh(Vec<u8>),
282 Insert(Vec<u8>),
283}