mod parser;
pub mod server;
pub mod client;
use error::Result;
use command::{Command, ArgumentIter};
use tag::{Tag, TagIter};
use std::ops::Range;
#[derive(Clone, PartialEq, Eq, Debug)]
struct PrefixRange {
raw_prefix: Range<usize>,
prefix: Range<usize>,
user: Option<Range<usize>>,
host: Option<Range<usize>>,
}
type TagRange = (Range<usize>, Option<Range<usize>>);
#[derive(Clone, PartialEq, Eq, Debug)]
pub struct Message {
message: String,
tags: Option<Vec<TagRange>>,
prefix: Option<PrefixRange>,
command: Range<usize>,
arguments: Option<Vec<Range<usize>>>,
}
impl Message {
pub fn try_from(value: String) -> Result<Message> {
let result = parser::parse_message(value)?;
Ok(result)
}
pub fn command<'a, T>(&'a self) -> Option<T>
where
T: Command<'a>,
{
<T as Command>::try_match(self.raw_command(), self.raw_args())
}
pub fn tag<'a, T>(&'a self) -> Option<T>
where
T: Tag<'a>,
{
<T as Tag>::try_match(self.raw_tags())
}
pub fn prefix(&self) -> Option<(&str, Option<&str>, Option<&str>)> {
if let Some(ref prefix_range) = self.prefix {
let user = prefix_range.user.clone().map(|user| &self.message[user]);
let host = prefix_range.host.clone().map(|host| &self.message[host]);
Some((&self.message[prefix_range.prefix.clone()], user, host))
} else {
None
}
}
pub fn raw_tags(&self) -> TagIter {
if let Some(ref tags) = self.tags {
TagIter::new(&self.message, tags.iter())
} else {
TagIter::new(&self.message, [].iter())
}
}
pub fn raw_prefix(&self) -> Option<&str> {
if let Some(ref prefix_range) = self.prefix {
Some(&self.message[prefix_range.raw_prefix.clone()])
} else {
None
}
}
pub fn raw_command(&self) -> &str {
&self.message[self.command.clone()]
}
pub fn raw_args(&self) -> ArgumentIter {
if let Some(ref arguments) = self.arguments {
ArgumentIter::new(&self.message, arguments.iter())
} else {
ArgumentIter::new(&self.message, [].iter())
}
}
pub fn raw_message(&self) -> &str {
&self.message
}
}
impl ::std::str::FromStr for Message {
type Err = ::error::Error;
fn from_str(input: &str) -> Result<Message> {
Message::try_from(input.to_owned())
}
}