use thiserror::Error;
#[derive(Debug, Error)]
pub enum IsoTpError {
#[error("Invalid frame format: {reason}")]
InvalidFrame {
reason: String,
},
#[error("Invalid PCI type: 0x{pci:02X}")]
InvalidPci {
pci: u8,
},
#[error("Sequence number mismatch: expected {expected}, got {actual}")]
SequenceMismatch {
expected: u8,
actual: u8,
},
#[error("Receive timeout after {timeout_ms}ms")]
RxTimeout {
timeout_ms: u64,
},
#[error("Timeout waiting for Flow Control after {timeout_ms}ms")]
FcTimeout {
timeout_ms: u64,
},
#[error("Too many FC(Wait) responses: {count} exceeds max {max}")]
TooManyWaits {
count: u8,
max: u8,
},
#[error("Buffer overflow: received {received} bytes, max {max}")]
BufferOverflow {
received: usize,
max: usize,
},
#[error("Remote reported overflow")]
RemoteOverflow,
#[error("Data too large: {size} bytes, max {max}")]
DataTooLarge {
size: usize,
max: usize,
},
#[error("Data is empty")]
EmptyData,
#[error("Transfer aborted")]
Aborted,
#[error("Invalid configuration: {reason}")]
InvalidConfig {
reason: String,
},
#[error("Backend error: {0}")]
BackendError(#[from] crate::CanError),
#[error("Backend disconnected")]
BackendDisconnected,
#[error("Buffer allocation failed: requested {size} bytes")]
BufferAllocationFailed {
size: usize,
},
#[error("Channel busy: {state}")]
ChannelBusy {
state: String,
},
#[error("Unexpected frame type: expected {expected}, got {actual}")]
UnexpectedFrame {
expected: String,
actual: String,
},
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_error_display() {
let err = IsoTpError::InvalidFrame {
reason: "too short".to_string(),
};
assert_eq!(err.to_string(), "Invalid frame format: too short");
let err = IsoTpError::InvalidPci { pci: 0x40 };
assert_eq!(err.to_string(), "Invalid PCI type: 0x40");
let err = IsoTpError::SequenceMismatch {
expected: 5,
actual: 7,
};
assert_eq!(
err.to_string(),
"Sequence number mismatch: expected 5, got 7"
);
let err = IsoTpError::RxTimeout { timeout_ms: 1000 };
assert_eq!(err.to_string(), "Receive timeout after 1000ms");
let err = IsoTpError::TooManyWaits { count: 11, max: 10 };
assert_eq!(
err.to_string(),
"Too many FC(Wait) responses: 11 exceeds max 10"
);
}
#[test]
fn test_error_variants() {
let _ = IsoTpError::InvalidFrame {
reason: "test".to_string(),
};
let _ = IsoTpError::InvalidPci { pci: 0 };
let _ = IsoTpError::SequenceMismatch {
expected: 0,
actual: 1,
};
let _ = IsoTpError::RxTimeout { timeout_ms: 100 };
let _ = IsoTpError::FcTimeout { timeout_ms: 100 };
let _ = IsoTpError::TooManyWaits { count: 1, max: 10 };
let _ = IsoTpError::BufferOverflow {
received: 5000,
max: 4095,
};
let _ = IsoTpError::RemoteOverflow;
let _ = IsoTpError::DataTooLarge {
size: 5000,
max: 4095,
};
let _ = IsoTpError::EmptyData;
let _ = IsoTpError::Aborted;
let _ = IsoTpError::InvalidConfig {
reason: "test".to_string(),
};
let _ = IsoTpError::BackendDisconnected;
let _ = IsoTpError::BufferAllocationFailed { size: 1000 };
let _ = IsoTpError::ChannelBusy {
state: "receiving".to_string(),
};
let _ = IsoTpError::UnexpectedFrame {
expected: "CF".to_string(),
actual: "SF".to_string(),
};
}
}