libkv/structures/
item.rs

1use std::{borrow::Cow, marker::PhantomData};
2
3use crate::{
4    Codec, DataStructure, Encoding, KeySerde, KeyType, Storage, StorageError, StorageMut, Terminal,
5};
6
7pub struct Item<'a, V: Codec<Enc>, Enc: Encoding, K: KeySerde = Cow<'a, [u8]>>(
8    KeyType<K>,
9    PhantomData<(&'a K, V, Enc)>,
10);
11
12impl<'a, V: Codec<Enc>, Enc: Encoding, K: KeySerde> DataStructure for Item<'a, V, Enc, K> {
13    type Key = K;
14    type Enc = Enc;
15    type Value = V;
16    type DsType = Terminal;
17
18    fn with_prefix(prefix: Vec<u8>) -> Self {
19        Self(KeyType::Raw(prefix), PhantomData)
20    }
21
22    fn should_skip_key(_: &Self::Key) -> bool {
23        false
24    }
25}
26
27impl<V: Codec<Enc>, Enc: Encoding> Item<'static, V, Enc> {
28    pub const fn new(key: &'static [u8]) -> Self {
29        Self(KeyType::Key(Cow::Borrowed(key)), PhantomData)
30    }
31}
32
33impl<'a, V: Codec<Enc>, Enc: Encoding, K: KeySerde> Item<'a, V, Enc, K> {
34    pub fn with_key(key: K) -> Self {
35        Self(KeyType::Key(key), PhantomData)
36    }
37
38    pub fn may_load<S: Storage>(&self, storage: &S) -> Result<Option<V>, StorageError<Enc>> {
39        let bytes = storage.get(&self.0)?;
40        let value = bytes.map(|b| V::decode(b.as_slice())).transpose();
41        value.map_err(StorageError::ValueDeserialize)
42    }
43
44    pub fn save<S: StorageMut>(&self, storage: &mut S, value: &V) -> Result<(), StorageError<Enc>> {
45        let key = self.0.encode()?;
46        let value = value.encode().map_err(StorageError::ValueSerialize)?;
47        storage.set_raw(key, value);
48        Ok(())
49    }
50
51    pub fn delete<S: StorageMut>(&self, storage: &mut S) -> Result<(), StorageError<Enc>> {
52        Ok(storage.delete(&self.0)?)
53    }
54}
55
56#[cfg(test)]
57mod test {
58    use std::collections::HashMap;
59
60    use crate::mock::DisplayEncoding;
61
62    use super::*;
63
64    #[test]
65    fn test_item() {
66        const ITEM: Item<String, DisplayEncoding> = Item::new(b"foo");
67        let item: Item<String, DisplayEncoding> = Item::with_key(Cow::Owned(b"bar".to_vec()));
68
69        let mut storage: HashMap<Vec<u8>, Vec<u8>> = HashMap::new();
70        assert_eq!(ITEM.may_load(&storage), Ok(None));
71        assert_eq!(item.may_load(&storage), Ok(None));
72
73        ITEM.save(&mut storage, &"baz".to_string()).unwrap();
74        assert_eq!(ITEM.may_load(&storage), Ok(Some("baz".to_string())));
75        assert_eq!(item.may_load(&storage), Ok(None));
76
77        item.save(&mut storage, &"qux".to_string()).unwrap();
78        assert_eq!(ITEM.may_load(&storage), Ok(Some("baz".to_string())));
79        assert_eq!(item.may_load(&storage), Ok(Some("qux".to_string())));
80
81        item.delete(&mut storage).unwrap();
82        assert_eq!(ITEM.may_load(&storage), Ok(Some("baz".to_string())));
83        assert_eq!(item.may_load(&storage), Ok(None));
84    }
85}