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