//! 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 variant's `impl GenericPrinter` runs completely different //! code (override). //! - `dispatch_gcode()` only exists on the two Bambu structs (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::{ BambuTls, BambuV1Printer, BambuV2Printer, GenericPrinter, KlipperPrinter, PrinterHandle, PrusaLinkPrinter, PrusaSerialPrinter, }; #[tokio::main] async fn main() { let mut fleet: Vec = vec![ PrinterHandle::BambuV1(BambuV1Printer::new( "p1", "P1S", "192.168.1.49", "87654321", "01P00A000000000", BambuTls::BundledCa, )), PrinterHandle::BambuV2(BambuV2Printer::new( "p2", "X1 Carbon", "192.168.1.50", "12345678", "00M00A000000000", BambuTls::BundledCa, )), PrinterHandle::PrusaLink(PrusaLinkPrinter::new("p3", "MK4", "192.168.1.51", "prusa-api-key")), PrinterHandle::PrusaSerial(PrusaSerialPrinter::new("p4", "MK3S+", 0)), PrinterHandle::Klipper(KlipperPrinter::new("p5", "Voron 2.4", "192.168.1.52")), // No host configured — this one will hit the Err path. PrinterHandle::Klipper(KlipperPrinter::new("p6", "Broken Voron", "")), ]; // Uniform call site: every printer connects the same way from the // caller's point of view, even though each variant's `connect()` body // is an unrelated implementation. 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. BambuV1Printer and BambuV2Printer are // separate types now (each *has* a BambuGenericPrinter rather than // being the same struct), so — unlike before the split — this needs // two arms instead of one `A(x) | B(x)` pattern: an or-pattern requires // every alternative to bind the same type, and these no longer do. for printer in &fleet { match printer { PrinterHandle::BambuV1(bambu) => bambu.dispatch_gcode("part.gcode.3mf"), PrinterHandle::BambuV2(bambu) => bambu.dispatch_gcode("part.gcode.3mf"), _ => {} } } }