1use crate::list_seg::{SEG_PROMOTE, SegListData};
10#[cfg(not(feature = "std"))]
11use crate::nostd_prelude::*;
12use crate::small_list::{self, PushResult, SmallListData};
13use crate::util::{norm_index, range_bounds};
14use crate::value::{ListData, SmallBytes, Value, list_item_weight};
15use crate::{Entry, Store, StoreError};
16use alloc::sync::Arc;
17
18fn push_inline(slot: &mut Value, v: &[u8], front: bool) -> bool {
27 let Value::SmallListInline(s) = slot else { return false };
28 let push = if front { s.try_push_front(v) } else { s.try_push_back(v) };
29 match push {
30 PushResult::Pushed => false,
31 PushResult::NoRoom => {
32 let mut promoted = small_list::promote(s);
33 if front {
34 promoted.push_front(v.to_vec());
35 } else {
36 promoted.push_back(v.to_vec());
37 }
38 *slot = Value::List(Arc::new(promoted));
39 true
40 }
41 }
42}
43
44impl Store {
45 fn list_mut(&mut self, key: &[u8], create: bool) -> Result<Option<&mut ListData>, StoreError> {
53 if self.live_entry_mut(key).is_none() {
54 if !create {
55 return Ok(None);
56 }
57 self.insert_entry(
58 SmallBytes::from_slice(key),
59 Entry::new(Value::List(Arc::default()), None),
60 );
61 }
62 let is_inline =
65 matches!(self.map.get(key).map(|e| &e.value), Some(Value::SmallListInline(_)));
66 if is_inline {
67 let promoted = {
68 let e = self.map.get(key).expect("present");
69 if let Value::SmallListInline(s) = &e.value {
70 small_list::promote(s)
71 } else {
72 unreachable!()
73 }
74 };
75 self.map.get_mut(key).expect("present").value = Value::List(Arc::new(promoted));
76 self.reweigh_entry(key);
77 }
78 match &mut self.map.get_mut(key).expect("present").value {
79 Value::List(l) => Ok(Some(Arc::make_mut(l))),
80 _ => Err(StoreError::WrongType),
81 }
82 }
83
84 fn is_seglist(&mut self, key: &[u8]) -> bool {
87 matches!(self.live_entry_mut(key).map(|e| &e.value), Some(Value::SegList(_)))
88 }
89
90 fn seglist_mut(&mut self, key: &[u8]) -> &mut SegListData {
95 match &mut self.map.get_mut(key).expect("is_seglist checked").value {
96 Value::SegList(l) => Arc::make_mut(l),
97 _ => unreachable!("is_seglist checked"),
98 }
99 }
100
101 fn list_value_for_push(&mut self, key: &[u8]) -> Result<Option<&mut Value>, StoreError> {
104 match self.live_entry_mut(key) {
105 None => Ok(None),
106 Some(e) => match &e.value {
107 Value::List(_) | Value::SegList(_) | Value::SmallListInline(_) => {
108 Ok(Some(&mut e.value))
109 }
110 _ => Err(StoreError::WrongType),
111 },
112 }
113 }
114
115 fn drop_if_empty_list(&mut self, key: &[u8]) {
117 let empty = match self.map.get(key).map(|e| &e.value) {
118 Some(Value::List(l)) => l.is_empty(),
119 Some(Value::SegList(l)) => l.is_empty(),
120 Some(Value::SmallListInline(l)) => l.is_empty(),
121 _ => false,
122 };
123 if empty {
124 self.remove_entry(key);
125 }
126 }
127
128 fn list_len(&self, key: &[u8]) -> usize {
131 match self.map.get(key).map(|e| &e.value) {
132 Some(Value::List(l)) => l.len(),
133 Some(Value::SegList(l)) => l.len(),
134 Some(Value::SmallListInline(l)) => l.len(),
135 _ => 0,
136 }
137 }
138
139 pub fn lpush(&mut self, key: &[u8], values: &[&[u8]]) -> Result<usize, StoreError> {
141 if values.is_empty() {
142 return Ok(self.list_len(key));
143 }
144 let mut delta: i64 = 0;
145 for v in values {
146 delta += self.list_push_one(key, v, true)?;
147 }
148 self.account_delta(key, delta);
149 Ok(self.list_len(key))
150 }
151
152 pub fn rpush(&mut self, key: &[u8], values: &[&[u8]]) -> Result<usize, StoreError> {
154 if values.is_empty() {
155 return Ok(self.list_len(key));
156 }
157 let mut delta: i64 = 0;
158 for v in values {
159 delta += self.list_push_one(key, v, false)?;
160 }
161 self.account_delta(key, delta);
162 Ok(self.list_len(key))
163 }
164
165 fn list_push_one(&mut self, key: &[u8], v: &[u8], front: bool) -> Result<i64, StoreError> {
169 if self.list_value_for_push(key)?.is_none() {
170 return Ok(self.list_push_create(key, v));
171 }
172 let slot = self.list_value_for_push(key)?.expect("present and a list");
173 if matches!(slot, Value::SmallListInline(_)) {
174 if push_inline(slot, v, front) {
177 self.reweigh_entry(key);
178 }
179 return Ok(0);
180 }
181 let reweigh = match slot {
182 Value::List(l) if l.len() >= SEG_PROMOTE => {
183 promote_flat_to_seg(slot, v, front);
184 true
185 }
186 Value::List(l) => {
187 let l = Arc::make_mut(l);
188 if front {
189 l.push_front(v.to_vec())
190 } else {
191 l.push_back(v.to_vec())
192 }
193 return Ok(list_item_weight(v.len()) as i64);
194 }
195 Value::SegList(l) => {
196 let l = Arc::make_mut(l);
197 if front {
198 l.push_front(v.to_vec())
199 } else {
200 l.push_back(v.to_vec())
201 }
202 return Ok(list_item_weight(v.len()) as i64);
203 }
204 _ => return Err(StoreError::WrongType),
205 };
206 if reweigh {
207 self.reweigh_entry(key);
208 }
209 Ok(0)
210 }
211
212 fn list_push_create(&mut self, key: &[u8], v: &[u8]) -> i64 {
215 if let Some(inline) = SmallListData::with_one(v) {
216 self.insert_entry(
217 SmallBytes::from_slice(key),
218 Entry::new(Value::SmallListInline(inline), None),
219 );
220 0
221 } else {
222 let mut d = alloc::collections::VecDeque::with_capacity(1);
223 d.push_back(v.to_vec());
224 self.insert_entry(
225 SmallBytes::from_slice(key),
226 Entry::new(Value::List(Arc::new(d)), None),
227 );
228 0
229 }
230 }
231
232 fn list_pop(
234 &mut self,
235 key: &[u8],
236 count: usize,
237 front: bool,
238 ) -> Result<Vec<Vec<u8>>, StoreError> {
239 if matches!(self.map.get(key).map(|e| &e.value), Some(Value::SmallListInline(_))) {
242 self.promote_list_inline_to_heap(key);
243 }
244 let (out, delta) = {
245 let mut o = Vec::new();
246 let mut d: i64 = 0;
247 if self.is_seglist(key) {
248 let l = self.seglist_mut(key);
249 for _ in 0..count {
250 let popped = if front { l.pop_front() } else { l.pop_back() };
251 match popped {
252 Some(v) => {
253 d -= list_item_weight(v.len()) as i64;
254 o.push(v);
255 }
256 None => break,
257 }
258 }
259 } else if let Some(l) = self.list_mut(key, false)? {
260 for _ in 0..count {
261 let popped = if front { l.pop_front() } else { l.pop_back() };
262 match popped {
263 Some(v) => {
264 d -= list_item_weight(v.len()) as i64;
265 o.push(v);
266 }
267 None => break,
268 }
269 }
270 }
271 (o, d)
272 };
273 self.account_delta(key, delta);
274 self.drop_if_empty_list(key);
275 Ok(out)
276 }
277
278 pub fn lpop(&mut self, key: &[u8], count: usize) -> Result<Vec<Vec<u8>>, StoreError> {
280 self.list_pop(key, count, true)
281 }
282
283 pub fn rpop(&mut self, key: &[u8], count: usize) -> Result<Vec<Vec<u8>>, StoreError> {
285 self.list_pop(key, count, false)
286 }
287
288 fn promote_list_inline_to_heap(&mut self, key: &[u8]) {
292 let needs = matches!(self.map.get(key).map(|e| &e.value), Some(Value::SmallListInline(_)));
293 if !needs {
294 return;
295 }
296 let Some(e) = self.map.get_mut(key) else { return };
297 if let Value::SmallListInline(s) = &e.value {
298 let promoted = small_list::promote(s);
299 e.value = Value::List(Arc::new(promoted));
300 }
301 self.reweigh_entry(key);
302 }
303
304 pub fn lset(&mut self, key: &[u8], idx: i64, val: &[u8]) -> Result<(), StoreError> {
306 self.promote_list_inline_to_heap(key);
307 let delta = if self.is_seglist(key) {
308 let l = self.seglist_mut(key);
309 let i = norm_index(idx, l.len()).ok_or(StoreError::OutOfRange)?;
310 let old = l.set(i, val.to_vec());
311 val.len() as i64 - old.len() as i64
312 } else {
313 let l = self.list_mut(key, false)?.ok_or(StoreError::NoSuchKey)?;
314 let i = norm_index(idx, l.len()).ok_or(StoreError::OutOfRange)?;
315 let old_len = l[i].len() as i64;
316 l[i] = val.to_vec();
317 val.len() as i64 - old_len
318 };
319 self.account_delta(key, delta);
320 Ok(())
321 }
322
323 pub fn linsert(
332 &mut self,
333 key: &[u8],
334 before: bool,
335 pivot: &[u8],
336 val: &[u8],
337 ) -> Result<i64, StoreError> {
338 self.promote_list_inline_to_heap(key);
339 let (result, delta) = if self.is_seglist(key) {
340 let l = self.seglist_mut(key);
341 let Some(idx) = l.position(pivot) else {
342 return Ok(-1);
343 };
344 let insert_at = if before { idx } else { idx + 1 };
345 l.insert(insert_at, val.to_vec());
346 (l.len() as i64, list_item_weight(val.len()) as i64)
347 } else {
348 match self.list_mut(key, false)? {
349 None => return Ok(0),
350 Some(l) => {
351 let Some(idx) = l.iter().position(|v| v.as_slice() == pivot) else {
352 return Ok(-1);
353 };
354 let insert_at = if before { idx } else { idx + 1 };
355 l.insert(insert_at, val.to_vec());
356 (l.len() as i64, list_item_weight(val.len()) as i64)
357 }
358 }
359 };
360 self.account_delta(key, delta);
361 Ok(result)
362 }
363
364 pub fn lrem(&mut self, key: &[u8], count: i64, val: &[u8]) -> Result<usize, StoreError> {
366 self.promote_list_inline_to_heap(key);
367 let (removed, delta) = if self.is_seglist(key) {
368 self.seglist_mut(key).remove_occurrences(val, count)
369 } else {
370 match self.list_mut(key, false)? {
371 None => (0, 0),
372 Some(l) => flat_lrem(l, count, val),
373 }
374 };
375 self.account_delta(key, delta);
376 self.drop_if_empty_list(key);
377 Ok(removed)
378 }
379
380 pub fn ltrim(&mut self, key: &[u8], start: i64, stop: i64) -> Result<(), StoreError> {
382 self.promote_list_inline_to_heap(key);
383 let delta = if self.is_seglist(key) {
384 let l = self.seglist_mut(key);
385 match range_bounds(start, stop, l.len()) {
386 None => l.clear(),
387 Some((s, e)) => l.trim_to(s, e),
388 }
389 } else if let Some(l) = self.list_mut(key, false)? {
390 match range_bounds(start, stop, l.len()) {
391 None => {
392 let d = -(l.iter().map(|v| list_item_weight(v.len()) as i64).sum::<i64>());
393 l.clear();
394 d
395 }
396 Some((s, e)) => {
397 let mut d: i64 = 0;
398 for v in l.iter().skip(e + 1) {
399 d -= list_item_weight(v.len()) as i64;
400 }
401 l.drain(e + 1..);
402 for v in l.iter().take(s) {
403 d -= list_item_weight(v.len()) as i64;
404 }
405 l.drain(..s);
406 d
407 }
408 }
409 } else {
410 0
411 };
412 self.account_delta(key, delta);
413 self.drop_if_empty_list(key);
414 Ok(())
415 }
416}
417
418fn promote_flat_to_seg(slot: &mut Value, v: &[u8], front: bool) {
422 let flat = match core::mem::replace(slot, Value::Int(0)) {
423 Value::List(a) => Arc::try_unwrap(a).unwrap_or_else(|a| (*a).clone()),
424 _ => unreachable!("matched List"),
425 };
426 let mut seg = SegListData::from_flat(flat);
427 if front {
428 seg.push_front(v.to_vec())
429 } else {
430 seg.push_back(v.to_vec())
431 }
432 *slot = Value::SegList(Arc::new(seg));
433}
434
435fn flat_lrem(l: &mut ListData, count: i64, val: &[u8]) -> (usize, i64) {
438 let mut r = 0usize;
439 let mut d: i64 = 0;
440 if count >= 0 {
441 let limit = if count == 0 { usize::MAX } else { count as usize };
442 let mut i = 0;
443 while i < l.len() {
444 if r < limit && l[i] == val {
445 d -= list_item_weight(l[i].len()) as i64;
446 l.remove(i);
447 r += 1;
448 } else {
449 i += 1;
450 }
451 }
452 } else {
453 let limit = (-count) as usize;
454 let mut i = l.len();
455 while i > 0 {
456 i -= 1;
457 if r < limit && l[i] == val {
458 d -= list_item_weight(l[i].len()) as i64;
459 l.remove(i);
460 r += 1;
461 }
462 }
463 }
464 (r, d)
465}