use std::str::{FromStr, Lines};
use str_reader::StringReader;
use crate::ParseError;
pub struct SessionDescriptionLines<'a> {
lines: Lines<'a>,
current: Option<(char, &'a str)>,
}
impl<'a> SessionDescriptionLines<'a> {
pub fn new(sdp: &'a str) -> Result<Self, ParseError> {
let mut res = Self {
lines: sdp.lines(),
current: None,
};
res.next()?;
Ok(res)
}
pub fn current(&self) -> Option<(char, &'a str)> {
self.current
}
pub fn next(&mut self) -> Result<(), ParseError> {
for line in &mut self.lines {
let line = line.trim();
if line.is_empty() {
continue;
}
let line = parse_sdp_line(line)
.map_err(|err| ParseError::with_cause_and_msg("invalid SDP line", err))?;
self.current = Some(line);
return Ok(());
}
self.current = None;
Ok(())
}
pub fn parse<T>(&mut self) -> Result<T, ParseError>
where
T: FromStr,
ParseError: From<T::Err>,
{
let (_, v) = self.current.unwrap();
let res = v.parse()?;
self.next()?;
Ok(res)
}
pub fn parse_multiple<T>(&mut self) -> Result<T, ParseError>
where
T: FromSessionDescriptionLines,
{
T::from_sdp_lines(self)
}
}
fn parse_sdp_line(line: &str) -> Result<(char, &str), ParseError> {
let mut reader = StringReader::new(line);
reader.skip_whitespace();
let t = reader.read_char()?;
reader.skip_whitespace();
reader.match_char('=')?;
Ok((t, reader.as_str()))
}
pub trait FromSessionDescriptionLines: Sized {
fn from_sdp_lines(lines: &mut SessionDescriptionLines) -> Result<Self, ParseError>;
}