use thiserror::Error;
#[derive(Error, Debug)]
pub enum TradeError {
#[error("Invalid trade: {reason}")]
InvalidTrade {
reason: String,
},
#[error("Invalid trade status: {reason}")]
InvalidTradeStatus {
reason: String,
},
#[error("Trade arithmetic overflow in {operation}: {reason}")]
ArithmeticOverflow {
operation: &'static str,
reason: String,
},
}
impl TradeError {
#[must_use]
#[cold]
#[inline(never)]
pub fn invalid_trade(reason: &str) -> Self {
TradeError::InvalidTrade {
reason: reason.to_string(),
}
}
#[must_use]
#[cold]
#[inline(never)]
pub fn invalid_trade_status(reason: &str) -> Self {
TradeError::InvalidTradeStatus {
reason: reason.to_string(),
}
}
#[must_use]
#[cold]
#[inline(never)]
pub fn arithmetic_overflow(operation: &'static str, reason: impl std::fmt::Display) -> Self {
TradeError::ArithmeticOverflow {
operation,
reason: reason.to_string(),
}
}
}
impl From<&str> for TradeError {
fn from(s: &str) -> Self {
TradeError::InvalidTrade {
reason: s.to_string(),
}
}
}
impl From<String> for TradeError {
fn from(s: String) -> Self {
TradeError::InvalidTrade { reason: s }
}
}
#[cfg(test)]
mod tests_trade_errors {
use super::*;
#[test]
fn test_invalid_trade_error() {
let error = TradeError::InvalidTrade {
reason: "Trade is not valid".to_string(),
};
assert_eq!(error.to_string(), "Invalid trade: Trade is not valid");
}
#[test]
fn test_trade_error_arithmetic_overflow_names_operation() {
let error = TradeError::arithmetic_overflow("Trade::cost", "overflow");
assert!(matches!(
error,
TradeError::ArithmeticOverflow {
operation: "Trade::cost",
..
}
));
assert_eq!(
error.to_string(),
"Trade arithmetic overflow in Trade::cost: overflow"
);
}
#[test]
fn test_invalid_trade_status_error() {
let error = TradeError::InvalidTradeStatus {
reason: "Trade status is not valid".to_string(),
};
assert_eq!(
error.to_string(),
"Invalid trade status: Trade status is not valid"
);
}
#[test]
fn test_invalid_trade_error_helper_method() {
let error = TradeError::invalid_trade("Trade is not valid");
assert_eq!(error.to_string(), "Invalid trade: Trade is not valid");
}
#[test]
fn test_invalid_trade_status_error_helper_method() {
let error = TradeError::invalid_trade_status("Trade status is not valid");
assert_eq!(
error.to_string(),
"Invalid trade status: Trade status is not valid"
);
}
}
#[cfg(test)]
mod tests_trade_error_from {
use super::*;
#[test]
fn from_str_creates_invalid_trade_error() {
let err: TradeError = "some error reason".into();
match err {
TradeError::InvalidTrade { reason } => {
assert_eq!(reason, "some error reason");
}
_ => panic!("Expected TradeError::InvalidTrade"),
}
}
#[test]
fn from_string_creates_invalid_trade_error() {
let input = String::from("string-based error reason");
let err: TradeError = input.clone().into();
match err {
TradeError::InvalidTrade { reason } => {
assert_eq!(reason, input);
}
_ => panic!("Expected TradeError::InvalidTrade"),
}
}
}