Skip to main content

memcached_async/
extract.rs

1use std::convert::Infallible;
2use std::sync::Arc;
3
4use bytes::Bytes;
5
6use crate::context::RequestContext;
7pub use crate::context::{ClientId, Extensions, LocalAddr, PeerAddr, State};
8use crate::error::Error;
9use crate::router::FromRequest;
10use crate::types::{MetaFlags, Op, Protocol as Proto, ReplyMode, Request};
11
12/// Raw command wrapper.
13#[derive(Debug, Clone, Copy)]
14pub struct Cmd(pub Op);
15
16/// Single key extractor.
17#[derive(Debug, Clone)]
18pub struct Key(pub Bytes);
19
20/// Multi-key extractor.
21#[derive(Debug, Clone)]
22pub struct Keys(pub Vec<Bytes>);
23
24/// Value extractor.
25#[derive(Debug, Clone)]
26pub struct Value(pub Bytes);
27
28/// Flags extractor.
29#[derive(Debug, Clone, Copy)]
30pub struct Flags(pub u32);
31
32/// Expiration extractor.
33#[derive(Debug, Clone, Copy)]
34pub struct Exptime(pub i64);
35
36/// CAS extractor.
37#[derive(Debug, Clone, Copy)]
38pub struct Cas(pub u64);
39
40/// Delta extractor for incr/decr.
41#[derive(Debug, Clone, Copy)]
42pub struct Delta(pub u64);
43
44/// Meta flags extractor.
45#[derive(Debug, Clone)]
46pub struct Meta(pub MetaFlags);
47
48/// Protocol extractor.
49#[derive(Debug, Clone, Copy)]
50pub struct Protocol(pub Proto);
51
52/// Reply mode extractor.
53#[derive(Debug, Clone, Copy)]
54pub struct Reply(pub ReplyMode);
55
56/// Opaque token extractor.
57#[derive(Debug, Clone, Copy)]
58pub struct Opaque(pub u32);
59
60impl<StateT> FromRequest<StateT> for Cmd
61where
62    StateT: Send + Sync + 'static,
63{
64    type Rejection = Infallible;
65
66    async fn from_request(
67        ctx: &mut RequestContext,
68        _state: &Arc<StateT>,
69    ) -> Result<Self, Self::Rejection> {
70        Ok(Cmd(ctx.request.op))
71    }
72}
73
74impl<StateT> FromRequest<StateT> for Op
75where
76    StateT: Send + Sync + 'static,
77{
78    type Rejection = Infallible;
79
80    async fn from_request(
81        ctx: &mut RequestContext,
82        _state: &Arc<StateT>,
83    ) -> Result<Self, Self::Rejection> {
84        Ok(ctx.request.op)
85    }
86}
87
88impl<StateT> FromRequest<StateT> for Request
89where
90    StateT: Send + Sync + 'static,
91{
92    type Rejection = Infallible;
93
94    async fn from_request(
95        ctx: &mut RequestContext,
96        _state: &Arc<StateT>,
97    ) -> Result<Self, Self::Rejection> {
98        Ok(ctx.request.clone())
99    }
100}
101
102impl<StateT> FromRequest<StateT> for Key
103where
104    StateT: Send + Sync + 'static,
105{
106    type Rejection = Error;
107
108    async fn from_request(
109        ctx: &mut RequestContext,
110        _state: &Arc<StateT>,
111    ) -> Result<Self, Self::Rejection> {
112        if let Some(key) = ctx.request.key.as_ref() {
113            return Ok(Key(key.clone()));
114        }
115        if ctx.request.keys.len() == 1 {
116            return Ok(Key(ctx.request.keys[0].clone()));
117        }
118        Err(Error::client("missing key"))
119    }
120}
121
122impl<StateT> FromRequest<StateT> for Keys
123where
124    StateT: Send + Sync + 'static,
125{
126    type Rejection = Error;
127
128    async fn from_request(
129        ctx: &mut RequestContext,
130        _state: &Arc<StateT>,
131    ) -> Result<Self, Self::Rejection> {
132        if !ctx.request.keys.is_empty() {
133            return Ok(Keys(ctx.request.keys.clone()));
134        }
135        if let Some(key) = ctx.request.key.as_ref() {
136            return Ok(Keys(vec![key.clone()]));
137        }
138        Err(Error::client("missing keys"))
139    }
140}
141
142impl<StateT> FromRequest<StateT> for Value
143where
144    StateT: Send + Sync + 'static,
145{
146    type Rejection = Error;
147
148    async fn from_request(
149        ctx: &mut RequestContext,
150        _state: &Arc<StateT>,
151    ) -> Result<Self, Self::Rejection> {
152        ctx.request
153            .value
154            .as_ref()
155            .map(|value| Value(value.clone()))
156            .ok_or_else(|| Error::client("missing value"))
157    }
158}
159
160impl<StateT> FromRequest<StateT> for Flags
161where
162    StateT: Send + Sync + 'static,
163{
164    type Rejection = Error;
165
166    async fn from_request(
167        ctx: &mut RequestContext,
168        _state: &Arc<StateT>,
169    ) -> Result<Self, Self::Rejection> {
170        ctx.request
171            .flags
172            .map(Flags)
173            .ok_or_else(|| Error::client("missing flags"))
174    }
175}
176
177impl<StateT> FromRequest<StateT> for Exptime
178where
179    StateT: Send + Sync + 'static,
180{
181    type Rejection = Error;
182
183    async fn from_request(
184        ctx: &mut RequestContext,
185        _state: &Arc<StateT>,
186    ) -> Result<Self, Self::Rejection> {
187        ctx.request
188            .exptime
189            .map(Exptime)
190            .ok_or_else(|| Error::client("missing exptime"))
191    }
192}
193
194impl<StateT> FromRequest<StateT> for Cas
195where
196    StateT: Send + Sync + 'static,
197{
198    type Rejection = Error;
199
200    async fn from_request(
201        ctx: &mut RequestContext,
202        _state: &Arc<StateT>,
203    ) -> Result<Self, Self::Rejection> {
204        ctx.request
205            .cas
206            .map(Cas)
207            .ok_or_else(|| Error::client("missing cas"))
208    }
209}
210
211impl<StateT> FromRequest<StateT> for Delta
212where
213    StateT: Send + Sync + 'static,
214{
215    type Rejection = Error;
216
217    async fn from_request(
218        ctx: &mut RequestContext,
219        _state: &Arc<StateT>,
220    ) -> Result<Self, Self::Rejection> {
221        ctx.request
222            .delta
223            .map(Delta)
224            .ok_or_else(|| Error::client("missing delta"))
225    }
226}
227
228impl<StateT> FromRequest<StateT> for Meta
229where
230    StateT: Send + Sync + 'static,
231{
232    type Rejection = Error;
233
234    async fn from_request(
235        ctx: &mut RequestContext,
236        _state: &Arc<StateT>,
237    ) -> Result<Self, Self::Rejection> {
238        ctx.request
239            .meta
240            .clone()
241            .map(Meta)
242            .ok_or_else(|| Error::client("missing meta flags"))
243    }
244}
245
246impl<StateT> FromRequest<StateT> for Protocol
247where
248    StateT: Send + Sync + 'static,
249{
250    type Rejection = Infallible;
251
252    async fn from_request(
253        ctx: &mut RequestContext,
254        _state: &Arc<StateT>,
255    ) -> Result<Self, Self::Rejection> {
256        Ok(Protocol(ctx.meta.protocol))
257    }
258}
259
260impl<StateT> FromRequest<StateT> for Reply
261where
262    StateT: Send + Sync + 'static,
263{
264    type Rejection = Infallible;
265
266    async fn from_request(
267        ctx: &mut RequestContext,
268        _state: &Arc<StateT>,
269    ) -> Result<Self, Self::Rejection> {
270        Ok(Reply(ctx.meta.reply))
271    }
272}
273
274impl<StateT> FromRequest<StateT> for Opaque
275where
276    StateT: Send + Sync + 'static,
277{
278    type Rejection = Error;
279
280    async fn from_request(
281        ctx: &mut RequestContext,
282        _state: &Arc<StateT>,
283    ) -> Result<Self, Self::Rejection> {
284        ctx.meta
285            .opaque
286            .map(Opaque)
287            .ok_or_else(|| Error::client("missing opaque"))
288    }
289}
290
291impl<T> FromRequest<T> for State<T>
292where
293    T: Send + Sync + 'static,
294{
295    type Rejection = Infallible;
296
297    async fn from_request(
298        _ctx: &mut RequestContext,
299        state: &Arc<T>,
300    ) -> Result<Self, Self::Rejection> {
301        Ok(State(Arc::clone(state)))
302    }
303}
304
305impl<StateT> FromRequest<StateT> for PeerAddr
306where
307    StateT: Send + Sync + 'static,
308{
309    type Rejection = Infallible;
310
311    async fn from_request(
312        ctx: &mut RequestContext,
313        _state: &Arc<StateT>,
314    ) -> Result<Self, Self::Rejection> {
315        Ok(PeerAddr(ctx.peer_addr))
316    }
317}
318
319impl<StateT> FromRequest<StateT> for LocalAddr
320where
321    StateT: Send + Sync + 'static,
322{
323    type Rejection = Infallible;
324
325    async fn from_request(
326        ctx: &mut RequestContext,
327        _state: &Arc<StateT>,
328    ) -> Result<Self, Self::Rejection> {
329        Ok(LocalAddr(ctx.local_addr))
330    }
331}
332
333impl<StateT> FromRequest<StateT> for ClientId
334where
335    StateT: Send + Sync + 'static,
336{
337    type Rejection = Infallible;
338
339    async fn from_request(
340        ctx: &mut RequestContext,
341        _state: &Arc<StateT>,
342    ) -> Result<Self, Self::Rejection> {
343        Ok(ClientId(ctx.client_id))
344    }
345}
346
347impl<StateT> FromRequest<StateT> for Extensions
348where
349    StateT: Send + Sync + 'static,
350{
351    type Rejection = Infallible;
352
353    async fn from_request(
354        ctx: &mut RequestContext,
355        _state: &Arc<StateT>,
356    ) -> Result<Self, Self::Rejection> {
357        Ok(ctx.extensions.clone())
358    }
359}