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}