1
0
Fork 0
mirror of https://github.com/sile/hls_m3u8.git synced 2024-06-02 13:39:27 +00:00
hls_m3u8/src/line.rs

184 lines
7 KiB
Rust
Raw Normal View History

2020-02-06 11:27:48 +00:00
use std::convert::TryFrom;
2018-02-14 15:50:57 +00:00
use std::fmt;
use std::str::FromStr;
2019-09-13 14:06:52 +00:00
use crate::tags;
use crate::Error;
#[derive(Debug, Clone, PartialEq, PartialOrd, Ord, Eq, Hash)]
2020-02-02 13:33:57 +00:00
pub(crate) struct Lines<'a> {
buffer: &'a str,
// the line at which the iterator currently is
position: usize,
2019-09-14 09:57:56 +00:00
}
2018-02-11 06:10:52 +00:00
2020-02-02 13:33:57 +00:00
impl<'a> Iterator for Lines<'a> {
2020-02-06 11:27:48 +00:00
type Item = crate::Result<Line<'a>>;
2019-09-14 09:57:56 +00:00
2020-02-02 13:33:57 +00:00
fn next(&mut self) -> Option<Self::Item> {
2019-09-14 10:29:54 +00:00
let mut stream_inf = false;
let mut stream_inf_line = None;
2020-02-02 13:33:57 +00:00
for line in self.buffer.lines().skip(self.position) {
let line = line.trim();
self.position += 1;
2019-09-14 10:29:54 +00:00
2020-02-02 13:33:57 +00:00
if line.is_empty() {
2019-09-14 09:57:56 +00:00
continue;
2018-02-11 06:10:52 +00:00
}
2019-09-14 09:57:56 +00:00
2020-02-02 13:33:57 +00:00
if line.starts_with(tags::ExtXStreamInf::PREFIX) {
stream_inf = true;
stream_inf_line = Some(line);
2019-09-14 10:29:54 +00:00
2020-02-02 13:33:57 +00:00
continue;
} else if line.starts_with("#EXT") {
2020-02-06 11:27:48 +00:00
return Some(Tag::try_from(line).map(Line::Tag));
2020-02-02 13:33:57 +00:00
} else if line.starts_with('#') {
continue; // ignore comments
} else {
// stream inf line needs special treatment
if stream_inf {
stream_inf = false;
if let Some(first_line) = stream_inf_line {
2020-02-06 11:27:48 +00:00
return Some(
tags::ExtXStreamInf::from_str(&format!("{}\n{}", first_line, line))
.map(|v| Line::Tag(Tag::ExtXStreamInf(v))),
);
2019-09-14 10:29:54 +00:00
} else {
2020-02-02 13:33:57 +00:00
continue;
2019-09-14 10:29:54 +00:00
}
2020-02-02 13:33:57 +00:00
} else {
2020-02-06 11:27:48 +00:00
return Some(Ok(Line::Uri(line)));
2019-09-14 09:57:56 +00:00
}
2020-02-02 13:33:57 +00:00
}
2018-02-11 06:10:52 +00:00
}
2019-09-14 09:57:56 +00:00
2020-02-02 13:33:57 +00:00
None
2018-02-11 06:10:52 +00:00
}
}
2019-09-13 14:06:52 +00:00
2020-02-02 13:33:57 +00:00
impl<'a> From<&'a str> for Lines<'a> {
fn from(buffer: &'a str) -> Self {
Self {
buffer,
position: 0,
}
}
2018-02-11 06:10:52 +00:00
}
#[derive(Debug, Clone, PartialEq)]
2020-02-06 11:27:48 +00:00
pub(crate) enum Line<'a> {
Tag(Tag<'a>),
Uri(&'a str),
2018-02-11 06:10:52 +00:00
}
2019-03-31 10:00:02 +00:00
#[allow(clippy::large_enum_variant)]
#[derive(Debug, Clone, PartialEq)]
2020-02-06 11:27:48 +00:00
pub(crate) enum Tag<'a> {
2018-02-14 19:51:44 +00:00
ExtXVersion(tags::ExtXVersion),
ExtInf(tags::ExtInf),
ExtXByteRange(tags::ExtXByteRange),
ExtXDiscontinuity(tags::ExtXDiscontinuity),
ExtXKey(tags::ExtXKey),
ExtXMap(tags::ExtXMap),
ExtXProgramDateTime(tags::ExtXProgramDateTime),
ExtXDateRange(tags::ExtXDateRange),
ExtXTargetDuration(tags::ExtXTargetDuration),
ExtXMediaSequence(tags::ExtXMediaSequence),
ExtXDiscontinuitySequence(tags::ExtXDiscontinuitySequence),
ExtXEndList(tags::ExtXEndList),
ExtXPlaylistType(tags::ExtXPlaylistType),
ExtXIFramesOnly(tags::ExtXIFramesOnly),
ExtXMedia(tags::ExtXMedia),
ExtXStreamInf(tags::ExtXStreamInf),
ExtXIFrameStreamInf(tags::ExtXIFrameStreamInf),
ExtXSessionData(tags::ExtXSessionData),
ExtXSessionKey(tags::ExtXSessionKey),
ExtXIndependentSegments(tags::ExtXIndependentSegments),
ExtXStart(tags::ExtXStart),
2020-02-06 11:27:48 +00:00
Unknown(&'a str),
2018-02-14 15:50:57 +00:00
}
2019-09-13 14:06:52 +00:00
2020-02-06 11:27:48 +00:00
impl<'a> fmt::Display for Tag<'a> {
2018-02-14 15:50:57 +00:00
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2019-09-14 19:42:06 +00:00
match &self {
2019-10-05 14:08:03 +00:00
Self::ExtXVersion(value) => value.fmt(f),
Self::ExtInf(value) => value.fmt(f),
Self::ExtXByteRange(value) => value.fmt(f),
Self::ExtXDiscontinuity(value) => value.fmt(f),
Self::ExtXKey(value) => value.fmt(f),
Self::ExtXMap(value) => value.fmt(f),
Self::ExtXProgramDateTime(value) => value.fmt(f),
Self::ExtXDateRange(value) => value.fmt(f),
Self::ExtXTargetDuration(value) => value.fmt(f),
Self::ExtXMediaSequence(value) => value.fmt(f),
Self::ExtXDiscontinuitySequence(value) => value.fmt(f),
Self::ExtXEndList(value) => value.fmt(f),
Self::ExtXPlaylistType(value) => value.fmt(f),
Self::ExtXIFramesOnly(value) => value.fmt(f),
Self::ExtXMedia(value) => value.fmt(f),
Self::ExtXStreamInf(value) => value.fmt(f),
Self::ExtXIFrameStreamInf(value) => value.fmt(f),
Self::ExtXSessionData(value) => value.fmt(f),
Self::ExtXSessionKey(value) => value.fmt(f),
Self::ExtXIndependentSegments(value) => value.fmt(f),
Self::ExtXStart(value) => value.fmt(f),
Self::Unknown(value) => value.fmt(f),
2018-02-14 15:50:57 +00:00
}
}
}
2019-09-13 14:06:52 +00:00
2020-02-06 11:27:48 +00:00
impl<'a> TryFrom<&'a str> for Tag<'a> {
type Error = Error;
2019-09-13 14:06:52 +00:00
2020-02-06 11:27:48 +00:00
fn try_from(input: &'a str) -> Result<Self, Self::Error> {
if input.starts_with(tags::ExtXVersion::PREFIX) {
2019-10-05 14:08:03 +00:00
input.parse().map(Self::ExtXVersion)
2019-10-03 14:23:27 +00:00
} else if input.starts_with(tags::ExtInf::PREFIX) {
2019-10-05 14:08:03 +00:00
input.parse().map(Self::ExtInf)
2019-10-03 14:23:27 +00:00
} else if input.starts_with(tags::ExtXByteRange::PREFIX) {
2019-10-05 14:08:03 +00:00
input.parse().map(Self::ExtXByteRange)
2019-10-03 14:23:27 +00:00
} else if input.starts_with(tags::ExtXDiscontinuity::PREFIX) {
2019-10-05 14:08:03 +00:00
input.parse().map(Self::ExtXDiscontinuity)
2019-10-03 14:23:27 +00:00
} else if input.starts_with(tags::ExtXKey::PREFIX) {
2019-10-05 14:08:03 +00:00
input.parse().map(Self::ExtXKey)
2019-10-03 14:23:27 +00:00
} else if input.starts_with(tags::ExtXMap::PREFIX) {
2019-10-05 14:08:03 +00:00
input.parse().map(Self::ExtXMap)
2019-10-03 14:23:27 +00:00
} else if input.starts_with(tags::ExtXProgramDateTime::PREFIX) {
2019-10-05 14:08:03 +00:00
input.parse().map(Self::ExtXProgramDateTime)
2019-10-03 14:23:27 +00:00
} else if input.starts_with(tags::ExtXTargetDuration::PREFIX) {
2019-10-05 14:08:03 +00:00
input.parse().map(Self::ExtXTargetDuration)
2019-10-03 14:23:27 +00:00
} else if input.starts_with(tags::ExtXDateRange::PREFIX) {
2019-10-05 14:08:03 +00:00
input.parse().map(Self::ExtXDateRange)
2019-10-03 14:23:27 +00:00
} else if input.starts_with(tags::ExtXMediaSequence::PREFIX) {
2019-10-05 14:08:03 +00:00
input.parse().map(Self::ExtXMediaSequence)
2019-10-03 14:23:27 +00:00
} else if input.starts_with(tags::ExtXDiscontinuitySequence::PREFIX) {
2019-10-05 14:08:03 +00:00
input.parse().map(Self::ExtXDiscontinuitySequence)
2019-10-03 14:23:27 +00:00
} else if input.starts_with(tags::ExtXEndList::PREFIX) {
2019-10-05 14:08:03 +00:00
input.parse().map(Self::ExtXEndList)
2019-10-03 14:23:27 +00:00
} else if input.starts_with(tags::ExtXPlaylistType::PREFIX) {
2019-10-05 14:08:03 +00:00
input.parse().map(Self::ExtXPlaylistType)
2019-10-03 14:23:27 +00:00
} else if input.starts_with(tags::ExtXIFramesOnly::PREFIX) {
2019-10-05 14:08:03 +00:00
input.parse().map(Self::ExtXIFramesOnly)
2019-10-03 14:23:27 +00:00
} else if input.starts_with(tags::ExtXMedia::PREFIX) {
2019-10-05 14:08:03 +00:00
input.parse().map(Self::ExtXMedia).map_err(Error::custom)
2019-10-03 14:23:27 +00:00
} else if input.starts_with(tags::ExtXStreamInf::PREFIX) {
2019-10-05 14:08:03 +00:00
input.parse().map(Self::ExtXStreamInf)
2019-10-03 14:23:27 +00:00
} else if input.starts_with(tags::ExtXIFrameStreamInf::PREFIX) {
2019-10-05 14:08:03 +00:00
input.parse().map(Self::ExtXIFrameStreamInf)
2019-10-03 14:23:27 +00:00
} else if input.starts_with(tags::ExtXSessionData::PREFIX) {
2019-10-05 14:08:03 +00:00
input.parse().map(Self::ExtXSessionData)
2019-10-03 14:23:27 +00:00
} else if input.starts_with(tags::ExtXSessionKey::PREFIX) {
2019-10-05 14:08:03 +00:00
input.parse().map(Self::ExtXSessionKey)
2019-10-03 14:23:27 +00:00
} else if input.starts_with(tags::ExtXIndependentSegments::PREFIX) {
2019-10-05 14:08:03 +00:00
input.parse().map(Self::ExtXIndependentSegments)
2019-10-03 14:23:27 +00:00
} else if input.starts_with(tags::ExtXStart::PREFIX) {
2019-10-05 14:08:03 +00:00
input.parse().map(Self::ExtXStart)
2018-02-14 15:50:57 +00:00
} else {
2020-02-06 11:27:48 +00:00
Ok(Self::Unknown(input))
2018-02-14 15:50:57 +00:00
}
}
}