Trait RangedFeature

Source
pub trait RangedFeature<'a>: Sized {
    type Value: Parse<'a>;
    type FeatureName: Peek<'a> + Parse<'a> + RangedFeatureKeyword;

    // Required methods
    fn new_legacy(
        open: LeftParen,
        name: Self::FeatureName,
        colon: Colon,
        value: Self::Value,
        close: RightParen,
    ) -> Result<Self>;
    fn new_left(
        open: LeftParen,
        name: Self::FeatureName,
        comparison: Comparison,
        value: Self::Value,
        close: RightParen,
    ) -> Result<Self>;
    fn new_right(
        open: LeftParen,
        value: Self::Value,
        comparison: Comparison,
        name: Self::FeatureName,
        close: RightParen,
    ) -> Result<Self>;
    fn new_ranged(
        open: LeftParen,
        left: Self::Value,
        left_comparison: Comparison,
        name: Self::FeatureName,
        right_comparison: Comparison,
        value: Self::Value,
        close: RightParen,
    ) -> Result<Self>;

    // Provided method
    fn parse_ranged_feature(p: &mut Parser<'a>) -> Result<Self> { ... }
}
Expand description

This trait provides an implementation for parsing a “Media Feature” in the “Range” context.

Rather than implementing this trait on an enum, use the ranged_feature! macro which expands to define the enum and necessary traits (Parse, this trait, and ToCursors) in a single macro call.

It does not implement Parse, but provides parse_ranged_feature(&mut Parser<'a>) -> Result<Self>, which can make for a trivial Parse implementation. The type Self::FeatureName must be defined, and represents the <feature-name> token(s), while Self::Value represents the <value> token(s). The grammar of both <value> and <feature-name> aren’t mandated by this spec but are very likely be an Ident for the <feature-name> and either a Dimension or Number for the <value> portion. Self::FeatureName must also implement the crate::RangedFeatureKeyword trait which provides RangedFeatureKeyword::is_legacy to determine if the <feature-name> is unambiguously a legacy “min-” or “max-” prefixed name, for “legacy” ranged media conditions.

CSS defines the Media Feature in Ranged context as:

                                          ╭─ "="  ─╮
                                          ├─ "<"  ─┤
                                          ├─ "<=" ─┤
                                          ├─ ">"  ─┤
 │├─ "(" ─╮─ [<feature-name> or <value>] ─╯─ ">=" ─╰─ [<feature-name> or <value>] ─╭─ ")" ─┤│
          ├────── <value> ─╮─ "<"  ─╭── <feature-name> ─╮─ "<"  ─╭── <value> ──────┤
          │                ╰─ "<=" ─╯                   ╰─ "<=" ─╯                 │
          ╰────── <value> ─╮─ ">"  ─╭── <feature-name> ─╮─ ">"  ─╭── <value> ──────╯
                           ╰─ ">=" ─╯                   ╰─ ">=" ─╯

This trait deviates slightly from the CSS spec ever so slightly for a few reasons:

  • It uses a <comparison> token to represent each of the comparison operators, implemented as Comparison. This makes for much more convenient parsing and subsequent analyses.
  • The CSS defined railroad diagram doesn’t quite fully convey that <value> <comparison> <value> and <feature-name> <comparison> <feature-name> are not valid productions. This trait will fail to parse such productions, as do all existing implementations of CSS (i.e browsers).
  • It does not do the extra validation to ensure a left/right comparison are “directionally equivalent” - in other words <value> "<=" <feature-name> "=>" <value> is a valid production in this trait - this allows for ASTs to factor in error tolerance. If an AST node wishes to be strict, it can check the comparators inside of RangedFeature::new_ranged and return an Err there.
  • It supports the “Legacy” modes which are defined for certain ranged media features. These legacy productions use a colon token and typically have min and max variants of the RangedFeature::FeatureName. For example width: 1024px is equivalent to width >= 1024px, while max-width: 1024px is equivalent to max-width <= 1024px. If an AST node wishes to not support legacy feature-names, it can return an Err in RangedFeature::new_legacy.

Given the above differences, the trait RangedFeature parses a grammar defined as:

<comparison>
 │├──╮─ "="  ─╭──┤│
     ├─ "<"  ─┤
     ├─ "<=" ─┤
     ├─ ">"  ─┤
     ╰─ ">=" ─╯

<ranged-feature-trait>
 │├─ "(" ─╮─ <feature-name> ─ <comparison> ─ <value> ─────────────────────────────────╭─ ")" ─┤│
          ├─ <value> ─ <comparison> ─ <ranged-feautre-name> ──────────────────────────┤
          ├─ <value> ─ <comparison> ─ <ranged-feature-name> ─ <comparison> ─ <value> ─┤
          ╰─ <feature-name> ─ ":" ─ <value> ──────────────────────────────────────────╯

Required Associated Types§

Required Methods§

Source

fn new_legacy( open: LeftParen, name: Self::FeatureName, colon: Colon, value: Self::Value, close: RightParen, ) -> Result<Self>

Method for constructing a “legacy” media feature. Legacy features always include a colon token.

Source

fn new_left( open: LeftParen, name: Self::FeatureName, comparison: Comparison, value: Self::Value, close: RightParen, ) -> Result<Self>

Method for constructing a “left” media feature. This method is called when the parsed tokens encountered the <value> token before the <feature-name>.

Source

fn new_right( open: LeftParen, value: Self::Value, comparison: Comparison, name: Self::FeatureName, close: RightParen, ) -> Result<Self>

Method for constructing a “right” media feature. This method is called when the parsed tokens encountered the <feature-name> token before the <value>.

Source

fn new_ranged( open: LeftParen, left: Self::Value, left_comparison: Comparison, name: Self::FeatureName, right_comparison: Comparison, value: Self::Value, close: RightParen, ) -> Result<Self>

Method for constructing a “ranged” media feature. This method is called when the parsed tokens encountered the <value> token, followed by a <comparison>, followed by a <feature-name>, followed by a <comparison> followed lastly by a <value>.

Provided Methods§

Source

fn parse_ranged_feature(p: &mut Parser<'a>) -> Result<Self>

Dyn Compatibility§

This trait is not dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.

Implementors§