Extract core stuff into own crates
This commit extracts five new crates:
- nu-source, which contains the core source-code handling logic in Nu,
including Text, Span, and also the pretty.rs-based debug logic
- nu-parser, which is the parser and expander logic
- nu-protocol, which is the bulk of the types and basic conveniences
used by plugins
- nu-errors, which contains ShellError, ParseError and error handling
conveniences
- nu-textview, which is the textview plugin extracted into a crate
One of the major consequences of this refactor is that it's no longer
possible to `impl X for Spanned<Y>` outside of the `nu-source` crate, so
a lot of types became more concrete (Value became a concrete type
instead of Spanned<Value>, for example).
This also turned a number of inherent methods in the main nu crate into
plain functions (impl Value {} became a bunch of functions in the
`value` namespace in `crate::data::value`).
2019-11-26 03:30:48 +01:00
use crate ::type_name ::ShellTypeName ;
use crate ::value ::column_path ::ColumnPath ;
2020-09-13 23:53:08 +02:00
use crate ::value ::range ::{ Range , RangeInclusion } ;
2020-10-13 04:44:28 +02:00
use crate ::value ::{ serde_bigdecimal , serde_bigint } ;
Extract core stuff into own crates
This commit extracts five new crates:
- nu-source, which contains the core source-code handling logic in Nu,
including Text, Span, and also the pretty.rs-based debug logic
- nu-parser, which is the parser and expander logic
- nu-protocol, which is the bulk of the types and basic conveniences
used by plugins
- nu-errors, which contains ShellError, ParseError and error handling
conveniences
- nu-textview, which is the textview plugin extracted into a crate
One of the major consequences of this refactor is that it's no longer
possible to `impl X for Spanned<Y>` outside of the `nu-source` crate, so
a lot of types became more concrete (Value became a concrete type
instead of Spanned<Value>, for example).
This also turned a number of inherent methods in the main nu crate into
plain functions (impl Value {} became a bunch of functions in the
`value` namespace in `crate::data::value`).
2019-11-26 03:30:48 +01:00
use bigdecimal ::BigDecimal ;
2020-12-12 19:18:03 +01:00
use chrono ::{ DateTime , FixedOffset , Utc } ;
2019-12-04 22:14:52 +01:00
use nu_errors ::{ ExpectedRange , ShellError } ;
use nu_source ::{ PrettyDebug , Span , SpannedItem } ;
Extract core stuff into own crates
This commit extracts five new crates:
- nu-source, which contains the core source-code handling logic in Nu,
including Text, Span, and also the pretty.rs-based debug logic
- nu-parser, which is the parser and expander logic
- nu-protocol, which is the bulk of the types and basic conveniences
used by plugins
- nu-errors, which contains ShellError, ParseError and error handling
conveniences
- nu-textview, which is the textview plugin extracted into a crate
One of the major consequences of this refactor is that it's no longer
possible to `impl X for Spanned<Y>` outside of the `nu-source` crate, so
a lot of types became more concrete (Value became a concrete type
instead of Spanned<Value>, for example).
This also turned a number of inherent methods in the main nu crate into
plain functions (impl Value {} became a bunch of functions in the
`value` namespace in `crate::data::value`).
2019-11-26 03:30:48 +01:00
use num_bigint ::BigInt ;
2020-07-10 19:48:11 +02:00
use num_integer ::Integer ;
2019-12-04 22:14:52 +01:00
use num_traits ::cast ::{ FromPrimitive , ToPrimitive } ;
2020-03-19 00:46:00 +01:00
use num_traits ::identities ::Zero ;
2020-07-10 19:48:11 +02:00
use num_traits ::sign ::Signed ;
Extract core stuff into own crates
This commit extracts five new crates:
- nu-source, which contains the core source-code handling logic in Nu,
including Text, Span, and also the pretty.rs-based debug logic
- nu-parser, which is the parser and expander logic
- nu-protocol, which is the bulk of the types and basic conveniences
used by plugins
- nu-errors, which contains ShellError, ParseError and error handling
conveniences
- nu-textview, which is the textview plugin extracted into a crate
One of the major consequences of this refactor is that it's no longer
possible to `impl X for Spanned<Y>` outside of the `nu-source` crate, so
a lot of types became more concrete (Value became a concrete type
instead of Spanned<Value>, for example).
This also turned a number of inherent methods in the main nu crate into
plain functions (impl Value {} became a bunch of functions in the
`value` namespace in `crate::data::value`).
2019-11-26 03:30:48 +01:00
use serde ::{ Deserialize , Serialize } ;
use std ::path ::PathBuf ;
2020-09-10 05:33:37 +02:00
const NANOS_PER_SEC : u32 = 1_000_000_000 ;
2020-07-10 19:48:11 +02:00
2020-09-10 05:33:37 +02:00
/// The most fundamental of structured values in Nu are the Primitive values. These values represent types like integers, strings, booleans, dates, etc
/// that are then used as the building blocks of more complex structures.
2020-01-15 17:28:31 +01:00
///
/// Primitives also include marker values BeginningOfStream and EndOfStream which denote a change of condition in the stream
2019-12-31 05:05:02 +01:00
#[ derive(Debug, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Deserialize, Serialize) ]
Extract core stuff into own crates
This commit extracts five new crates:
- nu-source, which contains the core source-code handling logic in Nu,
including Text, Span, and also the pretty.rs-based debug logic
- nu-parser, which is the parser and expander logic
- nu-protocol, which is the bulk of the types and basic conveniences
used by plugins
- nu-errors, which contains ShellError, ParseError and error handling
conveniences
- nu-textview, which is the textview plugin extracted into a crate
One of the major consequences of this refactor is that it's no longer
possible to `impl X for Spanned<Y>` outside of the `nu-source` crate, so
a lot of types became more concrete (Value became a concrete type
instead of Spanned<Value>, for example).
This also turned a number of inherent methods in the main nu crate into
plain functions (impl Value {} became a bunch of functions in the
`value` namespace in `crate::data::value`).
2019-11-26 03:30:48 +01:00
pub enum Primitive {
2020-01-15 17:28:31 +01:00
/// An empty value
Extract core stuff into own crates
This commit extracts five new crates:
- nu-source, which contains the core source-code handling logic in Nu,
including Text, Span, and also the pretty.rs-based debug logic
- nu-parser, which is the parser and expander logic
- nu-protocol, which is the bulk of the types and basic conveniences
used by plugins
- nu-errors, which contains ShellError, ParseError and error handling
conveniences
- nu-textview, which is the textview plugin extracted into a crate
One of the major consequences of this refactor is that it's no longer
possible to `impl X for Spanned<Y>` outside of the `nu-source` crate, so
a lot of types became more concrete (Value became a concrete type
instead of Spanned<Value>, for example).
This also turned a number of inherent methods in the main nu crate into
plain functions (impl Value {} became a bunch of functions in the
`value` namespace in `crate::data::value`).
2019-11-26 03:30:48 +01:00
Nothing ,
2020-01-15 17:28:31 +01:00
/// A "big int", an integer with arbitrarily large size (aka not limited to 64-bit)
2020-10-13 04:44:28 +02:00
#[ serde(with = " serde_bigint " ) ]
Extract core stuff into own crates
This commit extracts five new crates:
- nu-source, which contains the core source-code handling logic in Nu,
including Text, Span, and also the pretty.rs-based debug logic
- nu-parser, which is the parser and expander logic
- nu-protocol, which is the bulk of the types and basic conveniences
used by plugins
- nu-errors, which contains ShellError, ParseError and error handling
conveniences
- nu-textview, which is the textview plugin extracted into a crate
One of the major consequences of this refactor is that it's no longer
possible to `impl X for Spanned<Y>` outside of the `nu-source` crate, so
a lot of types became more concrete (Value became a concrete type
instead of Spanned<Value>, for example).
This also turned a number of inherent methods in the main nu crate into
plain functions (impl Value {} became a bunch of functions in the
`value` namespace in `crate::data::value`).
2019-11-26 03:30:48 +01:00
Int ( BigInt ) ,
2020-01-15 17:28:31 +01:00
/// A "big decimal", an decimal number with arbitrarily large size (aka not limited to 64-bit)
2020-10-13 04:44:28 +02:00
#[ serde(with = " serde_bigdecimal " ) ]
Extract core stuff into own crates
This commit extracts five new crates:
- nu-source, which contains the core source-code handling logic in Nu,
including Text, Span, and also the pretty.rs-based debug logic
- nu-parser, which is the parser and expander logic
- nu-protocol, which is the bulk of the types and basic conveniences
used by plugins
- nu-errors, which contains ShellError, ParseError and error handling
conveniences
- nu-textview, which is the textview plugin extracted into a crate
One of the major consequences of this refactor is that it's no longer
possible to `impl X for Spanned<Y>` outside of the `nu-source` crate, so
a lot of types became more concrete (Value became a concrete type
instead of Spanned<Value>, for example).
This also turned a number of inherent methods in the main nu crate into
plain functions (impl Value {} became a bunch of functions in the
`value` namespace in `crate::data::value`).
2019-11-26 03:30:48 +01:00
Decimal ( BigDecimal ) ,
2020-01-15 17:28:31 +01:00
/// A count in the number of bytes, used as a filesize
2021-01-29 23:35:18 +01:00
Filesize ( BigInt ) ,
2020-01-15 17:28:31 +01:00
/// A string value
Extract core stuff into own crates
This commit extracts five new crates:
- nu-source, which contains the core source-code handling logic in Nu,
including Text, Span, and also the pretty.rs-based debug logic
- nu-parser, which is the parser and expander logic
- nu-protocol, which is the bulk of the types and basic conveniences
used by plugins
- nu-errors, which contains ShellError, ParseError and error handling
conveniences
- nu-textview, which is the textview plugin extracted into a crate
One of the major consequences of this refactor is that it's no longer
possible to `impl X for Spanned<Y>` outside of the `nu-source` crate, so
a lot of types became more concrete (Value became a concrete type
instead of Spanned<Value>, for example).
This also turned a number of inherent methods in the main nu crate into
plain functions (impl Value {} became a bunch of functions in the
`value` namespace in `crate::data::value`).
2019-11-26 03:30:48 +01:00
String ( String ) ,
2020-01-15 17:28:31 +01:00
/// A path to travel to reach a value in a table
Extract core stuff into own crates
This commit extracts five new crates:
- nu-source, which contains the core source-code handling logic in Nu,
including Text, Span, and also the pretty.rs-based debug logic
- nu-parser, which is the parser and expander logic
- nu-protocol, which is the bulk of the types and basic conveniences
used by plugins
- nu-errors, which contains ShellError, ParseError and error handling
conveniences
- nu-textview, which is the textview plugin extracted into a crate
One of the major consequences of this refactor is that it's no longer
possible to `impl X for Spanned<Y>` outside of the `nu-source` crate, so
a lot of types became more concrete (Value became a concrete type
instead of Spanned<Value>, for example).
This also turned a number of inherent methods in the main nu crate into
plain functions (impl Value {} became a bunch of functions in the
`value` namespace in `crate::data::value`).
2019-11-26 03:30:48 +01:00
ColumnPath ( ColumnPath ) ,
2020-01-15 17:28:31 +01:00
/// A glob pattern, eg foo*
2021-01-08 08:30:41 +01:00
GlobPattern ( String ) ,
2020-01-15 17:28:31 +01:00
/// A boolean value
Extract core stuff into own crates
This commit extracts five new crates:
- nu-source, which contains the core source-code handling logic in Nu,
including Text, Span, and also the pretty.rs-based debug logic
- nu-parser, which is the parser and expander logic
- nu-protocol, which is the bulk of the types and basic conveniences
used by plugins
- nu-errors, which contains ShellError, ParseError and error handling
conveniences
- nu-textview, which is the textview plugin extracted into a crate
One of the major consequences of this refactor is that it's no longer
possible to `impl X for Spanned<Y>` outside of the `nu-source` crate, so
a lot of types became more concrete (Value became a concrete type
instead of Spanned<Value>, for example).
This also turned a number of inherent methods in the main nu crate into
plain functions (impl Value {} became a bunch of functions in the
`value` namespace in `crate::data::value`).
2019-11-26 03:30:48 +01:00
Boolean ( bool ) ,
2020-12-12 19:18:03 +01:00
/// A date value
Date ( DateTime < FixedOffset > ) ,
2020-07-10 19:48:11 +02:00
/// A count in the number of nanoseconds
2020-10-13 04:44:28 +02:00
#[ serde(with = " serde_bigint " ) ]
2020-07-10 19:48:11 +02:00
Duration ( BigInt ) ,
2020-01-15 17:28:31 +01:00
/// A range of values
2019-12-04 22:14:52 +01:00
Range ( Box < Range > ) ,
2020-01-15 17:28:31 +01:00
/// A file path
2021-01-08 08:30:41 +01:00
FilePath ( PathBuf ) ,
2020-01-15 17:28:31 +01:00
/// A vector of raw binary data
Extract core stuff into own crates
This commit extracts five new crates:
- nu-source, which contains the core source-code handling logic in Nu,
including Text, Span, and also the pretty.rs-based debug logic
- nu-parser, which is the parser and expander logic
- nu-protocol, which is the bulk of the types and basic conveniences
used by plugins
- nu-errors, which contains ShellError, ParseError and error handling
conveniences
- nu-textview, which is the textview plugin extracted into a crate
One of the major consequences of this refactor is that it's no longer
possible to `impl X for Spanned<Y>` outside of the `nu-source` crate, so
a lot of types became more concrete (Value became a concrete type
instead of Spanned<Value>, for example).
This also turned a number of inherent methods in the main nu crate into
plain functions (impl Value {} became a bunch of functions in the
`value` namespace in `crate::data::value`).
2019-11-26 03:30:48 +01:00
#[ serde(with = " serde_bytes " ) ]
Binary ( Vec < u8 > ) ,
2020-01-15 17:28:31 +01:00
/// Beginning of stream marker, a pseudo-value not intended for tables
Extract core stuff into own crates
This commit extracts five new crates:
- nu-source, which contains the core source-code handling logic in Nu,
including Text, Span, and also the pretty.rs-based debug logic
- nu-parser, which is the parser and expander logic
- nu-protocol, which is the bulk of the types and basic conveniences
used by plugins
- nu-errors, which contains ShellError, ParseError and error handling
conveniences
- nu-textview, which is the textview plugin extracted into a crate
One of the major consequences of this refactor is that it's no longer
possible to `impl X for Spanned<Y>` outside of the `nu-source` crate, so
a lot of types became more concrete (Value became a concrete type
instead of Spanned<Value>, for example).
This also turned a number of inherent methods in the main nu crate into
plain functions (impl Value {} became a bunch of functions in the
`value` namespace in `crate::data::value`).
2019-11-26 03:30:48 +01:00
BeginningOfStream ,
2020-01-15 17:28:31 +01:00
/// End of stream marker, a pseudo-value not intended for tables
Extract core stuff into own crates
This commit extracts five new crates:
- nu-source, which contains the core source-code handling logic in Nu,
including Text, Span, and also the pretty.rs-based debug logic
- nu-parser, which is the parser and expander logic
- nu-protocol, which is the bulk of the types and basic conveniences
used by plugins
- nu-errors, which contains ShellError, ParseError and error handling
conveniences
- nu-textview, which is the textview plugin extracted into a crate
One of the major consequences of this refactor is that it's no longer
possible to `impl X for Spanned<Y>` outside of the `nu-source` crate, so
a lot of types became more concrete (Value became a concrete type
instead of Spanned<Value>, for example).
This also turned a number of inherent methods in the main nu crate into
plain functions (impl Value {} became a bunch of functions in the
`value` namespace in `crate::data::value`).
2019-11-26 03:30:48 +01:00
EndOfStream ,
}
2019-12-04 22:14:52 +01:00
impl Primitive {
2020-01-15 17:28:31 +01:00
/// Converts a primitive value to a u64, if possible. Uses a span to build an error if the conversion isn't possible.
2019-12-04 22:14:52 +01:00
pub fn as_u64 ( & self , span : Span ) -> Result < u64 , ShellError > {
match self {
2020-08-03 00:34:33 +02:00
Primitive ::Int ( int ) = > int . to_u64 ( ) . ok_or_else ( | | {
ShellError ::range_error (
2019-12-04 22:14:52 +01:00
ExpectedRange ::U64 ,
& format! ( " {} " , int ) . spanned ( span ) ,
2020-11-11 21:35:02 +01:00
" converting an integer into an unsigned 64-bit integer " ,
2020-08-03 00:34:33 +02:00
)
} ) ,
2020-08-04 00:47:19 +02:00
Primitive ::Decimal ( decimal ) = > decimal . to_u64 ( ) . ok_or_else ( | | {
ShellError ::range_error (
ExpectedRange ::U64 ,
& format! ( " {} " , decimal ) . spanned ( span ) ,
2020-11-11 21:35:02 +01:00
" converting a decimal into an unsigned 64-bit integer " ,
)
} ) ,
other = > Err ( ShellError ::type_error (
" number " ,
other . type_name ( ) . spanned ( span ) ,
) ) ,
}
}
pub fn as_i64 ( & self , span : Span ) -> Result < i64 , ShellError > {
match self {
Primitive ::Int ( int ) = > int . to_i64 ( ) . ok_or_else ( | | {
ShellError ::range_error (
ExpectedRange ::I64 ,
& format! ( " {} " , int ) . spanned ( span ) ,
" converting an integer into a signed 64-bit integer " ,
)
} ) ,
Primitive ::Decimal ( decimal ) = > decimal . to_i64 ( ) . ok_or_else ( | | {
ShellError ::range_error (
ExpectedRange ::I64 ,
& format! ( " {} " , decimal ) . spanned ( span ) ,
" converting a decimal into a signed 64-bit integer " ,
2020-08-04 00:47:19 +02:00
)
} ) ,
2019-12-04 22:14:52 +01:00
other = > Err ( ShellError ::type_error (
2020-08-04 00:47:19 +02:00
" number " ,
2019-12-04 22:14:52 +01:00
other . type_name ( ) . spanned ( span ) ,
) ) ,
}
}
2020-03-31 01:19:48 +02:00
2020-07-10 19:48:11 +02:00
// FIXME: This is a bad name, but no other way to differentiate with our own Duration.
pub fn into_chrono_duration ( self , span : Span ) -> Result < chrono ::Duration , ShellError > {
match self {
Primitive ::Duration ( duration ) = > {
2020-09-10 05:33:37 +02:00
// Divide into seconds because BigInt can be larger than i64
2020-07-10 19:48:11 +02:00
let ( secs , nanos ) = duration . div_rem ( & BigInt ::from ( NANOS_PER_SEC ) ) ;
let secs = match secs . to_i64 ( ) {
Some ( secs ) = > secs ,
None = > {
return Err ( ShellError ::labeled_error (
" Internal duration conversion overflow. " ,
" duration overflow " ,
span ,
) )
}
} ;
2020-09-10 05:33:37 +02:00
// This should never fail since NANOS_PER_SEC won't overflow
let nanos = nanos . to_i64 ( ) . expect ( " Unexpected i64 overflow " ) ;
2020-07-10 19:48:11 +02:00
// This should also never fail since we are adding less than NANOS_PER_SEC.
2020-08-03 00:34:33 +02:00
chrono ::Duration ::seconds ( secs )
2020-09-10 05:33:37 +02:00
. checked_add ( & chrono ::Duration ::nanoseconds ( nanos ) )
2020-08-03 00:34:33 +02:00
. ok_or_else ( | | ShellError ::unexpected ( " Unexpected duration overflow " ) )
2020-07-10 19:48:11 +02:00
}
other = > Err ( ShellError ::type_error (
" duration " ,
other . type_name ( ) . spanned ( span ) ,
) ) ,
}
}
2020-03-31 01:19:48 +02:00
pub fn into_string ( self , span : Span ) -> Result < String , ShellError > {
match self {
Primitive ::String ( s ) = > Ok ( s ) ,
other = > Err ( ShellError ::type_error (
" string " ,
other . type_name ( ) . spanned ( span ) ,
) ) ,
}
}
2020-04-26 19:30:52 +02:00
/// Returns true if the value is empty
pub fn is_empty ( & self ) -> bool {
match self {
Primitive ::Nothing = > true ,
Primitive ::String ( s ) = > s . is_empty ( ) ,
_ = > false ,
}
}
2019-12-04 22:14:52 +01:00
}
2020-09-13 06:25:38 +02:00
impl From < bool > for Primitive {
/// Helper to convert from boolean to a primitive
fn from ( b : bool ) -> Primitive {
Primitive ::Boolean ( b )
}
}
2020-05-18 14:56:01 +02:00
impl From < & str > for Primitive {
/// Helper to convert from string slices to a primitive
fn from ( s : & str ) -> Primitive {
Primitive ::String ( s . to_string ( ) )
}
}
impl From < String > for Primitive {
/// Helper to convert from Strings to a primitive
fn from ( s : String ) -> Primitive {
Primitive ::String ( s )
}
}
Extract core stuff into own crates
This commit extracts five new crates:
- nu-source, which contains the core source-code handling logic in Nu,
including Text, Span, and also the pretty.rs-based debug logic
- nu-parser, which is the parser and expander logic
- nu-protocol, which is the bulk of the types and basic conveniences
used by plugins
- nu-errors, which contains ShellError, ParseError and error handling
conveniences
- nu-textview, which is the textview plugin extracted into a crate
One of the major consequences of this refactor is that it's no longer
possible to `impl X for Spanned<Y>` outside of the `nu-source` crate, so
a lot of types became more concrete (Value became a concrete type
instead of Spanned<Value>, for example).
This also turned a number of inherent methods in the main nu crate into
plain functions (impl Value {} became a bunch of functions in the
`value` namespace in `crate::data::value`).
2019-11-26 03:30:48 +01:00
impl From < BigDecimal > for Primitive {
2020-01-15 17:28:31 +01:00
/// Helper to convert from decimals to a Primitive value
Extract core stuff into own crates
This commit extracts five new crates:
- nu-source, which contains the core source-code handling logic in Nu,
including Text, Span, and also the pretty.rs-based debug logic
- nu-parser, which is the parser and expander logic
- nu-protocol, which is the bulk of the types and basic conveniences
used by plugins
- nu-errors, which contains ShellError, ParseError and error handling
conveniences
- nu-textview, which is the textview plugin extracted into a crate
One of the major consequences of this refactor is that it's no longer
possible to `impl X for Spanned<Y>` outside of the `nu-source` crate, so
a lot of types became more concrete (Value became a concrete type
instead of Spanned<Value>, for example).
This also turned a number of inherent methods in the main nu crate into
plain functions (impl Value {} became a bunch of functions in the
`value` namespace in `crate::data::value`).
2019-11-26 03:30:48 +01:00
fn from ( decimal : BigDecimal ) -> Primitive {
Primitive ::Decimal ( decimal )
}
}
2020-03-19 00:46:00 +01:00
impl From < BigInt > for Primitive {
/// Helper to convert from integers to a Primitive value
fn from ( int : BigInt ) -> Primitive {
Primitive ::Int ( int )
}
}
Extract core stuff into own crates
This commit extracts five new crates:
- nu-source, which contains the core source-code handling logic in Nu,
including Text, Span, and also the pretty.rs-based debug logic
- nu-parser, which is the parser and expander logic
- nu-protocol, which is the bulk of the types and basic conveniences
used by plugins
- nu-errors, which contains ShellError, ParseError and error handling
conveniences
- nu-textview, which is the textview plugin extracted into a crate
One of the major consequences of this refactor is that it's no longer
possible to `impl X for Spanned<Y>` outside of the `nu-source` crate, so
a lot of types became more concrete (Value became a concrete type
instead of Spanned<Value>, for example).
This also turned a number of inherent methods in the main nu crate into
plain functions (impl Value {} became a bunch of functions in the
`value` namespace in `crate::data::value`).
2019-11-26 03:30:48 +01:00
impl From < f64 > for Primitive {
2020-01-15 17:28:31 +01:00
/// Helper to convert from 64-bit float to a Primitive value
Extract core stuff into own crates
This commit extracts five new crates:
- nu-source, which contains the core source-code handling logic in Nu,
including Text, Span, and also the pretty.rs-based debug logic
- nu-parser, which is the parser and expander logic
- nu-protocol, which is the bulk of the types and basic conveniences
used by plugins
- nu-errors, which contains ShellError, ParseError and error handling
conveniences
- nu-textview, which is the textview plugin extracted into a crate
One of the major consequences of this refactor is that it's no longer
possible to `impl X for Spanned<Y>` outside of the `nu-source` crate, so
a lot of types became more concrete (Value became a concrete type
instead of Spanned<Value>, for example).
This also turned a number of inherent methods in the main nu crate into
plain functions (impl Value {} became a bunch of functions in the
`value` namespace in `crate::data::value`).
2019-11-26 03:30:48 +01:00
fn from ( float : f64 ) -> Primitive {
2020-01-04 07:44:17 +01:00
if let Some ( f ) = BigDecimal ::from_f64 ( float ) {
Primitive ::Decimal ( f )
} else {
unreachable! ( " Internal error: protocol did not use f64-compatible decimal " )
}
Extract core stuff into own crates
This commit extracts five new crates:
- nu-source, which contains the core source-code handling logic in Nu,
including Text, Span, and also the pretty.rs-based debug logic
- nu-parser, which is the parser and expander logic
- nu-protocol, which is the bulk of the types and basic conveniences
used by plugins
- nu-errors, which contains ShellError, ParseError and error handling
conveniences
- nu-textview, which is the textview plugin extracted into a crate
One of the major consequences of this refactor is that it's no longer
possible to `impl X for Spanned<Y>` outside of the `nu-source` crate, so
a lot of types became more concrete (Value became a concrete type
instead of Spanned<Value>, for example).
This also turned a number of inherent methods in the main nu crate into
plain functions (impl Value {} became a bunch of functions in the
`value` namespace in `crate::data::value`).
2019-11-26 03:30:48 +01:00
}
}
2020-07-10 19:48:11 +02:00
impl From < chrono ::Duration > for Primitive {
fn from ( duration : chrono ::Duration ) -> Primitive {
// FIXME: This is a hack since chrono::Duration does not give access to its 'nanos' field.
let secs : i64 = duration . num_seconds ( ) ;
// This will never fail.
let nanos : u32 = duration
. checked_sub ( & chrono ::Duration ::seconds ( secs ) )
. expect ( " Unexpected overflow " )
. num_nanoseconds ( )
. expect ( " Unexpected overflow " ) as u32 ;
Primitive ::Duration ( BigInt ::from ( secs ) * NANOS_PER_SEC + nanos )
}
}
2020-09-01 07:09:55 +02:00
impl std ::fmt ::Display for Primitive {
fn fmt ( & self , f : & mut std ::fmt ::Formatter ) -> std ::fmt ::Result {
write! ( f , " {:?} " , self )
}
}
Extract core stuff into own crates
This commit extracts five new crates:
- nu-source, which contains the core source-code handling logic in Nu,
including Text, Span, and also the pretty.rs-based debug logic
- nu-parser, which is the parser and expander logic
- nu-protocol, which is the bulk of the types and basic conveniences
used by plugins
- nu-errors, which contains ShellError, ParseError and error handling
conveniences
- nu-textview, which is the textview plugin extracted into a crate
One of the major consequences of this refactor is that it's no longer
possible to `impl X for Spanned<Y>` outside of the `nu-source` crate, so
a lot of types became more concrete (Value became a concrete type
instead of Spanned<Value>, for example).
This also turned a number of inherent methods in the main nu crate into
plain functions (impl Value {} became a bunch of functions in the
`value` namespace in `crate::data::value`).
2019-11-26 03:30:48 +01:00
impl ShellTypeName for Primitive {
2020-01-15 17:28:31 +01:00
/// Get the name of the type of a Primitive value
Extract core stuff into own crates
This commit extracts five new crates:
- nu-source, which contains the core source-code handling logic in Nu,
including Text, Span, and also the pretty.rs-based debug logic
- nu-parser, which is the parser and expander logic
- nu-protocol, which is the bulk of the types and basic conveniences
used by plugins
- nu-errors, which contains ShellError, ParseError and error handling
conveniences
- nu-textview, which is the textview plugin extracted into a crate
One of the major consequences of this refactor is that it's no longer
possible to `impl X for Spanned<Y>` outside of the `nu-source` crate, so
a lot of types became more concrete (Value became a concrete type
instead of Spanned<Value>, for example).
This also turned a number of inherent methods in the main nu crate into
plain functions (impl Value {} became a bunch of functions in the
`value` namespace in `crate::data::value`).
2019-11-26 03:30:48 +01:00
fn type_name ( & self ) -> & 'static str {
match self {
Primitive ::Nothing = > " nothing " ,
Primitive ::Int ( _ ) = > " integer " ,
2019-12-04 22:14:52 +01:00
Primitive ::Range ( _ ) = > " range " ,
Extract core stuff into own crates
This commit extracts five new crates:
- nu-source, which contains the core source-code handling logic in Nu,
including Text, Span, and also the pretty.rs-based debug logic
- nu-parser, which is the parser and expander logic
- nu-protocol, which is the bulk of the types and basic conveniences
used by plugins
- nu-errors, which contains ShellError, ParseError and error handling
conveniences
- nu-textview, which is the textview plugin extracted into a crate
One of the major consequences of this refactor is that it's no longer
possible to `impl X for Spanned<Y>` outside of the `nu-source` crate, so
a lot of types became more concrete (Value became a concrete type
instead of Spanned<Value>, for example).
This also turned a number of inherent methods in the main nu crate into
plain functions (impl Value {} became a bunch of functions in the
`value` namespace in `crate::data::value`).
2019-11-26 03:30:48 +01:00
Primitive ::Decimal ( _ ) = > " decimal " ,
2020-07-11 04:17:37 +02:00
Primitive ::Filesize ( _ ) = > " filesize(in bytes) " ,
Extract core stuff into own crates
This commit extracts five new crates:
- nu-source, which contains the core source-code handling logic in Nu,
including Text, Span, and also the pretty.rs-based debug logic
- nu-parser, which is the parser and expander logic
- nu-protocol, which is the bulk of the types and basic conveniences
used by plugins
- nu-errors, which contains ShellError, ParseError and error handling
conveniences
- nu-textview, which is the textview plugin extracted into a crate
One of the major consequences of this refactor is that it's no longer
possible to `impl X for Spanned<Y>` outside of the `nu-source` crate, so
a lot of types became more concrete (Value became a concrete type
instead of Spanned<Value>, for example).
This also turned a number of inherent methods in the main nu crate into
plain functions (impl Value {} became a bunch of functions in the
`value` namespace in `crate::data::value`).
2019-11-26 03:30:48 +01:00
Primitive ::String ( _ ) = > " string " ,
Primitive ::ColumnPath ( _ ) = > " column path " ,
2021-01-08 08:30:41 +01:00
Primitive ::GlobPattern ( _ ) = > " pattern " ,
Extract core stuff into own crates
This commit extracts five new crates:
- nu-source, which contains the core source-code handling logic in Nu,
including Text, Span, and also the pretty.rs-based debug logic
- nu-parser, which is the parser and expander logic
- nu-protocol, which is the bulk of the types and basic conveniences
used by plugins
- nu-errors, which contains ShellError, ParseError and error handling
conveniences
- nu-textview, which is the textview plugin extracted into a crate
One of the major consequences of this refactor is that it's no longer
possible to `impl X for Spanned<Y>` outside of the `nu-source` crate, so
a lot of types became more concrete (Value became a concrete type
instead of Spanned<Value>, for example).
This also turned a number of inherent methods in the main nu crate into
plain functions (impl Value {} became a bunch of functions in the
`value` namespace in `crate::data::value`).
2019-11-26 03:30:48 +01:00
Primitive ::Boolean ( _ ) = > " boolean " ,
Primitive ::Date ( _ ) = > " date " ,
Primitive ::Duration ( _ ) = > " duration " ,
2021-01-08 08:30:41 +01:00
Primitive ::FilePath ( _ ) = > " file path " ,
Extract core stuff into own crates
This commit extracts five new crates:
- nu-source, which contains the core source-code handling logic in Nu,
including Text, Span, and also the pretty.rs-based debug logic
- nu-parser, which is the parser and expander logic
- nu-protocol, which is the bulk of the types and basic conveniences
used by plugins
- nu-errors, which contains ShellError, ParseError and error handling
conveniences
- nu-textview, which is the textview plugin extracted into a crate
One of the major consequences of this refactor is that it's no longer
possible to `impl X for Spanned<Y>` outside of the `nu-source` crate, so
a lot of types became more concrete (Value became a concrete type
instead of Spanned<Value>, for example).
This also turned a number of inherent methods in the main nu crate into
plain functions (impl Value {} became a bunch of functions in the
`value` namespace in `crate::data::value`).
2019-11-26 03:30:48 +01:00
Primitive ::Binary ( _ ) = > " binary " ,
Primitive ::BeginningOfStream = > " marker<beginning of stream> " ,
Primitive ::EndOfStream = > " marker<end of stream> " ,
}
}
}
2019-12-09 19:39:51 +01:00
2020-01-15 17:28:31 +01:00
/// Format a Primitive value into a string
2019-12-09 19:39:51 +01:00
pub fn format_primitive ( primitive : & Primitive , field_name : Option < & String > ) -> String {
match primitive {
Primitive ::Nothing = > String ::new ( ) ,
Primitive ::BeginningOfStream = > String ::new ( ) ,
Primitive ::EndOfStream = > String ::new ( ) ,
2021-01-08 08:30:41 +01:00
Primitive ::FilePath ( p ) = > format! ( " {} " , p . display ( ) ) ,
2020-07-11 04:17:37 +02:00
Primitive ::Filesize ( num_bytes ) = > {
2021-01-29 23:35:18 +01:00
if let Some ( value ) = num_bytes . to_u128 ( ) {
let byte = byte_unit ::Byte ::from_bytes ( value ) ;
2019-12-09 19:39:51 +01:00
2021-01-29 23:35:18 +01:00
if byte . get_bytes ( ) = = 0 u128 {
return " — " . to_string ( ) ;
}
2019-12-09 19:39:51 +01:00
2021-01-29 23:35:18 +01:00
let byte = byte . get_appropriate_unit ( false ) ;
2019-12-09 19:39:51 +01:00
2021-01-29 23:35:18 +01:00
match byte . get_unit ( ) {
byte_unit ::ByteUnit ::B = > format! ( " {} B " , byte . get_value ( ) ) ,
_ = > byte . format ( 1 ) ,
}
} else {
format! ( " {} B " , num_bytes )
2019-12-09 19:39:51 +01:00
}
}
2020-07-10 19:48:11 +02:00
Primitive ::Duration ( duration ) = > format_duration ( duration ) ,
2019-12-09 19:39:51 +01:00
Primitive ::Int ( i ) = > i . to_string ( ) ,
2020-10-30 18:40:28 +01:00
Primitive ::Decimal ( decimal ) = > {
// TODO: We should really pass the precision in here instead of hard coding it
let decimal_string = decimal . to_string ( ) ;
let decimal_places : Vec < & str > = decimal_string . split ( '.' ) . collect ( ) ;
if decimal_places . len ( ) = = 2 & & decimal_places [ 1 ] . len ( ) > 4 {
format! ( " {:.4} " , decimal )
} else {
format! ( " {} " , decimal )
}
}
2019-12-04 22:14:52 +01:00
Primitive ::Range ( range ) = > format! (
2020-09-13 23:53:08 +02:00
" {}..{}{} " ,
2019-12-04 22:14:52 +01:00
format_primitive ( & range . from . 0. item , None ) ,
2020-09-13 23:53:08 +02:00
if range . to . 1 = = RangeInclusion ::Exclusive {
" < "
} else {
" "
} ,
2019-12-04 22:14:52 +01:00
format_primitive ( & range . to . 0. item , None )
) ,
2021-01-08 08:30:41 +01:00
Primitive ::GlobPattern ( s ) = > s . to_string ( ) ,
2019-12-09 19:39:51 +01:00
Primitive ::String ( s ) = > s . to_owned ( ) ,
Primitive ::ColumnPath ( p ) = > {
let mut members = p . iter ( ) ;
let mut f = String ::new ( ) ;
f . push_str (
& members
. next ( )
. expect ( " BUG: column path with zero members " )
. display ( ) ,
) ;
for member in members {
2020-11-22 01:37:16 +01:00
f . push ( '.' ) ;
2019-12-09 19:39:51 +01:00
f . push_str ( & member . display ( ) )
}
f
}
Primitive ::Boolean ( b ) = > match ( b , field_name ) {
2021-02-11 09:50:33 +01:00
( true , None ) = > " true " ,
( false , None ) = > " false " ,
2019-12-09 19:39:51 +01:00
( true , Some ( s ) ) if ! s . is_empty ( ) = > s ,
( false , Some ( s ) ) if ! s . is_empty ( ) = > " " ,
2021-02-11 09:50:33 +01:00
( true , Some ( _ ) ) = > " true " ,
( false , Some ( _ ) ) = > " false " ,
2019-12-09 19:39:51 +01:00
}
. to_owned ( ) ,
Primitive ::Binary ( _ ) = > " <binary> " . to_owned ( ) ,
2020-01-11 21:49:20 +01:00
Primitive ::Date ( d ) = > format_date ( d ) ,
2019-12-09 19:39:51 +01:00
}
}
2019-12-04 22:14:52 +01:00
2020-07-10 19:48:11 +02:00
/// Format a duration in nanoseconds into a string
pub fn format_duration ( duration : & BigInt ) -> String {
2020-09-19 19:13:14 +02:00
let is_zero = duration . is_zero ( ) ;
2020-07-10 19:48:11 +02:00
// FIXME: This involves a lot of allocation, but it seems inevitable with BigInt.
let big_int_1000 = BigInt ::from ( 1000 ) ;
let big_int_60 = BigInt ::from ( 60 ) ;
let big_int_24 = BigInt ::from ( 24 ) ;
2020-09-10 05:33:37 +02:00
// We only want the biggest subdivision to have the negative sign.
2020-07-10 19:48:11 +02:00
let ( sign , duration ) = if duration . is_zero ( ) | | duration . is_positive ( ) {
( 1 , duration . clone ( ) )
} else {
( - 1 , - duration )
} ;
let ( micros , nanos ) : ( BigInt , BigInt ) = duration . div_rem ( & big_int_1000 ) ;
let ( millis , micros ) : ( BigInt , BigInt ) = micros . div_rem ( & big_int_1000 ) ;
let ( secs , millis ) : ( BigInt , BigInt ) = millis . div_rem ( & big_int_1000 ) ;
let ( mins , secs ) : ( BigInt , BigInt ) = secs . div_rem ( & big_int_60 ) ;
let ( hours , mins ) : ( BigInt , BigInt ) = mins . div_rem ( & big_int_60 ) ;
let ( days , hours ) : ( BigInt , BigInt ) = hours . div_rem ( & big_int_24 ) ;
2020-07-10 23:06:52 +02:00
let mut output_prep = vec! [ ] ;
if ! days . is_zero ( ) {
2020-08-15 21:03:28 +02:00
output_prep . push ( format! ( " {} day " , days ) ) ;
2020-07-10 23:06:52 +02:00
}
if ! hours . is_zero ( ) {
2020-08-15 21:03:28 +02:00
output_prep . push ( format! ( " {} hr " , hours ) ) ;
2020-07-10 23:06:52 +02:00
}
if ! mins . is_zero ( ) {
2020-08-15 21:03:28 +02:00
output_prep . push ( format! ( " {} min " , mins ) ) ;
2019-12-09 19:39:51 +01:00
}
2020-09-19 19:13:14 +02:00
// output 0sec for zero duration
if is_zero | | ! secs . is_zero ( ) {
2020-08-15 21:03:28 +02:00
output_prep . push ( format! ( " {} sec " , secs ) ) ;
2020-07-10 23:06:52 +02:00
}
if ! millis . is_zero ( ) {
output_prep . push ( format! ( " {} ms " , millis ) ) ;
}
if ! micros . is_zero ( ) {
output_prep . push ( format! ( " {} us " , micros ) ) ;
}
if ! nanos . is_zero ( ) {
output_prep . push ( format! ( " {} ns " , nanos ) ) ;
}
format! (
" {}{} " ,
if sign = = - 1 { " - " } else { " " } ,
output_prep . join ( " " )
)
2019-12-09 19:39:51 +01:00
}
2020-01-11 21:49:20 +01:00
2020-04-18 03:50:58 +02:00
#[ allow(clippy::cognitive_complexity) ]
2020-12-12 19:18:03 +01:00
/// Format a date value into a humanized string (eg "1 week ago" instead of a formal date string)
pub fn format_date ( d : & DateTime < FixedOffset > ) -> String {
2020-01-11 21:49:20 +01:00
let utc : DateTime < Utc > = Utc ::now ( ) ;
let duration = utc . signed_duration_since ( * d ) ;
2020-04-18 03:50:58 +02:00
if duration . num_seconds ( ) < 0 {
// Our duration is negative, so we need to speak about the future
if - duration . num_weeks ( ) > = 52 {
let num_years = - duration . num_weeks ( ) / 52 ;
format! (
" {} year{} from now " ,
num_years ,
if num_years = = 1 { " " } else { " s " }
)
} else if - duration . num_weeks ( ) > = 4 {
let num_months = - duration . num_weeks ( ) / 4 ;
format! (
" {} month{} from now " ,
num_months ,
if num_months = = 1 { " " } else { " s " }
)
} else if - duration . num_weeks ( ) > = 1 {
let num_weeks = - duration . num_weeks ( ) ;
format! (
" {} week{} from now " ,
num_weeks ,
if num_weeks = = 1 { " " } else { " s " }
)
} else if - duration . num_days ( ) > = 1 {
let num_days = - duration . num_days ( ) ;
format! (
" {} day{} from now " ,
num_days ,
if num_days = = 1 { " " } else { " s " }
)
} else if - duration . num_hours ( ) > = 1 {
let num_hours = - duration . num_hours ( ) ;
format! (
" {} hour{} from now " ,
num_hours ,
if num_hours = = 1 { " " } else { " s " }
)
} else if - duration . num_minutes ( ) > = 1 {
let num_minutes = - duration . num_minutes ( ) ;
format! (
" {} min{} from now " ,
num_minutes ,
if num_minutes = = 1 { " " } else { " s " }
)
} else {
let num_seconds = - duration . num_seconds ( ) ;
format! (
" {} sec{} from now " ,
num_seconds ,
if num_seconds = = 1 { " " } else { " s " }
)
}
} else if duration . num_weeks ( ) > = 52 {
2020-01-11 21:49:20 +01:00
let num_years = duration . num_weeks ( ) / 52 ;
format! (
" {} year{} ago " ,
num_years ,
if num_years = = 1 { " " } else { " s " }
)
} else if duration . num_weeks ( ) > = 4 {
let num_months = duration . num_weeks ( ) / 4 ;
format! (
" {} month{} ago " ,
num_months ,
if num_months = = 1 { " " } else { " s " }
)
} else if duration . num_weeks ( ) > = 1 {
let num_weeks = duration . num_weeks ( ) ;
format! (
" {} week{} ago " ,
num_weeks ,
if num_weeks = = 1 { " " } else { " s " }
)
} else if duration . num_days ( ) > = 1 {
let num_days = duration . num_days ( ) ;
format! (
" {} day{} ago " ,
num_days ,
if num_days = = 1 { " " } else { " s " }
)
} else if duration . num_hours ( ) > = 1 {
let num_hours = duration . num_hours ( ) ;
format! (
" {} hour{} ago " ,
num_hours ,
if num_hours = = 1 { " " } else { " s " }
)
} else if duration . num_minutes ( ) > = 1 {
let num_minutes = duration . num_minutes ( ) ;
format! (
" {} min{} ago " ,
num_minutes ,
if num_minutes = = 1 { " " } else { " s " }
)
} else {
let num_seconds = duration . num_seconds ( ) ;
format! (
" {} sec{} ago " ,
num_seconds ,
if num_seconds = = 1 { " " } else { " s " }
)
}
}