forked from extern/nushell
Merge pull request #571 from nushell/bigint
Migrated numerics to BigInt/BigDecimal
This commit is contained in:
commit
3d5e31c55d
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,4 +1,5 @@
|
|||||||
/target
|
/target
|
||||||
|
/scratch
|
||||||
**/*.rs.bk
|
**/*.rs.bk
|
||||||
history.txt
|
history.txt
|
||||||
tests/fixtures/nuplayground
|
tests/fixtures/nuplayground
|
52
Cargo.lock
generated
52
Cargo.lock
generated
@ -111,6 +111,17 @@ dependencies = [
|
|||||||
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bigdecimal"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"num-bigint 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bincode"
|
name = "bincode"
|
||||||
version = "1.1.4"
|
version = "1.1.4"
|
||||||
@ -1560,6 +1571,7 @@ dependencies = [
|
|||||||
"app_dirs 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"app_dirs 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"battery 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
"battery 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"bigdecimal 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"bson 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"bson 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"byte-unit 3.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"byte-unit 3.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
"bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
@ -1592,6 +1604,7 @@ dependencies = [
|
|||||||
"neso 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"neso 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"nom 5.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"nom 5.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"nom5_locate 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"nom5_locate 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"num-bigint 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"onig_sys 69.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"onig_sys 69.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"pin-utils 0.1.0-alpha.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
"pin-utils 0.1.0-alpha.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
@ -1604,7 +1617,6 @@ dependencies = [
|
|||||||
"regex 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"regex 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"roxmltree 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"roxmltree 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"rusqlite 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"rusqlite 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"rust_decimal 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"rustyline 5.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"rustyline 5.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
@ -1627,19 +1639,6 @@ dependencies = [
|
|||||||
"which 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"which 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "num"
|
|
||||||
version = "0.2.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
dependencies = [
|
|
||||||
"num-bigint 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"num-complex 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"num-iter 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"num-rational 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "num-bigint"
|
name = "num-bigint"
|
||||||
version = "0.2.2"
|
version = "0.2.2"
|
||||||
@ -1647,15 +1646,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)",
|
"num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
"serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "num-complex"
|
|
||||||
version = "0.2.3"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
dependencies = [
|
|
||||||
"autocfg 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -1683,7 +1674,6 @@ version = "0.2.2"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"autocfg 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
"autocfg 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"num-bigint 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)",
|
"num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
@ -2286,16 +2276,6 @@ name = "rust-ini"
|
|||||||
version = "0.13.0"
|
version = "0.13.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "rust_decimal"
|
|
||||||
version = "1.0.3"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
dependencies = [
|
|
||||||
"byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"num 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustc-demangle"
|
name = "rustc-demangle"
|
||||||
version = "0.1.15"
|
version = "0.1.15"
|
||||||
@ -3130,6 +3110,7 @@ dependencies = [
|
|||||||
"checksum backtrace-sys 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)" = "82a830b4ef2d1124a711c71d263c5abdc710ef8e907bd508c88be475cebc422b"
|
"checksum backtrace-sys 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)" = "82a830b4ef2d1124a711c71d263c5abdc710ef8e907bd508c88be475cebc422b"
|
||||||
"checksum base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0b25d992356d2eb0ed82172f5248873db5560c4721f564b13cb5193bda5e668e"
|
"checksum base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0b25d992356d2eb0ed82172f5248873db5560c4721f564b13cb5193bda5e668e"
|
||||||
"checksum battery 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6d6fe5630049e900227cd89afce4c1204b88ec8e61a2581bb96fcce26f047b"
|
"checksum battery 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6d6fe5630049e900227cd89afce4c1204b88ec8e61a2581bb96fcce26f047b"
|
||||||
|
"checksum bigdecimal 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "460825c9e21708024d67c07057cd5560e5acdccac85de0de624a81d3de51bacb"
|
||||||
"checksum bincode 1.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "9f04a5e50dc80b3d5d35320889053637d15011aed5e66b66b37ae798c65da6f7"
|
"checksum bincode 1.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "9f04a5e50dc80b3d5d35320889053637d15011aed5e66b66b37ae798c65da6f7"
|
||||||
"checksum bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3d155346769a6855b86399e9bc3814ab343cd3d62c7e985113d46a0ec3c281fd"
|
"checksum bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3d155346769a6855b86399e9bc3814ab343cd3d62c7e985113d46a0ec3c281fd"
|
||||||
"checksum blake2b_simd 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "461f4b879a8eb70c1debf7d0788a9a5ff15f1ea9d25925fea264ef4258bed6b2"
|
"checksum blake2b_simd 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "461f4b879a8eb70c1debf7d0788a9a5ff15f1ea9d25925fea264ef4258bed6b2"
|
||||||
@ -3285,9 +3266,7 @@ dependencies = [
|
|||||||
"checksum nom 5.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e9761d859320e381010a4f7f8ed425f2c924de33ad121ace447367c713ad561b"
|
"checksum nom 5.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e9761d859320e381010a4f7f8ed425f2c924de33ad121ace447367c713ad561b"
|
||||||
"checksum nom5_locate 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3d4312467f8b28d909344b934207e502212fa5a3adf1bff7428b0b86a666223d"
|
"checksum nom5_locate 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3d4312467f8b28d909344b934207e502212fa5a3adf1bff7428b0b86a666223d"
|
||||||
"checksum ntapi 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f26e041cd983acbc087e30fcba770380cfa352d0e392e175b2344ebaf7ea0602"
|
"checksum ntapi 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f26e041cd983acbc087e30fcba770380cfa352d0e392e175b2344ebaf7ea0602"
|
||||||
"checksum num 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cf4825417e1e1406b3782a8ce92f4d53f26ec055e3622e1881ca8e9f5f9e08db"
|
|
||||||
"checksum num-bigint 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "57450397855d951f1a41305e54851b1a7b8f5d2e349543a02a2effe25459f718"
|
"checksum num-bigint 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "57450397855d951f1a41305e54851b1a7b8f5d2e349543a02a2effe25459f718"
|
||||||
"checksum num-complex 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "fcb0cf31fb3ff77e6d2a6ebd6800df7fdcd106f2ad89113c9130bcd07f93dffc"
|
|
||||||
"checksum num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "b85e541ef8255f6cf42bbfe4ef361305c6c135d10919ecc26126c4e5ae94bc09"
|
"checksum num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "b85e541ef8255f6cf42bbfe4ef361305c6c135d10919ecc26126c4e5ae94bc09"
|
||||||
"checksum num-iter 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "76bd5272412d173d6bf9afdf98db8612bbabc9a7a830b7bfc9c188911716132e"
|
"checksum num-iter 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "76bd5272412d173d6bf9afdf98db8612bbabc9a7a830b7bfc9c188911716132e"
|
||||||
"checksum num-rational 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f2885278d5fe2adc2f75ced642d52d879bffaceb5a2e0b1d4309ffdfb239b454"
|
"checksum num-rational 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f2885278d5fe2adc2f75ced642d52d879bffaceb5a2e0b1d4309ffdfb239b454"
|
||||||
@ -3360,7 +3339,6 @@ dependencies = [
|
|||||||
"checksum rusqlite 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2a194373ef527035645a1bc21b10dc2125f73497e6e155771233eb187aedd051"
|
"checksum rusqlite 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2a194373ef527035645a1bc21b10dc2125f73497e6e155771233eb187aedd051"
|
||||||
"checksum rust-argon2 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "81ed8d04228b44a740c8d46ff872a28e50fff3d659f307ab4da2cc502e019ff3"
|
"checksum rust-argon2 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "81ed8d04228b44a740c8d46ff872a28e50fff3d659f307ab4da2cc502e019ff3"
|
||||||
"checksum rust-ini 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3e52c148ef37f8c375d49d5a73aa70713125b7f19095948a923f80afdeb22ec2"
|
"checksum rust-ini 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3e52c148ef37f8c375d49d5a73aa70713125b7f19095948a923f80afdeb22ec2"
|
||||||
"checksum rust_decimal 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f7a28ded8f10361cefb69a8d8e1d195acf59344150534c165c401d6611cf013d"
|
|
||||||
"checksum rustc-demangle 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "a7f4dccf6f4891ebcc0c39f9b6eb1a83b9bf5d747cb439ec6fba4f3b977038af"
|
"checksum rustc-demangle 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "a7f4dccf6f4891ebcc0c39f9b6eb1a83b9bf5d747cb439ec6fba4f3b977038af"
|
||||||
"checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda"
|
"checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda"
|
||||||
"checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
|
"checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
|
||||||
|
@ -34,7 +34,6 @@ term = "0.5.2"
|
|||||||
bytes = "0.4.12"
|
bytes = "0.4.12"
|
||||||
log = "0.4.8"
|
log = "0.4.8"
|
||||||
pretty_env_logger = "0.3.1"
|
pretty_env_logger = "0.3.1"
|
||||||
rust_decimal = "1.0.3"
|
|
||||||
serde = { version = "1.0.99", features = ["derive"] }
|
serde = { version = "1.0.99", features = ["derive"] }
|
||||||
bson = { version = "0.14.0", features = ["decimal128"] }
|
bson = { version = "0.14.0", features = ["decimal128"] }
|
||||||
serde_json = "1.0.40"
|
serde_json = "1.0.40"
|
||||||
@ -81,6 +80,8 @@ clipboard = {version = "0.5", optional = true }
|
|||||||
shellexpand = "1.0.0"
|
shellexpand = "1.0.0"
|
||||||
futures-timer = "0.3.0"
|
futures-timer = "0.3.0"
|
||||||
pin-utils = "0.1.0-alpha.4"
|
pin-utils = "0.1.0-alpha.4"
|
||||||
|
num-bigint = { version = "0.2.2", features = ["serde"] }
|
||||||
|
bigdecimal = { version = "0.1.0", features = ["serde"] }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
raw-key = ["rawkey", "neso"]
|
raw-key = ["rawkey", "neso"]
|
||||||
|
@ -5,6 +5,11 @@ use crate::prelude::*;
|
|||||||
|
|
||||||
pub struct First;
|
pub struct First;
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
pub struct FirstArgs {
|
||||||
|
amount: Tagged<u64>,
|
||||||
|
}
|
||||||
|
|
||||||
impl WholeStreamCommand for First {
|
impl WholeStreamCommand for First {
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
"first"
|
"first"
|
||||||
@ -24,27 +29,13 @@ impl WholeStreamCommand for First {
|
|||||||
args: CommandArgs,
|
args: CommandArgs,
|
||||||
registry: &CommandRegistry,
|
registry: &CommandRegistry,
|
||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
first(args, registry)
|
args.process(registry, first)?.run()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn first(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
fn first(
|
||||||
let args = args.evaluate_once(registry)?;
|
FirstArgs { amount }: FirstArgs,
|
||||||
|
context: RunnableContext,
|
||||||
let amount = args.expect_nth(0)?.as_i64();
|
) -> Result<OutputStream, ShellError> {
|
||||||
|
Ok(OutputStream::from_input(context.input.values.take(*amount)))
|
||||||
let amount = match amount {
|
|
||||||
Ok(o) => o,
|
|
||||||
Err(_) => {
|
|
||||||
return Err(ShellError::labeled_error(
|
|
||||||
"Value is not a number",
|
|
||||||
"expected integer",
|
|
||||||
args.expect_nth(0)?.span(),
|
|
||||||
))
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(OutputStream::from_input(
|
|
||||||
args.input.values.take(amount as u64),
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
use crate::commands::WholeStreamCommand;
|
use crate::commands::WholeStreamCommand;
|
||||||
|
use crate::errors::ExpectedRange;
|
||||||
use crate::object::{Primitive, TaggedDictBuilder, Value};
|
use crate::object::{Primitive, TaggedDictBuilder, Value};
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use bson::{decode_document, spec::BinarySubtype, Bson};
|
use bson::{decode_document, spec::BinarySubtype, Bson};
|
||||||
@ -28,22 +29,30 @@ impl WholeStreamCommand for FromBSON {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn convert_bson_value_to_nu_value(v: &Bson, tag: impl Into<Tag>) -> Tagged<Value> {
|
fn bson_array(input: &Vec<Bson>, tag: Tag) -> Result<Vec<Tagged<Value>>, ShellError> {
|
||||||
|
let mut out = vec![];
|
||||||
|
|
||||||
|
for value in input {
|
||||||
|
out.push(convert_bson_value_to_nu_value(value, tag)?);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(out)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn convert_bson_value_to_nu_value(
|
||||||
|
v: &Bson,
|
||||||
|
tag: impl Into<Tag>,
|
||||||
|
) -> Result<Tagged<Value>, ShellError> {
|
||||||
let tag = tag.into();
|
let tag = tag.into();
|
||||||
|
|
||||||
match v {
|
Ok(match v {
|
||||||
Bson::FloatingPoint(n) => Value::Primitive(Primitive::from(*n)).tagged(tag),
|
Bson::FloatingPoint(n) => Value::Primitive(Primitive::from(*n)).tagged(tag),
|
||||||
Bson::String(s) => Value::Primitive(Primitive::String(String::from(s))).tagged(tag),
|
Bson::String(s) => Value::Primitive(Primitive::String(String::from(s))).tagged(tag),
|
||||||
Bson::Array(a) => Value::List(
|
Bson::Array(a) => Value::List(bson_array(a, tag)?).tagged(tag),
|
||||||
a.iter()
|
|
||||||
.map(|x| convert_bson_value_to_nu_value(x, tag))
|
|
||||||
.collect(),
|
|
||||||
)
|
|
||||||
.tagged(tag),
|
|
||||||
Bson::Document(doc) => {
|
Bson::Document(doc) => {
|
||||||
let mut collected = TaggedDictBuilder::new(tag);
|
let mut collected = TaggedDictBuilder::new(tag);
|
||||||
for (k, v) in doc.iter() {
|
for (k, v) in doc.iter() {
|
||||||
collected.insert_tagged(k.clone(), convert_bson_value_to_nu_value(v, tag));
|
collected.insert_tagged(k.clone(), convert_bson_value_to_nu_value(v, tag)?);
|
||||||
}
|
}
|
||||||
|
|
||||||
collected.into_tagged_value()
|
collected.into_tagged_value()
|
||||||
@ -62,11 +71,18 @@ fn convert_bson_value_to_nu_value(v: &Bson, tag: impl Into<Tag>) -> Tagged<Value
|
|||||||
);
|
);
|
||||||
collected.into_tagged_value()
|
collected.into_tagged_value()
|
||||||
}
|
}
|
||||||
// TODO: Add Int32 to nushell?
|
Bson::I32(n) => Value::number(n).tagged(tag),
|
||||||
Bson::I32(n) => Value::Primitive(Primitive::Int(*n as i64)).tagged(tag),
|
Bson::I64(n) => Value::number(n).tagged(tag),
|
||||||
Bson::I64(n) => Value::Primitive(Primitive::Int(*n as i64)).tagged(tag),
|
|
||||||
Bson::Decimal128(n) => {
|
Bson::Decimal128(n) => {
|
||||||
let decimal = Decimal::from_str(&format!("{}", n)).unwrap();
|
// TODO: this really isn't great, and we should update this to do a higher
|
||||||
|
// fidelity translation
|
||||||
|
let decimal = BigDecimal::from_str(&format!("{}", n)).map_err(|_| {
|
||||||
|
ShellError::range_error(
|
||||||
|
ExpectedRange::BigDecimal,
|
||||||
|
&n.tagged(tag),
|
||||||
|
format!("converting BSON Decimal128 to BigDecimal"),
|
||||||
|
)
|
||||||
|
})?;
|
||||||
Value::Primitive(Primitive::Decimal(decimal)).tagged(tag)
|
Value::Primitive(Primitive::Decimal(decimal)).tagged(tag)
|
||||||
}
|
}
|
||||||
Bson::JavaScriptCode(js) => {
|
Bson::JavaScriptCode(js) => {
|
||||||
@ -85,16 +101,13 @@ fn convert_bson_value_to_nu_value(v: &Bson, tag: impl Into<Tag>) -> Tagged<Value
|
|||||||
);
|
);
|
||||||
collected.insert_tagged(
|
collected.insert_tagged(
|
||||||
"$scope".to_string(),
|
"$scope".to_string(),
|
||||||
convert_bson_value_to_nu_value(&Bson::Document(doc.to_owned()), tag),
|
convert_bson_value_to_nu_value(&Bson::Document(doc.to_owned()), tag)?,
|
||||||
);
|
);
|
||||||
collected.into_tagged_value()
|
collected.into_tagged_value()
|
||||||
}
|
}
|
||||||
Bson::TimeStamp(ts) => {
|
Bson::TimeStamp(ts) => {
|
||||||
let mut collected = TaggedDictBuilder::new(tag);
|
let mut collected = TaggedDictBuilder::new(tag);
|
||||||
collected.insert_tagged(
|
collected.insert_tagged("$timestamp".to_string(), Value::number(ts).tagged(tag));
|
||||||
"$timestamp".to_string(),
|
|
||||||
Value::Primitive(Primitive::Int(*ts as i64)).tagged(tag),
|
|
||||||
);
|
|
||||||
collected.into_tagged_value()
|
collected.into_tagged_value()
|
||||||
}
|
}
|
||||||
Bson::Binary(bst, bytes) => {
|
Bson::Binary(bst, bytes) => {
|
||||||
@ -102,7 +115,7 @@ fn convert_bson_value_to_nu_value(v: &Bson, tag: impl Into<Tag>) -> Tagged<Value
|
|||||||
collected.insert_tagged(
|
collected.insert_tagged(
|
||||||
"$binary_subtype".to_string(),
|
"$binary_subtype".to_string(),
|
||||||
match bst {
|
match bst {
|
||||||
BinarySubtype::UserDefined(u) => Value::Primitive(Primitive::Int(*u as i64)),
|
BinarySubtype::UserDefined(u) => Value::number(u),
|
||||||
_ => Value::Primitive(Primitive::String(binary_subtype_to_string(*bst))),
|
_ => Value::Primitive(Primitive::String(binary_subtype_to_string(*bst))),
|
||||||
}
|
}
|
||||||
.tagged(tag),
|
.tagged(tag),
|
||||||
@ -130,7 +143,7 @@ fn convert_bson_value_to_nu_value(v: &Bson, tag: impl Into<Tag>) -> Tagged<Value
|
|||||||
);
|
);
|
||||||
collected.into_tagged_value()
|
collected.into_tagged_value()
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn binary_subtype_to_string(bst: BinarySubtype) -> String {
|
fn binary_subtype_to_string(bst: BinarySubtype) -> String {
|
||||||
@ -179,7 +192,7 @@ pub fn from_bson_bytes_to_value(
|
|||||||
while let Ok(v) = decode_document(&mut b_reader) {
|
while let Ok(v) = decode_document(&mut b_reader) {
|
||||||
docs.push(Bson::Document(v));
|
docs.push(Bson::Document(v));
|
||||||
}
|
}
|
||||||
Ok(convert_bson_value_to_nu_value(&Bson::Array(docs), tag))
|
Ok(convert_bson_value_to_nu_value(&Bson::Array(docs), tag).expect("FIXME: Don't commit like this"))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn from_bson(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
fn from_bson(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
||||||
|
@ -37,10 +37,10 @@ fn convert_json_value_to_nu_value(v: &serde_hjson::Value, tag: impl Into<Tag>) -
|
|||||||
|
|
||||||
match v {
|
match v {
|
||||||
serde_hjson::Value::Null => Value::Primitive(Primitive::Nothing).tagged(tag),
|
serde_hjson::Value::Null => Value::Primitive(Primitive::Nothing).tagged(tag),
|
||||||
serde_hjson::Value::Bool(b) => Value::Primitive(Primitive::Boolean(*b)).tagged(tag),
|
serde_hjson::Value::Bool(b) => Value::boolean(*b).tagged(tag),
|
||||||
serde_hjson::Value::F64(n) => Value::Primitive(Primitive::from(*n)).tagged(tag),
|
serde_hjson::Value::F64(n) => Value::number(n).tagged(tag),
|
||||||
serde_hjson::Value::U64(n) => Value::Primitive(Primitive::Int(*n as i64)).tagged(tag),
|
serde_hjson::Value::U64(n) => Value::number(n).tagged(tag),
|
||||||
serde_hjson::Value::I64(n) => Value::Primitive(Primitive::Int(*n as i64)).tagged(tag),
|
serde_hjson::Value::I64(n) => Value::number(n).tagged(tag),
|
||||||
serde_hjson::Value::String(s) => {
|
serde_hjson::Value::String(s) => {
|
||||||
Value::Primitive(Primitive::String(String::from(s))).tagged(tag)
|
Value::Primitive(Primitive::String(String::from(s))).tagged(tag)
|
||||||
}
|
}
|
||||||
|
@ -100,7 +100,7 @@ fn convert_sqlite_row_to_nu_value(
|
|||||||
fn convert_sqlite_value_to_nu_value(value: ValueRef, tag: impl Into<Tag> + Clone) -> Tagged<Value> {
|
fn convert_sqlite_value_to_nu_value(value: ValueRef, tag: impl Into<Tag> + Clone) -> Tagged<Value> {
|
||||||
match value {
|
match value {
|
||||||
ValueRef::Null => Value::Primitive(Primitive::String(String::from(""))).tagged(tag),
|
ValueRef::Null => Value::Primitive(Primitive::String(String::from(""))).tagged(tag),
|
||||||
ValueRef::Integer(i) => Value::Primitive(Primitive::Int(i)).tagged(tag),
|
ValueRef::Integer(i) => Value::number(i).tagged(tag),
|
||||||
ValueRef::Real(f) => Value::number(f).tagged(tag),
|
ValueRef::Real(f) => Value::number(f).tagged(tag),
|
||||||
t @ ValueRef::Text(_) => {
|
t @ ValueRef::Text(_) => {
|
||||||
// this unwrap is safe because we know the ValueRef is Text.
|
// this unwrap is safe because we know the ValueRef is Text.
|
||||||
|
@ -30,9 +30,9 @@ pub fn convert_toml_value_to_nu_value(v: &toml::Value, tag: impl Into<Tag>) -> T
|
|||||||
let tag = tag.into();
|
let tag = tag.into();
|
||||||
|
|
||||||
match v {
|
match v {
|
||||||
toml::Value::Boolean(b) => Value::Primitive(Primitive::Boolean(*b)).tagged(tag),
|
toml::Value::Boolean(b) => Value::boolean(*b).tagged(tag),
|
||||||
toml::Value::Integer(n) => Value::Primitive(Primitive::Int(*n)).tagged(tag),
|
toml::Value::Integer(n) => Value::number(n).tagged(tag),
|
||||||
toml::Value::Float(n) => Value::Primitive(Primitive::from(*n)).tagged(tag),
|
toml::Value::Float(n) => Value::number(n).tagged(tag),
|
||||||
toml::Value::String(s) => Value::Primitive(Primitive::String(String::from(s))).tagged(tag),
|
toml::Value::String(s) => Value::Primitive(Primitive::String(String::from(s))).tagged(tag),
|
||||||
toml::Value::Array(a) => Value::List(
|
toml::Value::Array(a) => Value::List(
|
||||||
a.iter()
|
a.iter()
|
||||||
|
@ -54,9 +54,9 @@ fn convert_yaml_value_to_nu_value(v: &serde_yaml::Value, tag: impl Into<Tag>) ->
|
|||||||
let tag = tag.into();
|
let tag = tag.into();
|
||||||
|
|
||||||
match v {
|
match v {
|
||||||
serde_yaml::Value::Bool(b) => Value::Primitive(Primitive::Boolean(*b)).tagged(tag),
|
serde_yaml::Value::Bool(b) => Value::boolean(*b).tagged(tag),
|
||||||
serde_yaml::Value::Number(n) if n.is_i64() => {
|
serde_yaml::Value::Number(n) if n.is_i64() => {
|
||||||
Value::Primitive(Primitive::Int(n.as_i64().unwrap())).tagged(tag)
|
Value::number(n.as_i64().unwrap()).tagged(tag)
|
||||||
}
|
}
|
||||||
serde_yaml::Value::Number(n) if n.is_f64() => {
|
serde_yaml::Value::Number(n) if n.is_f64() => {
|
||||||
Value::Primitive(Primitive::from(n.as_f64().unwrap())).tagged(tag)
|
Value::Primitive(Primitive::from(n.as_f64().unwrap())).tagged(tag)
|
||||||
|
@ -5,6 +5,11 @@ use crate::prelude::*;
|
|||||||
|
|
||||||
pub struct Last;
|
pub struct Last;
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
pub struct LastArgs {
|
||||||
|
amount: Tagged<u64>,
|
||||||
|
}
|
||||||
|
|
||||||
impl WholeStreamCommand for Last {
|
impl WholeStreamCommand for Last {
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
"last"
|
"last"
|
||||||
@ -24,37 +29,18 @@ impl WholeStreamCommand for Last {
|
|||||||
args: CommandArgs,
|
args: CommandArgs,
|
||||||
registry: &CommandRegistry,
|
registry: &CommandRegistry,
|
||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
last(args, registry)
|
args.process(registry, last)?.run()
|
||||||
|
// last(args, registry)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn last(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
fn last(
|
||||||
let args = args.evaluate_once(registry)?;
|
LastArgs { amount }: LastArgs,
|
||||||
|
context: RunnableContext,
|
||||||
let amount = args.expect_nth(0)?.as_i64();
|
) -> Result<OutputStream, ShellError> {
|
||||||
|
|
||||||
let amount = match amount {
|
|
||||||
Ok(o) => o,
|
|
||||||
Err(_) => {
|
|
||||||
return Err(ShellError::labeled_error(
|
|
||||||
"Value is not a number",
|
|
||||||
"expected integer",
|
|
||||||
args.expect_nth(0)?.span(),
|
|
||||||
))
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if amount <= 0 {
|
|
||||||
return Err(ShellError::labeled_error(
|
|
||||||
"Value is too low",
|
|
||||||
"expected a positive integer",
|
|
||||||
args.expect_nth(0)?.span(),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
let stream = async_stream_block! {
|
let stream = async_stream_block! {
|
||||||
let v: Vec<_> = args.input.into_vec().await;
|
let v: Vec<_> = context.input.into_vec().await;
|
||||||
let k = v.len() - (amount as usize);
|
let k = v.len() - (*amount as usize);
|
||||||
for x in v[k..].iter() {
|
for x in v[k..].iter() {
|
||||||
let y: Tagged<Value> = x.clone();
|
let y: Tagged<Value> = x.clone();
|
||||||
yield ReturnSuccess::value(y)
|
yield ReturnSuccess::value(y)
|
||||||
|
@ -28,12 +28,12 @@ impl WholeStreamCommand for ToBSON {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn value_to_bson_value(v: &Value) -> Bson {
|
pub fn value_to_bson_value(v: &Tagged<Value>) -> Result<Bson, ShellError> {
|
||||||
match v {
|
Ok(match &v.item {
|
||||||
Value::Primitive(Primitive::Boolean(b)) => Bson::Boolean(*b),
|
Value::Primitive(Primitive::Boolean(b)) => Bson::Boolean(*b),
|
||||||
// FIXME: What about really big decimals?
|
// FIXME: What about really big decimals?
|
||||||
Value::Primitive(Primitive::Bytes(decimal)) => Bson::FloatingPoint(
|
Value::Primitive(Primitive::Bytes(decimal)) => Bson::FloatingPoint(
|
||||||
(*decimal)
|
(decimal)
|
||||||
.to_f64()
|
.to_f64()
|
||||||
.expect("Unimplemented BUG: What about big decimals?"),
|
.expect("Unimplemented BUG: What about big decimals?"),
|
||||||
),
|
),
|
||||||
@ -41,20 +41,26 @@ pub fn value_to_bson_value(v: &Value) -> Bson {
|
|||||||
Value::Primitive(Primitive::EndOfStream) => Bson::Null,
|
Value::Primitive(Primitive::EndOfStream) => Bson::Null,
|
||||||
Value::Primitive(Primitive::BeginningOfStream) => Bson::Null,
|
Value::Primitive(Primitive::BeginningOfStream) => Bson::Null,
|
||||||
Value::Primitive(Primitive::Decimal(d)) => Bson::FloatingPoint(d.to_f64().unwrap()),
|
Value::Primitive(Primitive::Decimal(d)) => Bson::FloatingPoint(d.to_f64().unwrap()),
|
||||||
Value::Primitive(Primitive::Int(i)) => Bson::I64(*i),
|
Value::Primitive(Primitive::Int(i)) => {
|
||||||
|
Bson::I64(i.tagged(v.tag).coerce_into("converting to BSON")?)
|
||||||
|
}
|
||||||
Value::Primitive(Primitive::Nothing) => Bson::Null,
|
Value::Primitive(Primitive::Nothing) => Bson::Null,
|
||||||
Value::Primitive(Primitive::String(s)) => Bson::String(s.clone()),
|
Value::Primitive(Primitive::String(s)) => Bson::String(s.clone()),
|
||||||
Value::Primitive(Primitive::Path(s)) => Bson::String(s.display().to_string()),
|
Value::Primitive(Primitive::Path(s)) => Bson::String(s.display().to_string()),
|
||||||
Value::List(l) => Bson::Array(l.iter().map(|x| value_to_bson_value(x)).collect()),
|
Value::List(l) => Bson::Array(
|
||||||
|
l.iter()
|
||||||
|
.map(|x| value_to_bson_value(x))
|
||||||
|
.collect::<Result<_, _>>()?,
|
||||||
|
),
|
||||||
Value::Block(_) => Bson::Null,
|
Value::Block(_) => Bson::Null,
|
||||||
Value::Binary(b) => Bson::Binary(BinarySubtype::Generic, b.clone()),
|
Value::Binary(b) => Bson::Binary(BinarySubtype::Generic, b.clone()),
|
||||||
Value::Object(o) => object_value_to_bson(o),
|
Value::Object(o) => object_value_to_bson(o)?,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// object_value_to_bson handles all Objects, even those that correspond to special
|
// object_value_to_bson handles all Objects, even those that correspond to special
|
||||||
// types (things like regex or javascript code).
|
// types (things like regex or javascript code).
|
||||||
fn object_value_to_bson(o: &Dictionary) -> Bson {
|
fn object_value_to_bson(o: &Dictionary) -> Result<Bson, ShellError> {
|
||||||
let mut it = o.entries.iter();
|
let mut it = o.entries.iter();
|
||||||
if it.len() > 2 {
|
if it.len() > 2 {
|
||||||
return generic_object_value_to_bson(o);
|
return generic_object_value_to_bson(o);
|
||||||
@ -67,7 +73,7 @@ fn object_value_to_bson(o: &Dictionary) -> Bson {
|
|||||||
if r.is_err() || opts.is_err() {
|
if r.is_err() || opts.is_err() {
|
||||||
generic_object_value_to_bson(o)
|
generic_object_value_to_bson(o)
|
||||||
} else {
|
} else {
|
||||||
Bson::RegExp(r.unwrap(), opts.unwrap())
|
Ok(Bson::RegExp(r.unwrap(), opts.unwrap()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => generic_object_value_to_bson(o),
|
_ => generic_object_value_to_bson(o),
|
||||||
@ -80,8 +86,8 @@ fn object_value_to_bson(o: &Dictionary) -> Bson {
|
|||||||
if js.is_err() || s.is_err() {
|
if js.is_err() || s.is_err() {
|
||||||
generic_object_value_to_bson(o)
|
generic_object_value_to_bson(o)
|
||||||
} else {
|
} else {
|
||||||
if let Bson::Document(doc) = object_value_to_bson(s.unwrap()) {
|
if let Bson::Document(doc) = object_value_to_bson(s.unwrap())? {
|
||||||
Bson::JavaScriptCodeWithScope(js.unwrap(), doc)
|
Ok(Bson::JavaScriptCodeWithScope(js.unwrap(), doc))
|
||||||
} else {
|
} else {
|
||||||
generic_object_value_to_bson(o)
|
generic_object_value_to_bson(o)
|
||||||
}
|
}
|
||||||
@ -89,10 +95,10 @@ fn object_value_to_bson(o: &Dictionary) -> Bson {
|
|||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
let js: Result<String, _> = tagged_javascript_value.try_into();
|
let js: Result<String, _> = tagged_javascript_value.try_into();
|
||||||
if js.is_err() {
|
|
||||||
generic_object_value_to_bson(o)
|
match js {
|
||||||
} else {
|
Err(_) => generic_object_value_to_bson(o),
|
||||||
Bson::JavaScriptCode(js.unwrap())
|
Ok(v) => Ok(Bson::JavaScriptCode(v)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => generic_object_value_to_bson(o),
|
_ => generic_object_value_to_bson(o),
|
||||||
@ -103,7 +109,7 @@ fn object_value_to_bson(o: &Dictionary) -> Bson {
|
|||||||
if ts.is_err() {
|
if ts.is_err() {
|
||||||
generic_object_value_to_bson(o)
|
generic_object_value_to_bson(o)
|
||||||
} else {
|
} else {
|
||||||
Bson::TimeStamp(ts.unwrap())
|
Ok(Bson::TimeStamp(ts.unwrap()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Some((binary_subtype, tagged_binary_subtype_value))
|
Some((binary_subtype, tagged_binary_subtype_value))
|
||||||
@ -113,10 +119,10 @@ fn object_value_to_bson(o: &Dictionary) -> Bson {
|
|||||||
Some((binary, tagged_bin_value)) if binary == "$binary" => {
|
Some((binary, tagged_bin_value)) if binary == "$binary" => {
|
||||||
let bst = get_binary_subtype(tagged_binary_subtype_value);
|
let bst = get_binary_subtype(tagged_binary_subtype_value);
|
||||||
let bin: Result<Vec<u8>, _> = tagged_bin_value.try_into();
|
let bin: Result<Vec<u8>, _> = tagged_bin_value.try_into();
|
||||||
if bst.is_none() || bin.is_err() {
|
|
||||||
generic_object_value_to_bson(o)
|
match bst {
|
||||||
} else {
|
Err(_) => generic_object_value_to_bson(o),
|
||||||
Bson::Binary(bst.unwrap(), bin.unwrap())
|
Ok(v) => Ok(Bson::Binary(v, bin.unwrap())),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => generic_object_value_to_bson(o),
|
_ => generic_object_value_to_bson(o),
|
||||||
@ -131,7 +137,7 @@ fn object_value_to_bson(o: &Dictionary) -> Bson {
|
|||||||
if obj_id.is_err() {
|
if obj_id.is_err() {
|
||||||
generic_object_value_to_bson(o)
|
generic_object_value_to_bson(o)
|
||||||
} else {
|
} else {
|
||||||
Bson::ObjectId(obj_id.unwrap())
|
Ok(Bson::ObjectId(obj_id.unwrap()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -140,16 +146,16 @@ fn object_value_to_bson(o: &Dictionary) -> Bson {
|
|||||||
if sym.is_err() {
|
if sym.is_err() {
|
||||||
generic_object_value_to_bson(o)
|
generic_object_value_to_bson(o)
|
||||||
} else {
|
} else {
|
||||||
Bson::Symbol(sym.unwrap())
|
Ok(Bson::Symbol(sym.unwrap()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => generic_object_value_to_bson(o),
|
_ => generic_object_value_to_bson(o),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_binary_subtype<'a>(tagged_value: &'a Tagged<Value>) -> Option<BinarySubtype> {
|
fn get_binary_subtype<'a>(tagged_value: &'a Tagged<Value>) -> Result<BinarySubtype, ShellError> {
|
||||||
match tagged_value.item() {
|
match tagged_value.item() {
|
||||||
Value::Primitive(Primitive::String(s)) => Some(match s.as_ref() {
|
Value::Primitive(Primitive::String(s)) => Ok(match s.as_ref() {
|
||||||
"generic" => BinarySubtype::Generic,
|
"generic" => BinarySubtype::Generic,
|
||||||
"function" => BinarySubtype::Function,
|
"function" => BinarySubtype::Function,
|
||||||
"binary_old" => BinarySubtype::BinaryOld,
|
"binary_old" => BinarySubtype::BinaryOld,
|
||||||
@ -158,19 +164,25 @@ fn get_binary_subtype<'a>(tagged_value: &'a Tagged<Value>) -> Option<BinarySubty
|
|||||||
"md5" => BinarySubtype::Md5,
|
"md5" => BinarySubtype::Md5,
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}),
|
}),
|
||||||
Value::Primitive(Primitive::Int(i)) => Some(BinarySubtype::UserDefined(*i as u8)),
|
Value::Primitive(Primitive::Int(i)) => Ok(BinarySubtype::UserDefined(
|
||||||
_ => None,
|
i.tagged(tagged_value.tag)
|
||||||
|
.coerce_into("converting to BSON binary subtype")?,
|
||||||
|
)),
|
||||||
|
_ => Err(ShellError::type_error(
|
||||||
|
"bson binary",
|
||||||
|
tagged_value.tagged_type_name(),
|
||||||
|
)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// generic_object_value_bson handles any Object that does not
|
// generic_object_value_bson handles any Object that does not
|
||||||
// correspond to a special bson type (things like regex or javascript code).
|
// correspond to a special bson type (things like regex or javascript code).
|
||||||
fn generic_object_value_to_bson(o: &Dictionary) -> Bson {
|
fn generic_object_value_to_bson(o: &Dictionary) -> Result<Bson, ShellError> {
|
||||||
let mut doc = Document::new();
|
let mut doc = Document::new();
|
||||||
for (k, v) in o.entries.iter() {
|
for (k, v) in o.entries.iter() {
|
||||||
doc.insert(k.clone(), value_to_bson_value(v));
|
doc.insert(k.clone(), value_to_bson_value(v)?);
|
||||||
}
|
}
|
||||||
Bson::Document(doc)
|
Ok(Bson::Document(doc))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn shell_encode_document(
|
fn shell_encode_document(
|
||||||
@ -225,7 +237,7 @@ fn to_bson(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream
|
|||||||
Ok(out
|
Ok(out
|
||||||
.values
|
.values
|
||||||
.map(
|
.map(
|
||||||
move |a| match bson_value_to_bytes(value_to_bson_value(&a), name_span) {
|
move |a| match bson_value_to_bytes(value_to_bson_value(&a)?, name_span) {
|
||||||
Ok(x) => ReturnSuccess::value(Value::Binary(x).simple_spanned(name_span)),
|
Ok(x) => ReturnSuccess::value(Value::Binary(x).simple_spanned(name_span)),
|
||||||
_ => Err(ShellError::labeled_error_with_secondary(
|
_ => Err(ShellError::labeled_error_with_secondary(
|
||||||
"Expected an object with BSON-compatible structure from pipeline",
|
"Expected an object with BSON-compatible structure from pipeline",
|
||||||
|
@ -26,8 +26,8 @@ impl WholeStreamCommand for ToJSON {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn value_to_json_value(v: &Value) -> serde_json::Value {
|
pub fn value_to_json_value(v: &Tagged<Value>) -> Result<serde_json::Value, ShellError> {
|
||||||
match v {
|
Ok(match v.item() {
|
||||||
Value::Primitive(Primitive::Boolean(b)) => serde_json::Value::Bool(*b),
|
Value::Primitive(Primitive::Boolean(b)) => serde_json::Value::Bool(*b),
|
||||||
Value::Primitive(Primitive::Bytes(b)) => serde_json::Value::Number(
|
Value::Primitive(Primitive::Bytes(b)) => serde_json::Value::Number(
|
||||||
serde_json::Number::from(b.to_u64().expect("What about really big numbers")),
|
serde_json::Number::from(b.to_u64().expect("What about really big numbers")),
|
||||||
@ -41,16 +41,14 @@ pub fn value_to_json_value(v: &Value) -> serde_json::Value {
|
|||||||
)
|
)
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
),
|
),
|
||||||
Value::Primitive(Primitive::Int(i)) => {
|
Value::Primitive(Primitive::Int(i)) => serde_json::Value::Number(serde_json::Number::from(
|
||||||
serde_json::Value::Number(serde_json::Number::from(*i))
|
CoerceInto::<i64>::coerce_into(i.tagged(v.tag), "converting to JSON number")?,
|
||||||
}
|
)),
|
||||||
Value::Primitive(Primitive::Nothing) => serde_json::Value::Null,
|
Value::Primitive(Primitive::Nothing) => serde_json::Value::Null,
|
||||||
Value::Primitive(Primitive::String(s)) => serde_json::Value::String(s.clone()),
|
Value::Primitive(Primitive::String(s)) => serde_json::Value::String(s.clone()),
|
||||||
Value::Primitive(Primitive::Path(s)) => serde_json::Value::String(s.display().to_string()),
|
Value::Primitive(Primitive::Path(s)) => serde_json::Value::String(s.display().to_string()),
|
||||||
|
|
||||||
Value::List(l) => {
|
Value::List(l) => serde_json::Value::Array(json_list(l)?),
|
||||||
serde_json::Value::Array(l.iter().map(|x| value_to_json_value(x)).collect())
|
|
||||||
}
|
|
||||||
Value::Block(_) => serde_json::Value::Null,
|
Value::Block(_) => serde_json::Value::Null,
|
||||||
Value::Binary(b) => serde_json::Value::Array(
|
Value::Binary(b) => serde_json::Value::Array(
|
||||||
b.iter()
|
b.iter()
|
||||||
@ -62,11 +60,21 @@ pub fn value_to_json_value(v: &Value) -> serde_json::Value {
|
|||||||
Value::Object(o) => {
|
Value::Object(o) => {
|
||||||
let mut m = serde_json::Map::new();
|
let mut m = serde_json::Map::new();
|
||||||
for (k, v) in o.entries.iter() {
|
for (k, v) in o.entries.iter() {
|
||||||
m.insert(k.clone(), value_to_json_value(v));
|
m.insert(k.clone(), value_to_json_value(v)?);
|
||||||
}
|
}
|
||||||
serde_json::Value::Object(m)
|
serde_json::Value::Object(m)
|
||||||
}
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn json_list(input: &Vec<Tagged<Value>>) -> Result<Vec<serde_json::Value>, ShellError> {
|
||||||
|
let mut out = vec![];
|
||||||
|
|
||||||
|
for value in input {
|
||||||
|
out.push(value_to_json_value(value)?);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Ok(out)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_json(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
fn to_json(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
||||||
@ -77,7 +85,7 @@ fn to_json(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream
|
|||||||
Ok(out
|
Ok(out
|
||||||
.values
|
.values
|
||||||
.map(
|
.map(
|
||||||
move |a| match serde_json::to_string(&value_to_json_value(&a)) {
|
move |a| match serde_json::to_string(&value_to_json_value(&a)?) {
|
||||||
Ok(x) => ReturnSuccess::value(
|
Ok(x) => ReturnSuccess::value(
|
||||||
Value::Primitive(Primitive::String(x)).simple_spanned(name_span),
|
Value::Primitive(Primitive::String(x)).simple_spanned(name_span),
|
||||||
),
|
),
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
use crate::commands::WholeStreamCommand;
|
use crate::commands::WholeStreamCommand;
|
||||||
use crate::errors::ranged;
|
|
||||||
use crate::object::{Primitive, Value};
|
use crate::object::{Primitive, Value};
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
|
||||||
@ -27,12 +26,10 @@ impl WholeStreamCommand for ToTOML {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn value_to_toml_value(v: &Value) -> Result<toml::Value, ShellError> {
|
pub fn value_to_toml_value(v: &Tagged<Value>) -> Result<toml::Value, ShellError> {
|
||||||
Ok(match v {
|
Ok(match v.item() {
|
||||||
Value::Primitive(Primitive::Boolean(b)) => toml::Value::Boolean(*b),
|
Value::Primitive(Primitive::Boolean(b)) => toml::Value::Boolean(*b),
|
||||||
Value::Primitive(Primitive::Bytes(b)) => {
|
Value::Primitive(Primitive::Bytes(b)) => toml::Value::Integer(*b as i64),
|
||||||
toml::Value::Integer(ranged(b.to_i64(), "i64", b.tagged_unknown())?)
|
|
||||||
}
|
|
||||||
Value::Primitive(Primitive::Date(d)) => toml::Value::String(d.to_string()),
|
Value::Primitive(Primitive::Date(d)) => toml::Value::String(d.to_string()),
|
||||||
Value::Primitive(Primitive::EndOfStream) => {
|
Value::Primitive(Primitive::EndOfStream) => {
|
||||||
toml::Value::String("<End of Stream>".to_string())
|
toml::Value::String("<End of Stream>".to_string())
|
||||||
@ -41,9 +38,11 @@ pub fn value_to_toml_value(v: &Value) -> Result<toml::Value, ShellError> {
|
|||||||
toml::Value::String("<Beginning of Stream>".to_string())
|
toml::Value::String("<Beginning of Stream>".to_string())
|
||||||
}
|
}
|
||||||
Value::Primitive(Primitive::Decimal(f)) => {
|
Value::Primitive(Primitive::Decimal(f)) => {
|
||||||
toml::Value::Float(ranged(f.to_f64(), "f64", f.tagged_unknown())?)
|
toml::Value::Float(f.tagged(v.tag).coerce_into("converting to TOML float")?)
|
||||||
|
}
|
||||||
|
Value::Primitive(Primitive::Int(i)) => {
|
||||||
|
toml::Value::Integer(i.tagged(v.tag).coerce_into("converting to TOML integer")?)
|
||||||
}
|
}
|
||||||
Value::Primitive(Primitive::Int(i)) => toml::Value::Integer(*i),
|
|
||||||
Value::Primitive(Primitive::Nothing) => toml::Value::String("<Nothing>".to_string()),
|
Value::Primitive(Primitive::Nothing) => toml::Value::String("<Nothing>".to_string()),
|
||||||
Value::Primitive(Primitive::String(s)) => toml::Value::String(s.clone()),
|
Value::Primitive(Primitive::String(s)) => toml::Value::String(s.clone()),
|
||||||
Value::Primitive(Primitive::Path(s)) => toml::Value::String(s.display().to_string()),
|
Value::Primitive(Primitive::Path(s)) => toml::Value::String(s.display().to_string()),
|
||||||
|
@ -26,8 +26,8 @@ impl WholeStreamCommand for ToYAML {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn value_to_yaml_value(v: &Value) -> serde_yaml::Value {
|
pub fn value_to_yaml_value(v: &Tagged<Value>) -> Result<serde_yaml::Value, ShellError> {
|
||||||
match v {
|
Ok(match v.item() {
|
||||||
Value::Primitive(Primitive::Boolean(b)) => serde_yaml::Value::Bool(*b),
|
Value::Primitive(Primitive::Boolean(b)) => serde_yaml::Value::Bool(*b),
|
||||||
Value::Primitive(Primitive::Bytes(b)) => {
|
Value::Primitive(Primitive::Bytes(b)) => {
|
||||||
serde_yaml::Value::Number(serde_yaml::Number::from(b.to_f64().unwrap()))
|
serde_yaml::Value::Number(serde_yaml::Number::from(b.to_f64().unwrap()))
|
||||||
@ -38,15 +38,21 @@ pub fn value_to_yaml_value(v: &Value) -> serde_yaml::Value {
|
|||||||
Value::Primitive(Primitive::Decimal(f)) => {
|
Value::Primitive(Primitive::Decimal(f)) => {
|
||||||
serde_yaml::Value::Number(serde_yaml::Number::from(f.to_f64().unwrap()))
|
serde_yaml::Value::Number(serde_yaml::Number::from(f.to_f64().unwrap()))
|
||||||
}
|
}
|
||||||
Value::Primitive(Primitive::Int(i)) => {
|
Value::Primitive(Primitive::Int(i)) => serde_yaml::Value::Number(serde_yaml::Number::from(
|
||||||
serde_yaml::Value::Number(serde_yaml::Number::from(*i))
|
CoerceInto::<i64>::coerce_into(i.tagged(v.tag), "converting to YAML number")?,
|
||||||
}
|
)),
|
||||||
Value::Primitive(Primitive::Nothing) => serde_yaml::Value::Null,
|
Value::Primitive(Primitive::Nothing) => serde_yaml::Value::Null,
|
||||||
Value::Primitive(Primitive::String(s)) => serde_yaml::Value::String(s.clone()),
|
Value::Primitive(Primitive::String(s)) => serde_yaml::Value::String(s.clone()),
|
||||||
Value::Primitive(Primitive::Path(s)) => serde_yaml::Value::String(s.display().to_string()),
|
Value::Primitive(Primitive::Path(s)) => serde_yaml::Value::String(s.display().to_string()),
|
||||||
|
|
||||||
Value::List(l) => {
|
Value::List(l) => {
|
||||||
serde_yaml::Value::Sequence(l.iter().map(|x| value_to_yaml_value(x)).collect())
|
let mut out = vec![];
|
||||||
|
|
||||||
|
for value in l {
|
||||||
|
out.push(value_to_yaml_value(value)?);
|
||||||
|
}
|
||||||
|
|
||||||
|
serde_yaml::Value::Sequence(out)
|
||||||
}
|
}
|
||||||
Value::Block(_) => serde_yaml::Value::Null,
|
Value::Block(_) => serde_yaml::Value::Null,
|
||||||
Value::Binary(b) => serde_yaml::Value::Sequence(
|
Value::Binary(b) => serde_yaml::Value::Sequence(
|
||||||
@ -57,11 +63,14 @@ pub fn value_to_yaml_value(v: &Value) -> serde_yaml::Value {
|
|||||||
Value::Object(o) => {
|
Value::Object(o) => {
|
||||||
let mut m = serde_yaml::Mapping::new();
|
let mut m = serde_yaml::Mapping::new();
|
||||||
for (k, v) in o.entries.iter() {
|
for (k, v) in o.entries.iter() {
|
||||||
m.insert(serde_yaml::Value::String(k.clone()), value_to_yaml_value(v));
|
m.insert(
|
||||||
|
serde_yaml::Value::String(k.clone()),
|
||||||
|
value_to_yaml_value(v)?,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
serde_yaml::Value::Mapping(m)
|
serde_yaml::Value::Mapping(m)
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_yaml(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
fn to_yaml(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
||||||
@ -71,7 +80,7 @@ fn to_yaml(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream
|
|||||||
Ok(out
|
Ok(out
|
||||||
.values
|
.values
|
||||||
.map(
|
.map(
|
||||||
move |a| match serde_yaml::to_string(&value_to_yaml_value(&a)) {
|
move |a| match serde_yaml::to_string(&value_to_yaml_value(&a)?) {
|
||||||
Ok(x) => ReturnSuccess::value(
|
Ok(x) => ReturnSuccess::value(
|
||||||
Value::Primitive(Primitive::String(x)).simple_spanned(name_span),
|
Value::Primitive(Primitive::String(x)).simple_spanned(name_span),
|
||||||
),
|
),
|
||||||
|
156
src/errors.rs
156
src/errors.rs
@ -75,12 +75,14 @@ impl ShellError {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn range_error(
|
pub(crate) fn range_error(
|
||||||
expected: impl Into<String>,
|
expected: impl Into<ExpectedRange>,
|
||||||
actual: Tagged<impl fmt::Debug>,
|
actual: &Tagged<impl fmt::Debug>,
|
||||||
|
operation: String,
|
||||||
) -> ShellError {
|
) -> ShellError {
|
||||||
ProximateShellError::RangeError {
|
ProximateShellError::RangeError {
|
||||||
kind: expected.into(),
|
kind: expected.into(),
|
||||||
actual_kind: actual.map(|a| format!("{:?}", a)),
|
actual_kind: actual.copy_span(format!("{:?}", actual.item)),
|
||||||
|
operation,
|
||||||
}
|
}
|
||||||
.start()
|
.start()
|
||||||
}
|
}
|
||||||
@ -245,6 +247,7 @@ impl ShellError {
|
|||||||
|
|
||||||
ProximateShellError::RangeError {
|
ProximateShellError::RangeError {
|
||||||
kind,
|
kind,
|
||||||
|
operation,
|
||||||
actual_kind:
|
actual_kind:
|
||||||
Tagged {
|
Tagged {
|
||||||
item,
|
item,
|
||||||
@ -252,8 +255,10 @@ impl ShellError {
|
|||||||
},
|
},
|
||||||
} => Diagnostic::new(Severity::Error, "Range Error").with_label(
|
} => Diagnostic::new(Severity::Error, "Range Error").with_label(
|
||||||
Label::new_primary(span).with_message(format!(
|
Label::new_primary(span).with_message(format!(
|
||||||
"Expected to covert {} to {}, but it was out of range",
|
"Expected to convert {} to {} while {}, but it was out of range",
|
||||||
item, kind
|
item,
|
||||||
|
kind.desc(),
|
||||||
|
operation
|
||||||
)),
|
)),
|
||||||
),
|
),
|
||||||
|
|
||||||
@ -333,6 +338,45 @@ impl ShellError {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Eq, PartialEq, Clone, Ord, PartialOrd, Serialize, Deserialize)]
|
||||||
|
pub enum ExpectedRange {
|
||||||
|
I8,
|
||||||
|
I16,
|
||||||
|
I32,
|
||||||
|
I64,
|
||||||
|
I128,
|
||||||
|
U8,
|
||||||
|
U16,
|
||||||
|
U32,
|
||||||
|
U64,
|
||||||
|
U128,
|
||||||
|
F32,
|
||||||
|
F64,
|
||||||
|
BigInt,
|
||||||
|
BigDecimal,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ExpectedRange {
|
||||||
|
fn desc(&self) -> &'static str {
|
||||||
|
match self {
|
||||||
|
ExpectedRange::I8 => "an 8-bit signed integer",
|
||||||
|
ExpectedRange::I16 => "a 16-bit signed integer",
|
||||||
|
ExpectedRange::I32 => "a 32-bit signed integer",
|
||||||
|
ExpectedRange::I64 => "a 64-bit signed integer",
|
||||||
|
ExpectedRange::I128 => "a 128-bit signed integer",
|
||||||
|
ExpectedRange::U8 => "an 8-bit unsigned integer",
|
||||||
|
ExpectedRange::U16 => "a 16-bit unsigned integer",
|
||||||
|
ExpectedRange::U32 => "a 32-bit unsigned integer",
|
||||||
|
ExpectedRange::U64 => "a 64-bit unsigned integer",
|
||||||
|
ExpectedRange::U128 => "a 128-bit unsigned integer",
|
||||||
|
ExpectedRange::F32 => "a 32-bit float",
|
||||||
|
ExpectedRange::F64 => "a 64-bit float",
|
||||||
|
ExpectedRange::BigDecimal => "a decimal",
|
||||||
|
ExpectedRange::BigInt => "an integer",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Eq, PartialEq, Clone, Ord, PartialOrd, Serialize, Deserialize)]
|
#[derive(Debug, Eq, PartialEq, Clone, Ord, PartialOrd, Serialize, Deserialize)]
|
||||||
pub enum ProximateShellError {
|
pub enum ProximateShellError {
|
||||||
String(StringError),
|
String(StringError),
|
||||||
@ -360,8 +404,9 @@ pub enum ProximateShellError {
|
|||||||
span: Span,
|
span: Span,
|
||||||
},
|
},
|
||||||
RangeError {
|
RangeError {
|
||||||
kind: String,
|
kind: ExpectedRange,
|
||||||
actual_kind: Tagged<String>,
|
actual_kind: Tagged<String>,
|
||||||
|
operation: String,
|
||||||
},
|
},
|
||||||
Diagnostic(ShellDiagnostic),
|
Diagnostic(ShellDiagnostic),
|
||||||
CoerceError {
|
CoerceError {
|
||||||
@ -547,13 +592,94 @@ impl<T> ShellErrorUtils<Tagged<T>> for Option<Tagged<T>> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn ranged<T>(
|
pub trait CoerceInto<U> {
|
||||||
input: Option<T>,
|
fn coerce_into(self, operation: impl Into<String>) -> Result<U, ShellError>;
|
||||||
expected: impl Into<String>,
|
|
||||||
actual: Tagged<impl fmt::Debug>,
|
|
||||||
) -> Result<T, ShellError> {
|
|
||||||
match input {
|
|
||||||
Some(v) => Ok(v),
|
|
||||||
None => Err(ShellError::range_error(expected, actual)),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
trait ToExpectedRange {
|
||||||
|
fn to_expected_range() -> ExpectedRange;
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! ranged_int {
|
||||||
|
($ty:tt -> $op:tt -> $variant:tt) => {
|
||||||
|
impl ToExpectedRange for $ty {
|
||||||
|
fn to_expected_range() -> ExpectedRange {
|
||||||
|
ExpectedRange::$variant
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CoerceInto<$ty> for Tagged<BigInt> {
|
||||||
|
fn coerce_into(self, operation: impl Into<String>) -> Result<$ty, ShellError> {
|
||||||
|
match self.$op() {
|
||||||
|
Some(v) => Ok(v),
|
||||||
|
None => Err(ShellError::range_error(
|
||||||
|
$ty::to_expected_range(),
|
||||||
|
&self,
|
||||||
|
operation.into(),
|
||||||
|
)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CoerceInto<$ty> for Tagged<&BigInt> {
|
||||||
|
fn coerce_into(self, operation: impl Into<String>) -> Result<$ty, ShellError> {
|
||||||
|
match self.$op() {
|
||||||
|
Some(v) => Ok(v),
|
||||||
|
None => Err(ShellError::range_error(
|
||||||
|
$ty::to_expected_range(),
|
||||||
|
&self,
|
||||||
|
operation.into(),
|
||||||
|
)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
ranged_int!(u8 -> to_u8 -> U8);
|
||||||
|
ranged_int!(u16 -> to_u16 -> U16);
|
||||||
|
ranged_int!(u32 -> to_u32 -> U32);
|
||||||
|
ranged_int!(u64 -> to_u64 -> U64);
|
||||||
|
ranged_int!(i8 -> to_i8 -> I8);
|
||||||
|
ranged_int!(i16 -> to_i16 -> I16);
|
||||||
|
ranged_int!(i32 -> to_i32 -> I32);
|
||||||
|
ranged_int!(i64 -> to_i64 -> I64);
|
||||||
|
|
||||||
|
macro_rules! ranged_decimal {
|
||||||
|
($ty:tt -> $op:tt -> $variant:tt) => {
|
||||||
|
impl ToExpectedRange for $ty {
|
||||||
|
fn to_expected_range() -> ExpectedRange {
|
||||||
|
ExpectedRange::$variant
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CoerceInto<$ty> for Tagged<BigDecimal> {
|
||||||
|
fn coerce_into(self, operation: impl Into<String>) -> Result<$ty, ShellError> {
|
||||||
|
match self.$op() {
|
||||||
|
Some(v) => Ok(v),
|
||||||
|
None => Err(ShellError::range_error(
|
||||||
|
$ty::to_expected_range(),
|
||||||
|
&self,
|
||||||
|
operation.into(),
|
||||||
|
)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CoerceInto<$ty> for Tagged<&BigDecimal> {
|
||||||
|
fn coerce_into(self, operation: impl Into<String>) -> Result<$ty, ShellError> {
|
||||||
|
match self.$op() {
|
||||||
|
Some(v) => Ok(v),
|
||||||
|
None => Err(ShellError::range_error(
|
||||||
|
$ty::to_expected_range(),
|
||||||
|
&self,
|
||||||
|
operation.into(),
|
||||||
|
)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
ranged_decimal!(f32 -> to_f32 -> F32);
|
||||||
|
ranged_decimal!(f64 -> to_f64 -> F64);
|
||||||
|
@ -38,7 +38,7 @@ pub(crate) fn evaluate_baseline_expr(
|
|||||||
source: &Text,
|
source: &Text,
|
||||||
) -> Result<Tagged<Value>, ShellError> {
|
) -> Result<Tagged<Value>, ShellError> {
|
||||||
match &expr.item {
|
match &expr.item {
|
||||||
RawExpression::Literal(literal) => Ok(evaluate_literal(expr.copy_span(*literal), source)),
|
RawExpression::Literal(literal) => Ok(evaluate_literal(expr.copy_span(literal), source)),
|
||||||
RawExpression::FilePath(path) => Ok(Value::path(path.clone()).tagged(expr.span())),
|
RawExpression::FilePath(path) => Ok(Value::path(path.clone()).tagged(expr.span())),
|
||||||
RawExpression::Synthetic(hir::Synthetic::String(s)) => Ok(Value::string(s).tagged_unknown()),
|
RawExpression::Synthetic(hir::Synthetic::String(s)) => Ok(Value::string(s).tagged_unknown()),
|
||||||
RawExpression::Variable(var) => evaluate_reference(var, scope, source),
|
RawExpression::Variable(var) => evaluate_reference(var, scope, source),
|
||||||
@ -104,7 +104,7 @@ pub(crate) fn evaluate_baseline_expr(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn evaluate_literal(literal: Tagged<hir::Literal>, source: &Text) -> Tagged<Value> {
|
fn evaluate_literal(literal: Tagged<&hir::Literal>, source: &Text) -> Tagged<Value> {
|
||||||
let result = match literal.item {
|
let result = match literal.item {
|
||||||
hir::Literal::Number(int) => int.into(),
|
hir::Literal::Number(int) => int.into(),
|
||||||
hir::Literal::Size(int, unit) => unit.compute(int),
|
hir::Literal::Size(int, unit) => unit.compute(int),
|
||||||
|
@ -28,7 +28,7 @@ pub use crate::parser::hir::SyntaxType;
|
|||||||
pub use crate::plugin::{serve_plugin, Plugin};
|
pub use crate::plugin::{serve_plugin, Plugin};
|
||||||
pub use crate::utils::{AbsoluteFile, AbsolutePath, RelativePath};
|
pub use crate::utils::{AbsoluteFile, AbsolutePath, RelativePath};
|
||||||
pub use cli::cli;
|
pub use cli::cli;
|
||||||
pub use errors::ShellError;
|
pub use errors::{CoerceInto, ShellError};
|
||||||
pub use num_traits::cast::ToPrimitive;
|
pub use num_traits::cast::ToPrimitive;
|
||||||
pub use object::base::{Primitive, Value};
|
pub use object::base::{Primitive, Value};
|
||||||
pub use object::dict::{Dictionary, TaggedDictBuilder};
|
pub use object::dict::{Dictionary, TaggedDictBuilder};
|
||||||
|
@ -16,8 +16,8 @@ use std::time::SystemTime;
|
|||||||
#[derive(Debug, Clone, Ord, PartialOrd, Eq, PartialEq, Deserialize, Serialize)]
|
#[derive(Debug, Clone, Ord, PartialOrd, Eq, PartialEq, Deserialize, Serialize)]
|
||||||
pub enum Primitive {
|
pub enum Primitive {
|
||||||
Nothing,
|
Nothing,
|
||||||
Int(i64),
|
Int(BigInt),
|
||||||
Decimal(Decimal),
|
Decimal(BigDecimal),
|
||||||
Bytes(u64),
|
Bytes(u64),
|
||||||
String(String),
|
String(String),
|
||||||
Boolean(bool),
|
Boolean(bool),
|
||||||
@ -29,21 +29,15 @@ pub enum Primitive {
|
|||||||
EndOfStream,
|
EndOfStream,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<i64> for Primitive {
|
impl From<BigDecimal> for Primitive {
|
||||||
fn from(int: i64) -> Primitive {
|
fn from(decimal: BigDecimal) -> Primitive {
|
||||||
Primitive::Int(int)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<Decimal> for Primitive {
|
|
||||||
fn from(decimal: Decimal) -> Primitive {
|
|
||||||
Primitive::Decimal(decimal)
|
Primitive::Decimal(decimal)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<f64> for Primitive {
|
impl From<f64> for Primitive {
|
||||||
fn from(float: f64) -> Primitive {
|
fn from(float: f64) -> Primitive {
|
||||||
Primitive::Decimal(Decimal::from_f64(float).unwrap())
|
Primitive::Decimal(BigDecimal::from_f64(float).unwrap())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -193,6 +187,15 @@ impl Into<Value> for Number {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Into<Value> for &Number {
|
||||||
|
fn into(self) -> Value {
|
||||||
|
match self {
|
||||||
|
Number::Int(int) => Value::int(int.clone()),
|
||||||
|
Number::Decimal(decimal) => Value::decimal(decimal.clone()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn debug_list(values: &Vec<Tagged<Value>>) -> ValuesDebug<'_> {
|
pub fn debug_list(values: &Vec<Tagged<Value>>) -> ValuesDebug<'_> {
|
||||||
ValuesDebug { values }
|
ValuesDebug { values }
|
||||||
}
|
}
|
||||||
@ -251,7 +254,9 @@ impl std::convert::TryFrom<&Tagged<Value>> for i64 {
|
|||||||
|
|
||||||
fn try_from(value: &Tagged<Value>) -> Result<i64, ShellError> {
|
fn try_from(value: &Tagged<Value>) -> Result<i64, ShellError> {
|
||||||
match value.item() {
|
match value.item() {
|
||||||
Value::Primitive(Primitive::Int(int)) => Ok(*int),
|
Value::Primitive(Primitive::Int(int)) => {
|
||||||
|
int.tagged(value.tag).coerce_into("converting to i64")
|
||||||
|
}
|
||||||
v => Err(ShellError::type_error(
|
v => Err(ShellError::type_error(
|
||||||
"Integer",
|
"Integer",
|
||||||
value.copy_span(v.type_name()),
|
value.copy_span(v.type_name()),
|
||||||
@ -598,18 +603,6 @@ impl Value {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn as_i64(&self) -> Result<i64, ShellError> {
|
|
||||||
match self {
|
|
||||||
Value::Primitive(Primitive::Int(i)) => Ok(*i),
|
|
||||||
Value::Primitive(Primitive::Bytes(b)) => Ok(*b as i64),
|
|
||||||
// TODO: this should definitely be more general with better errors
|
|
||||||
other => Err(ShellError::string(format!(
|
|
||||||
"Expected integer, got {:?}",
|
|
||||||
other
|
|
||||||
))),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn is_true(&self) -> bool {
|
pub(crate) fn is_true(&self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
Value::Primitive(Primitive::Boolean(true)) => true,
|
Value::Primitive(Primitive::Boolean(true)) => true,
|
||||||
@ -629,11 +622,11 @@ impl Value {
|
|||||||
Value::Primitive(Primitive::Bytes(s.into()))
|
Value::Primitive(Primitive::Bytes(s.into()))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn int(s: impl Into<i64>) -> Value {
|
pub fn int(s: impl Into<BigInt>) -> Value {
|
||||||
Value::Primitive(Primitive::Int(s.into()))
|
Value::Primitive(Primitive::Int(s.into()))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn decimal(s: impl Into<Decimal>) -> Value {
|
pub fn decimal(s: impl Into<BigDecimal>) -> Value {
|
||||||
Value::Primitive(Primitive::Decimal(s.into()))
|
Value::Primitive(Primitive::Decimal(s.into()))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -727,18 +720,24 @@ pub(crate) fn find(obj: &Value, field: &str, op: &Operator, rhs: &Value) -> bool
|
|||||||
_ => false,
|
_ => false,
|
||||||
},
|
},
|
||||||
Value::Primitive(Primitive::Bytes(i)) => match (op, rhs) {
|
Value::Primitive(Primitive::Bytes(i)) => match (op, rhs) {
|
||||||
(Operator::LessThan, Value::Primitive(Primitive::Int(i2))) => i < (*i2 as u64),
|
(Operator::LessThan, Value::Primitive(Primitive::Int(i2))) => {
|
||||||
|
BigInt::from(i) < *i2
|
||||||
|
}
|
||||||
(Operator::GreaterThan, Value::Primitive(Primitive::Int(i2))) => {
|
(Operator::GreaterThan, Value::Primitive(Primitive::Int(i2))) => {
|
||||||
i > (*i2 as u64)
|
BigInt::from(i) > *i2
|
||||||
}
|
}
|
||||||
(Operator::LessThanOrEqual, Value::Primitive(Primitive::Int(i2))) => {
|
(Operator::LessThanOrEqual, Value::Primitive(Primitive::Int(i2))) => {
|
||||||
i <= (*i2 as u64)
|
BigInt::from(i) <= *i2
|
||||||
}
|
}
|
||||||
(Operator::GreaterThanOrEqual, Value::Primitive(Primitive::Int(i2))) => {
|
(Operator::GreaterThanOrEqual, Value::Primitive(Primitive::Int(i2))) => {
|
||||||
i >= (*i2 as u64)
|
BigInt::from(i) >= *i2
|
||||||
|
}
|
||||||
|
(Operator::Equal, Value::Primitive(Primitive::Int(i2))) => {
|
||||||
|
BigInt::from(i) == *i2
|
||||||
|
}
|
||||||
|
(Operator::NotEqual, Value::Primitive(Primitive::Int(i2))) => {
|
||||||
|
BigInt::from(i) != *i2
|
||||||
}
|
}
|
||||||
(Operator::Equal, Value::Primitive(Primitive::Int(i2))) => i == (*i2 as u64),
|
|
||||||
(Operator::NotEqual, Value::Primitive(Primitive::Int(i2))) => i != (*i2 as u64),
|
|
||||||
_ => false,
|
_ => false,
|
||||||
},
|
},
|
||||||
Value::Primitive(Primitive::Int(i)) => match (op, rhs) {
|
Value::Primitive(Primitive::Int(i)) => match (op, rhs) {
|
||||||
@ -764,22 +763,22 @@ pub(crate) fn find(obj: &Value, field: &str, op: &Operator, rhs: &Value) -> bool
|
|||||||
(Operator::Equal, Value::Primitive(Primitive::Decimal(i2))) => i == *i2,
|
(Operator::Equal, Value::Primitive(Primitive::Decimal(i2))) => i == *i2,
|
||||||
(Operator::NotEqual, Value::Primitive(Primitive::Decimal(i2))) => i != *i2,
|
(Operator::NotEqual, Value::Primitive(Primitive::Decimal(i2))) => i != *i2,
|
||||||
(Operator::LessThan, Value::Primitive(Primitive::Int(i2))) => {
|
(Operator::LessThan, Value::Primitive(Primitive::Int(i2))) => {
|
||||||
i < Decimal::from(*i2)
|
i < BigDecimal::from(i2.clone())
|
||||||
}
|
}
|
||||||
(Operator::GreaterThan, Value::Primitive(Primitive::Int(i2))) => {
|
(Operator::GreaterThan, Value::Primitive(Primitive::Int(i2))) => {
|
||||||
i > Decimal::from(*i2)
|
i > BigDecimal::from(i2.clone())
|
||||||
}
|
}
|
||||||
(Operator::LessThanOrEqual, Value::Primitive(Primitive::Int(i2))) => {
|
(Operator::LessThanOrEqual, Value::Primitive(Primitive::Int(i2))) => {
|
||||||
i <= Decimal::from(*i2)
|
i <= BigDecimal::from(i2.clone())
|
||||||
}
|
}
|
||||||
(Operator::GreaterThanOrEqual, Value::Primitive(Primitive::Int(i2))) => {
|
(Operator::GreaterThanOrEqual, Value::Primitive(Primitive::Int(i2))) => {
|
||||||
i >= Decimal::from(*i2)
|
i >= BigDecimal::from(i2.clone())
|
||||||
}
|
}
|
||||||
(Operator::Equal, Value::Primitive(Primitive::Int(i2))) => {
|
(Operator::Equal, Value::Primitive(Primitive::Int(i2))) => {
|
||||||
i == Decimal::from(*i2)
|
i == BigDecimal::from(i2.clone())
|
||||||
}
|
}
|
||||||
(Operator::NotEqual, Value::Primitive(Primitive::Int(i2))) => {
|
(Operator::NotEqual, Value::Primitive(Primitive::Int(i2))) => {
|
||||||
i != Decimal::from(*i2)
|
i != BigDecimal::from(i2.clone())
|
||||||
}
|
}
|
||||||
|
|
||||||
_ => false,
|
_ => false,
|
||||||
@ -796,9 +795,8 @@ pub(crate) fn find(obj: &Value, field: &str, op: &Operator, rhs: &Value) -> bool
|
|||||||
}
|
}
|
||||||
|
|
||||||
enum CompareValues {
|
enum CompareValues {
|
||||||
Ints(i64, i64),
|
Ints(BigInt, BigInt),
|
||||||
Decimals(Decimal, Decimal),
|
Decimals(BigDecimal, BigDecimal),
|
||||||
Bytes(u64, u64),
|
|
||||||
String(String, String),
|
String(String, String),
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -807,7 +805,6 @@ impl CompareValues {
|
|||||||
match self {
|
match self {
|
||||||
CompareValues::Ints(left, right) => left.cmp(right),
|
CompareValues::Ints(left, right) => left.cmp(right),
|
||||||
CompareValues::Decimals(left, right) => left.cmp(right),
|
CompareValues::Decimals(left, right) => left.cmp(right),
|
||||||
CompareValues::Bytes(left, right) => left.cmp(right),
|
|
||||||
CompareValues::String(left, right) => left.cmp(right),
|
CompareValues::String(left, right) => left.cmp(right),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -828,17 +825,21 @@ fn coerce_compare_primitive(
|
|||||||
use Primitive::*;
|
use Primitive::*;
|
||||||
|
|
||||||
Ok(match (left, right) {
|
Ok(match (left, right) {
|
||||||
(Int(left), Int(right)) => CompareValues::Ints(*left, *right),
|
(Int(left), Int(right)) => CompareValues::Ints(left.clone(), right.clone()),
|
||||||
(Int(left), Decimal(right)) => CompareValues::Decimals((*left).into(), *right),
|
(Int(left), Decimal(right)) => {
|
||||||
(Int(left), Bytes(right)) => CompareValues::Bytes(*left as u64, *right),
|
CompareValues::Decimals(BigDecimal::zero() + left, right.clone())
|
||||||
(Decimal(left), Decimal(right)) => CompareValues::Decimals(*left, *right),
|
|
||||||
(Decimal(left), Int(right)) => CompareValues::Decimals(*left, (*right).into()),
|
|
||||||
(Decimal(left), Bytes(right)) => {
|
|
||||||
CompareValues::Decimals(*left, rust_decimal::Decimal::from(*right))
|
|
||||||
}
|
}
|
||||||
(Bytes(left), Int(right)) => CompareValues::Bytes(*left, *right as u64),
|
(Int(left), Bytes(right)) => CompareValues::Ints(left.clone(), BigInt::from(*right)),
|
||||||
|
(Decimal(left), Decimal(right)) => CompareValues::Decimals(left.clone(), right.clone()),
|
||||||
|
(Decimal(left), Int(right)) => {
|
||||||
|
CompareValues::Decimals(left.clone(), BigDecimal::zero() + right)
|
||||||
|
}
|
||||||
|
(Decimal(left), Bytes(right)) => {
|
||||||
|
CompareValues::Decimals(left.clone(), BigDecimal::from(*right))
|
||||||
|
}
|
||||||
|
(Bytes(left), Int(right)) => CompareValues::Ints(BigInt::from(*left), right.clone()),
|
||||||
(Bytes(left), Decimal(right)) => {
|
(Bytes(left), Decimal(right)) => {
|
||||||
CompareValues::Decimals(rust_decimal::Decimal::from(*left), *right)
|
CompareValues::Decimals(BigDecimal::from(*left), right.clone())
|
||||||
}
|
}
|
||||||
(String(left), String(right)) => CompareValues::String(left.clone(), right.clone()),
|
(String(left), String(right)) => CompareValues::String(left.clone(), right.clone()),
|
||||||
_ => return Err((left.type_name(), right.type_name())),
|
_ => return Err((left.type_name(), right.type_name())),
|
||||||
|
@ -36,7 +36,8 @@ pub(crate) fn write_config(config: &IndexMap<String, Tagged<Value>>) -> Result<(
|
|||||||
let filename = location.join("config.toml");
|
let filename = location.join("config.toml");
|
||||||
touch(&filename)?;
|
touch(&filename)?;
|
||||||
|
|
||||||
let contents = value_to_toml_value(&Value::Object(Dictionary::new(config.clone())))?;
|
let contents =
|
||||||
|
value_to_toml_value(&Value::Object(Dictionary::new(config.clone())).tagged_unknown())?;
|
||||||
|
|
||||||
let contents = toml::to_string(&contents)?;
|
let contents = toml::to_string(&contents)?;
|
||||||
|
|
||||||
|
@ -135,11 +135,25 @@ impl ExtractType for i64 {
|
|||||||
fn extract(value: &Tagged<Value>) -> Result<i64, ShellError> {
|
fn extract(value: &Tagged<Value>) -> Result<i64, ShellError> {
|
||||||
trace!("Extracting {:?} for i64", value);
|
trace!("Extracting {:?} for i64", value);
|
||||||
|
|
||||||
match value {
|
match &value {
|
||||||
&Tagged {
|
&Tagged {
|
||||||
item: Value::Primitive(Primitive::Int(int)),
|
item: Value::Primitive(Primitive::Int(int)),
|
||||||
..
|
..
|
||||||
} => Ok(int),
|
} => Ok(int.tagged(value.tag).coerce_into("converting to i64")?),
|
||||||
|
other => Err(ShellError::type_error("Integer", other.tagged_type_name())),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ExtractType for u64 {
|
||||||
|
fn extract(value: &Tagged<Value>) -> Result<u64, ShellError> {
|
||||||
|
trace!("Extracting {:?} for u64", value);
|
||||||
|
|
||||||
|
match &value {
|
||||||
|
&Tagged {
|
||||||
|
item: Value::Primitive(Primitive::Int(int)),
|
||||||
|
..
|
||||||
|
} => Ok(int.tagged(value.tag).coerce_into("converting to u64")?),
|
||||||
other => Err(ShellError::type_error("Integer", other.tagged_type_name())),
|
other => Err(ShellError::type_error("Integer", other.tagged_type_name())),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -226,7 +226,7 @@ impl From<Tagged<Path>> for Expression {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize)]
|
||||||
pub enum Literal {
|
pub enum Literal {
|
||||||
Number(Number),
|
Number(Number),
|
||||||
Size(Number, Unit),
|
Size(Number, Unit),
|
||||||
|
@ -5,8 +5,10 @@ use std::path::PathBuf;
|
|||||||
|
|
||||||
pub fn baseline_parse_single_token(token: &Token, source: &Text) -> hir::Expression {
|
pub fn baseline_parse_single_token(token: &Token, source: &Text) -> hir::Expression {
|
||||||
match *token.item() {
|
match *token.item() {
|
||||||
RawToken::Number(number) => hir::Expression::number(number, token.span()),
|
RawToken::Number(number) => hir::Expression::number(number.to_number(source), token.span()),
|
||||||
RawToken::Size(int, unit) => hir::Expression::size(int, unit, token.span()),
|
RawToken::Size(int, unit) => {
|
||||||
|
hir::Expression::size(int.to_number(source), unit, token.span())
|
||||||
|
}
|
||||||
RawToken::String(span) => hir::Expression::string(span, token.span()),
|
RawToken::String(span) => hir::Expression::string(span, token.span()),
|
||||||
RawToken::Variable(span) if span.slice(source) == "it" => {
|
RawToken::Variable(span) if span.slice(source) == "it" => {
|
||||||
hir::Expression::it_variable(span, token.span())
|
hir::Expression::it_variable(span, token.span())
|
||||||
@ -24,8 +26,10 @@ pub fn baseline_parse_token_as_number(token: &Token, source: &Text) -> hir::Expr
|
|||||||
}
|
}
|
||||||
RawToken::External(span) => hir::Expression::external_command(span, token.span()),
|
RawToken::External(span) => hir::Expression::external_command(span, token.span()),
|
||||||
RawToken::Variable(span) => hir::Expression::variable(span, token.span()),
|
RawToken::Variable(span) => hir::Expression::variable(span, token.span()),
|
||||||
RawToken::Number(number) => hir::Expression::number(number, token.span()),
|
RawToken::Number(number) => hir::Expression::number(number.to_number(source), token.span()),
|
||||||
RawToken::Size(number, unit) => hir::Expression::size(number, unit, token.span()),
|
RawToken::Size(number, unit) => {
|
||||||
|
hir::Expression::size(number.to_number(source), unit, token.span())
|
||||||
|
}
|
||||||
RawToken::Bare => hir::Expression::bare(token.span()),
|
RawToken::Bare => hir::Expression::bare(token.span()),
|
||||||
RawToken::String(span) => hir::Expression::string(span, token.span()),
|
RawToken::String(span) => hir::Expression::string(span, token.span()),
|
||||||
}
|
}
|
||||||
|
@ -70,20 +70,60 @@ fn trace_step<'a, T: Debug>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash, Ord, PartialOrd, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Eq, PartialEq, Hash, Ord, PartialOrd, Serialize, Deserialize)]
|
||||||
pub enum Number {
|
pub enum Number {
|
||||||
Int(i64),
|
Int(BigInt),
|
||||||
Decimal(Decimal),
|
Decimal(BigDecimal),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
macro_rules! primitive_int {
|
||||||
|
($($ty:ty)*) => {
|
||||||
|
$(
|
||||||
|
impl From<$ty> for Number {
|
||||||
|
fn from(int: $ty) -> Number {
|
||||||
|
Number::Int(BigInt::zero() + int)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<&$ty> for Number {
|
||||||
|
fn from(int: &$ty) -> Number {
|
||||||
|
Number::Int(BigInt::zero() + *int)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)*
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
primitive_int!(i8 u8 i16 u16 i32 u32 i64 u64 i128 u128);
|
||||||
|
|
||||||
|
macro_rules! primitive_decimal {
|
||||||
|
($($ty:tt -> $from:tt),*) => {
|
||||||
|
$(
|
||||||
|
impl From<$ty> for Number {
|
||||||
|
fn from(decimal: $ty) -> Number {
|
||||||
|
Number::Decimal(BigDecimal::$from(decimal).unwrap())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<&$ty> for Number {
|
||||||
|
fn from(decimal: &$ty) -> Number {
|
||||||
|
Number::Decimal(BigDecimal::$from(*decimal).unwrap())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)*
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
primitive_decimal!(f32 -> from_f32, f64 -> from_f64);
|
||||||
|
|
||||||
impl std::ops::Mul for Number {
|
impl std::ops::Mul for Number {
|
||||||
type Output = Number;
|
type Output = Number;
|
||||||
|
|
||||||
fn mul(self, other: Number) -> Number {
|
fn mul(self, other: Number) -> Number {
|
||||||
match (self, other) {
|
match (self, other) {
|
||||||
(Number::Int(a), Number::Int(b)) => Number::Int(a * b),
|
(Number::Int(a), Number::Int(b)) => Number::Int(a * b),
|
||||||
(Number::Int(a), Number::Decimal(b)) => Number::Decimal(Decimal::from(a) * b),
|
(Number::Int(a), Number::Decimal(b)) => Number::Decimal(BigDecimal::from(a) * b),
|
||||||
(Number::Decimal(a), Number::Int(b)) => Number::Decimal(a * Decimal::from(b)),
|
(Number::Decimal(a), Number::Int(b)) => Number::Decimal(a * BigDecimal::from(b)),
|
||||||
(Number::Decimal(a), Number::Decimal(b)) => Number::Decimal(a * b),
|
(Number::Decimal(a), Number::Decimal(b)) => Number::Decimal(a * b),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -96,36 +136,18 @@ impl std::ops::Mul<u32> for Number {
|
|||||||
fn mul(self, other: u32) -> Number {
|
fn mul(self, other: u32) -> Number {
|
||||||
match self {
|
match self {
|
||||||
Number::Int(left) => Number::Int(left * (other as i64)),
|
Number::Int(left) => Number::Int(left * (other as i64)),
|
||||||
Number::Decimal(left) => Number::Decimal(left * Decimal::from(other)),
|
Number::Decimal(left) => Number::Decimal(left * BigDecimal::from(other)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Into<Number> for f32 {
|
impl Into<Number> for BigDecimal {
|
||||||
fn into(self) -> Number {
|
|
||||||
Number::Decimal(Decimal::from_f32(self).unwrap())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Into<Number> for f64 {
|
|
||||||
fn into(self) -> Number {
|
|
||||||
Number::Decimal(Decimal::from_f64(self).unwrap())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Into<Number> for i64 {
|
|
||||||
fn into(self) -> Number {
|
|
||||||
Number::Int(self)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Into<Number> for Decimal {
|
|
||||||
fn into(self) -> Number {
|
fn into(self) -> Number {
|
||||||
Number::Decimal(self)
|
Number::Decimal(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn raw_number(input: NomSpan) -> IResult<NomSpan, Tagged<Number>> {
|
pub fn raw_number(input: NomSpan) -> IResult<NomSpan, Tagged<RawNumber>> {
|
||||||
let original = input;
|
let original = input;
|
||||||
let start = input.offset;
|
let start = input.offset;
|
||||||
trace_step(input, "raw_decimal", move |input| {
|
trace_step(input, "raw_decimal", move |input| {
|
||||||
@ -137,28 +159,14 @@ pub fn raw_number(input: NomSpan) -> IResult<NomSpan, Tagged<Number>> {
|
|||||||
Ok((input, dot)) => input,
|
Ok((input, dot)) => input,
|
||||||
|
|
||||||
// it's just an integer
|
// it's just an integer
|
||||||
Err(_) => {
|
Err(_) => return Ok((input, RawNumber::int((start, input.offset)))),
|
||||||
return Ok((
|
|
||||||
input,
|
|
||||||
Tagged::from_simple_spanned_item(
|
|
||||||
Number::Int(int(head.fragment, neg)),
|
|
||||||
(start, input.offset),
|
|
||||||
),
|
|
||||||
))
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let (input, tail) = digit1(input)?;
|
let (input, tail) = digit1(input)?;
|
||||||
|
|
||||||
let end = input.offset;
|
let end = input.offset;
|
||||||
|
|
||||||
let decimal = Decimal::from_str(&format!("{}.{}", head.fragment, tail.fragment))
|
Ok((input, RawNumber::decimal((start, end))))
|
||||||
.expect("BUG: Should have already ensured that the input is a valid decimal");
|
|
||||||
|
|
||||||
Ok((
|
|
||||||
input,
|
|
||||||
Tagged::from_simple_spanned_item(Number::Decimal(decimal), (start, end)),
|
|
||||||
))
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -709,12 +717,12 @@ mod tests {
|
|||||||
fn test_integer() {
|
fn test_integer() {
|
||||||
assert_leaf! {
|
assert_leaf! {
|
||||||
parsers [ size ]
|
parsers [ size ]
|
||||||
"123" -> 0..3 { Number(Number::Int(123)) }
|
"123" -> 0..3 { Number(RawNumber::int((0, 3)).item) }
|
||||||
}
|
}
|
||||||
|
|
||||||
assert_leaf! {
|
assert_leaf! {
|
||||||
parsers [ size ]
|
parsers [ size ]
|
||||||
"-123" -> 0..4 { Number(Number::Int(-123)) }
|
"-123" -> 0..4 { Number(RawNumber::int((0, 4)).item) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -722,12 +730,12 @@ mod tests {
|
|||||||
fn test_size() {
|
fn test_size() {
|
||||||
assert_leaf! {
|
assert_leaf! {
|
||||||
parsers [ size ]
|
parsers [ size ]
|
||||||
"123MB" -> 0..5 { Size(Number::Int(123), Unit::MB) }
|
"123MB" -> 0..5 { Size(RawNumber::int((0, 3)).item, Unit::MB) }
|
||||||
}
|
}
|
||||||
|
|
||||||
assert_leaf! {
|
assert_leaf! {
|
||||||
parsers [ size ]
|
parsers [ size ]
|
||||||
"10GB" -> 0..4 { Size(Number::Int(10), Unit::GB) }
|
"10GB" -> 0..4 { Size(RawNumber::int((0, 2)).item, Unit::GB) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,10 +3,9 @@ use crate::prelude::*;
|
|||||||
|
|
||||||
use crate::parser::parse::flag::{Flag, FlagKind};
|
use crate::parser::parse::flag::{Flag, FlagKind};
|
||||||
use crate::parser::parse::operator::Operator;
|
use crate::parser::parse::operator::Operator;
|
||||||
use crate::parser::parse::parser::Number;
|
|
||||||
use crate::parser::parse::pipeline::{Pipeline, PipelineElement};
|
use crate::parser::parse::pipeline::{Pipeline, PipelineElement};
|
||||||
use crate::parser::parse::token_tree::{DelimitedNode, Delimiter, PathNode, TokenNode};
|
use crate::parser::parse::token_tree::{DelimitedNode, Delimiter, PathNode, TokenNode};
|
||||||
use crate::parser::parse::tokens::{RawToken, Token};
|
use crate::parser::parse::tokens::{RawNumber, RawToken};
|
||||||
use crate::parser::parse::unit::Unit;
|
use crate::parser::parse::unit::Unit;
|
||||||
use crate::parser::CallNode;
|
use crate::parser::CallNode;
|
||||||
use crate::Span;
|
use crate::Span;
|
||||||
@ -160,35 +159,32 @@ impl TokenTreeBuilder {
|
|||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn int(input: impl Into<i64>) -> CurriedToken {
|
pub fn int(input: impl Into<BigInt>) -> CurriedToken {
|
||||||
let int = input.into();
|
let int = input.into();
|
||||||
|
|
||||||
Box::new(move |b| {
|
Box::new(move |b| {
|
||||||
let (start, end) = b.consume(&int.to_string());
|
let (start, end) = b.consume(&int.to_string());
|
||||||
b.pos = end;
|
b.pos = end;
|
||||||
|
|
||||||
TokenTreeBuilder::spanned_int(int, (start, end))
|
TokenTreeBuilder::spanned_number(RawNumber::Int((start, end).into()), (start, end))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn spanned_number(input: impl Into<Number>, span: impl Into<Span>) -> TokenNode {
|
pub fn decimal(input: impl Into<BigDecimal>) -> CurriedToken {
|
||||||
match input.into() {
|
let decimal = input.into();
|
||||||
Number::Int(int) => TokenTreeBuilder::spanned_int(int, span),
|
|
||||||
Number::Decimal(decimal) => TokenTreeBuilder::spanned_decimal(decimal, span),
|
Box::new(move |b| {
|
||||||
}
|
let (start, end) = b.consume(&decimal.to_string());
|
||||||
|
b.pos = end;
|
||||||
|
|
||||||
|
TokenTreeBuilder::spanned_number(RawNumber::Decimal((start, end).into()), (start, end))
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn spanned_int(input: i64, span: impl Into<Span>) -> TokenNode {
|
pub fn spanned_number(input: impl Into<RawNumber>, span: impl Into<Span>) -> TokenNode {
|
||||||
TokenNode::Token(Token::from_simple_spanned_item(
|
TokenNode::Token(Tagged::from_simple_spanned_item(
|
||||||
RawToken::Number(Number::Int(input)),
|
RawToken::Number(input.into()),
|
||||||
span,
|
span.into(),
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn spanned_decimal(input: Decimal, span: impl Into<Span>) -> TokenNode {
|
|
||||||
TokenNode::Token(Token::from_simple_spanned_item(
|
|
||||||
RawToken::Number(Number::Decimal(input)),
|
|
||||||
span,
|
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -197,16 +193,19 @@ impl TokenTreeBuilder {
|
|||||||
let unit = unit.into();
|
let unit = unit.into();
|
||||||
|
|
||||||
Box::new(move |b| {
|
Box::new(move |b| {
|
||||||
let (start, _) = b.consume(&int.to_string());
|
let (start_int, end_int) = b.consume(&int.to_string());
|
||||||
let (_, end) = b.consume(unit.as_str());
|
let (start_unit, end_unit) = b.consume(unit.as_str());
|
||||||
b.pos = end;
|
b.pos = end_unit;
|
||||||
|
|
||||||
TokenTreeBuilder::spanned_size((int, unit), (start, end))
|
TokenTreeBuilder::spanned_size(
|
||||||
|
(RawNumber::Int((start_int, end_int).into()), unit),
|
||||||
|
(start_int, end_unit),
|
||||||
|
)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn spanned_size(
|
pub fn spanned_size(
|
||||||
input: (impl Into<Number>, impl Into<Unit>),
|
input: (impl Into<RawNumber>, impl Into<Unit>),
|
||||||
span: impl Into<Span>,
|
span: impl Into<Span>,
|
||||||
) -> TokenNode {
|
) -> TokenNode {
|
||||||
let (int, unit) = (input.0.into(), input.1.into());
|
let (int, unit) = (input.0.into(), input.1.into());
|
||||||
|
@ -2,17 +2,47 @@ use crate::parser::parse::unit::*;
|
|||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::{Span, Tagged, Text};
|
use crate::{Span, Tagged, Text};
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
use std::str::FromStr;
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash)]
|
#[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash)]
|
||||||
pub enum RawToken {
|
pub enum RawToken {
|
||||||
Number(Number),
|
Number(RawNumber),
|
||||||
Size(Number, Unit),
|
Size(RawNumber, Unit),
|
||||||
String(Span),
|
String(Span),
|
||||||
Variable(Span),
|
Variable(Span),
|
||||||
External(Span),
|
External(Span),
|
||||||
Bare,
|
Bare,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash)]
|
||||||
|
pub enum RawNumber {
|
||||||
|
Int(Span),
|
||||||
|
Decimal(Span),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RawNumber {
|
||||||
|
pub fn int(span: impl Into<Span>) -> Tagged<RawNumber> {
|
||||||
|
let span = span.into();
|
||||||
|
|
||||||
|
RawNumber::Int(span).tagged(span)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn decimal(span: impl Into<Span>) -> Tagged<RawNumber> {
|
||||||
|
let span = span.into();
|
||||||
|
|
||||||
|
RawNumber::Decimal(span).tagged(span)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn to_number(self, source: &Text) -> Number {
|
||||||
|
match self {
|
||||||
|
RawNumber::Int(span) => Number::Int(BigInt::from_str(span.slice(source)).unwrap()),
|
||||||
|
RawNumber::Decimal(span) => {
|
||||||
|
Number::Decimal(BigDecimal::from_str(span.slice(source)).unwrap())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl RawToken {
|
impl RawToken {
|
||||||
pub fn type_name(&self) -> &'static str {
|
pub fn type_name(&self) -> &'static str {
|
||||||
match self {
|
match self {
|
||||||
|
@ -25,7 +25,9 @@ impl Unit {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn compute(&self, size: Number) -> Value {
|
pub(crate) fn compute(&self, size: &Number) -> Value {
|
||||||
|
let size = size.clone();
|
||||||
|
|
||||||
Value::number(match self {
|
Value::number(match self {
|
||||||
Unit::B => size,
|
Unit::B => size,
|
||||||
Unit::KB => size * 1024,
|
Unit::KB => size * 1024,
|
||||||
|
@ -75,7 +75,7 @@ impl Inc {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn inc(&self, value: Tagged<Value>) -> Result<Tagged<Value>, ShellError> {
|
fn inc(&self, value: Tagged<Value>) -> Result<Tagged<Value>, ShellError> {
|
||||||
match value.item {
|
match value.item() {
|
||||||
Value::Primitive(Primitive::Int(i)) => Ok(Value::int(i + 1).tagged(value.tag())),
|
Value::Primitive(Primitive::Int(i)) => Ok(Value::int(i + 1).tagged(value.tag())),
|
||||||
Value::Primitive(Primitive::Bytes(b)) => {
|
Value::Primitive(Primitive::Bytes(b)) => {
|
||||||
Ok(Value::bytes(b + 1 as u64).tagged(value.tag()))
|
Ok(Value::bytes(b + 1 as u64).tagged(value.tag()))
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
use nu::{
|
use nu::{
|
||||||
serve_plugin, CallInfo, Plugin, Primitive, ReturnSuccess, ReturnValue, ShellError, Signature,
|
serve_plugin, CallInfo, CoerceInto, Plugin, Primitive, ReturnSuccess, ReturnValue, ShellError,
|
||||||
SyntaxType, Tagged, Value,
|
Signature, SyntaxType, Tagged, TaggedItem, Value,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Skip {
|
struct Skip {
|
||||||
skip_amount: i64,
|
skip_amount: i64,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Skip {
|
impl Skip {
|
||||||
fn new() -> Skip {
|
fn new() -> Skip {
|
||||||
Skip { skip_amount: 0 }
|
Skip { skip_amount: 0 }
|
||||||
@ -25,9 +26,9 @@ impl Plugin for Skip {
|
|||||||
match arg {
|
match arg {
|
||||||
Tagged {
|
Tagged {
|
||||||
item: Value::Primitive(Primitive::Int(i)),
|
item: Value::Primitive(Primitive::Int(i)),
|
||||||
..
|
tag,
|
||||||
} => {
|
} => {
|
||||||
self.skip_amount = i;
|
self.skip_amount = i.tagged(tag).coerce_into("converting for skip")?;
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
return Err(ShellError::labeled_error(
|
return Err(ShellError::labeled_error(
|
||||||
|
@ -258,13 +258,13 @@ fn main() {
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
|
||||||
use super::{Action, ReplaceAction, Str};
|
use super::{Action, ReplaceAction, Str};
|
||||||
use indexmap::IndexMap;
|
use indexmap::IndexMap;
|
||||||
use nu::{
|
use nu::{
|
||||||
CallInfo, EvaluatedArgs, Plugin, Primitive, ReturnSuccess, SourceMap, Span, Tag, Tagged,
|
CallInfo, EvaluatedArgs, Plugin, Primitive, ReturnSuccess, SourceMap, Span, Tag, Tagged,
|
||||||
TaggedDictBuilder, TaggedItem, Value,
|
TaggedDictBuilder, TaggedItem, Value,
|
||||||
};
|
};
|
||||||
|
use num_bigint::BigInt;
|
||||||
|
|
||||||
impl Str {
|
impl Str {
|
||||||
fn replace_with(&mut self, value: &str) {
|
fn replace_with(&mut self, value: &str) {
|
||||||
@ -600,7 +600,7 @@ mod tests {
|
|||||||
ReturnSuccess::Value(Tagged {
|
ReturnSuccess::Value(Tagged {
|
||||||
item: Value::Primitive(Primitive::Int(i)),
|
item: Value::Primitive(Primitive::Int(i)),
|
||||||
..
|
..
|
||||||
}) => assert_eq!(*i, 10),
|
}) => assert_eq!(*i, BigInt::from(10)),
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,10 +12,10 @@ impl Sum {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn sum(&mut self, value: Tagged<Value>) -> Result<(), ShellError> {
|
fn sum(&mut self, value: Tagged<Value>) -> Result<(), ShellError> {
|
||||||
match value.item {
|
match value.item() {
|
||||||
Value::Primitive(Primitive::Nothing) => Ok(()),
|
Value::Primitive(Primitive::Nothing) => Ok(()),
|
||||||
Value::Primitive(Primitive::Int(i)) => {
|
Value::Primitive(Primitive::Int(i)) => {
|
||||||
match self.total {
|
match &self.total {
|
||||||
Some(Tagged {
|
Some(Tagged {
|
||||||
item: Value::Primitive(Primitive::Int(j)),
|
item: Value::Primitive(Primitive::Int(j)),
|
||||||
tag: Tag { span, .. },
|
tag: Tag { span, .. },
|
||||||
@ -26,7 +26,7 @@ impl Sum {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
self.total = Some(value);
|
self.total = Some(value.clone());
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
_ => Err(ShellError::string(format!(
|
_ => Err(ShellError::string(format!(
|
||||||
|
@ -20,7 +20,7 @@ async fn cpu(tag: Tag) -> Option<Tagged<Value>> {
|
|||||||
match futures::future::try_join(heim::cpu::logical_count(), heim::cpu::frequency()).await {
|
match futures::future::try_join(heim::cpu::logical_count(), heim::cpu::frequency()).await {
|
||||||
Ok((num_cpu, cpu_speed)) => {
|
Ok((num_cpu, cpu_speed)) => {
|
||||||
let mut cpu_idx = TaggedDictBuilder::with_capacity(tag, 4);
|
let mut cpu_idx = TaggedDictBuilder::with_capacity(tag, 4);
|
||||||
cpu_idx.insert("cores", Primitive::Int(num_cpu as i64));
|
cpu_idx.insert("cores", Primitive::number(num_cpu));
|
||||||
|
|
||||||
let current_speed =
|
let current_speed =
|
||||||
(cpu_speed.current().get::<frequency::hertz>() as f64 / 1_000_000_000.0 * 100.0)
|
(cpu_speed.current().get::<frequency::hertz>() as f64 / 1_000_000_000.0 * 100.0)
|
||||||
|
@ -57,7 +57,7 @@ pub(crate) use crate::context::CommandRegistry;
|
|||||||
pub(crate) use crate::context::{Context, SpanSource};
|
pub(crate) use crate::context::{Context, SpanSource};
|
||||||
pub(crate) use crate::env::host::handle_unexpected;
|
pub(crate) use crate::env::host::handle_unexpected;
|
||||||
pub(crate) use crate::env::Host;
|
pub(crate) use crate::env::Host;
|
||||||
pub(crate) use crate::errors::ShellError;
|
pub(crate) use crate::errors::{CoerceInto, ShellError};
|
||||||
pub(crate) use crate::object::base as value;
|
pub(crate) use crate::object::base as value;
|
||||||
pub(crate) use crate::object::meta::{Tag, Tagged, TaggedItem};
|
pub(crate) use crate::object::meta::{Tag, Tagged, TaggedItem};
|
||||||
pub(crate) use crate::object::types::ExtractType;
|
pub(crate) use crate::object::types::ExtractType;
|
||||||
@ -73,13 +73,14 @@ pub(crate) use crate::stream::{InputStream, OutputStream};
|
|||||||
pub(crate) use crate::traits::{HasSpan, ToDebug};
|
pub(crate) use crate::traits::{HasSpan, ToDebug};
|
||||||
pub(crate) use crate::Span;
|
pub(crate) use crate::Span;
|
||||||
pub(crate) use crate::Text;
|
pub(crate) use crate::Text;
|
||||||
|
pub(crate) use bigdecimal::BigDecimal;
|
||||||
pub(crate) use futures::stream::BoxStream;
|
pub(crate) use futures::stream::BoxStream;
|
||||||
pub(crate) use futures::{FutureExt, Stream, StreamExt};
|
pub(crate) use futures::{FutureExt, Stream, StreamExt};
|
||||||
pub(crate) use futures_async_stream::async_stream_block;
|
pub(crate) use futures_async_stream::async_stream_block;
|
||||||
|
pub(crate) use num_bigint::BigInt;
|
||||||
pub(crate) use num_traits::cast::{FromPrimitive, ToPrimitive};
|
pub(crate) use num_traits::cast::{FromPrimitive, ToPrimitive};
|
||||||
pub(crate) use rust_decimal::Decimal;
|
pub(crate) use num_traits::identities::Zero;
|
||||||
#[allow(unused)]
|
pub(crate) use serde::Deserialize;
|
||||||
pub(crate) use serde::{Deserialize, Serialize};
|
|
||||||
pub(crate) use std::collections::VecDeque;
|
pub(crate) use std::collections::VecDeque;
|
||||||
pub(crate) use std::future::Future;
|
pub(crate) use std::future::Future;
|
||||||
pub(crate) use std::sync::{Arc, Mutex};
|
pub(crate) use std::sync::{Arc, Mutex};
|
||||||
|
Loading…
Reference in New Issue
Block a user