From fa96a76ca9c9044f3694a1d7ae5f305aa3a14802 Mon Sep 17 00:00:00 2001 From: Luro02 <24826124+Luro02@users.noreply.github.com> Date: Sun, 15 Sep 2019 11:25:41 +0200 Subject: [PATCH] parse Urls #9 --- Cargo.toml | 1 + src/error.rs | 13 +++++++++++++ src/line.rs | 6 ++++-- src/media_segment.rs | 5 +++-- src/tags/master_playlist/stream_inf.rs | 25 +++++++++++++++---------- tests/playlist.rs | 5 ++--- 6 files changed, 38 insertions(+), 17 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 35c5a24..4ee2342 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,6 +19,7 @@ codecov = {repository = "sile/hls_m3u8"} getset = "0.0.8" failure = "0.1.5" derive_builder = "0.7.2" +url = "2.1.0" [dev-dependencies] clap = "2" diff --git a/src/error.rs b/src/error.rs index 951bd18..c6eee27 100644 --- a/src/error.rs +++ b/src/error.rs @@ -9,6 +9,9 @@ pub type Result = std::result::Result; /// The ErrorKind. #[derive(Debug, Fail, Clone, PartialEq, Eq)] pub enum ErrorKind { + #[fail(display = "UrlParseError: {}", _0)] + /// An error from the [Url](url) crate. + UrlParseError(String), #[fail(display = "UnknownError: {}", _0)] /// An unknown error occured. UnknownError(String), @@ -177,6 +180,10 @@ impl Error { pub(crate) fn builder_error(value: T) -> Self { Self::from(ErrorKind::BuilderError(value.to_string())) } + + pub(crate) fn url(value: T) -> Self { + Self::from(ErrorKind::UrlParseError(value.to_string())) + } } impl From<::std::num::ParseIntError> for Error { @@ -196,3 +203,9 @@ impl From<::std::io::Error> for Error { Error::io(value) } } + +impl From<::url::ParseError> for Error { + fn from(value: ::url::ParseError) -> Self { + Error::url(value) + } +} diff --git a/src/line.rs b/src/line.rs index 6d8ca95..28b3a32 100644 --- a/src/line.rs +++ b/src/line.rs @@ -2,6 +2,8 @@ use std::fmt; use std::ops::{Deref, DerefMut}; use std::str::FromStr; +use url::Url; + use crate::tags; use crate::Error; @@ -53,7 +55,7 @@ impl FromStr for Lines { continue; } } else { - Line::Uri(line.trim().to_string()) + Line::Uri(line.trim().parse()?) } } }; @@ -91,7 +93,7 @@ impl DerefMut for Lines { #[derive(Debug, PartialEq, Eq)] pub enum Line { Tag(Tag), - Uri(String), + Uri(Url), } #[allow(clippy::large_enum_variant)] diff --git a/src/media_segment.rs b/src/media_segment.rs index 8460547..d637131 100644 --- a/src/media_segment.rs +++ b/src/media_segment.rs @@ -2,6 +2,7 @@ use std::fmt; use std::iter; use derive_builder::Builder; +use url::Url; use crate::tags::{ ExtInf, ExtXByteRange, ExtXDateRange, ExtXDiscontinuity, ExtXKey, ExtXMap, ExtXProgramDateTime, @@ -33,7 +34,7 @@ pub struct MediaSegment { /// Sets an [ExtInf] tag. inf_tag: ExtInf, /// Sets an Uri. - uri: String, + uri: Url, } impl MediaSegmentBuilder { @@ -80,7 +81,7 @@ impl MediaSegment { MediaSegmentBuilder::default() } /// Returns the URI of the media segment. - pub const fn uri(&self) -> &String { + pub const fn uri(&self) -> &Url { &self.uri } diff --git a/src/tags/master_playlist/stream_inf.rs b/src/tags/master_playlist/stream_inf.rs index e494e02..78dd7ee 100644 --- a/src/tags/master_playlist/stream_inf.rs +++ b/src/tags/master_playlist/stream_inf.rs @@ -1,6 +1,8 @@ use std::fmt; use std::str::FromStr; +use url::Url; + use crate::attribute::AttributePairs; use crate::types::{ ClosedCaptions, DecimalFloatingPoint, DecimalResolution, HdcpLevel, ProtocolVersion, @@ -13,7 +15,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: String, + uri: Url, bandwidth: u64, average_bandwidth: Option, codecs: Option, @@ -30,9 +32,9 @@ impl ExtXStreamInf { pub(crate) const PREFIX: &'static str = "#EXT-X-STREAM-INF:"; /// Makes a new `ExtXStreamInf` tag. - pub fn new(uri: T, bandwidth: u64) -> Self { + pub const fn new(uri: Url, bandwidth: u64) -> Self { ExtXStreamInf { - uri: uri.to_string(), + uri, bandwidth, average_bandwidth: None, codecs: None, @@ -47,7 +49,7 @@ impl ExtXStreamInf { } /// Returns the URI that identifies the associated media playlist. - pub const fn uri(&self) -> &String { + pub const fn uri(&self) -> &Url { &self.uri } @@ -191,7 +193,7 @@ impl FromStr for ExtXStreamInf { let bandwidth = bandwidth.ok_or(Error::missing_value("EXT-X-BANDWIDTH"))?; Ok(ExtXStreamInf { - uri: uri.to_string(), + uri: uri.parse()?, bandwidth, average_bandwidth, codecs, @@ -212,26 +214,29 @@ mod test { #[test] fn test_parser() { - let stream_inf = "#EXT-X-STREAM-INF:BANDWIDTH=1000\nfoo" + let stream_inf = "#EXT-X-STREAM-INF:BANDWIDTH=1000\nhttp://www.example.com" .parse::() .unwrap(); - assert_eq!(stream_inf, ExtXStreamInf::new("foo", 1000)); + assert_eq!( + stream_inf, + ExtXStreamInf::new("http://www.example.com".parse().unwrap(), 1000) + ); } #[test] fn test_requires_version() { assert_eq!( ProtocolVersion::V1, - ExtXStreamInf::new("foo", 1000).requires_version() + ExtXStreamInf::new("http://www.example.com".parse().unwrap(), 1000).requires_version() ); } #[test] fn test_display() { assert_eq!( - ExtXStreamInf::new("foo", 1000).to_string(), - "#EXT-X-STREAM-INF:BANDWIDTH=1000\nfoo".to_string() + ExtXStreamInf::new("http://www.example.com".parse().unwrap(), 1000).to_string(), + "#EXT-X-STREAM-INF:BANDWIDTH=1000\nhttp://www.example.com/".to_string() ); } } diff --git a/tests/playlist.rs b/tests/playlist.rs index 466a6c7..b61068a 100644 --- a/tests/playlist.rs +++ b/tests/playlist.rs @@ -1,7 +1,6 @@ //! Credits go to //! - https://github.com/globocom/m3u8/blob/master/tests/playlists.py use hls_m3u8::tags::*; -use hls_m3u8::types::*; use hls_m3u8::MediaPlaylist; use std::time::Duration; @@ -37,11 +36,11 @@ fn test_simple_playlist() { assert_eq!( media_playlist.segments()[0].uri(), - &"http://media.example.com/entire1.ts".to_string() + &"http://media.example.com/entire1.ts".parse().unwrap() ); assert_eq!( media_playlist.segments()[1].uri(), - &"http://media.example.com/entire2.ts".to_string() + &"http://media.example.com/entire2.ts".parse().unwrap() ); }