1
0
Fork 0
mirror of https://github.com/sile/hls_m3u8.git synced 2024-06-02 08:39:41 +00:00

rewrite Lines to reduce allocations

This commit is contained in:
Luro02 2020-02-02 14:33:57 +01:00
parent 006f36ff47
commit e6a1103d24
No known key found for this signature in database
GPG key ID: B66FD4F74501A9CF
5 changed files with 59 additions and 61 deletions

View file

@ -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,

View file

@ -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),

View file

@ -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) {

View file

@ -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) {

View file

@ -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.