azul_css/props/basic/
time.rs1use alloc::string::{String, ToString};
4use crate::corety::AzString;
5
6use crate::props::formatter::PrintAsCssValue;
7
8#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
10#[repr(C)]
11#[derive(Default)]
12pub struct CssDuration {
13 pub inner: u32,
15}
16
17
18impl PrintAsCssValue for CssDuration {
19 fn print_as_css_value(&self) -> String {
20 format!("{}ms", self.inner)
21 }
22}
23
24impl crate::codegen::format::FormatAsRustCode for CssDuration {
25 fn format_as_rust_code(&self, _tabs: usize) -> String {
26 format!("CssDuration {{ inner: {} }}", self.inner)
27 }
28}
29
30#[cfg(feature = "parser")]
32#[derive(Clone, PartialEq, Eq)]
33pub enum DurationParseError<'a> {
34 InvalidValue(&'a str),
35 ParseFloat(core::num::ParseFloatError),
36}
37
38#[cfg(feature = "parser")]
39impl_debug_as_display!(DurationParseError<'a>);
40#[cfg(feature = "parser")]
41impl_display! { DurationParseError<'a>, {
42 InvalidValue(v) => format!("Invalid time value: \"{}\"", v),
43 ParseFloat(e) => format!("Invalid number for time value: {}", e),
44}}
45
46#[cfg(feature = "parser")]
48#[derive(Debug, Clone, PartialEq, Eq)]
49#[repr(C, u8)]
50pub enum DurationParseErrorOwned {
51 InvalidValue(AzString),
52 ParseFloat(AzString),
53}
54
55#[cfg(feature = "parser")]
56impl DurationParseError<'_> {
57 #[must_use] pub fn to_contained(&self) -> DurationParseErrorOwned {
58 match self {
59 Self::InvalidValue(s) => DurationParseErrorOwned::InvalidValue((*s).to_string().into()),
60 Self::ParseFloat(e) => DurationParseErrorOwned::ParseFloat(e.to_string().into()),
61 }
62 }
63}
64
65#[cfg(feature = "parser")]
66impl DurationParseErrorOwned {
67 #[must_use] pub fn to_shared(&self) -> DurationParseError<'_> {
68 match self {
69 Self::InvalidValue(s) => DurationParseError::InvalidValue(s),
70 Self::ParseFloat(s) => DurationParseError::InvalidValue(s.as_str()),
71 }
72 }
73}
74
75#[cfg(feature = "parser")]
77pub fn parse_duration(input: &str) -> Result<CssDuration, DurationParseError<'_>> {
81 let trimmed = input.trim().to_lowercase();
82 if trimmed == "0" {
83 return Ok(CssDuration { inner: 0 });
84 }
85 if let Some(num_str) = trimmed.strip_suffix("ms") {
86 let ms = num_str
87 .parse::<f32>()
88 .map_err(DurationParseError::ParseFloat)?;
89 if ms < 0.0 {
90 return Err(DurationParseError::InvalidValue(input));
91 }
92 Ok(CssDuration { inner: crate::cast::f32_to_u32(ms) })
93 } else if let Some(num_str) = trimmed.strip_suffix('s') {
94 let s = num_str
95 .parse::<f32>()
96 .map_err(DurationParseError::ParseFloat)?;
97 if s < 0.0 {
98 return Err(DurationParseError::InvalidValue(input));
99 }
100 Ok(CssDuration {
101 inner: crate::cast::f32_to_u32(s * 1000.0),
102 })
103 } else {
104 Err(DurationParseError::InvalidValue(input))
105 }
106}