Skip to main content

moddef_core/
transport.rs

1// SPDX-License-Identifier: Apache-2.0
2
3//! Transport abstraction (spec §32.2). Implementations wrap a Modbus client
4//! (see `moddef-tokio-modbus`) or an in-memory register map for tests.
5//!
6//! Design notes:
7//! - Native async-fn-in-trait; no `async_trait` box. `no_std`-compatible.
8//! - `&mut self` on every method: a Modbus connection is a serial
9//!   request/response channel, so the borrow checker enforces one in-flight
10//!   request per transport.
11//! - Reads fill caller buffers (`&mut [u16]` / `&mut [bool]`) so the core
12//!   never allocates; the requested count is `out.len()`.
13
14/// Async register-level transport. `offset` is the zero-based data-model
15/// offset within the given address space (spec §7.2); implementations apply
16/// any unit/base-address mapping.
17#[allow(async_fn_in_trait)]
18pub trait Transport {
19    type Error;
20
21    async fn read_holding(&mut self, offset: u16, out: &mut [u16]) -> Result<(), Self::Error>;
22
23    async fn read_input(&mut self, offset: u16, out: &mut [u16]) -> Result<(), Self::Error>;
24
25    async fn read_coils(&mut self, offset: u16, out: &mut [bool]) -> Result<(), Self::Error>;
26
27    async fn read_discrete(&mut self, offset: u16, out: &mut [bool]) -> Result<(), Self::Error>;
28
29    async fn write_holding(&mut self, offset: u16, regs: &[u16]) -> Result<(), Self::Error>;
30
31    async fn write_coil(&mut self, offset: u16, on: bool) -> Result<(), Self::Error>;
32
33    /// Largest register window one read may request (Modbus caps at 125;
34    /// devices sometimes less). The facade chunks larger spans.
35    fn max_read_words(&self) -> u16 {
36        125
37    }
38}