use crate::prelude::*;
use std::fs::canonicalize;
#[derive(Options, Clone, Debug, Deserialize, Serialize)]
pub struct AuditArgs {
#[arg(value_name = "PATH | ID")]
#[options(required)]
pub audit_arg: String,
}
pub enum AuditMode {
Id(u32),
File(PathBuf),
Directory(PathBuf),
}
impl AuditArgs {
pub fn to_mode(&self) -> Result<AuditMode, OptionIssue> {
if let Ok(id) = self.audit_arg.parse::<u32>() {
return Ok(AuditMode::Id(id));
}
let path = PathBuf::from(&self.audit_arg);
if !path.exists() {
return Err(OptionIssue::path_not_found("audit_arg", &path));
}
let path = canonicalize(path).expect("should be able to canonicalize path");
if path.is_file() {
Ok(AuditMode::File(path))
} else if path.is_dir() {
Ok(AuditMode::Directory(path))
} else {
Err(OptionIssue::path_not_found("audit_arg", &path))
}
}
}
impl OptionsContract for AuditArgs {
type Partial = AuditArgsPartial;
fn validate(&self, validator: &mut OptionsValidator) {
if let Err(issue) = self.to_mode() {
validator.push(issue);
}
}
}
#[cfg(test)]
mod tests {
use crate::testing_prelude::*;
#[test]
fn audit_args_to_mode_id() {
let args = AuditArgs {
audit_arg: "12345".to_owned(),
};
assert!(matches!(args.to_mode(), Ok(AuditMode::Id(12345))));
}
#[test]
fn audit_args_to_mode_file() {
let dir = TempDirectory::create("audit_args_to_mode_file");
let file = dir.join("file.torrent");
write(&file, b"data").expect("write file");
let args = AuditArgs {
audit_arg: file.to_string_lossy().into_owned(),
};
let mode = args.to_mode();
assert!(matches!(mode, Ok(AuditMode::File(_))));
}
#[test]
fn audit_args_to_mode_directory() {
let dir = TempDirectory::create("audit_args_to_mode_directory");
let args = AuditArgs {
audit_arg: dir.to_string_lossy().into_owned(),
};
let mode = args.to_mode();
assert!(matches!(mode, Ok(AuditMode::Directory(_))));
}
#[test]
fn audit_args_validate_id() {
let args = AuditArgs {
audit_arg: "12345".to_owned(),
};
let mut validator = OptionsValidator::new();
args.validate(&mut validator);
assert!(validator.into_issues().is_empty());
}
#[test]
fn audit_args_validate_path() {
let args = AuditArgs {
audit_arg: "/no/such/path/at/all".to_owned(),
};
let mut validator = OptionsValidator::new();
args.validate(&mut validator);
let issues = validator.into_issues();
assert_eq!(issues.len(), 1);
}
}