use core::fmt;
pub trait ToCss {
fn to_css(&self, dest: &mut dyn fmt::Write) -> fmt::Result;
fn to_css_string(&self) -> String {
let mut s = String::new();
let _ = self.to_css(&mut s);
s
}
}
impl<T: ToCss + ?Sized> ToCss for &T {
fn to_css(&self, dest: &mut dyn fmt::Write) -> fmt::Result {
(**self).to_css(dest)
}
}
pub(crate) fn write_number(dest: &mut dyn fmt::Write, n: f32) -> fmt::Result {
if n.fract() == 0.0 && n.is_finite() && n.abs() < 1e16 {
write!(dest, "{}", n as i64)
} else {
write!(dest, "{n}")
}
}
pub(crate) fn number_to_string(n: f32) -> String {
let mut s = String::new();
let _ = write_number(&mut s, n);
s
}
#[cfg(test)]
mod tests {
use super::*;
struct Token(&'static str);
impl ToCss for Token {
fn to_css(&self, dest: &mut dyn fmt::Write) -> fmt::Result {
dest.write_str(self.0)
}
}
#[test]
fn write_number_drops_decimal_for_integers() {
let mut buf = String::new();
write_number(&mut buf, 1.0).unwrap();
assert_eq!(buf, "1");
buf.clear();
write_number(&mut buf, -3.0).unwrap();
assert_eq!(buf, "-3");
buf.clear();
write_number(&mut buf, 0.0).unwrap();
assert_eq!(buf, "0");
}
#[test]
fn write_number_keeps_decimal_for_fractions() {
let mut buf = String::new();
write_number(&mut buf, 0.5).unwrap();
assert_eq!(buf, "0.5");
buf.clear();
write_number(&mut buf, -1.25).unwrap();
assert_eq!(buf, "-1.25");
}
#[test]
fn write_number_handles_non_finite_safely() {
let mut buf = String::new();
let _ = write_number(&mut buf, f32::NAN);
let _ = write_number(&mut buf, f32::INFINITY);
assert!(!buf.is_empty());
}
#[test]
fn write_number_handles_huge_floats() {
let mut buf = String::new();
write_number(&mut buf, 1e20).unwrap();
assert!(!buf.is_empty());
}
#[test]
fn number_to_string_matches_write_number() {
assert_eq!(number_to_string(1.0), "1");
assert_eq!(number_to_string(0.25), "0.25");
assert_eq!(number_to_string(-2.5), "-2.5");
}
#[test]
fn to_css_blanket_reference_impl() {
let t = Token("ident");
let r: &Token = &t;
let s = r.to_css_string();
assert_eq!(s, "ident");
}
#[test]
fn to_css_string_uses_the_same_path() {
let t = Token("abc");
assert_eq!(t.to_css_string(), "abc");
}
}