1pub use capi::screquest::{HREQUEST, REQUEST_RESULT};
10pub use capi::screquest::{REQUEST_METHOD, REQUEST_STATE, REQUEST_TYPE, RESOURCE_TYPE};
11
12use capi::sctypes::{LPVOID, UINT};
13use capi::scdef::{LPCWSTR_RECEIVER};
14
15use utf::{store_astr, store_wstr, store_bstr};
16
17use _RAPI;
18
19
20
21macro_rules! ok_or {
22 ($ok:ident) => {
23 ok_or!((), $ok)
24 };
25
26 ($rv:expr, $ok:ident) => {
27 if $ok == REQUEST_RESULT::OK {
28 Ok($rv)
29 } else {
30 Err($ok)
31 }
32 };
33}
34
35pub type Result<T> = ::std::result::Result<T, REQUEST_RESULT>;
37
38type GetCountFn = extern "system" fn (rq: HREQUEST, pNumber: &mut UINT) -> REQUEST_RESULT;
39type GetNameFn = extern "system" fn (rq: HREQUEST, n: UINT, rcv: LPCWSTR_RECEIVER, rcv_param: LPVOID) -> REQUEST_RESULT;
40type GetValueFn = extern "system" fn (rq: HREQUEST, n: UINT, rcv: LPCWSTR_RECEIVER, rcv_param: LPVOID) -> REQUEST_RESULT;
41
42pub struct Request(HREQUEST);
56
57impl Drop for Request {
59 fn drop(&mut self) {
60 (_RAPI.RequestUnUse)(self.0);
61 }
62}
63
64impl Clone for Request {
68 fn clone(&self) -> Self {
69 let dst = Request(self.0);
70 (_RAPI.RequestUse)(dst.0);
71 dst
72 }
73}
74
75impl From<HREQUEST> for Request {
77 fn from(hrq: HREQUEST) -> Request {
78 assert!(!hrq.is_null());
79 (_RAPI.RequestUse)(hrq);
80 Request(hrq)
81 }
82}
83
84impl Request {
85 pub fn succeeded(&mut self, status: u32, data: Option<&[u8]>) -> Result<()> {
87 let (ptr, size) = if let Some(data) = data {
88 (data.as_ptr(), data.len() as u32)
89 } else {
90 (std::ptr::null(), 0_u32)
91 };
92 let ok = (_RAPI.RequestSetSucceeded)(self.0, status, ptr, size);
93 ok_or!(ok)
94 }
95
96 pub fn failed(&mut self, status: u32, data: Option<&[u8]>) -> Result<()> {
98 let (ptr, size) = if let Some(data) = data {
99 (data.as_ptr(), data.len() as u32)
100 } else {
101 (std::ptr::null(), 0_u32)
102 };
103 let ok = (_RAPI.RequestSetSucceeded)(self.0, status, ptr, size);
104 ok_or!(ok)
105 }
106
107 pub fn append_received_data(&mut self, data: &[u8]) -> Result<()> {
109 let (ptr, size) = (data.as_ptr(), data.len() as u32);
110 let ok = (_RAPI.RequestAppendDataChunk)(self.0, ptr, size);
111 ok_or!(ok)
112 }
113
114 pub fn get_received_data(&self) -> Result<Vec<u8>> {
116 let mut data = Vec::new();
117 let ok = (_RAPI.RequestGetData)(self.0, store_bstr, &mut data as *mut _ as LPVOID);
118 ok_or!(data, ok)
119 }
120
121 pub fn url(&self) -> Result<String> {
123 let mut s = String::new();
124 let ok = (_RAPI.RequestUrl)(self.0, store_astr, &mut s as *mut _ as LPVOID);
125 ok_or!(s, ok)
126 }
127
128 pub fn content_url(&self) -> Result<String> {
130 let mut s = String::new();
131 let ok = (_RAPI.RequestContentUrl)(self.0, store_astr, &mut s as *mut _ as LPVOID);
132 ok_or!(s, ok)
133 }
134
135 pub fn method(&self) -> Result<REQUEST_METHOD> {
137 let mut t = REQUEST_METHOD::GET;
138 let ok = (_RAPI.RequestGetRequestType)(self.0, &mut t);
139 ok_or!(t, ok)
140 }
141
142 pub fn request_type(&self) -> Result<RESOURCE_TYPE> {
144 let mut t = RESOURCE_TYPE::RAW;
145 let ok = (_RAPI.RequestGetRequestedDataType)(self.0, &mut t);
146 ok_or!(t, ok)
147 }
148
149 pub fn response_type(&self) -> Result<String> {
151 let mut s = String::new();
152 let ok = (_RAPI.RequestGetReceivedDataType)(self.0, store_astr, &mut s as *mut _ as LPVOID);
153 ok_or!(s, ok)
154 }
155
156 pub fn set_response_type(&mut self, mime_type: &str) -> Result<()> {
158 let text = s2u!(mime_type);
159 let ok = (_RAPI.RequestSetReceivedDataType)(self.0, text.as_ptr());
160 ok_or!(ok)
161 }
162
163 pub fn set_response_encoding(&mut self, encoding_type: &str) -> Result<()> {
165 let text = s2u!(encoding_type);
166 let ok = (_RAPI.RequestSetReceivedDataEncoding)(self.0, text.as_ptr());
167 ok_or!(ok)
168 }
169
170 fn get_collection_impl(&self, get_count: GetCountFn, get_name: GetNameFn, get_value: GetValueFn) -> Result<std::collections::HashMap<String, String>> {
171 let mut count = 0;
172 let ok = get_count(self.0, &mut count);
173 if ok != REQUEST_RESULT::OK {
174 return Err(ok);
175 }
176
177 let mut args = std::collections::HashMap::with_capacity(count as usize);
178 for i in 0..count {
179 let mut name = String::new();
180 let mut ok = get_name(self.0, i, store_wstr, &mut name as *mut _ as LPVOID);
181 if ok == REQUEST_RESULT::OK {
182 let mut value = String::new();
183 ok = get_value(self.0, i, store_wstr, &mut value as *mut _ as LPVOID);
184 if ok == REQUEST_RESULT::OK {
185 args.insert(name, value);
186 }
187 }
188 if ok != REQUEST_RESULT::OK {
189 return Err(ok);
190 }
191 }
192
193 Ok(args)
194 }
195
196 pub fn parameters(&self) -> Result<std::collections::HashMap<String, String>> {
198 self.get_collection_impl(_RAPI.RequestGetNumberOfParameters, _RAPI.RequestGetNthParameterName, _RAPI.RequestGetNthParameterValue)
199 }
200
201 pub fn request_headers(&self) -> Result<std::collections::HashMap<String, String>> {
203 self.get_collection_impl(_RAPI.RequestGetNumberOfRqHeaders, _RAPI.RequestGetNthRqHeaderName, _RAPI.RequestGetNthRqHeaderValue)
204 }
205
206 pub fn set_request_header(&mut self, name: &str, value: &str) -> Result<()> {
208 let wname = s2w!(name);
209 let wtext = s2w!(value);
210 let ok = (_RAPI.RequestSetRqHeader)(self.0, wname.as_ptr(), wtext.as_ptr());
211 ok_or!(ok)
212 }
213
214 pub fn response_headers(&self) -> Result<std::collections::HashMap<String, String>> {
216 self.get_collection_impl(_RAPI.RequestGetNumberOfRspHeaders, _RAPI.RequestGetNthRspHeaderName, _RAPI.RequestGetNthRspHeaderValue)
217 }
218
219 pub fn set_response_header(&mut self, name: &str, value: &str) -> Result<()> {
221 let wname = s2w!(name);
222 let wtext = s2w!(value);
223 let ok = (_RAPI.RequestSetRspHeader)(self.0, wname.as_ptr(), wtext.as_ptr());
224 ok_or!(ok)
225 }
226
227 pub fn proxy(&self) -> Result<(String, u16)> {
229 let mut s = String::new();
230 let mut ok = (_RAPI.RequestGetProxyHost)(self.0, store_astr, &mut s as *mut _ as LPVOID);
231 if ok == REQUEST_RESULT::OK {
232 let mut n = 0_u32;
233 ok = (_RAPI.RequestGetProxyPort)(self.0, &mut n);
234 if ok == REQUEST_RESULT::OK {
235 return Ok((s, n as u16));
236 }
237 }
238 Err(ok)
239 }
240
241 pub fn completion_status(&self) -> Result<(REQUEST_STATE, u32)> {
245 let mut state = REQUEST_STATE::SUCCESS;
246 let mut code = 0_u32;
247 let ok = (_RAPI.RequestGetCompletionStatus)(self.0, &mut state, &mut code);
248 ok_or!((state, code), ok)
249 }
250
251 pub fn request_duration(&self) -> Result<std::time::Duration> {
253 let mut started = 0;
254 let mut ended = 0;
255 let ok = (_RAPI.RequestGetTimes)(self.0, &mut started, &mut ended);
256 if ok == REQUEST_RESULT::OK && ended > started {
257 let d = std::time::Duration::from_millis(ended as u64 - started as u64);
258 Ok(d)
259 } else {
260 Err(ok)
261 }
262 }
263
264 pub fn request_time(&self) -> Result<(std::time::Duration, std::time::Duration)> {
266 let mut started = 0;
267 let mut ended = 0;
268 let ok = (_RAPI.RequestGetTimes)(self.0, &mut started, &mut ended);
269 if ok == REQUEST_RESULT::OK {
270 use std::time::Duration;
271 let s = Duration::from_millis(started as u64);
272 let e = Duration::from_millis(ended as u64);
273 Ok((s, e))
274 } else {
275 Err(ok)
276 }
277 }
278
279}