rust-irc/src/data/message.rs

85 lines
2.8 KiB
Rust
Raw Normal View History

2014-11-03 06:52:15 +01:00
//! Messages to and from the server
#![experimental]
use std::from_str::FromStr;
2014-11-03 06:52:15 +01:00
/// IRC Message data
#[experimental]
2014-11-02 23:25:45 +01:00
#[deriving(Clone, PartialEq, Show)]
pub struct Message {
2014-11-03 06:52:15 +01:00
/// The message prefix (or source) as defined by [RFC 2812](http://tools.ietf.org/html/rfc2812)
2014-11-02 23:25:45 +01:00
pub prefix: Option<String>,
2014-11-03 06:52:15 +01:00
/// The IRC command as defined by [RFC 2812](http://tools.ietf.org/html/rfc2812)
2014-11-02 23:25:45 +01:00
pub command: String,
2014-11-03 06:52:15 +01:00
/// The command arguments
2014-11-02 23:25:45 +01:00
pub args: Vec<String>,
2014-11-03 06:52:15 +01:00
/// The message suffix as defined by [RFC 2812](http://tools.ietf.org/html/rfc2812)
/// This is the only part of the message that is allowed to contain spaces.
2014-11-02 23:25:45 +01:00
pub suffix: Option<String>,
}
impl Message {
2014-11-03 06:52:15 +01:00
/// Creates a new Message
#[experimental]
2014-11-02 23:25:45 +01:00
pub fn new(prefix: Option<&str>, command: &str, args: Option<Vec<&str>>, 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()),
}
}
2014-11-03 06:52:15 +01:00
/// Converts a Message into a String according to the IRC protocol
#[experimental]
2014-11-02 23:25:45 +01:00
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.push_str("\r\n");
2014-11-02 23:25:45 +01:00
ret
}
}
impl FromStr for Message {
fn from_str(s: &str) -> Option<Message> {
let mut state = s.clone();
if s.len() == 0 { return None }
let prefix = if state.starts_with(":") {
let prefix = state.find(' ').map(|i| state[1..i]);
state = state.find(' ').map_or("", |i| state[i+1..]);
prefix
} else {
None
};
let suffix = if state.contains(":") {
let suffix = state.find(':').map(|i| state[i+1..state.len()-2]);
state = state.find(':').map_or("", |i| state[..i]);
suffix
} else {
None
};
let command = match state.find(' ').map(|i| state[..i]) {
Some(cmd) => {
state = state.find(' ').map_or("", |i| state[i+1..]);
cmd
}
_ => return None
};
let args: Vec<_> = state.splitn(14, ' ').filter(|s| s.len() != 0).collect();
Some(Message::new(prefix, command, if args.len() > 0 { Some(args) } else { None }, suffix))
}
}