Skip to main content

whisker_css/data_type/
time.rs

1//! `<time>` — a duration.
2//!
3//! Lynx reference: <https://lynxjs.org/api/css/data-type/time.html>
4//!
5//! Lynx accepts two CSS time units:
6//!
7//! | Variant | CSS | Notes |
8//! |---|---|---|
9//! | [`Time::S`]  | `s`  | Seconds, may be negative |
10//! | [`Time::Ms`] | `ms` | Milliseconds, may be negative |
11//!
12//! Unlike `<length>`, **a bare `0` is not a valid `<time>`** in
13//! Lynx — you must write `0s` or `0ms`. This is enforced by the
14//! shape of the enum: there is no zero variant.
15
16use core::fmt;
17
18use crate::to_css::{write_number, ToCss};
19
20/// A CSS `<time>` value.
21#[derive(Copy, Clone, Debug, PartialEq)]
22pub enum Time {
23    /// Seconds (`s`).
24    S(f32),
25    /// Milliseconds (`ms`).
26    Ms(f32),
27}
28
29impl ToCss for Time {
30    fn to_css(&self, dest: &mut dyn fmt::Write) -> fmt::Result {
31        let (v, unit) = match *self {
32            Time::S(v) => (v, "s"),
33            Time::Ms(v) => (v, "ms"),
34        };
35        write_number(dest, v)?;
36        dest.write_str(unit)
37    }
38}
39
40#[cfg(test)]
41mod tests {
42    use super::*;
43
44    #[test]
45    fn each_unit_serializes() {
46        assert_eq!(Time::S(1.5).to_css_string(), "1.5s");
47        assert_eq!(Time::Ms(300.0).to_css_string(), "300ms");
48    }
49
50    #[test]
51    fn negative_time() {
52        // Negative delays are valid in `transition-delay`.
53        assert_eq!(Time::Ms(-100.0).to_css_string(), "-100ms");
54    }
55
56    #[test]
57    fn zero_keeps_unit() {
58        // Crucial: a bare `0` is invalid; we always emit the unit.
59        assert_eq!(Time::S(0.0).to_css_string(), "0s");
60        assert_eq!(Time::Ms(0.0).to_css_string(), "0ms");
61    }
62}