2022-03-16 15:50:08 +00:00
|
|
|
use crate::sql::comment::comment;
|
2022-01-16 20:31:50 +00:00
|
|
|
use crate::sql::error::IResult;
|
2022-03-16 15:50:08 +00:00
|
|
|
use crate::sql::operator::{assigner, operator};
|
2022-05-21 00:35:59 +00:00
|
|
|
use crate::sql::serde::is_internal_serialization;
|
2022-03-17 21:01:29 +00:00
|
|
|
use bigdecimal::BigDecimal;
|
|
|
|
use bigdecimal::FromPrimitive;
|
|
|
|
use bigdecimal::ToPrimitive;
|
2022-03-16 15:50:08 +00:00
|
|
|
use nom::branch::alt;
|
2022-03-16 23:19:50 +00:00
|
|
|
use nom::character::complete::char;
|
2022-03-17 21:01:29 +00:00
|
|
|
use nom::character::complete::i64;
|
2022-03-16 15:50:08 +00:00
|
|
|
use nom::character::complete::multispace1;
|
|
|
|
use nom::combinator::eof;
|
|
|
|
use nom::combinator::map;
|
|
|
|
use nom::combinator::peek;
|
2022-01-23 12:30:59 +00:00
|
|
|
use nom::number::complete::recognize_float;
|
2020-06-29 15:36:01 +00:00
|
|
|
use serde::{Deserialize, Serialize};
|
2022-01-13 17:36:41 +00:00
|
|
|
use std::cmp::Ordering;
|
2020-06-29 15:36:01 +00:00
|
|
|
use std::fmt;
|
2022-01-13 17:36:41 +00:00
|
|
|
use std::iter::Product;
|
|
|
|
use std::iter::Sum;
|
2021-03-29 15:43:37 +00:00
|
|
|
use std::ops;
|
2020-06-29 15:36:01 +00:00
|
|
|
use std::str::FromStr;
|
|
|
|
|
2022-01-13 17:36:41 +00:00
|
|
|
#[derive(Clone, Debug, Deserialize)]
|
|
|
|
pub enum Number {
|
|
|
|
Int(i64),
|
|
|
|
Float(f64),
|
2022-03-17 21:01:29 +00:00
|
|
|
Decimal(BigDecimal),
|
2020-06-29 15:36:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl Default for Number {
|
|
|
|
fn default() -> Self {
|
2022-03-16 21:15:13 +00:00
|
|
|
Number::Int(0)
|
2021-03-29 15:43:37 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl From<i8> for Number {
|
|
|
|
fn from(i: i8) -> Self {
|
2022-03-16 21:15:13 +00:00
|
|
|
Number::Int(i as i64)
|
2021-03-29 15:43:37 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl From<i16> for Number {
|
|
|
|
fn from(i: i16) -> Self {
|
2022-03-16 21:15:13 +00:00
|
|
|
Number::Int(i as i64)
|
2020-06-29 15:36:01 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl From<i32> for Number {
|
|
|
|
fn from(i: i32) -> Self {
|
2022-03-16 21:15:13 +00:00
|
|
|
Number::Int(i as i64)
|
2020-06-29 15:36:01 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl From<i64> for Number {
|
|
|
|
fn from(i: i64) -> Self {
|
2022-03-16 21:15:13 +00:00
|
|
|
Number::Int(i as i64)
|
2022-01-23 12:30:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-01-13 17:36:41 +00:00
|
|
|
impl From<isize> for Number {
|
|
|
|
fn from(i: isize) -> Self {
|
2022-03-16 21:15:13 +00:00
|
|
|
Number::Int(i as i64)
|
2021-03-29 15:43:37 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl From<u8> for Number {
|
|
|
|
fn from(i: u8) -> Self {
|
2022-03-16 21:15:13 +00:00
|
|
|
Number::Int(i as i64)
|
2021-03-29 15:43:37 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl From<u16> for Number {
|
|
|
|
fn from(i: u16) -> Self {
|
2022-03-16 21:15:13 +00:00
|
|
|
Number::Int(i as i64)
|
2021-03-29 15:43:37 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl From<u32> for Number {
|
|
|
|
fn from(i: u32) -> Self {
|
2022-03-16 21:15:13 +00:00
|
|
|
Number::Int(i as i64)
|
2021-03-29 15:43:37 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl From<u64> for Number {
|
|
|
|
fn from(i: u64) -> Self {
|
2022-03-16 21:15:13 +00:00
|
|
|
Number::Int(i as i64)
|
2022-01-23 12:30:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-01-13 17:36:41 +00:00
|
|
|
impl From<usize> for Number {
|
|
|
|
fn from(i: usize) -> Self {
|
2022-03-16 21:15:13 +00:00
|
|
|
Number::Int(i as i64)
|
2020-06-29 15:36:01 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl From<f32> for Number {
|
|
|
|
fn from(f: f32) -> Self {
|
2022-03-16 21:15:13 +00:00
|
|
|
Number::Float(f as f64)
|
2020-06-29 15:36:01 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl From<f64> for Number {
|
|
|
|
fn from(f: f64) -> Self {
|
2022-03-16 21:15:13 +00:00
|
|
|
Number::Float(f as f64)
|
2020-06-29 15:36:01 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'a> From<&'a str> for Number {
|
|
|
|
fn from(s: &str) -> Self {
|
2022-03-17 21:01:29 +00:00
|
|
|
Number::Decimal(BigDecimal::from_str(s).unwrap_or_default())
|
2020-06-29 15:36:01 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl From<String> for Number {
|
|
|
|
fn from(s: String) -> Self {
|
2022-03-17 21:01:29 +00:00
|
|
|
Number::Decimal(BigDecimal::from_str(&s).unwrap_or_default())
|
2021-03-29 15:43:37 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-03-17 21:01:29 +00:00
|
|
|
impl From<BigDecimal> for Number {
|
|
|
|
fn from(v: BigDecimal) -> Self {
|
2022-01-13 17:36:41 +00:00
|
|
|
Number::Decimal(v)
|
2020-06-29 15:36:01 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl fmt::Display for Number {
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
2022-01-13 17:36:41 +00:00
|
|
|
match self {
|
|
|
|
Number::Int(v) => write!(f, "{}", v),
|
|
|
|
Number::Float(v) => write!(f, "{}", v),
|
|
|
|
Number::Decimal(v) => write!(f, "{}", v),
|
|
|
|
}
|
2020-06-29 15:36:01 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-29 15:43:37 +00:00
|
|
|
impl Serialize for Number {
|
2022-01-13 17:36:41 +00:00
|
|
|
fn serialize<S>(&self, s: S) -> Result<S::Ok, S::Error>
|
2021-03-29 15:43:37 +00:00
|
|
|
where
|
|
|
|
S: serde::Serializer,
|
|
|
|
{
|
2022-05-21 00:35:59 +00:00
|
|
|
if is_internal_serialization() {
|
2022-01-13 17:36:41 +00:00
|
|
|
match self {
|
|
|
|
Number::Int(v) => s.serialize_newtype_variant("Number", 0, "Int", v),
|
|
|
|
Number::Float(v) => s.serialize_newtype_variant("Number", 1, "Float", v),
|
|
|
|
Number::Decimal(v) => s.serialize_newtype_variant("Number", 2, "Decimal", v),
|
|
|
|
}
|
2022-05-21 00:35:59 +00:00
|
|
|
} else {
|
|
|
|
match self {
|
|
|
|
Number::Int(v) => s.serialize_i64(*v),
|
|
|
|
Number::Float(v) => s.serialize_f64(*v),
|
|
|
|
Number::Decimal(v) => s.serialize_some(v),
|
|
|
|
}
|
2022-01-13 17:36:41 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Number {
|
|
|
|
// -----------------------------------
|
|
|
|
// Simple number detection
|
|
|
|
// -----------------------------------
|
|
|
|
|
|
|
|
pub fn is_truthy(&self) -> bool {
|
|
|
|
match self {
|
|
|
|
Number::Int(v) => v != &0,
|
|
|
|
Number::Float(v) => v != &0.0,
|
2022-03-17 21:01:29 +00:00
|
|
|
Number::Decimal(v) => v != &BigDecimal::default(),
|
2022-01-13 17:36:41 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----------------------------------
|
|
|
|
// Simple conversion of number
|
|
|
|
// -----------------------------------
|
|
|
|
|
|
|
|
pub fn as_int(self) -> i64 {
|
|
|
|
match self {
|
|
|
|
Number::Int(v) => v,
|
|
|
|
Number::Float(v) => v as i64,
|
2022-03-17 21:01:29 +00:00
|
|
|
Number::Decimal(v) => v.to_i64().unwrap_or_default(),
|
2022-01-13 17:36:41 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn as_float(self) -> f64 {
|
|
|
|
match self {
|
|
|
|
Number::Int(v) => v as f64,
|
|
|
|
Number::Float(v) => v,
|
2022-03-17 21:01:29 +00:00
|
|
|
Number::Decimal(v) => v.to_f64().unwrap_or_default(),
|
2022-01-13 17:36:41 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-03-17 21:01:29 +00:00
|
|
|
pub fn as_decimal(self) -> BigDecimal {
|
2022-01-13 17:36:41 +00:00
|
|
|
match self {
|
2022-03-17 21:01:29 +00:00
|
|
|
Number::Int(v) => BigDecimal::from_i64(v).unwrap_or_default(),
|
|
|
|
Number::Float(v) => BigDecimal::from_f64(v).unwrap_or_default(),
|
2022-01-13 17:36:41 +00:00
|
|
|
Number::Decimal(v) => v,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----------------------------------
|
2022-03-17 21:01:29 +00:00
|
|
|
// Complex conversion of number
|
2022-01-13 17:36:41 +00:00
|
|
|
// -----------------------------------
|
|
|
|
|
|
|
|
pub fn to_usize(&self) -> usize {
|
|
|
|
match self {
|
|
|
|
Number::Int(v) => *v as usize,
|
|
|
|
Number::Float(v) => *v as usize,
|
2022-03-17 21:01:29 +00:00
|
|
|
Number::Decimal(v) => v.to_usize().unwrap_or_default(),
|
2022-01-13 17:36:41 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn to_int(&self) -> i64 {
|
|
|
|
match self {
|
|
|
|
Number::Int(v) => *v,
|
|
|
|
Number::Float(v) => *v as i64,
|
2022-03-17 21:01:29 +00:00
|
|
|
Number::Decimal(v) => v.to_i64().unwrap_or_default(),
|
2022-01-13 17:36:41 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn to_float(&self) -> f64 {
|
|
|
|
match self {
|
|
|
|
Number::Int(v) => *v as f64,
|
|
|
|
Number::Float(v) => *v,
|
2022-03-17 21:01:29 +00:00
|
|
|
Number::Decimal(v) => v.to_f64().unwrap_or_default(),
|
2022-01-13 17:36:41 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-03-17 21:01:29 +00:00
|
|
|
pub fn to_decimal(&self) -> BigDecimal {
|
2022-01-13 17:36:41 +00:00
|
|
|
match self {
|
2022-03-17 21:01:29 +00:00
|
|
|
Number::Int(v) => BigDecimal::from_i64(*v).unwrap_or_default(),
|
|
|
|
Number::Float(v) => BigDecimal::from_f64(*v).unwrap_or_default(),
|
|
|
|
Number::Decimal(v) => v.clone(),
|
2022-01-13 17:36:41 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----------------------------------
|
|
|
|
//
|
|
|
|
// -----------------------------------
|
|
|
|
|
|
|
|
pub fn abs(self) -> Self {
|
|
|
|
match self {
|
|
|
|
Number::Int(v) => v.abs().into(),
|
|
|
|
Number::Float(v) => v.abs().into(),
|
|
|
|
Number::Decimal(v) => v.abs().into(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn ceil(self) -> Self {
|
|
|
|
match self {
|
|
|
|
Number::Int(v) => v.into(),
|
|
|
|
Number::Float(v) => v.ceil().into(),
|
2022-03-17 21:01:29 +00:00
|
|
|
Number::Decimal(v) => (v + BigDecimal::from_f32(0.5).unwrap()).round(0).into(),
|
2022-01-13 17:36:41 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn floor(self) -> Self {
|
|
|
|
match self {
|
|
|
|
Number::Int(v) => v.into(),
|
|
|
|
Number::Float(v) => v.floor().into(),
|
2022-03-17 21:01:29 +00:00
|
|
|
Number::Decimal(v) => (v - BigDecimal::from_f32(0.5).unwrap()).round(0).into(),
|
2022-01-13 17:36:41 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn round(self) -> Self {
|
|
|
|
match self {
|
|
|
|
Number::Int(v) => v.into(),
|
|
|
|
Number::Float(v) => v.round().into(),
|
2022-03-17 21:01:29 +00:00
|
|
|
Number::Decimal(v) => v.round(0).into(),
|
2022-01-13 17:36:41 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn sqrt(self) -> Self {
|
|
|
|
match self {
|
|
|
|
Number::Int(v) => (v as f64).sqrt().into(),
|
|
|
|
Number::Float(v) => v.sqrt().into(),
|
2022-03-04 16:01:32 +00:00
|
|
|
Number::Decimal(v) => v.sqrt().unwrap_or_default().into(),
|
2022-01-13 17:36:41 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----------------------------------
|
|
|
|
//
|
|
|
|
// -----------------------------------
|
|
|
|
|
|
|
|
pub fn fixed(self, precision: usize) -> Number {
|
|
|
|
match self {
|
|
|
|
Number::Int(v) => format!("{:.1$}", v, precision).into(),
|
|
|
|
Number::Float(v) => format!("{:.1$}", v, precision).into(),
|
2022-03-17 21:01:29 +00:00
|
|
|
Number::Decimal(v) => v.round(precision as i64).into(),
|
2022-01-13 17:36:41 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Eq for Number {}
|
|
|
|
|
|
|
|
impl Ord for Number {
|
|
|
|
fn cmp(&self, other: &Self) -> Ordering {
|
2022-03-04 16:01:32 +00:00
|
|
|
self.partial_cmp(other).unwrap_or(Ordering::Equal)
|
2022-01-13 17:36:41 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl PartialEq for Number {
|
|
|
|
fn eq(&self, other: &Self) -> bool {
|
|
|
|
match (self, other) {
|
|
|
|
(Number::Int(v), Number::Int(w)) => v.eq(w),
|
|
|
|
(Number::Float(v), Number::Float(w)) => v.eq(w),
|
|
|
|
(Number::Decimal(v), Number::Decimal(w)) => v.eq(w),
|
|
|
|
// ------------------------------
|
|
|
|
(Number::Int(v), Number::Float(w)) => (*v as f64).eq(w),
|
|
|
|
(Number::Float(v), Number::Int(w)) => v.eq(&(*w as f64)),
|
|
|
|
// ------------------------------
|
2022-03-17 21:01:29 +00:00
|
|
|
(Number::Int(v), Number::Decimal(w)) => BigDecimal::from(*v).eq(w),
|
|
|
|
(Number::Decimal(v), Number::Int(w)) => v.eq(&BigDecimal::from(*w)),
|
2022-01-13 17:36:41 +00:00
|
|
|
// ------------------------------
|
|
|
|
(Number::Float(v), Number::Decimal(w)) => {
|
2022-03-17 21:01:29 +00:00
|
|
|
BigDecimal::from_f64(*v).unwrap_or_default().eq(w)
|
2022-01-13 17:36:41 +00:00
|
|
|
}
|
|
|
|
(Number::Decimal(v), Number::Float(w)) => {
|
2022-03-17 21:01:29 +00:00
|
|
|
v.eq(&BigDecimal::from_f64(*w).unwrap_or_default())
|
2022-01-13 17:36:41 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl PartialOrd for Number {
|
|
|
|
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
|
|
|
match (self, other) {
|
|
|
|
(Number::Int(v), Number::Int(w)) => v.partial_cmp(w),
|
|
|
|
(Number::Float(v), Number::Float(w)) => v.partial_cmp(w),
|
|
|
|
(Number::Decimal(v), Number::Decimal(w)) => v.partial_cmp(w),
|
|
|
|
// ------------------------------
|
|
|
|
(Number::Int(v), Number::Float(w)) => (*v as f64).partial_cmp(w),
|
|
|
|
(Number::Float(v), Number::Int(w)) => v.partial_cmp(&(*w as f64)),
|
|
|
|
// ------------------------------
|
2022-03-17 21:01:29 +00:00
|
|
|
(Number::Int(v), Number::Decimal(w)) => BigDecimal::from(*v).partial_cmp(w),
|
|
|
|
(Number::Decimal(v), Number::Int(w)) => v.partial_cmp(&BigDecimal::from(*w)),
|
2022-01-13 17:36:41 +00:00
|
|
|
// ------------------------------
|
|
|
|
(Number::Float(v), Number::Decimal(w)) => {
|
2022-03-17 21:01:29 +00:00
|
|
|
BigDecimal::from_f64(*v).unwrap_or_default().partial_cmp(w)
|
2022-01-13 17:36:41 +00:00
|
|
|
}
|
|
|
|
(Number::Decimal(v), Number::Float(w)) => {
|
2022-03-17 21:01:29 +00:00
|
|
|
v.partial_cmp(&BigDecimal::from_f64(*w).unwrap_or_default())
|
2022-01-13 17:36:41 +00:00
|
|
|
}
|
2021-03-29 15:43:37 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl ops::Add for Number {
|
|
|
|
type Output = Self;
|
|
|
|
fn add(self, other: Self) -> Self {
|
2022-01-13 17:36:41 +00:00
|
|
|
match (self, other) {
|
|
|
|
(Number::Int(v), Number::Int(w)) => Number::Int(v + w),
|
|
|
|
(Number::Float(v), Number::Float(w)) => Number::Float(v + w),
|
|
|
|
(Number::Decimal(v), Number::Decimal(w)) => Number::Decimal(v + w),
|
|
|
|
(Number::Int(v), Number::Float(w)) => Number::Float(v as f64 + w),
|
|
|
|
(Number::Float(v), Number::Int(w)) => Number::Float(v + w as f64),
|
|
|
|
(v, w) => Number::from(v.as_decimal() + w.as_decimal()),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'a, 'b> ops::Add<&'b Number> for &'a Number {
|
|
|
|
type Output = Number;
|
|
|
|
fn add(self, other: &'b Number) -> Number {
|
|
|
|
match (self, other) {
|
|
|
|
(Number::Int(v), Number::Int(w)) => Number::Int(v + w),
|
|
|
|
(Number::Float(v), Number::Float(w)) => Number::Float(v + w),
|
|
|
|
(Number::Decimal(v), Number::Decimal(w)) => Number::Decimal(v + w),
|
|
|
|
(Number::Int(v), Number::Float(w)) => Number::Float(*v as f64 + w),
|
|
|
|
(Number::Float(v), Number::Int(w)) => Number::Float(v + *w as f64),
|
|
|
|
(v, w) => Number::from(v.to_decimal() + w.to_decimal()),
|
|
|
|
}
|
2021-03-29 15:43:37 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl ops::Sub for Number {
|
|
|
|
type Output = Self;
|
|
|
|
fn sub(self, other: Self) -> Self {
|
2022-01-13 17:36:41 +00:00
|
|
|
match (self, other) {
|
|
|
|
(Number::Int(v), Number::Int(w)) => Number::Int(v - w),
|
|
|
|
(Number::Float(v), Number::Float(w)) => Number::Float(v - w),
|
|
|
|
(Number::Decimal(v), Number::Decimal(w)) => Number::Decimal(v - w),
|
|
|
|
(Number::Int(v), Number::Float(w)) => Number::Float(v as f64 - w),
|
|
|
|
(Number::Float(v), Number::Int(w)) => Number::Float(v - w as f64),
|
|
|
|
(v, w) => Number::from(v.as_decimal() - w.as_decimal()),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'a, 'b> ops::Sub<&'b Number> for &'a Number {
|
|
|
|
type Output = Number;
|
|
|
|
fn sub(self, other: &'b Number) -> Number {
|
|
|
|
match (self, other) {
|
|
|
|
(Number::Int(v), Number::Int(w)) => Number::Int(v - w),
|
|
|
|
(Number::Float(v), Number::Float(w)) => Number::Float(v - w),
|
|
|
|
(Number::Decimal(v), Number::Decimal(w)) => Number::Decimal(v - w),
|
|
|
|
(Number::Int(v), Number::Float(w)) => Number::Float(*v as f64 - w),
|
|
|
|
(Number::Float(v), Number::Int(w)) => Number::Float(v - *w as f64),
|
|
|
|
(v, w) => Number::from(v.to_decimal() - w.to_decimal()),
|
|
|
|
}
|
2021-03-29 15:43:37 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl ops::Mul for Number {
|
|
|
|
type Output = Self;
|
|
|
|
fn mul(self, other: Self) -> Self {
|
2022-01-13 17:36:41 +00:00
|
|
|
match (self, other) {
|
|
|
|
(Number::Int(v), Number::Int(w)) => Number::Int(v * w),
|
|
|
|
(Number::Float(v), Number::Float(w)) => Number::Float(v * w),
|
|
|
|
(Number::Decimal(v), Number::Decimal(w)) => Number::Decimal(v * w),
|
|
|
|
(Number::Int(v), Number::Float(w)) => Number::Float(v as f64 * w),
|
|
|
|
(Number::Float(v), Number::Int(w)) => Number::Float(v * w as f64),
|
|
|
|
(v, w) => Number::from(v.as_decimal() * w.as_decimal()),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'a, 'b> ops::Mul<&'b Number> for &'a Number {
|
|
|
|
type Output = Number;
|
|
|
|
fn mul(self, other: &'b Number) -> Number {
|
|
|
|
match (self, other) {
|
|
|
|
(Number::Int(v), Number::Int(w)) => Number::Int(v * w),
|
|
|
|
(Number::Float(v), Number::Float(w)) => Number::Float(v * w),
|
|
|
|
(Number::Decimal(v), Number::Decimal(w)) => Number::Decimal(v * w),
|
|
|
|
(Number::Int(v), Number::Float(w)) => Number::Float(*v as f64 * w),
|
|
|
|
(Number::Float(v), Number::Int(w)) => Number::Float(v * *w as f64),
|
|
|
|
(v, w) => Number::from(v.to_decimal() * w.to_decimal()),
|
|
|
|
}
|
2021-03-29 15:43:37 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl ops::Div for Number {
|
|
|
|
type Output = Self;
|
|
|
|
fn div(self, other: Self) -> Self {
|
2022-01-13 17:36:41 +00:00
|
|
|
match (self, other) {
|
|
|
|
(Number::Float(v), Number::Float(w)) => Number::Float(v / w),
|
|
|
|
(Number::Decimal(v), Number::Decimal(w)) => Number::Decimal(v / w),
|
|
|
|
(Number::Int(v), Number::Float(w)) => Number::Float(v as f64 / w),
|
|
|
|
(Number::Float(v), Number::Int(w)) => Number::Float(v / w as f64),
|
|
|
|
(v, w) => Number::from(v.as_decimal() / w.as_decimal()),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'a, 'b> ops::Div<&'b Number> for &'a Number {
|
|
|
|
type Output = Number;
|
|
|
|
fn div(self, other: &'b Number) -> Number {
|
|
|
|
match (self, other) {
|
|
|
|
(Number::Float(v), Number::Float(w)) => Number::Float(v / w),
|
|
|
|
(Number::Decimal(v), Number::Decimal(w)) => Number::Decimal(v / w),
|
|
|
|
(Number::Int(v), Number::Float(w)) => Number::Float(*v as f64 / w),
|
|
|
|
(Number::Float(v), Number::Int(w)) => Number::Float(v / *w as f64),
|
|
|
|
(v, w) => Number::from(v.to_decimal() / w.to_decimal()),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------
|
|
|
|
|
|
|
|
impl Sum<Self> for Number {
|
|
|
|
fn sum<I>(iter: I) -> Number
|
|
|
|
where
|
|
|
|
I: Iterator<Item = Self>,
|
|
|
|
{
|
|
|
|
iter.fold(Number::Int(0), |a, b| a + b)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'a> Sum<&'a Self> for Number {
|
|
|
|
fn sum<I>(iter: I) -> Number
|
|
|
|
where
|
|
|
|
I: Iterator<Item = &'a Self>,
|
|
|
|
{
|
|
|
|
iter.fold(Number::Int(0), |a, b| &a + b)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Product<Self> for Number {
|
|
|
|
fn product<I>(iter: I) -> Number
|
|
|
|
where
|
|
|
|
I: Iterator<Item = Self>,
|
|
|
|
{
|
|
|
|
iter.fold(Number::Int(1), |a, b| a * b)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'a> Product<&'a Self> for Number {
|
|
|
|
fn product<I>(iter: I) -> Number
|
|
|
|
where
|
|
|
|
I: Iterator<Item = &'a Self>,
|
|
|
|
{
|
|
|
|
iter.fold(Number::Int(1), |a, b| &a * b)
|
2021-03-29 15:43:37 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-06-29 15:36:01 +00:00
|
|
|
pub fn number(i: &str) -> IResult<&str, Number> {
|
2022-03-16 23:19:50 +00:00
|
|
|
alt((integer, decimal))(i)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn integer(i: &str) -> IResult<&str, Number> {
|
2022-03-17 21:01:29 +00:00
|
|
|
let (i, v) = i64(i)?;
|
2022-03-16 23:19:50 +00:00
|
|
|
let (i, _) = peek(alt((
|
|
|
|
map(multispace1, |_| ()),
|
|
|
|
map(operator, |_| ()),
|
|
|
|
map(assigner, |_| ()),
|
|
|
|
map(comment, |_| ()),
|
|
|
|
map(char(')'), |_| ()),
|
|
|
|
map(char(']'), |_| ()),
|
|
|
|
map(char('}'), |_| ()),
|
|
|
|
map(char(';'), |_| ()),
|
|
|
|
map(char(','), |_| ()),
|
|
|
|
map(eof, |_| ()),
|
|
|
|
)))(i)?;
|
2022-03-17 21:01:29 +00:00
|
|
|
Ok((i, Number::from(v)))
|
2022-03-16 23:19:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fn decimal(i: &str) -> IResult<&str, Number> {
|
2022-01-23 12:30:59 +00:00
|
|
|
let (i, v) = recognize_float(i)?;
|
2022-03-16 15:50:08 +00:00
|
|
|
let (i, _) = peek(alt((
|
|
|
|
map(multispace1, |_| ()),
|
|
|
|
map(operator, |_| ()),
|
|
|
|
map(assigner, |_| ()),
|
|
|
|
map(comment, |_| ()),
|
2022-03-16 23:19:50 +00:00
|
|
|
map(char(')'), |_| ()),
|
|
|
|
map(char(']'), |_| ()),
|
|
|
|
map(char('}'), |_| ()),
|
|
|
|
map(char(';'), |_| ()),
|
|
|
|
map(char(','), |_| ()),
|
2022-03-16 15:50:08 +00:00
|
|
|
map(eof, |_| ()),
|
|
|
|
)))(i)?;
|
2020-06-29 15:36:01 +00:00
|
|
|
Ok((i, Number::from(v)))
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
mod tests {
|
|
|
|
|
|
|
|
use super::*;
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn number_integer() {
|
|
|
|
let sql = "123";
|
|
|
|
let res = number(sql);
|
|
|
|
assert!(res.is_ok());
|
|
|
|
let out = res.unwrap().1;
|
|
|
|
assert_eq!("123", format!("{}", out));
|
|
|
|
assert_eq!(out, Number::from(123));
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn number_integer_neg() {
|
|
|
|
let sql = "-123";
|
|
|
|
let res = number(sql);
|
|
|
|
assert!(res.is_ok());
|
|
|
|
let out = res.unwrap().1;
|
|
|
|
assert_eq!("-123", format!("{}", out));
|
|
|
|
assert_eq!(out, Number::from(-123));
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn number_decimal() {
|
|
|
|
let sql = "123.45";
|
|
|
|
let res = number(sql);
|
|
|
|
assert!(res.is_ok());
|
|
|
|
let out = res.unwrap().1;
|
|
|
|
assert_eq!("123.45", format!("{}", out));
|
|
|
|
assert_eq!(out, Number::from(123.45));
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn number_decimal_neg() {
|
|
|
|
let sql = "-123.45";
|
|
|
|
let res = number(sql);
|
|
|
|
assert!(res.is_ok());
|
|
|
|
let out = res.unwrap().1;
|
|
|
|
assert_eq!("-123.45", format!("{}", out));
|
|
|
|
assert_eq!(out, Number::from(-123.45));
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn number_scientific_lower() {
|
|
|
|
let sql = "12345e-1";
|
|
|
|
let res = number(sql);
|
|
|
|
assert!(res.is_ok());
|
|
|
|
let out = res.unwrap().1;
|
|
|
|
assert_eq!("1234.5", format!("{}", out));
|
|
|
|
assert_eq!(out, Number::from(1234.5));
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn number_scientific_lower_neg() {
|
|
|
|
let sql = "-12345e-1";
|
|
|
|
let res = number(sql);
|
|
|
|
assert!(res.is_ok());
|
|
|
|
let out = res.unwrap().1;
|
|
|
|
assert_eq!("-1234.5", format!("{}", out));
|
|
|
|
assert_eq!(out, Number::from(-1234.5));
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn number_scientific_upper() {
|
|
|
|
let sql = "12345E-02";
|
|
|
|
let res = number(sql);
|
|
|
|
assert!(res.is_ok());
|
|
|
|
let out = res.unwrap().1;
|
|
|
|
assert_eq!("123.45", format!("{}", out));
|
|
|
|
assert_eq!(out, Number::from(123.45));
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn number_scientific_upper_neg() {
|
|
|
|
let sql = "-12345E-02";
|
|
|
|
let res = number(sql);
|
|
|
|
assert!(res.is_ok());
|
|
|
|
let out = res.unwrap().1;
|
|
|
|
assert_eq!("-123.45", format!("{}", out));
|
|
|
|
assert_eq!(out, Number::from(-123.45));
|
|
|
|
}
|
|
|
|
}
|