📄 src/receipt_printer/mod.rs
mod escpos_printer;
mod receipt_printer_actor;
mod receipt_printer_error;

use std::sync::Arc;

use tokio::sync::{mpsc, oneshot};

use self::receipt_printer_actor::{EscposPrinterActor, EscposPrinterRequest};
use self::receipt_printer_error::ReceiptPrinterError;

pub struct ReceiptPrinter {
    sender: mpsc::UnboundedSender<EscposPrinterRequest>,
}

impl ReceiptPrinter {
    pub const IMAGE_WIDTH_PIXEL: u32 = 72 * 8;
    pub const IMAGE_WIDTH_CM: f32 = 7.2;
    pub const IMAGE_WIDTH_PT: f32 = Self::IMAGE_WIDTH_CM / 0.03527;
    pub const IMAGE_PIXELS_PER_PT: f32 = Self::IMAGE_WIDTH_PIXEL as f32 / Self::IMAGE_WIDTH_PT;

    pub fn init(host: String, port: u16) -> Self {
        let (sender, receiver) = mpsc::unbounded_channel();

        EscposPrinterActor::run(host, port, receiver);

        Self { sender }
    }

    pub async fn print_image(&self, image: Arc<[u8]>) -> Result<(), ReceiptPrinterError> {
        let (responder, receiver) = oneshot::channel();
        self.sender
            .send(EscposPrinterRequest::PrintImage(image, responder))
            .map_err(ReceiptPrinterError::send)?;
        receiver
            .await
            .map_err(ReceiptPrinterError::receive)?
            .map_err(ReceiptPrinterError::printer)
    }
}