2019-05-23 09:23:06 +02:00
|
|
|
use crate::prelude::*;
|
2020-03-06 17:06:39 +01:00
|
|
|
use nu_errors::ShellError;
|
2020-06-27 07:38:19 +02:00
|
|
|
use nu_protocol::{Primitive, Type, UntaggedValue, Value};
|
2021-01-10 03:50:49 +01:00
|
|
|
use nu_source::{HasFallibleSpan, PrettyDebug, Tag, Tagged, TaggedItem};
|
2019-05-23 09:23:06 +02:00
|
|
|
|
2019-07-03 22:31:15 +02:00
|
|
|
pub struct InputStream {
|
2021-04-06 18:19:43 +02:00
|
|
|
values: Box<dyn Iterator<Item = Value> + Send + Sync>,
|
Move external closer to internal (#1611)
* Refactor InputStream and affected commands.
First, making `values` private and leaning on the `Stream` implementation makes
consumes of `InputStream` less likely to have to change in the future, if we
change what an `InputStream` is internally.
Second, we're dropping `Option<InputStream>` as the input to pipelines,
internals, and externals. Instead, `InputStream.is_empty` can be used to check
for "emptiness". Empty streams are typically only ever used as the first input
to a pipeline.
* Add run_external internal command.
We want to push external commands closer to internal commands, eventually
eliminating the concept of "external" completely. This means we can consolidate
a couple of things:
- Variable evaluation (for example, `$it`, `$nu`, alias vars)
- Behaviour of whole stream vs per-item external execution
It should also make it easier for us to start introducing argument signatures
for external commands,
* Update run_external.rs
* Update run_external.rs
* Update run_external.rs
* Update run_external.rs
Co-authored-by: Jonathan Turner <jonathandturner@users.noreply.github.com>
2020-04-20 05:30:44 +02:00
|
|
|
|
2020-10-29 04:14:08 +01:00
|
|
|
// Whether or not an empty stream was explicitly requested via InputStream::empty
|
Move external closer to internal (#1611)
* Refactor InputStream and affected commands.
First, making `values` private and leaning on the `Stream` implementation makes
consumes of `InputStream` less likely to have to change in the future, if we
change what an `InputStream` is internally.
Second, we're dropping `Option<InputStream>` as the input to pipelines,
internals, and externals. Instead, `InputStream.is_empty` can be used to check
for "emptiness". Empty streams are typically only ever used as the first input
to a pipeline.
* Add run_external internal command.
We want to push external commands closer to internal commands, eventually
eliminating the concept of "external" completely. This means we can consolidate
a couple of things:
- Variable evaluation (for example, `$it`, `$nu`, alias vars)
- Behaviour of whole stream vs per-item external execution
It should also make it easier for us to start introducing argument signatures
for external commands,
* Update run_external.rs
* Update run_external.rs
* Update run_external.rs
* Update run_external.rs
Co-authored-by: Jonathan Turner <jonathandturner@users.noreply.github.com>
2020-04-20 05:30:44 +02:00
|
|
|
empty: bool,
|
2019-07-03 22:31:15 +02:00
|
|
|
}
|
|
|
|
|
2021-04-06 18:19:43 +02:00
|
|
|
impl Iterator for InputStream {
|
|
|
|
type Item = Value;
|
|
|
|
|
|
|
|
fn next(&mut self) -> Option<Self::Item> {
|
|
|
|
self.values.next()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-07-03 22:31:15 +02:00
|
|
|
impl InputStream {
|
2020-01-07 22:00:01 +01:00
|
|
|
pub fn empty() -> InputStream {
|
Move external closer to internal (#1611)
* Refactor InputStream and affected commands.
First, making `values` private and leaning on the `Stream` implementation makes
consumes of `InputStream` less likely to have to change in the future, if we
change what an `InputStream` is internally.
Second, we're dropping `Option<InputStream>` as the input to pipelines,
internals, and externals. Instead, `InputStream.is_empty` can be used to check
for "emptiness". Empty streams are typically only ever used as the first input
to a pipeline.
* Add run_external internal command.
We want to push external commands closer to internal commands, eventually
eliminating the concept of "external" completely. This means we can consolidate
a couple of things:
- Variable evaluation (for example, `$it`, `$nu`, alias vars)
- Behaviour of whole stream vs per-item external execution
It should also make it easier for us to start introducing argument signatures
for external commands,
* Update run_external.rs
* Update run_external.rs
* Update run_external.rs
* Update run_external.rs
Co-authored-by: Jonathan Turner <jonathandturner@users.noreply.github.com>
2020-04-20 05:30:44 +02:00
|
|
|
InputStream {
|
2021-04-06 18:19:43 +02:00
|
|
|
values: Box::new(std::iter::empty()),
|
Move external closer to internal (#1611)
* Refactor InputStream and affected commands.
First, making `values` private and leaning on the `Stream` implementation makes
consumes of `InputStream` less likely to have to change in the future, if we
change what an `InputStream` is internally.
Second, we're dropping `Option<InputStream>` as the input to pipelines,
internals, and externals. Instead, `InputStream.is_empty` can be used to check
for "emptiness". Empty streams are typically only ever used as the first input
to a pipeline.
* Add run_external internal command.
We want to push external commands closer to internal commands, eventually
eliminating the concept of "external" completely. This means we can consolidate
a couple of things:
- Variable evaluation (for example, `$it`, `$nu`, alias vars)
- Behaviour of whole stream vs per-item external execution
It should also make it easier for us to start introducing argument signatures
for external commands,
* Update run_external.rs
* Update run_external.rs
* Update run_external.rs
* Update run_external.rs
Co-authored-by: Jonathan Turner <jonathandturner@users.noreply.github.com>
2020-04-20 05:30:44 +02:00
|
|
|
empty: true,
|
|
|
|
}
|
2020-01-07 22:00:01 +01:00
|
|
|
}
|
|
|
|
|
2020-05-16 05:18:24 +02:00
|
|
|
pub fn one(item: impl Into<Value>) -> InputStream {
|
2021-04-11 03:31:08 +02:00
|
|
|
InputStream {
|
|
|
|
values: Box::new(std::iter::once(item.into())),
|
|
|
|
empty: false,
|
|
|
|
}
|
2020-05-16 05:18:24 +02:00
|
|
|
}
|
|
|
|
|
2021-04-06 18:19:43 +02:00
|
|
|
pub fn into_vec(self) -> Vec<Value> {
|
2019-07-03 22:31:15 +02:00
|
|
|
self.values.collect()
|
|
|
|
}
|
|
|
|
|
Move external closer to internal (#1611)
* Refactor InputStream and affected commands.
First, making `values` private and leaning on the `Stream` implementation makes
consumes of `InputStream` less likely to have to change in the future, if we
change what an `InputStream` is internally.
Second, we're dropping `Option<InputStream>` as the input to pipelines,
internals, and externals. Instead, `InputStream.is_empty` can be used to check
for "emptiness". Empty streams are typically only ever used as the first input
to a pipeline.
* Add run_external internal command.
We want to push external commands closer to internal commands, eventually
eliminating the concept of "external" completely. This means we can consolidate
a couple of things:
- Variable evaluation (for example, `$it`, `$nu`, alias vars)
- Behaviour of whole stream vs per-item external execution
It should also make it easier for us to start introducing argument signatures
for external commands,
* Update run_external.rs
* Update run_external.rs
* Update run_external.rs
* Update run_external.rs
Co-authored-by: Jonathan Turner <jonathandturner@users.noreply.github.com>
2020-04-20 05:30:44 +02:00
|
|
|
pub fn is_empty(&self) -> bool {
|
|
|
|
self.empty
|
|
|
|
}
|
|
|
|
|
2021-04-06 18:19:43 +02:00
|
|
|
pub fn drain_vec(&mut self) -> Vec<Value> {
|
|
|
|
let mut output = vec![];
|
|
|
|
while let Some(x) = self.values.next() {
|
|
|
|
output.push(x);
|
|
|
|
}
|
|
|
|
output
|
2019-08-03 04:17:28 +02:00
|
|
|
}
|
|
|
|
|
2021-04-06 18:19:43 +02:00
|
|
|
pub fn from_stream(input: impl Iterator<Item = Value> + Send + Sync + 'static) -> InputStream {
|
2019-07-03 22:31:15 +02:00
|
|
|
InputStream {
|
2021-04-06 18:19:43 +02:00
|
|
|
values: Box::new(input),
|
Move external closer to internal (#1611)
* Refactor InputStream and affected commands.
First, making `values` private and leaning on the `Stream` implementation makes
consumes of `InputStream` less likely to have to change in the future, if we
change what an `InputStream` is internally.
Second, we're dropping `Option<InputStream>` as the input to pipelines,
internals, and externals. Instead, `InputStream.is_empty` can be used to check
for "emptiness". Empty streams are typically only ever used as the first input
to a pipeline.
* Add run_external internal command.
We want to push external commands closer to internal commands, eventually
eliminating the concept of "external" completely. This means we can consolidate
a couple of things:
- Variable evaluation (for example, `$it`, `$nu`, alias vars)
- Behaviour of whole stream vs per-item external execution
It should also make it easier for us to start introducing argument signatures
for external commands,
* Update run_external.rs
* Update run_external.rs
* Update run_external.rs
* Update run_external.rs
Co-authored-by: Jonathan Turner <jonathandturner@users.noreply.github.com>
2020-04-20 05:30:44 +02:00
|
|
|
empty: false,
|
2019-07-03 22:31:15 +02:00
|
|
|
}
|
|
|
|
}
|
2020-03-06 17:06:39 +01:00
|
|
|
|
2021-04-06 18:19:43 +02:00
|
|
|
pub fn collect_string(mut self, tag: Tag) -> Result<Tagged<String>, ShellError> {
|
2020-03-06 17:06:39 +01:00
|
|
|
let mut bytes = vec![];
|
|
|
|
let mut value_tag = tag.clone();
|
|
|
|
|
|
|
|
loop {
|
2021-04-06 18:19:43 +02:00
|
|
|
match self.values.next() {
|
2020-03-06 17:06:39 +01:00
|
|
|
Some(Value {
|
|
|
|
value: UntaggedValue::Primitive(Primitive::String(s)),
|
|
|
|
tag: value_t,
|
|
|
|
}) => {
|
|
|
|
value_tag = value_t;
|
|
|
|
bytes.extend_from_slice(&s.into_bytes());
|
|
|
|
}
|
|
|
|
Some(Value {
|
|
|
|
value: UntaggedValue::Primitive(Primitive::Binary(b)),
|
|
|
|
tag: value_t,
|
|
|
|
}) => {
|
|
|
|
value_tag = value_t;
|
|
|
|
bytes.extend_from_slice(&b);
|
|
|
|
}
|
2020-06-28 23:06:05 +02:00
|
|
|
Some(Value {
|
|
|
|
value: UntaggedValue::Primitive(Primitive::Nothing),
|
|
|
|
tag: value_t,
|
|
|
|
}) => {
|
|
|
|
value_tag = value_t;
|
|
|
|
}
|
2020-06-27 07:38:19 +02:00
|
|
|
Some(Value {
|
|
|
|
tag: value_tag,
|
|
|
|
value,
|
|
|
|
}) => {
|
2020-03-06 17:06:39 +01:00
|
|
|
return Err(ShellError::labeled_error_with_secondary(
|
|
|
|
"Expected a string from pipeline",
|
|
|
|
"requires string input",
|
|
|
|
tag,
|
2020-06-27 07:38:19 +02:00
|
|
|
format!(
|
|
|
|
"{} originates from here",
|
|
|
|
Type::from_value(&value).plain_string(100000)
|
|
|
|
),
|
2020-03-06 17:06:39 +01:00
|
|
|
value_tag,
|
|
|
|
))
|
|
|
|
}
|
|
|
|
None => break,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
match String::from_utf8(bytes) {
|
2021-04-06 18:19:43 +02:00
|
|
|
Ok(s) => Ok(s.tagged(value_tag)),
|
2020-03-06 17:06:39 +01:00
|
|
|
Err(_) => Err(ShellError::labeled_error_with_secondary(
|
|
|
|
"Expected a string from pipeline",
|
|
|
|
"requires string input",
|
|
|
|
tag,
|
|
|
|
"value originates from here",
|
|
|
|
value_tag,
|
|
|
|
)),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-04-06 18:19:43 +02:00
|
|
|
pub fn collect_binary(mut self, tag: Tag) -> Result<Tagged<Vec<u8>>, ShellError> {
|
2020-03-06 17:06:39 +01:00
|
|
|
let mut bytes = vec![];
|
|
|
|
let mut value_tag = tag.clone();
|
|
|
|
|
|
|
|
loop {
|
2021-04-06 18:19:43 +02:00
|
|
|
match self.values.next() {
|
2020-03-06 17:06:39 +01:00
|
|
|
Some(Value {
|
|
|
|
value: UntaggedValue::Primitive(Primitive::Binary(b)),
|
|
|
|
tag: value_t,
|
|
|
|
}) => {
|
|
|
|
value_tag = value_t;
|
|
|
|
bytes.extend_from_slice(&b);
|
|
|
|
}
|
|
|
|
Some(Value {
|
|
|
|
tag: value_tag,
|
2020-07-18 03:59:23 +02:00
|
|
|
value: _,
|
2020-03-06 17:06:39 +01:00
|
|
|
}) => {
|
|
|
|
return Err(ShellError::labeled_error_with_secondary(
|
|
|
|
"Expected binary from pipeline",
|
|
|
|
"requires binary input",
|
|
|
|
tag,
|
|
|
|
"value originates from here",
|
|
|
|
value_tag,
|
|
|
|
));
|
|
|
|
}
|
|
|
|
None => break,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Ok(bytes.tagged(value_tag))
|
|
|
|
}
|
2019-07-03 22:31:15 +02:00
|
|
|
}
|
|
|
|
|
2019-11-21 15:33:14 +01:00
|
|
|
impl From<VecDeque<Value>> for InputStream {
|
|
|
|
fn from(input: VecDeque<Value>) -> InputStream {
|
2019-07-03 22:31:15 +02:00
|
|
|
InputStream {
|
2021-04-06 18:19:43 +02:00
|
|
|
values: Box::new(input.into_iter()),
|
Move external closer to internal (#1611)
* Refactor InputStream and affected commands.
First, making `values` private and leaning on the `Stream` implementation makes
consumes of `InputStream` less likely to have to change in the future, if we
change what an `InputStream` is internally.
Second, we're dropping `Option<InputStream>` as the input to pipelines,
internals, and externals. Instead, `InputStream.is_empty` can be used to check
for "emptiness". Empty streams are typically only ever used as the first input
to a pipeline.
* Add run_external internal command.
We want to push external commands closer to internal commands, eventually
eliminating the concept of "external" completely. This means we can consolidate
a couple of things:
- Variable evaluation (for example, `$it`, `$nu`, alias vars)
- Behaviour of whole stream vs per-item external execution
It should also make it easier for us to start introducing argument signatures
for external commands,
* Update run_external.rs
* Update run_external.rs
* Update run_external.rs
* Update run_external.rs
Co-authored-by: Jonathan Turner <jonathandturner@users.noreply.github.com>
2020-04-20 05:30:44 +02:00
|
|
|
empty: false,
|
2019-07-03 22:31:15 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-11-21 15:33:14 +01:00
|
|
|
impl From<Vec<Value>> for InputStream {
|
|
|
|
fn from(input: Vec<Value>) -> InputStream {
|
2019-07-03 22:31:15 +02:00
|
|
|
InputStream {
|
2021-04-06 18:19:43 +02:00
|
|
|
values: Box::new(input.into_iter()),
|
Move external closer to internal (#1611)
* Refactor InputStream and affected commands.
First, making `values` private and leaning on the `Stream` implementation makes
consumes of `InputStream` less likely to have to change in the future, if we
change what an `InputStream` is internally.
Second, we're dropping `Option<InputStream>` as the input to pipelines,
internals, and externals. Instead, `InputStream.is_empty` can be used to check
for "emptiness". Empty streams are typically only ever used as the first input
to a pipeline.
* Add run_external internal command.
We want to push external commands closer to internal commands, eventually
eliminating the concept of "external" completely. This means we can consolidate
a couple of things:
- Variable evaluation (for example, `$it`, `$nu`, alias vars)
- Behaviour of whole stream vs per-item external execution
It should also make it easier for us to start introducing argument signatures
for external commands,
* Update run_external.rs
* Update run_external.rs
* Update run_external.rs
* Update run_external.rs
Co-authored-by: Jonathan Turner <jonathandturner@users.noreply.github.com>
2020-04-20 05:30:44 +02:00
|
|
|
empty: false,
|
2019-07-03 22:31:15 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2021-01-10 03:50:49 +01:00
|
|
|
|
2021-02-12 11:13:14 +01:00
|
|
|
#[allow(clippy::clippy::wrong_self_convention)]
|
2021-01-10 03:50:49 +01:00
|
|
|
pub trait ToInputStream {
|
|
|
|
fn to_input_stream(self) -> InputStream;
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T, U> ToInputStream for T
|
|
|
|
where
|
2021-04-06 18:19:43 +02:00
|
|
|
T: Iterator<Item = U> + Send + Sync + 'static,
|
2021-01-10 03:50:49 +01:00
|
|
|
U: Into<Result<nu_protocol::Value, nu_errors::ShellError>>,
|
|
|
|
{
|
|
|
|
fn to_input_stream(self) -> InputStream {
|
2021-04-06 18:19:43 +02:00
|
|
|
InputStream {
|
|
|
|
empty: false,
|
|
|
|
values: Box::new(self.map(|item| match item.into() {
|
|
|
|
Ok(result) => result,
|
|
|
|
Err(err) => match HasFallibleSpan::maybe_span(&err) {
|
|
|
|
Some(span) => nu_protocol::UntaggedValue::Error(err).into_value(span),
|
|
|
|
None => nu_protocol::UntaggedValue::Error(err).into_untagged_value(),
|
|
|
|
},
|
|
|
|
})),
|
|
|
|
}
|
2021-01-10 03:50:49 +01:00
|
|
|
}
|
|
|
|
}
|