use std::fmt; use std::str::{self, FromStr}; use getset::{Getters, MutGetters, Setters}; use trackable::error::ErrorKindExt; use crate::{Error, ErrorKind, Result}; /// Byte range. /// /// 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 #[derive(Getters, Setters, MutGetters, Debug, Clone, Copy, PartialEq, Eq, Hash)] #[get = "pub"] #[set = "pub"] #[get_mut = "pub"] pub struct ByteRange { /// The length of the range. length: usize, /// The start of the range. start: Option, } impl ByteRange { /// Creates a new [ByteRange]. pub const fn new(length: usize, start: Option) -> Self { Self { length, start } } } impl fmt::Display for ByteRange { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{}", self.length)?; if let Some(x) = self.start { write!(f, "@{}", x)?; } Ok(()) } } impl FromStr for ByteRange { type Err = Error; fn from_str(s: &str) -> Result { let tokens = s.splitn(2, '@').collect::>(); if tokens.is_empty() { Err(ErrorKind::InvalidInput)?; } let length = tokens[0] .parse() .map_err(|e| ErrorKind::InvalidInput.cause(e))?; let start = { let mut result = None; if tokens.len() == 2 { result = Some( tokens[1] .parse() .map_err(|e| ErrorKind::InvalidInput.cause(e))?, ); } result }; Ok(ByteRange::new(length, start)) } } #[cfg(test)] mod tests { use super::*; #[test] fn test_display() { let byte_range = ByteRange { length: 0, start: Some(5), }; assert_eq!(byte_range.to_string(), "0@5".to_string()); let byte_range = ByteRange { length: 99999, start: Some(2), }; assert_eq!(byte_range.to_string(), "99999@2".to_string()); let byte_range = ByteRange { length: 99999, start: None, }; assert_eq!(byte_range.to_string(), "99999".to_string()); } #[test] fn test_parse() { let byte_range = ByteRange { length: 99999, start: Some(2), }; assert_eq!(byte_range, "99999@2".parse::().unwrap()); let byte_range = ByteRange { length: 99999, start: Some(2), }; assert_eq!(byte_range, "99999@2".parse::().unwrap()); let byte_range = ByteRange { length: 99999, start: None, }; assert_eq!(byte_range, "99999".parse::().unwrap()); } }