macro_rules! create_unit_items {
{ $( $variant:tt => $function:tt => $literal_unit:tt ),* $(,)?} => {
#[macro_export]
macro_rules! unit {
{ $value:expr } => {
{
$value.to_string()
}
};
$(
{ $value:expr, $literal_unit } => {
{
$value.to_string() + stringify!($literal_unit)
}
};
)*
{ $value:expr, $unit:expr } => {
{
let unit: Unit = $unit;
format!("{}{}", $value, unit)
}
};
}
#[allow(dead_code)]
#[derive(Clone, Copy)]
pub enum Unit {
$($variant,)*
}
impl std::fmt::Display for Unit {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
let text_unit = match self {
$(Unit::$variant => stringify!($literal_unit),)*
};
write!(f, "{}", text_unit)
}
}
$(
#[allow(dead_code)]
pub fn $function(value: impl std::fmt::Display) -> String {
format!("{}{}", value, stringify!($literal_unit))
}
)*
}
}
create_unit_items! {
Ch => ch => ch,
Cm => cm => cm,
Em => em => em,
Fr => fr => fr,
Ex => ex => ex,
In => inch => in,
Mm => mm => mm,
Pc => pc => pc,
Percent => percent => %,
Pt => pt => pt,
Px => px => px,
Q => q => q,
Rem => rem => rem,
Vh => vh => vh,
Vmin => vmin => vmin,
Vmax => vmax => vmax,
Vw => vw => vw,
}
#[cfg(test)]
pub mod tests {
use super::*;
use wasm_bindgen_test::*;
#[wasm_bindgen_test]
fn variable() {
let width = -100;
assert_eq!(unit!(width, px), "-100px");
}
#[wasm_bindgen_test]
fn expression() {
assert_eq!(unit!(100 + 350, px), "450px");
}
#[wasm_bindgen_test]
fn without_unit() {
assert_eq!(unit!(2.5), "2.5");
}
#[wasm_bindgen_test]
fn str_with_variant() {
assert_eq!(unit!("68", Unit::Mm), "68mm");
}
#[wasm_bindgen_test]
fn percent_unit() {
assert_eq!(unit!(15_236.56f64, %), "15236.56%");
}
#[wasm_bindgen_test]
fn in_unit_with_negative_zero() {
assert_eq!(unit!(-0, in), "0in");
}
#[wasm_bindgen_test]
fn px_function() {
assert_eq!(px(15), "15px");
}
#[wasm_bindgen_test]
fn inch_function() {
assert_eq!(inch(-15.63), "-15.63in");
}
#[wasm_bindgen_test]
fn percent_function() {
assert_eq!(percent("35"), "35%");
}
}