mio_httpc/api/
simple_call.rs

1use crate::{Call, CallRef, Httpc, RecvState, ResponseBody, SendState};
2
3#[derive(Clone, Copy, PartialEq, Eq)]
4enum State {
5    Sending,
6    Receiving,
7    Done,
8}
9
10/// Simplified API for non-streaming requests and responses.
11/// If body exists it needs to be provided to Request. If response has a body
12/// it is returned in Response.
13pub struct SimpleCall {
14    state: State,
15    id: Call,
16    resp: Option<crate::Response>,
17    resp_body: Option<Vec<u8>>,
18}
19
20impl SimpleCall {
21    pub fn is_ref(&self, r: CallRef) -> bool {
22        self.id.is_ref(r)
23    }
24
25    pub fn call(&self) -> &Call {
26        &self.id
27    }
28
29    /// Replaces self with an empty SimpleCall and returns result if any.
30    pub fn finish_inplace(&mut self) -> Option<(crate::Response, Vec<u8>)> {
31        let out = ::std::mem::replace(self, SimpleCall::empty());
32        out.finish()
33    }
34
35    /// Consume and return response with body.
36    pub fn finish(mut self) -> Option<(crate::Response, Vec<u8>)> {
37        let r = self.resp.take();
38        let b = self.resp_body.take();
39        if let Some(rs) = r {
40            if let Some(rb) = b {
41                // ::std::mem::replace(rs.body_mut(), rb);
42                return Some((rs, rb));
43            }
44            return Some((rs, Vec::new()));
45        }
46        None
47    }
48
49    /// Abort and replace self with an empty call.
50    pub fn abort_inplace(&mut self, htp: &mut Httpc) {
51        let out = ::std::mem::replace(self, SimpleCall::empty());
52        htp.call_close(out.id);
53    }
54
55    /// Consume and abort call.
56    pub fn abort(self, htp: &mut Httpc) {
57        htp.call_close(self.id);
58    }
59
60    /// For quick comparison with httpc::event response.
61    /// If cid is none will return false.
62    pub fn is_call(&self, cid: &Option<CallRef>) -> bool {
63        if let &Some(ref b) = cid {
64            return self.id.is_ref(*b);
65        }
66        false
67    }
68
69    /// If using Option<SimpleCall> in a struct, you can quickly compare
70    /// callid from httpc::event. If either is none will return false.
71    pub fn is_opt_callid(a: &Option<SimpleCall>, b: &Option<CallRef>) -> bool {
72        if let &Some(ref a) = a {
73            if let &Some(ref b) = b {
74                return a.is_ref(*b);
75            }
76        }
77        false
78    }
79
80    /// Is request finished.
81    pub fn is_done(&self) -> bool {
82        self.state == State::Done
83    }
84
85    /// Are we in receiving state
86    pub fn is_receiving(&self) -> bool {
87        self.state == State::Receiving
88    }
89
90    /// Perform operation. Returns true if request is finished.
91    pub fn perform(&mut self, htp: &mut Httpc, poll: &::mio::Registry) -> crate::Result<bool> {
92        if self.is_done() {
93            return Ok(true);
94        }
95        if self.state == State::Sending {
96            match htp.call_send(poll, &mut self.id, None) {
97                SendState::Wait => {}
98                SendState::Receiving => {
99                    self.state = State::Receiving;
100                }
101                SendState::SentBody(_) => {}
102                SendState::Error(e) => {
103                    self.state = State::Done;
104                    return Err(From::from(e));
105                }
106                SendState::WaitReqBody => {
107                    self.state = State::Done;
108                    return Err(crate::Error::MissingBody);
109                }
110                SendState::Done => {
111                    self.state = State::Done;
112                    return Ok(true);
113                }
114            }
115        }
116        if self.state == State::Receiving {
117            loop {
118                match htp.call_recv(poll, &mut self.id, None) {
119                    RecvState::DoneWithBody(b) => {
120                        self.resp_body = Some(b);
121                        self.state = State::Done;
122                        return Ok(true);
123                    }
124                    RecvState::Done => {
125                        self.state = State::Done;
126                        return Ok(true);
127                    }
128                    RecvState::Error(e) => {
129                        self.state = State::Done;
130                        return Err(From::from(e));
131                    }
132                    RecvState::Response(r, body) => {
133                        self.resp = Some(r);
134                        match body {
135                            ResponseBody::Sized(0) => {
136                                self.state = State::Done;
137                                return Ok(true);
138                            }
139                            _ => {}
140                        }
141                    }
142                    RecvState::Wait => {
143                        break;
144                    }
145                    RecvState::Sending => {
146                        self.state = State::Sending;
147                        return self.perform(htp, poll);
148                    }
149                    RecvState::ReceivedBody(_s) => {}
150                }
151            }
152        }
153        Ok(false)
154    }
155
156    /// An empty SimpleCall not associated with a valid mio::Token/CallId.
157    /// Exists to be overwritten with an actual valid request.
158    /// Always returns is_done true.
159    pub fn empty() -> SimpleCall {
160        SimpleCall {
161            state: State::Done,
162            id: crate::Call::empty(),
163            resp: None,
164            resp_body: None,
165        }
166    }
167
168    pub fn is_empty(&self) -> bool {
169        self.id.is_empty()
170    }
171}
172impl From<Call> for SimpleCall {
173    fn from(v: Call) -> SimpleCall {
174        SimpleCall {
175            state: State::Sending,
176            id: v,
177            resp: None,
178            resp_body: None,
179        }
180    }
181}