mirror of
https://github.com/sile/hls_m3u8.git
synced 2024-11-22 15:21:01 +00:00
added RequiredVersion trait
This commit is contained in:
parent
b2c9f2db36
commit
81f9a421fe
28 changed files with 550 additions and 293 deletions
|
@ -61,10 +61,10 @@ impl FromStr for AttributePairs {
|
||||||
let key = pair[0].to_uppercase();
|
let key = pair[0].to_uppercase();
|
||||||
let value = pair[1].to_string();
|
let value = pair[1].to_string();
|
||||||
|
|
||||||
result.insert(key.to_string(), value.to_string());
|
result.insert(key.trim().to_string(), value.trim().to_string());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)] // this is very useful, when a test fails!
|
||||||
dbg!(&result);
|
dbg!(&result);
|
||||||
Ok(result)
|
Ok(result)
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@ use crate::tags::{
|
||||||
ExtM3u, ExtXIFrameStreamInf, ExtXIndependentSegments, ExtXMedia, ExtXSessionData,
|
ExtM3u, ExtXIFrameStreamInf, ExtXIndependentSegments, ExtXMedia, ExtXSessionData,
|
||||||
ExtXSessionKey, ExtXStart, ExtXStreamInf, ExtXVersion,
|
ExtXSessionKey, ExtXStart, ExtXStreamInf, ExtXVersion,
|
||||||
};
|
};
|
||||||
use crate::types::{ClosedCaptions, MediaType, ProtocolVersion};
|
use crate::types::{ClosedCaptions, MediaType, ProtocolVersion, RequiredVersion};
|
||||||
use crate::Error;
|
use crate::Error;
|
||||||
|
|
||||||
/// Master playlist.
|
/// Master playlist.
|
||||||
|
@ -92,6 +92,12 @@ impl MasterPlaylist {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl RequiredVersion for MasterPlaylist {
|
||||||
|
fn required_version(&self) -> ProtocolVersion {
|
||||||
|
self.version_tag.version()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl MasterPlaylistBuilder {
|
impl MasterPlaylistBuilder {
|
||||||
fn validate(&self) -> Result<(), String> {
|
fn validate(&self) -> Result<(), String> {
|
||||||
let required_version = self.required_version();
|
let required_version = self.required_version();
|
||||||
|
@ -118,43 +124,43 @@ impl MasterPlaylistBuilder {
|
||||||
.chain(
|
.chain(
|
||||||
self.independent_segments_tag
|
self.independent_segments_tag
|
||||||
.iter()
|
.iter()
|
||||||
.map(|t| t.iter().map(|t| t.requires_version()))
|
.map(|t| t.iter().map(|t| t.required_version()))
|
||||||
.flatten(),
|
.flatten(),
|
||||||
)
|
)
|
||||||
.chain(
|
.chain(
|
||||||
self.start_tag
|
self.start_tag
|
||||||
.iter()
|
.iter()
|
||||||
.map(|t| t.iter().map(|t| t.requires_version()))
|
.map(|t| t.iter().map(|t| t.required_version()))
|
||||||
.flatten(),
|
.flatten(),
|
||||||
)
|
)
|
||||||
.chain(
|
.chain(
|
||||||
self.media_tags
|
self.media_tags
|
||||||
.iter()
|
.iter()
|
||||||
.map(|t| t.iter().map(|t| t.requires_version()))
|
.map(|t| t.iter().map(|t| t.required_version()))
|
||||||
.flatten(),
|
.flatten(),
|
||||||
)
|
)
|
||||||
.chain(
|
.chain(
|
||||||
self.stream_inf_tags
|
self.stream_inf_tags
|
||||||
.iter()
|
.iter()
|
||||||
.map(|t| t.iter().map(|t| t.requires_version()))
|
.map(|t| t.iter().map(|t| t.required_version()))
|
||||||
.flatten(),
|
.flatten(),
|
||||||
)
|
)
|
||||||
.chain(
|
.chain(
|
||||||
self.i_frame_stream_inf_tags
|
self.i_frame_stream_inf_tags
|
||||||
.iter()
|
.iter()
|
||||||
.map(|t| t.iter().map(|t| t.requires_version()))
|
.map(|t| t.iter().map(|t| t.required_version()))
|
||||||
.flatten(),
|
.flatten(),
|
||||||
)
|
)
|
||||||
.chain(
|
.chain(
|
||||||
self.session_data_tags
|
self.session_data_tags
|
||||||
.iter()
|
.iter()
|
||||||
.map(|t| t.iter().map(|t| t.requires_version()))
|
.map(|t| t.iter().map(|t| t.required_version()))
|
||||||
.flatten(),
|
.flatten(),
|
||||||
)
|
)
|
||||||
.chain(
|
.chain(
|
||||||
self.session_key_tags
|
self.session_key_tags
|
||||||
.iter()
|
.iter()
|
||||||
.map(|t| t.iter().map(|t| t.requires_version()))
|
.map(|t| t.iter().map(|t| t.required_version()))
|
||||||
.flatten(),
|
.flatten(),
|
||||||
)
|
)
|
||||||
.max()
|
.max()
|
||||||
|
|
|
@ -11,7 +11,7 @@ use crate::tags::{
|
||||||
ExtM3u, ExtXDiscontinuitySequence, ExtXEndList, ExtXIFramesOnly, ExtXIndependentSegments,
|
ExtM3u, ExtXDiscontinuitySequence, ExtXEndList, ExtXIFramesOnly, ExtXIndependentSegments,
|
||||||
ExtXMediaSequence, ExtXPlaylistType, ExtXStart, ExtXTargetDuration, ExtXVersion,
|
ExtXMediaSequence, ExtXPlaylistType, ExtXStart, ExtXTargetDuration, ExtXVersion,
|
||||||
};
|
};
|
||||||
use crate::types::ProtocolVersion;
|
use crate::types::{ProtocolVersion, RequiredVersion};
|
||||||
use crate::Error;
|
use crate::Error;
|
||||||
|
|
||||||
/// Media playlist.
|
/// Media playlist.
|
||||||
|
@ -142,60 +142,60 @@ impl MediaPlaylistBuilder {
|
||||||
.chain(
|
.chain(
|
||||||
self.target_duration_tag
|
self.target_duration_tag
|
||||||
.iter()
|
.iter()
|
||||||
.map(|t| t.requires_version()),
|
.map(|t| t.required_version()),
|
||||||
)
|
)
|
||||||
.chain(self.media_sequence_tag.iter().map(|t| {
|
.chain(self.media_sequence_tag.iter().map(|t| {
|
||||||
if let Some(p) = t {
|
if let Some(p) = t {
|
||||||
p.requires_version()
|
p.required_version()
|
||||||
} else {
|
} else {
|
||||||
ProtocolVersion::V1
|
ProtocolVersion::V1
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
.chain(self.discontinuity_sequence_tag.iter().map(|t| {
|
.chain(self.discontinuity_sequence_tag.iter().map(|t| {
|
||||||
if let Some(p) = t {
|
if let Some(p) = t {
|
||||||
p.requires_version()
|
p.required_version()
|
||||||
} else {
|
} else {
|
||||||
ProtocolVersion::V1
|
ProtocolVersion::V1
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
.chain(self.playlist_type_tag.iter().map(|t| {
|
.chain(self.playlist_type_tag.iter().map(|t| {
|
||||||
if let Some(p) = t {
|
if let Some(p) = t {
|
||||||
p.requires_version()
|
p.required_version()
|
||||||
} else {
|
} else {
|
||||||
ProtocolVersion::V1
|
ProtocolVersion::V1
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
.chain(self.i_frames_only_tag.iter().map(|t| {
|
.chain(self.i_frames_only_tag.iter().map(|t| {
|
||||||
if let Some(p) = t {
|
if let Some(p) = t {
|
||||||
p.requires_version()
|
p.required_version()
|
||||||
} else {
|
} else {
|
||||||
ProtocolVersion::V1
|
ProtocolVersion::V1
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
.chain(self.independent_segments_tag.iter().map(|t| {
|
.chain(self.independent_segments_tag.iter().map(|t| {
|
||||||
if let Some(p) = t {
|
if let Some(p) = t {
|
||||||
p.requires_version()
|
p.required_version()
|
||||||
} else {
|
} else {
|
||||||
ProtocolVersion::V1
|
ProtocolVersion::V1
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
.chain(self.start_tag.iter().map(|t| {
|
.chain(self.start_tag.iter().map(|t| {
|
||||||
if let Some(p) = t {
|
if let Some(p) = t {
|
||||||
p.requires_version()
|
p.required_version()
|
||||||
} else {
|
} else {
|
||||||
ProtocolVersion::V1
|
ProtocolVersion::V1
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
.chain(self.end_list_tag.iter().map(|t| {
|
.chain(self.end_list_tag.iter().map(|t| {
|
||||||
if let Some(p) = t {
|
if let Some(p) = t {
|
||||||
p.requires_version()
|
p.required_version()
|
||||||
} else {
|
} else {
|
||||||
ProtocolVersion::V1
|
ProtocolVersion::V1
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
.chain(self.segments.iter().map(|t| {
|
.chain(self.segments.iter().map(|t| {
|
||||||
t.iter()
|
t.iter()
|
||||||
.map(|s| s.requires_version())
|
.map(|s| s.required_version())
|
||||||
.max()
|
.max()
|
||||||
.unwrap_or(ProtocolVersion::V1)
|
.unwrap_or(ProtocolVersion::V1)
|
||||||
}))
|
}))
|
||||||
|
|
|
@ -6,7 +6,7 @@ use derive_builder::Builder;
|
||||||
use crate::tags::{
|
use crate::tags::{
|
||||||
ExtInf, ExtXByteRange, ExtXDateRange, ExtXDiscontinuity, ExtXKey, ExtXMap, ExtXProgramDateTime,
|
ExtInf, ExtXByteRange, ExtXDateRange, ExtXDiscontinuity, ExtXKey, ExtXMap, ExtXProgramDateTime,
|
||||||
};
|
};
|
||||||
use crate::types::ProtocolVersion;
|
use crate::types::{ProtocolVersion, RequiredVersion};
|
||||||
|
|
||||||
/// Media segment.
|
/// Media segment.
|
||||||
#[derive(Debug, Clone, Builder)]
|
#[derive(Debug, Clone, Builder)]
|
||||||
|
@ -118,21 +118,22 @@ impl MediaSegment {
|
||||||
pub fn key_tags(&self) -> &[ExtXKey] {
|
pub fn key_tags(&self) -> &[ExtXKey] {
|
||||||
&self.key_tags
|
&self.key_tags
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns the protocol compatibility version that this segment requires.
|
impl RequiredVersion for MediaSegment {
|
||||||
pub fn requires_version(&self) -> ProtocolVersion {
|
fn required_version(&self) -> ProtocolVersion {
|
||||||
iter::empty()
|
iter::empty()
|
||||||
.chain(self.key_tags.iter().map(|t| t.requires_version()))
|
.chain(self.key_tags.iter().map(|t| t.required_version()))
|
||||||
.chain(self.map_tag.iter().map(|t| t.requires_version()))
|
.chain(self.map_tag.iter().map(|t| t.required_version()))
|
||||||
.chain(self.byte_range_tag.iter().map(|t| t.requires_version()))
|
.chain(self.byte_range_tag.iter().map(|t| t.required_version()))
|
||||||
.chain(self.date_range_tag.iter().map(|t| t.requires_version()))
|
.chain(self.date_range_tag.iter().map(|t| t.required_version()))
|
||||||
.chain(self.discontinuity_tag.iter().map(|t| t.requires_version()))
|
.chain(self.discontinuity_tag.iter().map(|t| t.required_version()))
|
||||||
.chain(
|
.chain(
|
||||||
self.program_date_time_tag
|
self.program_date_time_tag
|
||||||
.iter()
|
.iter()
|
||||||
.map(|t| t.requires_version()),
|
.map(|t| t.required_version()),
|
||||||
)
|
)
|
||||||
.chain(iter::once(self.inf_tag.requires_version()))
|
.chain(iter::once(self.inf_tag.required_version()))
|
||||||
.max()
|
.max()
|
||||||
.unwrap_or(ProtocolVersion::V7)
|
.unwrap_or(ProtocolVersion::V7)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
use crate::types::ProtocolVersion;
|
use crate::types::{ProtocolVersion, RequiredVersion};
|
||||||
use crate::utils::tag;
|
use crate::utils::tag;
|
||||||
use crate::Error;
|
use crate::Error;
|
||||||
|
|
||||||
|
@ -13,9 +13,10 @@ pub struct ExtM3u;
|
||||||
|
|
||||||
impl ExtM3u {
|
impl ExtM3u {
|
||||||
pub(crate) const PREFIX: &'static str = "#EXTM3U";
|
pub(crate) const PREFIX: &'static str = "#EXTM3U";
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns the protocol compatibility version that this tag requires.
|
impl RequiredVersion for ExtM3u {
|
||||||
pub const fn requires_version(&self) -> ProtocolVersion {
|
fn required_version(&self) -> ProtocolVersion {
|
||||||
ProtocolVersion::V1
|
ProtocolVersion::V1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -50,7 +51,7 @@ mod test {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_requires_version() {
|
fn test_required_version() {
|
||||||
assert_eq!(ExtM3u.requires_version(), ProtocolVersion::V1);
|
assert_eq!(ExtM3u.required_version(), ProtocolVersion::V1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
use crate::types::ProtocolVersion;
|
use crate::types::{ProtocolVersion, RequiredVersion};
|
||||||
use crate::utils::tag;
|
use crate::utils::tag;
|
||||||
use crate::Error;
|
use crate::Error;
|
||||||
|
|
||||||
|
@ -20,12 +20,24 @@ impl ExtXVersion {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the protocol compatibility version of the playlist containing this tag.
|
/// Returns the protocol compatibility version of the playlist containing this tag.
|
||||||
|
///
|
||||||
|
/// # Example
|
||||||
|
/// ```
|
||||||
|
/// # use hls_m3u8::tags::ExtXVersion;
|
||||||
|
/// use hls_m3u8::types::ProtocolVersion;
|
||||||
|
///
|
||||||
|
/// assert_eq!(
|
||||||
|
/// ExtXVersion::new(ProtocolVersion::V6).version(),
|
||||||
|
/// ProtocolVersion::V6
|
||||||
|
/// );
|
||||||
|
/// ```
|
||||||
pub const fn version(&self) -> ProtocolVersion {
|
pub const fn version(&self) -> ProtocolVersion {
|
||||||
self.0
|
self.0
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns the protocol compatibility version that this tag requires.
|
impl RequiredVersion for ExtXVersion {
|
||||||
pub const fn requires_version(&self) -> ProtocolVersion {
|
fn required_version(&self) -> ProtocolVersion {
|
||||||
ProtocolVersion::V1
|
ProtocolVersion::V1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -78,18 +90,10 @@ mod test {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_requires_version() {
|
fn test_required_version() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
ExtXVersion::new(ProtocolVersion::V6).requires_version(),
|
ExtXVersion::new(ProtocolVersion::V6).required_version(),
|
||||||
ProtocolVersion::V1
|
ProtocolVersion::V1
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_version() {
|
|
||||||
assert_eq!(
|
|
||||||
ExtXVersion::new(ProtocolVersion::V6).version(),
|
|
||||||
ProtocolVersion::V6
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,12 +3,23 @@ use std::ops::{Deref, DerefMut};
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
use crate::attribute::AttributePairs;
|
use crate::attribute::AttributePairs;
|
||||||
use crate::types::{ProtocolVersion, StreamInf};
|
use crate::types::{ProtocolVersion, RequiredVersion, StreamInf};
|
||||||
use crate::utils::{quote, tag, unquote};
|
use crate::utils::{quote, tag, unquote};
|
||||||
use crate::Error;
|
use crate::Error;
|
||||||
|
|
||||||
/// [4.3.4.3. EXT-X-I-FRAME-STREAM-INF]
|
/// # [4.3.4.3. EXT-X-I-FRAME-STREAM-INF]
|
||||||
|
/// The [ExtXIFrameStreamInf] tag identifies a [Media Playlist] file
|
||||||
|
/// containing the I-frames of a multimedia presentation. It stands
|
||||||
|
/// alone, in that it does not apply to a particular URI in the [Master Playlist].
|
||||||
///
|
///
|
||||||
|
/// Its format is:
|
||||||
|
///
|
||||||
|
/// ```text
|
||||||
|
/// #EXT-X-I-FRAME-STREAM-INF:<attribute-list>
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// [Master Playlist]: crate::MasterPlaylist
|
||||||
|
/// [Media Playlist]: crate::MediaPlaylist
|
||||||
/// [4.3.4.3. EXT-X-I-FRAME-STREAM-INF]: https://tools.ietf.org/html/rfc8216#section-4.3.4.3
|
/// [4.3.4.3. EXT-X-I-FRAME-STREAM-INF]: https://tools.ietf.org/html/rfc8216#section-4.3.4.3
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||||
pub struct ExtXIFrameStreamInf {
|
pub struct ExtXIFrameStreamInf {
|
||||||
|
@ -19,7 +30,7 @@ pub struct ExtXIFrameStreamInf {
|
||||||
impl ExtXIFrameStreamInf {
|
impl ExtXIFrameStreamInf {
|
||||||
pub(crate) const PREFIX: &'static str = "#EXT-X-I-FRAME-STREAM-INF:";
|
pub(crate) const PREFIX: &'static str = "#EXT-X-I-FRAME-STREAM-INF:";
|
||||||
|
|
||||||
/// Makes a new `ExtXIFrameStreamInf` tag.
|
/// Makes a new [ExtXIFrameStreamInf] tag.
|
||||||
pub fn new<T: ToString>(uri: T, bandwidth: u64) -> Self {
|
pub fn new<T: ToString>(uri: T, bandwidth: u64) -> Self {
|
||||||
ExtXIFrameStreamInf {
|
ExtXIFrameStreamInf {
|
||||||
uri: uri.to_string(),
|
uri: uri.to_string(),
|
||||||
|
@ -55,9 +66,10 @@ impl ExtXIFrameStreamInf {
|
||||||
self.uri = value.to_string();
|
self.uri = value.to_string();
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns the protocol compatibility version that this tag requires.
|
impl RequiredVersion for ExtXIFrameStreamInf {
|
||||||
pub const fn requires_version(&self) -> ProtocolVersion {
|
fn required_version(&self) -> ProtocolVersion {
|
||||||
ProtocolVersion::V1
|
ProtocolVersion::V1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -133,9 +145,9 @@ mod test {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_requires_version() {
|
fn test_required_version() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
ExtXIFrameStreamInf::new("foo", 1000).requires_version(),
|
ExtXIFrameStreamInf::new("foo", 1000).required_version(),
|
||||||
ProtocolVersion::V1
|
ProtocolVersion::V1
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@ use std::fmt;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
use crate::attribute::AttributePairs;
|
use crate::attribute::AttributePairs;
|
||||||
use crate::types::{InStreamId, MediaType, ProtocolVersion};
|
use crate::types::{InStreamId, MediaType, ProtocolVersion, RequiredVersion};
|
||||||
use crate::utils::{parse_yes_or_no, quote, tag, unquote};
|
use crate::utils::{parse_yes_or_no, quote, tag, unquote};
|
||||||
use crate::Error;
|
use crate::Error;
|
||||||
|
|
||||||
|
@ -273,9 +273,10 @@ impl ExtXMedia {
|
||||||
pub fn channels(&self) -> Option<&String> {
|
pub fn channels(&self) -> Option<&String> {
|
||||||
self.channels.as_ref()
|
self.channels.as_ref()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns the protocol compatibility version that this tag requires.
|
impl RequiredVersion for ExtXMedia {
|
||||||
pub fn requires_version(&self) -> ProtocolVersion {
|
fn required_version(&self) -> ProtocolVersion {
|
||||||
match self.instream_id {
|
match self.instream_id {
|
||||||
None
|
None
|
||||||
| Some(InStreamId::Cc1)
|
| Some(InStreamId::Cc1)
|
||||||
|
@ -385,11 +386,28 @@ mod test {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn ext_x_media() {
|
fn test_display() {
|
||||||
let tag = ExtXMedia::new(MediaType::Audio, "foo", "bar");
|
assert_eq!(
|
||||||
let text = r#"#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="foo",NAME="bar""#;
|
ExtXMedia::new(MediaType::Audio, "foo", "bar").to_string(),
|
||||||
assert_eq!(text.parse().ok(), Some(tag.clone()));
|
"#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID=\"foo\",NAME=\"bar\"".to_string()
|
||||||
assert_eq!(tag.to_string(), text);
|
)
|
||||||
assert_eq!(tag.requires_version(), ProtocolVersion::V1);
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_parser() {
|
||||||
|
assert_eq!(
|
||||||
|
ExtXMedia::new(MediaType::Audio, "foo", "bar"),
|
||||||
|
"#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID=\"foo\",NAME=\"bar\""
|
||||||
|
.parse()
|
||||||
|
.unwrap()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_required_version() {
|
||||||
|
assert_eq!(
|
||||||
|
ExtXMedia::new(MediaType::Audio, "foo", "bar").required_version(),
|
||||||
|
ProtocolVersion::V1
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@ use std::str::FromStr;
|
||||||
use derive_builder::Builder;
|
use derive_builder::Builder;
|
||||||
|
|
||||||
use crate::attribute::AttributePairs;
|
use crate::attribute::AttributePairs;
|
||||||
use crate::types::ProtocolVersion;
|
use crate::types::{ProtocolVersion, RequiredVersion};
|
||||||
use crate::utils::{quote, tag, unquote};
|
use crate::utils::{quote, tag, unquote};
|
||||||
use crate::Error;
|
use crate::Error;
|
||||||
|
|
||||||
|
@ -243,18 +243,10 @@ impl ExtXSessionData {
|
||||||
self.data = value;
|
self.data = value;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns the protocol compatibility version, that this tag requires.
|
impl RequiredVersion for ExtXSessionData {
|
||||||
///
|
fn required_version(&self) -> ProtocolVersion {
|
||||||
/// # Example
|
|
||||||
/// ```
|
|
||||||
/// # use hls_m3u8::types::ProtocolVersion;
|
|
||||||
/// # use hls_m3u8::tags::{ExtXSessionData, SessionData};
|
|
||||||
/// #
|
|
||||||
/// let tag = ExtXSessionData::new("foo", SessionData::Value("bar".into()));
|
|
||||||
/// assert_eq!(tag.requires_version(), ProtocolVersion::V1);
|
|
||||||
/// ```
|
|
||||||
pub const fn requires_version(&self) -> ProtocolVersion {
|
|
||||||
ProtocolVersion::V1
|
ProtocolVersion::V1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@ use std::fmt;
|
||||||
use std::ops::{Deref, DerefMut};
|
use std::ops::{Deref, DerefMut};
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
use crate::types::{DecryptionKey, EncryptionMethod, ProtocolVersion};
|
use crate::types::{DecryptionKey, EncryptionMethod, ProtocolVersion, RequiredVersion};
|
||||||
use crate::utils::tag;
|
use crate::utils::tag;
|
||||||
use crate::Error;
|
use crate::Error;
|
||||||
|
|
||||||
|
@ -25,24 +25,10 @@ impl ExtXSessionKey {
|
||||||
|
|
||||||
Self(DecryptionKey::new(method, uri))
|
Self(DecryptionKey::new(method, uri))
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns the protocol compatibility version that this tag requires.
|
impl RequiredVersion for ExtXSessionKey {
|
||||||
/// # Example
|
fn required_version(&self) -> ProtocolVersion {
|
||||||
/// ```
|
|
||||||
/// use hls_m3u8::tags::ExtXSessionKey;
|
|
||||||
/// use hls_m3u8::types::{EncryptionMethod, ProtocolVersion};
|
|
||||||
///
|
|
||||||
/// let mut key = ExtXSessionKey::new(
|
|
||||||
/// EncryptionMethod::Aes128,
|
|
||||||
/// "https://www.example.com/"
|
|
||||||
/// );
|
|
||||||
///
|
|
||||||
/// assert_eq!(
|
|
||||||
/// key.requires_version(),
|
|
||||||
/// ProtocolVersion::V1
|
|
||||||
/// );
|
|
||||||
/// ```
|
|
||||||
pub fn requires_version(&self) -> ProtocolVersion {
|
|
||||||
if self.0.key_format.is_some() | self.0.key_format_versions.is_some() {
|
if self.0.key_format.is_some() | self.0.key_format_versions.is_some() {
|
||||||
ProtocolVersion::V5
|
ProtocolVersion::V5
|
||||||
} else if self.0.iv.is_some() {
|
} else if self.0.iv.is_some() {
|
||||||
|
@ -143,4 +129,13 @@ mod test {
|
||||||
key
|
key
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_required_version() {
|
||||||
|
assert_eq!(
|
||||||
|
ExtXSessionKey::new(EncryptionMethod::Aes128, "https://www.example.com/")
|
||||||
|
.required_version(),
|
||||||
|
ProtocolVersion::V1
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,9 @@ use std::ops::{Deref, DerefMut};
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
use crate::attribute::AttributePairs;
|
use crate::attribute::AttributePairs;
|
||||||
use crate::types::{ClosedCaptions, DecimalFloatingPoint, ProtocolVersion, StreamInf};
|
use crate::types::{
|
||||||
|
ClosedCaptions, DecimalFloatingPoint, ProtocolVersion, RequiredVersion, StreamInf,
|
||||||
|
};
|
||||||
use crate::utils::{quote, tag, unquote};
|
use crate::utils::{quote, tag, unquote};
|
||||||
use crate::Error;
|
use crate::Error;
|
||||||
|
|
||||||
|
@ -23,7 +25,9 @@ pub struct ExtXStreamInf {
|
||||||
impl ExtXStreamInf {
|
impl ExtXStreamInf {
|
||||||
pub(crate) const PREFIX: &'static str = "#EXT-X-STREAM-INF:";
|
pub(crate) const PREFIX: &'static str = "#EXT-X-STREAM-INF:";
|
||||||
|
|
||||||
/// Makes a new [ExtXStreamInf] tag.
|
/// Creates a new [ExtXStreamInf] tag.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
/// ```
|
/// ```
|
||||||
/// # use hls_m3u8::tags::ExtXStreamInf;
|
/// # use hls_m3u8::tags::ExtXStreamInf;
|
||||||
/// #
|
/// #
|
||||||
|
@ -40,11 +44,21 @@ impl ExtXStreamInf {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_uri<T: ToString>(&mut self, value: T) -> &mut Self {
|
||||||
|
self.uri = value.to_string();
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns the URI that identifies the associated media playlist.
|
/// Returns the URI that identifies the associated media playlist.
|
||||||
pub const fn uri(&self) -> &String {
|
pub const fn uri(&self) -> &String {
|
||||||
&self.uri
|
&self.uri
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_frame_rate(&mut self, value: Option<f64>) -> &mut Self {
|
||||||
|
self.frame_rate = value.map(|v| v.into());
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns the maximum frame rate for all the video in the variant stream.
|
/// Returns the maximum frame rate for all the video in the variant stream.
|
||||||
pub fn frame_rate(&self) -> Option<f64> {
|
pub fn frame_rate(&self) -> Option<f64> {
|
||||||
self.frame_rate.map_or(None, |v| Some(v.as_f64()))
|
self.frame_rate.map_or(None, |v| Some(v.as_f64()))
|
||||||
|
@ -64,9 +78,10 @@ impl ExtXStreamInf {
|
||||||
pub fn closed_captions(&self) -> Option<&ClosedCaptions> {
|
pub fn closed_captions(&self) -> Option<&ClosedCaptions> {
|
||||||
self.closed_captions.as_ref()
|
self.closed_captions.as_ref()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns the protocol compatibility version that this tag requires.
|
impl RequiredVersion for ExtXStreamInf {
|
||||||
pub const fn requires_version(&self) -> ProtocolVersion {
|
fn required_version(&self) -> ProtocolVersion {
|
||||||
ProtocolVersion::V1
|
ProtocolVersion::V1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -158,10 +173,10 @@ mod test {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_requires_version() {
|
fn test_required_version() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
ProtocolVersion::V1,
|
ProtocolVersion::V1,
|
||||||
ExtXStreamInf::new("http://www.example.com", 1000).requires_version()
|
ExtXStreamInf::new("http://www.example.com", 1000).required_version()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,40 +1,39 @@
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
use crate::types::ProtocolVersion;
|
use crate::types::{ProtocolVersion, RequiredVersion};
|
||||||
use crate::utils::tag;
|
use crate::utils::tag;
|
||||||
|
|
||||||
/// [4.3.3.3. EXT-X-DISCONTINUITY-SEQUENCE]
|
/// [4.3.3.3. EXT-X-DISCONTINUITY-SEQUENCE]
|
||||||
///
|
///
|
||||||
/// [4.3.3.3. EXT-X-DISCONTINUITY-SEQUENCE]: https://tools.ietf.org/html/rfc8216#section-4.3.3.3
|
/// [4.3.3.3. EXT-X-DISCONTINUITY-SEQUENCE]: https://tools.ietf.org/html/rfc8216#section-4.3.3.3
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
|
||||||
pub struct ExtXDiscontinuitySequence {
|
pub struct ExtXDiscontinuitySequence(u64);
|
||||||
seq_num: u64,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ExtXDiscontinuitySequence {
|
impl ExtXDiscontinuitySequence {
|
||||||
pub(crate) const PREFIX: &'static str = "#EXT-X-DISCONTINUITY-SEQUENCE:";
|
pub(crate) const PREFIX: &'static str = "#EXT-X-DISCONTINUITY-SEQUENCE:";
|
||||||
|
|
||||||
/// Makes a new `ExtXDiscontinuitySequence` tag.
|
/// Makes a new `ExtXDiscontinuitySequence` tag.
|
||||||
pub const fn new(seq_num: u64) -> Self {
|
pub const fn new(seq_num: u64) -> Self {
|
||||||
ExtXDiscontinuitySequence { seq_num }
|
Self(seq_num)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the discontinuity sequence number of
|
/// Returns the discontinuity sequence number of
|
||||||
/// the first media segment that appears in the associated playlist.
|
/// the first media segment that appears in the associated playlist.
|
||||||
pub const fn seq_num(self) -> u64 {
|
pub const fn seq_num(&self) -> u64 {
|
||||||
self.seq_num
|
self.0
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns the protocol compatibility version that this tag requires.
|
impl RequiredVersion for ExtXDiscontinuitySequence {
|
||||||
pub const fn requires_version(self) -> ProtocolVersion {
|
fn required_version(&self) -> ProtocolVersion {
|
||||||
ProtocolVersion::V1
|
ProtocolVersion::V1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for ExtXDiscontinuitySequence {
|
impl fmt::Display for ExtXDiscontinuitySequence {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
write!(f, "{}{}", Self::PREFIX, self.seq_num)
|
write!(f, "{}{}", Self::PREFIX, self.0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,7 +41,7 @@ impl FromStr for ExtXDiscontinuitySequence {
|
||||||
type Err = crate::Error;
|
type Err = crate::Error;
|
||||||
|
|
||||||
fn from_str(input: &str) -> Result<Self, Self::Err> {
|
fn from_str(input: &str) -> Result<Self, Self::Err> {
|
||||||
let seq_num = tag(input, Self::PREFIX)?.parse().unwrap(); // TODO!
|
let seq_num = tag(input, Self::PREFIX)?.parse()?;
|
||||||
Ok(Self::new(seq_num))
|
Ok(Self::new(seq_num))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -52,11 +51,26 @@ mod test {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn ext_x_discontinuity_sequence() {
|
fn test_display() {
|
||||||
let tag = ExtXDiscontinuitySequence::new(123);
|
assert_eq!(
|
||||||
let text = "#EXT-X-DISCONTINUITY-SEQUENCE:123";
|
ExtXDiscontinuitySequence::new(123).to_string(),
|
||||||
assert_eq!(text.parse().ok(), Some(tag));
|
"#EXT-X-DISCONTINUITY-SEQUENCE:123".to_string()
|
||||||
assert_eq!(tag.to_string(), text);
|
);
|
||||||
assert_eq!(tag.requires_version(), ProtocolVersion::V1);
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_required_version() {
|
||||||
|
assert_eq!(
|
||||||
|
ExtXDiscontinuitySequence::new(123).required_version(),
|
||||||
|
ProtocolVersion::V1
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_parser() {
|
||||||
|
assert_eq!(
|
||||||
|
ExtXDiscontinuitySequence::new(123),
|
||||||
|
"#EXT-X-DISCONTINUITY-SEQUENCE:123".parse().unwrap()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
use crate::types::ProtocolVersion;
|
use crate::types::{ProtocolVersion, RequiredVersion};
|
||||||
use crate::utils::tag;
|
use crate::utils::tag;
|
||||||
use crate::Error;
|
use crate::Error;
|
||||||
|
|
||||||
|
@ -10,11 +10,13 @@ use crate::Error;
|
||||||
/// [4.3.3.4. EXT-X-ENDLIST]: https://tools.ietf.org/html/rfc8216#section-4.3.3.4
|
/// [4.3.3.4. EXT-X-ENDLIST]: https://tools.ietf.org/html/rfc8216#section-4.3.3.4
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
pub struct ExtXEndList;
|
pub struct ExtXEndList;
|
||||||
|
|
||||||
impl ExtXEndList {
|
impl ExtXEndList {
|
||||||
pub(crate) const PREFIX: &'static str = "#EXT-X-ENDLIST";
|
pub(crate) const PREFIX: &'static str = "#EXT-X-ENDLIST";
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns the protocol compatibility version that this tag requires.
|
impl RequiredVersion for ExtXEndList {
|
||||||
pub const fn requires_version(self) -> ProtocolVersion {
|
fn required_version(&self) -> ProtocolVersion {
|
||||||
ProtocolVersion::V1
|
ProtocolVersion::V1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -39,11 +41,17 @@ mod test {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn ext_x_endlist() {
|
fn test_display() {
|
||||||
let tag = ExtXEndList;
|
assert_eq!(ExtXEndList.to_string(), "#EXT-X-ENDLIST".to_string());
|
||||||
let text = "#EXT-X-ENDLIST";
|
}
|
||||||
assert_eq!(text.parse().ok(), Some(tag));
|
|
||||||
assert_eq!(tag.to_string(), text);
|
#[test]
|
||||||
assert_eq!(tag.requires_version(), ProtocolVersion::V1);
|
fn test_parser() {
|
||||||
|
assert_eq!(ExtXEndList, "#EXT-X-ENDLIST".parse().unwrap());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_required_version() {
|
||||||
|
assert_eq!(ExtXEndList.required_version(), ProtocolVersion::V1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
use crate::types::ProtocolVersion;
|
use crate::types::{ProtocolVersion, RequiredVersion};
|
||||||
use crate::utils::tag;
|
use crate::utils::tag;
|
||||||
use crate::Error;
|
use crate::Error;
|
||||||
|
|
||||||
|
@ -13,9 +13,10 @@ pub struct ExtXIFramesOnly;
|
||||||
|
|
||||||
impl ExtXIFramesOnly {
|
impl ExtXIFramesOnly {
|
||||||
pub(crate) const PREFIX: &'static str = "#EXT-X-I-FRAMES-ONLY";
|
pub(crate) const PREFIX: &'static str = "#EXT-X-I-FRAMES-ONLY";
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns the protocol compatibility version that this tag requires.
|
impl RequiredVersion for ExtXIFramesOnly {
|
||||||
pub const fn requires_version(self) -> ProtocolVersion {
|
fn required_version(&self) -> ProtocolVersion {
|
||||||
ProtocolVersion::V4
|
ProtocolVersion::V4
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -40,11 +41,20 @@ mod test {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn ext_i_frames_only() {
|
fn test_display() {
|
||||||
let tag = ExtXIFramesOnly;
|
assert_eq!(
|
||||||
let text = "#EXT-X-I-FRAMES-ONLY";
|
ExtXIFramesOnly.to_string(),
|
||||||
assert_eq!(text.parse().ok(), Some(tag));
|
"#EXT-X-I-FRAMES-ONLY".to_string(),
|
||||||
assert_eq!(tag.to_string(), text);
|
)
|
||||||
assert_eq!(tag.requires_version(), ProtocolVersion::V4);
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_parser() {
|
||||||
|
assert_eq!(ExtXIFramesOnly, "#EXT-X-I-FRAMES-ONLY".parse().unwrap(),)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_required_version() {
|
||||||
|
assert_eq!(ExtXIFramesOnly.required_version(), ProtocolVersion::V4)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
use crate::types::ProtocolVersion;
|
use crate::types::{ProtocolVersion, RequiredVersion};
|
||||||
use crate::utils::tag;
|
use crate::utils::tag;
|
||||||
use crate::Error;
|
use crate::Error;
|
||||||
|
|
||||||
|
@ -9,32 +9,32 @@ use crate::Error;
|
||||||
///
|
///
|
||||||
/// [4.3.3.2. EXT-X-MEDIA-SEQUENCE]: https://tools.ietf.org/html/rfc8216#section-4.3.3.2
|
/// [4.3.3.2. EXT-X-MEDIA-SEQUENCE]: https://tools.ietf.org/html/rfc8216#section-4.3.3.2
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
pub struct ExtXMediaSequence {
|
pub struct ExtXMediaSequence(u64);
|
||||||
seq_num: u64,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ExtXMediaSequence {
|
impl ExtXMediaSequence {
|
||||||
pub(crate) const PREFIX: &'static str = "#EXT-X-MEDIA-SEQUENCE:";
|
pub(crate) const PREFIX: &'static str = "#EXT-X-MEDIA-SEQUENCE:";
|
||||||
|
|
||||||
/// Makes a new `ExtXMediaSequence` tag.
|
/// Makes a new `ExtXMediaSequence` tag.
|
||||||
pub const fn new(seq_num: u64) -> Self {
|
pub const fn new(seq_num: u64) -> Self {
|
||||||
ExtXMediaSequence { seq_num }
|
Self(seq_num)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the sequence number of the first media segment that appears in the associated playlist.
|
/// Returns the sequence number of the first media segment,
|
||||||
pub const fn seq_num(self) -> u64 {
|
/// that appears in the associated playlist.
|
||||||
self.seq_num
|
pub const fn seq_num(&self) -> u64 {
|
||||||
|
self.0
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns the protocol compatibility version that this tag requires.
|
impl RequiredVersion for ExtXMediaSequence {
|
||||||
pub const fn requires_version(self) -> ProtocolVersion {
|
fn required_version(&self) -> ProtocolVersion {
|
||||||
ProtocolVersion::V1
|
ProtocolVersion::V1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for ExtXMediaSequence {
|
impl fmt::Display for ExtXMediaSequence {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
write!(f, "{}{}", Self::PREFIX, self.seq_num)
|
write!(f, "{}{}", Self::PREFIX, self.0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,7 +43,6 @@ impl FromStr for ExtXMediaSequence {
|
||||||
|
|
||||||
fn from_str(input: &str) -> Result<Self, Self::Err> {
|
fn from_str(input: &str) -> Result<Self, Self::Err> {
|
||||||
let seq_num = tag(input, Self::PREFIX)?.parse()?;
|
let seq_num = tag(input, Self::PREFIX)?.parse()?;
|
||||||
|
|
||||||
Ok(ExtXMediaSequence::new(seq_num))
|
Ok(ExtXMediaSequence::new(seq_num))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -53,11 +52,26 @@ mod test {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn ext_x_media_sequence() {
|
fn test_display() {
|
||||||
let tag = ExtXMediaSequence::new(123);
|
assert_eq!(
|
||||||
let text = "#EXT-X-MEDIA-SEQUENCE:123";
|
ExtXMediaSequence::new(123).to_string(),
|
||||||
assert_eq!(text.parse().ok(), Some(tag));
|
"#EXT-X-MEDIA-SEQUENCE:123".to_string()
|
||||||
assert_eq!(tag.to_string(), text);
|
);
|
||||||
assert_eq!(tag.requires_version(), ProtocolVersion::V1);
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_required_version() {
|
||||||
|
assert_eq!(
|
||||||
|
ExtXMediaSequence::new(123).required_version(),
|
||||||
|
ProtocolVersion::V1
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_parser() {
|
||||||
|
assert_eq!(
|
||||||
|
ExtXMediaSequence::new(123),
|
||||||
|
"#EXT-X-MEDIA-SEQUENCE:123".parse().unwrap()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
use crate::types::ProtocolVersion;
|
use crate::types::{ProtocolVersion, RequiredVersion};
|
||||||
use crate::utils::tag;
|
use crate::utils::tag;
|
||||||
use crate::Error;
|
use crate::Error;
|
||||||
|
|
||||||
|
@ -31,9 +31,10 @@ pub enum ExtXPlaylistType {
|
||||||
|
|
||||||
impl ExtXPlaylistType {
|
impl ExtXPlaylistType {
|
||||||
pub(crate) const PREFIX: &'static str = "#EXT-X-PLAYLIST-TYPE:";
|
pub(crate) const PREFIX: &'static str = "#EXT-X-PLAYLIST-TYPE:";
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns the protocol compatibility version that this tag requires.
|
impl RequiredVersion for ExtXPlaylistType {
|
||||||
pub const fn requires_version(&self) -> ProtocolVersion {
|
fn required_version(&self) -> ProtocolVersion {
|
||||||
ProtocolVersion::V1
|
ProtocolVersion::V1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -99,13 +100,13 @@ mod test {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_requires_version() {
|
fn test_required_version() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
ExtXPlaylistType::Vod.requires_version(),
|
ExtXPlaylistType::Vod.required_version(),
|
||||||
ProtocolVersion::V1
|
ProtocolVersion::V1
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
ExtXPlaylistType::Event.requires_version(),
|
ExtXPlaylistType::Event.required_version(),
|
||||||
ProtocolVersion::V1
|
ProtocolVersion::V1
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@ use std::fmt;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
use crate::types::ProtocolVersion;
|
use crate::types::{ProtocolVersion, RequiredVersion};
|
||||||
use crate::utils::tag;
|
use crate::utils::tag;
|
||||||
use crate::Error;
|
use crate::Error;
|
||||||
|
|
||||||
|
@ -10,9 +10,7 @@ use crate::Error;
|
||||||
///
|
///
|
||||||
/// [4.3.3.1. EXT-X-TARGETDURATION]: https://tools.ietf.org/html/rfc8216#section-4.3.3.1
|
/// [4.3.3.1. EXT-X-TARGETDURATION]: https://tools.ietf.org/html/rfc8216#section-4.3.3.1
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
|
||||||
pub struct ExtXTargetDuration {
|
pub struct ExtXTargetDuration(Duration);
|
||||||
duration: Duration,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ExtXTargetDuration {
|
impl ExtXTargetDuration {
|
||||||
pub(crate) const PREFIX: &'static str = "#EXT-X-TARGETDURATION:";
|
pub(crate) const PREFIX: &'static str = "#EXT-X-TARGETDURATION:";
|
||||||
|
@ -21,24 +19,24 @@ impl ExtXTargetDuration {
|
||||||
///
|
///
|
||||||
/// Note that the nanoseconds part of the `duration` will be discarded.
|
/// Note that the nanoseconds part of the `duration` will be discarded.
|
||||||
pub const fn new(duration: Duration) -> Self {
|
pub const fn new(duration: Duration) -> Self {
|
||||||
let duration = Duration::from_secs(duration.as_secs());
|
Self(Duration::from_secs(duration.as_secs()))
|
||||||
ExtXTargetDuration { duration }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the maximum media segment duration in the associated playlist.
|
/// Returns the maximum media segment duration in the associated playlist.
|
||||||
pub const fn duration(&self) -> Duration {
|
pub const fn duration(&self) -> Duration {
|
||||||
self.duration
|
self.0
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns the protocol compatibility version that this tag requires.
|
impl RequiredVersion for ExtXTargetDuration {
|
||||||
pub const fn requires_version(&self) -> ProtocolVersion {
|
fn required_version(&self) -> ProtocolVersion {
|
||||||
ProtocolVersion::V1
|
ProtocolVersion::V1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for ExtXTargetDuration {
|
impl fmt::Display for ExtXTargetDuration {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
write!(f, "{}{}", Self::PREFIX, self.duration.as_secs())
|
write!(f, "{}{}", Self::PREFIX, self.0.as_secs())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,9 +45,7 @@ impl FromStr for ExtXTargetDuration {
|
||||||
|
|
||||||
fn from_str(input: &str) -> Result<Self, Self::Err> {
|
fn from_str(input: &str) -> Result<Self, Self::Err> {
|
||||||
let input = tag(input, Self::PREFIX)?.parse()?;
|
let input = tag(input, Self::PREFIX)?.parse()?;
|
||||||
Ok(ExtXTargetDuration {
|
Ok(Self::new(Duration::from_secs(input)))
|
||||||
duration: Duration::from_secs(input),
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,11 +54,26 @@ mod test {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn ext_x_targetduration() {
|
fn test_display() {
|
||||||
let tag = ExtXTargetDuration::new(Duration::from_secs(5));
|
assert_eq!(
|
||||||
let text = "#EXT-X-TARGETDURATION:5";
|
ExtXTargetDuration::new(Duration::from_secs(5)).to_string(),
|
||||||
assert_eq!(text.parse().ok(), Some(tag));
|
"#EXT-X-TARGETDURATION:5".to_string()
|
||||||
assert_eq!(tag.to_string(), text);
|
);
|
||||||
assert_eq!(tag.requires_version(), ProtocolVersion::V1);
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_required_version() {
|
||||||
|
assert_eq!(
|
||||||
|
ExtXTargetDuration::new(Duration::from_secs(5)).required_version(),
|
||||||
|
ProtocolVersion::V1
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_parser() {
|
||||||
|
assert_eq!(
|
||||||
|
ExtXTargetDuration::new(Duration::from_secs(5)),
|
||||||
|
"#EXT-X-TARGETDURATION:5".parse().unwrap()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@ use std::fmt;
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
use crate::types::{ByteRange, ProtocolVersion};
|
use crate::types::{ByteRange, ProtocolVersion, RequiredVersion};
|
||||||
use crate::utils::tag;
|
use crate::utils::tag;
|
||||||
use crate::Error;
|
use crate::Error;
|
||||||
|
|
||||||
|
@ -16,6 +16,7 @@ impl ExtXByteRange {
|
||||||
pub(crate) const PREFIX: &'static str = "#EXT-X-BYTERANGE:";
|
pub(crate) const PREFIX: &'static str = "#EXT-X-BYTERANGE:";
|
||||||
|
|
||||||
/// Makes a new `ExtXByteRange` tag.
|
/// Makes a new `ExtXByteRange` tag.
|
||||||
|
///
|
||||||
/// # Example
|
/// # Example
|
||||||
/// ```
|
/// ```
|
||||||
/// use hls_m3u8::tags::ExtXByteRange;
|
/// use hls_m3u8::tags::ExtXByteRange;
|
||||||
|
@ -27,6 +28,7 @@ impl ExtXByteRange {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Converts the [ExtXByteRange] to a [ByteRange].
|
/// Converts the [ExtXByteRange] to a [ByteRange].
|
||||||
|
///
|
||||||
/// # Example
|
/// # Example
|
||||||
/// ```
|
/// ```
|
||||||
/// use hls_m3u8::tags::ExtXByteRange;
|
/// use hls_m3u8::tags::ExtXByteRange;
|
||||||
|
@ -38,17 +40,10 @@ impl ExtXByteRange {
|
||||||
pub const fn to_range(&self) -> ByteRange {
|
pub const fn to_range(&self) -> ByteRange {
|
||||||
self.0
|
self.0
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns the protocol compatibility version that this tag requires.
|
impl RequiredVersion for ExtXByteRange {
|
||||||
/// # Example
|
fn required_version(&self) -> ProtocolVersion {
|
||||||
/// ```
|
|
||||||
/// use hls_m3u8::tags::ExtXByteRange;
|
|
||||||
/// use hls_m3u8::types::ProtocolVersion;
|
|
||||||
///
|
|
||||||
/// let byte_range = ExtXByteRange::new(20, Some(5));
|
|
||||||
/// assert_eq!(byte_range.requires_version(), ProtocolVersion::V4);
|
|
||||||
/// ```
|
|
||||||
pub const fn requires_version(&self) -> ProtocolVersion {
|
|
||||||
ProtocolVersion::V4
|
ProtocolVersion::V4
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -76,6 +71,7 @@ impl FromStr for ExtXByteRange {
|
||||||
let input = tag(input, Self::PREFIX)?;
|
let input = tag(input, Self::PREFIX)?;
|
||||||
|
|
||||||
let tokens = input.splitn(2, '@').collect::<Vec<_>>();
|
let tokens = input.splitn(2, '@').collect::<Vec<_>>();
|
||||||
|
|
||||||
if tokens.is_empty() {
|
if tokens.is_empty() {
|
||||||
return Err(Error::invalid_input());
|
return Err(Error::invalid_input());
|
||||||
}
|
}
|
||||||
|
@ -135,4 +131,12 @@ mod test {
|
||||||
assert_eq!(byte_range.length(), 0);
|
assert_eq!(byte_range.length(), 0);
|
||||||
assert_eq!(byte_range.start(), Some(22));
|
assert_eq!(byte_range.start(), Some(22));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_required_version() {
|
||||||
|
assert_eq!(
|
||||||
|
ExtXByteRange::new(20, Some(5)).required_version(),
|
||||||
|
ProtocolVersion::V4
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@ use std::time::Duration;
|
||||||
use chrono::{DateTime, FixedOffset};
|
use chrono::{DateTime, FixedOffset};
|
||||||
|
|
||||||
use crate::attribute::AttributePairs;
|
use crate::attribute::AttributePairs;
|
||||||
use crate::types::{DecimalFloatingPoint, ProtocolVersion};
|
use crate::types::{DecimalFloatingPoint, ProtocolVersion, RequiredVersion};
|
||||||
use crate::utils::{quote, tag, unquote};
|
use crate::utils::{quote, tag, unquote};
|
||||||
use crate::Error;
|
use crate::Error;
|
||||||
|
|
||||||
|
@ -63,9 +63,10 @@ pub struct ExtXDateRange {
|
||||||
|
|
||||||
impl ExtXDateRange {
|
impl ExtXDateRange {
|
||||||
pub(crate) const PREFIX: &'static str = "#EXT-X-DATERANGE:";
|
pub(crate) const PREFIX: &'static str = "#EXT-X-DATERANGE:";
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns the protocol compatibility version that this tag requires.
|
impl RequiredVersion for ExtXDateRange {
|
||||||
pub const fn requires_version(&self) -> ProtocolVersion {
|
fn required_version(&self) -> ProtocolVersion {
|
||||||
ProtocolVersion::V1
|
ProtocolVersion::V1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
use crate::types::ProtocolVersion;
|
use crate::types::{ProtocolVersion, RequiredVersion};
|
||||||
use crate::utils::tag;
|
use crate::utils::tag;
|
||||||
use crate::{Error, Result};
|
use crate::Error;
|
||||||
|
|
||||||
/// [4.3.2.3. EXT-X-DISCONTINUITY]
|
/// [4.3.2.3. EXT-X-DISCONTINUITY]
|
||||||
///
|
///
|
||||||
|
@ -13,9 +13,10 @@ pub struct ExtXDiscontinuity;
|
||||||
|
|
||||||
impl ExtXDiscontinuity {
|
impl ExtXDiscontinuity {
|
||||||
pub(crate) const PREFIX: &'static str = "#EXT-X-DISCONTINUITY";
|
pub(crate) const PREFIX: &'static str = "#EXT-X-DISCONTINUITY";
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns the protocol compatibility version that this tag requires.
|
impl RequiredVersion for ExtXDiscontinuity {
|
||||||
pub const fn requires_version(self) -> ProtocolVersion {
|
fn required_version(&self) -> ProtocolVersion {
|
||||||
ProtocolVersion::V1
|
ProtocolVersion::V1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -29,7 +30,7 @@ impl fmt::Display for ExtXDiscontinuity {
|
||||||
impl FromStr for ExtXDiscontinuity {
|
impl FromStr for ExtXDiscontinuity {
|
||||||
type Err = Error;
|
type Err = Error;
|
||||||
|
|
||||||
fn from_str(input: &str) -> Result<Self> {
|
fn from_str(input: &str) -> Result<Self, Self::Err> {
|
||||||
tag(input, Self::PREFIX)?;
|
tag(input, Self::PREFIX)?;
|
||||||
Ok(ExtXDiscontinuity)
|
Ok(ExtXDiscontinuity)
|
||||||
}
|
}
|
||||||
|
@ -40,10 +41,20 @@ mod test {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn ext_x_discontinuity() {
|
fn test_display() {
|
||||||
let tag = ExtXDiscontinuity;
|
assert_eq!(
|
||||||
assert_eq!("#EXT-X-DISCONTINUITY".parse().ok(), Some(tag));
|
ExtXDiscontinuity.to_string(),
|
||||||
assert_eq!(tag.to_string(), "#EXT-X-DISCONTINUITY");
|
"#EXT-X-DISCONTINUITY".to_string(),
|
||||||
assert_eq!(tag.requires_version(), ProtocolVersion::V1);
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_parser() {
|
||||||
|
assert_eq!(ExtXDiscontinuity, "#EXT-X-DISCONTINUITY".parse().unwrap(),)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_required_version() {
|
||||||
|
assert_eq!(ExtXDiscontinuity.required_version(), ProtocolVersion::V1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@ use std::fmt;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
use crate::types::{DecimalFloatingPoint, ProtocolVersion};
|
use crate::types::{DecimalFloatingPoint, ProtocolVersion, RequiredVersion};
|
||||||
use crate::utils::tag;
|
use crate::utils::tag;
|
||||||
use crate::Error;
|
use crate::Error;
|
||||||
|
|
||||||
|
@ -78,9 +78,10 @@ impl ExtInf {
|
||||||
pub fn title(&self) -> Option<&String> {
|
pub fn title(&self) -> Option<&String> {
|
||||||
self.title.as_ref()
|
self.title.as_ref()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns the protocol compatibility version that this tag requires.
|
impl RequiredVersion for ExtInf {
|
||||||
pub fn requires_version(&self) -> ProtocolVersion {
|
fn required_version(&self) -> ProtocolVersion {
|
||||||
if self.duration.subsec_nanos() == 0 {
|
if self.duration.subsec_nanos() == 0 {
|
||||||
ProtocolVersion::V1
|
ProtocolVersion::V1
|
||||||
} else {
|
} else {
|
||||||
|
@ -206,13 +207,13 @@ mod test {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_requires_version() {
|
fn test_required_version() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
ExtInf::new(Duration::from_secs(4)).requires_version(),
|
ExtInf::new(Duration::from_secs(4)).required_version(),
|
||||||
ProtocolVersion::V1
|
ProtocolVersion::V1
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
ExtInf::new(Duration::from_millis(4400)).requires_version(),
|
ExtInf::new(Duration::from_millis(4400)).required_version(),
|
||||||
ProtocolVersion::V3
|
ProtocolVersion::V3
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@ use std::fmt;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
use crate::attribute::AttributePairs;
|
use crate::attribute::AttributePairs;
|
||||||
use crate::types::{ByteRange, ProtocolVersion};
|
use crate::types::{ByteRange, ProtocolVersion, RequiredVersion};
|
||||||
use crate::utils::{quote, tag, unquote};
|
use crate::utils::{quote, tag, unquote};
|
||||||
use crate::Error;
|
use crate::Error;
|
||||||
|
|
||||||
|
@ -43,9 +43,10 @@ impl ExtXMap {
|
||||||
pub const fn range(&self) -> Option<ByteRange> {
|
pub const fn range(&self) -> Option<ByteRange> {
|
||||||
self.range
|
self.range
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns the protocol compatibility version that this tag requires.
|
impl RequiredVersion for ExtXMap {
|
||||||
pub const fn requires_version(&self) -> ProtocolVersion {
|
fn required_version(&self) -> ProtocolVersion {
|
||||||
ProtocolVersion::V6
|
ProtocolVersion::V6
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -93,19 +94,37 @@ mod test {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn ext_x_map() {
|
fn test_display() {
|
||||||
let tag = ExtXMap::new("foo");
|
assert_eq!(
|
||||||
let text = r#"#EXT-X-MAP:URI="foo""#;
|
ExtXMap::new("foo").to_string(),
|
||||||
assert_eq!(text.parse().ok(), Some(tag.clone()));
|
"#EXT-X-MAP:URI=\"foo\"".to_string(),
|
||||||
assert_eq!(tag.to_string(), text);
|
);
|
||||||
assert_eq!(tag.requires_version(), ProtocolVersion::V6);
|
|
||||||
|
|
||||||
let tag = ExtXMap::with_range("foo", ByteRange::new(9, Some(2)));
|
assert_eq!(
|
||||||
let text = r#"#EXT-X-MAP:URI="foo",BYTERANGE="9@2""#;
|
ExtXMap::with_range("foo", ByteRange::new(9, Some(2))).to_string(),
|
||||||
ExtXMap::from_str(text).unwrap();
|
"#EXT-X-MAP:URI=\"foo\",BYTERANGE=\"9@2\"".to_string(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
assert_eq!(text.parse().ok(), Some(tag.clone()));
|
#[test]
|
||||||
assert_eq!(tag.to_string(), text);
|
fn test_parser() {
|
||||||
assert_eq!(tag.requires_version(), ProtocolVersion::V6);
|
assert_eq!(
|
||||||
|
ExtXMap::new("foo"),
|
||||||
|
"#EXT-X-MAP:URI=\"foo\"".parse().unwrap()
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
ExtXMap::with_range("foo", ByteRange::new(9, Some(2))),
|
||||||
|
"#EXT-X-MAP:URI=\"foo\",BYTERANGE=\"9@2\"".parse().unwrap()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_required_version() {
|
||||||
|
assert_eq!(ExtXMap::new("foo").required_version(), ProtocolVersion::V6);
|
||||||
|
assert_eq!(
|
||||||
|
ExtXMap::with_range("foo", ByteRange::new(9, Some(2))).required_version(),
|
||||||
|
ProtocolVersion::V6
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@ use std::str::FromStr;
|
||||||
|
|
||||||
use chrono::{DateTime, FixedOffset};
|
use chrono::{DateTime, FixedOffset};
|
||||||
|
|
||||||
use crate::types::ProtocolVersion;
|
use crate::types::{ProtocolVersion, RequiredVersion};
|
||||||
use crate::utils::tag;
|
use crate::utils::tag;
|
||||||
use crate::Error;
|
use crate::Error;
|
||||||
|
|
||||||
|
@ -25,9 +25,10 @@ impl ExtXProgramDateTime {
|
||||||
pub const fn date_time(&self) -> &DateTime<FixedOffset> {
|
pub const fn date_time(&self) -> &DateTime<FixedOffset> {
|
||||||
&self.0
|
&self.0
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns the protocol compatibility version that this tag requires.
|
impl RequiredVersion for ExtXProgramDateTime {
|
||||||
pub const fn requires_version(&self) -> ProtocolVersion {
|
fn required_version(&self) -> ProtocolVersion {
|
||||||
ProtocolVersion::V1
|
ProtocolVersion::V1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -45,7 +46,6 @@ impl FromStr for ExtXProgramDateTime {
|
||||||
fn from_str(input: &str) -> Result<Self, Self::Err> {
|
fn from_str(input: &str) -> Result<Self, Self::Err> {
|
||||||
let input = tag(input, Self::PREFIX)?;
|
let input = tag(input, Self::PREFIX)?;
|
||||||
|
|
||||||
// TODO: parse with chrono
|
|
||||||
let date_time = DateTime::parse_from_rfc3339(input)?;
|
let date_time = DateTime::parse_from_rfc3339(input)?;
|
||||||
Ok(Self::new(date_time))
|
Ok(Self::new(date_time))
|
||||||
}
|
}
|
||||||
|
@ -54,6 +54,9 @@ impl FromStr for ExtXProgramDateTime {
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
use chrono::TimeZone;
|
||||||
|
|
||||||
|
const HOURS_IN_SECS: i32 = 3600; // 1 hour = 3600 seconds
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_display() {
|
fn test_display() {
|
||||||
|
@ -71,19 +74,26 @@ mod test {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_parser() {
|
fn test_parser() {
|
||||||
"#EXT-X-PROGRAM-DATE-TIME:2010-02-19T14:54:23.031+08:00"
|
assert_eq!(
|
||||||
.parse::<ExtXProgramDateTime>()
|
ExtXProgramDateTime::new(
|
||||||
.unwrap();
|
FixedOffset::east(8 * HOURS_IN_SECS)
|
||||||
|
.ymd(2010, 2, 19)
|
||||||
|
.and_hms_milli(14, 54, 23, 31)
|
||||||
|
),
|
||||||
|
"#EXT-X-PROGRAM-DATE-TIME:2010-02-19T14:54:23.031+08:00"
|
||||||
|
.parse::<ExtXProgramDateTime>()
|
||||||
|
.unwrap()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_requires_version() {
|
fn test_required_version() {
|
||||||
let date_time = "2010-02-19T14:54:23.031+08:00"
|
let program_date_time = ExtXProgramDateTime::new(
|
||||||
.parse::<DateTime<FixedOffset>>()
|
FixedOffset::east(8 * HOURS_IN_SECS)
|
||||||
.unwrap();
|
.ymd(2010, 2, 19)
|
||||||
|
.and_hms_milli(14, 54, 23, 31),
|
||||||
|
);
|
||||||
|
|
||||||
let program_date_time = ExtXProgramDateTime::new(date_time);
|
assert_eq!(program_date_time.required_version(), ProtocolVersion::V1);
|
||||||
|
|
||||||
assert_eq!(program_date_time.requires_version(), ProtocolVersion::V1);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
use crate::types::ProtocolVersion;
|
use crate::types::{ProtocolVersion, RequiredVersion};
|
||||||
use crate::utils::tag;
|
use crate::utils::tag;
|
||||||
use crate::Error;
|
use crate::Error;
|
||||||
|
|
||||||
|
@ -10,11 +10,13 @@ use crate::Error;
|
||||||
/// [4.3.5.1. EXT-X-INDEPENDENT-SEGMENTS]: https://tools.ietf.org/html/rfc8216#section-4.3.5.1
|
/// [4.3.5.1. EXT-X-INDEPENDENT-SEGMENTS]: https://tools.ietf.org/html/rfc8216#section-4.3.5.1
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
pub struct ExtXIndependentSegments;
|
pub struct ExtXIndependentSegments;
|
||||||
|
|
||||||
impl ExtXIndependentSegments {
|
impl ExtXIndependentSegments {
|
||||||
pub(crate) const PREFIX: &'static str = "#EXT-X-INDEPENDENT-SEGMENTS";
|
pub(crate) const PREFIX: &'static str = "#EXT-X-INDEPENDENT-SEGMENTS";
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns the protocol compatibility version that this tag requires.
|
impl RequiredVersion for ExtXIndependentSegments {
|
||||||
pub const fn requires_version(&self) -> ProtocolVersion {
|
fn required_version(&self) -> ProtocolVersion {
|
||||||
ProtocolVersion::V1
|
ProtocolVersion::V1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -39,11 +41,26 @@ mod test {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn ext_x_independent_segments() {
|
fn test_display() {
|
||||||
let tag = ExtXIndependentSegments;
|
assert_eq!(
|
||||||
let text = "#EXT-X-INDEPENDENT-SEGMENTS";
|
ExtXIndependentSegments.to_string(),
|
||||||
assert_eq!(text.parse().ok(), Some(tag));
|
"#EXT-X-INDEPENDENT-SEGMENTS".to_string(),
|
||||||
assert_eq!(tag.to_string(), text);
|
)
|
||||||
assert_eq!(tag.requires_version(), ProtocolVersion::V1);
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_parser() {
|
||||||
|
assert_eq!(
|
||||||
|
ExtXIndependentSegments,
|
||||||
|
"#EXT-X-INDEPENDENT-SEGMENTS".parse().unwrap(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_required_version() {
|
||||||
|
assert_eq!(
|
||||||
|
ExtXIndependentSegments.required_version(),
|
||||||
|
ProtocolVersion::V1
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@ use std::fmt;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
use crate::attribute::AttributePairs;
|
use crate::attribute::AttributePairs;
|
||||||
use crate::types::{ProtocolVersion, SignedDecimalFloatingPoint};
|
use crate::types::{ProtocolVersion, RequiredVersion, SignedDecimalFloatingPoint};
|
||||||
use crate::utils::{parse_yes_or_no, tag};
|
use crate::utils::{parse_yes_or_no, tag};
|
||||||
use crate::Error;
|
use crate::Error;
|
||||||
|
|
||||||
|
@ -19,6 +19,7 @@ impl ExtXStart {
|
||||||
pub(crate) const PREFIX: &'static str = "#EXT-X-START:";
|
pub(crate) const PREFIX: &'static str = "#EXT-X-START:";
|
||||||
|
|
||||||
/// Makes a new `ExtXStart` tag.
|
/// Makes a new `ExtXStart` tag.
|
||||||
|
///
|
||||||
/// # Panic
|
/// # Panic
|
||||||
/// Panics if the time_offset value is infinite.
|
/// Panics if the time_offset value is infinite.
|
||||||
pub fn new(time_offset: f64) -> Self {
|
pub fn new(time_offset: f64) -> Self {
|
||||||
|
@ -33,6 +34,7 @@ impl ExtXStart {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Makes a new `ExtXStart` tag with the given `precise` flag.
|
/// Makes a new `ExtXStart` tag with the given `precise` flag.
|
||||||
|
///
|
||||||
/// # Panic
|
/// # Panic
|
||||||
/// Panics if the time_offset value is infinite.
|
/// Panics if the time_offset value is infinite.
|
||||||
pub fn with_precise(time_offset: f64, precise: bool) -> Self {
|
pub fn with_precise(time_offset: f64, precise: bool) -> Self {
|
||||||
|
@ -56,9 +58,10 @@ impl ExtXStart {
|
||||||
pub const fn precise(&self) -> bool {
|
pub const fn precise(&self) -> bool {
|
||||||
self.precise
|
self.precise
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns the protocol compatibility version that this tag requires.
|
impl RequiredVersion for ExtXStart {
|
||||||
pub const fn requires_version(&self) -> ProtocolVersion {
|
fn required_version(&self) -> ProtocolVersion {
|
||||||
ProtocolVersion::V1
|
ProtocolVersion::V1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -108,17 +111,41 @@ mod test {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn ext_x_start() {
|
fn test_display() {
|
||||||
let tag = ExtXStart::new(-1.23);
|
assert_eq!(
|
||||||
let text = "#EXT-X-START:TIME-OFFSET=-1.23";
|
ExtXStart::new(-1.23).to_string(),
|
||||||
assert_eq!(text.parse().ok(), Some(tag));
|
"#EXT-X-START:TIME-OFFSET=-1.23".to_string(),
|
||||||
assert_eq!(tag.to_string(), text);
|
);
|
||||||
assert_eq!(tag.requires_version(), ProtocolVersion::V1);
|
|
||||||
|
|
||||||
let tag = ExtXStart::with_precise(1.23, true);
|
assert_eq!(
|
||||||
let text = "#EXT-X-START:TIME-OFFSET=1.23,PRECISE=YES";
|
ExtXStart::with_precise(1.23, true).to_string(),
|
||||||
assert_eq!(text.parse().ok(), Some(tag));
|
"#EXT-X-START:TIME-OFFSET=1.23,PRECISE=YES".to_string(),
|
||||||
assert_eq!(tag.to_string(), text);
|
);
|
||||||
assert_eq!(tag.requires_version(), ProtocolVersion::V1);
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_required_version() {
|
||||||
|
assert_eq!(
|
||||||
|
ExtXStart::new(-1.23).required_version(),
|
||||||
|
ProtocolVersion::V1,
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
ExtXStart::with_precise(1.23, true).required_version(),
|
||||||
|
ProtocolVersion::V1,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_parser() {
|
||||||
|
assert_eq!(
|
||||||
|
ExtXStart::new(-1.23),
|
||||||
|
"#EXT-X-START:TIME-OFFSET=-1.23".parse().unwrap(),
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
ExtXStart::with_precise(1.23, true),
|
||||||
|
"#EXT-X-START:TIME-OFFSET=1.23,PRECISE=YES".parse().unwrap(),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -70,6 +70,18 @@ impl FromStr for DecimalFloatingPoint {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<f64> for DecimalFloatingPoint {
|
||||||
|
fn from(value: f64) -> Self {
|
||||||
|
Self(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<f32> for DecimalFloatingPoint {
|
||||||
|
fn from(value: f32) -> Self {
|
||||||
|
Self(value.into())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
|
@ -4,7 +4,7 @@ use std::str::FromStr;
|
||||||
use derive_builder::Builder;
|
use derive_builder::Builder;
|
||||||
|
|
||||||
use crate::attribute::AttributePairs;
|
use crate::attribute::AttributePairs;
|
||||||
use crate::types::{EncryptionMethod, InitializationVector, ProtocolVersion};
|
use crate::types::{EncryptionMethod, InitializationVector, ProtocolVersion, RequiredVersion};
|
||||||
use crate::utils::{quote, unquote};
|
use crate::utils::{quote, unquote};
|
||||||
use crate::Error;
|
use crate::Error;
|
||||||
|
|
||||||
|
@ -292,23 +292,10 @@ impl DecryptionKey {
|
||||||
pub fn set_key_format_versions<T: ToString>(&mut self, value: T) {
|
pub fn set_key_format_versions<T: ToString>(&mut self, value: T) {
|
||||||
self.key_format_versions = Some(value.to_string());
|
self.key_format_versions = Some(value.to_string());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns the protocol compatibility version that this tag requires.
|
impl RequiredVersion for DecryptionKey {
|
||||||
/// # Example
|
fn required_version(&self) -> ProtocolVersion {
|
||||||
/// ```
|
|
||||||
/// use hls_m3u8::types::{EncryptionMethod, ProtocolVersion, DecryptionKey};
|
|
||||||
///
|
|
||||||
/// let mut key = DecryptionKey::new(
|
|
||||||
/// EncryptionMethod::Aes128,
|
|
||||||
/// "https://www.example.com/"
|
|
||||||
/// );
|
|
||||||
///
|
|
||||||
/// assert_eq!(
|
|
||||||
/// key.requires_version(),
|
|
||||||
/// ProtocolVersion::V1
|
|
||||||
/// );
|
|
||||||
/// ```
|
|
||||||
pub fn requires_version(&self) -> ProtocolVersion {
|
|
||||||
if self.key_format.is_some() || self.key_format_versions.is_some() {
|
if self.key_format.is_some() || self.key_format_versions.is_some() {
|
||||||
ProtocolVersion::V5
|
ProtocolVersion::V5
|
||||||
} else if self.iv.is_some() {
|
} else if self.iv.is_some() {
|
||||||
|
@ -464,4 +451,13 @@ mod test {
|
||||||
key
|
key
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_required_version() {
|
||||||
|
assert_eq!(
|
||||||
|
DecryptionKey::new(EncryptionMethod::Aes128, "https://www.example.com/")
|
||||||
|
.required_version(),
|
||||||
|
ProtocolVersion::V1
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,30 @@ use std::str::FromStr;
|
||||||
|
|
||||||
use crate::Error;
|
use crate::Error;
|
||||||
|
|
||||||
|
/// # Example
|
||||||
|
/// Implementing it:
|
||||||
|
/// ```
|
||||||
|
/// # use hls_m3u8::types::{ProtocolVersion, RequiredVersion};
|
||||||
|
/// #
|
||||||
|
/// struct NewTag(u64);
|
||||||
|
///
|
||||||
|
/// impl RequiredVersion for NewTag {
|
||||||
|
/// fn required_version(&self) -> ProtocolVersion {
|
||||||
|
/// if self.0 == 5 {
|
||||||
|
/// ProtocolVersion::V4
|
||||||
|
/// } else {
|
||||||
|
/// ProtocolVersion::V1
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
/// assert_eq!(NewTag(5).required_version(), ProtocolVersion::V4);
|
||||||
|
/// assert_eq!(NewTag(2).required_version(), ProtocolVersion::V1);
|
||||||
|
/// ```
|
||||||
|
pub trait RequiredVersion {
|
||||||
|
/// Returns the protocol compatibility version that this tag requires.
|
||||||
|
fn required_version(&self) -> ProtocolVersion;
|
||||||
|
}
|
||||||
|
|
||||||
/// [7. Protocol Version Compatibility]
|
/// [7. Protocol Version Compatibility]
|
||||||
///
|
///
|
||||||
/// [7. Protocol Version Compatibility]: https://tools.ietf.org/html/rfc8216#section-7
|
/// [7. Protocol Version Compatibility]: https://tools.ietf.org/html/rfc8216#section-7
|
||||||
|
@ -29,13 +53,13 @@ impl fmt::Display for ProtocolVersion {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
let n = {
|
let n = {
|
||||||
match &self {
|
match &self {
|
||||||
ProtocolVersion::V1 => 1,
|
Self::V1 => 1,
|
||||||
ProtocolVersion::V2 => 2,
|
Self::V2 => 2,
|
||||||
ProtocolVersion::V3 => 3,
|
Self::V3 => 3,
|
||||||
ProtocolVersion::V4 => 4,
|
Self::V4 => 4,
|
||||||
ProtocolVersion::V5 => 5,
|
Self::V5 => 5,
|
||||||
ProtocolVersion::V6 => 6,
|
Self::V6 => 6,
|
||||||
ProtocolVersion::V7 => 7,
|
Self::V7 => 7,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
write!(f, "{}", n)
|
write!(f, "{}", n)
|
||||||
|
@ -47,16 +71,49 @@ impl FromStr for ProtocolVersion {
|
||||||
|
|
||||||
fn from_str(input: &str) -> Result<Self, Self::Err> {
|
fn from_str(input: &str) -> Result<Self, Self::Err> {
|
||||||
Ok({
|
Ok({
|
||||||
match input {
|
match input.trim() {
|
||||||
"1" => ProtocolVersion::V1,
|
"1" => Self::V1,
|
||||||
"2" => ProtocolVersion::V2,
|
"2" => Self::V2,
|
||||||
"3" => ProtocolVersion::V3,
|
"3" => Self::V3,
|
||||||
"4" => ProtocolVersion::V4,
|
"4" => Self::V4,
|
||||||
"5" => ProtocolVersion::V5,
|
"5" => Self::V5,
|
||||||
"6" => ProtocolVersion::V6,
|
"6" => Self::V6,
|
||||||
"7" => ProtocolVersion::V7,
|
"7" => Self::V7,
|
||||||
_ => return Err(Error::unknown_protocol_version(input)),
|
_ => return Err(Error::unknown_protocol_version(input)),
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Default for ProtocolVersion {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::V1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_display() {
|
||||||
|
assert_eq!(ProtocolVersion::V1.to_string(), "1".to_string());
|
||||||
|
assert_eq!(ProtocolVersion::V2.to_string(), "2".to_string());
|
||||||
|
assert_eq!(ProtocolVersion::V3.to_string(), "3".to_string());
|
||||||
|
assert_eq!(ProtocolVersion::V4.to_string(), "4".to_string());
|
||||||
|
assert_eq!(ProtocolVersion::V5.to_string(), "5".to_string());
|
||||||
|
assert_eq!(ProtocolVersion::V6.to_string(), "6".to_string());
|
||||||
|
assert_eq!(ProtocolVersion::V7.to_string(), "7".to_string());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_parser() {
|
||||||
|
assert_eq!(ProtocolVersion::V1, "1".parse().unwrap());
|
||||||
|
assert_eq!(ProtocolVersion::V2, "2".parse().unwrap());
|
||||||
|
assert_eq!(ProtocolVersion::V3, "3".parse().unwrap());
|
||||||
|
assert_eq!(ProtocolVersion::V4, "4".parse().unwrap());
|
||||||
|
assert_eq!(ProtocolVersion::V5, "5".parse().unwrap());
|
||||||
|
assert_eq!(ProtocolVersion::V6, "6".parse().unwrap());
|
||||||
|
assert_eq!(ProtocolVersion::V7, "7".parse().unwrap());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue