1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
use crate::{
    attribute::IppAttribute,
    operation::{CreateJob, GetPrinterAttributes, IppOperation, PrintJob, SendDocument},
    IppJobSource,
};

/// Builder to create IPP operations
pub struct IppOperationBuilder;

impl IppOperationBuilder {
    /// Create PrintJob operation
    ///
    /// * `source` - `IppJobSource`
    pub fn print_job<T>(source: T) -> PrintJobBuilder
    where
        IppJobSource: From<T>,
    {
        PrintJobBuilder::new(source.into())
    }

    /// Create GetPrinterAttributes operation
    pub fn get_printer_attributes() -> GetPrinterAttributesBuilder {
        GetPrinterAttributesBuilder::new()
    }

    /// Create CreateJob operation
    pub fn create_job() -> CreateJobBuilder {
        CreateJobBuilder::new()
    }

    /// Create SendDocument operation
    ///
    /// * `job_id` - job id returned by Create-Job operation <br/>
    /// * `source` - `IppJobSource` <br/>
    pub fn send_document<T>(job_id: i32, source: T) -> SendDocumentBuilder
    where
        IppJobSource: From<T>,
    {
        SendDocumentBuilder::new(job_id, source.into())
    }
}

/// Builder to create PrintJob operation
pub struct PrintJobBuilder {
    source: IppJobSource,
    user_name: Option<String>,
    job_title: Option<String>,
    attributes: Vec<IppAttribute>,
}

impl PrintJobBuilder {
    fn new(source: IppJobSource) -> PrintJobBuilder {
        PrintJobBuilder {
            source,
            user_name: None,
            job_title: None,
            attributes: Vec::new(),
        }
    }
    /// Specify requesting-user-name attribute
    pub fn user_name(mut self, user_name: &str) -> Self {
        self.user_name = Some(user_name.to_owned());
        self
    }

    /// Specify job-name attribute
    pub fn job_title(mut self, job_title: &str) -> Self {
        self.job_title = Some(job_title.to_owned());
        self
    }

    /// Specify custom job attribute
    pub fn attribute(mut self, attribute: IppAttribute) -> Self {
        self.attributes.push(attribute);
        self
    }

    /// Build operation
    pub fn build(self) -> impl IppOperation {
        let op = PrintJob::new(self.source, self.user_name.as_ref(), self.job_title.as_ref());
        self.attributes.into_iter().fold(op, |mut op, attr| {
            op.add_attribute(attr);
            op
        })
    }
}

/// Builder to create GetPrinterAttributes operation
pub struct GetPrinterAttributesBuilder {
    attributes: Vec<String>,
}

impl GetPrinterAttributesBuilder {
    fn new() -> GetPrinterAttributesBuilder {
        GetPrinterAttributesBuilder { attributes: Vec::new() }
    }

    /// Specify which attribute to retrieve from the printer. Can be repeated.
    pub fn attribute(mut self, attribute: &str) -> Self {
        self.attributes.push(attribute.to_owned());
        self
    }

    /// Specify which attributes to retrieve from the printer
    pub fn attributes<T>(mut self, attributes: &[T]) -> Self
    where
        T: AsRef<str>,
    {
        self.attributes
            .extend(attributes.iter().map(|s| s.as_ref().to_string()));
        self
    }

    /// Build operation
    pub fn build(self) -> impl IppOperation {
        GetPrinterAttributes::with_attributes(&self.attributes)
    }
}

/// Builder to create CreateJob operation
pub struct CreateJobBuilder {
    job_name: Option<String>,
    attributes: Vec<IppAttribute>,
}

impl CreateJobBuilder {
    fn new() -> CreateJobBuilder {
        CreateJobBuilder {
            job_name: None,
            attributes: Vec::new(),
        }
    }

    /// Specify job-name attribute
    pub fn job_name(mut self, job_name: &str) -> Self {
        self.job_name = Some(job_name.to_owned());
        self
    }

    /// Specify custom job attribute
    pub fn attribute(mut self, attribute: IppAttribute) -> Self {
        self.attributes.push(attribute);
        self
    }

    /// Build operation
    pub fn build(self) -> impl IppOperation {
        let op = CreateJob::new(self.job_name.as_ref());
        self.attributes.into_iter().fold(op, |mut op, attr| {
            op.add_attribute(attr);
            op
        })
    }
}

/// Builder to create SendDocument operation
pub struct SendDocumentBuilder {
    job_id: i32,
    source: IppJobSource,
    user_name: Option<String>,
    is_last: bool,
}

impl SendDocumentBuilder {
    fn new(job_id: i32, source: IppJobSource) -> SendDocumentBuilder {
        SendDocumentBuilder {
            job_id,
            source,
            user_name: None,
            is_last: true,
        }
    }

    /// Specify originating-user-name attribute
    pub fn user_name(mut self, user_name: &str) -> Self {
        self.user_name = Some(user_name.to_owned());
        self
    }

    /// Parameter which indicates whether this document is a last one
    pub fn last(mut self, last: bool) -> Self {
        self.is_last = last;
        self
    }

    /// Build operation
    pub fn build(self) -> impl IppOperation {
        SendDocument::new(self.job_id, self.source, self.user_name.as_ref(), self.is_last)
    }
}