Skip to main content

laser_dac/
backend.rs

1//! DAC backend trait and implementations for the streaming API.
2//!
3//! This module provides the [`StreamBackend`] trait that all DAC backends must
4//! implement, as well as implementations for all supported DAC types.
5
6use crate::types::{DacCapabilities, DacType, LaserPoint};
7
8// Re-export error types for backwards compatibility
9pub use crate::error::{Error, Result};
10
11// =============================================================================
12// StreamBackend Trait
13// =============================================================================
14
15/// Write result from a backend chunk submission.
16#[derive(Debug, Clone, Copy, PartialEq, Eq)]
17pub enum WriteOutcome {
18    /// The chunk was accepted and written.
19    Written,
20    /// The device cannot accept more data right now.
21    WouldBlock,
22}
23
24/// Backend trait for streaming DAC output.
25///
26/// All backends must implement this trait to support the streaming API.
27/// The key contract is uniform backpressure: `try_write_chunk` must return
28/// `WriteOutcome::WouldBlock` when the device cannot accept more data,
29/// enabling the stream scheduler to pace output correctly.
30pub trait StreamBackend: Send + 'static {
31    /// Returns the DAC type for this backend.
32    fn dac_type(&self) -> DacType;
33
34    /// Returns the device capabilities.
35    fn caps(&self) -> &DacCapabilities;
36
37    /// Connect to the device.
38    fn connect(&mut self) -> Result<()>;
39
40    /// Disconnect from the device.
41    fn disconnect(&mut self) -> Result<()>;
42
43    /// Returns whether the device is connected.
44    fn is_connected(&self) -> bool;
45
46    /// Attempt to write a chunk of points at the given PPS.
47    ///
48    /// # Contract
49    ///
50    /// This is the core backpressure mechanism. Implementations must:
51    ///
52    /// 1. Return `WriteOutcome::WouldBlock` when the device cannot accept more data
53    ///    (buffer full, not ready, etc.).
54    /// 2. Return `WriteOutcome::Written` when the chunk was accepted.
55    /// 3. Return `Err(...)` only for actual errors (disconnection, protocol errors).
56    fn try_write_chunk(&mut self, pps: u32, points: &[LaserPoint]) -> Result<WriteOutcome>;
57
58    /// Stop output (if supported by the device).
59    fn stop(&mut self) -> Result<()>;
60
61    /// Open/close the shutter (if supported by the device).
62    fn set_shutter(&mut self, open: bool) -> Result<()>;
63
64    /// Best-effort estimate of points currently queued in the device.
65    ///
66    /// Not all devices can report this. Return `None` if unavailable.
67    fn queued_points(&self) -> Option<u64> {
68        None
69    }
70}
71
72// =============================================================================
73// Re-exports from protocol-specific backends
74// =============================================================================
75
76#[cfg(feature = "helios")]
77pub use crate::protocols::helios::HeliosBackend;
78
79#[cfg(feature = "ether-dream")]
80pub use crate::protocols::ether_dream::EtherDreamBackend;
81
82#[cfg(feature = "idn")]
83pub use crate::protocols::idn::IdnBackend;
84
85#[cfg(feature = "lasercube-wifi")]
86pub use crate::protocols::lasercube_wifi::LasercubeWifiBackend;
87
88#[cfg(feature = "lasercube-usb")]
89pub use crate::protocols::lasercube_usb::LasercubeUsbBackend;