1
0
Fork 0
mirror of https://github.com/sile/hls_m3u8.git synced 2024-11-26 00:51:00 +00:00

Rewrote Lines

This commit is contained in:
Luro02 2019-09-14 11:57:56 +02:00
parent 3721106795
commit 273c0990dc
3 changed files with 72 additions and 78 deletions

View file

@ -1,87 +1,74 @@
use std::fmt; use std::fmt;
use std::ops::{Deref, DerefMut};
use std::str::FromStr; use std::str::FromStr;
use crate::tags; use crate::tags;
use crate::types::SingleLineString; use crate::types::SingleLineString;
use crate::Error; use crate::Error;
#[derive(Debug)] #[derive(Debug, Default)]
pub struct Lines<'a> { pub struct Lines(Vec<Line>);
input: &'a str,
impl Lines {
pub fn new() -> Self {
Self::default()
} }
impl<'a> Lines<'a> {
pub const fn new(input: &'a str) -> Self {
Lines { input }
} }
fn read_line(&mut self) -> crate::Result<Line<'a>> { impl FromStr for Lines {
let mut end = self.input.len(); type Err = Error;
let mut next_start = self.input.len();
let mut adjust = 0;
let mut next_line_of_ext_x_stream_inf = false;
for (i, c) in self.input.char_indices() { fn from_str(input: &str) -> Result<Self, Self::Err> {
match c { let mut result = Lines::new();
'\n' => {
if !next_line_of_ext_x_stream_inf for line in input.lines() {
&& self.input.starts_with(tags::ExtXStreamInf::PREFIX) // ignore empty lines
{ if line.trim().len() == 0 {
next_line_of_ext_x_stream_inf = true;
adjust = 0;
continue; continue;
} }
next_start = i + 1;
end = i - adjust;
break;
}
'\r' => {
adjust = 1;
}
_ => {
if c.is_control() {
return Err(Error::invalid_input());
}
adjust = 0;
}
}
}
let raw_line = &self.input[..end];
let line = if raw_line.is_empty() { let pline = {
Line::Blank if line.starts_with("#EXT") {
} else if raw_line.starts_with("#EXT") { Line::Tag(line.parse()?)
Line::Tag((raw_line.parse())?) } else if line.starts_with("#") {
} else if raw_line.starts_with('#') { continue; // ignore comments
Line::Comment(raw_line)
} else { } else {
let uri = SingleLineString::new(raw_line)?; Line::Uri(SingleLineString::new(line)?)
Line::Uri(uri) }
}; };
self.input = &self.input[next_start..]; result.push(pline);
Ok(line)
}
}
impl<'a> Iterator for Lines<'a> {
type Item = crate::Result<Line<'a>>;
fn next(&mut self) -> Option<Self::Item> {
if self.input.is_empty() {
return None;
} }
match self.read_line() { Ok(result)
Err(e) => Some(Err(e)), }
Ok(line) => Some(Ok(line)), }
}
impl IntoIterator for Lines {
type Item = Line;
type IntoIter = ::std::vec::IntoIter<Line>;
fn into_iter(self) -> Self::IntoIter {
self.0.into_iter()
}
}
impl Deref for Lines {
type Target = Vec<Line>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl DerefMut for Lines {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
} }
} }
#[allow(clippy::large_enum_variant)]
#[derive(Debug, PartialEq, Eq)] #[derive(Debug, PartialEq, Eq)]
pub enum Line<'a> { pub enum Line {
Blank,
Comment(&'a str),
Tag(Tag), Tag(Tag),
Uri(SingleLineString), Uri(SingleLineString),
} }

View file

@ -9,7 +9,7 @@ use crate::tags::{
ExtXSessionKey, ExtXStart, ExtXStreamInf, ExtXVersion, MasterPlaylistTag, ExtXSessionKey, ExtXStart, ExtXStreamInf, ExtXVersion, MasterPlaylistTag,
}; };
use crate::types::{ClosedCaptions, MediaType, ProtocolVersion}; use crate::types::{ClosedCaptions, MediaType, ProtocolVersion};
use crate::{Error, Result}; use crate::Error;
/// Master playlist builder. /// Master playlist builder.
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
@ -69,7 +69,7 @@ impl MasterPlaylistBuilder {
} }
/// Builds a `MasterPlaylist` instance. /// Builds a `MasterPlaylist` instance.
pub fn finish(self) -> Result<MasterPlaylist> { pub fn finish(self) -> crate::Result<MasterPlaylist> {
let required_version = self.required_version(); let required_version = self.required_version();
let specified_version = self.version.unwrap_or(required_version); let specified_version = self.version.unwrap_or(required_version);
@ -116,7 +116,7 @@ impl MasterPlaylistBuilder {
.expect("Never fails") .expect("Never fails")
} }
fn validate_stream_inf_tags(&self) -> Result<()> { fn validate_stream_inf_tags(&self) -> crate::Result<()> {
let mut has_none_closed_captions = false; let mut has_none_closed_captions = false;
for t in &self.stream_inf_tags { for t in &self.stream_inf_tags {
if let Some(group_id) = t.audio() { if let Some(group_id) = t.audio() {
@ -159,7 +159,7 @@ impl MasterPlaylistBuilder {
Ok(()) Ok(())
} }
fn validate_i_frame_stream_inf_tags(&self) -> Result<()> { fn validate_i_frame_stream_inf_tags(&self) -> crate::Result<()> {
for t in &self.i_frame_stream_inf_tags { for t in &self.i_frame_stream_inf_tags {
if let Some(group_id) = t.video() { if let Some(group_id) = t.video() {
if !self.check_media_group(MediaType::Video, group_id) { if !self.check_media_group(MediaType::Video, group_id) {
@ -171,7 +171,7 @@ impl MasterPlaylistBuilder {
Ok(()) Ok(())
} }
fn validate_session_data_tags(&self) -> Result<()> { fn validate_session_data_tags(&self) -> crate::Result<()> {
let mut set = HashSet::new(); let mut set = HashSet::new();
for t in &self.session_data_tags { for t in &self.session_data_tags {
if !set.insert((t.data_id(), t.language())) { if !set.insert((t.data_id(), t.language())) {
@ -182,7 +182,7 @@ impl MasterPlaylistBuilder {
Ok(()) Ok(())
} }
fn validate_session_key_tags(&self) -> Result<()> { fn validate_session_key_tags(&self) -> crate::Result<()> {
let mut set = HashSet::new(); let mut set = HashSet::new();
for t in &self.session_key_tags { for t in &self.session_key_tags {
if !set.insert(t.key()) { if !set.insert(t.key()) {
@ -294,11 +294,11 @@ impl fmt::Display for MasterPlaylist {
impl FromStr for MasterPlaylist { impl FromStr for MasterPlaylist {
type Err = Error; type Err = Error;
fn from_str(s: &str) -> Result<Self> {
fn from_str(input: &str) -> Result<Self, Self::Err> {
let mut builder = MasterPlaylistBuilder::new(); let mut builder = MasterPlaylistBuilder::new();
for (i, line) in Lines::new(s).enumerate() { for (i, line) in input.parse::<Lines>()?.into_iter().enumerate() {
match (line)? { match line {
Line::Blank | Line::Comment(_) => {}
Line::Tag(tag) => { Line::Tag(tag) => {
if i == 0 { if i == 0 {
if tag != Tag::ExtM3u(ExtM3u) { if tag != Tag::ExtM3u(ExtM3u) {
@ -373,3 +373,11 @@ impl FromStr for MasterPlaylist {
builder.finish() builder.finish()
} }
} }
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_parser() {}
}

View file

@ -337,9 +337,8 @@ impl MediaPlaylistOptions {
let mut segment = MediaSegmentBuilder::new(); let mut segment = MediaSegmentBuilder::new();
let mut has_partial_segment = false; let mut has_partial_segment = false;
let mut has_discontinuity_tag = false; let mut has_discontinuity_tag = false;
for (i, line) in Lines::new(m3u8).enumerate() { for (i, line) in m3u8.parse::<Lines>()?.into_iter().enumerate() {
match (line)? { match line {
Line::Blank | Line::Comment(_) => {}
Line::Tag(tag) => { Line::Tag(tag) => {
if i == 0 { if i == 0 {
if tag != Tag::ExtM3u(ExtM3u) { if tag != Tag::ExtM3u(ExtM3u) {