From 47aac49e629147c1627ae081a2ba918d02ccb6c4 Mon Sep 17 00:00:00 2001 From: Benjamin Peter Date: Wed, 14 Feb 2024 16:13:18 +0100 Subject: [PATCH] refacto: update `crate::Result` to `Result` --- src/client/mod.rs | 107 +++++++++++------------------------------ src/client/sync/mod.rs | 91 +++++++++-------------------------- src/client/tcp.rs | 4 +- src/service/rtu.rs | 7 +-- src/service/tcp.rs | 5 +- 5 files changed, 60 insertions(+), 154 deletions(-) diff --git a/src/client/mod.rs b/src/client/mod.rs index 3b6773ab..05ece67c 100644 --- a/src/client/mod.rs +++ b/src/client/mod.rs @@ -7,7 +7,7 @@ use std::{borrow::Cow, fmt::Debug, io}; use async_trait::async_trait; -use crate::{frame::*, slave::*}; +use crate::{frame::*, slave::*, Result}; #[cfg(feature = "rtu")] pub mod rtu; @@ -22,39 +22,23 @@ pub mod sync; #[async_trait] pub trait Client: SlaveContext + Send + Debug { /// Invoke a Modbus function - async fn call(&mut self, request: Request<'_>) -> io::Result>; + async fn call(&mut self, request: Request<'_>) -> Result; } /// Asynchronous Modbus reader #[async_trait] pub trait Reader: Client { /// Read multiple coils (0x01) - async fn read_coils( - &mut self, - addr: Address, - cnt: Quantity, - ) -> io::Result>>; + async fn read_coils(&mut self, addr: Address, cnt: Quantity) -> Result>; /// Read multiple discrete inputs (0x02) - async fn read_discrete_inputs( - &mut self, - addr: Address, - cnt: Quantity, - ) -> io::Result>>; + async fn read_discrete_inputs(&mut self, addr: Address, cnt: Quantity) -> Result>; /// Read multiple holding registers (0x03) - async fn read_holding_registers( - &mut self, - addr: Address, - cnt: Quantity, - ) -> io::Result>>; + async fn read_holding_registers(&mut self, addr: Address, cnt: Quantity) -> Result>; /// Read multiple input registers (0x04) - async fn read_input_registers( - &mut self, - addr: Address, - cnt: Quantity, - ) -> io::Result>>; + async fn read_input_registers(&mut self, addr: Address, cnt: Quantity) -> Result>; /// Read and write multiple holding registers (0x17) /// @@ -66,39 +50,23 @@ pub trait Reader: Client { read_count: Quantity, write_addr: Address, write_data: &[Word], - ) -> io::Result>>; + ) -> Result>; } /// Asynchronous Modbus writer #[async_trait] pub trait Writer: Client { /// Write a single coil (0x05) - async fn write_single_coil( - &mut self, - addr: Address, - coil: Coil, - ) -> io::Result>; + async fn write_single_coil(&mut self, addr: Address, coil: Coil) -> Result<()>; /// Write a single holding register (0x06) - async fn write_single_register( - &mut self, - addr: Address, - word: Word, - ) -> io::Result>; + async fn write_single_register(&mut self, addr: Address, word: Word) -> Result<()>; /// Write multiple coils (0x0F) - async fn write_multiple_coils( - &mut self, - addr: Address, - coils: &'_ [Coil], - ) -> io::Result>; + async fn write_multiple_coils(&mut self, addr: Address, coils: &'_ [Coil]) -> Result<()>; /// Write multiple holding registers (0x10) - async fn write_multiple_registers( - &mut self, - addr: Address, - words: &[Word], - ) -> io::Result>; + async fn write_multiple_registers(&mut self, addr: Address, words: &[Word]) -> Result<()>; /// Set or clear individual bits of a holding register (0x16) async fn masked_write_register( @@ -106,7 +74,7 @@ pub trait Writer: Client { addr: Address, and_mask: Word, or_mask: Word, - ) -> io::Result>; + ) -> Result<()>; } /// Asynchronous Modbus client context @@ -117,13 +85,13 @@ pub struct Context { impl Context { /// Disconnect the client - pub async fn disconnect(&mut self) -> Result<(), io::Error> { + pub async fn disconnect(&mut self) -> Result<()> { // Disconnecting is expected to fail! let res = self.client.call(Request::Disconnect).await; match res { Ok(_) => unreachable!(), Err(err) => match err.kind() { - io::ErrorKind::NotConnected | io::ErrorKind::BrokenPipe => Ok(()), + io::ErrorKind::NotConnected | io::ErrorKind::BrokenPipe => Ok(Ok(())), _ => Err(err), }, } @@ -144,7 +112,7 @@ impl From for Box { #[async_trait] impl Client for Context { - async fn call(&mut self, request: Request<'_>) -> io::Result> { + async fn call(&mut self, request: Request<'_>) -> Result { self.client.call(request).await } } @@ -157,11 +125,7 @@ impl SlaveContext for Context { #[async_trait] impl Reader for Context { - async fn read_coils<'a>( - &'a mut self, - addr: Address, - cnt: Quantity, - ) -> io::Result>> { + async fn read_coils<'a>(&'a mut self, addr: Address, cnt: Quantity) -> Result> { self.client .call(Request::ReadCoils(addr, cnt)) .await @@ -187,7 +151,7 @@ impl Reader for Context { &'a mut self, addr: Address, cnt: Quantity, - ) -> io::Result>> { + ) -> Result> { self.client .call(Request::ReadDiscreteInputs(addr, cnt)) .await @@ -213,7 +177,7 @@ impl Reader for Context { &'a mut self, addr: Address, cnt: Quantity, - ) -> io::Result>> { + ) -> Result> { self.client .call(Request::ReadInputRegisters(addr, cnt)) .await @@ -238,7 +202,7 @@ impl Reader for Context { &'a mut self, addr: Address, cnt: Quantity, - ) -> io::Result>> { + ) -> Result> { self.client .call(Request::ReadHoldingRegisters(addr, cnt)) .await @@ -265,7 +229,7 @@ impl Reader for Context { read_count: Quantity, write_addr: Address, write_data: &[Word], - ) -> io::Result>> { + ) -> Result> { self.client .call(Request::ReadWriteMultipleRegisters( read_addr, @@ -294,11 +258,7 @@ impl Reader for Context { #[async_trait] impl Writer for Context { - async fn write_single_coil<'a>( - &'a mut self, - addr: Address, - coil: Coil, - ) -> io::Result> { + async fn write_single_coil<'a>(&'a mut self, addr: Address, coil: Coil) -> Result<()> { self.client .call(Request::WriteSingleCoil(addr, coil)) .await @@ -319,11 +279,7 @@ impl Writer for Context { }) } - async fn write_multiple_coils<'a>( - &'a mut self, - addr: Address, - coils: &[Coil], - ) -> io::Result> { + async fn write_multiple_coils<'a>(&'a mut self, addr: Address, coils: &[Coil]) -> Result<()> { let cnt = coils.len(); self.client @@ -346,11 +302,7 @@ impl Writer for Context { }) } - async fn write_single_register<'a>( - &'a mut self, - addr: Address, - word: Word, - ) -> io::Result> { + async fn write_single_register<'a>(&'a mut self, addr: Address, word: Word) -> Result<()> { self.client .call(Request::WriteSingleRegister(addr, word)) .await @@ -375,7 +327,7 @@ impl Writer for Context { &'a mut self, addr: Address, data: &[Word], - ) -> io::Result> { + ) -> Result<()> { let cnt = data.len(); self.client @@ -403,7 +355,7 @@ impl Writer for Context { addr: Address, and_mask: Word, or_mask: Word, - ) -> io::Result> { + ) -> Result<()> { self.client .call(Request::MaskWriteRegister(addr, and_mask, or_mask)) .await @@ -435,7 +387,7 @@ mod tests { pub(crate) struct ClientMock { slave: Option, last_request: Mutex>>, - next_response: Option>>, + next_response: Option>, } #[allow(dead_code)] @@ -448,17 +400,14 @@ mod tests { &self.last_request } - pub(crate) fn set_next_response( - &mut self, - next_response: io::Result>, - ) { + pub(crate) fn set_next_response(&mut self, next_response: Result) { self.next_response = Some(next_response); } } #[async_trait] impl Client for ClientMock { - async fn call(&mut self, request: Request<'_>) -> io::Result> { + async fn call(&mut self, request: Request<'_>) -> Result { *self.last_request.lock().unwrap() = Some(request.into_owned()); match self.next_response.as_ref().unwrap() { Ok(response) => Ok(response.clone()), diff --git a/src/client/sync/mod.rs b/src/client/sync/mod.rs index e21ad5e5..2414d424 100644 --- a/src/client/sync/mod.rs +++ b/src/client/sync/mod.rs @@ -13,7 +13,7 @@ use std::{future::Future, io, time::Duration}; use futures_util::future::Either; -use crate::{frame::*, slave::*}; +use crate::{frame::*, slave::*, Result}; use super::{ Client as AsyncClient, Context as AsyncContext, Reader as AsyncReader, SlaveContext, @@ -41,55 +41,34 @@ fn block_on_with_timeout( /// A transport independent synchronous client trait. pub trait Client: SlaveContext { - fn call(&mut self, req: Request<'_>) -> io::Result>; + fn call(&mut self, req: Request<'_>) -> Result; } /// A transport independent synchronous reader trait. /// -/// The synchronous counterpart of the asynchronous [`Reader`](`crate::client::Reader`) trait. +/// The synchronous counterpart of the asynchronous [`Reader`](`client::Reader`) trait. pub trait Reader: Client { - fn read_coils(&mut self, addr: Address, cnt: Quantity) -> io::Result>>; - fn read_discrete_inputs( - &mut self, - addr: Address, - cnt: Quantity, - ) -> io::Result>>; - fn read_input_registers( - &mut self, - addr: Address, - cnt: Quantity, - ) -> io::Result>>; - fn read_holding_registers( - &mut self, - addr: Address, - cnt: Quantity, - ) -> io::Result>>; + fn read_coils(&mut self, addr: Address, cnt: Quantity) -> Result>; + fn read_discrete_inputs(&mut self, addr: Address, cnt: Quantity) -> Result>; + fn read_input_registers(&mut self, addr: Address, cnt: Quantity) -> Result>; + fn read_holding_registers(&mut self, addr: Address, cnt: Quantity) -> Result>; fn read_write_multiple_registers( &mut self, read_addr: Address, read_count: Quantity, write_addr: Address, write_data: &[Word], - ) -> io::Result>>; + ) -> Result>; } /// A transport independent synchronous writer trait. /// -/// The synchronous counterpart of the asynchronous [`Writer`](`crate::client::Writer`) trait. +/// The synchronous counterpart of the asynchronous [`Writer`](`client::Writer`) trait. pub trait Writer: Client { - fn write_single_coil(&mut self, addr: Address, coil: Coil) -> io::Result>; - fn write_multiple_coils( - &mut self, - addr: Address, - coils: &[Coil], - ) -> io::Result>; - fn write_single_register(&mut self, addr: Address, word: Word) - -> io::Result>; - fn write_multiple_registers( - &mut self, - addr: Address, - words: &[Word], - ) -> io::Result>; + fn write_single_coil(&mut self, addr: Address, coil: Coil) -> Result<()>; + fn write_multiple_coils(&mut self, addr: Address, coils: &[Coil]) -> Result<()>; + fn write_single_register(&mut self, addr: Address, word: Word) -> Result<()>; + fn write_multiple_registers(&mut self, addr: Address, words: &[Word]) -> Result<()>; } /// A synchronous Modbus client context. @@ -120,7 +99,7 @@ impl Context { } impl Client for Context { - fn call(&mut self, req: Request<'_>) -> io::Result> { + fn call(&mut self, req: Request<'_>) -> Result { block_on_with_timeout(&self.runtime, self.timeout, self.async_ctx.call(req)) } } @@ -132,7 +111,7 @@ impl SlaveContext for Context { } impl Reader for Context { - fn read_coils(&mut self, addr: Address, cnt: Quantity) -> io::Result>> { + fn read_coils(&mut self, addr: Address, cnt: Quantity) -> Result> { block_on_with_timeout( &self.runtime, self.timeout, @@ -140,11 +119,7 @@ impl Reader for Context { ) } - fn read_discrete_inputs( - &mut self, - addr: Address, - cnt: Quantity, - ) -> io::Result>> { + fn read_discrete_inputs(&mut self, addr: Address, cnt: Quantity) -> Result> { block_on_with_timeout( &self.runtime, self.timeout, @@ -152,11 +127,7 @@ impl Reader for Context { ) } - fn read_input_registers( - &mut self, - addr: Address, - cnt: Quantity, - ) -> io::Result>> { + fn read_input_registers(&mut self, addr: Address, cnt: Quantity) -> Result> { block_on_with_timeout( &self.runtime, self.timeout, @@ -164,11 +135,7 @@ impl Reader for Context { ) } - fn read_holding_registers( - &mut self, - addr: Address, - cnt: Quantity, - ) -> io::Result>> { + fn read_holding_registers(&mut self, addr: Address, cnt: Quantity) -> Result> { block_on_with_timeout( &self.runtime, self.timeout, @@ -182,7 +149,7 @@ impl Reader for Context { read_count: Quantity, write_addr: Address, write_data: &[Word], - ) -> io::Result>> { + ) -> Result> { block_on_with_timeout( &self.runtime, self.timeout, @@ -193,11 +160,7 @@ impl Reader for Context { } impl Writer for Context { - fn write_single_register( - &mut self, - addr: Address, - data: Word, - ) -> io::Result> { + fn write_single_register(&mut self, addr: Address, data: Word) -> Result<()> { block_on_with_timeout( &self.runtime, self.timeout, @@ -205,11 +168,7 @@ impl Writer for Context { ) } - fn write_multiple_registers( - &mut self, - addr: Address, - data: &[Word], - ) -> io::Result> { + fn write_multiple_registers(&mut self, addr: Address, data: &[Word]) -> Result<()> { block_on_with_timeout( &self.runtime, self.timeout, @@ -217,7 +176,7 @@ impl Writer for Context { ) } - fn write_single_coil(&mut self, addr: Address, data: Coil) -> io::Result> { + fn write_single_coil(&mut self, addr: Address, data: Coil) -> Result<()> { block_on_with_timeout( &self.runtime, self.timeout, @@ -225,11 +184,7 @@ impl Writer for Context { ) } - fn write_multiple_coils( - &mut self, - addr: Address, - data: &[Coil], - ) -> io::Result> { + fn write_multiple_coils(&mut self, addr: Address, data: &[Coil]) -> Result<()> { block_on_with_timeout( &self.runtime, self.timeout, diff --git a/src/client/tcp.rs b/src/client/tcp.rs index 3f1e7a73..acd0df56 100644 --- a/src/client/tcp.rs +++ b/src/client/tcp.rs @@ -13,14 +13,14 @@ use tokio::{ use super::*; /// Establish a direct connection to a Modbus TCP coupler. -pub async fn connect(socket_addr: SocketAddr) -> Result { +pub async fn connect(socket_addr: SocketAddr) -> io::Result { connect_slave(socket_addr, Slave::tcp_device()).await } /// Connect to a physical, broadcast, or custom Modbus device, /// probably through a Modbus TCP gateway that is forwarding /// messages to/from the corresponding slave device. -pub async fn connect_slave(socket_addr: SocketAddr, slave: Slave) -> Result { +pub async fn connect_slave(socket_addr: SocketAddr, slave: Slave) -> io::Result { let transport = TcpStream::connect(socket_addr).await?; let context = attach_slave(transport, slave); Ok(context) diff --git a/src/service/rtu.rs b/src/service/rtu.rs index 82665977..bf30e5a8 100644 --- a/src/service/rtu.rs +++ b/src/service/rtu.rs @@ -11,6 +11,7 @@ use crate::{ codec, frame::{rtu::*, *}, slave::*, + Result, }; /// Modbus RTU client @@ -44,7 +45,7 @@ where } } - async fn call(&mut self, req: Request<'_>) -> io::Result> { + async fn call(&mut self, req: Request<'_>) -> Result { let disconnect = req == Request::Disconnect; let req_adu = self.next_request_adu(req, disconnect); let req_hdr = req_adu.hdr; @@ -65,7 +66,7 @@ where } } -fn verify_response_header(req_hdr: Header, rsp_hdr: Header) -> Result<(), io::Error> { +fn verify_response_header(req_hdr: Header, rsp_hdr: Header) -> io::Result<()> { if req_hdr != rsp_hdr { return Err(io::Error::new( io::ErrorKind::InvalidData, @@ -88,7 +89,7 @@ impl crate::client::Client for Client where T: fmt::Debug + AsyncRead + AsyncWrite + Send + Unpin, { - async fn call(&mut self, req: Request<'_>) -> io::Result> { + async fn call(&mut self, req: Request<'_>) -> Result { self.call(req).await } } diff --git a/src/service/tcp.rs b/src/service/tcp.rs index 8fa02a07..3125f9d2 100644 --- a/src/service/tcp.rs +++ b/src/service/tcp.rs @@ -14,6 +14,7 @@ use crate::{ codec, frame::{tcp::*, *}, slave::*, + Result, }; const INITIAL_TRANSACTION_ID: TransactionId = 0; @@ -67,7 +68,7 @@ where } } - pub(crate) async fn call(&mut self, req: Request<'_>) -> io::Result> { + pub(crate) async fn call(&mut self, req: Request<'_>) -> Result { log::debug!("Call {:?}", req); let disconnect = req == Request::Disconnect; let req_adu = self.next_request_adu(req, disconnect); @@ -112,7 +113,7 @@ impl crate::client::Client for Client where T: fmt::Debug + AsyncRead + AsyncWrite + Send + Unpin, { - async fn call(&mut self, req: Request<'_>) -> io::Result> { + async fn call(&mut self, req: Request<'_>) -> Result { Client::call(self, req).await } }