Move MathNumber into the library.
While this will be used for the OwnedLiterals since they must always exhibit the original DustJS behavior, I am going to keep exposing separate math functions for ContextElement instead of simply requiring them to implement Into<MathNumber> since people might want to implement math in unusual ways with unusual types.master
parent
d9ce011113
commit
d6ad7c28f3
@ -0,0 +1,76 @@
|
|||||||
|
use crate::parser::OwnedLiteral;
|
||||||
|
use std::convert::TryInto;
|
||||||
|
use std::ops::Add;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum MathNumber {
|
||||||
|
Integer(i128),
|
||||||
|
Decimal(f64),
|
||||||
|
Failure,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<&OwnedLiteral> for MathNumber {
|
||||||
|
fn from(original: &OwnedLiteral) -> Self {
|
||||||
|
match original {
|
||||||
|
OwnedLiteral::LString(_) => panic!("Strings should not be cast to numbers for math"),
|
||||||
|
OwnedLiteral::LPositiveInteger(num) => {
|
||||||
|
return MathNumber::Integer((*num).try_into().unwrap())
|
||||||
|
}
|
||||||
|
OwnedLiteral::LNegativeInteger(num) => return MathNumber::Integer((*num).into()),
|
||||||
|
OwnedLiteral::LFloat(num) => return MathNumber::Decimal(*num),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Add<MathNumber> for MathNumber {
|
||||||
|
type Output = Option<OwnedLiteral>;
|
||||||
|
|
||||||
|
fn add(self, other: MathNumber) -> Self::Output {
|
||||||
|
match (self, other) {
|
||||||
|
(MathNumber::Failure, _) | (_, MathNumber::Failure) => None,
|
||||||
|
(MathNumber::Integer(self_num), MathNumber::Integer(other_num)) => {
|
||||||
|
math_ints(self_num, other_num, std::ops::Add::add)
|
||||||
|
}
|
||||||
|
(MathNumber::Decimal(self_num), MathNumber::Decimal(other_num)) => {
|
||||||
|
Some(OwnedLiteral::LFloat(self_num + other_num))
|
||||||
|
}
|
||||||
|
(MathNumber::Integer(self_num), MathNumber::Decimal(other_num)) => {
|
||||||
|
Some(OwnedLiteral::LFloat((self_num as f64) + other_num))
|
||||||
|
}
|
||||||
|
(MathNumber::Decimal(self_num), MathNumber::Integer(other_num)) => {
|
||||||
|
Some(OwnedLiteral::LFloat(self_num + (other_num as f64)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// For math operations that take in integers and return integers
|
||||||
|
/// (add, subtract, multiply)
|
||||||
|
pub fn math_ints<L, R, F>(left: L, right: R, operation: F) -> Option<OwnedLiteral>
|
||||||
|
where
|
||||||
|
L: Into<i128>,
|
||||||
|
R: Into<i128>,
|
||||||
|
F: Fn(i128, i128) -> i128,
|
||||||
|
{
|
||||||
|
let result = operation(left.into(), right.into());
|
||||||
|
std::convert::TryInto::<u64>::try_into(result)
|
||||||
|
.map(OwnedLiteral::LPositiveInteger)
|
||||||
|
.ok()
|
||||||
|
.or(std::convert::TryInto::<i64>::try_into(result)
|
||||||
|
.map(OwnedLiteral::LNegativeInteger)
|
||||||
|
.ok())
|
||||||
|
}
|
||||||
|
|
||||||
|
// /// For math operations that take in integers and return integers
|
||||||
|
// /// (add, subtract, multiply)
|
||||||
|
// fn math_floats<L, R, F>(left: L, right: R, operation: F) -> Option<OwnedLiteral>
|
||||||
|
// where
|
||||||
|
// L: Into<f64>,
|
||||||
|
// R: Into<f64>,
|
||||||
|
// F: Fn(f64, f64) -> f64,
|
||||||
|
// {
|
||||||
|
// let result = operation(left.into(), right.into());
|
||||||
|
// std::convert::TryInto::<f64>::try_into(result)
|
||||||
|
// .map(OwnedLiteral::LFloat)
|
||||||
|
// .ok()
|
||||||
|
// }
|
Loading…
Reference in New Issue