use std::io::{self, Read, Write};
use byteorder::{BigEndian, WriteBytesExt};
use attribute::{IppAttribute, IppAttributeList};
use ::{Result, IPP_VERSION};
use consts::tag::*;
use consts::attribute::*;
use value::IppValue;
pub struct IppRequest<'a> {
operation: u16,
uri: String,
attributes: IppAttributeList,
payload: Option<&'a mut Read>
}
impl<'a> IppRequest<'a> {
pub fn new(operation: u16, uri: &str) -> IppRequest<'a> {
let mut retval = IppRequest {
operation: operation,
uri: uri.to_string(),
attributes: IppAttributeList::new(),
payload: None };
retval.set_attribute(
OPERATION_ATTRIBUTES_TAG,
IppAttribute::new(ATTRIBUTES_CHARSET,
IppValue::Charset("utf-8".to_string())));
retval.set_attribute(
OPERATION_ATTRIBUTES_TAG,
IppAttribute::new(ATTRIBUTES_NATURAL_LANGUAGE,
IppValue::NaturalLanguage("en".to_string())));
retval.set_attribute(
OPERATION_ATTRIBUTES_TAG,
IppAttribute::new(PRINTER_URI,
IppValue::Uri(uri.replace("http", "ipp").to_string())));
retval
}
pub fn uri(&self) -> &String {
&self.uri
}
pub fn set_payload(&mut self, payload: &'a mut Read) {
self.payload = Some(payload)
}
pub fn set_attribute(&mut self, group: u8, attribute: IppAttribute) {
self.attributes.add(group, attribute);
}
pub fn write(&'a mut self, writer: &mut Write) -> Result<usize> {
let mut retval = 0;
try!(writer.write_u16::<BigEndian>(IPP_VERSION));
retval += 2;
try!(writer.write_u16::<BigEndian>(self.operation));
retval += 2;
try!(writer.write_u32::<BigEndian>(1));
retval += 4;
retval += try!(self.attributes.write(writer));
debug!("Wrote {} bytes IPP stream", retval);
match self.payload {
Some(ref mut payload) => {
let size = try!(io::copy(payload, writer)) as usize;
debug!("Wrote {} bytes payload", size);
retval += size;
}
None => {}
}
Ok(retval)
}
}