///|
/// A plan is a preview, not permission to retry a network submission.
pub(all) struct PrintPlan {
printer : String
options : JobOptions
document_bytes : Int
diagnostics : Array[Diagnostic]
} derive(Debug)
///|
pub extend PrintPlan with @debug.Debug::{to_repr}
///|
pub fn PrintPlan::can_submit(self : PrintPlan) -> Bool {
self.document_bytes > 0 &&
!self.diagnostics.any(fn(item) { item.severity == Error })
}
///|
pub fn Capabilities::plan(
self : Capabilities,
options : JobOptions,
document_bytes : Int,
) -> PrintPlan raise IppError {
if document_bytes < 0 {
raise Invalid("document byte count cannot be negative")
}
let diagnostics = self.validate_options(options, document_bytes~)
if document_bytes == 0 {
diagnostics.push({
severity: Error,
attribute: "document",
message: "empty document cannot be submitted",
})
}
if self.supports_operation(PrintJob) == Some(false) {
diagnostics.push({
severity: Error,
attribute: "operations-supported",
message: "printer does not support Print-Job",
})
}
let health = self.health()
for diagnostic in health.diagnostics {
diagnostics.push(diagnostic)
}
{ printer: self.name(), options, document_bytes, diagnostics, }
}
///|
/// Select only an explicitly advertised input format. No conversion is implied.
pub fn Capabilities::choose_format(
self : Capabilities,
candidates : Array[String],
) -> String raise IppError {
let supported = self.document_formats()
for format in candidates {
if !valid_mime_type(format) {
raise Invalid("invalid candidate MIME type")
}
if supported.contains(format) {
return format
}
}
raise Unsupported("none of the supplied document formats is advertised")
}
///|
pub fn Capabilities::default_options(
self : Capabilities,
name : String,
format : String,
) -> JobOptions raise IppError {
let base = JobOptions::new(name, format)
let copies = match self.printer.get_int("copies-default") {
Some(n) if n > 0 => n
_ => 1
}
let sides = match self.printer.get_string("sides-default") {
Some("one-sided") => Some(OneSided)
Some("two-sided-long-edge") => Some(TwoSidedLongEdge)
Some("two-sided-short-edge") => Some(TwoSidedShortEdge)
_ => None
}
let resolution = match self.printer.find("printer-resolution-default") {
Some(attribute) =>
match attribute.first() {
Some(ResolutionValue(value)) => Some(value)
_ => None
}
None => None
}
let options = JobOptions::{
..base,
copies,
sides,
resolution,
media: self.printer.get_string("media-default"),
color_mode: self.printer.get_string("print-color-mode-default"),
print_quality: self.printer.get_int("print-quality-default"),
orientation: self.printer.get_int("orientation-requested-default"),
number_up: self.printer.get_int("number-up-default"),
}
options.validate()
self.require_options(options)
options
}
///|
pub fn JobOptions::to_json(self : JobOptions) -> Json {
{
"name": Json::string(self.name),
"document_format": Json::string(self.document_format),
"copies": json_int(self.copies),
"media": match self.media {
Some(value) => Json::string(value)
None => Json::null()
},
"sides": match self.sides {
Some(value) => Json::string(value.keyword())
None => Json::null()
},
"color_mode": match self.color_mode {
Some(value) => Json::string(value)
None => Json::null()
},
"resolution": match self.resolution {
Some(value) =>
{
"x": json_int(value.x),
"y": json_int(value.y),
"units": json_int(value.units),
}
None => Json::null()
},
"print_quality": match self.print_quality {
Some(value) => json_int(value)
None => Json::null()
},
"orientation": match self.orientation {
Some(value) => json_int(value)
None => Json::null()
},
"number_up": match self.number_up {
Some(value) => json_int(value)
None => Json::null()
},
"page_ranges": Json::array(
self.page_ranges.map(range => {
let value : Json = {
"first": json_int(range.first),
"last": json_int(range.last),
}
value
}),
),
}
}
///|
pub fn PrintPlan::to_json(self : PrintPlan) -> Json {
{
"printer": Json::string(self.printer),
"options": self.options.to_json(),
"document_bytes": json_int(self.document_bytes),
"can_submit": Json::boolean(self.can_submit()),
"diagnostics": Json::array(self.diagnostics.map(item => item.to_json())),
}
}
///|
pub fn Capabilities::summary_json(self : Capabilities) -> Json {
{
"health": self.health().to_json(),
"document_formats": Json::array(
self.document_formats().map(value => Json::string(value)),
),
"media": Json::array(self.media().map(value => Json::string(value))),
"sides": Json::array(
self.strings("sides-supported").map(value => Json::string(value)),
),
"color_modes": Json::array(
self
.strings("print-color-mode-supported")
.map(value => Json::string(value)),
),
"resolutions": Json::array(
self
.resolutions()
.map(value => {
let resolution : Json = {
"x": json_int(value.x),
"y": json_int(value.y),
"units": json_int(value.units),
}
resolution
}),
),
"operations": Json::array(
self
.integers("operations-supported")
.map(code => {
let operation : Json = {
"code": json_int(code),
"name": match operation_from_code(code) {
Some(value) => Json::string(value.name())
None => Json::string("unknown")
},
}
operation
}),
),
}
}