use std::fmt;
use std::str::FromStr;
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum BackupMode {
Both,
PathOnly,
ShellOnly,
}
impl Default for BackupMode {
fn default() -> Self {
Self::Both
}
}
impl fmt::Display for BackupMode {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
BackupMode::Both => write!(f, "both"),
BackupMode::PathOnly => write!(f, "path"),
BackupMode::ShellOnly => write!(f, "shell"),
}
}
}
impl FromStr for BackupMode {
type Err = String;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s.to_lowercase().as_str() {
"both" => Ok(BackupMode::Both),
"path" => Ok(BackupMode::PathOnly),
"shell" => Ok(BackupMode::ShellOnly),
_ => Err(format!("Invalid backup mode: {}", s)),
}
}
}
#[allow(dead_code)]
impl BackupMode {
pub fn should_backup_path(&self) -> bool {
matches!(self, BackupMode::Both | BackupMode::PathOnly)
}
pub fn should_backup_shell(&self) -> bool {
matches!(self, BackupMode::Both | BackupMode::ShellOnly)
}
pub fn toggle(&self) -> Self {
match self {
BackupMode::Both => BackupMode::PathOnly,
BackupMode::PathOnly => BackupMode::ShellOnly,
BackupMode::ShellOnly => BackupMode::PathOnly,
}
}
}
#[derive(Debug, PartialEq)]
#[allow(dead_code)]
pub enum ModeChangeResult {
Changed(BackupMode),
NeedsConfirmation {
current: BackupMode,
requested: BackupMode,
},
}
#[derive(Debug)]
#[allow(dead_code)]
pub struct BackupModeManager {
current_mode: BackupMode,
}
impl Default for BackupModeManager {
fn default() -> Self {
Self {
current_mode: BackupMode::default(),
}
}
}
#[allow(dead_code)]
impl BackupModeManager {
pub fn new() -> Self {
Self::default()
}
pub fn current_mode(&self) -> BackupMode {
self.current_mode
}
pub fn request_mode_change(&self, new_mode: BackupMode) -> ModeChangeResult {
if self.current_mode == new_mode {
return ModeChangeResult::Changed(new_mode);
}
if self.current_mode == BackupMode::Both {
ModeChangeResult::Changed(new_mode)
} else {
ModeChangeResult::NeedsConfirmation {
current: self.current_mode,
requested: new_mode,
}
}
}
pub fn confirm_mode_change(&mut self, new_mode: BackupMode) {
self.current_mode = new_mode;
}
pub fn reset_to_default(&mut self) {
self.current_mode = BackupMode::default();
}
pub fn toggle_mode(&mut self) {
self.current_mode = self.current_mode.toggle();
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_backup_mode_defaults() {
assert_eq!(BackupMode::default(), BackupMode::Both);
assert_eq!(BackupModeManager::new().current_mode(), BackupMode::Both);
}
#[test]
fn test_backup_flags() {
let mode = BackupMode::Both;
assert!(mode.should_backup_path());
assert!(mode.should_backup_shell());
let mode = BackupMode::PathOnly;
assert!(mode.should_backup_path());
assert!(!mode.should_backup_shell());
let mode = BackupMode::ShellOnly;
assert!(!mode.should_backup_path());
assert!(mode.should_backup_shell());
}
#[test]
fn test_mode_toggle() {
assert_eq!(BackupMode::Both.toggle(), BackupMode::PathOnly);
assert_eq!(BackupMode::PathOnly.toggle(), BackupMode::ShellOnly);
assert_eq!(BackupMode::ShellOnly.toggle(), BackupMode::PathOnly);
}
#[test]
fn test_mode_change_requests() {
let manager = BackupModeManager::new();
match manager.request_mode_change(BackupMode::PathOnly) {
ModeChangeResult::Changed(mode) => assert_eq!(mode, BackupMode::PathOnly),
_ => panic!("Expected direct mode change"),
}
let mut manager = BackupModeManager::new();
manager.confirm_mode_change(BackupMode::PathOnly);
match manager.request_mode_change(BackupMode::ShellOnly) {
ModeChangeResult::NeedsConfirmation { current, requested } => {
assert_eq!(current, BackupMode::PathOnly);
assert_eq!(requested, BackupMode::ShellOnly);
}
_ => panic!("Expected confirmation request"),
}
}
#[test]
fn test_mode_parsing() {
assert_eq!("both".parse::<BackupMode>().unwrap(), BackupMode::Both);
assert_eq!("path".parse::<BackupMode>().unwrap(), BackupMode::PathOnly);
assert_eq!(
"shell".parse::<BackupMode>().unwrap(),
BackupMode::ShellOnly
);
assert!("invalid".parse::<BackupMode>().is_err());
}
#[test]
fn test_mode_display() {
assert_eq!(BackupMode::Both.to_string(), "both");
assert_eq!(BackupMode::PathOnly.to_string(), "path");
assert_eq!(BackupMode::ShellOnly.to_string(), "shell");
}
}