diff --git a/src/line.rs b/src/line.rs index a5aa690..6d8ca95 100644 --- a/src/line.rs +++ b/src/line.rs @@ -3,7 +3,6 @@ use std::ops::{Deref, DerefMut}; use std::str::FromStr; use crate::tags; -use crate::types::SingleLineString; use crate::Error; #[derive(Debug, Default)] @@ -54,7 +53,7 @@ impl FromStr for Lines { continue; } } else { - Line::Uri(SingleLineString::new(line)?) + Line::Uri(line.trim().to_string()) } } }; @@ -92,7 +91,7 @@ impl DerefMut for Lines { #[derive(Debug, PartialEq, Eq)] pub enum Line { Tag(Tag), - Uri(SingleLineString), + Uri(String), } #[allow(clippy::large_enum_variant)] @@ -120,7 +119,7 @@ pub enum Tag { ExtXSessionKey(tags::ExtXSessionKey), ExtXIndependentSegments(tags::ExtXIndependentSegments), ExtXStart(tags::ExtXStart), - Unknown(SingleLineString), + Unknown(String), } impl fmt::Display for Tag { @@ -202,7 +201,7 @@ impl FromStr for Tag { } else if s.starts_with(tags::ExtXStart::PREFIX) { s.parse().map(Tag::ExtXStart) } else { - SingleLineString::new(s).map(Tag::Unknown) + Ok(Tag::Unknown(s.to_string())) } } } diff --git a/src/media_segment.rs b/src/media_segment.rs index f157ad2..8460547 100644 --- a/src/media_segment.rs +++ b/src/media_segment.rs @@ -6,7 +6,7 @@ use derive_builder::Builder; use crate::tags::{ ExtInf, ExtXByteRange, ExtXDateRange, ExtXDiscontinuity, ExtXKey, ExtXMap, ExtXProgramDateTime, }; -use crate::types::{ProtocolVersion, SingleLineString}; +use crate::types::ProtocolVersion; /// Media segment. #[derive(Debug, Clone, Builder)] @@ -33,7 +33,7 @@ pub struct MediaSegment { /// Sets an [ExtInf] tag. inf_tag: ExtInf, /// Sets an Uri. - uri: SingleLineString, + uri: String, } impl MediaSegmentBuilder { @@ -80,7 +80,7 @@ impl MediaSegment { MediaSegmentBuilder::default() } /// Returns the URI of the media segment. - pub const fn uri(&self) -> &SingleLineString { + pub const fn uri(&self) -> &String { &self.uri } diff --git a/src/tags/master_playlist/stream_inf.rs b/src/tags/master_playlist/stream_inf.rs index d613d6a..e494e02 100644 --- a/src/tags/master_playlist/stream_inf.rs +++ b/src/tags/master_playlist/stream_inf.rs @@ -4,7 +4,6 @@ use std::str::FromStr; use crate::attribute::AttributePairs; use crate::types::{ ClosedCaptions, DecimalFloatingPoint, DecimalResolution, HdcpLevel, ProtocolVersion, - SingleLineString, }; use crate::utils::{parse_u64, quote, tag, unquote}; use crate::Error; @@ -14,7 +13,7 @@ use crate::Error; /// [4.3.4.2. EXT-X-STREAM-INF]: https://tools.ietf.org/html/rfc8216#section-4.3.4.2 #[derive(Debug, Clone, PartialEq, Eq)] pub struct ExtXStreamInf { - uri: SingleLineString, + uri: String, bandwidth: u64, average_bandwidth: Option, codecs: Option, @@ -33,7 +32,7 @@ impl ExtXStreamInf { /// Makes a new `ExtXStreamInf` tag. pub fn new(uri: T, bandwidth: u64) -> Self { ExtXStreamInf { - uri: SingleLineString::new(uri.to_string()).unwrap(), + uri: uri.to_string(), bandwidth, average_bandwidth: None, codecs: None, @@ -48,7 +47,7 @@ impl ExtXStreamInf { } /// Returns the URI that identifies the associated media playlist. - pub const fn uri(&self) -> &SingleLineString { + pub const fn uri(&self) -> &String { &self.uri } @@ -155,12 +154,10 @@ impl FromStr for ExtXStreamInf { fn from_str(input: &str) -> Result { let mut lines = input.lines(); let first_line = lines.next().ok_or(Error::missing_value("first_line"))?; - let second_line = lines.next().ok_or(Error::missing_value("second_line"))?; + let uri = lines.next().ok_or(Error::missing_value("second_line"))?; let first_line = tag(first_line, Self::PREFIX)?; - let uri = SingleLineString::new(second_line)?; - let mut bandwidth = None; let mut average_bandwidth = None; let mut codecs = None; @@ -194,7 +191,7 @@ impl FromStr for ExtXStreamInf { let bandwidth = bandwidth.ok_or(Error::missing_value("EXT-X-BANDWIDTH"))?; Ok(ExtXStreamInf { - uri, + uri: uri.to_string(), bandwidth, average_bandwidth, codecs, diff --git a/src/tags/media_segment/inf.rs b/src/tags/media_segment/inf.rs index 9d2c5b7..287864b 100644 --- a/src/tags/media_segment/inf.rs +++ b/src/tags/media_segment/inf.rs @@ -2,7 +2,7 @@ use std::fmt; use std::str::FromStr; use std::time::Duration; -use crate::types::{DecimalFloatingPoint, ProtocolVersion, SingleLineString}; +use crate::types::{DecimalFloatingPoint, ProtocolVersion}; use crate::utils::tag; use crate::Error; @@ -35,11 +35,10 @@ use crate::Error; /// ``` /// use std::time::Duration; /// use hls_m3u8::tags::ExtInf; -/// use hls_m3u8::types::SingleLineString; /// /// let ext_inf = ExtInf::with_title( /// Duration::from_millis(88), -/// SingleLineString::new("title").unwrap() +/// "title" /// ); /// /// assert_eq!(ext_inf.duration(), Duration::from_millis(88)); @@ -48,7 +47,7 @@ use crate::Error; #[derive(Default, Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] pub struct ExtInf { duration: Duration, - title: Option, + title: Option, } impl ExtInf { @@ -63,10 +62,10 @@ impl ExtInf { } /// Makes a new `ExtInf` tag with the given title. - pub const fn with_title(duration: Duration, title: SingleLineString) -> Self { + pub fn with_title(duration: Duration, title: T) -> Self { ExtInf { duration, - title: Some(title), + title: Some(title.to_string()), } } @@ -76,7 +75,7 @@ impl ExtInf { } /// Returns the title of the associated media segment. - pub fn title(&self) -> Option<&SingleLineString> { + pub fn title(&self) -> Option<&String> { self.title.as_ref() } @@ -127,7 +126,7 @@ impl FromStr for ExtInf { if tokens[1].trim().is_empty() { None } else { - Some(SingleLineString::new(tokens[1])?) + Some(tokens[1].to_string()) } } else { None @@ -160,19 +159,11 @@ mod test { ); assert_eq!( "#EXTINF:5.5,title".to_string(), - ExtInf::with_title( - Duration::from_millis(5500), - SingleLineString::new("title").unwrap() - ) - .to_string() + ExtInf::with_title(Duration::from_millis(5500), "title").to_string() ); assert_eq!( "#EXTINF:5,title".to_string(), - ExtInf::with_title( - Duration::from_secs(5), - SingleLineString::new("title").unwrap() - ) - .to_string() + ExtInf::with_title(Duration::from_secs(5), "title").to_string() ); } @@ -197,17 +188,11 @@ mod test { ); assert_eq!( "#EXTINF:5.5,title".parse::().unwrap(), - ExtInf::with_title( - Duration::from_millis(5500), - SingleLineString::new("title").unwrap() - ) + ExtInf::with_title(Duration::from_millis(5500), "title") ); assert_eq!( "#EXTINF:5,title".parse::().unwrap(), - ExtInf::with_title( - Duration::from_secs(5), - SingleLineString::new("title").unwrap() - ) + ExtInf::with_title(Duration::from_secs(5), "title") ); } @@ -215,12 +200,8 @@ mod test { fn test_title() { assert_eq!(ExtInf::new(Duration::from_secs(5)).title(), None); assert_eq!( - ExtInf::with_title( - Duration::from_secs(5), - SingleLineString::new("title").unwrap() - ) - .title(), - Some(&SingleLineString::new("title").unwrap()) + ExtInf::with_title(Duration::from_secs(5), "title").title(), + Some(&"title".to_string()) ); } diff --git a/src/tags/media_segment/program_date_time.rs b/src/tags/media_segment/program_date_time.rs index a4be50d..46a2874 100644 --- a/src/tags/media_segment/program_date_time.rs +++ b/src/tags/media_segment/program_date_time.rs @@ -1,7 +1,7 @@ use std::fmt; use std::str::FromStr; -use crate::types::{ProtocolVersion, SingleLineString}; +use crate::types::ProtocolVersion; use crate::utils::tag; use crate::Error; @@ -9,21 +9,19 @@ use crate::Error; /// /// [4.3.2.6. EXT-X-PROGRAM-DATE-TIME]: https://tools.ietf.org/html/rfc8216#section-4.3.2.6 #[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct ExtXProgramDateTime { - date_time: SingleLineString, -} +pub struct ExtXProgramDateTime(String); impl ExtXProgramDateTime { pub(crate) const PREFIX: &'static str = "#EXT-X-PROGRAM-DATE-TIME:"; /// Makes a new `ExtXProgramDateTime` tag. - pub const fn new(date_time: SingleLineString) -> Self { - ExtXProgramDateTime { date_time } + pub fn new(date_time: T) -> Self { + Self(date_time.to_string()) } /// Returns the date-time of the first sample of the associated media segment. - pub const fn date_time(&self) -> &SingleLineString { - &self.date_time + pub const fn date_time(&self) -> &String { + &self.0 } /// Returns the protocol compatibility version that this tag requires. @@ -34,7 +32,7 @@ impl ExtXProgramDateTime { impl fmt::Display for ExtXProgramDateTime { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}{}", Self::PREFIX, self.date_time) + write!(f, "{}{}", Self::PREFIX, self.0) } } @@ -46,9 +44,7 @@ impl FromStr for ExtXProgramDateTime { // TODO: parse with chrono - Ok(ExtXProgramDateTime { - date_time: (SingleLineString::new(input))?, - }) + Ok(Self::new(input)) } } diff --git a/src/types/mod.rs b/src/types/mod.rs index 4e2e6a1..5a78297 100644 --- a/src/types/mod.rs +++ b/src/types/mod.rs @@ -13,7 +13,6 @@ mod media_type; mod protocol_version; mod session_data; mod signed_decimal_floating_point; -mod single_line_string; pub use byte_range::*; pub use closed_captions::*; @@ -29,4 +28,3 @@ pub use media_type::*; pub use protocol_version::*; pub use session_data::*; pub use signed_decimal_floating_point::*; -pub use single_line_string::*; diff --git a/src/types/single_line_string.rs b/src/types/single_line_string.rs deleted file mode 100644 index fea3dbb..0000000 --- a/src/types/single_line_string.rs +++ /dev/null @@ -1,58 +0,0 @@ -use crate::Error; -use std::fmt; -use std::ops::Deref; - -/// String that represents a single line in a playlist file. -/// -/// See: [4.1. Definition of a Playlist] -/// -/// [4.1. Definition of a Playlist]: https://tools.ietf.org/html/rfc8216#section-4.1 -#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] -pub struct SingleLineString(String); - -impl SingleLineString { - /// Makes a new `SingleLineString` instance. - /// - /// # Errors - /// - /// If the given string contains any control characters, - /// this function will return an error which has the kind `ErrorKind::InvalidInput`. - pub fn new>(s: T) -> crate::Result { - let s = s.into(); - if s.chars().any(|c| c.is_control()) { - Err(Error::invalid_input()) - } else { - Ok(SingleLineString(s)) - } - } -} - -impl Deref for SingleLineString { - type Target = str; - fn deref(&self) -> &Self::Target { - &self.0 - } -} - -impl AsRef for SingleLineString { - fn as_ref(&self) -> &str { - &self.0 - } -} - -impl fmt::Display for SingleLineString { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - self.0.fmt(f) - } -} - -#[cfg(test)] -mod test { - use super::*; - - #[test] - fn single_line_string() { - assert!(SingleLineString::new("foo").is_ok()); - assert!(SingleLineString::new("b\rar").is_err()); - } -} diff --git a/tests/playlist.rs b/tests/playlist.rs index 9b92ae5..466a6c7 100644 --- a/tests/playlist.rs +++ b/tests/playlist.rs @@ -37,11 +37,11 @@ fn test_simple_playlist() { assert_eq!( media_playlist.segments()[0].uri(), - &SingleLineString::new("http://media.example.com/entire1.ts").unwrap() + &"http://media.example.com/entire1.ts".to_string() ); assert_eq!( media_playlist.segments()[1].uri(), - &SingleLineString::new("http://media.example.com/entire2.ts").unwrap() + &"http://media.example.com/entire2.ts".to_string() ); }