mirror of
https://github.com/sile/hls_m3u8.git
synced 2024-06-02 05:02:43 +00:00
commit
56f8d10f38
|
@ -16,10 +16,8 @@ travis-ci = {repository = "sile/hls_m3u8"}
|
||||||
codecov = {repository = "sile/hls_m3u8"}
|
codecov = {repository = "sile/hls_m3u8"}
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
getset = "0.0.8"
|
|
||||||
failure = "0.1.5"
|
failure = "0.1.5"
|
||||||
derive_builder = "0.7.2"
|
derive_builder = "0.7.2"
|
||||||
url = "2.1.0"
|
|
||||||
chrono = "0.4.9"
|
chrono = "0.4.9"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
|
|
14
src/error.rs
14
src/error.rs
|
@ -12,9 +12,7 @@ pub enum ErrorKind {
|
||||||
#[fail(display = "ChronoParseError: {}", _0)]
|
#[fail(display = "ChronoParseError: {}", _0)]
|
||||||
/// An error from the [Chrono](chrono) crate.
|
/// An error from the [Chrono](chrono) crate.
|
||||||
ChronoParseError(String),
|
ChronoParseError(String),
|
||||||
#[fail(display = "UrlParseError: {}", _0)]
|
|
||||||
/// An error from the [Url](url) crate.
|
|
||||||
UrlParseError(String),
|
|
||||||
#[fail(display = "UnknownError: {}", _0)]
|
#[fail(display = "UnknownError: {}", _0)]
|
||||||
/// An unknown error occured.
|
/// An unknown error occured.
|
||||||
UnknownError(String),
|
UnknownError(String),
|
||||||
|
@ -184,10 +182,6 @@ impl Error {
|
||||||
Self::from(ErrorKind::BuilderError(value.to_string()))
|
Self::from(ErrorKind::BuilderError(value.to_string()))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn url<T: ToString>(value: T) -> Self {
|
|
||||||
Self::from(ErrorKind::UrlParseError(value.to_string()))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn chrono<T: ToString>(value: T) -> Self {
|
pub(crate) fn chrono<T: ToString>(value: T) -> Self {
|
||||||
Self::from(ErrorKind::ChronoParseError(value.to_string()))
|
Self::from(ErrorKind::ChronoParseError(value.to_string()))
|
||||||
}
|
}
|
||||||
|
@ -211,12 +205,6 @@ impl From<::std::io::Error> for Error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<::url::ParseError> for Error {
|
|
||||||
fn from(value: ::url::ParseError) -> Self {
|
|
||||||
Error::url(value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<::chrono::ParseError> for Error {
|
impl From<::chrono::ParseError> for Error {
|
||||||
fn from(value: ::chrono::ParseError) -> Self {
|
fn from(value: ::chrono::ParseError) -> Self {
|
||||||
Error::chrono(value)
|
Error::chrono(value)
|
||||||
|
|
|
@ -2,8 +2,6 @@ use std::fmt;
|
||||||
use std::ops::{Deref, DerefMut};
|
use std::ops::{Deref, DerefMut};
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
use url::Url;
|
|
||||||
|
|
||||||
use crate::tags;
|
use crate::tags;
|
||||||
use crate::Error;
|
use crate::Error;
|
||||||
|
|
||||||
|
@ -55,7 +53,7 @@ impl FromStr for Lines {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Line::Uri(line.trim().parse()?)
|
Line::Uri(line.trim().to_string())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -93,7 +91,7 @@ impl DerefMut for Lines {
|
||||||
#[derive(Debug, PartialEq, Eq)]
|
#[derive(Debug, PartialEq, Eq)]
|
||||||
pub enum Line {
|
pub enum Line {
|
||||||
Tag(Tag),
|
Tag(Tag),
|
||||||
Uri(Url),
|
Uri(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::large_enum_variant)]
|
#[allow(clippy::large_enum_variant)]
|
||||||
|
|
|
@ -2,7 +2,6 @@ use std::fmt;
|
||||||
use std::iter;
|
use std::iter;
|
||||||
|
|
||||||
use derive_builder::Builder;
|
use derive_builder::Builder;
|
||||||
use url::Url;
|
|
||||||
|
|
||||||
use crate::tags::{
|
use crate::tags::{
|
||||||
ExtInf, ExtXByteRange, ExtXDateRange, ExtXDiscontinuity, ExtXKey, ExtXMap, ExtXProgramDateTime,
|
ExtInf, ExtXByteRange, ExtXDateRange, ExtXDiscontinuity, ExtXKey, ExtXMap, ExtXProgramDateTime,
|
||||||
|
@ -34,7 +33,7 @@ pub struct MediaSegment {
|
||||||
/// Sets an [ExtInf] tag.
|
/// Sets an [ExtInf] tag.
|
||||||
inf_tag: ExtInf,
|
inf_tag: ExtInf,
|
||||||
/// Sets an Uri.
|
/// Sets an Uri.
|
||||||
uri: Url,
|
uri: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MediaSegmentBuilder {
|
impl MediaSegmentBuilder {
|
||||||
|
@ -81,7 +80,7 @@ impl MediaSegment {
|
||||||
MediaSegmentBuilder::default()
|
MediaSegmentBuilder::default()
|
||||||
}
|
}
|
||||||
/// Returns the URI of the media segment.
|
/// Returns the URI of the media segment.
|
||||||
pub const fn uri(&self) -> &Url {
|
pub const fn uri(&self) -> &String {
|
||||||
&self.uri
|
&self.uri
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
use getset::{Getters, MutGetters, Setters};
|
|
||||||
|
|
||||||
use crate::attribute::AttributePairs;
|
use crate::attribute::AttributePairs;
|
||||||
use crate::types::{DecimalResolution, HdcpLevel, ProtocolVersion};
|
use crate::types::{DecimalResolution, HdcpLevel, ProtocolVersion};
|
||||||
use crate::utils::parse_u64;
|
use crate::utils::parse_u64;
|
||||||
|
@ -12,39 +10,14 @@ use crate::Error;
|
||||||
/// [4.3.4.3. EXT-X-I-FRAME-STREAM-INF]
|
/// [4.3.4.3. EXT-X-I-FRAME-STREAM-INF]
|
||||||
///
|
///
|
||||||
/// [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(Getters, Setters, MutGetters, Debug, Clone, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||||
pub struct ExtXIFrameStreamInf {
|
pub struct ExtXIFrameStreamInf {
|
||||||
#[get = "pub"]
|
|
||||||
#[set = "pub"]
|
|
||||||
#[get_mut = "pub"]
|
|
||||||
/// The URI, that identifies the associated media playlist.
|
|
||||||
uri: String,
|
uri: String,
|
||||||
#[get = "pub"]
|
|
||||||
#[set = "pub"]
|
|
||||||
#[get_mut = "pub"]
|
|
||||||
/// The peak segment bit rate of the variant stream.
|
|
||||||
bandwidth: u64,
|
bandwidth: u64,
|
||||||
#[get = "pub"]
|
|
||||||
#[set = "pub"]
|
|
||||||
#[get_mut = "pub"]
|
|
||||||
/// The average segment bit rate of the variant stream.
|
|
||||||
average_bandwidth: Option<u64>,
|
average_bandwidth: Option<u64>,
|
||||||
#[get = "pub"]
|
|
||||||
#[set = "pub"]
|
|
||||||
#[get_mut = "pub"]
|
|
||||||
/// A string that represents the list of codec types contained the variant stream.
|
|
||||||
codecs: Option<String>,
|
codecs: Option<String>,
|
||||||
/// The optimal pixel resolution at which to display all the video in the variant stream.
|
|
||||||
resolution: Option<DecimalResolution>,
|
resolution: Option<DecimalResolution>,
|
||||||
#[get = "pub"]
|
|
||||||
#[set = "pub"]
|
|
||||||
#[get_mut = "pub"]
|
|
||||||
/// The HDCP level of the variant stream.
|
|
||||||
hdcp_level: Option<HdcpLevel>,
|
hdcp_level: Option<HdcpLevel>,
|
||||||
#[get = "pub"]
|
|
||||||
#[set = "pub"]
|
|
||||||
#[get_mut = "pub"]
|
|
||||||
/// The group identifier for the video in the variant stream.
|
|
||||||
video: Option<String>,
|
video: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,7 +37,160 @@ impl ExtXIFrameStreamInf {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The optimal pixel resolution at which to display all the video in the variant stream.
|
/// Returns the URI, that identifies the associated media playlist.
|
||||||
|
///
|
||||||
|
/// # Example
|
||||||
|
/// ```
|
||||||
|
/// # use hls_m3u8::tags::ExtXIFrameStreamInf;
|
||||||
|
/// #
|
||||||
|
/// let stream = ExtXIFrameStreamInf::new("https://www.example.com", 20);
|
||||||
|
/// assert_eq!(stream.uri(), &"https://www.example.com".to_string());
|
||||||
|
/// ```
|
||||||
|
pub const fn uri(&self) -> &String {
|
||||||
|
&self.uri
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sets the URI, that identifies the associated media playlist.
|
||||||
|
///
|
||||||
|
/// # Example
|
||||||
|
/// ```
|
||||||
|
/// # use hls_m3u8::tags::ExtXIFrameStreamInf;
|
||||||
|
/// #
|
||||||
|
/// let mut stream = ExtXIFrameStreamInf::new("https://www.example.com", 20);
|
||||||
|
///
|
||||||
|
/// stream.set_uri("../new/uri");
|
||||||
|
/// assert_eq!(stream.uri(), &"../new/uri".to_string());
|
||||||
|
/// ```
|
||||||
|
pub fn set_uri<T: ToString>(&mut self, value: T) -> &mut Self {
|
||||||
|
self.uri = value.to_string();
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the peak segment bit rate of the variant stream.
|
||||||
|
///
|
||||||
|
/// # Example
|
||||||
|
/// ```
|
||||||
|
/// # use hls_m3u8::tags::ExtXIFrameStreamInf;
|
||||||
|
/// #
|
||||||
|
/// let stream = ExtXIFrameStreamInf::new("https://www.example.com", 20);
|
||||||
|
/// assert_eq!(stream.bandwidth(), 20);
|
||||||
|
/// ```
|
||||||
|
pub const fn bandwidth(&self) -> u64 {
|
||||||
|
self.bandwidth
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sets the group identifier for the video in the variant stream.
|
||||||
|
///
|
||||||
|
/// # Example
|
||||||
|
/// ```
|
||||||
|
/// # use hls_m3u8::tags::ExtXIFrameStreamInf;
|
||||||
|
/// #
|
||||||
|
/// let mut stream = ExtXIFrameStreamInf::new("https://www.example.com", 20);
|
||||||
|
///
|
||||||
|
/// stream.set_video(Some("video"));
|
||||||
|
/// assert_eq!(stream.video(), &Some("video".to_string()));
|
||||||
|
/// ```
|
||||||
|
pub fn set_video<T: ToString>(&mut self, value: Option<T>) -> &mut Self {
|
||||||
|
self.video = value.map(|v| v.to_string());
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the group identifier for the video in the variant stream.
|
||||||
|
///
|
||||||
|
/// # Example
|
||||||
|
/// ```
|
||||||
|
/// # use hls_m3u8::tags::ExtXIFrameStreamInf;
|
||||||
|
/// #
|
||||||
|
/// let stream = ExtXIFrameStreamInf::new("https://www.example.com", 20);
|
||||||
|
/// assert_eq!(stream.video(), &None);
|
||||||
|
/// ```
|
||||||
|
pub const fn video(&self) -> &Option<String> {
|
||||||
|
&self.video
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sets the peak segment bit rate of the variant stream.
|
||||||
|
///
|
||||||
|
/// # Example
|
||||||
|
/// ```
|
||||||
|
/// # use hls_m3u8::tags::ExtXIFrameStreamInf;
|
||||||
|
/// #
|
||||||
|
/// let mut stream = ExtXIFrameStreamInf::new("https://www.example.com", 20);
|
||||||
|
///
|
||||||
|
/// stream.set_bandwidth(5);
|
||||||
|
/// assert_eq!(stream.bandwidth(), 5);
|
||||||
|
/// ```
|
||||||
|
pub fn set_bandwidth(&mut self, value: u64) -> &mut Self {
|
||||||
|
self.bandwidth = value;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the average segment bit rate of the variant stream.
|
||||||
|
///
|
||||||
|
/// # Example
|
||||||
|
/// ```
|
||||||
|
/// # use hls_m3u8::tags::ExtXIFrameStreamInf;
|
||||||
|
/// #
|
||||||
|
/// let stream = ExtXIFrameStreamInf::new("https://www.example.com", 20);
|
||||||
|
/// assert_eq!(stream.average_bandwidth(), None);
|
||||||
|
/// ```
|
||||||
|
pub const fn average_bandwidth(&self) -> Option<u64> {
|
||||||
|
self.average_bandwidth
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sets the average segment bit rate of the variant stream.
|
||||||
|
///
|
||||||
|
/// # Example
|
||||||
|
/// ```
|
||||||
|
/// # use hls_m3u8::tags::ExtXIFrameStreamInf;
|
||||||
|
/// #
|
||||||
|
/// let mut stream = ExtXIFrameStreamInf::new("https://www.example.com", 20);
|
||||||
|
///
|
||||||
|
/// stream.set_average_bandwidth(Some(300));
|
||||||
|
/// assert_eq!(stream.average_bandwidth(), Some(300));
|
||||||
|
/// ```
|
||||||
|
pub fn set_average_bandwidth(&mut self, value: Option<u64>) -> &mut Self {
|
||||||
|
self.average_bandwidth = value;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A string that represents the list of codec types contained the variant stream.
|
||||||
|
///
|
||||||
|
/// # Example
|
||||||
|
/// ```
|
||||||
|
/// # use hls_m3u8::tags::ExtXIFrameStreamInf;
|
||||||
|
/// #
|
||||||
|
/// let stream = ExtXIFrameStreamInf::new("https://www.example.com", 20);
|
||||||
|
/// assert_eq!(stream.codecs(), &None);
|
||||||
|
/// ```
|
||||||
|
pub const fn codecs(&self) -> &Option<String> {
|
||||||
|
&self.codecs
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A string that represents the list of codec types contained the variant stream.
|
||||||
|
///
|
||||||
|
/// # Example
|
||||||
|
/// ```
|
||||||
|
/// # use hls_m3u8::tags::ExtXIFrameStreamInf;
|
||||||
|
/// #
|
||||||
|
/// let mut stream = ExtXIFrameStreamInf::new("https://www.example.com", 20);
|
||||||
|
///
|
||||||
|
/// stream.set_uri("../new/uri");
|
||||||
|
/// assert_eq!(stream.uri(), &"../new/uri".to_string());
|
||||||
|
/// ```
|
||||||
|
pub fn set_codecs<T: ToString>(&mut self, value: Option<T>) -> &mut Self {
|
||||||
|
self.codecs = value.map(|v| v.to_string());
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the resolution of the stream.
|
||||||
|
///
|
||||||
|
/// # Example
|
||||||
|
/// ```
|
||||||
|
/// # use hls_m3u8::tags::ExtXIFrameStreamInf;
|
||||||
|
/// #
|
||||||
|
/// let stream = ExtXIFrameStreamInf::new("https://www.example.com", 20);
|
||||||
|
/// assert_eq!(stream.resolution(), None);
|
||||||
|
/// ```
|
||||||
pub fn resolution(&self) -> Option<(usize, usize)> {
|
pub fn resolution(&self) -> Option<(usize, usize)> {
|
||||||
if let Some(res) = &self.resolution {
|
if let Some(res) = &self.resolution {
|
||||||
Some((res.width(), res.height()))
|
Some((res.width(), res.height()))
|
||||||
|
@ -73,7 +199,17 @@ impl ExtXIFrameStreamInf {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets the optimal pixel resolution at which to display all the video in the variant stream.
|
/// Sets the resolution of the stream.
|
||||||
|
///
|
||||||
|
/// # Example
|
||||||
|
/// ```
|
||||||
|
/// # use hls_m3u8::tags::ExtXIFrameStreamInf;
|
||||||
|
/// #
|
||||||
|
/// let mut stream = ExtXIFrameStreamInf::new("https://www.example.com", 20);
|
||||||
|
///
|
||||||
|
/// stream.set_resolution(1920, 1080);
|
||||||
|
/// assert_eq!(stream.resolution(), Some((1920, 1080)));
|
||||||
|
/// ```
|
||||||
pub fn set_resolution(&mut self, width: usize, height: usize) -> &mut Self {
|
pub fn set_resolution(&mut self, width: usize, height: usize) -> &mut Self {
|
||||||
if let Some(res) = &mut self.resolution {
|
if let Some(res) = &mut self.resolution {
|
||||||
res.set_width(width);
|
res.set_width(width);
|
||||||
|
@ -83,6 +219,36 @@ impl ExtXIFrameStreamInf {
|
||||||
}
|
}
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The HDCP level of the variant stream.
|
||||||
|
///
|
||||||
|
/// # Example
|
||||||
|
/// ```
|
||||||
|
/// # use hls_m3u8::tags::ExtXIFrameStreamInf;
|
||||||
|
/// #
|
||||||
|
/// let stream = ExtXIFrameStreamInf::new("https://www.example.com", 20);
|
||||||
|
/// assert_eq!(stream.uri(), &"https://www.example.com".to_string());
|
||||||
|
/// ```
|
||||||
|
pub const fn hdcp_level(&self) -> Option<HdcpLevel> {
|
||||||
|
self.hdcp_level
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The HDCP level of the variant stream.
|
||||||
|
///
|
||||||
|
/// # Example
|
||||||
|
/// ```
|
||||||
|
/// # use hls_m3u8::tags::ExtXIFrameStreamInf;
|
||||||
|
/// #
|
||||||
|
/// let mut stream = ExtXIFrameStreamInf::new("https://www.example.com", 20);
|
||||||
|
///
|
||||||
|
/// stream.set_uri("../new/uri");
|
||||||
|
/// assert_eq!(stream.uri(), &"../new/uri".to_string());
|
||||||
|
/// ```
|
||||||
|
pub fn set_hdcp_level<T: Into<HdcpLevel>>(&mut self, value: Option<T>) -> &mut Self {
|
||||||
|
self.hdcp_level = value.map(|v| v.into());
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns the protocol compatibility version that this tag requires.
|
/// Returns the protocol compatibility version that this tag requires.
|
||||||
pub const fn requires_version(&self) -> ProtocolVersion {
|
pub const fn requires_version(&self) -> ProtocolVersion {
|
||||||
ProtocolVersion::V1
|
ProtocolVersion::V1
|
||||||
|
@ -179,7 +345,7 @@ mod test {
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(i_frame_stream_inf.uri(), "foo");
|
assert_eq!(i_frame_stream_inf.uri(), "foo");
|
||||||
assert_eq!(*i_frame_stream_inf.bandwidth(), 1000);
|
assert_eq!(i_frame_stream_inf.bandwidth(), 1000);
|
||||||
// TODO: test all the optional fields
|
// TODO: test all the optional fields
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,45 +1,64 @@
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
use getset::{Getters, MutGetters, Setters};
|
use derive_builder::Builder;
|
||||||
|
|
||||||
use crate::attribute::AttributePairs;
|
use crate::attribute::AttributePairs;
|
||||||
use crate::types::ProtocolVersion;
|
use crate::types::ProtocolVersion;
|
||||||
use crate::utils::{quote, tag, unquote};
|
use crate::utils::{quote, tag, unquote};
|
||||||
use crate::Error;
|
use crate::Error;
|
||||||
|
|
||||||
/// Session data.
|
/// The data of an [ExtXSessionData] tag.
|
||||||
///
|
#[derive(Hash, Eq, Ord, Debug, PartialEq, Clone, PartialOrd)]
|
||||||
/// See: [4.3.4.4. EXT-X-SESSION-DATA]
|
|
||||||
///
|
|
||||||
/// [4.3.4.4. EXT-X-SESSION-DATA]: https://tools.ietf.org/html/rfc8216#section-4.3.4.4
|
|
||||||
#[allow(missing_docs)]
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
|
||||||
pub enum SessionData {
|
pub enum SessionData {
|
||||||
|
/// A String, that contains the data identified by [data_id](ExtXSessionData::data_id).
|
||||||
|
/// If a [language](ExtXSessionData::language) is specified, the value should
|
||||||
|
/// contain a human-readable string written in the specified language.
|
||||||
Value(String),
|
Value(String),
|
||||||
|
/// An [uri], which points to a [json].
|
||||||
|
///
|
||||||
|
/// [json]: https://tools.ietf.org/html/rfc8259
|
||||||
|
/// [uri]: https://tools.ietf.org/html/rfc3986
|
||||||
Uri(String),
|
Uri(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// [4.3.4.4. EXT-X-SESSION-DATA]
|
/// [4.3.4.4. EXT-X-SESSION-DATA]
|
||||||
///
|
///
|
||||||
|
/// The [ExtXSessionData] tag allows arbitrary session data to be
|
||||||
|
/// carried in a [Master Playlist](crate::MasterPlaylist).
|
||||||
|
///
|
||||||
/// [4.3.4.4. EXT-X-SESSION-DATA]: https://tools.ietf.org/html/rfc8216#section-4.3.4.4
|
/// [4.3.4.4. EXT-X-SESSION-DATA]: https://tools.ietf.org/html/rfc8216#section-4.3.4.4
|
||||||
#[derive(Getters, MutGetters, Setters, Debug, Clone, PartialEq, Eq, Hash)]
|
#[derive(Builder, Hash, Eq, Ord, Debug, PartialEq, Clone, PartialOrd)]
|
||||||
#[get = "pub"]
|
#[builder(setter(into))]
|
||||||
#[set = "pub"]
|
|
||||||
#[get_mut = "pub"]
|
|
||||||
pub struct ExtXSessionData {
|
pub struct ExtXSessionData {
|
||||||
/// The identifier of the data.
|
/// The identifier of the data. For more information look [here](ExtXSessionData::set_data_id).
|
||||||
|
/// # Note
|
||||||
|
/// This field is required.
|
||||||
data_id: String,
|
data_id: String,
|
||||||
/// The session data.
|
/// The data associated with the [data_id](ExtXSessionDataBuilder::data_id).
|
||||||
|
/// For more information look [here](SessionData).
|
||||||
|
/// # Note
|
||||||
|
/// This field is required.
|
||||||
data: SessionData,
|
data: SessionData,
|
||||||
/// The language of the data.
|
/// The language of the [data](ExtXSessionDataBuilder::data).
|
||||||
|
#[builder(setter(into, strip_option), default)]
|
||||||
language: Option<String>,
|
language: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ExtXSessionData {
|
impl ExtXSessionData {
|
||||||
pub(crate) const PREFIX: &'static str = "#EXT-X-SESSION-DATA:";
|
pub(crate) const PREFIX: &'static str = "#EXT-X-SESSION-DATA:";
|
||||||
|
|
||||||
/// Makes a new `ExtXSessionData` tag.
|
/// Makes a new [ExtXSessionData] tag.
|
||||||
|
///
|
||||||
|
/// # Example
|
||||||
|
/// ```
|
||||||
|
/// use hls_m3u8::tags::{ExtXSessionData, SessionData};
|
||||||
|
///
|
||||||
|
/// ExtXSessionData::new(
|
||||||
|
/// "com.example.movie.title",
|
||||||
|
/// SessionData::Uri("https://www.example.com/".to_string())
|
||||||
|
/// );
|
||||||
|
/// ```
|
||||||
pub fn new<T: ToString>(data_id: T, data: SessionData) -> Self {
|
pub fn new<T: ToString>(data_id: T, data: SessionData) -> Self {
|
||||||
ExtXSessionData {
|
ExtXSessionData {
|
||||||
data_id: data_id.to_string(),
|
data_id: data_id.to_string(),
|
||||||
|
@ -48,7 +67,44 @@ impl ExtXSessionData {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Makes a new `ExtXSessionData` with the given language.
|
/// Returns a new Builder for [ExtXSessionData].
|
||||||
|
///
|
||||||
|
/// # Example
|
||||||
|
/// ```
|
||||||
|
/// use hls_m3u8::tags::{ExtXSessionData, SessionData};
|
||||||
|
///
|
||||||
|
/// let session_data = ExtXSessionData::builder()
|
||||||
|
/// .data_id("com.example.movie.title")
|
||||||
|
/// .data(SessionData::Value("some data".to_string()))
|
||||||
|
/// .language("english")
|
||||||
|
/// .build()
|
||||||
|
/// .expect("Failed to build an ExtXSessionData tag.");
|
||||||
|
///
|
||||||
|
/// assert_eq!(
|
||||||
|
/// session_data,
|
||||||
|
/// ExtXSessionData::with_language(
|
||||||
|
/// "com.example.movie.title",
|
||||||
|
/// SessionData::Value("some data".to_string()),
|
||||||
|
/// "english"
|
||||||
|
/// )
|
||||||
|
/// );
|
||||||
|
/// ```
|
||||||
|
pub fn builder() -> ExtXSessionDataBuilder {
|
||||||
|
ExtXSessionDataBuilder::default()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Makes a new [ExtXSessionData] tag, with the given language.
|
||||||
|
///
|
||||||
|
/// # Example
|
||||||
|
/// ```
|
||||||
|
/// use hls_m3u8::tags::{ExtXSessionData, SessionData};
|
||||||
|
///
|
||||||
|
/// let session_data = ExtXSessionData::with_language(
|
||||||
|
/// "com.example.movie.title",
|
||||||
|
/// SessionData::Value("some data".to_string()),
|
||||||
|
/// "english"
|
||||||
|
/// );
|
||||||
|
/// ```
|
||||||
pub fn with_language<T: ToString>(data_id: T, data: SessionData, language: T) -> Self {
|
pub fn with_language<T: ToString>(data_id: T, data: SessionData, language: T) -> Self {
|
||||||
ExtXSessionData {
|
ExtXSessionData {
|
||||||
data_id: data_id.to_string(),
|
data_id: data_id.to_string(),
|
||||||
|
@ -57,7 +113,147 @@ impl ExtXSessionData {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the protocol compatibility version that this tag requires.
|
/// Returns the `data_id`, that identifies a `data_value`.
|
||||||
|
///
|
||||||
|
/// # Example
|
||||||
|
/// ```
|
||||||
|
/// # use hls_m3u8::tags::{ExtXSessionData, SessionData};
|
||||||
|
/// #
|
||||||
|
/// let data = ExtXSessionData::new(
|
||||||
|
/// "com.example.movie.title",
|
||||||
|
/// SessionData::Value("some data".to_string())
|
||||||
|
/// );
|
||||||
|
///
|
||||||
|
/// assert_eq!(
|
||||||
|
/// data.data_id(),
|
||||||
|
/// &"com.example.movie.title".to_string()
|
||||||
|
/// )
|
||||||
|
/// ```
|
||||||
|
pub const fn data_id(&self) -> &String {
|
||||||
|
&self.data_id
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the `data`.
|
||||||
|
///
|
||||||
|
/// # Example
|
||||||
|
/// ```
|
||||||
|
/// # use hls_m3u8::tags::{ExtXSessionData, SessionData};
|
||||||
|
/// #
|
||||||
|
/// let data = ExtXSessionData::new(
|
||||||
|
/// "com.example.movie.title",
|
||||||
|
/// SessionData::Value("some data".to_string())
|
||||||
|
/// );
|
||||||
|
///
|
||||||
|
/// assert_eq!(
|
||||||
|
/// data.data(),
|
||||||
|
/// &SessionData::Value("some data".to_string())
|
||||||
|
/// )
|
||||||
|
/// ```
|
||||||
|
pub const fn data(&self) -> &SessionData {
|
||||||
|
&self.data
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the `language` tag, that identifies the language of [SessionData].
|
||||||
|
///
|
||||||
|
/// # Example
|
||||||
|
/// ```
|
||||||
|
/// # use hls_m3u8::tags::{ExtXSessionData, SessionData};
|
||||||
|
/// #
|
||||||
|
/// let data = ExtXSessionData::with_language(
|
||||||
|
/// "com.example.movie.title",
|
||||||
|
/// SessionData::Value("some data".to_string()),
|
||||||
|
/// "english"
|
||||||
|
/// );
|
||||||
|
///
|
||||||
|
/// assert_eq!(
|
||||||
|
/// data.language(),
|
||||||
|
/// &Some("english".to_string())
|
||||||
|
/// )
|
||||||
|
/// ```
|
||||||
|
pub const fn language(&self) -> &Option<String> {
|
||||||
|
&self.language
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sets the `language` attribute, that identifies the language of [SessionData].
|
||||||
|
/// See [rfc5646](https://tools.ietf.org/html/rfc5646).
|
||||||
|
///
|
||||||
|
/// # Example
|
||||||
|
/// ```
|
||||||
|
/// # use hls_m3u8::tags::{ExtXSessionData, SessionData};
|
||||||
|
/// #
|
||||||
|
/// let mut data = ExtXSessionData::new(
|
||||||
|
/// "com.example.movie.title",
|
||||||
|
/// SessionData::Value("some data".to_string()),
|
||||||
|
/// );
|
||||||
|
///
|
||||||
|
/// assert_eq!(data.language(), &None);
|
||||||
|
///
|
||||||
|
/// data.set_language(Some("english"));
|
||||||
|
/// assert_eq!(data.language(), &Some("english".to_string()));
|
||||||
|
/// ```
|
||||||
|
pub fn set_language<T: ToString>(&mut self, value: Option<T>) -> &mut Self {
|
||||||
|
self.language = value.map(|v| v.to_string());
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sets the `data_id` attribute, that should conform to a [reverse DNS] naming convention,
|
||||||
|
/// such as `com.example.movie.title`.
|
||||||
|
///
|
||||||
|
/// # Note:
|
||||||
|
/// There is no central registration authority, so a value
|
||||||
|
/// should be choosen, that is unlikely to collide with others.
|
||||||
|
///
|
||||||
|
/// # Example
|
||||||
|
/// ```
|
||||||
|
/// # use hls_m3u8::tags::{ExtXSessionData, SessionData};
|
||||||
|
/// #
|
||||||
|
/// let mut data = ExtXSessionData::new(
|
||||||
|
/// "com.example.movie.title",
|
||||||
|
/// SessionData::Value("some data".to_string()),
|
||||||
|
/// );
|
||||||
|
///
|
||||||
|
/// assert_eq!(data.data_id(), &"com.example.movie.title".to_string());
|
||||||
|
///
|
||||||
|
/// data.set_data_id("com.other.movie.title");
|
||||||
|
/// assert_eq!(data.data_id(), &"com.other.movie.title".to_string());
|
||||||
|
/// ```
|
||||||
|
/// [reverse DNS]: https://en.wikipedia.org/wiki/Reverse_domain_name_notation
|
||||||
|
pub fn set_data_id<T: ToString>(&mut self, value: T) -> &mut Self {
|
||||||
|
self.data_id = value.to_string();
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sets the [data](ExtXSessionData::data) of this tag.
|
||||||
|
///
|
||||||
|
/// # Example
|
||||||
|
/// ```
|
||||||
|
/// # use hls_m3u8::tags::{ExtXSessionData, SessionData};
|
||||||
|
/// #
|
||||||
|
/// let mut data = ExtXSessionData::new(
|
||||||
|
/// "com.example.movie.title",
|
||||||
|
/// SessionData::Value("some data".to_string()),
|
||||||
|
/// );
|
||||||
|
///
|
||||||
|
/// assert_eq!(data.data(), &SessionData::Value("some data".to_string()));
|
||||||
|
///
|
||||||
|
/// data.set_data(SessionData::Value("new data".to_string()));
|
||||||
|
/// assert_eq!(data.data(), &SessionData::Value("new data".to_string()));
|
||||||
|
/// ```
|
||||||
|
pub fn set_data(&mut self, value: SessionData) -> &mut Self {
|
||||||
|
self.data = value;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the protocol compatibility version, that this tag requires.
|
||||||
|
///
|
||||||
|
/// # 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 {
|
pub const fn requires_version(&self) -> ProtocolVersion {
|
||||||
ProtocolVersion::V1
|
ProtocolVersion::V1
|
||||||
}
|
}
|
||||||
|
@ -106,7 +302,7 @@ impl FromStr for ExtXSessionData {
|
||||||
let data = {
|
let data = {
|
||||||
if let Some(value) = session_value {
|
if let Some(value) = session_value {
|
||||||
if uri.is_some() {
|
if uri.is_some() {
|
||||||
return Err(Error::invalid_input());
|
return Err(Error::custom("Unexpected URI"));
|
||||||
} else {
|
} else {
|
||||||
SessionData::Value(value)
|
SessionData::Value(value)
|
||||||
}
|
}
|
||||||
|
@ -146,6 +342,46 @@ mod test {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_parser() {
|
fn test_parser() {
|
||||||
|
let tag = "#EXT-X-SESSION-DATA:DATA-ID=\"com.example.lyrics\",URI=\"lyrics.json\""
|
||||||
|
.parse::<ExtXSessionData>()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
tag,
|
||||||
|
ExtXSessionData::new(
|
||||||
|
"com.example.lyrics",
|
||||||
|
SessionData::Uri("lyrics.json".to_string())
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
let tag = "#EXT-X-SESSION-DATA:DATA-ID=\"com.example.title\",\
|
||||||
|
LANGUAGE=\"en\", VALUE=\"This is an example\""
|
||||||
|
.parse::<ExtXSessionData>()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
tag,
|
||||||
|
ExtXSessionData::with_language(
|
||||||
|
"com.example.title",
|
||||||
|
SessionData::Value("This is an example".to_string()),
|
||||||
|
"en"
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
let tag = "#EXT-X-SESSION-DATA:DATA-ID=\"com.example.title\",\
|
||||||
|
LANGUAGE=\"es\", VALUE=\"Este es un ejemplo\""
|
||||||
|
.parse::<ExtXSessionData>()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
tag,
|
||||||
|
ExtXSessionData::with_language(
|
||||||
|
"com.example.title",
|
||||||
|
SessionData::Value("Este es un ejemplo".to_string()),
|
||||||
|
"es"
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
let tag = ExtXSessionData::new("foo", SessionData::Value("bar".into()));
|
let tag = ExtXSessionData::new("foo", SessionData::Value("bar".into()));
|
||||||
let text = r#"#EXT-X-SESSION-DATA:DATA-ID="foo",VALUE="bar""#;
|
let text = r#"#EXT-X-SESSION-DATA:DATA-ID="foo",VALUE="bar""#;
|
||||||
assert_eq!(text.parse::<ExtXSessionData>().unwrap(), tag);
|
assert_eq!(text.parse::<ExtXSessionData>().unwrap(), tag);
|
||||||
|
@ -158,10 +394,4 @@ mod test {
|
||||||
let text = r#"#EXT-X-SESSION-DATA:DATA-ID="foo",VALUE="bar",LANGUAGE="baz""#;
|
let text = r#"#EXT-X-SESSION-DATA:DATA-ID="foo",VALUE="bar",LANGUAGE="baz""#;
|
||||||
assert_eq!(text.parse::<ExtXSessionData>().unwrap(), tag);
|
assert_eq!(text.parse::<ExtXSessionData>().unwrap(), tag);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_requires_version() {
|
|
||||||
let tag = ExtXSessionData::new("foo", SessionData::Value("bar".into()));
|
|
||||||
assert_eq!(tag.requires_version(), ProtocolVersion::V1);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,8 +2,6 @@ use std::fmt;
|
||||||
use std::ops::{Deref, DerefMut};
|
use std::ops::{Deref, DerefMut};
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
use url::Url;
|
|
||||||
|
|
||||||
use crate::types::{DecryptionKey, EncryptionMethod, ProtocolVersion};
|
use crate::types::{DecryptionKey, EncryptionMethod, ProtocolVersion};
|
||||||
use crate::utils::tag;
|
use crate::utils::tag;
|
||||||
use crate::Error;
|
use crate::Error;
|
||||||
|
@ -20,7 +18,7 @@ impl ExtXSessionKey {
|
||||||
/// Makes a new [ExtXSessionKey] tag.
|
/// Makes a new [ExtXSessionKey] tag.
|
||||||
/// # Panic
|
/// # Panic
|
||||||
/// This method will panic, if the [EncryptionMethod] is None.
|
/// This method will panic, if the [EncryptionMethod] is None.
|
||||||
pub fn new(method: EncryptionMethod, uri: Url) -> Self {
|
pub fn new<T: ToString>(method: EncryptionMethod, uri: T) -> Self {
|
||||||
if method == EncryptionMethod::None {
|
if method == EncryptionMethod::None {
|
||||||
panic!("The EncryptionMethod is not allowed to be None");
|
panic!("The EncryptionMethod is not allowed to be None");
|
||||||
}
|
}
|
||||||
|
@ -36,7 +34,7 @@ impl ExtXSessionKey {
|
||||||
///
|
///
|
||||||
/// let mut key = ExtXSessionKey::new(
|
/// let mut key = ExtXSessionKey::new(
|
||||||
/// EncryptionMethod::Aes128,
|
/// EncryptionMethod::Aes128,
|
||||||
/// "https://www.example.com".parse().unwrap()
|
/// "https://www.example.com/"
|
||||||
/// );
|
/// );
|
||||||
///
|
///
|
||||||
/// assert_eq!(
|
/// assert_eq!(
|
||||||
|
@ -93,7 +91,7 @@ mod test {
|
||||||
fn test_display() {
|
fn test_display() {
|
||||||
let mut key = ExtXSessionKey::new(
|
let mut key = ExtXSessionKey::new(
|
||||||
EncryptionMethod::Aes128,
|
EncryptionMethod::Aes128,
|
||||||
"https://www.example.com/hls-key/key.bin".parse().unwrap(),
|
"https://www.example.com/hls-key/key.bin",
|
||||||
);
|
);
|
||||||
key.set_iv([
|
key.set_iv([
|
||||||
16, 239, 143, 117, 140, 165, 85, 17, 85, 132, 187, 91, 60, 104, 127, 82,
|
16, 239, 143, 117, 140, 165, 85, 17, 85, 132, 187, 91, 60, 104, 127, 82,
|
||||||
|
@ -116,13 +114,13 @@ mod test {
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
ExtXSessionKey::new(
|
ExtXSessionKey::new(
|
||||||
EncryptionMethod::Aes128,
|
EncryptionMethod::Aes128,
|
||||||
"https://priv.example.com/key.php?r=52".parse().unwrap()
|
"https://priv.example.com/key.php?r=52"
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut key = ExtXSessionKey::new(
|
let mut key = ExtXSessionKey::new(
|
||||||
EncryptionMethod::Aes128,
|
EncryptionMethod::Aes128,
|
||||||
"https://www.example.com/hls-key/key.bin".parse().unwrap(),
|
"https://www.example.com/hls-key/key.bin",
|
||||||
);
|
);
|
||||||
key.set_iv([
|
key.set_iv([
|
||||||
16, 239, 143, 117, 140, 165, 85, 17, 85, 132, 187, 91, 60, 104, 127, 82,
|
16, 239, 143, 117, 140, 165, 85, 17, 85, 132, 187, 91, 60, 104, 127, 82,
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
use url::Url;
|
|
||||||
|
|
||||||
use crate::attribute::AttributePairs;
|
use crate::attribute::AttributePairs;
|
||||||
use crate::types::{
|
use crate::types::{
|
||||||
ClosedCaptions, DecimalFloatingPoint, DecimalResolution, HdcpLevel, ProtocolVersion,
|
ClosedCaptions, DecimalFloatingPoint, DecimalResolution, HdcpLevel, ProtocolVersion,
|
||||||
|
@ -15,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
|
/// [4.3.4.2. EXT-X-STREAM-INF]: https://tools.ietf.org/html/rfc8216#section-4.3.4.2
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
pub struct ExtXStreamInf {
|
pub struct ExtXStreamInf {
|
||||||
uri: Url,
|
uri: String,
|
||||||
bandwidth: u64,
|
bandwidth: u64,
|
||||||
average_bandwidth: Option<u64>,
|
average_bandwidth: Option<u64>,
|
||||||
codecs: Option<String>,
|
codecs: Option<String>,
|
||||||
|
@ -32,9 +30,9 @@ 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.
|
/// Makes a new `ExtXStreamInf` tag.
|
||||||
pub const fn new(uri: Url, bandwidth: u64) -> Self {
|
pub fn new<T: ToString>(uri: T, bandwidth: u64) -> Self {
|
||||||
ExtXStreamInf {
|
ExtXStreamInf {
|
||||||
uri,
|
uri: uri.to_string(),
|
||||||
bandwidth,
|
bandwidth,
|
||||||
average_bandwidth: None,
|
average_bandwidth: None,
|
||||||
codecs: None,
|
codecs: None,
|
||||||
|
@ -49,7 +47,7 @@ impl ExtXStreamInf {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the URI that identifies the associated media playlist.
|
/// Returns the URI that identifies the associated media playlist.
|
||||||
pub const fn uri(&self) -> &Url {
|
pub const fn uri(&self) -> &String {
|
||||||
&self.uri
|
&self.uri
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -193,7 +191,7 @@ impl FromStr for ExtXStreamInf {
|
||||||
let bandwidth = bandwidth.ok_or(Error::missing_value("EXT-X-BANDWIDTH"))?;
|
let bandwidth = bandwidth.ok_or(Error::missing_value("EXT-X-BANDWIDTH"))?;
|
||||||
|
|
||||||
Ok(ExtXStreamInf {
|
Ok(ExtXStreamInf {
|
||||||
uri: uri.parse()?,
|
uri: uri.to_string(),
|
||||||
bandwidth,
|
bandwidth,
|
||||||
average_bandwidth,
|
average_bandwidth,
|
||||||
codecs,
|
codecs,
|
||||||
|
@ -220,7 +218,7 @@ mod test {
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
stream_inf,
|
stream_inf,
|
||||||
ExtXStreamInf::new("http://www.example.com".parse().unwrap(), 1000)
|
ExtXStreamInf::new("http://www.example.com", 1000)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -228,14 +226,14 @@ mod test {
|
||||||
fn test_requires_version() {
|
fn test_requires_version() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
ProtocolVersion::V1,
|
ProtocolVersion::V1,
|
||||||
ExtXStreamInf::new("http://www.example.com".parse().unwrap(), 1000).requires_version()
|
ExtXStreamInf::new("http://www.example.com", 1000).requires_version()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_display() {
|
fn test_display() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
ExtXStreamInf::new("http://www.example.com".parse().unwrap(), 1000).to_string(),
|
ExtXStreamInf::new("http://www.example.com/", 1000).to_string(),
|
||||||
"#EXT-X-STREAM-INF:BANDWIDTH=1000\nhttp://www.example.com/".to_string()
|
"#EXT-X-STREAM-INF:BANDWIDTH=1000\nhttp://www.example.com/".to_string()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -114,7 +114,7 @@ mod test {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_parse() {
|
fn test_parser() {
|
||||||
let byte_range = ExtXByteRange::new(99999, Some(2));
|
let byte_range = ExtXByteRange::new(99999, Some(2));
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
byte_range,
|
byte_range,
|
||||||
|
@ -132,7 +132,7 @@ mod test {
|
||||||
fn test_deref() {
|
fn test_deref() {
|
||||||
let byte_range = ExtXByteRange::new(0, Some(22));
|
let byte_range = ExtXByteRange::new(0, Some(22));
|
||||||
|
|
||||||
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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,6 @@ use std::str::FromStr;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
use chrono::{DateTime, FixedOffset};
|
use chrono::{DateTime, FixedOffset};
|
||||||
use getset::{Getters, MutGetters, Setters};
|
|
||||||
|
|
||||||
use crate::attribute::AttributePairs;
|
use crate::attribute::AttributePairs;
|
||||||
use crate::types::{DecimalFloatingPoint, ProtocolVersion};
|
use crate::types::{DecimalFloatingPoint, ProtocolVersion};
|
||||||
|
@ -17,10 +16,7 @@ use crate::Error;
|
||||||
///
|
///
|
||||||
/// TODO: Implement properly
|
/// TODO: Implement properly
|
||||||
#[allow(missing_docs)]
|
#[allow(missing_docs)]
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Hash, Getters, MutGetters, Setters)]
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||||
#[get = "pub"]
|
|
||||||
#[set = "pub"]
|
|
||||||
#[get_mut = "pub"]
|
|
||||||
pub struct ExtXDateRange {
|
pub struct ExtXDateRange {
|
||||||
/// A string that uniquely identifies a Date Range in the Playlist.
|
/// A string that uniquely identifies a Date Range in the Playlist.
|
||||||
/// This attribute is REQUIRED.
|
/// This attribute is REQUIRED.
|
||||||
|
|
|
@ -2,8 +2,6 @@ use std::fmt;
|
||||||
use std::ops::{Deref, DerefMut};
|
use std::ops::{Deref, DerefMut};
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
use url::Url;
|
|
||||||
|
|
||||||
use crate::types::{DecryptionKey, EncryptionMethod};
|
use crate::types::{DecryptionKey, EncryptionMethod};
|
||||||
use crate::utils::tag;
|
use crate::utils::tag;
|
||||||
use crate::Error;
|
use crate::Error;
|
||||||
|
@ -22,14 +20,12 @@ impl ExtXKey {
|
||||||
/// Makes a new `ExtXKey` tag.
|
/// Makes a new `ExtXKey` tag.
|
||||||
/// # Example
|
/// # Example
|
||||||
/// ```
|
/// ```
|
||||||
/// use url::Url;
|
|
||||||
///
|
|
||||||
/// use hls_m3u8::tags::ExtXKey;
|
/// use hls_m3u8::tags::ExtXKey;
|
||||||
/// use hls_m3u8::types::EncryptionMethod;
|
/// use hls_m3u8::types::EncryptionMethod;
|
||||||
///
|
///
|
||||||
/// let key = ExtXKey::new(
|
/// let key = ExtXKey::new(
|
||||||
/// EncryptionMethod::Aes128,
|
/// EncryptionMethod::Aes128,
|
||||||
/// "https://www.example.com".parse().unwrap()
|
/// "https://www.example.com/"
|
||||||
/// );
|
/// );
|
||||||
///
|
///
|
||||||
/// assert_eq!(
|
/// assert_eq!(
|
||||||
|
@ -37,7 +33,7 @@ impl ExtXKey {
|
||||||
/// "#EXT-X-KEY:METHOD=AES-128,URI=\"https://www.example.com/\""
|
/// "#EXT-X-KEY:METHOD=AES-128,URI=\"https://www.example.com/\""
|
||||||
/// );
|
/// );
|
||||||
/// ```
|
/// ```
|
||||||
pub const fn new(method: EncryptionMethod, uri: Url) -> Self {
|
pub fn new<T: ToString>(method: EncryptionMethod, uri: T) -> Self {
|
||||||
Self(DecryptionKey::new(method, uri))
|
Self(DecryptionKey::new(method, uri))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -128,7 +124,7 @@ mod test {
|
||||||
key.set_iv([
|
key.set_iv([
|
||||||
16, 239, 143, 117, 140, 165, 85, 17, 85, 132, 187, 91, 60, 104, 127, 82,
|
16, 239, 143, 117, 140, 165, 85, 17, 85, 132, 187, 91, 60, 104, 127, 82,
|
||||||
]);
|
]);
|
||||||
key.set_uri("https://www.example.com".parse().unwrap());
|
key.set_uri(Some("https://www.example.com"));
|
||||||
key.set_key_format_versions("1/2/3");
|
key.set_key_format_versions("1/2/3");
|
||||||
|
|
||||||
assert_eq!(key.to_string(), "#EXT-X-KEY:METHOD=NONE".to_string());
|
assert_eq!(key.to_string(), "#EXT-X-KEY:METHOD=NONE".to_string());
|
||||||
|
@ -142,13 +138,13 @@ mod test {
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
ExtXKey::new(
|
ExtXKey::new(
|
||||||
EncryptionMethod::Aes128,
|
EncryptionMethod::Aes128,
|
||||||
"https://priv.example.com/key.php?r=52".parse().unwrap()
|
"https://priv.example.com/key.php?r=52"
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut key = ExtXKey::new(
|
let mut key = ExtXKey::new(
|
||||||
EncryptionMethod::Aes128,
|
EncryptionMethod::Aes128,
|
||||||
"https://www.example.com/hls-key/key.bin".parse().unwrap(),
|
"https://www.example.com/hls-key/key.bin",
|
||||||
);
|
);
|
||||||
key.set_iv([
|
key.set_iv([
|
||||||
16, 239, 143, 117, 140, 165, 85, 17, 85, 132, 187, 91, 60, 104, 127, 82,
|
16, 239, 143, 117, 140, 165, 85, 17, 85, 132, 187, 91, 60, 104, 127, 82,
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
use getset::{Getters, MutGetters, Setters};
|
|
||||||
|
|
||||||
use crate::Error;
|
use crate::Error;
|
||||||
|
|
||||||
/// Byte range.
|
/// Byte range.
|
||||||
|
@ -10,14 +8,9 @@ use crate::Error;
|
||||||
/// See: [4.3.2.2. EXT-X-BYTERANGE]
|
/// See: [4.3.2.2. EXT-X-BYTERANGE]
|
||||||
///
|
///
|
||||||
/// [4.3.2.2. EXT-X-BYTERANGE]: https://tools.ietf.org/html/rfc8216#section-4.3.2.2
|
/// [4.3.2.2. EXT-X-BYTERANGE]: https://tools.ietf.org/html/rfc8216#section-4.3.2.2
|
||||||
#[derive(Getters, Setters, MutGetters, Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
#[derive(Copy, Hash, Eq, Ord, Debug, PartialEq, Clone, PartialOrd)]
|
||||||
#[get = "pub"]
|
|
||||||
#[set = "pub"]
|
|
||||||
#[get_mut = "pub"]
|
|
||||||
pub struct ByteRange {
|
pub struct ByteRange {
|
||||||
/// The length of the range.
|
|
||||||
length: usize,
|
length: usize,
|
||||||
/// The start of the range.
|
|
||||||
start: Option<usize>,
|
start: Option<usize>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,6 +19,60 @@ impl ByteRange {
|
||||||
pub const fn new(length: usize, start: Option<usize>) -> Self {
|
pub const fn new(length: usize, start: Option<usize>) -> Self {
|
||||||
Self { length, start }
|
Self { length, start }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the length of the range.
|
||||||
|
/// # Example
|
||||||
|
/// ```
|
||||||
|
/// # use hls_m3u8::types::ByteRange;
|
||||||
|
/// #
|
||||||
|
/// assert_eq!(ByteRange::new(20, Some(3)).length(), 20);
|
||||||
|
/// ```
|
||||||
|
pub const fn length(&self) -> usize {
|
||||||
|
self.length
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sets the length of the range.
|
||||||
|
/// # Example
|
||||||
|
/// ```
|
||||||
|
/// # use hls_m3u8::types::ByteRange;
|
||||||
|
/// #
|
||||||
|
/// let mut range = ByteRange::new(20, Some(3));
|
||||||
|
///
|
||||||
|
/// # assert_eq!(range.length(), 20);
|
||||||
|
/// range.set_length(10);
|
||||||
|
/// assert_eq!(range.length(), 10);
|
||||||
|
/// ```
|
||||||
|
pub fn set_length(&mut self, value: usize) -> &mut Self {
|
||||||
|
self.length = value;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the start of the range.
|
||||||
|
/// # Example
|
||||||
|
/// ```
|
||||||
|
/// # use hls_m3u8::types::ByteRange;
|
||||||
|
/// #
|
||||||
|
/// assert_eq!(ByteRange::new(20, Some(3)).start(), Some(3));
|
||||||
|
/// ```
|
||||||
|
pub const fn start(&self) -> Option<usize> {
|
||||||
|
self.start
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sets the start of the range.
|
||||||
|
/// # Example
|
||||||
|
/// ```
|
||||||
|
/// # use hls_m3u8::types::ByteRange;
|
||||||
|
/// #
|
||||||
|
/// let mut range = ByteRange::new(20, None);
|
||||||
|
///
|
||||||
|
/// # assert_eq!(range.start(), None);
|
||||||
|
/// range.set_start(Some(3));
|
||||||
|
/// assert_eq!(range.start(), Some(3));
|
||||||
|
/// ```
|
||||||
|
pub fn set_start(&mut self, value: Option<usize>) -> &mut Self {
|
||||||
|
self.start = value;
|
||||||
|
self
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for ByteRange {
|
impl fmt::Display for ByteRange {
|
||||||
|
@ -86,7 +133,7 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_parse() {
|
fn test_parser() {
|
||||||
let byte_range = ByteRange {
|
let byte_range = ByteRange {
|
||||||
length: 99999,
|
length: 99999,
|
||||||
start: Some(2),
|
start: Some(2),
|
||||||
|
|
|
@ -2,7 +2,6 @@ use std::fmt;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
use derive_builder::Builder;
|
use derive_builder::Builder;
|
||||||
use url::Url;
|
|
||||||
|
|
||||||
use crate::attribute::AttributePairs;
|
use crate::attribute::AttributePairs;
|
||||||
use crate::types::{EncryptionMethod, InitializationVector, ProtocolVersion};
|
use crate::types::{EncryptionMethod, InitializationVector, ProtocolVersion};
|
||||||
|
@ -14,7 +13,7 @@ use crate::Error;
|
||||||
pub struct DecryptionKey {
|
pub struct DecryptionKey {
|
||||||
pub(crate) method: EncryptionMethod,
|
pub(crate) method: EncryptionMethod,
|
||||||
#[builder(setter(into, strip_option), default)]
|
#[builder(setter(into, strip_option), default)]
|
||||||
pub(crate) uri: Option<Url>,
|
pub(crate) uri: Option<String>,
|
||||||
#[builder(setter(into, strip_option), default)]
|
#[builder(setter(into, strip_option), default)]
|
||||||
pub(crate) iv: Option<InitializationVector>,
|
pub(crate) iv: Option<InitializationVector>,
|
||||||
#[builder(setter(into, strip_option), default)]
|
#[builder(setter(into, strip_option), default)]
|
||||||
|
@ -27,13 +26,11 @@ impl DecryptionKey {
|
||||||
/// Makes a new `DecryptionKey`.
|
/// Makes a new `DecryptionKey`.
|
||||||
/// # Example
|
/// # Example
|
||||||
/// ```
|
/// ```
|
||||||
/// use url::Url;
|
|
||||||
///
|
|
||||||
/// use hls_m3u8::types::{EncryptionMethod, DecryptionKey};
|
/// use hls_m3u8::types::{EncryptionMethod, DecryptionKey};
|
||||||
///
|
///
|
||||||
/// let key = DecryptionKey::new(
|
/// let key = DecryptionKey::new(
|
||||||
/// EncryptionMethod::Aes128,
|
/// EncryptionMethod::Aes128,
|
||||||
/// "https://www.example.com".parse().unwrap()
|
/// "https://www.example.com/"
|
||||||
/// );
|
/// );
|
||||||
///
|
///
|
||||||
/// assert_eq!(
|
/// assert_eq!(
|
||||||
|
@ -41,10 +38,10 @@ impl DecryptionKey {
|
||||||
/// "METHOD=AES-128,URI=\"https://www.example.com/\""
|
/// "METHOD=AES-128,URI=\"https://www.example.com/\""
|
||||||
/// );
|
/// );
|
||||||
/// ```
|
/// ```
|
||||||
pub const fn new(method: EncryptionMethod, uri: Url) -> Self {
|
pub fn new<T: ToString>(method: EncryptionMethod, uri: T) -> Self {
|
||||||
Self {
|
Self {
|
||||||
method,
|
method,
|
||||||
uri: Some(uri),
|
uri: Some(uri.to_string()),
|
||||||
iv: None,
|
iv: None,
|
||||||
key_format: None,
|
key_format: None,
|
||||||
key_format_versions: None,
|
key_format_versions: None,
|
||||||
|
@ -58,7 +55,7 @@ impl DecryptionKey {
|
||||||
///
|
///
|
||||||
/// let key = DecryptionKey::new(
|
/// let key = DecryptionKey::new(
|
||||||
/// EncryptionMethod::Aes128,
|
/// EncryptionMethod::Aes128,
|
||||||
/// "https://www.example.com".parse().unwrap()
|
/// "https://www.example.com/"
|
||||||
/// );
|
/// );
|
||||||
///
|
///
|
||||||
/// assert_eq!(
|
/// assert_eq!(
|
||||||
|
@ -82,7 +79,7 @@ impl DecryptionKey {
|
||||||
///
|
///
|
||||||
/// let mut key = DecryptionKey::new(
|
/// let mut key = DecryptionKey::new(
|
||||||
/// EncryptionMethod::Aes128,
|
/// EncryptionMethod::Aes128,
|
||||||
/// "https://www.example.com".parse().unwrap()
|
/// "https://www.example.com/"
|
||||||
/// );
|
/// );
|
||||||
///
|
///
|
||||||
/// key.set_method(EncryptionMethod::SampleAes);
|
/// key.set_method(EncryptionMethod::SampleAes);
|
||||||
|
@ -105,39 +102,41 @@ impl DecryptionKey {
|
||||||
///
|
///
|
||||||
/// let key = DecryptionKey::new(
|
/// let key = DecryptionKey::new(
|
||||||
/// EncryptionMethod::Aes128,
|
/// EncryptionMethod::Aes128,
|
||||||
/// "https://www.example.com".parse().unwrap()
|
/// "https://www.example.com/"
|
||||||
/// );
|
/// );
|
||||||
///
|
///
|
||||||
/// assert_eq!(
|
/// assert_eq!(
|
||||||
/// key.uri(),
|
/// key.uri(),
|
||||||
/// &Some("https://www.example.com".parse().unwrap())
|
/// &Some("https://www.example.com/".to_string())
|
||||||
/// );
|
/// );
|
||||||
/// ```
|
/// ```
|
||||||
pub const fn uri(&self) -> &Option<Url> {
|
pub const fn uri(&self) -> &Option<String> {
|
||||||
&self.uri
|
&self.uri
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets the `URI` attribute.
|
/// Sets the `URI` attribute.
|
||||||
///
|
///
|
||||||
/// This attribute is required, if the [EncryptionMethod] is not None.
|
/// # Note
|
||||||
|
/// This attribute is required, if the [EncryptionMethod] is not `None`.
|
||||||
|
///
|
||||||
/// # Example
|
/// # Example
|
||||||
/// ```
|
/// ```
|
||||||
/// use hls_m3u8::types::{DecryptionKey, EncryptionMethod};
|
/// use hls_m3u8::types::{DecryptionKey, EncryptionMethod};
|
||||||
///
|
///
|
||||||
/// let mut key = DecryptionKey::new(
|
/// let mut key = DecryptionKey::new(
|
||||||
/// EncryptionMethod::Aes128,
|
/// EncryptionMethod::Aes128,
|
||||||
/// "https://www.example.com".parse().unwrap()
|
/// "https://www.example.com/"
|
||||||
/// );
|
/// );
|
||||||
///
|
///
|
||||||
/// key.set_uri("http://www.google.com".parse().unwrap());
|
/// key.set_uri(Some("http://www.google.com/"));
|
||||||
///
|
///
|
||||||
/// assert_eq!(
|
/// assert_eq!(
|
||||||
/// key.to_string(),
|
/// key.to_string(),
|
||||||
/// "METHOD=AES-128,URI=\"http://www.google.com/\"".to_string()
|
/// "METHOD=AES-128,URI=\"http://www.google.com/\"".to_string()
|
||||||
/// );
|
/// );
|
||||||
/// ```
|
/// ```
|
||||||
pub fn set_uri(&mut self, value: Url) {
|
pub fn set_uri<T: ToString>(&mut self, value: Option<T>) {
|
||||||
self.uri = Some(value);
|
self.uri = value.map(|v| v.to_string());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the IV (Initialization Vector) attribute.
|
/// Returns the IV (Initialization Vector) attribute.
|
||||||
|
@ -149,7 +148,7 @@ impl DecryptionKey {
|
||||||
///
|
///
|
||||||
/// let mut key = DecryptionKey::new(
|
/// let mut key = DecryptionKey::new(
|
||||||
/// EncryptionMethod::Aes128,
|
/// EncryptionMethod::Aes128,
|
||||||
/// "https://www.example.com".parse().unwrap()
|
/// "https://www.example.com/"
|
||||||
/// );
|
/// );
|
||||||
///
|
///
|
||||||
/// key.set_iv([
|
/// key.set_iv([
|
||||||
|
@ -178,7 +177,7 @@ impl DecryptionKey {
|
||||||
///
|
///
|
||||||
/// let mut key = DecryptionKey::new(
|
/// let mut key = DecryptionKey::new(
|
||||||
/// EncryptionMethod::Aes128,
|
/// EncryptionMethod::Aes128,
|
||||||
/// "https://www.example.com".parse().unwrap()
|
/// "https://www.example.com/"
|
||||||
/// );
|
/// );
|
||||||
///
|
///
|
||||||
/// key.set_iv([
|
/// key.set_iv([
|
||||||
|
@ -207,7 +206,7 @@ impl DecryptionKey {
|
||||||
///
|
///
|
||||||
/// let mut key = DecryptionKey::new(
|
/// let mut key = DecryptionKey::new(
|
||||||
/// EncryptionMethod::Aes128,
|
/// EncryptionMethod::Aes128,
|
||||||
/// "https://www.example.com".parse().unwrap()
|
/// "https://www.example.com/"
|
||||||
/// );
|
/// );
|
||||||
///
|
///
|
||||||
/// key.set_key_format("key_format_attribute");
|
/// key.set_key_format("key_format_attribute");
|
||||||
|
@ -230,7 +229,7 @@ impl DecryptionKey {
|
||||||
///
|
///
|
||||||
/// let mut key = DecryptionKey::new(
|
/// let mut key = DecryptionKey::new(
|
||||||
/// EncryptionMethod::Aes128,
|
/// EncryptionMethod::Aes128,
|
||||||
/// "https://www.example.com".parse().unwrap()
|
/// "https://www.example.com/"
|
||||||
/// );
|
/// );
|
||||||
///
|
///
|
||||||
/// key.set_key_format("key_format_attribute");
|
/// key.set_key_format("key_format_attribute");
|
||||||
|
@ -257,7 +256,7 @@ impl DecryptionKey {
|
||||||
///
|
///
|
||||||
/// let mut key = DecryptionKey::new(
|
/// let mut key = DecryptionKey::new(
|
||||||
/// EncryptionMethod::Aes128,
|
/// EncryptionMethod::Aes128,
|
||||||
/// "https://www.example.com".parse().unwrap()
|
/// "https://www.example.com/"
|
||||||
/// );
|
/// );
|
||||||
///
|
///
|
||||||
/// key.set_key_format_versions("1/2/3/4/5");
|
/// key.set_key_format_versions("1/2/3/4/5");
|
||||||
|
@ -280,7 +279,7 @@ impl DecryptionKey {
|
||||||
///
|
///
|
||||||
/// let mut key = DecryptionKey::new(
|
/// let mut key = DecryptionKey::new(
|
||||||
/// EncryptionMethod::Aes128,
|
/// EncryptionMethod::Aes128,
|
||||||
/// "https://www.example.com".parse().unwrap()
|
/// "https://www.example.com/"
|
||||||
/// );
|
/// );
|
||||||
///
|
///
|
||||||
/// key.set_key_format_versions("1/2/3/4/5");
|
/// key.set_key_format_versions("1/2/3/4/5");
|
||||||
|
@ -301,7 +300,7 @@ impl DecryptionKey {
|
||||||
///
|
///
|
||||||
/// let mut key = DecryptionKey::new(
|
/// let mut key = DecryptionKey::new(
|
||||||
/// EncryptionMethod::Aes128,
|
/// EncryptionMethod::Aes128,
|
||||||
/// "https://www.example.com".parse().unwrap()
|
/// "https://www.example.com/"
|
||||||
/// );
|
/// );
|
||||||
///
|
///
|
||||||
/// assert_eq!(
|
/// assert_eq!(
|
||||||
|
@ -333,7 +332,7 @@ impl FromStr for DecryptionKey {
|
||||||
for (key, value) in input.parse::<AttributePairs>()? {
|
for (key, value) in input.parse::<AttributePairs>()? {
|
||||||
match key.as_str() {
|
match key.as_str() {
|
||||||
"METHOD" => method = Some((value.parse())?),
|
"METHOD" => method = Some((value.parse())?),
|
||||||
"URI" => uri = Some(unquote(value).parse()?),
|
"URI" => uri = Some(unquote(value)),
|
||||||
"IV" => iv = Some((value.parse())?),
|
"IV" => iv = Some((value.parse())?),
|
||||||
"KEYFORMAT" => key_format = Some(unquote(value)),
|
"KEYFORMAT" => key_format = Some(unquote(value)),
|
||||||
"KEYFORMATVERSIONS" => key_format_versions = Some(unquote(value)),
|
"KEYFORMATVERSIONS" => key_format_versions = Some(unquote(value)),
|
||||||
|
@ -388,22 +387,28 @@ mod test {
|
||||||
use crate::types::EncryptionMethod;
|
use crate::types::EncryptionMethod;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_requires_version() {
|
fn test_builder() {
|
||||||
let key = DecryptionKey::builder()
|
let key = DecryptionKey::builder()
|
||||||
.method(EncryptionMethod::Aes128)
|
.method(EncryptionMethod::Aes128)
|
||||||
.uri("https://www.example.com".parse::<Url>().unwrap())
|
.uri("https://www.example.com/")
|
||||||
.iv([
|
.iv([
|
||||||
16, 239, 143, 117, 140, 165, 85, 17, 85, 132, 187, 91, 60, 104, 127, 82,
|
16, 239, 143, 117, 140, 165, 85, 17, 85, 132, 187, 91, 60, 104, 127, 82,
|
||||||
])
|
])
|
||||||
|
.key_format("ABC123")
|
||||||
|
.key_format_versions("1,2,3,4,5/12345")
|
||||||
.build()
|
.build()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
assert_eq!(
|
||||||
|
key.to_string(),
|
||||||
|
"METHOD=AES-128,URI=\"https://www.example.com/\",IV=0x10ef8f758ca555115584bb5b3c687f52,KEYFORMAT=\"ABC123\",KEYFORMATVERSIONS=\"1,2,3,4,5/12345\"".to_string()
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_display() {
|
fn test_display() {
|
||||||
let mut key = DecryptionKey::new(
|
let mut key = DecryptionKey::new(
|
||||||
EncryptionMethod::Aes128,
|
EncryptionMethod::Aes128,
|
||||||
"https://www.example.com/hls-key/key.bin".parse().unwrap(),
|
"https://www.example.com/hls-key/key.bin",
|
||||||
);
|
);
|
||||||
key.set_iv([
|
key.set_iv([
|
||||||
16, 239, 143, 117, 140, 165, 85, 17, 85, 132, 187, 91, 60, 104, 127, 82,
|
16, 239, 143, 117, 140, 165, 85, 17, 85, 132, 187, 91, 60, 104, 127, 82,
|
||||||
|
@ -426,13 +431,13 @@ mod test {
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
DecryptionKey::new(
|
DecryptionKey::new(
|
||||||
EncryptionMethod::Aes128,
|
EncryptionMethod::Aes128,
|
||||||
"https://priv.example.com/key.php?r=52".parse().unwrap()
|
"https://priv.example.com/key.php?r=52"
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut key = DecryptionKey::new(
|
let mut key = DecryptionKey::new(
|
||||||
EncryptionMethod::Aes128,
|
EncryptionMethod::Aes128,
|
||||||
"https://www.example.com/hls-key/key.bin".parse().unwrap(),
|
"https://www.example.com/hls-key/key.bin",
|
||||||
);
|
);
|
||||||
key.set_iv([
|
key.set_iv([
|
||||||
16, 239, 143, 117, 140, 165, 85, 17, 85, 132, 187, 91, 60, 104, 127, 82,
|
16, 239, 143, 117, 140, 165, 85, 17, 85, 132, 187, 91, 60, 104, 127, 82,
|
||||||
|
@ -447,10 +452,7 @@ mod test {
|
||||||
key
|
key
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut key = DecryptionKey::new(
|
let mut key = DecryptionKey::new(EncryptionMethod::Aes128, "http://www.example.com");
|
||||||
EncryptionMethod::Aes128,
|
|
||||||
"http://www.example.com".parse().unwrap(),
|
|
||||||
);
|
|
||||||
key.set_iv([
|
key.set_iv([
|
||||||
16, 239, 143, 117, 140, 165, 85, 17, 85, 132, 187, 91, 60, 104, 127, 82,
|
16, 239, 143, 117, 140, 165, 85, 17, 85, 132, 187, 91, 60, 104, 127, 82,
|
||||||
]);
|
]);
|
||||||
|
|
|
@ -36,11 +36,11 @@ fn test_simple_playlist() {
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
media_playlist.segments()[0].uri(),
|
media_playlist.segments()[0].uri(),
|
||||||
&"http://media.example.com/entire1.ts".parse().unwrap()
|
&"http://media.example.com/entire1.ts".to_string()
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
media_playlist.segments()[1].uri(),
|
media_playlist.segments()[1].uri(),
|
||||||
&"http://media.example.com/entire2.ts".parse().unwrap()
|
&"http://media.example.com/entire2.ts".to_string()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue