sipmsg/headers/parsers/
accept_language.rs

1use crate::{
2    common::{bnfcore::is_alpha, errorparse::SipParseError, nom_wrappers::take_sws},
3    headers::{
4        header::{HeaderValue, HeaderValueType},
5        traits::SipHeaderParser,
6    },
7};
8use nom::{bytes::complete::take_while1};
9
10/// Accept-Language  =  "Accept-Language" HCOLON
11//                      [ language *(COMMA language) ]
12// language         =  language-range *(SEMI accept-param)
13// language-range   =  ( ( 1*8ALPHA *( "-" 1*8ALPHA ) ) / "*" )
14pub struct AcceptLanguageParser;
15
16impl SipHeaderParser for AcceptLanguageParser {
17    fn take_value(initial_input: &[u8]) -> nom::IResult<&[u8], HeaderValue, SipParseError> {
18        if !initial_input.is_empty() && initial_input[0] == b'*' {
19            let (input, _) = take_sws(initial_input)?;
20            let (_, hdr_val) =
21                HeaderValue::new(&input[..1], HeaderValueType::TokenValue, None, None)?;
22            return Ok((&input[1..], hdr_val));
23        }
24        let (input, left_part) = take_while1(is_alpha)(initial_input)?;
25        if !input.is_empty() && input[0] != b'-' {
26            let (_, hdr_val) =
27                HeaderValue::new(left_part, HeaderValueType::TokenValue, None, None)?;
28            return Ok((input, hdr_val));
29        }
30        if left_part.len() < 1 || left_part.len() > 8 {
31            return sip_parse_error!(1, "Invalid length of left part of AcceptLanguage Header");
32        }
33
34        let (input, _) = nom::character::complete::char('-')(input)?; // skip -
35        let (input, right_part) = take_while1(is_alpha)(input)?;
36
37        if right_part.len() < 1 || right_part.len() > 8 {
38            return sip_parse_error!(2, "Invalid length of right part of AcceptLanguage Header");
39        }
40        let offset = left_part.len() + right_part.len() + 1 /*`-`*/;
41        let (_, hdr_val) = HeaderValue::new(
42            &initial_input[..offset],
43            HeaderValueType::TokenValue,
44            None,
45            None,
46        )?;
47        Ok((input, hdr_val))
48    }
49}
50
51#[cfg(test)]
52mod test {
53    use super::*;
54    // Accept-Language: da, en-gb;q=0.8, en;q=0.7
55    #[test]
56    fn accept_language_value() {
57        let (input, val) = AcceptLanguageParser::take_value("en-gb ;q=0.8\r\n".as_bytes()).unwrap();
58        assert_eq!(input, " ;q=0.8\r\n".as_bytes());
59        assert_eq!(val.vstr, "en-gb");
60
61        let (input, val) = AcceptLanguageParser::take_value("da \r\n".as_bytes()).unwrap();
62        assert_eq!(input, " \r\n".as_bytes());
63        assert_eq!(val.vstr, "da");
64
65        let (input, val) = AcceptLanguageParser::take_value("*\r\n".as_bytes()).unwrap();
66        assert_eq!(input, "\r\n".as_bytes());
67        assert_eq!(val.vstr, "*");
68    }
69}