Skip to main content

ardop_interface/tnc/
error.rs

1//! TNC errors
2
3use std::convert::From;
4use std::fmt;
5use std::io;
6use std::string::String;
7
8use async_std::future::TimeoutError;
9
10use futures::channel::mpsc::{SendError, TrySendError};
11
12use crate::protocol::response::CommandResult;
13
14/// Errors raised by the `Tnc` interface
15#[derive(Debug)]
16pub enum TncError {
17    /// TNC rejected a command with a `FAULT` message
18    CommandFailed(String),
19
20    /// Event timed out
21    ///
22    /// This error indicates that an expected TNC event did
23    /// not occur within the allotted time. The operation
24    /// should probably be retried.
25    TimedOut,
26
27    /// Socket connectivity problem
28    ///
29    /// These errors are generally fatal and indicate serious,
30    /// uncorrectable problems with the local ARDOP TNC
31    /// connection.
32    ///
33    /// - `io::ErrorKind::ConnectionReset`: lost connection
34    ///    to TNC
35    /// - `io::ErrorKind::TimedOut`: TNC did not respond to
36    ///    a command
37    /// - `io::ErrorKind::InvalidData`: TNC sent a malformed
38    ///    or unsolicited command response
39    IoError(io::Error),
40}
41
42/// Composite `Ok`/`Err` return type
43pub type TncResult<T> = Result<T, TncError>;
44
45impl fmt::Display for TncError {
46    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
47        match &self {
48            TncError::CommandFailed(s) => write!(f, "TNC command failed: \"{}\"", s),
49            TncError::TimedOut => write!(f, "Timed out"),
50            TncError::IoError(e) => write!(f, "IO Error: {}", e),
51        }
52    }
53}
54
55impl From<CommandResult> for TncError {
56    fn from(r: CommandResult) -> Self {
57        match r {
58            Ok(_a) => unreachable!(),
59            Err(x) => TncError::CommandFailed(x),
60        }
61    }
62}
63
64impl From<io::Error> for TncError {
65    fn from(e: io::Error) -> Self {
66        match e.kind() {
67            // these errors might come from a runtime timeout
68            io::ErrorKind::TimedOut => TncError::TimedOut,
69            _ => TncError::IoError(e),
70        }
71    }
72}
73
74impl From<SendError> for TncError {
75    fn from(_e: SendError) -> Self {
76        TncError::IoError(connection_reset_err())
77    }
78}
79
80impl<T> From<TrySendError<T>> for TncError {
81    fn from(_e: TrySendError<T>) -> Self {
82        TncError::IoError(connection_reset_err())
83    }
84}
85
86impl From<TimeoutError> for TncError {
87    fn from(_e: TimeoutError) -> Self {
88        TncError::TimedOut
89    }
90}
91
92fn connection_reset_err() -> io::Error {
93    io::Error::new(
94        io::ErrorKind::ConnectionReset,
95        "Lost connection to ARDOP TNC",
96    )
97}