diff --git a/src/conn.rs b/src/conn.rs index e69de29..d31f3ea 100644 --- a/src/conn.rs +++ b/src/conn.rs @@ -0,0 +1,35 @@ +use std::sync::Mutex; +use std::io::{BufferedReader, BufferedWriter, IoResult, TcpStream}; +use data::kinds::{IrcWriter, IrcReader}; +use data::message::Message; + +pub struct Connection where T: IrcWriter, U: IrcReader { + writer: Mutex, + reader: Mutex, +} + +impl Connection, BufferedReader> { + pub fn connect(host: &str, port: u16) -> IoResult, BufferedReader>> { + let socket = try!(TcpStream::connect(host, port)); + Ok(Connection::new(BufferedWriter::new(socket.clone()), BufferedReader::new(socket))) + } +} + +impl Connection where T: IrcWriter, U: IrcReader { + pub fn new(writer: T, reader: U) -> Connection { + Connection { + writer: Mutex::new(writer), + reader: Mutex::new(reader), + } + } + + pub fn send(&self, msg: Message) -> IoResult<()> { + let mut send = self.writer.lock(); + try!(send.write_str(msg.into_string()[])); + send.flush() + } + + pub fn recv(&self) -> IoResult { + self.reader.lock().read_line() + } +} diff --git a/src/data/message.rs b/src/data/message.rs new file mode 100644 index 0000000..fd3ed90 --- /dev/null +++ b/src/data/message.rs @@ -0,0 +1,38 @@ +#[deriving(Clone, PartialEq, Show)] +pub struct Message { + pub prefix: Option, + pub command: String, + pub args: Vec, + pub suffix: Option, +} + +impl Message { + pub fn new(prefix: Option<&str>, command: &str, args: Option>, suffix: Option<&str>) + -> Message { + Message { + prefix: prefix.map(|s| s.into_string()), + command: command.into_string(), + args: args.map_or(Vec::new(), |v| v.iter().map(|s| s.into_string()).collect()), + suffix: suffix.map(|s| s.into_string()), + } + } + + pub fn into_string(&self) -> String { + let mut ret = String::new(); + if let Some(ref prefix) = self.prefix { + ret.push(':'); + ret.push_str(prefix[]); + ret.push(' '); + } + ret.push_str(self.command[]); + for arg in self.args.iter() { + ret.push(' '); + ret.push_str(arg[]); + } + if let Some(ref suffix) = self.suffix { + ret.push_str(" :"); + ret.push_str(suffix[]); + } + ret + } +} diff --git a/src/data/mod.rs b/src/data/mod.rs new file mode 100644 index 0000000..3178a28 --- /dev/null +++ b/src/data/mod.rs @@ -0,0 +1,8 @@ +pub mod kinds { + pub trait IrcWriter: Writer + Sized + Send + 'static {} + impl IrcWriter for T where T: Writer + Sized + Send + 'static {} + pub trait IrcReader: Buffer + Sized + Send + 'static {} + impl IrcReader for T where T: Buffer + Sized + Send + 'static {} +} + +pub mod message; diff --git a/src/lib.rs b/src/lib.rs index 7e3d85e..2de2166 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -3,12 +3,9 @@ #![crate_type = "lib"] #![feature(if_let)] -#![feature(phase)] #![feature(slicing_syntax)] -extern crate regex; -#[phase(plugin)] extern crate regex_macros; extern crate serialize; -mod conn; + mod conn; +pub mod data; pub mod server; -mod utils; diff --git a/src/utils.rs b/src/utils.rs deleted file mode 100644 index 324e70c..0000000 --- a/src/utils.rs +++ /dev/null @@ -1,53 +0,0 @@ -use std::io::{InvalidInput, IoError, IoResult}; - -fn process(msg: &str) -> IoResult<(&str, &str, Vec<&str>)> { - let reg = regex!(r"^(?::([^ ]+) )?([^ ]+)(.*)"); - let cap = match reg.captures(msg) { - Some(x) => x, - None => return Err(IoError { - kind: InvalidInput, - desc: "Failed to parse line", - detail: None, - }), - }; - let source = cap.at(1); - let command = cap.at(2); - let args = parse_args(cap.at(3)); - Ok((source, command, args)) -} - -fn parse_args(line: &str) -> Vec<&str> { - let reg = regex!(r" ([^: ]+)| :([^\r\n]*)[\r\n]*$"); - reg.captures_iter(line).map(|cap| { - match cap.at(1) { - "" => cap.at(2), - x => x, - } - }).collect() -} - -#[cfg(test)] -mod test { - use super::{process, parse_args}; - - #[test] - fn process_line() { - let res = process(":flare.to.ca.fyrechat.net 353 pickles = #pickles :pickles awe\r\n").unwrap(); - let (source, command, args) = res; - assert_eq!(source, "flare.to.ca.fyrechat.net"); - assert_eq!(command, "353"); - assert_eq!(args, vec!["pickles", "=", "#pickles", "pickles awe"]); - - let res = process("PING :flare.to.ca.fyrechat.net\r\n").unwrap(); - let (source, command, args) = res; - assert_eq!(source, ""); - assert_eq!(command, "PING"); - assert_eq!(args, vec!["flare.to.ca.fyrechat.net"]); - } - - #[test] - fn process_args() { - let res = parse_args("PRIVMSG #vana :hi"); - assert_eq!(res, vec!["#vana", "hi"]) - } -}