tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

list.rs (5586B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this
      3 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
      4 
      5 //! `list` specified values.
      6 
      7 #[cfg(feature = "gecko")]
      8 use crate::counter_style::{CounterStyle, CounterStyleParsingFlags};
      9 use crate::derives::*;
     10 use crate::parser::{Parse, ParserContext};
     11 #[cfg(feature = "servo")]
     12 use crate::properties::longhands::list_style_type::SpecifiedValue as ListStyleType;
     13 use cssparser::{Parser, Token};
     14 use style_traits::{ParseError, StyleParseErrorKind};
     15 
     16 /// Specified and computed `list-style-type` property.
     17 #[cfg(feature = "gecko")]
     18 #[derive(
     19    Clone,
     20    Debug,
     21    Eq,
     22    MallocSizeOf,
     23    PartialEq,
     24    SpecifiedValueInfo,
     25    ToComputedValue,
     26    ToCss,
     27    ToResolvedValue,
     28    ToShmem,
     29    ToTyped,
     30 )]
     31 #[repr(transparent)]
     32 pub struct ListStyleType(pub CounterStyle);
     33 
     34 #[cfg(feature = "gecko")]
     35 impl ListStyleType {
     36    /// Initial specified value for `list-style-type`.
     37    #[inline]
     38    pub fn disc() -> Self {
     39        Self(CounterStyle::disc())
     40    }
     41 
     42    /// none value.
     43    #[inline]
     44    pub fn none() -> Self {
     45        Self(CounterStyle::None)
     46    }
     47 
     48    /// Convert from gecko keyword to list-style-type.
     49    ///
     50    /// This should only be used for mapping type attribute to list-style-type, and thus only
     51    /// values possible in that attribute is considered here.
     52    pub fn from_gecko_keyword(value: u32) -> Self {
     53        use crate::gecko_bindings::structs;
     54        use crate::values::CustomIdent;
     55        let v8 = value as u8;
     56        if v8 == structs::ListStyle_None {
     57            return Self::none();
     58        }
     59 
     60        Self(CounterStyle::Name(CustomIdent(match v8 {
     61            structs::ListStyle_Disc => atom!("disc"),
     62            structs::ListStyle_Circle => atom!("circle"),
     63            structs::ListStyle_Square => atom!("square"),
     64            structs::ListStyle_Decimal => atom!("decimal"),
     65            structs::ListStyle_LowerRoman => atom!("lower-roman"),
     66            structs::ListStyle_UpperRoman => atom!("upper-roman"),
     67            structs::ListStyle_LowerAlpha => atom!("lower-alpha"),
     68            structs::ListStyle_UpperAlpha => atom!("upper-alpha"),
     69            _ => unreachable!("Unknown counter style keyword value"),
     70        })))
     71    }
     72 
     73    /// Is this a bullet? (i.e. `list-style-type: disc|circle|square|disclosure-closed|disclosure-open`)
     74    #[inline]
     75    pub fn is_bullet(&self) -> bool {
     76        self.0.is_bullet()
     77    }
     78 }
     79 
     80 #[cfg(feature = "gecko")]
     81 impl Parse for ListStyleType {
     82    fn parse<'i, 't>(
     83        context: &ParserContext,
     84        input: &mut Parser<'i, 't>,
     85    ) -> Result<Self, ParseError<'i>> {
     86        let flags = CounterStyleParsingFlags::ALLOW_NONE | CounterStyleParsingFlags::ALLOW_STRING;
     87        Ok(Self(CounterStyle::parse(context, input, flags)?))
     88    }
     89 }
     90 
     91 #[cfg(feature = "servo")]
     92 impl ListStyleType {
     93    /// Initial specified value for `list-style-type`.
     94    #[inline]
     95    pub fn disc() -> Self {
     96        Self::Disc
     97    }
     98 
     99    /// none value.
    100    #[inline]
    101    pub fn none() -> Self {
    102        Self::None
    103    }
    104 }
    105 
    106 /// A quote pair.
    107 #[derive(
    108    Clone,
    109    Debug,
    110    MallocSizeOf,
    111    PartialEq,
    112    SpecifiedValueInfo,
    113    ToComputedValue,
    114    ToCss,
    115    ToResolvedValue,
    116    ToShmem,
    117 )]
    118 #[repr(C)]
    119 pub struct QuotePair {
    120    /// The opening quote.
    121    pub opening: crate::OwnedStr,
    122 
    123    /// The closing quote.
    124    pub closing: crate::OwnedStr,
    125 }
    126 
    127 /// List of quote pairs for the specified/computed value of `quotes` property.
    128 #[derive(
    129    Clone,
    130    Debug,
    131    Default,
    132    MallocSizeOf,
    133    PartialEq,
    134    SpecifiedValueInfo,
    135    ToComputedValue,
    136    ToCss,
    137    ToResolvedValue,
    138    ToShmem,
    139 )]
    140 #[repr(transparent)]
    141 pub struct QuoteList(
    142    #[css(iterable, if_empty = "none")]
    143    #[ignore_malloc_size_of = "Arc"]
    144    pub crate::ArcSlice<QuotePair>,
    145 );
    146 
    147 /// Specified and computed `quotes` property: `auto`, `none`, or a list
    148 /// of characters.
    149 #[derive(
    150    Clone,
    151    Debug,
    152    MallocSizeOf,
    153    PartialEq,
    154    SpecifiedValueInfo,
    155    ToComputedValue,
    156    ToCss,
    157    ToResolvedValue,
    158    ToShmem,
    159    ToTyped,
    160 )]
    161 #[repr(C)]
    162 pub enum Quotes {
    163    /// list of quote pairs
    164    QuoteList(QuoteList),
    165    /// auto (use lang-dependent quote marks)
    166    Auto,
    167 }
    168 
    169 impl Parse for Quotes {
    170    fn parse<'i, 't>(
    171        _: &ParserContext,
    172        input: &mut Parser<'i, 't>,
    173    ) -> Result<Quotes, ParseError<'i>> {
    174        if input
    175            .try_parse(|input| input.expect_ident_matching("auto"))
    176            .is_ok()
    177        {
    178            return Ok(Quotes::Auto);
    179        }
    180 
    181        if input
    182            .try_parse(|input| input.expect_ident_matching("none"))
    183            .is_ok()
    184        {
    185            return Ok(Quotes::QuoteList(QuoteList::default()));
    186        }
    187 
    188        let mut quotes = Vec::new();
    189        loop {
    190            let location = input.current_source_location();
    191            let opening = match input.next() {
    192                Ok(&Token::QuotedString(ref value)) => value.as_ref().to_owned().into(),
    193                Ok(t) => return Err(location.new_unexpected_token_error(t.clone())),
    194                Err(_) => break,
    195            };
    196 
    197            let closing = input.expect_string()?.as_ref().to_owned().into();
    198            quotes.push(QuotePair { opening, closing });
    199        }
    200 
    201        if !quotes.is_empty() {
    202            Ok(Quotes::QuoteList(QuoteList(crate::ArcSlice::from_iter(
    203                quotes.into_iter(),
    204            ))))
    205        } else {
    206            Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError))
    207        }
    208    }
    209 }