refactor Number::to_integer

This commit is contained in:
ConnorSkees 2020-05-20 22:40:21 -04:00
parent 38ffb5fe31
commit 45a29c9697
3 changed files with 155 additions and 9 deletions

View File

@ -131,7 +131,7 @@ fn str_slice(mut args: CallArgs, scope: &Scope, super_selector: &Selector) -> Sa
}
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())
Value::Dimension(n, Unit::None) => (n.to_integer() + BigInt::from(str_len + 1))
.to_usize()
.unwrap(),
v @ Value::Dimension(..) => {
@ -164,7 +164,7 @@ fn str_slice(mut args: CallArgs, scope: &Scope, super_selector: &Selector) -> Sa
}
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())
Value::Dimension(n, Unit::None) => (n.to_integer() + BigInt::from(str_len + 1))
.to_usize()
.unwrap_or(str_len + 1),
v @ Value::Dimension(..) => {

View File

@ -471,7 +471,7 @@ impl Color {
impl Color {
pub fn to_ie_hex_str(&self) -> String {
format!(
"#{:02X}{:02X}{:02X}{:02X}",
"#{:X}{:X}{:X}{:X}",
(self.alpha() * Number::from(255)).round().to_integer(),
self.red().to_integer(),
self.green().to_integer(),

View File

@ -1,6 +1,6 @@
use std::cmp::Ordering;
use std::convert::{From, TryFrom};
use std::fmt::{self, Display, Write};
use std::fmt::{self, Display, UpperHex, Write};
use std::mem;
use std::ops::{
Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Rem, RemAssign, Sub, SubAssign,
@ -8,10 +8,156 @@ use std::ops::{
use num_bigint::BigInt;
use num_rational::{BigRational, Rational64};
use num_traits::{CheckedAdd, CheckedDiv, CheckedMul, CheckedSub, Num, One, Signed, Zero};
use num_traits::{
CheckedAdd, CheckedDiv, CheckedMul, CheckedSub, Num, One, Signed, ToPrimitive, Zero,
};
const PRECISION: usize = 10;
#[derive(Eq, PartialEq)]
pub(crate) enum Integer {
Machine(i64),
Big(BigInt),
}
impl Default for Integer {
fn default() -> Self {
Self::zero()
}
}
impl UpperHex for Integer {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Machine(v) => write!(f, "{:02X}", v),
Self::Big(v) => write!(f, "{:02X}", v),
}
}
}
impl Add for Integer {
type Output = Self;
fn add(self, rhs: Self) -> Self::Output {
match self {
Self::Machine(val1) => match rhs {
Self::Machine(val2) => match val1.checked_add(val2) {
Some(v) => Self::Machine(v),
None => Self::Big(BigInt::from(val1) + val2),
},
Self::Big(val2) => Self::Big(BigInt::from(val1) + val2),
},
Self::Big(val1) => match rhs {
Self::Big(val2) => Self::Big(val1 + val2),
Self::Machine(val2) => Self::Big(val1 + BigInt::from(val2)),
},
}
}
}
impl Add<BigInt> for Integer {
type Output = Self;
fn add(self, rhs: BigInt) -> Self::Output {
match self {
Self::Machine(v) => Self::Big(BigInt::from(v) + rhs),
Self::Big(v) => Self::Big(v + rhs),
}
}
}
impl Add<i32> for Integer {
type Output = Self;
fn add(self, rhs: i32) -> Self::Output {
match self {
Self::Machine(v) => match v.checked_add(rhs as i64) {
Some(v) => Self::Machine(v),
None => Self::Big(BigInt::from(v) + rhs),
},
Self::Big(v) => Self::Big(v + rhs),
}
}
}
impl AddAssign<i32> for Integer {
fn add_assign(&mut self, rhs: i32) {
let tmp = mem::take(self);
*self = tmp + rhs;
}
}
impl AddAssign for Integer {
fn add_assign(&mut self, rhs: Self) {
let tmp = mem::take(self);
*self = tmp + rhs;
}
}
impl Zero for Integer {
fn zero() -> Self {
Self::Machine(0)
}
fn is_zero(&self) -> bool {
match self {
Self::Machine(0) => true,
Self::Machine(..) => false,
Self::Big(v) => v.is_zero(),
}
}
fn set_zero(&mut self) {
*self = Self::zero()
}
}
impl Integer {
fn abs(&self) -> Self {
match self {
Self::Machine(v) => Self::Machine(v.abs()),
Self::Big(v) => Self::Big(v.abs()),
}
}
fn is_ten(&self) -> bool {
match self {
Self::Machine(10) => true,
Self::Machine(..) => false,
Self::Big(v) => v == &BigInt::from(10),
}
}
}
impl Display for Integer {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Machine(v) => write!(f, "{}", v),
Self::Big(v) => write!(f, "{}", v),
}
}
}
impl ToPrimitive for Integer {
fn to_u8(&self) -> Option<u8> {
match self {
Self::Machine(v) => v.to_u8(),
Self::Big(v) => v.to_u8(),
}
}
fn to_u64(&self) -> Option<u64> {
match self {
Self::Machine(v) => v.to_u64(),
Self::Big(v) => v.to_u64(),
}
}
fn to_i64(&self) -> std::option::Option<i64> {
match self {
Self::Machine(v) => Some(*v),
Self::Big(v) => v.to_i64(),
}
}
}
#[derive(Clone, Eq, PartialEq, Ord)]
pub(crate) enum Number {
Machine(Rational64),
@ -27,10 +173,10 @@ impl Number {
Number::Big(val)
}
pub fn to_integer(&self) -> BigInt {
pub fn to_integer(&self) -> Integer {
match self {
Self::Machine(val) => BigInt::from(val.to_integer()),
Self::Big(val) => val.to_integer(),
Self::Machine(val) => Integer::Machine(val.to_integer()),
Self::Big(val) => Integer::Big(val.to_integer()),
}
}
@ -246,7 +392,7 @@ impl Display for Number {
}
if !frac.is_zero() {
let end = (frac * Self::from(10)).round().to_integer();
if end == BigInt::from(10) {
if end.is_ten() {
loop {
match dec.pop() {
Some('9') => continue,