1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
/// Check if a whole buffer was successfully transferred.
pub fn check_transfer(transferred: usize, total: usize) -> Result<(), IncompleteTransmissionError> {
	if transferred == total {
		Ok(())
	} else {
		Err(IncompleteTransmissionError { transferred, total })
	}
}

#[cfg(test)]
#[test]
fn test_check_transfer() {
	use assert2::assert;
	assert!(let Err(IncompleteTransmissionError { transferred: 1, total: 2}) = check_transfer(1, 2));
	assert!(let Err(IncompleteTransmissionError { transferred: 2, total: 1}) = check_transfer(2, 1));
	assert!(let Ok(()) = check_transfer(3, 3));
}

/// Error that may occur when receiving a message.
#[derive(Debug)]
pub enum ReceiveError {
	Io(std::io::Error),
	Decode(prost::DecodeError),
}

/// Error that may occur when sending a message.
#[derive(Debug)]
pub enum SendError {
	InvalidMessage(InvalidMessageError),
	Io(std::io::Error),
	Encode(prost::EncodeError),
	IncompleteTransmission(IncompleteTransmissionError),
}

/// Error indicating that a message is invalid.
#[derive(Debug)]
pub enum InvalidMessageError {
	/// The message being sent contains one or more NaN values.
	MessageHasNan,
}

impl InvalidMessageError {
	/// Check if an [`msg::EgmSensor`] is invalid.
	pub fn check_sensor_msg(message: &crate::msg::EgmSensor) -> Result<(), Self> {
		if message.has_nan() {
			Err(Self::MessageHasNan)
		} else {
			Ok(())
		}
	}
}

/// Error indicating that a message was only partially transmitted.
#[derive(Clone, Debug)]
pub struct IncompleteTransmissionError {
	/// The number of bytes that were transmitted.
	pub transferred: usize,

	/// The total number of bytes that should have been transmitted.
	pub total: usize,
}

impl From<std::io::Error> for ReceiveError {
	fn from(other: std::io::Error) -> Self {
		Self::Io(other)
	}
}

impl From<prost::DecodeError> for ReceiveError {
	fn from(other: prost::DecodeError) -> Self {
		Self::Decode(other)
	}
}

impl From<InvalidMessageError> for SendError {
	fn from(other: InvalidMessageError) -> Self {
		Self::InvalidMessage(other)
	}
}

impl From<std::io::Error> for SendError {
	fn from(other: std::io::Error) -> Self {
		Self::Io(other)
	}
}

impl From<prost::EncodeError> for SendError {
	fn from(other: prost::EncodeError) -> Self {
		Self::Encode(other)
	}
}

impl From<IncompleteTransmissionError> for SendError {
	fn from(other: IncompleteTransmissionError) -> Self {
		Self::IncompleteTransmission(other)
	}
}

impl std::fmt::Display for ReceiveError {
	fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
		match self {
			Self::Io(e) => e.fmt(f),
			Self::Decode(e) => e.fmt(f),
		}
	}
}

impl std::fmt::Display for SendError {
	fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
		match self {
			Self::InvalidMessage(e) => e.fmt(f),
			Self::Io(e) => e.fmt(f),
			Self::Encode(e) => e.fmt(f),
			Self::IncompleteTransmission(e) => e.fmt(f),
		}
	}
}

impl std::fmt::Display for InvalidMessageError {
	fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
		match self {
			Self::MessageHasNan => write!(f, "invalid message: message contains one or more NaN values"),
		}
	}
}

impl std::fmt::Display for IncompleteTransmissionError {
	#[rustfmt::skip]
	fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
		write!(f, "incomplete transmission: transferred only {} of {} bytes",
			self.transferred,
			self.total
		)
	}
}

impl std::error::Error for ReceiveError {}
impl std::error::Error for SendError {}
impl std::error::Error for InvalidMessageError {}
impl std::error::Error for IncompleteTransmissionError {}