diff --git a/src/builtin/color/other.rs b/src/builtin/color/other.rs index 568fbb3..cab3aa0 100644 --- a/src/builtin/color/other.rs +++ b/src/builtin/color/other.rs @@ -8,8 +8,9 @@ use crate::value::{Number, Value}; macro_rules! opt_rgba { ($args:ident, $name:ident, $arg:literal, $low:literal, $high:literal) => { + let x = $low; let $name = match arg!($args, -1, $arg = Value::Null) { - Value::Dimension(n, u) => Some(bound!($arg, n, u, $low, $high)), + Value::Dimension(n, u) => Some(bound!($arg, n, u, x, $high)), Value::Null => None, v => return Err(format!("${}: {} is not a number.", $arg, v).into()), }; @@ -18,8 +19,9 @@ macro_rules! opt_rgba { macro_rules! opt_hsl { ($args:ident, $name:ident, $arg:literal, $low:literal, $high:literal) => { + let x = $low; let $name = match arg!($args, -1, $arg = Value::Null) { - Value::Dimension(n, u) => Some(bound!($arg, n, u, $low, $high) / Number::from(100)), + Value::Dimension(n, u) => Some(bound!($arg, n, u, x, $high) / Number::from(100)), Value::Null => None, v => return Err(format!("${}: {} is not a number.", $arg, v).into()), }; @@ -129,12 +131,15 @@ pub(crate) fn register(f: &mut HashMap) { macro_rules! opt_scale_arg { ($args:ident, $name:ident, $arg:literal, $low:literal, $high:literal) => { + let x = $low; let $name = match arg!($args, -1, $arg = Value::Null) { Value::Dimension(n, Unit::Percent) => { - Some(bound!($arg, n, Unit::Percent, $low, $high) / Number::from(100)) + Some(bound!($arg, n, Unit::Percent, x, $high) / Number::from(100)) } v @ Value::Dimension(..) => { - return Err(format!("${}: Expected {} to have unit \"%\".", $arg, v).into()) + return Err( + format!("${}: Expected {} to have unit \"%\".", $arg, v).into() + ) } Value::Null => None, v => return Err(format!("${}: {} is not a number.", $arg, v).into()), diff --git a/src/builtin/macros.rs b/src/builtin/macros.rs index 50a59b1..950159c 100644 --- a/src/builtin/macros.rs +++ b/src/builtin/macros.rs @@ -53,6 +53,20 @@ macro_rules! bound { $arg } }; + // HACK: we accept `$low` as an ident here in order to work around + // a bug in the nightly compiler. + // https://github.com/rust-lang/rust/issues/70050 + ($name:literal, $arg:ident, $unit:ident, $low:ident, $high:literal) => { + if $arg > Number::from($high) || $arg < Number::from($low) { + return Err(format!( + "${}: Expected {}{} to be within {}{} and {}{}.", + $name, $arg, $unit, $low, $unit, $high, $unit, + ) + .into()); + } else { + $arg + } + }; ($name:literal, $arg:ident, $unit:path, $low:literal, $high:literal) => { if $arg > Number::from($high) || $arg < Number::from($low) { return Err(format!( @@ -64,4 +78,18 @@ macro_rules! bound { $arg } }; + // HACK: we accept `$low` as an ident here in order to work around + // a bug in the nightly compiler. + // https://github.com/rust-lang/rust/issues/70050 + ($name:literal, $arg:ident, $unit:path, $low:ident, $high:literal) => { + if $arg > Number::from($high) || $arg < Number::from($low) { + return Err(format!( + "${}: Expected {}{} to be within {}{} and {}{}.", + $name, $arg, $unit, $low, $unit, $high, $unit, + ) + .into()); + } else { + $arg + } + }; }