use serde::{Deserialize, Serialize};
use std::fmt;
#[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize)]
pub enum TransferState {
#[default]
Pending,
InProgress(f64),
Paused(f64),
Completed,
Failed(String),
Cancelled,
}
impl TransferState {
pub fn is_completed(&self) -> bool {
matches!(self, TransferState::Completed)
}
pub fn progress(&self) -> f64 {
match self {
TransferState::Pending => 0.0,
TransferState::InProgress(p) => *p,
TransferState::Paused(p) => *p,
TransferState::Completed => 100.0,
TransferState::Failed(_) => 0.0,
TransferState::Cancelled => 0.0,
}
}
pub fn is_paused(&self) -> bool {
matches!(self, TransferState::Paused(_))
}
pub fn is_cancelled(&self) -> bool {
matches!(self, TransferState::Cancelled)
}
pub fn is_terminal(&self) -> bool {
matches!(
self,
TransferState::Completed | TransferState::Failed(_) | TransferState::Cancelled
)
}
pub fn error(&self) -> Option<&str> {
match self {
TransferState::Failed(msg) => Some(msg),
_ => None,
}
}
}
impl fmt::Display for TransferState {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
TransferState::Pending => write!(f, "Pending"),
TransferState::InProgress(p) => write!(f, "In Progress ({:.1}%)", p),
TransferState::Paused(p) => write!(f, "Paused ({:.1}%)", p),
TransferState::Completed => write!(f, "Completed"),
TransferState::Failed(msg) => write!(f, "Failed: {}", msg),
TransferState::Cancelled => write!(f, "Cancelled"),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_default_is_pending() {
let state = TransferState::default();
assert_eq!(state, TransferState::Pending);
assert_eq!(state.progress(), 0.0);
}
#[test]
fn test_in_progress_state() {
let state = TransferState::InProgress(50.0);
assert!(matches!(state, TransferState::InProgress(_)));
assert_eq!(state.progress(), 50.0);
}
#[test]
fn test_completed_state() {
let state = TransferState::Completed;
assert!(state.is_completed());
assert_eq!(state.progress(), 100.0);
}
#[test]
fn test_failed_state() {
let state = TransferState::Failed("Network error".into());
assert!(matches!(state, TransferState::Failed(_)));
assert_eq!(state.error(), Some("Network error"));
assert_eq!(state.progress(), 0.0);
}
#[test]
fn test_display_formatting() {
assert_eq!(format!("{}", TransferState::Pending), "Pending");
assert_eq!(
format!("{}", TransferState::InProgress(50.5)),
"In Progress (50.5%)"
);
assert_eq!(format!("{}", TransferState::Completed), "Completed");
assert_eq!(
format!("{}", TransferState::Failed("Error".into())),
"Failed: Error"
);
}
}