use crate::{
common::{
bnfcore::{is_crlf, is_token_char},
errorparse::SipParseError,
nom_wrappers::take_sws,
take_sws_token,
},
headers::{
header::{HeaderValue, HeaderValueType},
traits::SipHeaderParser,
},
};
use nom::bytes::complete::{take_until, take_while1};
pub struct UserAgent;
impl SipHeaderParser for UserAgent {
fn take_value(source_input: &[u8]) -> nom::IResult<&[u8], HeaderValue, SipParseError> {
let mut tmp_input = source_input;
loop {
if tmp_input.len() < 2 || is_crlf(tmp_input) {
break;
}
if tmp_input[0] == b'(' {
let (input, _) = take_sws_token::lparen(tmp_input)?;
let (input, _) = take_until(")")(input)?;
let (input, _) = take_sws_token::rparen(input)?;
tmp_input = input;
continue;
}
if tmp_input[0] == b'/' {
let (input, _) = take_sws_token::slash(tmp_input)?;
let (input, _) = take_while1(is_token_char)(input)?;
let (input, _) = take_sws(input)?;
tmp_input = input;
continue;
}
if tmp_input[0] == b'<' {
let (input, _) = take_sws_token::laquot(tmp_input)?;
let (input, _) = take_until(">")(input)?;
let (input, _) = take_sws_token::raquot(input)?;
tmp_input = input;
continue;
}
let (input, _) = take_while1(is_token_char)(tmp_input)?;
let (input, _) = take_sws(input)?;
tmp_input = input;
}
let (_, hdr_val) = HeaderValue::new(
&source_input[..source_input.len() - tmp_input.len()],
HeaderValueType::UserAgent,
None,
None,
)?;
Ok((tmp_input, hdr_val))
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn test_server_value() {
let (input, val) = UserAgent::take_value("HomeServer v2\r\n".as_bytes()).unwrap();
assert_eq!(val.vstr, "HomeServer v2");
assert_eq!(input, b"\r\n");
}
#[test]
fn test_user_agent_val() {
let user_agent = "<Motorola VT1000 mac: 000CE5C74EF8 sw:VT20_02.03.00_A ln:0 cfg:1253778536520/1002173358>";
let ua_with_end_line = [user_agent, "\r\n"].join("");
let (input, val) = UserAgent::take_value(ua_with_end_line.as_bytes()).unwrap();
assert_eq!(val.vstr, user_agent);
assert_eq!(input, b"\r\n");
}
}