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::format_rust_code::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)]
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)]
49#[repr(C, u8)]
50pub enum DurationParseErrorOwned {
51 InvalidValue(AzString),
52 ParseFloat(AzString),
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().into()),
60 Self::ParseFloat(e) => DurationParseErrorOwned::ParseFloat(e.to_string().into()),
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(s.as_str()),
71 }
72 }
73}
74
75#[cfg(feature = "parser")]
77pub fn parse_duration<'a>(input: &'a str) -> Result<CssDuration, DurationParseError<'a>> {
78 let trimmed = input.trim().to_lowercase();
79 if trimmed == "0" {
80 return Ok(CssDuration { inner: 0 });
81 }
82 if let Some(num_str) = trimmed.strip_suffix("ms") {
83 let ms = num_str
84 .parse::<f32>()
85 .map_err(DurationParseError::ParseFloat)?;
86 if ms < 0.0 {
87 return Err(DurationParseError::InvalidValue(input));
88 }
89 Ok(CssDuration { inner: ms as u32 })
90 } else if let Some(num_str) = trimmed.strip_suffix('s') {
91 let s = num_str
92 .parse::<f32>()
93 .map_err(DurationParseError::ParseFloat)?;
94 if s < 0.0 {
95 return Err(DurationParseError::InvalidValue(input));
96 }
97 Ok(CssDuration {
98 inner: (s * 1000.0) as u32,
99 })
100 } else {
101 Err(DurationParseError::InvalidValue(input))
102 }
103}