mirror of
https://github.com/rutgersc/m3u8-rs.git
synced 2025-01-03 03:38:40 +00:00
Allow unknown tags at the master playlist level
This commit is contained in:
parent
c1ff2b3730
commit
dc352301a3
3 changed files with 53 additions and 5 deletions
|
@ -276,6 +276,7 @@ pub enum MasterPlaylistTag {
|
|||
IndependentSegments,
|
||||
Comment(String),
|
||||
Uri(String),
|
||||
Unknown(ExtTag),
|
||||
}
|
||||
|
||||
pub fn master_playlist_tag(input: &[u8]) -> IResult<&[u8], MasterPlaylistTag> {
|
||||
|
@ -291,6 +292,8 @@ pub fn master_playlist_tag(input: &[u8]) -> IResult<&[u8], MasterPlaylistTag> {
|
|||
| map!(start_tag, MasterPlaylistTag::Start)
|
||||
| map!(tag!("#EXT-X-INDEPENDENT-SEGMENTS"), |_| MasterPlaylistTag::IndependentSegments)
|
||||
|
||||
| map!(ext_tag, MasterPlaylistTag::Unknown)
|
||||
|
||||
| map!(comment_tag, MasterPlaylistTag::Comment)
|
||||
|
||||
| map!(consume_line, MasterPlaylistTag::Uri)
|
||||
|
@ -328,6 +331,9 @@ pub fn master_playlist_from_tags(mut tags: Vec<MasterPlaylistTag>) -> MasterPlay
|
|||
MasterPlaylistTag::IndependentSegments => {
|
||||
master_playlist.independent_segments = true;
|
||||
}
|
||||
MasterPlaylistTag::Unknown(unknown) => {
|
||||
master_playlist.unknown_tags.push(unknown);
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ use std::collections::HashMap;
|
|||
use std::str::FromStr;
|
||||
use std::fmt;
|
||||
use std::f32;
|
||||
use std::fmt::Display;
|
||||
|
||||
macro_rules! write_some_attribute_quoted {
|
||||
($w:expr, $tag:expr, $o:expr) => (
|
||||
|
@ -69,6 +70,7 @@ pub struct MasterPlaylist {
|
|||
pub start: Option<Start>,
|
||||
pub independent_segments: bool,
|
||||
pub alternatives: Vec<AlternativeMedia>, // EXT-X-MEDIA tags
|
||||
pub unknown_tags: Vec<ExtTag>,
|
||||
}
|
||||
|
||||
impl MasterPlaylist {
|
||||
|
@ -100,6 +102,9 @@ impl MasterPlaylist {
|
|||
if self.independent_segments {
|
||||
writeln!(w, "#EXT-X-INDEPENDENT-SEGMENTS")?;
|
||||
}
|
||||
for unknown_tag in &self.unknown_tags {
|
||||
writeln!(w, "{}", unknown_tag)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -528,11 +533,7 @@ impl MediaSegment {
|
|||
writeln!(w, "#EXT-X-DATERANGE:{}", v)?;
|
||||
}
|
||||
for unknown_tag in &self.unknown_tags {
|
||||
write!(w, "#EXT-{}", unknown_tag.tag)?;
|
||||
if let Some(v) = &unknown_tag.rest {
|
||||
writeln!(w, ":{}", v)?;
|
||||
}
|
||||
write!(w, "\n")?;
|
||||
writeln!(w, "{}", unknown_tag)?;
|
||||
}
|
||||
|
||||
write!(w, "#EXTINF:{},", self.duration)?;
|
||||
|
@ -692,3 +693,43 @@ pub struct ExtTag {
|
|||
pub rest: Option<String>,
|
||||
}
|
||||
|
||||
impl Display for ExtTag {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "#EXT-{}", self.tag)?;
|
||||
if let Some(v) = &self.rest {
|
||||
write!(f, ":{}", v)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn ext_tag_with_value_is_printable() {
|
||||
let cue_out_tag = ExtTag {
|
||||
tag: "X-CUE-OUT".into(),
|
||||
rest: Some("DURATION=30".into()),
|
||||
};
|
||||
|
||||
let mut output = Vec::new();
|
||||
write!(output, "{}", cue_out_tag);
|
||||
|
||||
assert_eq!(std::str::from_utf8(output.as_slice()).unwrap(), "#EXT-X-CUE-OUT:DURATION=30")
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ext_tag_without_value_is_printable() {
|
||||
let cue_in_tag = ExtTag {
|
||||
tag: "X-CUE-IN".into(),
|
||||
rest: None,
|
||||
};
|
||||
|
||||
let mut output = Vec::new();
|
||||
write!(output, "{}", cue_in_tag);
|
||||
|
||||
assert_eq!(std::str::from_utf8(output.as_slice()).unwrap(), "#EXT-X-CUE-IN")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -390,6 +390,7 @@ fn create_and_parse_master_playlist_full() {
|
|||
precise: Some("YES".into()),
|
||||
}),
|
||||
independent_segments: true,
|
||||
unknown_tags: vec![],
|
||||
});
|
||||
let playlist_parsed = print_create_and_parse_playlist(&mut playlist_original);
|
||||
assert_eq!(playlist_original, playlist_parsed);
|
||||
|
|
Loading…
Reference in a new issue