use std::fmt;
use std::fmt::{Display, Formatter};
use crate::builder::Builder as MessageBuilder;
use crate::errors::ParserError;
use crate::parsed::Parsed;
use crate::prefix::Prefix;
use crate::tokenizer::{PartialCfg, Start, Tokenizer};
use std::convert::TryFrom;
use std::str::FromStr;
#[derive(Debug, Clone, Eq, Ord, PartialOrd, PartialEq, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct Message {
raw: String,
}
impl Message {
pub fn parse(&self) -> Result<Parsed, ParserError> {
Parsed::try_from(self.raw.as_str())
}
pub fn parse_partial<'a>(&'a self, cfg: PartialCfg<'a>) -> Result<Parsed<'a>, ParserError> {
Tokenizer::new(self.raw.as_str())?.parse_partial(cfg)
}
pub fn tokenizer(&self) -> Result<Tokenizer<Start>, ParserError> {
Tokenizer::new(self.raw.as_str())
}
pub fn builder(command: &str) -> MessageBuilder {
MessageBuilder::new(command)
}
pub fn to_builder(&self) -> Result<MessageBuilder, ParserError> {
MessageBuilder::from_str(self.raw.as_str())
}
pub fn tags(
&self,
) -> Result<impl Iterator<Item = Result<(&str, &str), ParserError>>, ParserError> {
Tokenizer::new(self.raw.as_str()).map(|tokenizer| tokenizer.tags().into_iter())
}
pub fn prefix(&self) -> Result<Option<Prefix>, ParserError> {
Tokenizer::new(self.raw.as_str()).and_then(|tokenizer| tokenizer.prefix().parts())
}
pub fn command(&self) -> Result<&str, ParserError> {
Tokenizer::new(self.raw.as_str()).and_then(|tokenizer| tokenizer.command().command())
}
pub fn params(&self) -> Result<impl Iterator<Item = &str>, ParserError> {
Tokenizer::new(self.raw.as_str()).map(|tokenizer| tokenizer.params().into_iter())
}
pub fn trailing(&self) -> Result<Option<&str>, ParserError> {
Tokenizer::new(self.raw.as_str()).map(|tokenizer| tokenizer.trailing().trailing())
}
}
impl Display for Message {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
self.raw.fmt(f)
}
}
impl FromStr for Message {
type Err = ParserError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(Message::from(s.to_string()))
}
}
impl From<String> for Message {
fn from(raw: String) -> Self {
Message { raw }
}
}
impl From<&str> for Message {
fn from(raw: &str) -> Self {
Message {
raw: raw.to_string(),
}
}
}
#[cfg(test)]
mod tests {
use crate::message::Message;
#[test]
#[cfg(feature = "serde")]
fn test_serde() {
let message =
Message::from("@test=test :user@prefix!host COMMAND param :trailing".to_string());
let serialized = serde_json::to_string(&message).unwrap();
println!("Ser: {}", serialized);
let deserialized: Message = serde_json::from_str(serialized.as_str()).unwrap();
assert_eq!(deserialized.to_string(), message.to_string());
}
#[test]
fn test_tags() {
let message =
Message::from("@test=test :user@prefix!host COMMAND param :trailing".to_string());
let tags = message.tags();
assert!(tags.is_ok(), "{:?}", tags.err());
let mut tags = tags.unwrap().into_iter();
let tag = tags.next();
assert!(tag.is_some(), "{:?}", tag);
}
#[test]
fn test_prefix() {
let message =
Message::from("@test=test :user@prefix!host COMMAND param :trailing".to_string());
let prefix = message.prefix();
assert!(prefix.is_ok(), "{:?}", prefix);
let prefix = prefix.unwrap();
assert!(prefix.is_some(), "{:?}", prefix);
}
}