1use http::uri::PathAndQuery;
5use hyper::{Body, Method, Request, Uri};
6use serde::Serialize;
7use serde_json;
8
9pub trait RequestType {
11 const METHOD: Method;
13 const PATH_AND_QUERY: &'static str;
15}
16
17pub trait IntoBody {
19 type Body: Serialize;
21 fn into_body(self) -> Self::Body;
23}
24
25pub trait IntoRequest: RequestType + IntoBody {
27 fn into_request(self, base_uri: Uri) -> Request<Body>;
30}
31
32type Key = Vec<u8>;
34type Value = Vec<u8>;
36
37#[derive(Clone, Debug, Eq, Hash, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
39pub struct Get {
40 pub key: Key,
41}
42
43#[derive(Clone, Debug, Eq, Hash, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
45pub struct Del {
46 pub key: Key,
47}
48
49#[derive(Clone, Debug, Eq, Hash, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
51pub struct Set {
52 pub key: Key,
53 pub value: Value,
54}
55
56#[derive(Clone, Debug, Eq, Hash, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
64pub struct Cas {
65 pub key: Key,
66 pub old: Option<Value>,
67 pub new: Option<Value>,
68}
69
70#[derive(Clone, Debug, Eq, Hash, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
72pub struct Merge {
73 pub key: Key,
74 pub value: Value,
75}
76
77#[derive(Clone, Debug, Eq, Hash, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
79pub struct Flush;
80
81#[derive(Clone, Debug, Eq, Hash, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
83pub struct Iter;
84
85#[derive(Clone, Debug, Eq, Hash, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
87pub struct Scan {
88 pub key: Key,
89}
90
91#[derive(Clone, Debug, Eq, Hash, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
95pub struct ScanRange {
96 pub start: Key,
97 pub end: Key,
98}
99
100#[derive(Clone, Debug, Eq, Hash, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
102pub struct Max;
103
104#[derive(Clone, Debug, Eq, Hash, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
106pub struct Pred {
107 pub key: Key,
108}
109
110#[derive(Clone, Debug, Eq, Hash, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
112pub struct PredIncl {
113 pub key: Key,
114}
115
116#[derive(Clone, Debug, Eq, Hash, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
118pub struct Succ {
119 pub key: Key,
120}
121
122#[derive(Clone, Debug, Eq, Hash, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
124pub struct SuccIncl {
125 pub key: Key,
126}
127
128impl RequestType for Get {
129 const METHOD: Method = Method::GET;
130 const PATH_AND_QUERY: &'static str = "/tree/entries/get";
131}
132
133impl RequestType for Del {
134 const METHOD: Method = Method::DELETE;
135 const PATH_AND_QUERY: &'static str = "/tree/entries/delete";
136}
137
138impl RequestType for Set {
139 const METHOD: Method = Method::POST;
140 const PATH_AND_QUERY: &'static str = "/tree/entries/set";
141}
142
143impl RequestType for Cas {
144 const METHOD: Method = Method::PUT;
145 const PATH_AND_QUERY: &'static str = "/tree/entries/cas";
146}
147
148impl RequestType for Merge {
149 const METHOD: Method = Method::POST;
150 const PATH_AND_QUERY: &'static str = "/tree/entries/merge";
151}
152
153impl RequestType for Flush {
154 const METHOD: Method = Method::PUT;
155 const PATH_AND_QUERY: &'static str = "/tree/entries/flush";
156}
157
158impl RequestType for Iter {
159 const METHOD: Method = Method::GET;
160 const PATH_AND_QUERY: &'static str = "/tree/entries/iter";
161}
162
163impl RequestType for Scan {
164 const METHOD: Method = Method::GET;
165 const PATH_AND_QUERY: &'static str = "/tree/entries/scan";
166}
167
168impl RequestType for ScanRange {
169 const METHOD: Method = Method::GET;
170 const PATH_AND_QUERY: &'static str = "/tree/entries/scan_range";
171}
172
173impl RequestType for Max {
174 const METHOD: Method = Method::GET;
175 const PATH_AND_QUERY: &'static str = "/tree/entries/max";
176}
177
178impl RequestType for Pred {
179 const METHOD: Method = Method::GET;
180 const PATH_AND_QUERY: &'static str = "/tree/entries/pred";
181}
182
183impl RequestType for PredIncl {
184 const METHOD: Method = Method::GET;
185 const PATH_AND_QUERY: &'static str = "/tree/entries/pred_incl";
186}
187
188impl RequestType for Succ {
189 const METHOD: Method = Method::GET;
190 const PATH_AND_QUERY: &'static str = "/tree/entries/succ";
191}
192
193impl RequestType for SuccIncl {
194 const METHOD: Method = Method::GET;
195 const PATH_AND_QUERY: &'static str = "/tree/entries/succ_incl";
196}
197
198impl IntoBody for Get {
199 type Body = Self;
200 fn into_body(self) -> Self::Body { self }
201}
202
203impl IntoBody for Del {
204 type Body = Self;
205 fn into_body(self) -> Self::Body { self }
206}
207
208impl IntoBody for Set {
209 type Body = Self;
210 fn into_body(self) -> Self::Body { self }
211}
212
213impl IntoBody for Cas {
214 type Body = Self;
215 fn into_body(self) -> Self::Body { self }
216}
217
218impl IntoBody for Merge {
219 type Body = Self;
220 fn into_body(self) -> Self::Body { self }
221}
222
223impl IntoBody for Flush {
224 type Body = Self;
225 fn into_body(self) -> Self::Body { self }
226}
227
228impl IntoBody for Iter {
229 type Body = Self;
230 fn into_body(self) -> Self::Body { self }
231}
232
233impl IntoBody for Scan {
234 type Body = Self;
235 fn into_body(self) -> Self::Body { self }
236}
237
238impl IntoBody for ScanRange {
239 type Body = Self;
240 fn into_body(self) -> Self::Body { self }
241}
242
243impl IntoBody for Max {
244 type Body = Self;
245 fn into_body(self) -> Self::Body { self }
246}
247
248impl IntoBody for Pred {
249 type Body = Self;
250 fn into_body(self) -> Self::Body { self }
251}
252
253impl IntoBody for PredIncl {
254 type Body = Self;
255 fn into_body(self) -> Self::Body { self }
256}
257
258impl IntoBody for Succ {
259 type Body = Self;
260 fn into_body(self) -> Self::Body { self }
261}
262
263impl IntoBody for SuccIncl {
264 type Body = Self;
265 fn into_body(self) -> Self::Body { self }
266}
267
268impl<T> IntoRequest for T
269where
270 T: RequestType + IntoBody,
271{
272 fn into_request(self, base_uri: Uri) -> Request<Body> {
273 let method = T::METHOD;
274 let uri = uri_with_path(base_uri, T::PATH_AND_QUERY);
275 let body = self.into_body();
276 let body_json = serde_json::to_vec(&body).expect("failed to serialize request body");
277 Request::builder()
278 .method(method)
279 .uri(uri)
280 .body(body_json.into())
281 .expect("attempted to construct invalid request")
282 }
283}
284
285fn uri_with_path(uri: Uri, path: &str) -> Uri {
289 let mut parts = uri.into_parts();
290 let path_and_query = path
291 .parse::<PathAndQuery>()
292 .expect("failed to parse path and query for request URI");
293 parts.path_and_query = Some(path_and_query);
294 Uri::from_parts(parts)
295 .expect("failed to construct request URI from parts")
296}
297
298pub fn from<T>(base_uri: Uri, req: T) -> Request<Body>
302where
303 T: IntoRequest,
304{
305 req.into_request(base_uri)
306}
307
308pub fn get(base_uri: Uri, key: Key) -> Request<Body> {
310 from(base_uri, Get { key })
311}
312
313pub fn del(base_uri: Uri, key: Key) -> Request<Body> {
315 from(base_uri, Del { key })
316}
317
318pub fn set(base_uri: Uri, key: Key, value: Value) -> Request<Body> {
320 from(base_uri, Set { key, value })
321}
322
323pub fn iter(base_uri: Uri) -> Request<Body> {
325 from(base_uri, Iter)
326}
327
328pub fn scan(base_uri: Uri, key: Key) -> Request<Body> {
330 from(base_uri, Scan { key })
331}
332
333pub fn scan_range(base_uri: Uri, start: Key, end: Key) -> Request<Body> {
335 from(base_uri, ScanRange { start, end })
336}
337
338pub fn max(base_uri: Uri) -> Request<Body> {
340 from(base_uri, Max)
341}
342
343pub fn pred(base_uri: Uri, key: Key) -> Request<Body> {
345 from(base_uri, Pred { key })
346}
347
348pub fn pred_incl(base_uri: Uri, key: Key) -> Request<Body> {
350 from(base_uri, PredIncl { key })
351}
352
353pub fn succ(base_uri: Uri, key: Key) -> Request<Body> {
355 from(base_uri, Succ { key })
356}
357
358pub fn succ_incl(base_uri: Uri, key: Key) -> Request<Body> {
360 from(base_uri, SuccIncl { key })
361}
362
363pub fn cas(base_uri: Uri, key: Key, old: Option<Value>, new: Option<Value>) -> Request<Body> {
365 from(base_uri, Cas { key, old, new })
366}
367
368pub fn merge(base_uri: Uri, key: Key, value: Value) -> Request<Body> {
370 from(base_uri, Merge { key, value })
371}
372
373pub fn flush(base_uri: Uri) -> Request<Body> {
375 from(base_uri, Flush)
376}