tor-browser

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

rect.rs (4254B)


      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 //! Generic types for CSS values that are composed of four sides.
      6 
      7 use crate::derives::*;
      8 use crate::parser::{Parse, ParserContext};
      9 use cssparser::Parser;
     10 use std::fmt::{self, Write};
     11 use style_traits::{CssWriter, ParseError, ToCss};
     12 
     13 /// A CSS value made of four components, where its `ToCss` impl will try to
     14 /// serialize as few components as possible, like for example in `border-width`.
     15 #[derive(
     16    Animate,
     17    Clone,
     18    ComputeSquaredDistance,
     19    Copy,
     20    Debug,
     21    Deserialize,
     22    MallocSizeOf,
     23    PartialEq,
     24    SpecifiedValueInfo,
     25    Serialize,
     26    ToAnimatedValue,
     27    ToAnimatedZero,
     28    ToComputedValue,
     29    ToResolvedValue,
     30    ToShmem,
     31    ToTyped,
     32 )]
     33 #[repr(C)]
     34 pub struct Rect<T>(pub T, pub T, pub T, pub T);
     35 
     36 impl<T> Rect<T> {
     37    /// Returns a new `Rect<T>` value.
     38    pub fn new(first: T, second: T, third: T, fourth: T) -> Self {
     39        Rect(first, second, third, fourth)
     40    }
     41 }
     42 
     43 impl<T> Rect<T>
     44 where
     45    T: Clone,
     46 {
     47    /// Returns a rect with all the values equal to `v`.
     48    pub fn all(v: T) -> Self {
     49        Rect::new(v.clone(), v.clone(), v.clone(), v)
     50    }
     51 
     52    /// Parses a new `Rect<T>` value with the given parse function.
     53    pub fn parse_with<'i, 't, Parse>(
     54        context: &ParserContext,
     55        input: &mut Parser<'i, 't>,
     56        parse: Parse,
     57    ) -> Result<Self, ParseError<'i>>
     58    where
     59        Parse: Fn(&ParserContext, &mut Parser<'i, 't>) -> Result<T, ParseError<'i>>,
     60    {
     61        let first = parse(context, input)?;
     62        let second = if let Ok(second) = input.try_parse(|i| parse(context, i)) {
     63            second
     64        } else {
     65            // <first>
     66            return Ok(Self::new(
     67                first.clone(),
     68                first.clone(),
     69                first.clone(),
     70                first,
     71            ));
     72        };
     73        let third = if let Ok(third) = input.try_parse(|i| parse(context, i)) {
     74            third
     75        } else {
     76            // <first> <second>
     77            return Ok(Self::new(first.clone(), second.clone(), first, second));
     78        };
     79        let fourth = if let Ok(fourth) = input.try_parse(|i| parse(context, i)) {
     80            fourth
     81        } else {
     82            // <first> <second> <third>
     83            return Ok(Self::new(first, second.clone(), third, second));
     84        };
     85        // <first> <second> <third> <fourth>
     86        Ok(Self::new(first, second, third, fourth))
     87    }
     88 
     89    /// Parses a new `Rect<T>` value which all components must be specified, with the given parse
     90    /// function.
     91    pub fn parse_all_components_with<'i, 't, Parse>(
     92        context: &ParserContext,
     93        input: &mut Parser<'i, 't>,
     94        parse: Parse,
     95    ) -> Result<Self, ParseError<'i>>
     96    where
     97        Parse: Fn(&ParserContext, &mut Parser<'i, 't>) -> Result<T, ParseError<'i>>,
     98    {
     99        let first = parse(context, input)?;
    100        let second = parse(context, input)?;
    101        let third = parse(context, input)?;
    102        let fourth = parse(context, input)?;
    103        // <first> <second> <third> <fourth>
    104        Ok(Self::new(first, second, third, fourth))
    105    }
    106 }
    107 
    108 impl<T> Parse for Rect<T>
    109 where
    110    T: Clone + Parse,
    111 {
    112    #[inline]
    113    fn parse<'i, 't>(
    114        context: &ParserContext,
    115        input: &mut Parser<'i, 't>,
    116    ) -> Result<Self, ParseError<'i>> {
    117        Self::parse_with(context, input, T::parse)
    118    }
    119 }
    120 
    121 impl<T> ToCss for Rect<T>
    122 where
    123    T: PartialEq + ToCss,
    124 {
    125    fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
    126    where
    127        W: Write,
    128    {
    129        self.0.to_css(dest)?;
    130        let same_vertical = self.0 == self.2;
    131        let same_horizontal = self.1 == self.3;
    132        if same_vertical && same_horizontal && self.0 == self.1 {
    133            return Ok(());
    134        }
    135        dest.write_char(' ')?;
    136        self.1.to_css(dest)?;
    137        if same_vertical && same_horizontal {
    138            return Ok(());
    139        }
    140        dest.write_char(' ')?;
    141        self.2.to_css(dest)?;
    142        if same_horizontal {
    143            return Ok(());
    144        }
    145        dest.write_char(' ')?;
    146        self.3.to_css(dest)
    147    }
    148 }