lightningcss/values/
ratio.rs

1//! CSS ratio values.
2
3use super::number::CSSNumber;
4use crate::error::{ParserError, PrinterError};
5use crate::printer::Printer;
6use crate::traits::{Parse, ToCss};
7#[cfg(feature = "visitor")]
8use crate::visitor::Visit;
9use cssparser::*;
10
11/// A CSS [`<ratio>`](https://www.w3.org/TR/css-values-4/#ratios) value,
12/// representing the ratio of two numeric values.
13#[derive(Debug, Clone, PartialEq)]
14#[cfg_attr(feature = "visitor", derive(Visit))]
15#[cfg_attr(feature = "visitor", visit(visit_ratio, RATIOS))]
16#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
17#[cfg_attr(feature = "jsonschema", derive(schemars::JsonSchema))]
18#[cfg_attr(feature = "into_owned", derive(static_self::IntoOwned))]
19pub struct Ratio(pub CSSNumber, pub CSSNumber);
20
21impl<'i> Parse<'i> for Ratio {
22  fn parse<'t>(input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i, ParserError<'i>>> {
23    let first = CSSNumber::parse(input)?;
24    let second = if input.try_parse(|input| input.expect_delim('/')).is_ok() {
25      CSSNumber::parse(input)?
26    } else {
27      1.0
28    };
29
30    Ok(Ratio(first, second))
31  }
32}
33
34impl Ratio {
35  /// Parses a ratio where both operands are required.
36  pub fn parse_required<'i, 't>(input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i, ParserError<'i>>> {
37    let first = CSSNumber::parse(input)?;
38    input.expect_delim('/')?;
39    let second = CSSNumber::parse(input)?;
40    Ok(Ratio(first, second))
41  }
42}
43
44impl ToCss for Ratio {
45  fn to_css<W>(&self, dest: &mut Printer<W>) -> Result<(), PrinterError>
46  where
47    W: std::fmt::Write,
48  {
49    self.0.to_css(dest)?;
50    if self.1 != 1.0 {
51      dest.delim('/', true)?;
52      self.1.to_css(dest)?;
53    }
54    Ok(())
55  }
56}
57
58impl std::ops::Add<CSSNumber> for Ratio {
59  type Output = Self;
60
61  fn add(self, other: CSSNumber) -> Ratio {
62    Ratio(self.0 + other, self.1)
63  }
64}