1use anyhow::anyhow;
2use bytemuck::bytes_of;
3use std::{borrow::Borrow, marker::PhantomData, ops::Range, sync::Arc};
4
5use crate::{
6 store::{ReplaceStatus, SetStatus, TYPED_NAMESPACE},
7 CandyStore, ListCompactionParams,
8};
9
10use crate::Result;
11use databuf::{config::num::LE, DecodeOwned, Encode};
12
13pub trait CandyTypedKey: Encode + DecodeOwned {
14 const TYPE_ID: u32;
17}
18
19macro_rules! typed_builtin {
20 ($t:ty, $v:literal) => {
21 impl CandyTypedKey for $t {
22 const TYPE_ID: u32 = $v;
23 }
24 };
25}
26
27typed_builtin!(u8, 1);
28typed_builtin!(u16, 2);
29typed_builtin!(u32, 3);
30typed_builtin!(u64, 4);
31typed_builtin!(u128, 5);
32typed_builtin!(i8, 6);
33typed_builtin!(i16, 7);
34typed_builtin!(i32, 8);
35typed_builtin!(i64, 9);
36typed_builtin!(i128, 10);
37typed_builtin!(bool, 11);
38typed_builtin!(usize, 12);
39typed_builtin!(isize, 13);
40typed_builtin!(char, 14);
41typed_builtin!(String, 15);
42typed_builtin!(Vec<u8>, 16);
43typed_builtin!(uuid::Bytes, 17);
44
45fn from_bytes<T: DecodeOwned>(bytes: &[u8]) -> Result<T> {
46 T::from_bytes::<LE>(bytes).map_err(|e| anyhow!(e))
47}
48
49pub struct CandyTypedStore<K, V> {
60 store: Arc<CandyStore>,
61 _phantom: PhantomData<(K, V)>,
62}
63
64impl<K, V> Clone for CandyTypedStore<K, V> {
65 fn clone(&self) -> Self {
66 Self {
67 store: self.store.clone(),
68 _phantom: Default::default(),
69 }
70 }
71}
72
73impl<K, V> CandyTypedStore<K, V>
74where
75 K: CandyTypedKey,
76 V: Encode + DecodeOwned,
77{
78 pub fn new(store: Arc<CandyStore>) -> Self {
80 Self {
81 store,
82 _phantom: Default::default(),
83 }
84 }
85
86 fn make_key<Q: ?Sized + Encode>(key: &Q) -> Vec<u8>
87 where
88 K: Borrow<Q>,
89 {
90 let mut kbytes = key.to_bytes::<LE>();
91 kbytes.extend_from_slice(bytes_of(&K::TYPE_ID));
92 kbytes.extend_from_slice(TYPED_NAMESPACE);
93 kbytes
94 }
95
96 pub fn contains<Q: ?Sized + Encode>(&self, key: &Q) -> Result<bool>
98 where
99 K: Borrow<Q>,
100 {
101 Ok(self.store.get_raw(&Self::make_key(key))?.is_some())
102 }
103
104 pub fn get<Q: ?Sized + Encode>(&self, key: &Q) -> Result<Option<V>>
106 where
107 K: Borrow<Q>,
108 {
109 let kbytes = Self::make_key(key);
110 if let Some(vbytes) = self.store.get_raw(&kbytes)? {
111 Ok(Some(from_bytes::<V>(&vbytes)?))
112 } else {
113 Ok(None)
114 }
115 }
116
117 pub fn replace<Q1: ?Sized + Encode, Q2: ?Sized + Encode>(
119 &self,
120 key: &Q1,
121 val: &Q2,
122 expected_val: Option<&Q2>,
123 ) -> Result<Option<V>>
124 where
125 K: Borrow<Q1>,
126 V: Borrow<Q2>,
127 {
128 let kbytes = Self::make_key(key);
129 let vbytes = val.to_bytes::<LE>();
130 let ebytes = expected_val.map(|ev| ev.to_bytes::<LE>()).unwrap_or(vec![]);
131 match self
132 .store
133 .replace_raw(&kbytes, &vbytes, expected_val.map(|_| &*ebytes))?
134 {
135 ReplaceStatus::DoesNotExist => Ok(None),
136 ReplaceStatus::PrevValue(v) => Ok(Some(from_bytes::<V>(&v)?)),
137 ReplaceStatus::WrongValue(_) => Ok(None),
138 }
139 }
140
141 pub fn set<Q1: ?Sized + Encode, Q2: ?Sized + Encode>(
143 &self,
144 key: &Q1,
145 val: &Q2,
146 ) -> Result<Option<V>>
147 where
148 K: Borrow<Q1>,
149 V: Borrow<Q2>,
150 {
151 let kbytes = Self::make_key(key);
152 let vbytes = val.to_bytes::<LE>();
153 match self.store.set_raw(&kbytes, &vbytes)? {
154 SetStatus::CreatedNew => Ok(None),
155 SetStatus::PrevValue(v) => Ok(Some(from_bytes::<V>(&v)?)),
156 }
157 }
158
159 pub fn get_or_create<Q1: ?Sized + Encode, Q2: ?Sized + Encode>(
161 &self,
162 key: &Q1,
163 default_val: &Q2,
164 ) -> Result<V>
165 where
166 K: Borrow<Q1>,
167 V: Borrow<Q2>,
168 {
169 let kbytes = Self::make_key(key);
170 Ok(from_bytes::<V>(
171 &self
172 .store
173 .get_or_create_raw(&kbytes, default_val.to_bytes::<LE>())?
174 .value(),
175 )?)
176 }
177
178 pub fn remove<Q: ?Sized + Encode>(&self, k: &Q) -> Result<Option<V>>
180 where
181 K: Borrow<Q>,
182 {
183 let kbytes = Self::make_key(k);
184 if let Some(vbytes) = self.store.remove_raw(&kbytes)? {
185 Ok(Some(from_bytes::<V>(&vbytes)?))
186 } else {
187 Ok(None)
188 }
189 }
190
191 pub fn get_big<Q: ?Sized + Encode>(&self, key: &Q) -> Result<Option<V>>
193 where
194 K: Borrow<Q>,
195 {
196 let kbytes = Self::make_key(key);
197 if let Some(vbytes) = self.store.get_big(&kbytes)? {
198 Ok(Some(from_bytes::<V>(&vbytes)?))
199 } else {
200 Ok(None)
201 }
202 }
203
204 pub fn set_big<Q1: ?Sized + Encode, Q2: ?Sized + Encode>(
206 &self,
207 key: &Q1,
208 val: &Q2,
209 ) -> Result<bool>
210 where
211 K: Borrow<Q1>,
212 V: Borrow<Q2>,
213 {
214 let kbytes = Self::make_key(key);
215 let vbytes = val.to_bytes::<LE>();
216 self.store.set_big(&kbytes, &vbytes)
217 }
218
219 pub fn remove_big<Q: ?Sized + Encode>(&self, k: &Q) -> Result<bool>
221 where
222 K: Borrow<Q>,
223 {
224 let kbytes = Self::make_key(k);
225 self.store.remove_big(&kbytes)
226 }
227}
228
229pub struct CandyTypedList<L, K, V> {
232 store: Arc<CandyStore>,
233 _phantom: PhantomData<(L, K, V)>,
234}
235
236impl<L, K, V> Clone for CandyTypedList<L, K, V> {
237 fn clone(&self) -> Self {
238 Self {
239 store: self.store.clone(),
240 _phantom: Default::default(),
241 }
242 }
243}
244
245impl<L, K, V> CandyTypedList<L, K, V>
246where
247 L: CandyTypedKey,
248 K: Encode + DecodeOwned,
249 V: Encode + DecodeOwned,
250{
251 pub fn new(store: Arc<CandyStore>) -> Self {
253 Self {
254 store,
255 _phantom: PhantomData,
256 }
257 }
258
259 fn make_list_key<Q: ?Sized + Encode>(list_key: &Q) -> Vec<u8>
260 where
261 L: Borrow<Q>,
262 {
263 let mut kbytes = list_key.to_bytes::<LE>();
264 kbytes.extend_from_slice(bytes_of(&L::TYPE_ID));
265 kbytes
266 }
267
268 pub fn contains<Q1: ?Sized + Encode, Q2: ?Sized + Encode>(
270 &self,
271 list_key: &Q1,
272 item_key: &Q2,
273 ) -> Result<bool>
274 where
275 L: Borrow<Q1>,
276 K: Borrow<Q2>,
277 {
278 let list_key = Self::make_list_key(list_key);
279 let item_key = item_key.to_bytes::<LE>();
280 Ok(self
281 .store
282 .owned_get_from_list(list_key, item_key)?
283 .is_some())
284 }
285
286 pub fn get<Q1: ?Sized + Encode, Q2: ?Sized + Encode>(
288 &self,
289 list_key: &Q1,
290 item_key: &Q2,
291 ) -> Result<Option<V>>
292 where
293 L: Borrow<Q1>,
294 K: Borrow<Q2>,
295 {
296 let list_key = Self::make_list_key(list_key);
297 let item_key = item_key.to_bytes::<LE>();
298 if let Some(vbytes) = self.store.owned_get_from_list(list_key, item_key)? {
299 Ok(Some(from_bytes::<V>(&vbytes)?))
300 } else {
301 Ok(None)
302 }
303 }
304
305 fn _set<Q1: ?Sized + Encode, Q2: ?Sized + Encode, Q3: ?Sized + Encode>(
306 &self,
307 list_key: &Q1,
308 item_key: &Q2,
309 val: &Q3,
310 promote: bool,
311 ) -> Result<Option<V>>
312 where
313 L: Borrow<Q1>,
314 K: Borrow<Q2>,
315 V: Borrow<Q3>,
316 {
317 let list_key = Self::make_list_key(list_key);
318 let item_key = item_key.to_bytes::<LE>();
319 let val = val.to_bytes::<LE>();
320 match self
321 .store
322 .owned_set_in_list(list_key, item_key, val, promote)?
323 {
324 SetStatus::CreatedNew => Ok(None),
325 SetStatus::PrevValue(v) => Ok(Some(from_bytes::<V>(&v)?)),
326 }
327 }
328
329 pub fn set<Q1: ?Sized + Encode, Q2: ?Sized + Encode, Q3: ?Sized + Encode>(
331 &self,
332 list_key: &Q1,
333 item_key: &Q2,
334 val: &Q3,
335 ) -> Result<Option<V>>
336 where
337 L: Borrow<Q1>,
338 K: Borrow<Q2>,
339 V: Borrow<Q3>,
340 {
341 self._set(list_key, item_key, val, false)
342 }
343
344 pub fn set_promoting<Q1: ?Sized + Encode, Q2: ?Sized + Encode, Q3: ?Sized + Encode>(
346 &self,
347 list_key: &Q1,
348 item_key: &Q2,
349 val: &Q3,
350 ) -> Result<Option<V>>
351 where
352 L: Borrow<Q1>,
353 K: Borrow<Q2>,
354 V: Borrow<Q3>,
355 {
356 self._set(list_key, item_key, val, true)
357 }
358
359 pub fn get_or_create<Q1: ?Sized + Encode, Q2: ?Sized + Encode, Q3: ?Sized + Encode>(
361 &self,
362 list_key: &Q1,
363 item_key: &Q2,
364 default_val: &Q3,
365 ) -> Result<V>
366 where
367 L: Borrow<Q1>,
368 K: Borrow<Q2>,
369 {
370 let list_key = Self::make_list_key(list_key);
371 let item_key = item_key.to_bytes::<LE>();
372 let default_val = default_val.to_bytes::<LE>();
373 let vbytes = self
374 .store
375 .owned_get_or_create_in_list(list_key, item_key, default_val)?
376 .value();
377 from_bytes::<V>(&vbytes)
378 }
379
380 pub fn replace<Q1: ?Sized + Encode, Q2: ?Sized + Encode, Q3: ?Sized + Encode>(
382 &self,
383 list_key: &Q1,
384 item_key: &Q2,
385 val: &Q3,
386 expected_val: Option<&Q3>,
387 ) -> Result<Option<V>>
388 where
389 L: Borrow<Q1>,
390 K: Borrow<Q2>,
391 V: Borrow<Q3>,
392 {
393 let list_key = Self::make_list_key(list_key);
394 let item_key = item_key.to_bytes::<LE>();
395 let val = val.to_bytes::<LE>();
396 let ebytes = expected_val
397 .map(|ev| ev.to_bytes::<LE>())
398 .unwrap_or_default();
399 match self.store.owned_replace_in_list(
400 list_key,
401 item_key,
402 val,
403 expected_val.map(|_| &*ebytes),
404 )? {
405 ReplaceStatus::DoesNotExist => Ok(None),
406 ReplaceStatus::PrevValue(v) => Ok(Some(from_bytes::<V>(&v)?)),
407 ReplaceStatus::WrongValue(_) => Ok(None),
408 }
409 }
410
411 pub fn remove<Q1: ?Sized + Encode, Q2: ?Sized + Encode>(
413 &self,
414 list_key: &Q1,
415 item_key: &Q2,
416 ) -> Result<Option<V>>
417 where
418 L: Borrow<Q1>,
419 K: Borrow<Q2>,
420 {
421 let list_key = Self::make_list_key(list_key);
422 let item_key = item_key.to_bytes::<LE>();
423 if let Some(vbytes) = self.store.owned_remove_from_list(list_key, item_key)? {
424 Ok(Some(from_bytes::<V>(&vbytes)?))
425 } else {
426 Ok(None)
427 }
428 }
429
430 pub fn iter<'a, Q: ?Sized + Encode>(
432 &'a self,
433 list_key: &Q,
434 ) -> impl Iterator<Item = Result<(K, V)>> + 'a
435 where
436 L: Borrow<Q>,
437 {
438 let list_key = Self::make_list_key(list_key);
439 self.store.owned_iter_list(list_key).map(|res| match res {
440 Err(e) => Err(e),
441 Ok((k, v)) => {
442 let key = from_bytes::<K>(&k)?;
443 let val = from_bytes::<V>(&v)?;
444 Ok((key, val))
445 }
446 })
447 }
448
449 pub fn iter_backwards<'a, Q: ?Sized + Encode>(
451 &'a self,
452 list_key: &Q,
453 ) -> impl Iterator<Item = Result<(K, V)>> + 'a
454 where
455 L: Borrow<Q>,
456 {
457 let list_key = Self::make_list_key(list_key);
458 self.store
459 .owned_iter_list_backwards(list_key)
460 .map(|res| match res {
461 Err(e) => Err(e),
462 Ok((k, v)) => {
463 let key = from_bytes::<K>(&k)?;
464 let val = from_bytes::<V>(&v)?;
465 Ok((key, val))
466 }
467 })
468 }
469
470 pub fn discard<Q: ?Sized + Encode>(&self, list_key: &Q) -> Result<bool>
472 where
473 L: Borrow<Q>,
474 {
475 let list_key = Self::make_list_key(list_key);
476 self.store.owned_discard_list(list_key)
477 }
478
479 pub fn compact_if_needed<Q: ?Sized + Encode>(
481 &self,
482 list_key: &Q,
483 params: ListCompactionParams,
484 ) -> Result<bool>
485 where
486 L: Borrow<Q>,
487 {
488 let list_key = Self::make_list_key(list_key);
489 self.store.compact_list_if_needed(&list_key, params)
490 }
491
492 pub fn pop_tail<Q: ?Sized + Encode>(&self, list_key: &Q) -> Result<Option<(K, V)>>
494 where
495 L: Borrow<Q>,
496 {
497 let list_key = Self::make_list_key(list_key);
498 let Some((k, v)) = self.store.owned_pop_list_tail(list_key)? else {
499 return Ok(None);
500 };
501 Ok(Some((from_bytes::<K>(&k)?, from_bytes::<V>(&v)?)))
502 }
503
504 pub fn pop_head<Q: ?Sized + Encode>(&self, list_key: &Q) -> Result<Option<(K, V)>>
506 where
507 L: Borrow<Q>,
508 {
509 let list_key = Self::make_list_key(list_key);
510 let Some((k, v)) = self.store.owned_pop_list_head(list_key)? else {
511 return Ok(None);
512 };
513 Ok(Some((from_bytes::<K>(&k)?, from_bytes::<V>(&v)?)))
514 }
515
516 pub fn peek_tail<Q: ?Sized + Encode>(&self, list_key: &Q) -> Result<Option<(K, V)>>
518 where
519 L: Borrow<Q>,
520 {
521 let list_key = Self::make_list_key(list_key);
522 let Some((k, v)) = self.store.owned_peek_list_tail(list_key)? else {
523 return Ok(None);
524 };
525 Ok(Some((from_bytes::<K>(&k)?, from_bytes::<V>(&v)?)))
526 }
527
528 pub fn peek_head<Q: ?Sized + Encode>(&self, list_key: &Q) -> Result<Option<(K, V)>>
530 where
531 L: Borrow<Q>,
532 {
533 let list_key = Self::make_list_key(list_key);
534 let Some((k, v)) = self.store.owned_peek_list_head(list_key)? else {
535 return Ok(None);
536 };
537 Ok(Some((from_bytes::<K>(&k)?, from_bytes::<V>(&v)?)))
538 }
539
540 pub fn len<Q: ?Sized + Encode>(&self, list_key: &Q) -> Result<usize>
542 where
543 L: Borrow<Q>,
544 {
545 self.store.owned_list_len(Self::make_list_key(list_key))
546 }
547
548 pub fn retain<Q: ?Sized + Encode>(
550 &self,
551 list_key: &Q,
552 mut func: impl FnMut(&K, &V) -> Result<bool>,
553 ) -> Result<()>
554 where
555 L: Borrow<Q>,
556 {
557 let list_key = Self::make_list_key(list_key);
558 self.store.owned_retain_in_list(list_key, |k, v| {
559 let tk = from_bytes::<K>(&k)?;
560 let tv = from_bytes::<V>(&v)?;
561 func(&tk, &tv)
562 })
563 }
564}
565
566pub struct CandyTypedDeque<L, V> {
569 store: Arc<CandyStore>,
570 _phantom: PhantomData<(L, V)>,
571}
572
573impl<L, V> Clone for CandyTypedDeque<L, V> {
574 fn clone(&self) -> Self {
575 Self {
576 store: self.store.clone(),
577 _phantom: Default::default(),
578 }
579 }
580}
581
582impl<L, V> CandyTypedDeque<L, V>
583where
584 L: CandyTypedKey,
585 V: Encode + DecodeOwned,
586{
587 pub fn new(store: Arc<CandyStore>) -> Self {
588 Self {
589 store,
590 _phantom: Default::default(),
591 }
592 }
593
594 pub fn push_head<Q1: ?Sized + Encode, Q2: ?Sized + Encode>(
596 &self,
597 queue_key: &Q1,
598 val: &Q2,
599 ) -> Result<()>
600 where
601 L: Borrow<Q1>,
602 V: Borrow<Q2>,
603 {
604 let queue_key = CandyTypedList::<L, (), ()>::make_list_key(queue_key);
605 let val = val.to_bytes::<LE>();
606 self.store.push_to_queue_head(&queue_key, &val)?;
607 Ok(())
608 }
609
610 pub fn push_tail<Q1: ?Sized + Encode, Q2: ?Sized + Encode>(
612 &self,
613 queue_key: &Q1,
614 val: &Q2,
615 ) -> Result<()>
616 where
617 L: Borrow<Q1>,
618 V: Borrow<Q2>,
619 {
620 let queue_key = CandyTypedList::<L, (), ()>::make_list_key(queue_key);
621 let val = val.to_bytes::<LE>();
622 self.store.push_to_queue_tail(&queue_key, &val)?;
623 Ok(())
624 }
625
626 pub fn pop_head_with_idx<Q: ?Sized + Encode>(&self, queue_key: &Q) -> Result<Option<(usize, V)>>
628 where
629 L: Borrow<Q>,
630 {
631 let queue_key = CandyTypedList::<L, (), ()>::make_list_key(queue_key);
632 let Some((idx, v)) = self.store.pop_queue_head_with_idx(&queue_key)? else {
633 return Ok(None);
634 };
635 Ok(Some((idx, from_bytes::<V>(&v)?)))
636 }
637
638 pub fn pop_head<Q: ?Sized + Encode>(&self, queue_key: &Q) -> Result<Option<V>>
640 where
641 L: Borrow<Q>,
642 {
643 Ok(self.pop_head_with_idx(queue_key)?.map(|iv| iv.1))
644 }
645
646 pub fn pop_tail_with_idx<Q: ?Sized + Encode>(&self, queue_key: &Q) -> Result<Option<(usize, V)>>
648 where
649 L: Borrow<Q>,
650 {
651 let queue_key = CandyTypedList::<L, (), ()>::make_list_key(queue_key);
652 let Some((idx, v)) = self.store.pop_queue_tail_with_idx(&queue_key)? else {
653 return Ok(None);
654 };
655 Ok(Some((idx, from_bytes::<V>(&v)?)))
656 }
657
658 pub fn pop_tail<Q: ?Sized + Encode>(&self, queue_key: &Q) -> Result<Option<V>>
660 where
661 L: Borrow<Q>,
662 {
663 Ok(self.pop_tail_with_idx(queue_key)?.map(|iv| iv.1))
664 }
665
666 pub fn peek_head_with_idx<Q: ?Sized + Encode>(
668 &self,
669 queue_key: &Q,
670 ) -> Result<Option<(usize, V)>>
671 where
672 L: Borrow<Q>,
673 {
674 let queue_key = CandyTypedList::<L, (), ()>::make_list_key(queue_key);
675 let Some((idx, v)) = self.store.peek_queue_head_with_idx(&queue_key)? else {
676 return Ok(None);
677 };
678 Ok(Some((idx, from_bytes::<V>(&v)?)))
679 }
680
681 pub fn peek_head<Q: ?Sized + Encode>(&self, queue_key: &Q) -> Result<Option<V>>
683 where
684 L: Borrow<Q>,
685 {
686 Ok(self.peek_head_with_idx(queue_key)?.map(|iv| iv.1))
687 }
688
689 pub fn peek_tail_with_idx<Q: ?Sized + Encode>(
691 &self,
692 queue_key: &Q,
693 ) -> Result<Option<(usize, V)>>
694 where
695 L: Borrow<Q>,
696 {
697 let queue_key = CandyTypedList::<L, (), ()>::make_list_key(queue_key);
698 let Some((idx, v)) = self.store.peek_queue_tail_with_idx(&queue_key)? else {
699 return Ok(None);
700 };
701 Ok(Some((idx, from_bytes::<V>(&v)?)))
702 }
703
704 pub fn peek_tail<Q: ?Sized + Encode>(&self, queue_key: &Q) -> Result<Option<V>>
706 where
707 L: Borrow<Q>,
708 {
709 Ok(self.peek_tail_with_idx(queue_key)?.map(|iv| iv.1))
710 }
711
712 pub fn iter<'a, Q: ?Sized + Encode>(
714 &'a self,
715 queue_key: &Q,
716 ) -> impl Iterator<Item = Result<(usize, V)>> + 'a
717 where
718 L: Borrow<Q>,
719 {
720 let queue_key = CandyTypedList::<L, (), ()>::make_list_key(queue_key);
721 self.store.iter_queue(&queue_key).map(|res| match res {
722 Err(e) => Err(e),
723 Ok((idx, v)) => Ok((idx, from_bytes::<V>(&v).unwrap())),
724 })
725 }
726
727 pub fn iter_backwards<'a, Q: ?Sized + Encode>(
729 &'a self,
730 queue_key: &Q,
731 ) -> impl Iterator<Item = Result<(usize, V)>> + 'a
732 where
733 L: Borrow<Q>,
734 {
735 let queue_key = CandyTypedList::<L, (), ()>::make_list_key(queue_key);
736 self.store
737 .iter_queue_backwards(&queue_key)
738 .map(|res| match res {
739 Err(e) => Err(e),
740 Ok((idx, v)) => Ok((idx, from_bytes::<V>(&v).unwrap())),
741 })
742 }
743
744 pub fn len<Q: ?Sized + Encode>(&self, queue_key: &Q) -> Result<usize>
745 where
746 L: Borrow<Q>,
747 {
748 let queue_key = CandyTypedList::<L, (), ()>::make_list_key(queue_key);
749 self.store.queue_len(&queue_key)
750 }
751
752 pub fn range<Q: ?Sized + Encode>(&self, queue_key: &Q) -> Result<Range<usize>>
753 where
754 L: Borrow<Q>,
755 {
756 let queue_key = CandyTypedList::<L, (), ()>::make_list_key(queue_key);
757 self.store.queue_range(&queue_key)
758 }
759}