1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
use crate::headers::{
    parsers::{
        digit_header, token_header, utf8_trim_header, AcceptEncodingParser, AcceptLanguageParser,
        AcceptParser, AlertInfoParser, AuthenticationInfoParser, Authorization, CSeq, CallID,
        Contact, Date, From, MimeVersion, RetryAfter, Timestamp, UserAgent, Via, Warning,
    },
    traits::{HeaderValueParserFn, SipHeaderParser},
};
use unicase::Ascii;

/// Headers that defined in rfc3261
#[derive(Copy, Clone, PartialEq, Debug, PartialOrd, Ord, Eq)]
pub enum SipRFCHeader {
    Accept,
    AcceptEncoding,
    AcceptLanguage,
    AlertInfo,
    Allow,
    AuthenticationInfo,
    Authorization,
    CallID,
    CallInfo,
    Contact,
    ContentDisposition,
    ContentEncoding,
    ContentLanguage,
    ContentLength,
    ContentType,
    CSeq,
    Date,
    ErrorInfo,
    Expires,
    From,
    InReplyTo,
    MaxForwards,
    MimeVersion,
    MinExpires,
    Organization,
    Priority,
    ProxyAuthenticate,
    ProxyAuthorization,
    ProxyRequire,
    RecordRoute,
    ReplyTo,
    Require,
    RetryAfter,
    Route,
    Server,
    Subject,
    Supported,
    Timestamp,
    To,
    Unsupported,
    UserAgent,
    Via,
    Warning,
    WWWAuthenticate,
}

impl SipRFCHeader {
    /// Supports compact forms and case-insensitive
    pub fn from_str(s: &str) -> Option<SipRFCHeader> {
        let s = Ascii::new(s);
        macro_rules! match_str {
            ($input_str:expr, $enum_result:expr) => {
                if s == $input_str {
                    return Some($enum_result);
                }
            };
        }

        match_str!("Accept", SipRFCHeader::Accept);
        match_str!("Accept-Encoding", SipRFCHeader::AcceptEncoding);
        match_str!("Accept-Language", SipRFCHeader::AcceptLanguage);
        match_str!("Alert-Info", SipRFCHeader::AlertInfo);
        match_str!("Allow", SipRFCHeader::Allow);
        match_str!("Authentication-Info", SipRFCHeader::AuthenticationInfo);
        match_str!("Authorization", SipRFCHeader::Authorization);
        match_str!("Call-ID", SipRFCHeader::CallID);
        match_str!("i", SipRFCHeader::CallID);
        match_str!("Call-Info", SipRFCHeader::CallInfo);
        match_str!("Contact", SipRFCHeader::Contact);
        match_str!("m", SipRFCHeader::Contact);
        match_str!("Content-Disposition", SipRFCHeader::ContentDisposition);
        match_str!("Content-Encoding", SipRFCHeader::ContentEncoding);
        match_str!("e", SipRFCHeader::ContentEncoding);
        match_str!("Content-Language", SipRFCHeader::ContentLanguage);
        match_str!("Content-Length", SipRFCHeader::ContentLength);
        match_str!("l", SipRFCHeader::ContentLength);
        match_str!("Content-Type", SipRFCHeader::ContentType);
        match_str!("c", SipRFCHeader::ContentType);
        match_str!("CSeq", SipRFCHeader::CSeq);
        match_str!("Date", SipRFCHeader::Date);
        match_str!("Error-Info", SipRFCHeader::ErrorInfo);
        match_str!("Expires", SipRFCHeader::Expires);
        match_str!("From", SipRFCHeader::From);
        match_str!("f", SipRFCHeader::From);
        match_str!("In-Reply-To", SipRFCHeader::InReplyTo);
        match_str!("Max-Forwards", SipRFCHeader::MaxForwards);
        match_str!("MIME-Version", SipRFCHeader::MimeVersion);
        match_str!("Min-Expires", SipRFCHeader::MinExpires);
        match_str!("Organization", SipRFCHeader::Organization);
        match_str!("Priority", SipRFCHeader::Priority);
        match_str!("Proxy-Authenticate", SipRFCHeader::ProxyAuthenticate);
        match_str!("Proxy-Authorization", SipRFCHeader::ProxyAuthorization);
        match_str!("Proxy-Require", SipRFCHeader::ProxyRequire);
        match_str!("Record-Route", SipRFCHeader::RecordRoute);
        match_str!("Reply-To", SipRFCHeader::ReplyTo);
        match_str!("Require", SipRFCHeader::Require);
        match_str!("Retry-After", SipRFCHeader::RetryAfter);
        match_str!("Route", SipRFCHeader::Route);
        match_str!("Server", SipRFCHeader::Server);
        match_str!("Subject", SipRFCHeader::Subject);
        match_str!("s", SipRFCHeader::Subject);
        match_str!("Supported", SipRFCHeader::Supported);
        match_str!("k", SipRFCHeader::Supported);
        match_str!("Timestamp", SipRFCHeader::Timestamp);
        match_str!("To", SipRFCHeader::To);
        match_str!("t", SipRFCHeader::To);
        match_str!("Unsupported", SipRFCHeader::Unsupported);
        match_str!("User-Agent", SipRFCHeader::UserAgent);
        match_str!("Via", SipRFCHeader::Via);
        match_str!("v", SipRFCHeader::Via);
        match_str!("Warning", SipRFCHeader::Warning);
        match_str!("WWW-Authenticate", SipRFCHeader::WWWAuthenticate);
        None
    }

    pub fn as_str(&self) -> &str {
        match self {
            &SipRFCHeader::Accept => "Accept",
            &SipRFCHeader::AcceptEncoding => "Accept-Encoding",
            &SipRFCHeader::AcceptLanguage => "Accept-Language",
            &SipRFCHeader::AlertInfo => "Alert-Info",
            &SipRFCHeader::Allow => "Allow",
            &SipRFCHeader::AuthenticationInfo => "Authentication-Info",
            &SipRFCHeader::Authorization => "Authorization",
            &SipRFCHeader::CallID => "Call-ID",
            &SipRFCHeader::CallInfo => "Call-Info",
            &SipRFCHeader::Contact => "Contact",
            &SipRFCHeader::ContentDisposition => "Content-Disposition",
            &SipRFCHeader::ContentEncoding => "Content-Encoding",
            &SipRFCHeader::ContentLanguage => "Content-Language",
            &SipRFCHeader::ContentLength => "Content-Length",
            &SipRFCHeader::ContentType => "Content-Type",
            &SipRFCHeader::CSeq => "CSeq",
            &SipRFCHeader::Date => "Date",
            &SipRFCHeader::ErrorInfo => "Error-Info",
            &SipRFCHeader::Expires => "Expires",
            &SipRFCHeader::From => "From",
            &SipRFCHeader::InReplyTo => "In-Reply-To",
            &SipRFCHeader::MaxForwards => "Max-Forwards",
            &SipRFCHeader::MimeVersion => "MIME-Version",
            &SipRFCHeader::MinExpires => "Min-Expires",
            &SipRFCHeader::Organization => "Organization",
            &SipRFCHeader::Priority => "Priority",
            &SipRFCHeader::ProxyAuthenticate => "Proxy-Authenticate",
            &SipRFCHeader::ProxyAuthorization => "Proxy-Authorization",
            &SipRFCHeader::ProxyRequire => "Proxy-Require",
            &SipRFCHeader::RecordRoute => "Record-Route",
            &SipRFCHeader::ReplyTo => "Reply-To",
            &SipRFCHeader::Require => "Require",
            &SipRFCHeader::RetryAfter => "Retry-After",
            &SipRFCHeader::Route => "Route",
            &SipRFCHeader::Server => "Server",
            &SipRFCHeader::Subject => "Subject",
            &SipRFCHeader::Supported => "Supported",
            &SipRFCHeader::Timestamp => "Timestamp",
            &SipRFCHeader::To => "To",
            &SipRFCHeader::Unsupported => "Unsupported",
            &SipRFCHeader::UserAgent => "User-Agent",
            &SipRFCHeader::Via => "Via",
            &SipRFCHeader::Warning => "Warning",
            &SipRFCHeader::WWWAuthenticate => "WWW-Authenticate",
        }
    }

    pub fn get_parser(&self) -> HeaderValueParserFn {
        match self {
            &SipRFCHeader::Accept => AcceptParser::take_value,
            &SipRFCHeader::AcceptEncoding => AcceptEncodingParser::take_value,
            &SipRFCHeader::AcceptLanguage => AcceptLanguageParser::take_value,
            &SipRFCHeader::AlertInfo => AlertInfoParser::take_value,
            &SipRFCHeader::Allow => token_header::take,
            &SipRFCHeader::AuthenticationInfo => AuthenticationInfoParser::take_value,
            &SipRFCHeader::Authorization => Authorization::take_value,
            &SipRFCHeader::CallID => CallID::take_value,
            &SipRFCHeader::CallInfo => AlertInfoParser::take_value,
            &SipRFCHeader::Contact => Contact::take_value,
            &SipRFCHeader::ContentDisposition => token_header::take,
            &SipRFCHeader::ContentEncoding => token_header::take,
            &SipRFCHeader::ContentLanguage => token_header::take,
            &SipRFCHeader::ContentLength => digit_header::take,
            &SipRFCHeader::ContentType => AcceptParser::take_value,
            &SipRFCHeader::CSeq => CSeq::take_value,
            &SipRFCHeader::Date => Date::take_value,
            &SipRFCHeader::ErrorInfo => AlertInfoParser::take_value,
            &SipRFCHeader::Expires => digit_header::take,
            &SipRFCHeader::From => From::take_value,
            &SipRFCHeader::To => From::take_value,
            &SipRFCHeader::InReplyTo => CallID::take_value,
            &SipRFCHeader::MaxForwards => digit_header::take,
            &SipRFCHeader::Organization => utf8_trim_header::take,
            &SipRFCHeader::Priority => token_header::take,
            &SipRFCHeader::ProxyAuthenticate => Authorization::take_value,
            &SipRFCHeader::ProxyAuthorization => Authorization::take_value,
            &SipRFCHeader::ProxyRequire => token_header::take,
            &SipRFCHeader::RecordRoute => From::take_value,
            &SipRFCHeader::Route => From::take_value,
            &SipRFCHeader::ReplyTo => From::take_value,
            &SipRFCHeader::Require => token_header::take,
            &SipRFCHeader::RetryAfter => RetryAfter::take_value,
            &SipRFCHeader::Server => UserAgent::take_value,
            &SipRFCHeader::UserAgent => UserAgent::take_value,
            &SipRFCHeader::Subject => utf8_trim_header::take,
            &SipRFCHeader::Supported => token_header::take,
            &SipRFCHeader::MimeVersion => MimeVersion::take_value,
            &SipRFCHeader::MinExpires => digit_header::take,
            &SipRFCHeader::Timestamp => Timestamp::take_value,
            &SipRFCHeader::Unsupported => token_header::take,
            &SipRFCHeader::Via => Via::take_value,
            &SipRFCHeader::Warning => Warning::take_value,
            &SipRFCHeader::WWWAuthenticate => Authorization::take_value,
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    #[test]
    fn from_str_test() {
        assert_eq!(SipRFCHeader::from_str("V").unwrap(), SipRFCHeader::Via);
        assert_eq!(
            SipRFCHeader::from_str("accept").unwrap(),
            SipRFCHeader::Accept
        );
        assert_eq!(
            SipRFCHeader::from_str("accept-encoding").unwrap(),
            SipRFCHeader::AcceptEncoding
        );

        assert_eq!(
            SipRFCHeader::from_str("l").unwrap(),
            SipRFCHeader::ContentLength
        );

        assert_eq!(SipRFCHeader::from_str("1"), None);
    }

    #[test]
    fn as_str_test() {
        let s = SipRFCHeader::Via;
        assert_eq!(s.as_str(), "Via");
    }
}