1
0
Fork 0
mirror of https://github.com/sile/hls_m3u8.git synced 2024-11-21 23:01: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::ops::{Deref, DerefMut};
use std::str::FromStr;
use crate::tags;
use crate::types::SingleLineString;
use crate::Error;
#[derive(Debug)]
pub struct Lines<'a> {
input: &'a str,
}
impl<'a> Lines<'a> {
pub const fn new(input: &'a str) -> Self {
Lines { input }
#[derive(Debug, Default)]
pub struct Lines(Vec<Line>);
impl Lines {
pub fn new() -> Self {
Self::default()
}
}
fn read_line(&mut self) -> crate::Result<Line<'a>> {
let mut end = self.input.len();
let mut next_start = self.input.len();
let mut adjust = 0;
let mut next_line_of_ext_x_stream_inf = false;
impl FromStr for Lines {
type Err = Error;
for (i, c) in self.input.char_indices() {
match c {
'\n' => {
if !next_line_of_ext_x_stream_inf
&& self.input.starts_with(tags::ExtXStreamInf::PREFIX)
{
next_line_of_ext_x_stream_inf = true;
adjust = 0;
continue;
}
next_start = i + 1;
end = i - adjust;
break;
}
'\r' => {
adjust = 1;
}
_ => {
if c.is_control() {
return Err(Error::invalid_input());
}
adjust = 0;
}
fn from_str(input: &str) -> Result<Self, Self::Err> {
let mut result = Lines::new();
for line in input.lines() {
// ignore empty lines
if line.trim().len() == 0 {
continue;
}
}
let raw_line = &self.input[..end];
let line = if raw_line.is_empty() {
Line::Blank
} else if raw_line.starts_with("#EXT") {
Line::Tag((raw_line.parse())?)
} else if raw_line.starts_with('#') {
Line::Comment(raw_line)
} else {
let uri = SingleLineString::new(raw_line)?;
Line::Uri(uri)
};
let pline = {
if line.starts_with("#EXT") {
Line::Tag(line.parse()?)
} else if line.starts_with("#") {
continue; // ignore comments
} else {
Line::Uri(SingleLineString::new(line)?)
}
};
self.input = &self.input[next_start..];
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;
result.push(pline);
}
match self.read_line() {
Err(e) => Some(Err(e)),
Ok(line) => Some(Ok(line)),
}
Ok(result)
}
}
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)]
pub enum Line<'a> {
Blank,
Comment(&'a str),
pub enum Line {
Tag(Tag),
Uri(SingleLineString),
}

View file

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