//! 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 Bambu struct (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, BambuProtocolPreference, BambuTls, GenericPrinter, KlipperPrinter, PrinterHandle, PrusaLinkPrinter, PrusaSerialPrinter, }; #[tokio::main] async fn main() { let mut fleet: Vec = vec![ // Forced: a known-old printer. PrinterHandle::Bambu(BambuPrinter::new( "p1", "P1S", "192.168.1.49", "87654321", "01P00A000000000", BambuTls::BundledCa, BambuProtocolPreference::ForceV1, )), // Auto: the recommended default - see bambu.rs's doc comment. PrinterHandle::Bambu(BambuPrinter::new( "p2", "X1 Carbon", "192.168.1.50", "12345678", "00M00A000000000", BambuTls::BundledCa, BambuProtocolPreference::Auto, )), PrinterHandle::PrusaLink(PrusaLinkPrinter::new("p3", "MK4", "192.168.1.51", "prusa-api-key")), PrinterHandle::PrusaSerial(PrusaSerialPrinter::new("p4", "MK3S+", "/dev/ttyACM0", 115_200)), 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 - one arm now that Bambu is a single // type regardless of which protocol version `connect()` settled on. for printer in &fleet { match printer { PrinterHandle::Bambu(bambu) => bambu.dispatch_gcode("part.gcode.3mf"), _ => {} } } // A second trait method, same uniform call site as connect(): every // vendor sends "50%" a completely different way - an MQTT gcode // command, Moonraker's native API, gcode over HTTP, gcode over serial // - but the caller doesn't need to know or care which. println!(); for printer in &mut fleet { let _ = printer.set_fan_speed(50).await; } }