mirror of
https://github.com/sile/hls_m3u8.git
synced 2025-02-16 21:25:15 +00:00
rewrite Lines
to reduce allocations
This commit is contained in:
parent
006f36ff47
commit
e6a1103d24
5 changed files with 59 additions and 61 deletions
|
@ -4,7 +4,12 @@
|
||||||
clippy::nursery,
|
clippy::nursery,
|
||||||
clippy::cargo
|
clippy::cargo
|
||||||
)]
|
)]
|
||||||
#![allow(clippy::multiple_crate_versions, clippy::must_use_candidate)]
|
#![allow(
|
||||||
|
clippy::multiple_crate_versions,
|
||||||
|
clippy::must_use_candidate,
|
||||||
|
clippy::module_name_repetitions,
|
||||||
|
clippy::default_trait_access
|
||||||
|
)]
|
||||||
#![warn(
|
#![warn(
|
||||||
missing_docs,
|
missing_docs,
|
||||||
missing_copy_implementations,
|
missing_copy_implementations,
|
||||||
|
|
103
src/line.rs
103
src/line.rs
|
@ -1,93 +1,86 @@
|
||||||
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::Error;
|
use crate::Error;
|
||||||
|
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Ord, Eq, Hash)]
|
||||||
pub struct Lines(Vec<Line>);
|
pub(crate) struct Lines<'a> {
|
||||||
|
buffer: &'a str,
|
||||||
impl Lines {
|
// the line at which the iterator currently is
|
||||||
pub fn new() -> Self { Self::default() }
|
position: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FromStr for Lines {
|
impl<'a> Iterator for Lines<'a> {
|
||||||
type Err = Error;
|
type Item = crate::Result<Line>;
|
||||||
|
|
||||||
fn from_str(input: &str) -> Result<Self, Self::Err> {
|
|
||||||
let mut result = Self::new();
|
|
||||||
|
|
||||||
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
let mut stream_inf = false;
|
let mut stream_inf = false;
|
||||||
let mut stream_inf_line = None;
|
let mut stream_inf_line = None;
|
||||||
|
|
||||||
for l in input.lines() {
|
for line in self.buffer.lines().skip(self.position) {
|
||||||
let raw_line = l.trim();
|
let line = line.trim();
|
||||||
|
self.position += 1;
|
||||||
|
|
||||||
if raw_line.is_empty() {
|
if line.is_empty() {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
let line = {
|
if line.starts_with(tags::ExtXStreamInf::PREFIX) {
|
||||||
if raw_line.starts_with(tags::ExtXStreamInf::PREFIX) {
|
stream_inf = true;
|
||||||
stream_inf = true;
|
stream_inf_line = Some(line);
|
||||||
stream_inf_line = Some(raw_line);
|
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
} else if raw_line.starts_with("#EXT") {
|
} else if line.starts_with("#EXT") {
|
||||||
Line::Tag(raw_line.parse()?)
|
match line.parse() {
|
||||||
} else if raw_line.starts_with('#') {
|
Ok(value) => return Some(Ok(Line::Tag(value))),
|
||||||
continue; // ignore comments
|
Err(e) => return Some(Err(e)),
|
||||||
} else {
|
}
|
||||||
// stream inf line needs special treatment
|
} else if line.starts_with('#') {
|
||||||
if stream_inf {
|
continue; // ignore comments
|
||||||
stream_inf = false;
|
} else {
|
||||||
if let Some(first_line) = stream_inf_line {
|
// stream inf line needs special treatment
|
||||||
let res = Line::Tag(format!("{}\n{}", first_line, raw_line).parse()?);
|
if stream_inf {
|
||||||
stream_inf_line = None;
|
stream_inf = false;
|
||||||
res
|
|
||||||
} else {
|
if let Some(first_line) = stream_inf_line {
|
||||||
continue;
|
match format!("{}\n{}", first_line, line).parse() {
|
||||||
|
Ok(value) => {
|
||||||
|
return Some(Ok(Line::Tag(value)));
|
||||||
|
}
|
||||||
|
Err(e) => return Some(Err(e)),
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Line::Uri(raw_line.to_string())
|
continue;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
return Some(Ok(Line::Uri(line.to_string())));
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
result.push(line);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(result)
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IntoIterator for Lines {
|
impl<'a> From<&'a str> for Lines<'a> {
|
||||||
type IntoIter = ::std::vec::IntoIter<Line>;
|
fn from(buffer: &'a str) -> Self {
|
||||||
type Item = Line;
|
Self {
|
||||||
|
buffer,
|
||||||
fn into_iter(self) -> Self::IntoIter { self.0.into_iter() }
|
position: 0,
|
||||||
}
|
}
|
||||||
|
}
|
||||||
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 }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub enum Line {
|
pub(crate) enum Line {
|
||||||
Tag(Tag),
|
Tag(Tag),
|
||||||
Uri(String),
|
Uri(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::large_enum_variant)]
|
#[allow(clippy::large_enum_variant)]
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub enum Tag {
|
pub(crate) enum Tag {
|
||||||
ExtM3u(tags::ExtM3u),
|
ExtM3u(tags::ExtM3u),
|
||||||
ExtXVersion(tags::ExtXVersion),
|
ExtXVersion(tags::ExtXVersion),
|
||||||
ExtInf(tags::ExtInf),
|
ExtInf(tags::ExtInf),
|
||||||
|
|
|
@ -272,8 +272,8 @@ impl FromStr for MasterPlaylist {
|
||||||
let mut session_key_tags = vec![];
|
let mut session_key_tags = vec![];
|
||||||
let mut unknown_tags = vec![];
|
let mut unknown_tags = vec![];
|
||||||
|
|
||||||
for (i, line) in input.parse::<Lines>()?.into_iter().enumerate() {
|
for (i, line) in Lines::from(input).enumerate() {
|
||||||
match line {
|
match line? {
|
||||||
Line::Tag(tag) => {
|
Line::Tag(tag) => {
|
||||||
if i == 0 {
|
if i == 0 {
|
||||||
if tag != Tag::ExtM3u(ExtM3u) {
|
if tag != Tag::ExtM3u(ExtM3u) {
|
||||||
|
|
|
@ -285,8 +285,8 @@ fn parse_media_playlist(
|
||||||
|
|
||||||
let mut available_key_tags: Vec<crate::tags::ExtXKey> = vec![];
|
let mut available_key_tags: Vec<crate::tags::ExtXKey> = vec![];
|
||||||
|
|
||||||
for (i, line) in input.parse::<Lines>()?.into_iter().enumerate() {
|
for (i, line) in Lines::from(input).enumerate() {
|
||||||
match line {
|
match line? {
|
||||||
Line::Tag(tag) => {
|
Line::Tag(tag) => {
|
||||||
if i == 0 {
|
if i == 0 {
|
||||||
if tag != Tag::ExtM3u(ExtM3u) {
|
if tag != Tag::ExtM3u(ExtM3u) {
|
||||||
|
|
|
@ -14,7 +14,7 @@ use crate::{Encrypted, RequiredVersion};
|
||||||
#[builder(setter(into, strip_option))]
|
#[builder(setter(into, strip_option))]
|
||||||
#[shorthand(enable(must_use, get_mut, collection_magic))]
|
#[shorthand(enable(must_use, get_mut, collection_magic))]
|
||||||
pub struct MediaSegment {
|
pub struct MediaSegment {
|
||||||
/// Sets all [`ExtXKey`] tags.
|
/// All [`ExtXKey`] tags.
|
||||||
#[builder(default)]
|
#[builder(default)]
|
||||||
keys: Vec<ExtXKey>,
|
keys: Vec<ExtXKey>,
|
||||||
/// The [`ExtXMap`] tag associated with the media segment.
|
/// The [`ExtXMap`] tag associated with the media segment.
|
||||||
|
|
Loading…
Reference in a new issue