#[allow(patterns_in_fns_without_body)] use std::fs::OpenOptions; use std::os::unix::fs::OpenOptionsExt; use std::fs::File; use std::io::Write; use std::error::Error; use std::str; struct PrintJob { chars: Vec } struct ThermalPrinter { port: String, jobQueue: Vec } impl PrintJob { fn new() -> PrintJob { let mut chars: Vec = vec![]; PrintJob { chars: chars, } } } trait PrintJobBuilder { fn header(mut self, text: String) -> PrintJob; fn set_underline(mut self, active: bool) -> PrintJob; fn select_font(mut self, font: String) -> PrintJob; fn select_table(mut self, table: String) -> PrintJob; fn set_rot90(mut self, active: bool) -> PrintJob; fn print(mut self, to_print: String) -> PrintJob; fn feed(mut self, n: u32) -> PrintJob; fn cut(mut self) -> PrintJob; fn build(mut self) -> Option; } impl PrintJobBuilder for PrintJob { fn header(mut self, text: String) -> PrintJob { // TODO big font // append text // self.chars.append() self } // select and deselct underline fn set_underline(mut self, active: bool) -> PrintJob { if active { self.chars.append(&mut vec![0x1b]); self.chars.append(&mut "-1".to_string().into_bytes()); } else { self.chars.append(&mut vec![0x1b]); self.chars.append(&mut "-0".to_string().into_bytes()); } self } // select and font fn select_font(mut self, font: String) -> PrintJob { self.chars.append(&mut vec![0x1b]); self.chars.append(&mut "M".to_string().into_bytes()); self.chars.append(&mut font.to_string().into_bytes()); self } // select and print table fn select_table(mut self, table: String) -> PrintJob { self.chars.append(&mut vec![0x1b]); self.chars.append(&mut "t".to_string().into_bytes()); self.chars.append(&mut table.to_string().into_bytes()); self } // rotate text 90 degrees fn set_rot90(mut self, active: bool) -> PrintJob { if active { self.chars.append(&mut vec![0x1b]); self.chars.append(&mut "V1".to_string().into_bytes()); } else { self.chars.append(&mut vec![0x1b]); self.chars.append(&mut "V0".to_string().into_bytes()); } self } fn print(mut self, to_print: String) -> PrintJob { self.chars.append(&mut to_print.to_string().into_bytes()); self } // append n newlines fn feed(mut self, n: u32) -> PrintJob { for _ in 0..n { self.chars.append(&mut "\n".to_string().into_bytes()) } self } // append 0x1b i to cut the paper fn cut(mut self) -> PrintJob { self.chars.append(&mut vec![0x1b, 0x69]); self } fn build(self) -> Option { if self.chars.len() != 0 { return Some(PrintJob { chars: self.chars.clone() }) } else { return None; } } } impl ThermalPrinter { fn new(port: String) -> ThermalPrinter { let mut jobQueue: Vec = vec![]; ThermalPrinter { port: port, jobQueue: jobQueue, } } fn set_port(&mut self, portaddr: String) { self.port = portaddr } fn get_port(&self) -> &str { &self.port } fn add_job(&mut self, job: PrintJob) { self.jobQueue.push(job); } fn print(&self) { let mut options = OpenOptions::new(); let mut file = options.open("/dev/usb/lp0").unwrap(); for job in &self.jobQueue { let s = match str::from_utf8(&*job.chars) { Ok(v) => match file.write(v.as_bytes()) { Ok(..) => { file.flush().unwrap(); }, Err(e) => println!("{}", e), }, Err(e) => panic!("Invalid UTF-8 sequence: {}", e), }; } } } fn main() { let mut printer = ThermalPrinter::new("/dev/usb/lp0".to_string()); let pj = PrintJob::new() .header("".to_string()) .print("Dies ist ein Test".to_string()) .feed(10) .cut() .build(); printer.add_job(pj.unwrap()); printer.print(); }