curl_easybuilder/
easy.rs

1extern crate curl;
2
3use std::error::Error;
4use std::path::Path;
5use std::time::Duration;
6use curl::easy::{Easy, List};
7use curl::easy::{IpResolve, ProxyType, SslVersion, TimeCondition};
8use curl::easy::{ReadError, WriteError};
9
10use super::errors::*;
11
12/// The builder struct for `curl::easy::Easy` handler.
13///
14/// See the API document of `curl-rust` for detailed descriptions
15/// that `Easy` API provides.
16///
17/// All errors occured during building operations will be stored in a internal `Vec`,
18/// and exposed at finalization, which is when the builder's `build()` method is called.
19pub struct EasyBuilder {
20    easy: Easy,
21    // FIXME: I'm not sure is it reasonable and effective.
22    errors: Vec<curl::Error>,
23}
24
25macro_rules! option_setter {
26    ( $meth:ident, $an:ident: $mt:ty ) => {
27        pub fn $meth(&mut self, $an: $mt) -> &mut EasyBuilder {
28            if let Err(e) = self.easy.$meth($an) {
29                self.errors.push(e);
30            }
31            self
32        }
33    };
34}
35
36macro_rules! path_opt {
37    ( $meth:ident, $an:ident ) => {
38        pub fn $meth<P: AsRef<Path>>(&mut self, $an: P) -> &mut EasyBuilder {
39            if let Err(e) = self.easy.$meth($an) {
40                self.errors.push(e);
41            }
42            self
43        }
44    };
45}
46
47impl EasyBuilder {
48
49    /// Creates a builder.
50    /// # Examples
51    ///
52    /// ```
53    /// use curl_easybuilder::EasyBuilder;
54    ///
55    /// let easy = EasyBuilder::new();
56    /// ```
57    pub fn new() -> EasyBuilder {
58        EasyBuilder {
59            easy: Easy::new(),
60            errors: Vec::new(),
61        }
62    }
63
64    option_setter!(verbose, verbose: bool);
65    option_setter!(show_header, show: bool);
66    option_setter!(progress, progress: bool);
67    option_setter!(signal, signal: bool);
68    option_setter!(wildcard_match, m: bool);
69    option_setter!(fail_on_error, fail: bool);
70    option_setter!(url, url: &str);
71    option_setter!(port, port: u16);
72    option_setter!(proxy, url: &str);
73    option_setter!(proxy_port, port: u16);
74    option_setter!(proxy_type, kind: ProxyType);
75    option_setter!(noproxy, skip: &str);
76    option_setter!(http_proxy_tunnel, tunnel: bool);
77    option_setter!(interface, interface: &str);
78    option_setter!(set_local_port, port: u16);
79    option_setter!(local_port_range, range: u16);
80    option_setter!(dns_cache_timeout, dur: Duration);
81    option_setter!(buffer_size, size: usize);
82    option_setter!(tcp_nodelay, enable: bool);
83    option_setter!(address_scope, scope: u32);
84    option_setter!(username, user: &str);
85    option_setter!(password, pass: &str);
86    option_setter!(proxy_username, user: &str);
87    option_setter!(proxy_password, pass: &str);
88    option_setter!(autoreferer, enable: bool);
89    option_setter!(accept_encoding, encoding: &str);
90    option_setter!(transfer_encoding, enable: bool);
91    option_setter!(follow_location, enable: bool);
92    option_setter!(unrestricted_auth, enable: bool);
93    option_setter!(max_redirections, max: u32);
94    option_setter!(put, enable: bool);
95    option_setter!(post, enable: bool);
96    option_setter!(post_fields_copy, data: &[u8]);
97    option_setter!(post_field_size, size: u64);
98    option_setter!(referer, referer: &str);
99    option_setter!(useragent, useragent: &str);
100    option_setter!(http_headers, list: List);
101    option_setter!(cookie, cookie: &str);
102    path_opt!(cookie_file, file);
103    path_opt!(cookie_jar, file);
104    option_setter!(cookie_session, session: bool);
105    option_setter!(cookie_list, cookie: &str);
106    option_setter!(get, enable: bool);
107    option_setter!(ignore_content_length, ignore: bool);
108    option_setter!(http_content_decoding, enable: bool);
109    option_setter!(http_transfer_decoding, enable: bool);
110    option_setter!(range, range: &str);
111    option_setter!(resume_from, from: u64);
112    option_setter!(custom_request, request: &str);
113    option_setter!(fetch_filetime, fetch: bool);
114    option_setter!(nobody, enable: bool);
115    option_setter!(in_filesize, size: u64);
116    option_setter!(upload, enable: bool);
117    option_setter!(max_filesize, size: u64);
118    option_setter!(time_condition, cond: TimeCondition);
119    option_setter!(time_value, val: i64);
120    option_setter!(timeout, timeout: Duration);
121    option_setter!(low_speed_limit, limit: u32);
122    option_setter!(low_speed_time, dur: Duration);
123    option_setter!(max_send_speed, speed: u64);
124    option_setter!(max_recv_speed, speed: u64);
125    option_setter!(max_connects, max: u32);
126    option_setter!(fresh_connect, enable: bool);
127    option_setter!(forbid_reuse, enable: bool);
128    option_setter!(connect_timeout, timeout: Duration);
129    option_setter!(ip_resolve, resolve: IpResolve);
130    option_setter!(connect_only, enable: bool);
131    path_opt!(ssl_cert, cert);
132    option_setter!(ssl_cert_type, kind: &str);
133    path_opt!(ssl_key, key);
134    option_setter!(ssl_key_type, kind: &str);
135    option_setter!(key_password, password: &str);
136    option_setter!(ssl_engine, engine: &str);
137    option_setter!(ssl_engine_default, enable: bool);
138    option_setter!(ssl_version, version: SslVersion);
139    option_setter!(ssl_verify_host, verify: bool);
140    option_setter!(ssl_verify_peer, verify: bool);
141    path_opt!(cainfo, path);
142    path_opt!(issuer_cert, path);
143    path_opt!(capath, path);
144    path_opt!(crlfile, path);
145    option_setter!(certinfo, enable: bool);
146    path_opt!(random_file, p);
147    path_opt!(egd_socket, p);
148    option_setter!(ssl_cipher_list, ciphers: &str);
149    option_setter!(ssl_sessionid_cache, enable: bool);
150
151    pub fn write_function<F>(&mut self, f: F) -> &mut EasyBuilder
152        where F: FnMut(&[u8]) -> Result<usize, WriteError> + Send + 'static
153    {
154        if let Err(e) = self.easy.write_function(f) {
155            self.errors.push(e);
156        }
157        self
158    }
159
160    pub fn read_function<F>(&mut self, f: F) -> &mut EasyBuilder
161        where F: FnMut(&mut [u8]) -> Result<usize, ReadError> + Send + 'static
162    {
163        if let Err(e) = self.easy.read_function(f) {
164            self.errors.push(e);
165        }
166        self
167    }
168
169    /// Tests if the builder stores any `curl::Error` happend during this build.
170    pub fn has_errors(&self) -> bool {
171        !self.errors.is_empty()
172    }
173
174    /// Finalize the builder and returns mutable reference of `Easy` wrapped inside a `Result`.
175    ///
176    /// # Examples
177    ///
178    /// ```
179    /// use curl_easybuilder::EasyBuilder;
180    ///
181    /// let mut b = EasyBuilder::new();
182    /// assert!(b.result().is_ok());
183    /// ```
184    pub fn result(&mut self) -> BuildResult<&mut Easy> {
185        if !self.has_errors() {
186            Ok(&mut self.easy)
187        } else {
188            let mut s = String::new();
189            for e in &self.errors {
190                s.push_str(e.description());
191                s.push('\n');
192            }
193            Err(BuildError::from(s))
194        }
195    }
196}