diff options
author | tcmal <me@aria.rip> | 2024-10-01 15:42:50 +0100 |
---|---|---|
committer | tcmal <me@aria.rip> | 2024-10-11 23:57:19 +0100 |
commit | 34572a8f3839e37063641fa693029ad52265730a (patch) | |
tree | dd81dfba798039acb638aa1945a58cff023f1c38 /crates/windlass/src/mcu.rs | |
parent | d7275a13989b82ea8fc7b2320ef0cf2f427f7d5d (diff) |
Stricter clippy lints
Diffstat (limited to 'crates/windlass/src/mcu.rs')
-rw-r--r-- | crates/windlass/src/mcu.rs | 142 |
1 files changed, 65 insertions, 77 deletions
diff --git a/crates/windlass/src/mcu.rs b/crates/windlass/src/mcu.rs index c2ca54a..8bc725f 100644 --- a/crates/windlass/src/mcu.rs +++ b/crates/windlass/src/mcu.rs @@ -20,8 +20,8 @@ use tracing::{debug, error, trace}; use crate::messages::{format_command_args, EncodedMessage, Message, WithOid, WithoutOid}; use crate::transport::{Transport, TransportReceiver}; use crate::{ - dictionary::{Dictionary, DictionaryError, RawDictionary}, - transport::TransportError, + dictionary::{self, Dictionary, RawDictionary}, + transport::Error, }; use crate::{ encoding::{parse_vlq_int, MessageDecodeError}, @@ -38,7 +38,7 @@ mcu_reply!( /// MCU Connection Errors #[derive(thiserror::Error, Debug)] -pub enum McuConnectionError { +pub enum ConnectionError { /// Encoding a message was attempted but a command with a matching name doesn't exist in the /// dictionary. #[error("unknown message ID for command '{0}'")] @@ -51,7 +51,7 @@ pub enum McuConnectionError { DictionaryFetch(Box<dyn std::error::Error + Send + Sync>), /// An error was encountered while parsing the dictionary #[error("dictionary issue: {0}")] - Dictionary(#[from] DictionaryError), + Dictionary(#[from] dictionary::Error), /// Received an unknown command from the MCU #[error("unknown command {0}")] UnknownCommand(u16), @@ -60,7 +60,7 @@ pub enum McuConnectionError { CommandMismatch(&'static str, String, String), /// There was a transport-level issue #[error("transport error: {0}")] - Transport(#[from] TransportError), + Transport(#[from] Error), } #[derive(thiserror::Error, Debug)] @@ -68,7 +68,7 @@ pub enum SendReceiveError { #[error("timeout")] Timeout, #[error("mcu connection error: {0}")] - McuConnection(#[from] McuConnectionError), + McuConnection(#[from] ConnectionError), } #[derive(Debug, Clone, Copy, Eq, PartialEq, Hash, Ord, PartialOrd)] @@ -94,7 +94,7 @@ impl std::fmt::Debug for Handlers { let h = self .handlers .try_lock() - .map(|h| h.keys().cloned().collect::<BTreeSet<_>>()) + .map(|h| h.keys().copied().collect::<BTreeSet<_>>()) .unwrap_or_default(); f.debug_struct("Handlers") .field("handlers", &h) @@ -158,11 +158,11 @@ struct McuConnectionInner { } impl McuConnectionInner { - async fn receive_loop(&self, mut inbox: TransportReceiver) -> Result<(), McuConnectionError> { + async fn receive_loop(&self, mut inbox: TransportReceiver) -> Result<(), ConnectionError> { while let Some(frame) = inbox.recv().await { let frame = match frame { Ok(frame) => frame, - Err(e) => return Err(McuConnectionError::Transport(e)), + Err(e) => return Err(ConnectionError::Transport(e)), }; let frame = &mut frame.as_slice(); self.parse_frame(frame)?; @@ -170,9 +170,9 @@ impl McuConnectionInner { Ok(()) } - fn parse_frame(&self, frame: &mut &[u8]) -> Result<(), McuConnectionError> { + fn parse_frame(&self, frame: &mut &[u8]) -> Result<(), ConnectionError> { while !frame.is_empty() { - let cmd = parse_vlq_int(frame)? as u16; + let cmd = u16::try_from(parse_vlq_int(frame)?).expect("command handler overflow"); // If a raw handler is registered for this, call it if self.handlers.call(cmd, None, frame) { @@ -206,7 +206,7 @@ impl McuConnectionInner { ); } } else { - return Err(McuConnectionError::UnknownCommand(cmd)); + return Err(ConnectionError::UnknownCommand(cmd)); } } else { break; @@ -220,7 +220,7 @@ impl McuConnectionInner { /// /// #[derive(Debug)] -pub struct McuConnection { +pub struct Connection { inner: Arc<McuConnectionInner>, transport: Transport, _receiver: JoinHandle<()>, @@ -229,22 +229,24 @@ pub struct McuConnection { #[derive(Debug)] enum ExitCode { - Waiting(oneshot::Receiver<Result<(), McuConnectionError>>), - Exited(Result<(), McuConnectionError>), + Waiting(oneshot::Receiver<Result<(), ConnectionError>>), + Exited(Result<(), ConnectionError>), } -impl McuConnection { +impl Connection { /// Connect to an MCU /// /// Attempts to connect to a MCU on the given data stream interface. The MCU is contacted and - /// the dictionary is loaded and applied. The returned [McuConnection] is fully ready to + /// the dictionary is loaded and applied. The returned [`McuConnection`] is fully ready to /// communicate with the MCU. - pub async fn connect<R, W>(rdr: R, wr: W) -> Result<Self, McuConnectionError> + /// # Panics + /// Panics if the MCU attempts to send an identify payload with size > [`u32::MAX`] + pub async fn connect<R, W>(rdr: R, wr: W) -> Result<Self, ConnectionError> where R: AsyncBufRead + Send + Unpin + 'static, W: AsyncWrite + Send + Unpin + 'static, { - let (transport, inbox) = Transport::connect(rdr, wr).await; + let (transport, inbox) = Transport::connect(rdr, wr); let (exit_tx, exit_rx) = oneshot::channel(); let inner = Arc::new(McuConnectionInner { @@ -258,7 +260,7 @@ impl McuConnection { let _ = exit_tx.send(receiver_inner.receive_loop(inbox).await); }); - let conn = McuConnection { + let conn = Self { inner, transport, _receiver: receiver, @@ -269,16 +271,16 @@ impl McuConnection { let identify_start = Instant::now(); loop { let data = conn - .send_receive( - Identify::encode(identify_data.len() as u32, 40), - IdentifyResponse, - ) + .send_receive::<_, IdentifyResponse>(Identify::encode( + u32::try_from(identify_data.len()).expect("identify data too long"), + 40, + )) .await; let mut data = match data { Ok(data) => data, Err(e) => { if identify_start.elapsed() > Duration::from_secs(10) { - return Err(McuConnectionError::DictionaryFetch(Box::new(e))); + return Err(ConnectionError::DictionaryFetch(Box::new(e))); } continue; } @@ -294,20 +296,19 @@ impl McuConnection { let mut buf = Vec::new(); decoder .read_to_end(&mut buf) - .map_err(|err| McuConnectionError::DictionaryFetch(Box::new(err)))?; + .map_err(|err| ConnectionError::DictionaryFetch(Box::new(err)))?; let raw_dict: RawDictionary = serde_json::from_slice(&buf) - .map_err(|err| McuConnectionError::DictionaryFetch(Box::new(err)))?; - let dict = Dictionary::try_from(raw_dict).map_err(McuConnectionError::Dictionary)?; + .map_err(|err| ConnectionError::DictionaryFetch(Box::new(err)))?; + let dict = Dictionary::try_from(raw_dict).map_err(ConnectionError::Dictionary)?; debug!(dictionary = ?dict, "MCU dictionary"); - conn.inner - .dictionary - .set(dict) - .expect("Dictionary already set"); + let Ok(()) = conn.inner.dictionary.set(dict) else { + unreachable!() + }; Ok(conn) } - fn verify_command_matches<C: Message>(&self) -> Result<(), McuConnectionError> { + fn verify_command_matches<C: Message>(&self) -> Result<(), ConnectionError> { // Special handling for identify/identify_response if C::get_id(None) == Some(0) || C::get_id(None) == Some(1) { return Ok(()); @@ -327,7 +328,7 @@ impl McuConnection { // tested before then. let dictionary = self.inner.dictionary.get().unwrap(); let id = C::get_id(Some(dictionary)) - .ok_or_else(|| McuConnectionError::UnknownMessageId(C::get_name()))?; + .ok_or_else(|| ConnectionError::UnknownMessageId(C::get_name()))?; // Must exist because we know the tag let parser = dictionary.message_parser(id).unwrap(); @@ -335,7 +336,7 @@ impl McuConnection { let local_fields = C::fields().into_iter(); if !remote_fields.eq(local_fields) { - return Err(McuConnectionError::CommandMismatch( + return Err(ConnectionError::CommandMismatch( C::get_name(), format_command_args(parser.fields.iter().map(|(s, t)| (s.as_str(), *t))), format_command_args(C::fields().into_iter()), @@ -354,9 +355,9 @@ impl McuConnection { fn encode_command<C: Message>( &self, command: EncodedMessage<C>, - ) -> Result<FrontTrimmableBuffer, McuConnectionError> { + ) -> Result<FrontTrimmableBuffer, ConnectionError> { let id = C::get_id(self.inner.dictionary.get()) - .ok_or_else(|| McuConnectionError::UnknownMessageId(C::get_name()))?; + .ok_or_else(|| ConnectionError::UnknownMessageId(C::get_name()))?; let mut payload = command.payload; if id >= 0x80 { payload.content[0] = ((id >> 7) & 0x7F) as u8 | 0x80; @@ -368,24 +369,20 @@ impl McuConnection { } /// Sends a command to the MCU - pub async fn send<C: Message>( - &self, - command: EncodedMessage<C>, - ) -> Result<(), McuConnectionError> { + pub fn send<C: Message>(&self, command: EncodedMessage<C>) -> Result<(), ConnectionError> { let cmd = self.encode_command(command)?; self.transport .send(cmd.as_slice()) - .map_err(|e| McuConnectionError::Transport(TransportError::Transmitter(e))) + .map_err(|e| ConnectionError::Transport(Error::Transmitter(e))) } async fn send_receive_impl<C: Message, R: Message>( &self, command: EncodedMessage<C>, - reply: R, oid: Option<u8>, ) -> Result<R::PodOwned, SendReceiveError> { struct RespHandler<R: Message>( - Option<oneshot::Sender<Result<R::PodOwned, McuConnectionError>>>, + Option<oneshot::Sender<Result<R::PodOwned, ConnectionError>>>, ); impl<R: Message> Handler for RespHandler<R> { @@ -393,7 +390,7 @@ impl McuConnection { if let Some(tx) = self.0.take() { let _ = match R::decode(data) { Ok(msg) => tx.send(Ok(msg.into())), - Err(e) => tx.send(Err(McuConnectionError::DecodingError(e))), + Err(e) => tx.send(Err(ConnectionError::DecodingError(e))), }; } HandlerResult::Deregister @@ -406,13 +403,13 @@ impl McuConnection { self.verify_command_matches::<R>()?; let (tx, mut rx) = tokio::sync::oneshot::channel::<Result<R::PodOwned, _>>(); - self.register_raw_response(reply, oid, Box::new(RespHandler::<R>(Some(tx))))?; + self.register_raw_response::<R>(oid, Box::new(RespHandler::<R>(Some(tx))))?; let mut retry_delay = 0.01; for _retry in 0..=5 { self.transport .send(cmd.as_slice()) - .map_err(|e| McuConnectionError::Transport(TransportError::Transmitter(e)))?; + .map_err(|e| ConnectionError::Transport(Error::Transmitter(e)))?; let sleep = tokio::time::sleep(Duration::from_secs_f32(retry_delay)); tokio::pin!(sleep); @@ -425,7 +422,7 @@ impl McuConnection { Err(_) => Err(SendReceiveError::Timeout) }; }, - _ = &mut sleep => {}, + () = &mut sleep => {}, } retry_delay *= 2.0; @@ -441,10 +438,9 @@ impl McuConnection { pub async fn send_receive_oid<C: Message, R: Message + WithOid>( &self, command: EncodedMessage<C>, - reply: R, oid: u8, ) -> Result<R::PodOwned, SendReceiveError> { - self.send_receive_impl(command, reply, Some(oid)).await + self.send_receive_impl::<C, R>(command, Some(oid)).await } /// Sends a message to the MCU, and await a reply @@ -454,27 +450,24 @@ impl McuConnection { pub async fn send_receive<C: Message, R: Message + WithoutOid>( &self, command: EncodedMessage<C>, - reply: R, ) -> Result<R::PodOwned, SendReceiveError> { - self.send_receive_impl(command, reply, None).await + self.send_receive_impl::<C, R>(command, None).await } fn register_raw_response<R: Message>( &self, - _reply: R, oid: Option<u8>, handler: Box<dyn Handler>, - ) -> Result<RegisteredResponseHandle, McuConnectionError> { + ) -> Result<RegisteredResponseHandle, ConnectionError> { let id = R::get_id(self.inner.dictionary.get()) - .ok_or_else(|| McuConnectionError::UnknownMessageId(R::get_name()))?; + .ok_or_else(|| ConnectionError::UnknownMessageId(R::get_name()))?; Ok(self.inner.handlers.register(id, oid, handler)) } fn register_response_impl<R: Message>( &self, - reply: R, oid: Option<u8>, - ) -> Result<UnboundedReceiver<R::PodOwned>, McuConnectionError> { + ) -> Result<UnboundedReceiver<R::PodOwned>, ConnectionError> { struct RespHandler<R: Message>(UnboundedSender<R::PodOwned>, Option<oneshot::Sender<()>>); impl<R: Message> Drop for RespHandler<R> { @@ -489,7 +482,7 @@ impl McuConnection { .expect("Parser should already have assured this could parse") .into(); match self.0.send(msg) { - Ok(_) => HandlerResult::Continue, + Ok(()) => HandlerResult::Continue, Err(_) => HandlerResult::Deregister, } } @@ -500,11 +493,8 @@ impl McuConnection { let (tx, rx) = unbounded_channel(); let tx_closed = tx.clone(); let (closer_tx, closer_rx) = oneshot::channel(); - let uniq = self.register_raw_response( - reply, - oid, - Box::new(RespHandler::<R>(tx, Some(closer_tx))), - )?; + let uniq = + self.register_raw_response::<R>(oid, Box::new(RespHandler::<R>(tx, Some(closer_tx))))?; // Safe because register_raw_response already verified this let id = R::get_id(self.inner.dictionary.get()).unwrap(); @@ -512,7 +502,7 @@ impl McuConnection { let inner = self.inner.clone(); spawn(async move { select! { - _ = tx_closed.closed() => {}, + () = tx_closed.closed() => {}, _ = closer_rx => {}, } inner.handlers.remove_handler(id, oid, Some(uniq)); @@ -528,10 +518,9 @@ impl McuConnection { /// This version works with replies that have an `oid` field. pub fn register_response_oid<R: Message + WithOid>( &self, - reply: R, oid: u8, - ) -> Result<UnboundedReceiver<R::PodOwned>, McuConnectionError> { - self.register_response_impl(reply, Some(oid)) + ) -> Result<UnboundedReceiver<R::PodOwned>, ConnectionError> { + self.register_response_impl::<R>(Some(oid)) } /// Registers a subscriber for a reply message @@ -541,14 +530,16 @@ impl McuConnection { /// This version works with replies that do not have an `oid` field. pub fn register_response<R: Message + WithoutOid>( &self, - reply: R, - ) -> Result<UnboundedReceiver<R::PodOwned>, McuConnectionError> { - self.register_response_impl(reply, None) + ) -> Result<UnboundedReceiver<R::PodOwned>, ConnectionError> { + self.register_response_impl::<R>(None) } /// Returns a reference the dictionary the MCU returned during initial handshake pub fn dictionary(&self) -> &Dictionary { - self.inner.dictionary.get().unwrap() + self.inner + .dictionary + .get() + .unwrap_or_else(|| unreachable!()) } /// Closes the transport and ends all subscriptions. Returns when the transport is closed. @@ -557,16 +548,13 @@ impl McuConnection { } /// Waits for the connection to close, returning the error that closed it if any. - pub async fn closed(&mut self) -> &Result<(), McuConnectionError> { + pub async fn closed(&mut self) -> &Result<(), ConnectionError> { if let ExitCode::Waiting(chan) = &mut self.exit_code { - self.exit_code = ExitCode::Exited(match chan.await { - Ok(r) => r, - Err(_) => Ok(()), - }); + self.exit_code = ExitCode::Exited(chan.await.unwrap_or_else(|_| Ok(()))); } match self.exit_code { ExitCode::Exited(ref val) => val, - _ => unreachable!(), + ExitCode::Waiting(_) => unreachable!(), } } } |