use cssparser::*; use crate::traits::{Parse, ToCss}; use crate::printer::Printer; use super::calc::Calc; /// https://www.w3.org/TR/css3-values/#time-value #[derive(Debug, Clone, PartialEq)] pub enum Time { Seconds(f32), Milliseconds(f32) } impl Time { pub fn to_ms(&self) -> f32 { match self { Time::Seconds(s) => s * 1000.0, Time::Milliseconds(ms) => *ms } } } impl Parse for Time { fn parse<'i, 't>(input: &mut Parser<'i, 't>) -> Result> { match input.try_parse(Calc::parse) { Ok(Calc::Value(v)) => return Ok(*v), // Time is always compatible, so they will always compute to a value. Ok(_) => return Err(input.new_error(BasicParseErrorKind::QualifiedRuleInvalid)), _ => {} } let location = input.current_source_location(); match *input.next()? { Token::Dimension { value, ref unit, .. } => { match_ignore_ascii_case! { unit, "s" => Ok(Time::Seconds(value)), "ms" => Ok(Time::Milliseconds(value)), _ => Err(input.new_error(BasicParseErrorKind::QualifiedRuleInvalid)) } } ref t => Err(location.new_unexpected_token_error(t.clone())), } } } impl ToCss for Time { fn to_css(&self, dest: &mut Printer) -> std::fmt::Result where W: std::fmt::Write { // 0.1s is shorter than 100ms // anything smaller is longer match self { Time::Seconds(s) => { if *s > 0.0 && *s < 0.1 { (*s * 1000.0).to_css(dest)?; dest.write_str("ms") } else { s.to_css(dest)?; dest.write_str("s") } } Time::Milliseconds(ms) => { if *ms == 0.0 || *ms >= 100.0 { (*ms / 1000.0).to_css(dest)?; dest.write_str("s") } else { ms.to_css(dest)?; dest.write_str("ms") } } } } } impl std::convert::Into> for Time { fn into(self) -> Calc