forked from extern/nushell
Make the default int an i64 (#3428)
* Make the default int an i64 * fmt * Fix random integer * Treat pids as i64 for now
This commit is contained in:
@ -10,18 +10,18 @@ use crate::{hir, Dictionary, PositionalType, Primitive, SyntaxShape, UntaggedVal
|
||||
use crate::{PathMember, ShellTypeName};
|
||||
use derive_new::new;
|
||||
|
||||
use nu_errors::ParseError;
|
||||
use nu_errors::{ParseError, ShellError};
|
||||
use nu_source::{
|
||||
DbgDocBldr, DebugDocBuilder, HasSpan, PrettyDebug, PrettyDebugRefineKind, PrettyDebugWithSource,
|
||||
};
|
||||
use nu_source::{IntoSpanned, Span, Spanned, SpannedItem, Tag};
|
||||
|
||||
use bigdecimal::BigDecimal;
|
||||
use bigdecimal::{BigDecimal, ToPrimitive};
|
||||
use indexmap::IndexMap;
|
||||
use log::trace;
|
||||
use num_bigint::{BigInt, ToBigInt};
|
||||
use num_traits::identities::Zero;
|
||||
use num_traits::{FromPrimitive, ToPrimitive};
|
||||
use num_traits::FromPrimitive;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize)]
|
||||
pub struct InternalCommand {
|
||||
@ -363,7 +363,7 @@ pub enum Unit {
|
||||
#[derive(Debug, Ord, PartialOrd, Eq, PartialEq, Clone, Hash, Deserialize, Serialize)]
|
||||
pub enum Member {
|
||||
String(/* outer */ Span, /* inner */ Span),
|
||||
Int(BigInt, Span),
|
||||
Int(i64, Span),
|
||||
Bare(Spanned<String>),
|
||||
}
|
||||
|
||||
@ -371,7 +371,7 @@ impl Member {
|
||||
pub fn to_path_member(&self) -> PathMember {
|
||||
match self {
|
||||
//Member::String(outer, inner) => PathMember::string(inner.slice(source), *outer),
|
||||
Member::Int(int, span) => PathMember::int(int.clone(), *span),
|
||||
Member::Int(int, span) => PathMember::int(*int, *span),
|
||||
Member::Bare(spanned_string) => {
|
||||
PathMember::string(spanned_string.item.clone(), spanned_string.span)
|
||||
}
|
||||
@ -402,13 +402,32 @@ impl HasSpan for Member {
|
||||
|
||||
#[derive(Debug, Ord, PartialOrd, Eq, PartialEq, Clone, Hash, Deserialize, Serialize)]
|
||||
pub enum Number {
|
||||
Int(BigInt),
|
||||
BigInt(BigInt),
|
||||
Int(i64),
|
||||
Decimal(BigDecimal),
|
||||
}
|
||||
|
||||
impl Number {
|
||||
pub fn to_i64(&self) -> Result<i64, ShellError> {
|
||||
match self {
|
||||
Number::BigInt(bi) => match bi.to_i64() {
|
||||
Some(i) => Ok(i),
|
||||
None => Err(ShellError::untagged_runtime_error(
|
||||
"Cannot convert bigint to i64, too large",
|
||||
)),
|
||||
},
|
||||
Number::Int(i) => Ok(*i),
|
||||
Number::Decimal(_) => Err(ShellError::untagged_runtime_error(
|
||||
"Cannont convert decimal to i64",
|
||||
)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl PrettyDebug for Number {
|
||||
fn pretty(&self) -> DebugDocBuilder {
|
||||
match self {
|
||||
Number::BigInt(int) => DbgDocBldr::primitive(int),
|
||||
Number::Int(int) => DbgDocBldr::primitive(int),
|
||||
Number::Decimal(decimal) => DbgDocBldr::primitive(decimal),
|
||||
}
|
||||
@ -420,13 +439,13 @@ macro_rules! primitive_int {
|
||||
$(
|
||||
impl From<$ty> for Number {
|
||||
fn from(int: $ty) -> Number {
|
||||
Number::Int(BigInt::zero() + int)
|
||||
Number::BigInt(BigInt::zero() + int)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&$ty> for Number {
|
||||
fn from(int: &$ty) -> Number {
|
||||
Number::Int(BigInt::zero() + *int)
|
||||
Number::BigInt(BigInt::zero() + *int)
|
||||
}
|
||||
}
|
||||
)*
|
||||
@ -469,8 +488,13 @@ impl std::ops::Mul for Number {
|
||||
fn mul(self, other: Number) -> Number {
|
||||
match (self, other) {
|
||||
(Number::Int(a), Number::Int(b)) => Number::Int(a * b),
|
||||
(Number::BigInt(a), Number::Int(b)) => Number::BigInt(a * BigInt::from(b)),
|
||||
(Number::Int(a), Number::BigInt(b)) => Number::BigInt(BigInt::from(a) * b),
|
||||
(Number::BigInt(a), Number::BigInt(b)) => Number::BigInt(a * b),
|
||||
(Number::Int(a), Number::Decimal(b)) => Number::Decimal(BigDecimal::from(a) * b),
|
||||
(Number::Decimal(a), Number::Int(b)) => Number::Decimal(a * BigDecimal::from(b)),
|
||||
(Number::BigInt(a), Number::Decimal(b)) => Number::Decimal(BigDecimal::from(a) * b),
|
||||
(Number::Decimal(a), Number::BigInt(b)) => Number::Decimal(a * BigDecimal::from(b)),
|
||||
(Number::Decimal(a), Number::Decimal(b)) => Number::Decimal(a * b),
|
||||
}
|
||||
}
|
||||
@ -482,6 +506,7 @@ impl std::ops::Mul<u32> for Number {
|
||||
|
||||
fn mul(self, other: u32) -> Number {
|
||||
match self {
|
||||
Number::BigInt(left) => Number::BigInt(left * (other as i64)),
|
||||
Number::Int(left) => Number::Int(left * (other as i64)),
|
||||
Number::Decimal(left) => Number::Decimal(left * BigDecimal::from(other)),
|
||||
}
|
||||
@ -491,7 +516,8 @@ impl std::ops::Mul<u32> for Number {
|
||||
impl ToBigInt for Number {
|
||||
fn to_bigint(&self) -> Option<BigInt> {
|
||||
match self {
|
||||
Number::Int(int) => Some(int.clone()),
|
||||
Number::Int(int) => Some(BigInt::from(*int)),
|
||||
Number::BigInt(int) => Some(int.clone()),
|
||||
// The BigDecimal to BigInt conversion always return Some().
|
||||
// FIXME: This conversion might not be want we want, it just remove the scale.
|
||||
Number::Decimal(decimal) => decimal.to_bigint(),
|
||||
@ -505,25 +531,6 @@ impl PrettyDebug for Unit {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn convert_number_to_u64(number: &Number) -> u64 {
|
||||
match number {
|
||||
Number::Int(big_int) => {
|
||||
if let Some(x) = big_int.to_u64() {
|
||||
x
|
||||
} else {
|
||||
unreachable!("Internal error: convert_number_to_u64 given incompatible number")
|
||||
}
|
||||
}
|
||||
Number::Decimal(big_decimal) => {
|
||||
if let Some(x) = big_decimal.to_u64() {
|
||||
x
|
||||
} else {
|
||||
unreachable!("Internal error: convert_number_to_u64 given incompatible number")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Unit {
|
||||
pub fn as_str(self) -> &'static str {
|
||||
match self {
|
||||
@ -553,22 +560,18 @@ impl Unit {
|
||||
let size = size.clone();
|
||||
|
||||
match self {
|
||||
Unit::Byte => filesize(convert_number_to_u64(&size)),
|
||||
Unit::Kilobyte => filesize(convert_number_to_u64(&size) * 1000),
|
||||
Unit::Megabyte => filesize(convert_number_to_u64(&size) * 1000 * 1000),
|
||||
Unit::Gigabyte => filesize(convert_number_to_u64(&size) * 1000 * 1000 * 1000),
|
||||
Unit::Terabyte => filesize(convert_number_to_u64(&size) * 1000 * 1000 * 1000 * 1000),
|
||||
Unit::Petabyte => {
|
||||
filesize(convert_number_to_u64(&size) * 1000 * 1000 * 1000 * 1000 * 1000)
|
||||
}
|
||||
Unit::Byte => filesize(size),
|
||||
Unit::Kilobyte => filesize(size * 1000),
|
||||
Unit::Megabyte => filesize(size * 1000 * 1000),
|
||||
Unit::Gigabyte => filesize(size * 1000 * 1000 * 1000),
|
||||
Unit::Terabyte => filesize(size * 1000 * 1000 * 1000 * 1000),
|
||||
Unit::Petabyte => filesize(size * 1000 * 1000 * 1000 * 1000 * 1000),
|
||||
|
||||
Unit::Kibibyte => filesize(convert_number_to_u64(&size) * 1024),
|
||||
Unit::Mebibyte => filesize(convert_number_to_u64(&size) * 1024 * 1024),
|
||||
Unit::Gibibyte => filesize(convert_number_to_u64(&size) * 1024 * 1024 * 1024),
|
||||
Unit::Tebibyte => filesize(convert_number_to_u64(&size) * 1024 * 1024 * 1024 * 1024),
|
||||
Unit::Pebibyte => {
|
||||
filesize(convert_number_to_u64(&size) * 1024 * 1024 * 1024 * 1024 * 1024)
|
||||
}
|
||||
Unit::Kibibyte => filesize(size * 1024),
|
||||
Unit::Mebibyte => filesize(size * 1024 * 1024),
|
||||
Unit::Gibibyte => filesize(size * 1024 * 1024 * 1024),
|
||||
Unit::Tebibyte => filesize(size * 1024 * 1024 * 1024 * 1024),
|
||||
Unit::Pebibyte => filesize(size * 1024 * 1024 * 1024 * 1024 * 1024),
|
||||
|
||||
Unit::Nanosecond => duration(size.to_bigint().expect("Conversion should never fail.")),
|
||||
Unit::Microsecond => {
|
||||
@ -614,8 +617,19 @@ impl Unit {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn filesize(size_in_bytes: impl Into<BigInt>) -> UntaggedValue {
|
||||
UntaggedValue::Primitive(Primitive::Filesize(size_in_bytes.into()))
|
||||
pub fn filesize(size_in_bytes: Number) -> UntaggedValue {
|
||||
match size_in_bytes {
|
||||
Number::Int(i) => UntaggedValue::Primitive(Primitive::Filesize(i as u64)),
|
||||
Number::BigInt(bi) => match bi.to_u64() {
|
||||
Some(i) => UntaggedValue::Primitive(Primitive::Filesize(i)),
|
||||
None => UntaggedValue::Error(ShellError::untagged_runtime_error(
|
||||
"Big int too large to convert to filesize",
|
||||
)),
|
||||
},
|
||||
Number::Decimal(_) => UntaggedValue::Error(ShellError::untagged_runtime_error(
|
||||
"Decimal can't convert to filesize",
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn duration(nanos: BigInt) -> UntaggedValue {
|
||||
@ -1069,10 +1083,14 @@ impl IntoSpanned for Expression {
|
||||
}
|
||||
|
||||
impl Expression {
|
||||
pub fn integer(i: BigInt) -> Expression {
|
||||
pub fn integer(i: i64) -> Expression {
|
||||
Expression::Literal(Literal::Number(Number::Int(i)))
|
||||
}
|
||||
|
||||
pub fn big_integer(i: BigInt) -> Expression {
|
||||
Expression::Literal(Literal::Number(Number::BigInt(i)))
|
||||
}
|
||||
|
||||
pub fn decimal(dec: BigDecimal) -> Expression {
|
||||
Expression::Literal(Literal::Number(Number::Decimal(dec)))
|
||||
}
|
||||
@ -1116,7 +1134,7 @@ impl Expression {
|
||||
|
||||
pub fn unit(i: Spanned<i64>, unit: Spanned<Unit>) -> Expression {
|
||||
Expression::Literal(Literal::Size(
|
||||
Number::Int(BigInt::from(i.item)).spanned(i.span),
|
||||
Number::BigInt(BigInt::from(i.item)).spanned(i.span),
|
||||
unit,
|
||||
))
|
||||
}
|
||||
|
@ -30,6 +30,8 @@ pub enum Type {
|
||||
Nothing,
|
||||
/// An integer-based value
|
||||
Int,
|
||||
/// An big integer-based value
|
||||
BigInt,
|
||||
/// A range between two values
|
||||
Range(Box<RangeType>),
|
||||
/// A decimal (floating point) value
|
||||
@ -131,6 +133,7 @@ impl Type {
|
||||
match primitive {
|
||||
Primitive::Nothing => Type::Nothing,
|
||||
Primitive::Int(_) => Type::Int,
|
||||
Primitive::BigInt(_) => Type::BigInt,
|
||||
Primitive::Range(range) => {
|
||||
let (left_value, left_inclusion) = &range.from;
|
||||
let (right_value, right_inclusion) = &range.to;
|
||||
@ -199,6 +202,7 @@ impl PrettyDebug for Type {
|
||||
match self {
|
||||
Type::Nothing => ty("nothing"),
|
||||
Type::Int => ty("integer"),
|
||||
Type::BigInt => ty("big integer"),
|
||||
Type::Range(range) => {
|
||||
let (left, left_inclusion) = &range.from;
|
||||
let (right, right_inclusion) = &range.to;
|
||||
|
@ -178,10 +178,15 @@ impl UntaggedValue {
|
||||
}
|
||||
|
||||
/// Helper for creating integer values
|
||||
pub fn int(i: impl Into<BigInt>) -> UntaggedValue {
|
||||
pub fn int(i: impl Into<i64>) -> UntaggedValue {
|
||||
UntaggedValue::Primitive(Primitive::Int(i.into()))
|
||||
}
|
||||
|
||||
/// Helper for creating big integer values
|
||||
pub fn big_int(i: impl Into<BigInt>) -> UntaggedValue {
|
||||
UntaggedValue::Primitive(Primitive::BigInt(i.into()))
|
||||
}
|
||||
|
||||
/// Helper for creating glob pattern values
|
||||
pub fn glob_pattern(s: impl Into<String>) -> UntaggedValue {
|
||||
UntaggedValue::Primitive(Primitive::String(s.into()))
|
||||
@ -193,8 +198,8 @@ impl UntaggedValue {
|
||||
}
|
||||
|
||||
/// Helper for creating filesize values
|
||||
pub fn filesize(s: impl Into<BigInt>) -> UntaggedValue {
|
||||
UntaggedValue::Primitive(Primitive::Filesize(s.into()))
|
||||
pub fn filesize(s: u64) -> UntaggedValue {
|
||||
UntaggedValue::Primitive(Primitive::Filesize(s))
|
||||
}
|
||||
|
||||
/// Helper for creating decimal values
|
||||
@ -339,22 +344,30 @@ impl Value {
|
||||
}
|
||||
}
|
||||
|
||||
/// View the Value as a Int (BigInt), if possible
|
||||
pub fn as_int(&self) -> Result<BigInt, ShellError> {
|
||||
/// View the Value as a Int, if possible
|
||||
pub fn as_int(&self) -> Result<i64, ShellError> {
|
||||
match &self.value {
|
||||
UntaggedValue::Primitive(Primitive::Int(n)) => Ok(n.clone()),
|
||||
UntaggedValue::Primitive(Primitive::Int(n)) => Ok(*n),
|
||||
_ => Err(ShellError::type_error("bigint", self.spanned_type_name())),
|
||||
}
|
||||
}
|
||||
|
||||
/// View the Value as a Filesize (BigInt), if possible
|
||||
pub fn as_filesize(&self) -> Result<BigInt, ShellError> {
|
||||
/// View the Value as a Int, if possible
|
||||
pub fn as_big_int(&self) -> Result<BigInt, ShellError> {
|
||||
match &self.value {
|
||||
UntaggedValue::Primitive(Primitive::Filesize(fs)) => Ok(fs.clone()),
|
||||
UntaggedValue::Primitive(Primitive::BigInt(n)) => Ok(n.clone()),
|
||||
_ => Err(ShellError::type_error("bigint", self.spanned_type_name())),
|
||||
}
|
||||
}
|
||||
|
||||
/// View the Value as a Filesize (u64), if possible
|
||||
pub fn as_filesize(&self) -> Result<u64, ShellError> {
|
||||
match &self.value {
|
||||
UntaggedValue::Primitive(Primitive::Filesize(fs)) => Ok(*fs),
|
||||
_ => Err(ShellError::type_error("int", self.spanned_type_name())),
|
||||
}
|
||||
}
|
||||
|
||||
/// View the Value as a Duration (BigInt), if possible
|
||||
pub fn as_duration(&self) -> Result<BigInt, ShellError> {
|
||||
match &self.value {
|
||||
@ -808,8 +821,6 @@ pub trait U64Ext {
|
||||
fn to_untagged_value(&self) -> UntaggedValue;
|
||||
fn to_value(&self, tag: Tag) -> Value;
|
||||
fn to_value_create_tag(&self) -> Value;
|
||||
fn to_filesize_untagged_value(&self) -> UntaggedValue;
|
||||
fn to_filesize_value(&self, tag: Tag) -> Value;
|
||||
fn to_duration_untagged_value(&self) -> UntaggedValue;
|
||||
fn to_duration_value(&self, tag: Tag) -> Value;
|
||||
}
|
||||
@ -817,14 +828,7 @@ pub trait U64Ext {
|
||||
impl U64Ext for u64 {
|
||||
fn to_value(&self, the_tag: Tag) -> Value {
|
||||
Value {
|
||||
value: UntaggedValue::Primitive(Primitive::Int(BigInt::from(*self))),
|
||||
tag: the_tag,
|
||||
}
|
||||
}
|
||||
|
||||
fn to_filesize_value(&self, the_tag: Tag) -> Value {
|
||||
Value {
|
||||
value: UntaggedValue::Primitive(Primitive::Filesize(BigInt::from(*self))),
|
||||
value: UntaggedValue::Primitive(Primitive::BigInt(BigInt::from(*self))),
|
||||
tag: the_tag,
|
||||
}
|
||||
}
|
||||
@ -839,7 +843,7 @@ impl U64Ext for u64 {
|
||||
fn to_value_create_tag(&self) -> Value {
|
||||
let end = self.to_string().len();
|
||||
Value {
|
||||
value: UntaggedValue::Primitive(Primitive::Int(BigInt::from(*self))),
|
||||
value: UntaggedValue::Primitive(Primitive::BigInt(BigInt::from(*self))),
|
||||
tag: Tag {
|
||||
anchor: None,
|
||||
span: Span::new(0, end),
|
||||
@ -848,11 +852,7 @@ impl U64Ext for u64 {
|
||||
}
|
||||
|
||||
fn to_untagged_value(&self) -> UntaggedValue {
|
||||
UntaggedValue::int(*self)
|
||||
}
|
||||
|
||||
fn to_filesize_untagged_value(&self) -> UntaggedValue {
|
||||
UntaggedValue::filesize(*self)
|
||||
UntaggedValue::big_int(*self)
|
||||
}
|
||||
|
||||
fn to_duration_untagged_value(&self) -> UntaggedValue {
|
||||
@ -869,7 +869,7 @@ pub trait I64Ext {
|
||||
impl I64Ext for i64 {
|
||||
fn to_value(&self, the_tag: Tag) -> Value {
|
||||
Value {
|
||||
value: UntaggedValue::Primitive(Primitive::Int(BigInt::from(*self))),
|
||||
value: UntaggedValue::Primitive(Primitive::Int(*self)),
|
||||
tag: the_tag,
|
||||
}
|
||||
}
|
||||
@ -877,7 +877,7 @@ impl I64Ext for i64 {
|
||||
fn to_value_create_tag(&self) -> Value {
|
||||
let end = self.to_string().len();
|
||||
Value {
|
||||
value: UntaggedValue::Primitive(Primitive::Int(BigInt::from(*self))),
|
||||
value: UntaggedValue::Primitive(Primitive::Int(*self)),
|
||||
tag: Tag {
|
||||
anchor: None,
|
||||
span: Span::new(0, end),
|
||||
|
@ -4,7 +4,6 @@ use nu_source::{
|
||||
span_for_spanned_list, DbgDocBldr, DebugDocBuilder, HasFallibleSpan, PrettyDebug, Span,
|
||||
Spanned, SpannedItem,
|
||||
};
|
||||
use num_bigint::BigInt;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::hir::{Expression, Literal, Member, SpannedExpression};
|
||||
@ -14,7 +13,7 @@ use nu_errors::ParseError;
|
||||
#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize)]
|
||||
pub enum UnspannedPathMember {
|
||||
String(String),
|
||||
Int(BigInt),
|
||||
Int(i64),
|
||||
}
|
||||
|
||||
impl UnspannedPathMember {
|
||||
@ -125,8 +124,8 @@ impl PathMember {
|
||||
}
|
||||
|
||||
/// Create a numeric path member
|
||||
pub fn int(int: impl Into<BigInt>, span: impl Into<Span>) -> PathMember {
|
||||
UnspannedPathMember::Int(int.into()).into_path_member(span)
|
||||
pub fn int(int: i64, span: impl Into<Span>) -> PathMember {
|
||||
UnspannedPathMember::Int(int).into_path_member(span)
|
||||
}
|
||||
|
||||
pub fn as_string(&self) -> String {
|
||||
@ -160,8 +159,8 @@ fn parse(raw_column_path: &Spanned<String>) -> (SpannedExpression, Option<ParseE
|
||||
raw_column_path.span.start() + idx,
|
||||
);
|
||||
|
||||
if let Ok(row_number) = current_part.parse::<u64>() {
|
||||
output.push(Member::Int(BigInt::from(row_number), part_span));
|
||||
if let Ok(row_number) = current_part.parse::<i64>() {
|
||||
output.push(Member::Int(row_number, part_span));
|
||||
} else {
|
||||
let trimmed = trim_quotes(¤t_part);
|
||||
output.push(Member::Bare(trimmed.clone().spanned(part_span)));
|
||||
@ -180,8 +179,8 @@ fn parse(raw_column_path: &Spanned<String>) -> (SpannedExpression, Option<ParseE
|
||||
raw_column_path.span.start() + start_index,
|
||||
raw_column_path.span.start() + last_index + 1,
|
||||
);
|
||||
if let Ok(row_number) = current_part.parse::<u64>() {
|
||||
output.push(Member::Int(BigInt::from(row_number), part_span));
|
||||
if let Ok(row_number) = current_part.parse::<i64>() {
|
||||
output.push(Member::Int(row_number, part_span));
|
||||
} else {
|
||||
let current_part = trim_quotes(¤t_part);
|
||||
output.push(Member::Bare(current_part.spanned(part_span)));
|
||||
|
@ -11,7 +11,8 @@ impl std::convert::TryFrom<&Value> for i64 {
|
||||
/// Convert to an i64 integer, if possible
|
||||
fn try_from(value: &Value) -> Result<i64, ShellError> {
|
||||
match &value.value {
|
||||
UntaggedValue::Primitive(Primitive::Int(int)) => {
|
||||
UntaggedValue::Primitive(Primitive::Int(int)) => Ok(*int),
|
||||
UntaggedValue::Primitive(Primitive::BigInt(int)) => {
|
||||
int.tagged(&value.tag).coerce_into("converting to i64")
|
||||
}
|
||||
_ => Err(ShellError::type_error("Integer", value.spanned_type_name())),
|
||||
|
@ -36,6 +36,7 @@ impl PrettyType for Primitive {
|
||||
match self {
|
||||
Primitive::Nothing => ty("nothing"),
|
||||
Primitive::Int(_) => ty("integer"),
|
||||
Primitive::BigInt(_) => ty("big-integer"),
|
||||
Primitive::Range(_) => ty("range"),
|
||||
Primitive::Decimal(_) => ty("decimal"),
|
||||
Primitive::Filesize(_) => ty("filesize"),
|
||||
@ -59,6 +60,7 @@ impl PrettyDebug for Primitive {
|
||||
match self {
|
||||
Primitive::Nothing => DbgDocBldr::primitive("nothing"),
|
||||
Primitive::Int(int) => prim(format_args!("{}", int)),
|
||||
Primitive::BigInt(int) => prim(format_args!("{}", int)),
|
||||
Primitive::Decimal(decimal) => prim(format_args!("{}", decimal)),
|
||||
Primitive::Range(range) => {
|
||||
let (left, left_inclusion) = &range.from;
|
||||
|
@ -24,14 +24,16 @@ const NANOS_PER_SEC: u32 = 1_000_000_000;
|
||||
pub enum Primitive {
|
||||
/// An empty value
|
||||
Nothing,
|
||||
/// A common integer
|
||||
Int(i64),
|
||||
/// A "big int", an integer with arbitrarily large size (aka not limited to 64-bit)
|
||||
#[serde(with = "serde_bigint")]
|
||||
Int(BigInt),
|
||||
BigInt(BigInt),
|
||||
/// A "big decimal", an decimal number with arbitrarily large size (aka not limited to 64-bit)
|
||||
#[serde(with = "serde_bigdecimal")]
|
||||
Decimal(BigDecimal),
|
||||
/// A count in the number of bytes, used as a filesize
|
||||
Filesize(BigInt),
|
||||
Filesize(u64),
|
||||
/// A string value
|
||||
String(String),
|
||||
/// A path to travel to reach a value in a table
|
||||
@ -351,7 +353,7 @@ impl From<BigDecimal> for Primitive {
|
||||
impl From<BigInt> for Primitive {
|
||||
/// Helper to convert from integers to a Primitive value
|
||||
fn from(int: BigInt) -> Primitive {
|
||||
Primitive::Int(int)
|
||||
Primitive::BigInt(int)
|
||||
}
|
||||
}
|
||||
|
||||
@ -373,14 +375,14 @@ macro_rules! from_native_to_primitive {
|
||||
};
|
||||
}
|
||||
|
||||
from_native_to_primitive!(i8, Primitive::Int, BigInt::from_i8);
|
||||
from_native_to_primitive!(i16, Primitive::Int, BigInt::from_i16);
|
||||
from_native_to_primitive!(i32, Primitive::Int, BigInt::from_i32);
|
||||
from_native_to_primitive!(i64, Primitive::Int, BigInt::from_i64);
|
||||
from_native_to_primitive!(u8, Primitive::Int, BigInt::from_u8);
|
||||
from_native_to_primitive!(u16, Primitive::Int, BigInt::from_u16);
|
||||
from_native_to_primitive!(u32, Primitive::Int, BigInt::from_u32);
|
||||
from_native_to_primitive!(u64, Primitive::Int, BigInt::from_u64);
|
||||
from_native_to_primitive!(i8, Primitive::Int, i64::from_i8);
|
||||
from_native_to_primitive!(i16, Primitive::Int, i64::from_i16);
|
||||
from_native_to_primitive!(i32, Primitive::Int, i64::from_i32);
|
||||
from_native_to_primitive!(i64, Primitive::Int, i64::from_i64);
|
||||
from_native_to_primitive!(u8, Primitive::Int, i64::from_u8);
|
||||
from_native_to_primitive!(u16, Primitive::Int, i64::from_u16);
|
||||
from_native_to_primitive!(u32, Primitive::Int, i64::from_u32);
|
||||
from_native_to_primitive!(u64, Primitive::BigInt, BigInt::from_u64);
|
||||
from_native_to_primitive!(f32, Primitive::Decimal, BigDecimal::from_f32);
|
||||
from_native_to_primitive!(f64, Primitive::Decimal, BigDecimal::from_f64);
|
||||
|
||||
@ -410,6 +412,7 @@ impl ShellTypeName for Primitive {
|
||||
match self {
|
||||
Primitive::Nothing => "nothing",
|
||||
Primitive::Int(_) => "integer",
|
||||
Primitive::BigInt(_) => "big integer",
|
||||
Primitive::Range(_) => "range",
|
||||
Primitive::Decimal(_) => "decimal",
|
||||
Primitive::Filesize(_) => "filesize(in bytes)",
|
||||
@ -454,6 +457,7 @@ pub fn format_primitive(primitive: &Primitive, field_name: Option<&String>) -> S
|
||||
}
|
||||
Primitive::Duration(duration) => format_duration(duration),
|
||||
Primitive::Int(i) => i.to_string(),
|
||||
Primitive::BigInt(i) => i.to_string(),
|
||||
Primitive::Decimal(decimal) => {
|
||||
// TODO: We should really pass the precision in here instead of hard coding it
|
||||
let decimal_string = decimal.to_string();
|
||||
|
@ -68,6 +68,36 @@ impl Range {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn min_i64(&self) -> Result<i64, ShellError> {
|
||||
let (from, range_incl) = &self.from;
|
||||
|
||||
let minval = if let Primitive::Nothing = from.item {
|
||||
0
|
||||
} else {
|
||||
from.item.as_i64(from.span)?
|
||||
};
|
||||
|
||||
match range_incl {
|
||||
RangeInclusion::Inclusive => Ok(minval),
|
||||
RangeInclusion::Exclusive => Ok(minval.saturating_add(1)),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn max_i64(&self) -> Result<i64, ShellError> {
|
||||
let (to, range_incl) = &self.to;
|
||||
|
||||
let maxval = if let Primitive::Nothing = to.item {
|
||||
i64::MAX
|
||||
} else {
|
||||
to.item.as_i64(to.span)?
|
||||
};
|
||||
|
||||
match range_incl {
|
||||
RangeInclusion::Inclusive => Ok(maxval),
|
||||
RangeInclusion::Exclusive => Ok(maxval.saturating_sub(1)),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn min_usize(&self) -> Result<usize, ShellError> {
|
||||
let (from, range_incl) = &self.from;
|
||||
|
||||
|
Reference in New Issue
Block a user