1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105
use std::{str, fmt}; use hash::H96; use Error; #[derive(Debug, PartialEq, Clone, Hash, Eq, Serializable, Deserializable)] pub struct Command(H96); impl str::FromStr for Command { type Err = Error; fn from_str(s: &str) -> Result<Self, Self::Err> { if !s.is_ascii() || s.len() > 12 { return Err(Error::InvalidCommand); } let mut result = H96::default(); result[..s.len()].copy_from_slice(s.as_ref()); Ok(Command(result)) } } impl From<&'static str> for Command { fn from(s: &'static str) -> Self { s.parse().unwrap() } } impl Command { pub fn len(&self) -> usize { let trailing_zeros = self.0.iter().rev().take_while(|&x| x == &0).count(); self.0.len() - trailing_zeros } pub fn is_empty(&self) -> bool { self.0.is_zero() } fn as_string(&self) -> String { String::from_utf8_lossy(&self.0[..self.len()]).to_ascii_lowercase() } } impl From<Command> for String { fn from(c: Command) -> Self { c.as_string() } } impl fmt::Display for Command { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.write_str(&self.as_string()) } } impl<'a> PartialEq<&'a str> for Command { fn eq(&self, other: &&'a str) -> bool { self.len() == other.len() && &self.0[..other.len()] == other.as_ref() as &[u8] } } #[cfg(test)] mod tests { use bytes::Bytes; use ser::{serialize, deserialize}; use super::Command; #[test] fn test_command_parse() { let command: Command = "version".into(); assert_eq!(Command("76657273696f6e0000000000".into()), command); } #[test] fn test_command_to_string() { let command: Command = "version".into(); let expected: String = "version".into(); assert_eq!(expected, String::from(command)); } #[test] fn test_command_serialize() { let expected = "76657273696f6e0000000000".into(); let command: Command = "version".into(); assert_eq!(serialize(&command), expected); } #[test] fn test_command_deserialize() { let raw: Bytes = "76657273696f6e0000000000".into(); let expected: Command = "version".into(); assert_eq!(expected, deserialize::<_, Command>(raw.as_ref()).unwrap()); } #[test] fn partial_eq_command_str() { let command: Command = "version".into(); assert_eq!(command, "version"); assert!(command != "ver"); assert!(command != "versionx"); } }