diff --git a/src/media_playlist.rs b/src/media_playlist.rs index 6a860fe..238aaf3 100644 --- a/src/media_playlist.rs +++ b/src/media_playlist.rs @@ -6,7 +6,7 @@ use std::time::Duration; use derive_builder::Builder; use crate::line::{Line, Lines, Tag}; -use crate::media_segment::{MediaSegment, MediaSegmentBuilder}; +use crate::media_segment::MediaSegment; use crate::tags::{ ExtM3u, ExtXDiscontinuitySequence, ExtXEndList, ExtXIFramesOnly, ExtXIndependentSegments, ExtXMediaSequence, ExtXPlaylistType, ExtXStart, ExtXTargetDuration, ExtXVersion, @@ -314,7 +314,7 @@ fn parse_media_playlist( input: &str, builder: &mut MediaPlaylistBuilder, ) -> crate::Result { - let mut segment = MediaSegmentBuilder::new(); + let mut segment = MediaSegment::builder(); let mut segments = vec![]; let mut has_partial_segment = false; @@ -336,32 +336,32 @@ fn parse_media_playlist( } Tag::ExtInf(t) => { has_partial_segment = true; - segment.tag(t); + segment.inf_tag(t); } Tag::ExtXByteRange(t) => { has_partial_segment = true; - segment.tag(t); + segment.byte_range_tag(t); } Tag::ExtXDiscontinuity(t) => { has_discontinuity_tag = true; has_partial_segment = true; - segment.tag(t); + segment.discontinuity_tag(t); } Tag::ExtXKey(t) => { has_partial_segment = true; - segment.tag(t); + segment.push_key_tag(t); } Tag::ExtXMap(t) => { has_partial_segment = true; - segment.tag(t); + segment.map_tag(t); } Tag::ExtXProgramDateTime(t) => { has_partial_segment = true; - segment.tag(t); + segment.program_date_time_tag(t); } Tag::ExtXDateRange(t) => { has_partial_segment = true; - segment.tag(t); + segment.date_range_tag(t); } Tag::ExtXTargetDuration(t) => { builder.target_duration_tag(t); @@ -408,8 +408,8 @@ fn parse_media_playlist( } Line::Uri(uri) => { segment.uri(uri); - segments.push(segment.finish()?); - segment = MediaSegmentBuilder::new(); + segments.push(segment.build().map_err(Error::builder_error)?); + segment = MediaSegment::builder(); has_partial_segment = false; } } diff --git a/src/media_segment.rs b/src/media_segment.rs index 3f45f5b..45520b5 100644 --- a/src/media_segment.rs +++ b/src/media_segment.rs @@ -1,96 +1,51 @@ use std::fmt; use std::iter; +use derive_builder::Builder; + use crate::tags::{ ExtInf, ExtXByteRange, ExtXDateRange, ExtXDiscontinuity, ExtXKey, ExtXMap, ExtXProgramDateTime, - MediaSegmentTag, }; use crate::types::{ProtocolVersion, SingleLineString}; -use crate::Error; -/// Media segment builder. -#[derive(Debug, Clone)] -pub struct MediaSegmentBuilder { +/// Media segment. +#[derive(Debug, Clone, Builder)] +#[builder(setter(into, strip_option))] +pub struct MediaSegment { + #[builder(default)] + /// Sets all [ExtXKey] tags. key_tags: Vec, + #[builder(default)] + /// Sets an [ExtXMap] tag. map_tag: Option, + #[builder(default)] + /// Sets an [ExtXByteRange] tag. byte_range_tag: Option, + #[builder(default)] + /// Sets an [ExtXDateRange] tag. date_range_tag: Option, + #[builder(default)] + /// Sets an [ExtXDiscontinuity] tag. discontinuity_tag: Option, + #[builder(default)] + /// Sets an [ExtXProgramDateTime] tag. program_date_time_tag: Option, - inf_tag: Option, - uri: Option, + /// Sets an [ExtInf] tag. + inf_tag: ExtInf, + /// Sets an Uri. + uri: SingleLineString, } impl MediaSegmentBuilder { - /// Makes a new `MediaSegmentBuilder` instance. - pub fn new() -> Self { - MediaSegmentBuilder { - key_tags: Vec::new(), - map_tag: None, - byte_range_tag: None, - date_range_tag: None, - discontinuity_tag: None, - program_date_time_tag: None, - inf_tag: None, - uri: None, - } - } - - /// Sets the URI of the resulting media segment. - pub fn uri(&mut self, uri: SingleLineString) -> &mut Self { - self.uri = Some(uri); - self - } - - /// Sets the given tag to the resulting media segment. - pub fn tag>(&mut self, tag: T) -> &mut Self { - match tag.into() { - MediaSegmentTag::ExtInf(t) => self.inf_tag = Some(t), - MediaSegmentTag::ExtXByteRange(t) => self.byte_range_tag = Some(t), - MediaSegmentTag::ExtXDateRange(t) => self.date_range_tag = Some(t), - MediaSegmentTag::ExtXDiscontinuity(t) => self.discontinuity_tag = Some(t), - MediaSegmentTag::ExtXKey(t) => self.key_tags.push(t), - MediaSegmentTag::ExtXMap(t) => self.map_tag = Some(t), - MediaSegmentTag::ExtXProgramDateTime(t) => self.program_date_time_tag = Some(t), + /// Pushes an [ExtXKey] tag. + pub fn push_key_tag>(&mut self, value: VALUE) -> &mut Self { + if let Some(key_tags) = &mut self.key_tags { + key_tags.push(value.into()); + } else { + self.key_tags = Some(vec![value.into()]); } self } - - /// Builds a `MediaSegment` instance. - pub fn finish(self) -> crate::Result { - let uri = self.uri.ok_or(Error::missing_value("self.uri"))?; - let inf_tag = self.inf_tag.ok_or(Error::missing_value("self.inf_tag"))?; - - Ok(MediaSegment { - key_tags: self.key_tags, - map_tag: self.map_tag, - byte_range_tag: self.byte_range_tag, - date_range_tag: self.date_range_tag, - discontinuity_tag: self.discontinuity_tag, - program_date_time_tag: self.program_date_time_tag, - inf_tag, - uri, - }) - } -} - -impl Default for MediaSegmentBuilder { - fn default() -> Self { - Self::new() - } -} - -/// Media segment. -#[derive(Debug, Clone)] -pub struct MediaSegment { - key_tags: Vec, - map_tag: Option, - byte_range_tag: Option, - date_range_tag: Option, - discontinuity_tag: Option, - program_date_time_tag: Option, - inf_tag: ExtInf, - uri: SingleLineString, } impl fmt::Display for MediaSegment { @@ -120,6 +75,10 @@ impl fmt::Display for MediaSegment { } impl MediaSegment { + /// Creates a [MediaSegmentBuilder]. + pub fn builder() -> MediaSegmentBuilder { + MediaSegmentBuilder::default() + } /// Returns the URI of the media segment. pub const fn uri(&self) -> &SingleLineString { &self.uri @@ -175,6 +134,6 @@ impl MediaSegment { ) .chain(iter::once(self.inf_tag.requires_version())) .max() - .expect("Never fails") + .unwrap_or(ProtocolVersion::V7) } }