1use std::{
2 fmt, io,
3 path::{Path, PathBuf},
4};
5
6use ipp_proto::{ipp::StatusCode, ParseError};
7
8pub use crate::client::IppClient;
9
10pub mod client;
11
12#[derive(Debug)]
14pub enum IppError {
15 HttpError(reqwest::Error),
17 IOError(::std::io::Error),
19 StatusError(StatusCode),
21 PrinterStateError(Vec<String>),
23 PrinterStopped,
25 ParamError(String),
27 ParseError(ParseError),
29 MissingAttribute,
31 InvalidAttributeType,
33}
34
35impl fmt::Display for IppError {
36 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
37 match *self {
38 IppError::HttpError(ref e) => write!(f, "{}", e),
39 IppError::IOError(ref e) => write!(f, "{}", e),
40 IppError::StatusError(ref e) => write!(f, "IPP status error: {}", e),
41 IppError::ParamError(ref e) => write!(f, "IPP param error: {}", e),
42 IppError::PrinterStateError(ref e) => write!(f, "IPP printer state error: {:?}", e),
43 IppError::PrinterStopped => write!(f, "IPP printer stopped"),
44 IppError::ParseError(ref e) => write!(f, "{}", e),
45 IppError::MissingAttribute => write!(f, "Missing attribute in response"),
46 IppError::InvalidAttributeType => write!(f, "Invalid attribute type"),
47 }
48 }
49}
50
51impl From<io::Error> for IppError {
52 fn from(error: io::Error) -> Self {
53 IppError::IOError(error)
54 }
55}
56
57impl From<StatusCode> for IppError {
58 fn from(code: StatusCode) -> Self {
59 IppError::StatusError(code)
60 }
61}
62
63impl From<reqwest::Error> for IppError {
64 fn from(error: reqwest::Error) -> Self {
65 IppError::HttpError(error)
66 }
67}
68
69impl From<ParseError> for IppError {
70 fn from(error: ParseError) -> Self {
71 IppError::ParseError(error)
72 }
73}
74
75impl std::error::Error for IppError {}
76
77pub struct IppClientBuilder {
79 uri: String,
80 ca_certs: Vec<PathBuf>,
81 verify_hostname: bool,
82 verify_certificate: bool,
83 timeout: u64,
84}
85
86impl IppClientBuilder {
87 pub fn new(uri: &str) -> Self {
89 IppClientBuilder {
90 uri: uri.to_owned(),
91 ca_certs: Vec::new(),
92 verify_hostname: true,
93 verify_certificate: true,
94 timeout: 0,
95 }
96 }
97
98 pub fn ca_cert<P>(mut self, path: P) -> Self
100 where
101 P: AsRef<Path>,
102 {
103 self.ca_certs.push(path.as_ref().to_owned());
104 self
105 }
106
107 pub fn ca_certs<I, P>(mut self, paths: I) -> Self
109 where
110 I: IntoIterator<Item = P>,
111 P: AsRef<Path>,
112 {
113 self.ca_certs.extend(paths.into_iter().map(|p| p.as_ref().to_owned()));
114 self
115 }
116
117 pub fn verify_hostname(mut self, verify: bool) -> Self {
119 self.verify_hostname = verify;
120 self
121 }
122
123 pub fn verify_certificate(mut self, verify: bool) -> Self {
125 self.verify_certificate = verify;
126 self
127 }
128
129 pub fn timeout(mut self, timeout: u64) -> Self {
131 self.timeout = timeout;
132 self
133 }
134
135 pub fn build(self) -> IppClient {
137 IppClient {
138 uri: self.uri,
139 ca_certs: self.ca_certs,
140 verify_hostname: self.verify_hostname,
141 verify_certificate: self.verify_certificate,
142 timeout: self.timeout,
143 }
144 }
145}
146
147#[cfg(test)]
148mod tests {
149 use super::*;
150
151 #[test]
152 fn test_builder() {
153 let mut builder = IppClientBuilder::new("foobar");
154 assert_eq!(builder.uri, "foobar");
155
156 let cert = PathBuf::from("mycert");
157 builder = builder.ca_cert(&cert);
158 assert_eq!(builder.ca_certs, vec![cert.clone()]);
159
160 builder = builder.ca_certs(&[cert.clone()]);
161 assert_eq!(builder.ca_certs, vec![cert.clone(), cert.clone()]);
162
163 builder = builder.verify_hostname(false);
164 assert!(!builder.verify_hostname);
165
166 builder = builder.verify_certificate(false);
167 assert!(!builder.verify_certificate);
168
169 builder = builder.timeout(100);
170 assert_eq!(builder.timeout, 100);
171
172 let _ = builder.build();
173 }
174}