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

Merge pull request #60 from Luro02/master

Fix issue #59 related to parsing the #EXT-X-DISCONTINUITY-SEQUENCE tag
This commit is contained in:
Lucas 2020-08-11 10:38:33 +02:00 committed by GitHub
commit c343858860
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 52 additions and 11 deletions

View file

@ -176,6 +176,10 @@ impl Error {
}) })
} }
pub(crate) fn unexpected_data(value: &str) -> Self {
Self::custom(format!("Unexpected data in the line: {:?}", value))
}
// third party crates: // third party crates:
#[cfg(feature = "chrono")] #[cfg(feature = "chrono")]
pub(crate) fn chrono(source: chrono::format::ParseError) -> Self { pub(crate) fn chrono(source: chrono::format::ParseError) -> Self {

View file

@ -92,6 +92,8 @@ impl<'a> TryFrom<&'a str> for Tag<'a> {
TryFrom::try_from(input).map(Self::ExtInf) TryFrom::try_from(input).map(Self::ExtInf)
} else if input.starts_with(tags::ExtXByteRange::PREFIX) { } else if input.starts_with(tags::ExtXByteRange::PREFIX) {
TryFrom::try_from(input).map(Self::ExtXByteRange) TryFrom::try_from(input).map(Self::ExtXByteRange)
} else if input.starts_with(tags::ExtXDiscontinuitySequence::PREFIX) {
TryFrom::try_from(input).map(Self::ExtXDiscontinuitySequence)
} else if input.starts_with(tags::ExtXDiscontinuity::PREFIX) { } else if input.starts_with(tags::ExtXDiscontinuity::PREFIX) {
TryFrom::try_from(input).map(Self::ExtXDiscontinuity) TryFrom::try_from(input).map(Self::ExtXDiscontinuity)
} else if input.starts_with(tags::ExtXKey::PREFIX) { } else if input.starts_with(tags::ExtXKey::PREFIX) {
@ -106,8 +108,6 @@ impl<'a> TryFrom<&'a str> for Tag<'a> {
TryFrom::try_from(input).map(Self::ExtXDateRange) TryFrom::try_from(input).map(Self::ExtXDateRange)
} else if input.starts_with(tags::ExtXMediaSequence::PREFIX) { } else if input.starts_with(tags::ExtXMediaSequence::PREFIX) {
TryFrom::try_from(input).map(Self::ExtXMediaSequence) TryFrom::try_from(input).map(Self::ExtXMediaSequence)
} else if input.starts_with(tags::ExtXDiscontinuitySequence::PREFIX) {
TryFrom::try_from(input).map(Self::ExtXDiscontinuitySequence)
} else if input.starts_with(tags::ExtXEndList::PREFIX) { } else if input.starts_with(tags::ExtXEndList::PREFIX) {
TryFrom::try_from(input).map(Self::ExtXEndList) TryFrom::try_from(input).map(Self::ExtXEndList)
} else if input.starts_with(PlaylistType::PREFIX) { } else if input.starts_with(PlaylistType::PREFIX) {

View file

@ -659,12 +659,16 @@ fn parse_media_playlist<'a>(
builder.media_sequence(t.0); builder.media_sequence(t.0);
} }
Tag::ExtXDiscontinuitySequence(t) => { Tag::ExtXDiscontinuitySequence(t) => {
if segments.is_empty() { // this tag must appear before the first MediaSegment in the playlist
return Err(Error::invalid_input()); // https://tools.ietf.org/html/rfc8216#section-4.3.3.3
if !segments.is_empty() {
return Err(Error::custom("discontinuity sequence tag must appear before the first media segment in the playlist"));
} }
// this tag must appear before any ExtXDiscontinuity tag
// https://tools.ietf.org/html/rfc8216#section-4.3.3.3
if has_discontinuity_tag { if has_discontinuity_tag {
return Err(Error::invalid_input()); return Err(Error::custom("discontinuity sequence tag must appear before any `ExtXDiscontinuity` tag"));
} }
builder.discontinuity_sequence(t.0); builder.discontinuity_sequence(t.0);

View file

@ -2,7 +2,6 @@ use std::convert::TryFrom;
use std::fmt; use std::fmt;
use crate::types::ProtocolVersion; use crate::types::ProtocolVersion;
use crate::utils::tag;
use crate::{Error, RequiredVersion}; use crate::{Error, RequiredVersion};
/// The `ExtXDiscontinuity` tag indicates a discontinuity between the /// The `ExtXDiscontinuity` tag indicates a discontinuity between the
@ -27,8 +26,13 @@ impl TryFrom<&str> for ExtXDiscontinuity {
type Error = Error; type Error = Error;
fn try_from(input: &str) -> Result<Self, Self::Error> { fn try_from(input: &str) -> Result<Self, Self::Error> {
tag(input, Self::PREFIX)?; // the parser assumes that only a single line is passed as input,
Ok(Self) // which should be "#EXT-X-DISCONTINUITY"
if input == Self::PREFIX {
Ok(Self)
} else {
Err(Error::unexpected_data(input))
}
} }
} }
@ -50,7 +54,9 @@ mod test {
assert_eq!( assert_eq!(
ExtXDiscontinuity, ExtXDiscontinuity,
ExtXDiscontinuity::try_from("#EXT-X-DISCONTINUITY").unwrap() ExtXDiscontinuity::try_from("#EXT-X-DISCONTINUITY").unwrap()
) );
assert!(ExtXDiscontinuity::try_from("#EXT-X-DISCONTINUITY:0").is_err());
} }
#[test] #[test]

View file

@ -1,6 +1,6 @@
// The relevant issue: // The relevant issue:
// https://github.com/sile/hls_m3u8/issues/55 // https://github.com/sile/hls_m3u8/issues/55
use std::str::FromStr; use std::convert::TryFrom;
use hls_m3u8::tags::{ExtXMedia, VariantStream}; use hls_m3u8::tags::{ExtXMedia, VariantStream};
use hls_m3u8::types::{MediaType, StreamData, UFloat}; use hls_m3u8::types::{MediaType, StreamData, UFloat};
@ -13,7 +13,7 @@ fn parse() {
let file = include_str!("assets/issue_00055.m3u8"); let file = include_str!("assets/issue_00055.m3u8");
assert_eq!( assert_eq!(
MasterPlaylist::from_str(file).unwrap(), MasterPlaylist::try_from(file).unwrap(),
MasterPlaylist::builder() MasterPlaylist::builder()
.has_independent_segments(true) .has_independent_segments(true)
.media(vec![ .media(vec![

View file

@ -0,0 +1,27 @@
// The relevant issue:
// https://github.com/sile/hls_m3u8/issues/59
use std::convert::TryFrom;
use hls_m3u8::MediaPlaylist;
use pretty_assertions::assert_eq;
#[test]
fn parse() {
let playlist = concat!(
"#EXTM3U\n",
"#EXT-X-DISCONTINUITY-SEQUENCE:1\n",
"#EXT-X-TARGETDURATION:10\n",
"#EXT-X-VERSION:3\n",
"#EXTINF:9.009,\n",
"http://media.example.com/first.ts\n",
"#EXTINF:9.009,\n",
"http://media.example.com/second.ts\n",
"#EXTINF:3.003,\n",
"http://media.example.com/third.ts\n",
"#EXT-X-ENDLIST"
);
let playlist = MediaPlaylist::try_from(playlist).unwrap();
assert_eq!(playlist.discontinuity_sequence, 1);
}