use nom::IResult;
pub trait PrimitiveParser {
fn parse(bytes: &[u8]) -> IResult<&[u8], Self>
where
Self: Sized;
}
macro_rules! standard_string_parser {
($name:ty) => {
impl PrimitiveParser for $name {
fn parse(bytes: &[u8]) -> IResult<&[u8], Self> {
let (rest, val) = nom::combinator::map_res(
nom::bytes::complete::take_till(|c| c == b' '),
std::str::from_utf8,
)(bytes)?;
Ok((rest, Self(val.to_string())))
}
}
};
}
#[derive(Debug)]
pub struct Username(pub(crate) String);
standard_string_parser!(Username);
#[derive(Debug)]
pub struct HostName(pub(crate) String);
standard_string_parser!(HostName);
#[derive(Debug)]
pub struct ServerName(pub(crate) String);
standard_string_parser!(ServerName);
#[derive(Debug)]
pub struct RealName(pub(crate) String);
standard_string_parser!(RealName);
#[derive(Debug)]
pub struct Nick(pub(crate) String);
standard_string_parser!(Nick);
#[derive(Debug)]
pub struct Channel(pub(crate) String);
standard_string_parser!(Channel);
#[derive(Debug)]
pub enum Receiver {
User(Nick),
Channel(Channel),
}
impl PrimitiveParser for Receiver {
fn parse(bytes: &[u8]) -> IResult<&[u8], Self> {
if let Ok((rest, _)) =
nom::bytes::complete::tag::<_, _, nom::error::Error<&[u8]>>("#")(bytes)
{
let (rest, channel) = Channel::parse(rest)?;
Ok((rest, Self::Channel(channel)))
} else {
let (rest, nick) = Nick::parse(bytes)?;
Ok((rest, Self::User(nick)))
}
}
}
#[derive(Debug)]
pub struct Message(pub(crate) String);
impl PrimitiveParser for Message {
fn parse(bytes: &[u8]) -> IResult<&[u8], Self> {
let val = std::str::from_utf8(bytes).expect("utf-8").to_string();
Ok((b"", Self(val)))
}
}