From 6ef8182f2ce9efa6e16a47eec370078bd0d5ae15 Mon Sep 17 00:00:00 2001 From: Luro02 <24826124+Luro02@users.noreply.github.com> Date: Mon, 24 Feb 2020 16:44:02 +0100 Subject: [PATCH] improvments to ExtXStart --- src/master_playlist.rs | 5 +- src/tags/media_segment/date_range.rs | 154 ++++++++++++--------------- src/tags/shared/start.rs | 108 ++++++++----------- 3 files changed, 118 insertions(+), 149 deletions(-) diff --git a/src/master_playlist.rs b/src/master_playlist.rs index 4499db2..cfc1156 100644 --- a/src/master_playlist.rs +++ b/src/master_playlist.rs @@ -103,11 +103,12 @@ impl MasterPlaylist { /// # Example /// /// ``` + /// # use hls_m3u8::MasterPlaylist; /// use hls_m3u8::tags::ExtXStart; - /// use hls_m3u8::MasterPlaylist; + /// use hls_m3u8::types::Float; /// /// MasterPlaylist::builder() - /// .start(ExtXStart::new(20.123456)) + /// .start(ExtXStart::new(Float::new(20.3))) /// .build()?; /// # Ok::<(), Box>(()) /// ``` diff --git a/src/tags/media_segment/date_range.rs b/src/tags/media_segment/date_range.rs index 337322b..061489d 100644 --- a/src/tags/media_segment/date_range.rs +++ b/src/tags/media_segment/date_range.rs @@ -326,53 +326,70 @@ impl fmt::Display for ExtXDateRange { #[cfg(test)] mod test { use super::*; + use crate::types::Float; use chrono::offset::TimeZone; use pretty_assertions::assert_eq; const HOURS_IN_SECS: i32 = 3600; // 1 hour = 3600 seconds - #[test] - fn test_parser() { - assert_eq!( - "#EXT-X-DATERANGE:\ - ID=\"splice-6FFFFFF0\",\ - START-DATE=\"2014-03-05T11:15:00Z\",\ - PLANNED-DURATION=59.993,\ - SCTE35-OUT=0xFC002F0000000000FF000014056F\ - FFFFF000E011622DCAFF000052636200000000000\ - A0008029896F50000008700000000" + macro_rules! generate_tests { + ( $( { $left:expr, $right:expr } ),* $(,)* ) => { + #[test] + fn test_display() { + $( + assert_eq!($left.to_string(), $right.to_string()); + )* + } + + #[test] + fn test_parser() { + $( + assert_eq!($left, $right.parse().unwrap()); + )* + assert!("#EXT-X-DATERANGE:END-ON-NEXT=NO" + .parse::() + .is_err()); + + assert!("garbage".parse::().is_err()); + assert!("".parse::().is_err()); + + assert!(concat!( + "#EXT-X-DATERANGE:", + "ID=\"test_id\",", + "START-DATE=\"2014-03-05T11:15:00Z\",", + "END-ON-NEXT=YES" + ) .parse::() - .unwrap(), + .is_err()); + } + } + } + + generate_tests! { + { ExtXDateRange::builder() .id("splice-6FFFFFF0") .start_date(FixedOffset::east(0).ymd(2014, 3, 5).and_hms(11, 15, 0)) .planned_duration(Duration::from_secs_f64(59.993)) - .scte35_out( - "0xFC002F0000000000FF00001\ - 4056FFFFFF000E011622DCAFF0\ - 00052636200000000000A00080\ - 29896F50000008700000000" - ) + .scte35_out(concat!( + "0xFC002F0000000000FF00001", + "4056FFFFFF000E011622DCAFF0", + "00052636200000000000A00080", + "29896F50000008700000000" + )) .build() - .unwrap() - ); - - assert_eq!( - "#EXT-X-DATERANGE:\ - ID=\"test_id\",\ - CLASS=\"test_class\",\ - START-DATE=\"2014-03-05T11:15:00Z\",\ - END-DATE=\"2014-03-05T11:16:00Z\",\ - DURATION=60.1,\ - PLANNED-DURATION=59.993,\ - X-CUSTOM=45.3,\ - SCTE35-CMD=0xFC002F0000000000FF2,\ - SCTE35-OUT=0xFC002F0000000000FF0,\ - SCTE35-IN=0xFC002F0000000000FF1,\ - END-ON-NEXT=YES,\ - UNKNOWN=PHANTOM" - .parse::() .unwrap(), + concat!( + "#EXT-X-DATERANGE:", + "ID=\"splice-6FFFFFF0\",", + "START-DATE=\"2014-03-05T11:15:00Z\",", + "PLANNED-DURATION=59.993,", + "SCTE35-OUT=0xFC002F0000000000FF000014056F", + "FFFFF000E011622DCAFF000052636200000000000", + "A0008029896F50000008700000000" + ) + }, + { ExtXDateRange::builder() .id("test_id") .class("test_class") @@ -380,61 +397,28 @@ mod test { .end_date(FixedOffset::east(0).ymd(2014, 3, 5).and_hms(11, 16, 0)) .duration(Duration::from_secs_f64(60.1)) .planned_duration(Duration::from_secs_f64(59.993)) - .insert_client_attribute("X-CUSTOM", 45.3) + .insert_client_attribute("X-CUSTOM", Float::new(45.3)) .scte35_cmd("0xFC002F0000000000FF2") .scte35_out("0xFC002F0000000000FF0") .scte35_in("0xFC002F0000000000FF1") .end_on_next(true) .build() - .unwrap() - ); - - assert!("#EXT-X-DATERANGE:END-ON-NEXT=NO" - .parse::() - .is_err()); - - assert!("garbage".parse::().is_err()); - assert!("".parse::().is_err()); - - assert!("#EXT-X-DATERANGE:\ - ID=\"test_id\",\ - START-DATE=\"2014-03-05T11:15:00Z\",\ - END-ON-NEXT=YES" - .parse::() - .is_err()); - } - - #[test] - fn test_display() { - assert_eq!( - ExtXDateRange::builder() - .id("test_id") - .class("test_class") - .start_date(FixedOffset::east(0).ymd(2014, 3, 5).and_hms(11, 15, 0)) - .end_date(FixedOffset::east(0).ymd(2014, 3, 5).and_hms(11, 16, 0)) - .duration(Duration::from_secs_f64(60.1)) - .planned_duration(Duration::from_secs_f64(59.993)) - .insert_client_attribute("X-CUSTOM", 45.3) - .scte35_cmd("0xFC002F0000000000FF2") - .scte35_out("0xFC002F0000000000FF0") - .scte35_in("0xFC002F0000000000FF1") - .end_on_next(true) - .build() - .unwrap() - .to_string(), - "#EXT-X-DATERANGE:\ - ID=\"test_id\",\ - CLASS=\"test_class\",\ - START-DATE=\"2014-03-05T11:15:00Z\",\ - END-DATE=\"2014-03-05T11:16:00Z\",\ - DURATION=60.1,\ - PLANNED-DURATION=59.993,\ - SCTE35-CMD=0xFC002F0000000000FF2,\ - SCTE35-OUT=0xFC002F0000000000FF0,\ - SCTE35-IN=0xFC002F0000000000FF1,\ - X-CUSTOM=45.3,\ - END-ON-NEXT=YES" - ) + .unwrap(), + concat!( + "#EXT-X-DATERANGE:", + "ID=\"test_id\",", + "CLASS=\"test_class\",", + "START-DATE=\"2014-03-05T11:15:00Z\",", + "END-DATE=\"2014-03-05T11:16:00Z\",", + "DURATION=60.1,", + "PLANNED-DURATION=59.993,", + "SCTE35-CMD=0xFC002F0000000000FF2,", + "SCTE35-OUT=0xFC002F0000000000FF0,", + "SCTE35-IN=0xFC002F0000000000FF1,", + "X-CUSTOM=45.3,", + "END-ON-NEXT=YES" + ) + }, } #[test] diff --git a/src/tags/shared/start.rs b/src/tags/shared/start.rs index 1b2afb2..0d676c7 100644 --- a/src/tags/shared/start.rs +++ b/src/tags/shared/start.rs @@ -8,22 +8,42 @@ use crate::types::{Float, ProtocolVersion}; use crate::utils::{parse_yes_or_no, tag}; use crate::{Error, RequiredVersion}; -/// # [4.3.5.2. EXT-X-START] +/// This tag indicates a preferred point at which to start +/// playing a Playlist. /// -/// [4.3.5.2. EXT-X-START]: https://tools.ietf.org/html/rfc8216#section-4.3.5.2 +/// By default, clients should start playback at this point when beginning a +/// playback session. #[derive(ShortHand, PartialOrd, Debug, Clone, Copy, PartialEq)] #[shorthand(enable(must_use))] pub struct ExtXStart { - #[shorthand(enable(skip))] - time_offset: Float, - /// Returns whether clients should not render media stream whose - /// presentation times are prior to the specified time offset. + /// The time offset of the [`MediaSegment`]s in the playlist. /// /// # Example /// /// ``` /// # use hls_m3u8::tags::ExtXStart; - /// let mut start = ExtXStart::new(20.123456); + /// use hls_m3u8::types::Float; + /// + /// let mut start = ExtXStart::new(Float::new(20.123456)); + /// # assert_eq!(start.time_offset(), Float::new(20.123456)); + /// + /// start.set_time_offset(Float::new(1.0)); + /// assert_eq!(start.time_offset(), Float::new(1.0)); + /// ``` + /// + /// [`MediaSegment`]: crate::MediaSegment + #[shorthand(enable(copy))] + time_offset: Float, + /// Whether clients should not render media stream whose presentation times + /// are prior to the specified time offset. + /// + /// # Example + /// + /// ``` + /// # use hls_m3u8::tags::ExtXStart; + /// use hls_m3u8::types::Float; + /// + /// let mut start = ExtXStart::new(Float::new(20.123456)); /// # assert_eq!(start.is_precise(), false); /// start.set_is_precise(true); /// @@ -37,76 +57,40 @@ impl ExtXStart { /// Makes a new [`ExtXStart`] tag. /// - /// # Panics - /// - /// Panics if the `time_offset` is infinite or [`NaN`]. - /// /// # Example /// /// ``` /// # use hls_m3u8::tags::ExtXStart; - /// let start = ExtXStart::new(20.123456); - /// ``` + /// use hls_m3u8::types::Float; /// - /// [`NaN`]: core::f64::NAN - pub fn new(time_offset: f32) -> Self { + /// let start = ExtXStart::new(Float::new(20.123456)); + /// ``` + #[must_use] + pub const fn new(time_offset: Float) -> Self { Self { - time_offset: Float::new(time_offset), + time_offset, is_precise: false, } } /// Makes a new [`ExtXStart`] tag with the given `precise` flag. /// - /// # Panics - /// - /// Panics if the `time_offset` is infinite or [`NaN`]. - /// /// # Example /// /// ``` /// # use hls_m3u8::tags::ExtXStart; - /// let start = ExtXStart::with_precise(20.123456, true); + /// use hls_m3u8::types::Float; + /// + /// let start = ExtXStart::with_precise(Float::new(20.123456), true); /// assert_eq!(start.is_precise(), true); /// ``` - /// - /// [`NaN`]: core::f64::NAN - pub fn with_precise(time_offset: f32, is_precise: bool) -> Self { + #[must_use] + pub const fn with_precise(time_offset: Float, is_precise: bool) -> Self { Self { - time_offset: Float::new(time_offset), + time_offset, is_precise, } } - - /// Returns the time offset of the media segments in the playlist. - /// - /// # Example - /// - /// ``` - /// # use hls_m3u8::tags::ExtXStart; - /// let start = ExtXStart::new(20.123456); - /// - /// assert_eq!(start.time_offset(), 20.123456); - /// ``` - pub const fn time_offset(self) -> f32 { self.time_offset.as_f32() } - - /// Sets the time offset of the media segments in the playlist. - /// - /// # Example - /// - /// ``` - /// # use hls_m3u8::tags::ExtXStart; - /// let mut start = ExtXStart::new(20.123456); - /// # assert_eq!(start.time_offset(), 20.123456); - /// - /// start.set_time_offset(1.0); - /// - /// assert_eq!(start.time_offset(), 1.0); - /// ``` - pub fn set_time_offset(&mut self, value: f32) -> &mut Self { - self.time_offset = Float::new(value); - self - } } /// This tag requires [`ProtocolVersion::V1`]. @@ -165,12 +149,12 @@ mod test { #[test] fn test_display() { assert_eq!( - ExtXStart::new(-1.23).to_string(), + ExtXStart::new(Float::new(-1.23)).to_string(), "#EXT-X-START:TIME-OFFSET=-1.23".to_string(), ); assert_eq!( - ExtXStart::with_precise(1.23, true).to_string(), + ExtXStart::with_precise(Float::new(1.23), true).to_string(), "#EXT-X-START:TIME-OFFSET=1.23,PRECISE=YES".to_string(), ); } @@ -178,12 +162,12 @@ mod test { #[test] fn test_required_version() { assert_eq!( - ExtXStart::new(-1.23).required_version(), + ExtXStart::new(Float::new(-1.23)).required_version(), ProtocolVersion::V1, ); assert_eq!( - ExtXStart::with_precise(1.23, true).required_version(), + ExtXStart::with_precise(Float::new(1.23), true).required_version(), ProtocolVersion::V1, ); } @@ -191,17 +175,17 @@ mod test { #[test] fn test_parser() { assert_eq!( - ExtXStart::new(-1.23), + ExtXStart::new(Float::new(-1.23)), "#EXT-X-START:TIME-OFFSET=-1.23".parse().unwrap(), ); assert_eq!( - ExtXStart::with_precise(1.23, true), + ExtXStart::with_precise(Float::new(1.23), true), "#EXT-X-START:TIME-OFFSET=1.23,PRECISE=YES".parse().unwrap(), ); assert_eq!( - ExtXStart::with_precise(1.23, true), + ExtXStart::with_precise(Float::new(1.23), true), "#EXT-X-START:TIME-OFFSET=1.23,PRECISE=YES,UNKNOWN=TAG" .parse() .unwrap(),