1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
use std::rc::Rc;
use super::SOURCE_GUEST;
use crate::HostRuntimeInterface;
use crate::Result;
use codec::keyvalue::{
AddRequest, AddResponse, DelRequest, GetRequest, GetResponse, ListPushRequest,
ListRangeRequest, ListRangeResponse, ListResponse, SetRequest, SetResponse,
};
use prost::Message;
use wascap_codec as codec;
use wascap_codec::AsCommand;
const TARGET_KEYVALUE: &'static str = "wascap:keyvalue";
pub struct KeyValueStore {
hri: Rc<&'static dyn HostRuntimeInterface>,
}
impl KeyValueStore {
pub(crate) fn new(hri: Rc<&'static dyn HostRuntimeInterface>) -> KeyValueStore {
KeyValueStore {
hri,
}
}
pub fn get(&self, key: &str) -> Result<(String, bool)> {
let cmd = GetRequest {
key: key.to_string(),
}
.as_command(SOURCE_GUEST, TARGET_KEYVALUE);
self.hri.do_host_call(&cmd).map(|evt| {
let resp = GetResponse::decode(&evt.payload.unwrap().value).unwrap();
(resp.value, resp.exists)
})
}
pub fn set(&self, key: &str, value: &str) -> Result<()> {
let cmd = SetRequest {
key: key.to_string(),
value: value.to_string(),
}
.as_command(SOURCE_GUEST, TARGET_KEYVALUE);
self.hri.do_host_call(&cmd).map(|_evt| ())
}
pub fn atomic_add(&self, key: &str, value: i32) -> Result<i32> {
let cmd = AddRequest {
key: key.to_string(),
value: value,
}
.as_command(SOURCE_GUEST, TARGET_KEYVALUE);
self.hri.do_host_call(&cmd).map(|evt| {
let resp = AddResponse::decode(&evt.payload.unwrap().value).unwrap();
resp.value
})
}
pub fn list_add(&self, key: &str, item: &str) -> Result<usize> {
let cmd = ListPushRequest {
key: key.to_string(),
value: item.to_string(),
}
.as_command(SOURCE_GUEST, TARGET_KEYVALUE);
self.hri.do_host_call(&cmd).map(|evt| {
let resp = ListResponse::decode(&evt.payload.unwrap().value).unwrap();
resp.new_count as usize
})
}
pub fn del_key(&self, key: &str) -> Result<()> {
let cmd = DelRequest {
key: key.to_string(),
}
.as_command(SOURCE_GUEST, TARGET_KEYVALUE);
self.hri.do_host_call(&cmd).map(|_evt| ())
}
pub fn list_range(&self, key: &str, start: isize, stop_inclusive: isize) -> Result<Vec<String>> {
let cmd = ListRangeRequest {
key: key.to_string(),
start: start as i32,
stop: stop_inclusive as i32,
}
.as_command(SOURCE_GUEST, TARGET_KEYVALUE);
self.hri.do_host_call(&cmd).map(|evt| {
let resp = ListRangeResponse::decode(&evt.payload.unwrap().value).unwrap();
resp.values
})
}
}