1use bytes::Bytes;
2
3pub trait Command {
5 const CMD_NAME: &'static [u8];
7 fn into_vec(self) -> Result<Bytes, CommandError>;
9 fn try_parse(buf: &[u8]) -> Result<Self, CommandError>
11 where
12 Self: Sized;
13}
14
15pub(crate) fn check_command_arg(s: &str) -> Result<(), ArgumentValidationError> {
16 if s.contains(' ') {
17 return Err(ArgumentValidationError::ContainsSpace);
18 } else if s.contains('\t') {
19 return Err(ArgumentValidationError::ContainsTab);
20 }
21
22 Ok(())
23}
24
25macro_rules! check_cmd_arg {
26 ($val:ident, $part:expr) => {
27 use protocol::{check_command_arg, ArgumentValidationError};
28
29 match check_command_arg($val) {
30 Ok(_) => {}
31 Err(ArgumentValidationError::ContainsSpace) => {
32 return Err(format!("{} contains spaces", $part).into());
33 }
34 Err(ArgumentValidationError::ContainsTab) => {
35 return Err(format!("{} contains tabs", $part).into());
36 }
37 }
38 };
39}
40
41mod error;
42pub use self::error::*;
43
44mod client;
45mod server;
46
47mod op;
48pub use self::op::*;
49
50pub mod commands {
51 pub use super::{
52 client::{connect::*, pub_cmd::*, sub_cmd::*, unsub_cmd::*},
53 server::{info::*, message::*, server_error::ServerError},
54 };
55 pub use Command;
56}
57
58#[cfg(test)]
59mod tests {
60 use super::check_command_arg;
61
62 #[test]
63 #[should_panic]
64 fn it_detects_spaces() {
65 check_command_arg(&"foo bar").unwrap()
66 }
67
68 #[test]
69 #[should_panic]
70 fn it_detects_tabs() {
71 check_command_arg(&"foo\tbar").unwrap()
72 }
73
74 #[test]
75 fn it_works() {
76 check_command_arg(&"foo.bar").unwrap()
77 }
78}