Skip to main content

azul_css/props/basic/
time.rs

1//! CSS property types for time durations (s, ms).
2
3use alloc::string::{String, ToString};
4use core::fmt;
5
6use crate::props::formatter::PrintAsCssValue;
7
8#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
9#[repr(C)]
10pub struct CssDuration {
11    /// Duration in milliseconds.
12    pub inner: u32,
13}
14
15impl Default for CssDuration {
16    fn default() -> Self {
17        Self { inner: 0 }
18    }
19}
20
21impl PrintAsCssValue for CssDuration {
22    fn print_as_css_value(&self) -> String {
23        format!("{}ms", self.inner)
24    }
25}
26
27impl crate::format_rust_code::FormatAsRustCode for CssDuration {
28    fn format_as_rust_code(&self, _tabs: usize) -> String {
29        format!("CssDuration {{ inner: {} }}", self.inner)
30    }
31}
32
33#[cfg(feature = "parser")]
34#[derive(Clone, PartialEq)]
35pub enum DurationParseError<'a> {
36    InvalidValue(&'a str),
37    ParseFloat(core::num::ParseFloatError),
38}
39
40#[cfg(feature = "parser")]
41impl_debug_as_display!(DurationParseError<'a>);
42#[cfg(feature = "parser")]
43impl_display! { DurationParseError<'a>, {
44    InvalidValue(v) => format!("Invalid time value: \"{}\"", v),
45    ParseFloat(e) => format!("Invalid number for time value: {}", e),
46}}
47
48#[cfg(feature = "parser")]
49#[derive(Debug, Clone, PartialEq)]
50pub enum DurationParseErrorOwned {
51    InvalidValue(String),
52    ParseFloat(String),
53}
54
55#[cfg(feature = "parser")]
56impl<'a> DurationParseError<'a> {
57    pub fn to_contained(&self) -> DurationParseErrorOwned {
58        match self {
59            Self::InvalidValue(s) => DurationParseErrorOwned::InvalidValue(s.to_string()),
60            Self::ParseFloat(e) => DurationParseErrorOwned::ParseFloat(e.to_string()),
61        }
62    }
63}
64
65#[cfg(feature = "parser")]
66impl DurationParseErrorOwned {
67    pub fn to_shared<'a>(&'a self) -> DurationParseError<'a> {
68        match self {
69            Self::InvalidValue(s) => DurationParseError::InvalidValue(s),
70            Self::ParseFloat(s) => DurationParseError::InvalidValue("invalid float"), /* Can't reconstruct */
71        }
72    }
73}
74
75#[cfg(feature = "parser")]
76pub fn parse_duration<'a>(input: &'a str) -> Result<CssDuration, DurationParseError<'a>> {
77    let trimmed = input.trim().to_lowercase();
78    if trimmed.ends_with("ms") {
79        let num_str = &trimmed[..trimmed.len() - 2];
80        let ms = num_str
81            .parse::<f32>()
82            .map_err(|e| DurationParseError::ParseFloat(e))?;
83        Ok(CssDuration { inner: ms as u32 })
84    } else if trimmed.ends_with('s') {
85        let num_str = &trimmed[..trimmed.len() - 1];
86        let s = num_str
87            .parse::<f32>()
88            .map_err(|e| DurationParseError::ParseFloat(e))?;
89        Ok(CssDuration {
90            inner: (s * 1000.0) as u32,
91        })
92    } else {
93        Err(DurationParseError::InvalidValue(input))
94    }
95}