#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[repr(u8)]
pub enum Verb {
Scan = 0x01,
Format = 0x02,
Search = 0x03,
EndStream = 0x04,
Ping = 0x05,
Ok = 0x06,
Alert = 0x07,
Back = 0x08,
Context = 0x09,
Next = 0x0A,
Stats = 0x0B,
Clear = 0x0C,
Complete = 0x0D,
AuthStart = 0x0E,
AuthEnd = 0x0F,
Audio = 0x10,
Permit = 0x11,
Deny = 0x12,
Elevate = 0x13,
Audit = 0x14,
Error = 0x15,
Subscribe = 0x16,
Unsubscribe = 0x17,
Cancel = 0x18,
M8Wave = 0x19,
Remember = 0x1A,
Recall = 0x1C,
Forget = 0x1D,
Session = 0x1E,
User = 0x1F,
}
impl Verb {
pub fn from_byte(b: u8) -> Option<Self> {
match b {
0x01 => Some(Verb::Scan),
0x02 => Some(Verb::Format),
0x03 => Some(Verb::Search),
0x04 => Some(Verb::EndStream),
0x05 => Some(Verb::Ping),
0x06 => Some(Verb::Ok),
0x07 => Some(Verb::Alert),
0x08 => Some(Verb::Back),
0x09 => Some(Verb::Context),
0x0A => Some(Verb::Next),
0x0B => Some(Verb::Stats),
0x0C => Some(Verb::Clear),
0x0D => Some(Verb::Complete),
0x0E => Some(Verb::AuthStart),
0x0F => Some(Verb::AuthEnd),
0x10 => Some(Verb::Audio),
0x11 => Some(Verb::Permit),
0x12 => Some(Verb::Deny),
0x13 => Some(Verb::Elevate),
0x14 => Some(Verb::Audit),
0x15 => Some(Verb::Error),
0x16 => Some(Verb::Subscribe),
0x17 => Some(Verb::Unsubscribe),
0x18 => Some(Verb::Cancel),
0x19 => Some(Verb::M8Wave),
0x1A => Some(Verb::Remember),
0x1C => Some(Verb::Recall),
0x1D => Some(Verb::Forget),
0x1E => Some(Verb::Session),
0x1F => Some(Verb::User),
_ => None,
}
}
#[inline]
pub fn as_byte(self) -> u8 {
self as u8
}
pub fn requires_auth(self) -> bool {
matches!(
self,
Verb::Format
| Verb::Clear
| Verb::Permit
| Verb::Deny
| Verb::Elevate
| Verb::Remember
| Verb::Forget
)
}
pub fn security_level(self) -> u8 {
match self {
Verb::Scan | Verb::Search | Verb::Stats | Verb::Ping |
Verb::Context | Verb::Recall | Verb::Format |
Verb::Remember | Verb::Forget | Verb::M8Wave | Verb::Audio => 0,
Verb::Clear | Verb::Subscribe | Verb::Unsubscribe => 1,
Verb::Elevate => 2,
Verb::Permit | Verb::Deny | Verb::Audit => 3,
_ => 1,
}
}
pub fn name(self) -> &'static str {
match self {
Verb::Scan => "SCAN",
Verb::Format => "FORMAT",
Verb::Search => "SEARCH",
Verb::EndStream => "END_STREAM",
Verb::Ping => "PING",
Verb::Ok => "OK",
Verb::Alert => "ALERT",
Verb::Back => "BACK",
Verb::Context => "CONTEXT",
Verb::Next => "NEXT",
Verb::Stats => "STATS",
Verb::Clear => "CLEAR",
Verb::Complete => "COMPLETE",
Verb::AuthStart => "AUTH_START",
Verb::AuthEnd => "AUTH_END",
Verb::Audio => "AUDIO",
Verb::Permit => "PERMIT",
Verb::Deny => "DENY",
Verb::Elevate => "ELEVATE",
Verb::Audit => "AUDIT",
Verb::Error => "ERROR",
Verb::Subscribe => "SUBSCRIBE",
Verb::Unsubscribe => "UNSUBSCRIBE",
Verb::Cancel => "CANCEL",
Verb::M8Wave => "M8_WAVE",
Verb::Remember => "REMEMBER",
Verb::Recall => "RECALL",
Verb::Forget => "FORGET",
Verb::Session => "SESSION",
Verb::User => "USER",
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_verb_roundtrip() {
for b in 0x01..=0x1F {
if let Some(verb) = Verb::from_byte(b) {
assert_eq!(verb.as_byte(), b);
}
}
}
#[test]
fn test_ping_is_0x05() {
assert_eq!(Verb::Ping.as_byte(), 0x05);
}
#[test]
fn test_security_levels() {
assert_eq!(Verb::Scan.security_level(), 0);
assert_eq!(Verb::Search.security_level(), 0);
assert_eq!(Verb::Ping.security_level(), 0);
assert_eq!(Verb::Permit.security_level(), 3);
assert_eq!(Verb::Deny.security_level(), 3);
}
}