ftth_rsip/headers/
header.rs

1use crate::headers::untyped::*;
2
3#[doc(hidden)]
4pub use tokenizer::Tokenizer;
5
6/// Big enum holding in each variant every possible header defined in SIP. All variants hold an
7/// [untyped](super::untyped) header which is basically a NewType around String.
8///
9/// In case a header is not defined in Rsip, parsing will store it in the `Other`
10/// variant, which is a tuple of Strings.
11/// For instance, constructing the `X-Fs-Sending-Message` header (related to SMS in SIP),
12/// you can do:
13/// ```
14/// let x_fs_sending_message = ftth_rsip::Header::Other("X-FS-Sending-Message".into(), "f9c4adc8-9c2a-47d5-a7f1-63d20784685e".into());
15/// ```
16#[derive(Debug, PartialEq, Eq, Clone)]
17pub enum Header {
18    Accept(Accept),
19    AcceptEncoding(AcceptEncoding),
20    AcceptLanguage(AcceptLanguage),
21    AlertInfo(AlertInfo),
22    Allow(Allow),
23    AuthenticationInfo(AuthenticationInfo),
24    Authorization(Authorization),
25    CSeq(CSeq),
26    CallId(CallId),
27    CallInfo(CallInfo),
28    Contact(Contact),
29    ContentDisposition(ContentDisposition),
30    ContentEncoding(ContentEncoding),
31    ContentLanguage(ContentLanguage),
32    ContentLength(ContentLength),
33    ContentType(ContentType),
34    Date(Date),
35    ErrorInfo(ErrorInfo),
36    Event(Event),
37    Expires(Expires),
38    From(From),
39    InReplyTo(InReplyTo),
40    MaxForwards(MaxForwards),
41    MimeVersion(MimeVersion),
42    MinExpires(MinExpires),
43    Organization(Organization),
44    Other(String, String),
45    Priority(Priority),
46    ProxyAuthenticate(ProxyAuthenticate),
47    ProxyAuthorization(ProxyAuthorization),
48    ProxyRequire(ProxyRequire),
49    RecordRoute(RecordRoute),
50    ReplyTo(ReplyTo),
51    Require(Require),
52    RetryAfter(RetryAfter),
53    Route(Route),
54    Server(Server),
55    Subject(Subject),
56    SubscriptionState(SubscriptionState),
57    Supported(Supported),
58    Timestamp(Timestamp),
59    To(To),
60    Unsupported(Unsupported),
61    UserAgent(UserAgent),
62    Via(Via),
63    Warning(Warning),
64    WwwAuthenticate(WwwAuthenticate),
65}
66
67impl std::fmt::Display for Header {
68    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
69        match self {
70            Self::Accept(inner) => write!(f, "{}", inner),
71            Self::AcceptEncoding(inner) => write!(f, "{}", inner),
72            Self::AcceptLanguage(inner) => write!(f, "{}", inner),
73            Self::AlertInfo(inner) => write!(f, "{}", inner),
74            Self::Allow(inner) => write!(f, "{}", inner),
75            Self::AuthenticationInfo(inner) => write!(f, "{}", inner),
76            Self::Authorization(inner) => write!(f, "{}", inner),
77            Self::CSeq(inner) => write!(f, "{}", inner),
78            Self::CallId(inner) => write!(f, "{}", inner),
79            Self::CallInfo(inner) => write!(f, "{}", inner),
80            Self::Contact(inner) => write!(f, "{}", inner),
81            Self::ContentDisposition(inner) => write!(f, "{}", inner),
82            Self::ContentEncoding(inner) => write!(f, "{}", inner),
83            Self::ContentLanguage(inner) => write!(f, "{}", inner),
84            Self::ContentLength(inner) => write!(f, "{}", inner),
85            Self::ContentType(inner) => write!(f, "{}", inner),
86            Self::Date(inner) => write!(f, "{}", inner),
87            Self::ErrorInfo(inner) => write!(f, "{}", inner),
88            Self::Event(inner) => write!(f, "{}", inner),
89            Self::Expires(inner) => write!(f, "{}", inner),
90            Self::From(inner) => write!(f, "{}", inner),
91            Self::InReplyTo(inner) => write!(f, "{}", inner),
92            Self::MaxForwards(inner) => write!(f, "{}", inner),
93            Self::MimeVersion(inner) => write!(f, "{}", inner),
94            Self::MinExpires(inner) => write!(f, "{}", inner),
95            Self::Organization(inner) => write!(f, "{}", inner),
96            Self::Other(key, value) => write!(f, "{}: {}", key, value),
97            Self::Priority(inner) => write!(f, "{}", inner),
98            Self::ProxyAuthenticate(inner) => write!(f, "{}", inner),
99            Self::ProxyAuthorization(inner) => write!(f, "{}", inner),
100            Self::ProxyRequire(inner) => write!(f, "{}", inner),
101            Self::RecordRoute(inner) => write!(f, "{}", inner),
102            Self::ReplyTo(inner) => write!(f, "{}", inner),
103            Self::Require(inner) => write!(f, "{}", inner),
104            Self::RetryAfter(inner) => write!(f, "{}", inner),
105            Self::Route(inner) => write!(f, "{}", inner),
106            Self::Server(inner) => write!(f, "{}", inner),
107            Self::Subject(inner) => write!(f, "{}", inner),
108            Self::SubscriptionState(inner) => write!(f, "{}", inner),
109            Self::Supported(inner) => write!(f, "{}", inner),
110            Self::Timestamp(inner) => write!(f, "{}", inner),
111            Self::To(inner) => write!(f, "{}", inner),
112            Self::Unsupported(inner) => write!(f, "{}", inner),
113            Self::UserAgent(inner) => write!(f, "{}", inner),
114            Self::Via(inner) => write!(f, "{}", inner),
115            Self::Warning(inner) => write!(f, "{}", inner),
116            Self::WwwAuthenticate(inner) => write!(f, "{}", inner),
117        }
118    }
119}
120
121#[doc(hidden)]
122pub mod tokenizer {
123    use super::*;
124    use crate::{Error, IResult, TokenizerError};
125    use rsip_derives::Utf8Tokenizer;
126    use std::convert::TryInto;
127
128    impl<'a> TryInto<Header> for Tokenizer<'a> {
129        type Error = Error;
130
131        fn try_into(self) -> Result<Header, Error> {
132            let tokenizer: Utf8Tokenizer = self.try_into()?;
133
134            match tokenizer.name {
135                s if s.eq_ignore_ascii_case("Accept") => {
136                    Ok(Header::Accept(Accept::new(tokenizer.value)))
137                }
138                s if s.eq_ignore_ascii_case("Accept-Encoding") => {
139                    Ok(Header::AcceptEncoding(AcceptEncoding::new(tokenizer.value)))
140                }
141                s if s.eq_ignore_ascii_case("Accept-Language") => {
142                    Ok(Header::AcceptLanguage(AcceptLanguage::new(tokenizer.value)))
143                }
144                s if s.eq_ignore_ascii_case("Alert-Info") => {
145                    Ok(Header::AlertInfo(AlertInfo::new(tokenizer.value)))
146                }
147                s if s.eq_ignore_ascii_case("Allow") => {
148                    Ok(Header::Allow(Allow::new(tokenizer.value)))
149                }
150                s if s.eq_ignore_ascii_case("Authentication-Info") => Ok(
151                    Header::AuthenticationInfo(AuthenticationInfo::new(tokenizer.value)),
152                ),
153                s if s.eq_ignore_ascii_case("Authorization") => {
154                    Ok(Header::Authorization(Authorization::new(tokenizer.value)))
155                }
156                s if s.eq_ignore_ascii_case("CSeq") => Ok(Header::CSeq(CSeq::new(tokenizer.value))),
157                s if s.eq_ignore_ascii_case("Call-Id") || s.eq_ignore_ascii_case("i") => {
158                    Ok(Header::CallId(CallId::new(tokenizer.value)))
159                }
160                s if s.eq_ignore_ascii_case("Call-Info") => {
161                    Ok(Header::CallInfo(CallInfo::new(tokenizer.value)))
162                }
163                s if s.eq_ignore_ascii_case("Contact") || s.eq_ignore_ascii_case("m") => {
164                    Ok(Header::Contact(Contact::new(tokenizer.value)))
165                }
166                s if s.eq_ignore_ascii_case("Content-Disposition") => Ok(
167                    Header::ContentDisposition(ContentDisposition::new(tokenizer.value)),
168                ),
169                s if s.eq_ignore_ascii_case("Content-Encoding") || s.eq_ignore_ascii_case("e") => Ok(Header::ContentEncoding(
170                    ContentEncoding::new(tokenizer.value),
171                )),
172                s if s.eq_ignore_ascii_case("Content-Language") => Ok(Header::ContentLanguage(
173                    ContentLanguage::new(tokenizer.value),
174                )),
175                s if s.eq_ignore_ascii_case("Content-Length") || s.eq_ignore_ascii_case("l") => {
176                    Ok(Header::ContentLength(ContentLength::new(tokenizer.value)))
177                }
178                s if s.eq_ignore_ascii_case("Content-Type") || s.eq_ignore_ascii_case("c") => {
179                    Ok(Header::ContentType(ContentType::new(tokenizer.value)))
180                }
181                s if s.eq_ignore_ascii_case("Date") => Ok(Header::Date(Date::new(tokenizer.value))),
182                s if s.eq_ignore_ascii_case("Error-Info") => {
183                    Ok(Header::ErrorInfo(ErrorInfo::new(tokenizer.value)))
184                }
185                s if s.eq_ignore_ascii_case("Event") => {
186                    Ok(Header::Event(Event::new(tokenizer.value)))
187                }
188                s if s.eq_ignore_ascii_case("Expires") => {
189                    Ok(Header::Expires(Expires::new(tokenizer.value)))
190                }
191                s if s.eq_ignore_ascii_case("From") || s.eq_ignore_ascii_case("f") => Ok(Header::From(From::new(tokenizer.value))),
192                s if s.eq_ignore_ascii_case("In-Reply-To") => {
193                    Ok(Header::InReplyTo(InReplyTo::new(tokenizer.value)))
194                }
195                s if s.eq_ignore_ascii_case("Max-Forwards") => {
196                    Ok(Header::MaxForwards(MaxForwards::new(tokenizer.value)))
197                }
198                s if s.eq_ignore_ascii_case("Mime-Version") => {
199                    Ok(Header::MimeVersion(MimeVersion::new(tokenizer.value)))
200                }
201                s if s.eq_ignore_ascii_case("Min-Expires") => {
202                    Ok(Header::MinExpires(MinExpires::new(tokenizer.value)))
203                }
204                s if s.eq_ignore_ascii_case("Organization") => {
205                    Ok(Header::Organization(Organization::new(tokenizer.value)))
206                }
207                s if s.eq_ignore_ascii_case("Priority") => {
208                    Ok(Header::Priority(Priority::new(tokenizer.value)))
209                }
210                s if s.eq_ignore_ascii_case("Proxy-Authenticate") => Ok(Header::ProxyAuthenticate(
211                    ProxyAuthenticate::new(tokenizer.value),
212                )),
213                s if s.eq_ignore_ascii_case("Proxy-Authorization") => Ok(
214                    Header::ProxyAuthorization(ProxyAuthorization::new(tokenizer.value)),
215                ),
216                s if s.eq_ignore_ascii_case("Proxy-Require") => {
217                    Ok(Header::ProxyRequire(ProxyRequire::new(tokenizer.value)))
218                }
219                s if s.eq_ignore_ascii_case("Record-Route") => {
220                    Ok(Header::RecordRoute(RecordRoute::new(tokenizer.value)))
221                }
222                s if s.eq_ignore_ascii_case("Reply-To") => {
223                    Ok(Header::ReplyTo(ReplyTo::new(tokenizer.value)))
224                }
225                s if s.eq_ignore_ascii_case("Require") => {
226                    Ok(Header::Require(Require::new(tokenizer.value)))
227                }
228                s if s.eq_ignore_ascii_case("Retry-After") => {
229                    Ok(Header::RetryAfter(RetryAfter::new(tokenizer.value)))
230                }
231                s if s.eq_ignore_ascii_case("Route") => {
232                    Ok(Header::Route(Route::new(tokenizer.value)))
233                }
234                s if s.eq_ignore_ascii_case("Server") => {
235                    Ok(Header::Server(Server::new(tokenizer.value)))
236                }
237                s if s.eq_ignore_ascii_case("Subject") || s.eq_ignore_ascii_case("s") => {
238                    Ok(Header::Subject(Subject::new(tokenizer.value)))
239                }
240                s if s.eq_ignore_ascii_case("Supported") || s.eq_ignore_ascii_case("k") => {
241                    Ok(Header::Supported(Supported::new(tokenizer.value)))
242                }
243                s if s.eq_ignore_ascii_case("Timestamp") => {
244                    Ok(Header::Timestamp(Timestamp::new(tokenizer.value)))
245                }
246                s if s.eq_ignore_ascii_case("To") || s.eq_ignore_ascii_case("t") => Ok(Header::To(To::new(tokenizer.value))),
247                s if s.eq_ignore_ascii_case("Unsupported") => {
248                    Ok(Header::Unsupported(Unsupported::new(tokenizer.value)))
249                }
250                s if s.eq_ignore_ascii_case("User-Agent") => {
251                    Ok(Header::UserAgent(UserAgent::new(tokenizer.value)))
252                }
253                s if s.eq_ignore_ascii_case("Via") || s.eq_ignore_ascii_case("v") => Ok(Header::Via(Via::new(tokenizer.value))),
254                s if s.eq_ignore_ascii_case("Warning") => {
255                    Ok(Header::Warning(Warning::new(tokenizer.value)))
256                }
257                s if s.eq_ignore_ascii_case("WWW-Authenticate") => Ok(Header::WwwAuthenticate(
258                    WwwAuthenticate::new(tokenizer.value),
259                )),
260                _ => Ok(Header::Other(tokenizer.name.into(), tokenizer.value.into())),
261            }
262        }
263    }
264
265    #[derive(Debug, PartialEq, Eq, Utf8Tokenizer)]
266    pub struct Tokenizer<'a> {
267        pub name: &'a [u8],
268        pub value: &'a [u8],
269    }
270
271    impl<'a> Tokenizer<'a> {
272        pub fn tokenize(part: &'a [u8]) -> IResult<Self> {
273            use crate::NomError;
274            use nom::{
275                branch::alt,
276                bytes::complete::{tag, take_until, take_while1},
277                character::complete::space0,
278                combinator::{map, rest},
279                sequence::tuple,
280            };
281
282            let (rem, (name, _, _, value)) = tuple((
283                take_while1(crate::parser_utils::is_token),
284                tag(":"),
285                space0,
286                alt((
287                    map(tuple((take_until("\r\n"), tag("\r\n"))), |(value, _)| value),
288                    rest,
289                )),
290            ))(part)
291            .map_err(|_: NomError<'a>| TokenizerError::from(("header", part)).into())?;
292
293            Ok((rem, (name, value).into()))
294        }
295    }
296
297    impl<'a> std::convert::From<(&'a [u8], &'a [u8])> for Tokenizer<'a> {
298        fn from(tuple: (&'a [u8], &'a [u8])) -> Self {
299            Self {
300                name: tuple.0,
301                value: tuple.1,
302            }
303        }
304    }
305}