Skip to content

Commit 79df04c

Browse files
authored
Merge pull request #60 from Occuros/feature/key_removal
Feature/key removal
2 parents ee2aa3d + 6594949 commit 79df04c

File tree

5 files changed

+198
-16
lines changed

5 files changed

+198
-16
lines changed

src/lib.rs

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,18 @@ use serde::{de::DeserializeOwned, Serialize};
1414
trait StoreImpl {
1515
type GetError;
1616
type SetError;
17+
type RemoveError;
1718

1819
fn set_string(&mut self, key: &str, value: &str) -> Result<(), Self::SetError> {
1920
self.set(key, &value.to_string())
2021
}
2122
fn get<T: DeserializeOwned>(&self, key: &str) -> Result<T, Self::GetError>;
2223
fn set<T: Serialize>(&mut self, key: &str, value: &T) -> Result<(), Self::SetError>;
24+
fn remove(&mut self, key: &str) -> Result<(), Self::RemoveError>;
25+
fn remove_and_get<T: DeserializeOwned>(
26+
&mut self,
27+
key: &str,
28+
) -> Result<Option<T>, Self::RemoveError>;
2329
fn clear(&mut self) -> Result<(), Self::SetError>;
2430
}
2531

@@ -42,7 +48,7 @@ mod rocksdb_store;
4248
use rocksdb_store::{self as backend};
4349

4450
// todo: Look into unifying these types?
45-
pub use backend::{GetError, SetError};
51+
pub use backend::{GetError, RemoveError, SetError};
4652

4753
enum Location<'a> {
4854
PlatformDefault(&'a PlatformDefault),
@@ -125,6 +131,18 @@ impl PkvStore {
125131
pub fn get<T: DeserializeOwned>(&self, key: impl AsRef<str>) -> Result<T, GetError> {
126132
self.inner.get(key.as_ref())
127133
}
134+
/// Remove the value from the store for the given key
135+
/// returns the removed value if one existed
136+
pub fn remove_and_get<T: DeserializeOwned>(
137+
&mut self,
138+
key: impl AsRef<str>,
139+
) -> Result<Option<T>, RemoveError> {
140+
self.inner.remove_and_get(key.as_ref())
141+
}
142+
/// Remove the value from the store for the given key
143+
pub fn remove(&mut self, key: impl AsRef<str>) -> Result<(), RemoveError> {
144+
self.inner.remove(key.as_ref())
145+
}
128146

129147
/// Clear all key values data
130148
/// returns Err(SetError) if clear error
@@ -237,4 +255,31 @@ mod tests {
237255
store.set("user", &user).unwrap();
238256
assert_eq!(store.get::<User>("user").unwrap(), user);
239257
}
258+
259+
#[test]
260+
fn remove() {
261+
setup();
262+
let mut store = PkvStore::new("BevyPkv", "test_remove");
263+
let user = User {
264+
name: "alice".to_string(),
265+
age: 32,
266+
};
267+
store.set("user", &user).unwrap();
268+
store.remove("user").unwrap();
269+
assert_eq!(store.get::<User>("user").ok(), None);
270+
}
271+
272+
#[test]
273+
fn remove_and_get() {
274+
setup();
275+
let mut store = PkvStore::new("BevyPkv", "test_remove_and_get");
276+
let user = User {
277+
name: "alice".to_string(),
278+
age: 32,
279+
};
280+
store.set("user", &user).unwrap();
281+
let removed_user = store.remove_and_get::<User>("user").unwrap().unwrap();
282+
assert_eq!(user, removed_user);
283+
assert_eq!(store.get::<User>("user").ok(), None);
284+
}
240285
}

src/local_storage_store.rs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,18 @@ pub enum SetError {
2727
Clear(wasm_bindgen::JsValue),
2828
}
2929

30+
#[derive(thiserror::Error, Debug)]
31+
pub enum RemoveError {
32+
#[error("No value found for the given key")]
33+
NotFound,
34+
#[error("error deserializing json")]
35+
Json(#[from] serde_json::Error),
36+
#[error("JavaScript error from getItem")]
37+
GetItem(wasm_bindgen::JsValue),
38+
#[error("JavaScript error from clear")]
39+
Clear(wasm_bindgen::JsValue),
40+
}
41+
3042
impl LocalStorageStore {
3143
fn storage(&self) -> web_sys::Storage {
3244
web_sys::window()
@@ -59,6 +71,7 @@ impl LocalStorageStore {
5971
impl StoreImpl for LocalStorageStore {
6072
type GetError = GetError;
6173
type SetError = SetError;
74+
type RemoveError = RemoveError;
6275

6376
fn set_string(&mut self, key: &str, value: &str) -> Result<(), SetError> {
6477
let json = serde_json::to_string(value)?;
@@ -99,4 +112,20 @@ impl StoreImpl for LocalStorageStore {
99112
}
100113
Ok(())
101114
}
115+
116+
fn remove(&mut self, key: &str) -> Result<(), Self::RemoveError> {
117+
let storage = self.storage();
118+
let key = self.format_key(key);
119+
storage.remove_item(&key).map_err(RemoveError::Clear)?;
120+
Ok(())
121+
}
122+
123+
fn remove_and_get<T: serde::de::DeserializeOwned>(
124+
&mut self,
125+
key: &str,
126+
) -> Result<Option<T>, Self::RemoveError> {
127+
let previous_value = self.get(key).map_err(|_| RemoveError::NotFound)?;
128+
self.remove(key)?;
129+
Ok(Some(previous_value))
130+
}
102131
}

src/redb_store.rs

Lines changed: 64 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,26 @@ pub enum GetError {
3333
MessagePack(#[from] rmp_serde::decode::Error),
3434
}
3535

36+
/// Errors that can occur during `PkvStore::`
37+
#[derive(thiserror::Error, Debug)]
38+
pub enum RemoveError {
39+
/// An internal commit error from the `redb` crate
40+
#[error("ReDbCommitError error")]
41+
ReDbCommitError(#[from] redb::CommitError),
42+
/// An internal storage error from the `redb` crate
43+
#[error("ReDbStorageError error")]
44+
ReDbStorageError(#[from] redb::StorageError),
45+
/// An internal transaction error from the `redb` crate
46+
#[error("ReDbTransactionError error")]
47+
ReDbTransactionError(#[from] redb::TransactionError),
48+
/// An internal table error from the `redb` crate
49+
#[error("ReDbTableError error")]
50+
ReDbTableError(#[from] redb::TableError),
51+
/// Error when serializing the value
52+
#[error("MessagePack serialization error")]
53+
MessagePack(#[from] rmp_serde::encode::Error),
54+
}
55+
3656
/// Errors that can occur during `PkvStore::set`
3757
#[derive(thiserror::Error, Debug)]
3858
pub enum SetError {
@@ -74,20 +94,7 @@ const TABLE: TableDefinition<&str, &[u8]> = TableDefinition::new("redb");
7494
impl StoreImpl for ReDbStore {
7595
type GetError = GetError;
7696
type SetError = SetError;
77-
78-
/// Serialize and store the value
79-
fn set<T: Serialize>(&mut self, key: &str, value: &T) -> Result<(), Self::SetError> {
80-
let mut serializer = rmp_serde::Serializer::new(Vec::new()).with_struct_map();
81-
value.serialize(&mut serializer)?;
82-
let write_txn = self.db.begin_write()?;
83-
{
84-
let mut table = write_txn.open_table(TABLE).unwrap();
85-
table.insert(key, serializer.into_inner().as_slice())?;
86-
}
87-
write_txn.commit()?;
88-
89-
Ok(())
90-
}
97+
type RemoveError = RemoveError;
9198

9299
/// More or less the same as set::<String>, but can take a &str
93100
fn set_string(&mut self, key: &str, value: &str) -> Result<(), Self::SetError> {
@@ -113,6 +120,49 @@ impl StoreImpl for ReDbStore {
113120
Ok(value)
114121
}
115122

123+
/// Serialize and store the value
124+
fn set<T: Serialize>(&mut self, key: &str, value: &T) -> Result<(), Self::SetError> {
125+
let mut serializer = rmp_serde::Serializer::new(Vec::new()).with_struct_map();
126+
value.serialize(&mut serializer)?;
127+
let write_txn = self.db.begin_write()?;
128+
{
129+
let mut table = write_txn.open_table(TABLE).unwrap();
130+
table.insert(key, serializer.into_inner().as_slice())?;
131+
}
132+
write_txn.commit()?;
133+
134+
Ok(())
135+
}
136+
137+
fn remove_and_get<T: DeserializeOwned>(
138+
&mut self,
139+
key: &str,
140+
) -> Result<Option<T>, Self::RemoveError> {
141+
let value: Option<T>;
142+
let write_txn = self.db.begin_write()?;
143+
{
144+
let mut table = write_txn.open_table(TABLE).unwrap();
145+
value = match table.remove(key)? {
146+
Some(kv) => rmp_serde::from_slice(kv.value()).ok(),
147+
None => None,
148+
};
149+
}
150+
write_txn.commit()?;
151+
152+
Ok(value)
153+
}
154+
155+
fn remove(&mut self, key: &str) -> Result<(), Self::RemoveError> {
156+
let write_txn = self.db.begin_write()?;
157+
{
158+
let mut table = write_txn.open_table(TABLE).unwrap();
159+
table.remove(key)?;
160+
}
161+
write_txn.commit()?;
162+
163+
Ok(())
164+
}
165+
116166
/// Clear all keys and their values
117167
fn clear(&mut self) -> Result<(), Self::SetError> {
118168
let write_txn = self.db.begin_write()?;

src/rocksdb_store.rs

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ pub enum GetError {
2121
#[error("No value found for the given key")]
2222
NotFound,
2323
}
24-
2524
/// Errors that can occur during `PkvStore::set`
2625
#[derive(thiserror::Error, Debug)]
2726
pub enum SetError {
@@ -33,6 +32,20 @@ pub enum SetError {
3332
MessagePack(#[from] rmp_serde::encode::Error),
3433
}
3534

35+
/// Errors that can occur during `PkvStore::remove`
36+
#[derive(thiserror::Error, Debug)]
37+
pub enum RemoveError {
38+
/// An internal error from the rocksdb crate
39+
#[error("Rocksdb error")]
40+
Rocksdb(#[from] rocksdb::Error),
41+
/// Error when deserializing the value
42+
#[error("MessagePack deserialization error")]
43+
MessagePack(#[from] rmp_serde::decode::Error),
44+
/// The value for the given key was not found
45+
#[error("No value found for the given key")]
46+
NotFound,
47+
}
48+
3649
impl RocksDBStore {
3750
pub(crate) fn new(location: Location) -> Self {
3851
let mut options = rocksdb::Options::default();
@@ -49,6 +62,7 @@ impl RocksDBStore {
4962
impl StoreImpl for RocksDBStore {
5063
type GetError = GetError;
5164
type SetError = SetError;
65+
type RemoveError = RemoveError;
5266

5367
/// Serialize and store the value
5468
fn set<T: Serialize>(&mut self, key: &str, value: &T) -> Result<(), Self::SetError> {
@@ -87,4 +101,19 @@ impl StoreImpl for RocksDBStore {
87101

88102
Ok(())
89103
}
104+
105+
fn remove(&mut self, key: &str) -> Result<(), Self::RemoveError> {
106+
self.db.delete(key)?;
107+
Ok(())
108+
}
109+
110+
fn remove_and_get<T: DeserializeOwned>(
111+
&mut self,
112+
key: &str,
113+
) -> Result<Option<T>, Self::RemoveError> {
114+
let bytes = self.db.get(key)?.ok_or(Self::RemoveError::NotFound)?;
115+
let value = rmp_serde::from_slice(&bytes)?;
116+
self.db.delete(key)?;
117+
Ok(value)
118+
}
90119
}

src/sled_store.rs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,20 @@ pub enum SetError {
3333
MessagePack(#[from] rmp_serde::encode::Error),
3434
}
3535

36+
/// Errors that can occur during `PkvStore::remove`
37+
#[derive(thiserror::Error, Debug)]
38+
pub enum RemoveError {
39+
/// An internal error from the sled crate
40+
#[error("Sled error")]
41+
Sled(#[from] sled::Error),
42+
/// Error when deserializing the value
43+
#[error("MessagePack deserialization error")]
44+
MessagePack(#[from] rmp_serde::decode::Error),
45+
/// The value for the given key was not found
46+
#[error("No value found for the given key")]
47+
NotFound,
48+
}
49+
3650
impl SledStore {
3751
pub(crate) fn new(location: Location) -> Self {
3852
let db_path = location.get_path().join("bevy_pkv.sled");
@@ -44,6 +58,7 @@ impl SledStore {
4458
impl StoreImpl for SledStore {
4559
type GetError = GetError;
4660
type SetError = SetError;
61+
type RemoveError = RemoveError;
4762

4863
/// Serialize and store the value
4964
fn set<T: Serialize>(&mut self, key: &str, value: &T) -> Result<(), Self::SetError> {
@@ -77,4 +92,18 @@ impl StoreImpl for SledStore {
7792
self.db.flush()?;
7893
Ok(())
7994
}
95+
96+
fn remove(&mut self, key: &str) -> Result<(), Self::RemoveError> {
97+
self.db.remove(key)?;
98+
Ok(())
99+
}
100+
101+
fn remove_and_get<T: DeserializeOwned>(
102+
&mut self,
103+
key: &str,
104+
) -> Result<Option<T>, Self::RemoveError> {
105+
let bytes = self.db.remove(key)?.ok_or(Self::RemoveError::NotFound)?;
106+
let value = rmp_serde::from_slice(&bytes)?;
107+
Ok(value)
108+
}
80109
}

0 commit comments

Comments
 (0)