use std::{
fmt, io,
path::{Path, PathBuf},
};
use ipp_proto::{ipp::StatusCode, ParseError};
pub use crate::client::IppClient;
pub mod client;
#[derive(Debug)]
pub enum IppError {
HttpError(reqwest::Error),
IOError(::std::io::Error),
StatusError(StatusCode),
PrinterStateError(Vec<String>),
PrinterStopped,
ParamError(String),
ParseError(ParseError),
MissingAttribute,
InvalidAttributeType,
}
impl fmt::Display for IppError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
IppError::HttpError(ref e) => write!(f, "{}", e),
IppError::IOError(ref e) => write!(f, "{}", e),
IppError::StatusError(ref e) => write!(f, "IPP status error: {}", e),
IppError::ParamError(ref e) => write!(f, "IPP param error: {}", e),
IppError::PrinterStateError(ref e) => write!(f, "IPP printer state error: {:?}", e),
IppError::PrinterStopped => write!(f, "IPP printer stopped"),
IppError::ParseError(ref e) => write!(f, "{}", e),
IppError::MissingAttribute => write!(f, "Missing attribute in response"),
IppError::InvalidAttributeType => write!(f, "Invalid attribute type"),
}
}
}
impl From<io::Error> for IppError {
fn from(error: io::Error) -> Self {
IppError::IOError(error)
}
}
impl From<StatusCode> for IppError {
fn from(code: StatusCode) -> Self {
IppError::StatusError(code)
}
}
impl From<reqwest::Error> for IppError {
fn from(error: reqwest::Error) -> Self {
IppError::HttpError(error)
}
}
impl From<ParseError> for IppError {
fn from(error: ParseError) -> Self {
IppError::ParseError(error)
}
}
impl std::error::Error for IppError {}
pub struct IppClientBuilder {
uri: String,
ca_certs: Vec<PathBuf>,
verify_hostname: bool,
verify_certificate: bool,
timeout: u64,
}
impl IppClientBuilder {
pub fn new(uri: &str) -> Self {
IppClientBuilder {
uri: uri.to_owned(),
ca_certs: Vec::new(),
verify_hostname: true,
verify_certificate: true,
timeout: 0,
}
}
pub fn ca_cert<P>(mut self, path: P) -> Self
where
P: AsRef<Path>,
{
self.ca_certs.push(path.as_ref().to_owned());
self
}
pub fn ca_certs<I, P>(mut self, paths: I) -> Self
where
I: IntoIterator<Item = P>,
P: AsRef<Path>,
{
self.ca_certs.extend(paths.into_iter().map(|p| p.as_ref().to_owned()));
self
}
pub fn verify_hostname(mut self, verify: bool) -> Self {
self.verify_hostname = verify;
self
}
pub fn verify_certificate(mut self, verify: bool) -> Self {
self.verify_certificate = verify;
self
}
pub fn timeout(mut self, timeout: u64) -> Self {
self.timeout = timeout;
self
}
pub fn build(self) -> IppClient {
IppClient {
uri: self.uri,
ca_certs: self.ca_certs,
verify_hostname: self.verify_hostname,
verify_certificate: self.verify_certificate,
timeout: self.timeout,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_builder() {
let mut builder = IppClientBuilder::new("foobar");
assert_eq!(builder.uri, "foobar");
let cert = PathBuf::from("mycert");
builder = builder.ca_cert(&cert);
assert_eq!(builder.ca_certs, vec![cert.clone()]);
builder = builder.ca_certs(&[cert.clone()]);
assert_eq!(builder.ca_certs, vec![cert.clone(), cert.clone()]);
builder = builder.verify_hostname(false);
assert!(!builder.verify_hostname);
builder = builder.verify_certificate(false);
assert!(!builder.verify_certificate);
builder = builder.timeout(100);
assert_eq!(builder.timeout, 100);
let _ = builder.build();
}
}