#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum Operation {
Download,
Upload,
}
impl Operation {
pub const ALL: &'static [Operation] = &[Operation::Download, Operation::Upload];
pub fn as_str(self) -> &'static str {
match self {
Operation::Download => "download",
Operation::Upload => "upload",
}
}
pub fn parse(text: &str) -> Option<Operation> {
Operation::ALL
.iter()
.copied()
.find(|op| op.as_str() == text)
}
pub fn may_upload(self) -> bool {
matches!(self, Operation::Upload)
}
pub fn may_download(self) -> bool {
matches!(self, Operation::Download)
}
}
impl std::fmt::Display for Operation {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str(self.as_str())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn only_the_two_operations_parse() {
assert_eq!(Operation::parse("upload"), Some(Operation::Upload));
assert_eq!(Operation::parse("download"), Some(Operation::Download));
for bad in ["", "Upload", "UPLOAD", "upload ", " upload", "lock", "quit"] {
assert_eq!(Operation::parse(bad), None, "{bad:?} must not parse");
}
}
#[test]
fn the_directions_do_not_imply_each_other() {
assert!(Operation::Upload.may_upload());
assert!(!Operation::Upload.may_download());
assert!(Operation::Download.may_download());
assert!(!Operation::Download.may_upload());
}
#[test]
fn all_is_complete() {
for op in Operation::ALL {
assert_eq!(Operation::parse(op.as_str()), Some(*op));
}
assert_eq!(Operation::ALL.len(), 2);
}
}