1
1
// TODO: Eventually to be replaced with tower_util::Oneshot.
2
2
3
- use std:: marker:: Unpin ;
4
- use std:: mem;
5
-
3
+ use pin_project:: pin_project;
6
4
use tower_service:: Service ;
7
5
8
6
use crate :: common:: { task, Future , Pin , Poll } ;
@@ -20,49 +18,43 @@ where
20
18
// is ready, and then calling `Service::call` with the request, and
21
19
// waiting for that `Future`.
22
20
#[ allow( missing_debug_implementations) ]
21
+ #[ pin_project]
23
22
pub struct Oneshot < S : Service < Req > , Req > {
23
+ #[ pin]
24
24
state : State < S , Req > ,
25
25
}
26
26
27
+ #[ pin_project( Replace , project = StateProj , project_replace = StateProjOwn ) ]
27
28
enum State < S : Service < Req > , Req > {
28
29
NotReady ( S , Req ) ,
29
- Called ( S :: Future ) ,
30
+ Called ( # [ pin ] S :: Future ) ,
30
31
Tmp ,
31
32
}
32
33
33
- // Unpin is projected to S::Future, but never S.
34
- impl < S , Req > Unpin for Oneshot < S , Req >
35
- where
36
- S : Service < Req > ,
37
- S :: Future : Unpin ,
38
- {
39
- }
40
-
41
34
impl < S , Req > Future for Oneshot < S , Req >
42
35
where
43
36
S : Service < Req > ,
44
37
{
45
38
type Output = Result < S :: Response , S :: Error > ;
46
39
47
40
fn poll ( self : Pin < & mut Self > , cx : & mut task:: Context < ' _ > ) -> Poll < Self :: Output > {
48
- // Safety: The service's future is never moved once we get one.
49
- let mut me = unsafe { Pin :: get_unchecked_mut ( self ) } ;
41
+ let mut me = self . project ( ) ;
50
42
51
43
loop {
52
- match me. state {
53
- State :: NotReady ( ref mut svc, _) => {
44
+ match me. state . as_mut ( ) . project ( ) {
45
+ StateProj :: NotReady ( ref mut svc, _) => {
54
46
ready ! ( svc. poll_ready( cx) ) ?;
55
47
// fallthrough out of the match's borrow
56
48
}
57
- State :: Called ( ref mut fut) => {
58
- return unsafe { Pin :: new_unchecked ( fut) } . poll ( cx) ;
49
+ StateProj :: Called ( fut) => {
50
+ return fut. poll ( cx) ;
59
51
}
60
- State :: Tmp => unreachable ! ( ) ,
52
+ StateProj :: Tmp => unreachable ! ( ) ,
61
53
}
62
54
63
- match mem :: replace ( & mut me. state , State :: Tmp ) {
64
- State :: NotReady ( mut svc, req) => {
65
- me. state = State :: Called ( svc. call ( req) ) ;
55
+ match me. state . as_mut ( ) . project_replace ( State :: Tmp ) {
56
+ StateProjOwn :: NotReady ( mut svc, req) => {
57
+ me. state . set ( State :: Called ( svc. call ( req) ) ) ;
66
58
}
67
59
_ => unreachable ! ( ) ,
68
60
}
0 commit comments