From 5e85202dd5dfa0213532e80c221a648a4af07a99 Mon Sep 17 00:00:00 2001 From: Adrian Hedqvist Date: Mon, 18 Jun 2018 16:24:39 +0200 Subject: [PATCH] Initial commit --- .gitignore | 3 ++ Cargo.lock | 4 ++ Cargo.toml | 7 +++ src/main.rs | 5 ++ src/models.rs | 147 ++++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 166 insertions(+) create mode 100644 .gitignore create mode 100644 Cargo.lock create mode 100644 Cargo.toml create mode 100644 src/main.rs create mode 100644 src/models.rs diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..70e3cae --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ + +/target +**/*.rs.bk diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..c014380 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,4 @@ +[[package]] +name = "plankircd" +version = "0.1.0" + diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..c4f161f --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "plankircd" +version = "0.1.0" +authors = ["Adrian Hedqvist "] + +[dependencies] +tokio = "0.1" \ No newline at end of file diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..66ab730 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,5 @@ +pub mod models; + +fn main() { + println!("Hello, world!"); +} diff --git a/src/models.rs b/src/models.rs new file mode 100644 index 0000000..93c6967 --- /dev/null +++ b/src/models.rs @@ -0,0 +1,147 @@ +#[derive(Debug, PartialEq, Eq)] +pub enum IrcCommand { + USER, + NICK, + JOIN, + PART, + PRIVMSG, + WHO, +} + +impl IrcCommand { + fn from_str(s: &str) -> Option { + use self::IrcCommand::*; + match s { + "USER" => Some(USER), + "NICK" => Some(NICK), + "JOIN" => Some(JOIN), + "PART" => Some(PART), + "PRIVMSG" => Some(PRIVMSG), + "WHO" => Some(WHO), + _ => None, + } + } +} + +#[derive(Debug, PartialEq, Eq)] +pub struct IrcMessage { + pub prefix: Option, + pub command: IrcCommand, + pub params: Vec, +} + +impl IrcMessage { + pub fn new(pre: Option<&str>, cmd: IrcCommand, prm: Vec<&str>) -> IrcMessage { + IrcMessage { + prefix: if let Some(s) = pre { Some(s.to_string()) } else { None }, + command: cmd, + params: prm.iter().map(|s| s.to_string()).collect(), + } + } + + pub fn from_str(msg: &str) -> Option { // TODO: Wrap in Result<> + let mut args = msg.trim().splitn(2, " :"); + let mut left = args.next().unwrap().split(' '); + + let mut prefix = None; + let mut cmd = None; + + if let Some(s) = left.next() { + if s.starts_with(':') { + prefix = Some(&s[1..]); + + if let Some(c) = left.next() { + cmd = IrcCommand::from_str(c); + }; + } + else { + cmd = IrcCommand::from_str(s); + } + } + + let mut params: Vec<&str> = left.collect(); + + if let Some(s) = args.next() { + params.push(s); + }; + + match cmd { + Some(c) => Some(IrcMessage::new(prefix, c, params)), + None => None, + } + } + + pub fn to_string(&self) -> String { + let param: Vec = self.params.iter() + .map(|s| if s.contains(" ") { format!(":{}", s) } else { s.clone() }) + .collect(); + // TODO: get rid of clone, also would be better to only check and (...) + // replace the last element since we assume that the preceding params + // doesn't have any spaces + + match self.prefix { + Some(ref prefix) => format!(":{} {:?} {}\r\n", prefix, self.command, param.join(" ")), + None => format!("{:?} {}\r\n", self.command, param.join(" ")) + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn message_from_string() { + let msg = IrcMessage::from_str(":tlx PRIVMSG supes :u suk lol\r\n").unwrap(); + + assert_eq!(msg, IrcMessage { + prefix: Some("tlx".to_string()), + command: IrcCommand::PRIVMSG, + params: vec!["supes".to_string(), "u suk lol".to_string()] + }); + } + + #[test] + fn message_from_string_with_multiple_colons_in_trailing() { + let msg = IrcMessage::from_str(":tlx PRIVMSG supes :u suk lol :D\r\n").unwrap(); + + assert_eq!(msg, IrcMessage { + prefix: Some("tlx".to_string()), + command: IrcCommand::PRIVMSG, + params: vec!["supes".to_string(), "u suk lol :D".to_string()] + }); + } + + #[test] + fn message_from_string_without_prefix() { + let msg = IrcMessage::from_str("PRIVMSG supes :u suk lol\r\n").unwrap(); + + assert_eq!(msg, IrcMessage { + prefix: None, + command: IrcCommand::PRIVMSG, + params: vec!["supes".to_string(), "u suk lol".to_string()] + }); + } + + #[test] + fn message_to_string() { + let msg = IrcMessage { + prefix: Some("tlx".to_string()), + command: IrcCommand::PRIVMSG, + params: vec!["supes".to_string(), "u suk lol".to_string()] + }; + + assert_eq!(&msg.to_string(), ":tlx PRIVMSG supes :u suk lol\r\n"); + } + + #[test] + fn message_to_string_without_prefix() { + let msg = IrcMessage { + prefix: None, + command: IrcCommand::PRIVMSG, + params: vec!["supes".to_string(), "u suk lol".to_string()] + }; + + assert_eq!(&msg.to_string(), "PRIVMSG supes :u suk lol\r\n"); + } +} \ No newline at end of file