1use std::fmt;
2use std::fmt::{Display, Formatter};
3
4use crate::builder::Builder as MessageBuilder;
5use crate::errors::ParserError;
6use crate::parsed::Parsed;
7use crate::prefix::Prefix;
8use crate::tokenizer::{PartialCfg, Start, Tokenizer};
9use std::convert::TryFrom;
10use std::str::FromStr;
11
12#[derive(Debug, Clone, Eq, Ord, PartialOrd, PartialEq, Hash)]
40#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
41pub struct Message {
42 raw: String,
43}
44
45impl Message {
46 pub fn parse(&self) -> Result<Parsed, ParserError> {
48 Parsed::try_from(self.raw.as_str())
49 }
50
51 pub fn parse_partial<'a>(&'a self, cfg: PartialCfg<'a>) -> Result<Parsed<'a>, ParserError> {
78 Tokenizer::new(self.raw.as_str())?.parse_partial(cfg)
79 }
80
81 pub fn tokenizer(&self) -> Result<Tokenizer<Start>, ParserError> {
83 Tokenizer::new(self.raw.as_str())
84 }
85
86 pub fn builder(command: &str) -> MessageBuilder {
88 MessageBuilder::new(command)
89 }
90
91 pub fn to_builder(&self) -> Result<MessageBuilder, ParserError> {
94 MessageBuilder::from_str(self.raw.as_str())
95 }
96
97 pub fn tags(
99 &self,
100 ) -> Result<impl Iterator<Item = Result<(&str, &str), ParserError>>, ParserError> {
101 Tokenizer::new(self.raw.as_str()).map(|tokenizer| tokenizer.tags().into_iter())
102 }
103
104 pub fn prefix(&self) -> Result<Option<Prefix>, ParserError> {
106 Tokenizer::new(self.raw.as_str()).and_then(|tokenizer| tokenizer.prefix().parts())
107 }
108
109 pub fn command(&self) -> Result<&str, ParserError> {
111 Tokenizer::new(self.raw.as_str()).and_then(|tokenizer| tokenizer.command().command())
112 }
113
114 pub fn params(&self) -> Result<impl Iterator<Item = &str>, ParserError> {
116 Tokenizer::new(self.raw.as_str()).map(|tokenizer| tokenizer.params().into_iter())
117 }
118
119 pub fn trailing(&self) -> Result<Option<&str>, ParserError> {
121 Tokenizer::new(self.raw.as_str()).map(|tokenizer| tokenizer.trailing().trailing())
122 }
123}
124
125impl Display for Message {
126 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
127 self.raw.fmt(f)
128 }
129}
130
131impl FromStr for Message {
132 type Err = ParserError;
133
134 fn from_str(s: &str) -> Result<Self, Self::Err> {
135 Ok(Message::from(s.to_string()))
136 }
137}
138
139impl From<String> for Message {
140 fn from(raw: String) -> Self {
141 Message { raw }
142 }
143}
144
145impl From<&str> for Message {
146 fn from(raw: &str) -> Self {
147 Message {
148 raw: raw.to_string(),
149 }
150 }
151}
152
153#[cfg(test)]
154mod tests {
155 use crate::message::Message;
156
157 #[test]
158 #[cfg(feature = "serde")]
159 fn test_serde() {
160 let message =
161 Message::from("@test=test :user@prefix!host COMMAND param :trailing".to_string());
162 let serialized = serde_json::to_string(&message).unwrap();
163 println!("Ser: {}", serialized);
164 let deserialized: Message = serde_json::from_str(serialized.as_str()).unwrap();
165 assert_eq!(deserialized.to_string(), message.to_string());
166 }
167
168 #[test]
169 fn test_tags() {
170 let message =
171 Message::from("@test=test :user@prefix!host COMMAND param :trailing".to_string());
172 let tags = message.tags();
173 assert!(tags.is_ok(), "{:?}", tags.err());
174 let mut tags = tags.unwrap().into_iter();
175 let tag = tags.next();
176 assert!(tag.is_some(), "{:?}", tag);
177 }
178
179 #[test]
180 fn test_prefix() {
181 let message =
182 Message::from("@test=test :user@prefix!host COMMAND param :trailing".to_string());
183 let prefix = message.prefix();
184 assert!(prefix.is_ok(), "{:?}", prefix);
185 let prefix = prefix.unwrap();
186 assert!(prefix.is_some(), "{:?}", prefix);
187 }
188}