Skip to content
This repository was archived by the owner on May 9, 2022. It is now read-only.

Commit d20e6b4

Browse files
committed
feat(rtc_tenclave,kv_store): add alter operation
1 parent 71e1563 commit d20e6b4

File tree

2 files changed

+42
-0
lines changed

2 files changed

+42
-0
lines changed

rtc_tenclave/src/kv_store/mod.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,23 @@ pub trait KvStore<V> {
2727

2828
/// Delete the saved value for `key`.
2929
fn delete(&mut self, key: &str) -> StoreResult<()>;
30+
31+
/// Alter the value of `key`.
32+
///
33+
/// This operation is a generalisation of [`Self::load`], [`Self::save`], and [`Self::delete`].
34+
///
35+
fn alter<F>(&mut self, key: &str, alter_fn: F) -> StoreResult<Option<V>>
36+
where
37+
F: FnOnce(Option<V>) -> Option<V>,
38+
{
39+
let loaded: Option<V> = self.load(key)?;
40+
let altered: Option<V> = alter_fn(loaded);
41+
match &altered {
42+
None => self.delete(key)?,
43+
Some(value) => self.save(key, value)?,
44+
};
45+
Ok(altered)
46+
}
3047
}
3148

3249
mod fs;

rtc_tenclave/src/kv_store/tests.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@ fn prop_store_ops_match_model() {
2525
enum StoreOp {
2626
Save { key: String, value: V },
2727
Delete { key: String },
28+
AlterId { key: String },
29+
AlterConst { key: String, replacement: Option<V> },
30+
AlterUpdate { key: String, new_value: V },
2831
}
2932
use StoreOp::*;
3033
impl StoreOp {
@@ -39,6 +42,22 @@ fn prop_store_ops_match_model() {
3942
store.delete(key)?;
4043
assert_eq!(store.load(key)?, None);
4144
}
45+
AlterId { key } => {
46+
let previous = store.load(key)?;
47+
store.alter(key, |loaded| loaded)?;
48+
assert_eq!(store.load(key)?, previous);
49+
}
50+
AlterConst { key, replacement } => {
51+
store.alter(key, |_| replacement.clone())?;
52+
assert_eq!(store.load(key)?.as_ref(), replacement.as_ref());
53+
}
54+
AlterUpdate { key, new_value } => {
55+
let previous = store.load(key)?;
56+
store.alter(key, |existing: Option<V>| {
57+
existing.map(|_| new_value.clone())
58+
})?;
59+
assert_eq!(store.load(key)?.as_ref(), previous.map(|_| new_value));
60+
}
4261
};
4362
Ok(())
4463
}
@@ -51,6 +70,9 @@ fn prop_store_ops_match_model() {
5170
let half_ops = prop_oneof!(
5271
(Just("Save"), values.clone().prop_map(Some)),
5372
(Just("Delete"), Just(None)),
73+
(Just("AlterId"), Just(None)),
74+
(Just("AlterConst"), proptest::option::of(values.clone())),
75+
(Just("AlterUpdate"), values.clone().prop_map(Some)),
5476
);
5577

5678
// This strategy will generate key / value pairs with multiple values per key,
@@ -64,6 +86,9 @@ fn prop_store_ops_match_model() {
6486
match half_op {
6587
("Save", Some(value)) => Save { key, value },
6688
("Delete", None) => Delete { key },
89+
("AlterId", None) => AlterId { key },
90+
("AlterConst", replacement) => AlterConst { key, replacement },
91+
("AlterUpdate", Some(new_value)) => AlterUpdate { key, new_value },
6792
unexpected => panic!("unexpected: {:?}", unexpected),
6893
}
6994
})

0 commit comments

Comments
 (0)