//! Run with: cargo run --example printer_polymorphism //! //! Demonstrates the trait+enum pattern that stands in for inheritance: //! - `connect()` is called the same way regardless of vendor (polymorphism), //! but each vendor's `impl Printer` runs completely different code //! (override). //! - `dispatch_gcode()` only exists on `BambuPrinter` (extension) — you //! have to `match` the enum back down to the concrete type to reach it, //! which is the trade-off for not having implicit downcasting. use continuum_proxy::printer::{BambuPrinter, KlipperPrinter, Printer, PrinterHandle, PrusaPrinter}; #[tokio::main] async fn main() { let mut fleet: Vec = vec![ PrinterHandle::Bambu(BambuPrinter::new("p1", "X1 Carbon", "192.168.1.50", "12345678")), PrinterHandle::Prusa(PrusaPrinter::new("p2", "MK4", "192.168.1.51", "prusa-api-key")), PrinterHandle::Klipper(KlipperPrinter::new("p3", "Voron 2.4", "192.168.1.52")), // No host configured — this one will hit the Err path. PrinterHandle::Klipper(KlipperPrinter::new("p4", "Broken Voron", "")), ]; // Uniform call site: every printer connects the same way from the // caller's point of view, even though the three `connect()` bodies // are unrelated implementations. for printer in &mut fleet { match printer.connect().await { Ok(()) => println!(" -> connected: {}\n", printer.display_name()), Err(err) => println!(" -> failed: {err}\n"), } } // Vendor-only extension: reachable only after matching the concrete // variant back out of the enum. for printer in &fleet { if let PrinterHandle::Bambu(bambu) = printer { bambu.dispatch_gcode("part.gcode.3mf"); } } }