Skip to main content

TagValue

Struct TagValue 

Source
pub struct TagValue<'a>(pub &'a [u8]);
Expand description

A wrapper struct that provides many convenience methods for converting a tag value into a more specialized type.

The TagValue is intended to wrap the bytes following the : and before the end of line (not including the \r or \n characters). The constructor remains public (for convenience, as described below) so bear this in mind if trying to use this struct directly. It is unlikely that a user will need to construct this directly, and instead, should access this via crate::tag::UnknownTag::value (Tag is via crate::custom_parsing::tag::parse). There may be exceptions and so the library provides this flexibility.

For example, a (perhaps interesting) use case for using this struct directly can be to parse information out of comment tags. For example, it has been noticed that the Unified Streaming Packager seems to output a custom timestamp comment with its live playlists, that looks like a tag; however, the library will not parse this as a tag because the syntax is #USP-X-TIMESTAMP-MAP:<attribute-list>, so the lack of #EXT prefix means it is seen as a comment only. Despite this, if we split on the :, we can use this struct to extract information about the value.

let pseudo_tag = "#USP-X-TIMESTAMP-MAP:MPEGTS=900000,LOCAL=1970-01-01T00:00:00Z";
let mut reader = Reader::from_str(pseudo_tag, ParsingOptions::default());
match reader.read_line() {
    Ok(Some(HlsLine::Comment(tag))) => {
        let mut tag_split = tag.splitn(2, ':');
        if tag_split.next() != Some("USP-X-TIMESTAMP-MAP") {
            return Err(format!("unexpected tag name").into());
        }
        let Some(value) = tag_split.next() else {
            return Err(format!("unexpected no tag value").into());
        };
        let tag_value = TagValue(value.trim().as_bytes());
        let list = tag_value.try_as_attribute_list()?;

        // Prove that we can extract the value of MPEGTS
        let mpegts = list
            .get("MPEGTS")
            .and_then(AttributeValue::unquoted)
            .ok_or(ValidationError::MissingRequiredAttribute("MPEGTS"))?
            .try_as_decimal_integer()?;
        assert_eq!(900000, mpegts);

        // Prove that we can extract the value of LOCAL
        let local = list
            .get("LOCAL")
            .and_then(AttributeValue::unquoted)
            .and_then(|v| date::parse_bytes(v.0).ok())
            .ok_or(ValidationError::MissingRequiredAttribute("LOCAL"))?;
        assert_eq!(date_time!(1970-01-01 T 00:00:00.000), local);
    }
    r => return Err(format!("unexpected result {r:?}").into()),
}

Tuple Fields§

§0: &'a [u8]

Implementations§

Source§

impl<'a> TagValue<'a>

Source

pub fn is_empty(&self) -> bool

Indicates whether the value is empty or not.

This is only the case if the tag contained a : value separator but had no value content afterwards (before the new line). Under all known circumstances this is an error. If a tag value is empty then this is indicated via crate::tag::UnknownTag::value providing None.

Source

pub fn try_as_decimal_integer(&self) -> Result<u64, ParseNumberError>

Attempt to convert the tag value bytes into a decimal integer.

For example:

let tag = quick_m3u8::custom_parsing::tag::parse("#EXT-X-EXAMPLE:100")?.parsed;
if let Some(value) = tag.value() {
    assert_eq!(100, value.try_as_decimal_integer()?);
}
Source

pub fn try_as_decimal_integer_range( &self, ) -> Result<DecimalIntegerRange, ParseDecimalIntegerRangeError>

Attempt to convert the tag value bytes into a decimal integer range (<n>[@<o>]).

For example:

let tag = quick_m3u8::custom_parsing::tag::parse("#EXT-X-EXAMPLE:1024@512")?.parsed;
if let Some(value) = tag.value() {
    assert_eq!(
        DecimalIntegerRange {
            length: 1024,
            offset: Some(512)
        },
        value.try_as_decimal_integer_range()?
    );
}
Source

pub fn try_as_playlist_type( &self, ) -> Result<HlsPlaylistType, ParsePlaylistTypeError>

Attempt to convert the tag value bytes into a playlist type.

For example:

let tag = quick_m3u8::custom_parsing::tag::parse("#EXT-X-EXAMPLE:VOD")?.parsed;
if let Some(value) = tag.value() {
    assert_eq!(HlsPlaylistType::Vod, value.try_as_playlist_type()?);
}
Source

pub fn try_as_decimal_floating_point(&self) -> Result<f64, ParseFloatError>

Attempt to convert the tag value bytes into a decimal floating point.

For example:

let tag = quick_m3u8::custom_parsing::tag::parse("#EXT-X-EXAMPLE:3.14")?.parsed;
if let Some(value) = tag.value() {
    assert_eq!(3.14, value.try_as_decimal_floating_point()?);
}
Source

pub fn try_as_decimal_floating_point_with_title( &self, ) -> Result<(f64, &'a str), ParseDecimalFloatingPointWithTitleError>

Attempt to convert the tag value bytes into a decimal floating point with title.

For example:

let tag = quick_m3u8::custom_parsing::tag::parse("#EXT-X-EXAMPLE:3.14,pi")?.parsed;
if let Some(value) = tag.value() {
    assert_eq!((3.14, "pi"), value.try_as_decimal_floating_point_with_title()?);
}
Source

pub fn try_as_date_time(&self) -> Result<DateTime, DateTimeSyntaxError>

Attempt to convert the tag value bytes into a date time.

For example:

let tag = quick_m3u8::custom_parsing::tag::parse(
    "#EXT-X-EXAMPLE:2025-08-10T17:27:42.213-05:00"
)?.parsed;
if let Some(value) = tag.value() {
    assert_eq!(date_time!(2025-08-10 T 17:27:42.213 -05:00), value.try_as_date_time()?);
}
Source

pub fn try_as_attribute_list( &self, ) -> Result<HashMap<&'a str, AttributeValue<'a>>, AttributeListParsingError>

Attempt to convert the tag value bytes into an attribute list.

For example:

let tag = quick_m3u8::custom_parsing::tag::parse(
    "#EXT-X-EXAMPLE:TYPE=LIST,VALUE=\"example\""
)?.parsed;
if let Some(value) = tag.value() {
    assert_eq!(
        HashMap::from([
            ("TYPE", AttributeValue::Unquoted(UnquotedAttributeValue(b"LIST"))),
            ("VALUE", AttributeValue::Quoted("example"))
        ]),
        value.try_as_attribute_list()?
    );
}
Source

pub fn try_as_ordered_attribute_list( &self, ) -> Result<Vec<(&'a str, AttributeValue<'a>)>, AttributeListParsingError>

Attempt to convert the tag value bytes into an ordered attribute list.

For example:

let tag = quick_m3u8::custom_parsing::tag::parse(
    "#EXT-X-EXAMPLE:TYPE=LIST,VALUE=\"example\""
)?.parsed;
if let Some(value) = tag.value() {
    assert_eq!(
        vec![
            ("TYPE", AttributeValue::Unquoted(UnquotedAttributeValue(b"LIST"))),
            ("VALUE", AttributeValue::Quoted("example"))
        ],
        value.try_as_ordered_attribute_list()?
    );
}

Trait Implementations§

Source§

impl<'a> Clone for TagValue<'a>

Source§

fn clone(&self) -> TagValue<'a>

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl<'a> Debug for TagValue<'a>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<'a> PartialEq for TagValue<'a>

Source§

fn eq(&self, other: &TagValue<'a>) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl<'a> Copy for TagValue<'a>

Source§

impl<'a> StructuralPartialEq for TagValue<'a>

Auto Trait Implementations§

§

impl<'a> Freeze for TagValue<'a>

§

impl<'a> RefUnwindSafe for TagValue<'a>

§

impl<'a> Send for TagValue<'a>

§

impl<'a> Sync for TagValue<'a>

§

impl<'a> Unpin for TagValue<'a>

§

impl<'a> UnsafeUnpin for TagValue<'a>

§

impl<'a> UnwindSafe for TagValue<'a>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.