make better use of num traits

This commit is contained in:
ConnorSkees 2020-03-22 22:28:54 -04:00
parent 0e0b01f595
commit 0be8828bf0
12 changed files with 180 additions and 116 deletions

View File

@ -1,5 +1,7 @@
use std::collections::HashMap;
use num_traits::One;
use super::Builtin;
use crate::color::Color;
use crate::common::QuoteKind;
@ -46,7 +48,7 @@ pub(crate) fn register(f: &mut HashMap<String, Builtin>) {
hue,
saturation,
luminance,
Number::from(1),
Number::one(),
)))
} else {
let hue = match arg!(args, 0, "hue") {
@ -64,7 +66,7 @@ pub(crate) fn register(f: &mut HashMap<String, Builtin>) {
let alpha = match arg!(
args,
3,
"alpha" = Value::Dimension(Number::from(1), Unit::None)
"alpha" = Value::Dimension(Number::one(), Unit::None)
) {
Value::Dimension(n, Unit::None) => n,
Value::Dimension(n, Unit::Percent) => n / Number::from(100),
@ -120,7 +122,7 @@ pub(crate) fn register(f: &mut HashMap<String, Builtin>) {
hue,
saturation,
luminance,
Number::from(1),
Number::one(),
)))
} else {
let hue = match arg!(args, 0, "hue") {
@ -138,7 +140,7 @@ pub(crate) fn register(f: &mut HashMap<String, Builtin>) {
let alpha = match arg!(
args,
3,
"alpha" = Value::Dimension(Number::from(1), Unit::None)
"alpha" = Value::Dimension(Number::one(), Unit::None)
) {
Value::Dimension(n, Unit::None) => n,
Value::Dimension(n, Unit::Percent) => n / Number::from(100),
@ -280,7 +282,7 @@ pub(crate) fn register(f: &mut HashMap<String, Builtin>) {
}
v => return Err(format!("$color: {} is not a color.", v).into()),
};
Ok(Value::Color(color.desaturate(Number::from(1))))
Ok(Value::Color(color.desaturate(Number::one())))
}),
);
f.insert(

View File

@ -1,5 +1,7 @@
use std::collections::HashMap;
use num_traits::{One, Signed, Zero};
use super::Builtin;
use crate::color::Color;
use crate::common::QuoteKind;
@ -84,10 +86,10 @@ pub(crate) fn register(f: &mut HashMap<String, Builtin>) {
if red.is_some() || green.is_some() || blue.is_some() {
return Ok(Value::Color(Color::from_rgba(
color.red() + red.unwrap_or(Number::from(0)),
color.green() + green.unwrap_or(Number::from(0)),
color.blue() + blue.unwrap_or(Number::from(0)),
color.alpha() + alpha.unwrap_or(Number::from(0)),
color.red() + red.unwrap_or(Number::zero()),
color.green() + green.unwrap_or(Number::zero()),
color.blue() + blue.unwrap_or(Number::zero()),
color.alpha() + alpha.unwrap_or(Number::zero()),
)));
}
@ -104,10 +106,10 @@ pub(crate) fn register(f: &mut HashMap<String, Builtin>) {
// Color::as_hsla() returns more exact values than Color::hue(), etc.
let (this_hue, this_saturation, this_luminance, this_alpha) = color.as_hsla();
return Ok(Value::Color(Color::from_hsla(
this_hue + hue.unwrap_or(Number::from(0)),
this_saturation + saturation.unwrap_or(Number::from(0)),
this_luminance + luminance.unwrap_or(Number::from(0)),
this_alpha + alpha.unwrap_or(Number::from(0)),
this_hue + hue.unwrap_or(Number::zero()),
this_saturation + saturation.unwrap_or(Number::zero()),
this_luminance + luminance.unwrap_or(Number::zero()),
this_alpha + alpha.unwrap_or(Number::zero()),
)));
}
@ -154,23 +156,23 @@ pub(crate) fn register(f: &mut HashMap<String, Builtin>) {
return Ok(Value::Color(Color::from_rgba(
scale(
color.red(),
red.unwrap_or(Number::from(0)),
red.unwrap_or(Number::zero()),
Number::from(255),
),
scale(
color.green(),
green.unwrap_or(Number::from(0)),
green.unwrap_or(Number::zero()),
Number::from(255),
),
scale(
color.blue(),
blue.unwrap_or(Number::from(0)),
blue.unwrap_or(Number::zero()),
Number::from(255),
),
scale(
color.alpha(),
alpha.unwrap_or(Number::from(0)),
Number::from(1),
alpha.unwrap_or(Number::zero()),
Number::one(),
),
)));
}
@ -182,28 +184,24 @@ pub(crate) fn register(f: &mut HashMap<String, Builtin>) {
// Color::as_hsla() returns more exact values than Color::hue(), etc.
let (this_hue, this_saturation, this_luminance, this_alpha) = color.as_hsla();
return Ok(Value::Color(Color::from_hsla(
scale(this_hue, Number::from(0), Number::from(360)),
scale(this_hue, Number::zero(), Number::from(360)),
scale(
this_saturation,
saturation.unwrap_or(Number::from(0)),
Number::from(1),
saturation.unwrap_or(Number::zero()),
Number::one(),
),
scale(
this_luminance,
luminance.unwrap_or(Number::from(0)),
Number::from(1),
),
scale(
this_alpha,
alpha.unwrap_or(Number::from(0)),
Number::from(1),
luminance.unwrap_or(Number::zero()),
Number::one(),
),
scale(this_alpha, alpha.unwrap_or(Number::zero()), Number::one()),
)));
}
Ok(Value::Color(if let Some(a) = alpha {
let temp_alpha = color.alpha();
color.with_alpha(scale(temp_alpha, a, Number::from(1)))
color.with_alpha(scale(temp_alpha, a, Number::one()))
} else {
color
}))
@ -223,8 +221,8 @@ pub(crate) fn register(f: &mut HashMap<String, Builtin>) {
}
fn scale(val: Number, by: Number, max: Number) -> Number {
if by == Number::from(0) {
if by.is_zero() {
return val;
}
val.clone() + (if by > Number::from(0) { max - val } else { val }) * by
val.clone() + (if by.is_positive() { max - val } else { val }) * by
}

View File

@ -1,5 +1,7 @@
use std::collections::HashMap;
use num_traits::One;
use super::Builtin;
use crate::color::Color;
use crate::unit::Unit;
@ -50,7 +52,7 @@ pub(crate) fn register(f: &mut HashMap<String, Builtin>) {
None => return Err("Missing element $red.".into()),
};
let color = Color::from_rgba(red, green, blue, Number::from(1));
let color = Color::from_rgba(red, green, blue, Number::one());
Ok(Value::Color(color))
} else if args.len() == 2 {
@ -109,7 +111,7 @@ pub(crate) fn register(f: &mut HashMap<String, Builtin>) {
let alpha = match arg!(
args,
3,
"alpha" = Value::Dimension(Number::from(1), Unit::None)
"alpha" = Value::Dimension(Number::one(), Unit::None)
) {
Value::Dimension(n, Unit::None) => n,
Value::Dimension(n, Unit::Percent) => n / Number::from(100),
@ -168,7 +170,7 @@ pub(crate) fn register(f: &mut HashMap<String, Builtin>) {
None => return Err("Missing element $red.".into()),
};
let color = Color::from_rgba(red, green, blue, Number::from(1));
let color = Color::from_rgba(red, green, blue, Number::one());
Ok(Value::Color(color))
} else if args.len() == 2 {
@ -227,7 +229,7 @@ pub(crate) fn register(f: &mut HashMap<String, Builtin>) {
let alpha = match arg!(
args,
3,
"alpha" = Value::Dimension(Number::from(1), Unit::None)
"alpha" = Value::Dimension(Number::one(), Unit::None)
) {
Value::Dimension(n, Unit::None) => n,
Value::Dimension(n, Unit::Percent) => n / Number::from(100),

View File

@ -1,6 +1,6 @@
use std::collections::HashMap;
use num_traits::cast::ToPrimitive;
use num_traits::{One, Signed, ToPrimitive, Zero};
use super::Builtin;
use crate::common::{ListSeparator, QuoteKind};
@ -14,7 +14,7 @@ pub(crate) fn register(f: &mut HashMap<String, Builtin>) {
max_args!(args, 1);
let len = match arg!(args, 0, "list") {
Value::List(v, _) => Number::from(v.len()),
_ => Number::from(1),
_ => Number::one(),
};
Ok(Value::Dimension(len, Unit::None))
}),
@ -32,7 +32,7 @@ pub(crate) fn register(f: &mut HashMap<String, Builtin>) {
v => return Err(format!("$n: {} is not a number.", v).into()),
};
if n == Number::from(0) {
if n.is_zero() {
return Err("$n: List index may not be 0.".into());
}
@ -49,7 +49,7 @@ pub(crate) fn register(f: &mut HashMap<String, Builtin>) {
return Err(format!("$n: {} is not an int.", n).into());
}
if n > Number::from(0) {
if n.is_positive() {
Ok(list[n.to_integer().to_usize().unwrap() - 1].clone())
} else {
Ok(list[list.len() - n.abs().to_integer().to_usize().unwrap()].clone())
@ -83,7 +83,7 @@ pub(crate) fn register(f: &mut HashMap<String, Builtin>) {
v => return Err(format!("$n: {} is not a number.", v).into()),
};
if n == Number::from(0) {
if n.is_zero() {
return Err("$n: List index may not be 0.".into());
}
@ -101,7 +101,7 @@ pub(crate) fn register(f: &mut HashMap<String, Builtin>) {
let val = arg!(args, 2, "value");
if n > Number::from(0) {
if n.is_positive() {
list[n.to_integer().to_usize().unwrap() - 1] = val;
} else {
list[len - n.abs().to_integer().to_usize().unwrap()] = val;

View File

@ -1,8 +1,7 @@
use std::collections::HashMap;
use num_bigint::BigInt;
use num_traits::cast::ToPrimitive;
use num_traits::sign::Signed;
use num_traits::{Signed, ToPrimitive, Zero};
use super::Builtin;
use crate::common::QuoteKind;
@ -35,7 +34,10 @@ pub(crate) fn register(f: &mut HashMap<String, Builtin>) {
Box::new(|args, _| {
max_args!(args, 1);
match arg!(args, 0, "string") {
Value::Ident(i, _) => Ok(Value::Dimension(Number::from(i.chars().count()), Unit::None)),
Value::Ident(i, _) => Ok(Value::Dimension(
Number::from(i.chars().count()),
Unit::None,
)),
v => Err(format!("$string: {} is not a string.", v).into()),
}
}),
@ -73,10 +75,10 @@ pub(crate) fn register(f: &mut HashMap<String, Builtin>) {
Value::Dimension(n, Unit::None) if n.is_decimal() => {
return Err(format!("{} is not an int.", n).into())
}
Value::Dimension(n, Unit::None) if n.to_integer().is_positive() => {
Value::Dimension(n, Unit::None) if n.is_positive() => {
n.to_integer().to_usize().unwrap()
}
Value::Dimension(n, Unit::None) if n == Number::from(0) => 1_usize,
Value::Dimension(n, Unit::None) if n.is_zero() => 1_usize,
Value::Dimension(n, Unit::None) if n < -Number::from(str_len) => 1_usize,
Value::Dimension(n, Unit::None) => (BigInt::from(str_len + 1) + n.to_integer())
.to_usize()
@ -90,10 +92,10 @@ pub(crate) fn register(f: &mut HashMap<String, Builtin>) {
Value::Dimension(n, Unit::None) if n.is_decimal() => {
return Err(format!("{} is not an int.", n).into())
}
Value::Dimension(n, Unit::None) if n.to_integer().is_positive() => {
Value::Dimension(n, Unit::None) if n.is_positive() => {
n.to_integer().to_usize().unwrap()
}
Value::Dimension(n, Unit::None) if n == Number::from(0) => 0_usize,
Value::Dimension(n, Unit::None) if n.is_zero() => 0_usize,
Value::Dimension(n, Unit::None) if n < -Number::from(str_len) => 0_usize,
Value::Dimension(n, Unit::None) => (BigInt::from(str_len + 1) + n.to_integer())
.to_usize()
@ -197,13 +199,13 @@ pub(crate) fn register(f: &mut HashMap<String, Builtin>) {
.collect::<String>()
};
let string = if index > Number::from(0) {
let string = if index.is_positive() {
insert(
index.to_integer().to_usize().unwrap().min(len + 1) - 1,
s1,
&substr,
)
} else if index == Number::from(0) {
} else if index.is_zero() {
insert(0, s1, &substr)
} else {
let idx = index.abs().to_integer().to_usize().unwrap();

View File

@ -20,7 +20,7 @@ use std::fmt::{self, Display};
use crate::value::Number;
pub(crate) use name::ColorName;
use num_traits::cast::ToPrimitive;
use num_traits::{One, Signed, ToPrimitive, Zero};
mod name;
@ -149,8 +149,8 @@ impl Color {
($channel:ident) => {
let $channel = if $channel > Number::from(255) {
Number::from(255)
} else if $channel < Number::from(0) {
Number::from(0)
} else if $channel.is_negative() {
Number::zero()
} else {
$channel
};
@ -161,10 +161,10 @@ impl Color {
clamp!(green);
clamp!(blue);
let alpha = if alpha > Number::from(1) {
Number::from(1)
} else if alpha < Number::from(0) {
Number::from(0)
let alpha = if alpha > Number::one() {
Number::one()
} else if alpha.is_negative() {
Number::zero()
} else {
alpha
};
@ -190,7 +190,7 @@ impl Color {
/// <https://github.com/sass/dart-sass/blob/0d0270cb12a9ac5cce73a4d0785fecb00735feee/lib/src/functions/color.dart#L718>
pub fn mix(self, other: &Color, weight: Number) -> Self {
let weight = clamp!(weight, 0, 100);
let normalized_weight = weight.clone() * Number::from(2) - Number::from(1);
let normalized_weight = weight.clone() * Number::from(2) - Number::one();
let alpha_distance = self.alpha() - other.alpha();
let combined_weight1 =
@ -198,16 +198,16 @@ impl Color {
normalized_weight
} else {
(normalized_weight.clone() + alpha_distance.clone())
/ (Number::from(1) + normalized_weight * alpha_distance)
/ (Number::one() + normalized_weight * alpha_distance)
};
let weight1 = (combined_weight1 + Number::from(1)) / Number::from(2);
let weight2 = Number::from(1) - weight1.clone();
let weight1 = (combined_weight1 + Number::one()) / Number::from(2);
let weight2 = Number::one() - weight1.clone();
Color::from_rgba(
self.red() * weight1.clone() + other.red() * weight2.clone(),
self.green() * weight1.clone() + other.green() * weight2.clone(),
self.blue() * weight1 + other.blue() * weight2,
self.alpha() * weight.clone() + other.alpha() * (Number::from(1) - weight),
self.alpha() * weight.clone() + other.alpha() * (Number::one() - weight),
)
}
}
@ -227,7 +227,7 @@ impl Color {
let min = red.clone().min(green.clone().min(blue.clone()));
let max = red.clone().max(green.clone().max(blue.clone()));
if min == max {
return Number::from(0);
return Number::zero();
}
let mut hue = if blue == max {
@ -238,7 +238,7 @@ impl Color {
(green - blue) / (max - min)
};
if hue < Number::from(0) {
if hue.is_negative() {
hue += Number::from(360);
}
@ -259,12 +259,12 @@ impl Color {
let max = red.max(green.max(blue));
if min == max {
return Number::from(0);
return Number::zero();
}
let d = max.clone() - min.clone();
let mm = max + min;
let s = d / if mm > Number::from(1) {
let s = d / if mm > Number::one() {
Number::from(2) - mm
} else {
mm
@ -300,11 +300,11 @@ impl Color {
let lightness = (min.clone() + max.clone()) / Number::from(2);
let saturation = if min == max {
Number::from(0)
Number::zero()
} else {
let d = max.clone() - min.clone();
let mm = max.clone() + min.clone();
d / if mm > Number::from(1) {
d / if mm > Number::one() {
Number::from(2) - mm
} else {
mm
@ -312,7 +312,7 @@ impl Color {
};
let mut hue = if min == max {
Number::from(0)
Number::zero()
} else if blue == max {
Number::from(4) + (red - green) / (max - min)
} else if green == max {
@ -321,7 +321,7 @@ impl Color {
(green - blue) / (max - min)
};
if hue < Number::from(0) {
if hue.is_negative() {
hue += Number::from(360);
}
@ -361,7 +361,7 @@ impl Color {
hue % Number::from(360)
} else if hue < Number::from(-360) {
Number::from(360) + hue % Number::from(360)
} else if hue < Number::from(0) {
} else if hue.is_negative() {
Number::from(360) + clamp!(hue, -360, 360)
} else {
hue
@ -378,7 +378,7 @@ impl Color {
alpha.clone(),
);
if saturation.clone() == Number::from(0) {
if saturation.is_zero() {
let luminance = if luminance > Number::from(100) {
Number::from(100)
} else {
@ -388,8 +388,8 @@ impl Color {
let repr = repr(&val, &val, &val, &alpha);
return Color::new_hsla(val.clone(), val.clone(), val, alpha, hsla, repr);
}
let temporary_1 = if luminance.clone() < Number::ratio(1, 2) {
luminance.clone() * (Number::from(1) + saturation)
let temporary_1 = if luminance < Number::ratio(1, 2) {
luminance.clone() * (Number::one() + saturation)
} else {
luminance.clone() + saturation.clone() - luminance.clone() * saturation
};
@ -401,10 +401,10 @@ impl Color {
macro_rules! clamp_temp {
($temp:ident) => {
if $temp > Number::from(1) {
$temp -= Number::from(1);
} else if $temp < Number::from(0) {
$temp += Number::from(1);
if $temp > Number::one() {
$temp -= Number::one();
} else if $temp.is_negative() {
$temp += Number::one();
}
};
}
@ -415,10 +415,10 @@ impl Color {
macro_rules! channel {
($name:ident, $temp:ident, $temp1:ident, $temp2:ident) => {
let $name = if Number::from(6) * $temp.clone() < Number::from(1) {
let $name = if Number::from(6) * $temp.clone() < Number::one() {
$temp2.clone()
+ ($temp1.clone() - $temp2.clone()) * Number::from(6) * $temp.clone()
} else if Number::from(2) * $temp.clone() < Number::from(1) {
} else if Number::from(2) * $temp.clone() < Number::one() {
$temp1.clone()
} else if Number::from(3) * $temp.clone() < Number::from(2) {
$temp2.clone()
@ -440,7 +440,7 @@ impl Color {
}
pub fn invert(&self, weight: Number) -> Self {
if weight == Number::from(0) {
if weight.is_zero() {
return self.clone();
}
let red = Number::from(u8::max_value()) - self.red();
@ -466,7 +466,7 @@ impl Color {
impl Color {
pub fn alpha(&self) -> Number {
let a = self.rgba.alpha();
if a > Number::from(1) {
if a > Number::one() {
a / Number::from(255)
} else {
a
@ -512,7 +512,7 @@ fn repr(red: &Number, green: &Number, blue: &Number, alpha: &Number) -> String {
($channel:ident) => {
let $channel = if $channel > &Number::from(255) {
255_u8
} else if $channel < &Number::from(0) {
} else if $channel.is_negative() {
0_u8
} else {
$channel.clone().round().to_integer().to_u8().unwrap()
@ -524,7 +524,7 @@ fn repr(red: &Number, green: &Number, blue: &Number, alpha: &Number) -> String {
into_u8!(green);
into_u8!(blue);
if alpha < &Number::from(1) {
if alpha < &Number::one() {
format!("rgba({}, {}, {}, {})", red, green, blue, alpha)
} else if let Ok(c) = ColorName::try_from([red, green, blue]) {
format!("{}", c)

View File

@ -208,10 +208,10 @@ impl<'a> Lexer<'a> {
self.buf.next();
self.pos.next_char();
if let TokenKind::Ident(s) = self.lex_ident() {
if !s.is_empty() {
TokenKind::AtRule(AtRuleKind::from(s.as_ref()))
} else {
if s.is_empty() {
TokenKind::Error("Expected identifier.".into())
} else {
TokenKind::AtRule(AtRuleKind::from(s.as_ref()))
}
} else {
TokenKind::Error("Expected identifier.".into())

View File

@ -416,7 +416,7 @@ impl<'a> StyleSheetParser<'a> {
AtRule::If(cond, yes, no) => {
if Value::from_tokens(
&mut cond.into_iter().peekable(),
&mut GLOBAL_SCOPE.with(|s| s.borrow().clone()),
&GLOBAL_SCOPE.with(|s| s.borrow().clone()),
&Selector::new(),
)?.is_true()? {
rules.extend(yes);
@ -453,7 +453,7 @@ impl<'a> StyleSheetParser<'a> {
AtRule::If(cond, yes, no) => {
if Value::from_tokens(
&mut cond.into_iter().peekable(),
&mut GLOBAL_SCOPE.with(|s| s.borrow().clone()),
&GLOBAL_SCOPE.with(|s| s.borrow().clone()),
&Selector::new(),
)?
.is_true()?

View File

@ -6,6 +6,7 @@ use std::collections::HashMap;
use std::f64::consts::PI;
use std::string::ToString;
use num_traits::One;
use once_cell::sync::Lazy;
use crate::value::Number;
@ -13,17 +14,17 @@ use crate::value::Number;
pub(crate) static UNIT_CONVERSION_TABLE: Lazy<HashMap<String, HashMap<String, Number>>> =
Lazy::new(|| {
let mut from_in = HashMap::new();
from_in.insert("in".to_string(), Number::from(1));
from_in.insert("cm".to_string(), Number::from(1) / Number::from(2.54));
from_in.insert("in".to_string(), Number::one());
from_in.insert("cm".to_string(), Number::one() / Number::from(2.54));
from_in.insert("pc".to_string(), Number::ratio(1, 6));
from_in.insert("mm".to_string(), Number::from(1) / Number::from(25.4));
from_in.insert("q".to_string(), Number::from(1) / Number::from(101.6));
from_in.insert("mm".to_string(), Number::one() / Number::from(25.4));
from_in.insert("q".to_string(), Number::one() / Number::from(101.6));
from_in.insert("pt".to_string(), Number::ratio(1, 72));
from_in.insert("px".to_string(), Number::ratio(1, 96));
let mut from_cm = HashMap::new();
from_cm.insert("in".to_string(), Number::from(2.54));
from_cm.insert("cm".to_string(), Number::from(1));
from_cm.insert("cm".to_string(), Number::one());
from_cm.insert("pc".to_string(), Number::from(2.54) / Number::from(6));
from_cm.insert("mm".to_string(), Number::ratio(1, 10));
from_cm.insert("q".to_string(), Number::ratio(1, 40));
@ -33,7 +34,7 @@ pub(crate) static UNIT_CONVERSION_TABLE: Lazy<HashMap<String, HashMap<String, Nu
let mut from_pc = HashMap::new();
from_pc.insert("in".to_string(), Number::from(6));
from_pc.insert("cm".to_string(), Number::from(6) / Number::from(2.54));
from_pc.insert("pc".to_string(), Number::from(1));
from_pc.insert("pc".to_string(), Number::one());
from_pc.insert("mm".to_string(), Number::from(6) / Number::from(25.4));
from_pc.insert("q".to_string(), Number::from(6) / Number::from(101.6));
from_pc.insert("pt".to_string(), Number::ratio(1, 12));
@ -43,7 +44,7 @@ pub(crate) static UNIT_CONVERSION_TABLE: Lazy<HashMap<String, HashMap<String, Nu
from_mm.insert("in".to_string(), Number::from(25.4));
from_mm.insert("cm".to_string(), Number::from(10));
from_mm.insert("pc".to_string(), Number::from(25.4) / Number::from(6));
from_mm.insert("mm".to_string(), Number::from(1));
from_mm.insert("mm".to_string(), Number::one());
from_mm.insert("q".to_string(), Number::ratio(1, 4));
from_mm.insert("pt".to_string(), Number::from(25.4) / Number::from(72));
from_mm.insert("px".to_string(), Number::from(25.4) / Number::from(96));
@ -53,7 +54,7 @@ pub(crate) static UNIT_CONVERSION_TABLE: Lazy<HashMap<String, HashMap<String, Nu
from_q.insert("cm".to_string(), Number::from(40));
from_q.insert("pc".to_string(), Number::from(101.6) / Number::from(6));
from_q.insert("mm".to_string(), Number::from(4));
from_q.insert("q".to_string(), Number::from(1));
from_q.insert("q".to_string(), Number::one());
from_q.insert("pt".to_string(), Number::from(101.6) / Number::from(72));
from_q.insert("px".to_string(), Number::from(101.6) / Number::from(96));
@ -63,7 +64,7 @@ pub(crate) static UNIT_CONVERSION_TABLE: Lazy<HashMap<String, HashMap<String, Nu
from_pt.insert("pc".to_string(), Number::from(12));
from_pt.insert("mm".to_string(), Number::from(72) / Number::from(25.4));
from_pt.insert("q".to_string(), Number::from(72) / Number::from(101.6));
from_pt.insert("pt".to_string(), Number::from(1));
from_pt.insert("pt".to_string(), Number::one());
from_pt.insert("px".to_string(), Number::ratio(3, 4));
let mut from_px = HashMap::new();
@ -73,62 +74,62 @@ pub(crate) static UNIT_CONVERSION_TABLE: Lazy<HashMap<String, HashMap<String, Nu
from_px.insert("mm".to_string(), Number::from(96) / Number::from(25.4));
from_px.insert("q".to_string(), Number::from(96) / Number::from(101.6));
from_px.insert("pt".to_string(), Number::ratio(4, 3));
from_px.insert("px".to_string(), Number::from(1));
from_px.insert("px".to_string(), Number::one());
let mut from_deg = HashMap::new();
from_deg.insert("deg".to_string(), Number::from(1));
from_deg.insert("deg".to_string(), Number::one());
from_deg.insert("grad".to_string(), Number::ratio(9, 10));
from_deg.insert("rad".to_string(), Number::from(180) / Number::from(PI));
from_deg.insert("turn".to_string(), Number::from(360));
let mut from_grad = HashMap::new();
from_grad.insert("deg".to_string(), Number::ratio(10, 9));
from_grad.insert("grad".to_string(), Number::from(1));
from_grad.insert("grad".to_string(), Number::one());
from_grad.insert("rad".to_string(), Number::from(200) / Number::from(PI));
from_grad.insert("turn".to_string(), Number::from(400));
let mut from_rad = HashMap::new();
from_rad.insert("deg".to_string(), Number::from(PI) / Number::from(180));
from_rad.insert("grad".to_string(), Number::from(PI) / Number::from(200));
from_rad.insert("rad".to_string(), Number::from(1));
from_rad.insert("rad".to_string(), Number::one());
from_rad.insert("turn".to_string(), Number::from(2.0 * PI));
let mut from_turn = HashMap::new();
from_turn.insert("deg".to_string(), Number::ratio(1, 360));
from_turn.insert("grad".to_string(), Number::ratio(1, 400));
from_turn.insert("rad".to_string(), Number::from(1) / Number::from(2.0 * PI));
from_turn.insert("turn".to_string(), Number::from(1));
from_turn.insert("rad".to_string(), Number::one() / Number::from(2.0 * PI));
from_turn.insert("turn".to_string(), Number::one());
let mut from_s = HashMap::new();
from_s.insert("s".to_string(), Number::from(1));
from_s.insert("s".to_string(), Number::one());
from_s.insert("ms".to_string(), Number::ratio(1, 1000));
let mut from_ms = HashMap::new();
from_ms.insert("s".to_string(), Number::from(1000));
from_ms.insert("ms".to_string(), Number::from(1));
from_ms.insert("ms".to_string(), Number::one());
let mut from_hz = HashMap::new();
from_hz.insert("Hz".to_string(), Number::from(1));
from_hz.insert("Hz".to_string(), Number::one());
from_hz.insert("kHz".to_string(), Number::from(1000));
let mut from_khz = HashMap::new();
from_khz.insert("Hz".to_string(), Number::ratio(1, 1000));
from_khz.insert("kHz".to_string(), Number::from(1));
from_khz.insert("kHz".to_string(), Number::one());
let mut from_dpi = HashMap::new();
from_dpi.insert("dpi".to_string(), Number::from(1));
from_dpi.insert("dpi".to_string(), Number::one());
from_dpi.insert("dpcm".to_string(), Number::from(2.54));
from_dpi.insert("dppx".to_string(), Number::from(96));
let mut from_dpcm = HashMap::new();
from_dpcm.insert("dpi".to_string(), Number::from(1) / Number::from(2.54));
from_dpcm.insert("dpcm".to_string(), Number::from(1));
from_dpcm.insert("dpi".to_string(), Number::one() / Number::from(2.54));
from_dpcm.insert("dpcm".to_string(), Number::one());
from_dpcm.insert("dppx".to_string(), Number::from(96) / Number::from(2.54));
let mut from_dppx = HashMap::new();
from_dppx.insert("dpi".to_string(), Number::ratio(1, 96));
from_dppx.insert("dpcm".to_string(), Number::from(2.54) / Number::from(96));
from_dppx.insert("dppx".to_string(), Number::from(1));
from_dppx.insert("dppx".to_string(), Number::one());
let mut m = HashMap::new();
m.insert("in".to_string(), from_in);

View File

@ -102,7 +102,7 @@ impl Value {
match self {
&Value::Null => true,
Value::Ident(i, QuoteKind::None) if i.is_empty() => true,
_ => false
_ => false,
}
}

View File

@ -6,7 +6,9 @@ use std::ops::{
use num_bigint::BigInt;
use num_rational::BigRational;
use num_traits::sign::Signed;
use num_traits::{Num, One, Signed, Zero};
use crate::error::SassError;
const PRECISION: usize = 10;
@ -57,6 +59,63 @@ impl Number {
}
}
impl Zero for Number {
fn zero() -> Self {
Number::from(0)
}
fn is_zero(&self) -> bool {
self.val.is_zero()
}
}
impl One for Number {
fn one() -> Self {
Number::from(1)
}
fn is_one(&self) -> bool {
self.val.is_one()
}
}
impl Num for Number {
type FromStrRadixErr = SassError;
fn from_str_radix(_str: &str, _radix: u32) -> Result<Self, Self::FromStrRadixErr> {
todo!()
}
}
impl Signed for Number {
fn abs(&self) -> Self {
self.abs()
}
fn abs_sub(&self, other: &Self) -> Self {
Number {
val: self.val.abs_sub(&other.val),
}
}
fn signum(&self) -> Self {
if self.is_zero() {
Self::zero()
} else if self.is_positive() {
Self::one()
} else {
-Self::one()
}
}
fn is_positive(&self) -> bool {
self.val.is_positive()
}
fn is_negative(&self) -> bool {
self.val.is_negative()
}
}
impl fmt::LowerHex for Number {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{:0>2x}", self.val.to_integer())

View File

@ -293,7 +293,7 @@ impl Value {
TokenKind::Keyword(Keyword::Through(s)) => Ok(Value::Ident(s, QuoteKind::None)),
TokenKind::Keyword(Keyword::To(s)) => Ok(Value::Ident(s, QuoteKind::None)),
TokenKind::AtRule(_) => Err("expected \";\".".into()),
TokenKind::Error(e) => return Err(e),
TokenKind::Error(e) => Err(e),
TokenKind::Symbol(Symbol::BackSlash) => {
if let Some(tok) = toks.next() {
match tok.kind {