use {
crate::{
parsers::{Parse, ParserContext},
CustomParseError,
},
cssparser::{ParseError, Parser, ToCss},
std::fmt,
};
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Ratio {
width: u32,
height: u32,
}
impl ToCss for Ratio {
fn to_css<W: fmt::Write>(&self, dest: &mut W) -> fmt::Result {
self.width.to_css(dest)?;
dest.write_str("/")?;
self.height.to_css(dest)
}
}
impl Parse for Ratio {
fn parse<'i, 't>(
_context: &ParserContext,
input: &mut Parser<'i, 't>,
) -> Result<Self, ParseError<'i, CustomParseError<'i>>> {
let width = input.expect_integer()?;
if width <= 0 {
return Err(ParseError::from(
CustomParseError::RatioNumeratorCanNotBeNegativeOrZero(width),
));
}
input.expect_delim('/')?;
let height = input.expect_integer()?;
if height <= 0 {
return Err(ParseError::from(
CustomParseError::RatioDivisorCanNotBeNegativeOrZero(width),
));
}
Ok(Self::new(width as u32, height as u32))
}
}
impl Ratio {
#[inline(always)]
pub fn new(width: u32, height: u32) -> Self {
debug_assert!(width != 0, "width can not be zero");
debug_assert!(height != 0, "height can not be zero");
#[inline(always)]
fn greatestCommonDivisorByEuclidsAlgorithm(
nominator: u32,
denominator: u32,
) -> u32 {
let mut x = nominator;
let mut y = denominator;
while y != 0 {
let t = y;
y = x % y;
x = t;
}
x
}
let greatestCommonDivisor =
greatestCommonDivisorByEuclidsAlgorithm(width, height);
Self {
width: width / greatestCommonDivisor,
height: height / greatestCommonDivisor,
}
}
#[inline(always)]
pub fn width(&self) -> u32 {
self.width
}
#[inline(always)]
pub fn height(&self) -> u32 {
self.height
}
#[inline(always)]
pub fn to_scalar(&self) -> f64 {
(self.width as f64) / (self.height as f64)
}
}