use crate::{Config, PipelineData, ShellError, Signals, Span, Value};
use std::fmt::Debug;
pub type ValueIterator = Box<dyn Iterator<Item = Value> + Send + 'static>;
pub struct ListStream {
stream: ValueIterator,
span: Span,
caller_spans: Vec<Span>,
}
impl ListStream {
pub fn new(
iter: impl Iterator<Item = Value> + Send + 'static,
span: Span,
signals: Signals,
) -> Self {
Self {
stream: Box::new(InterruptIter::new(iter, signals)),
span,
caller_spans: vec![],
}
}
pub fn span(&self) -> Span {
self.span
}
pub fn push_caller_span(&mut self, span: Span) {
if span != self.span {
self.caller_spans.push(span)
}
}
pub fn get_caller_spans(&self) -> &Vec<Span> {
&self.caller_spans
}
pub fn with_span(mut self, span: Span) -> Self {
self.span = span;
self
}
pub fn into_inner(self) -> ValueIterator {
self.stream
}
pub fn next_value(&mut self) -> Option<Value> {
self.stream.next()
}
pub fn into_string(self, separator: &str, config: &Config) -> String {
self.into_iter()
.map(|val| val.to_expanded_string(", ", config))
.collect::<Vec<String>>()
.join(separator)
}
pub fn into_value(self) -> Result<Value, ShellError> {
Ok(Value::list(
self.stream
.map(Value::unwrap_error)
.collect::<Result<_, _>>()?,
self.span,
))
}
pub fn into_debug_value(self) -> Value {
Value::list(self.stream.collect(), self.span)
}
pub fn drain(self) -> Result<(), ShellError> {
for next in self {
if let Value::Error { error, .. } = next {
return Err(*error);
}
}
Ok(())
}
pub fn modify<I>(self, f: impl FnOnce(ValueIterator) -> I) -> Self
where
I: Iterator<Item = Value> + Send + 'static,
{
Self {
stream: Box::new(f(self.stream)),
span: self.span,
caller_spans: self.caller_spans,
}
}
pub fn map(self, mapping: impl FnMut(Value) -> Value + Send + 'static) -> Self {
self.modify(|iter| iter.map(mapping))
}
}
impl Debug for ListStream {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("ListStream").finish()
}
}
impl IntoIterator for ListStream {
type Item = Value;
type IntoIter = IntoIter;
fn into_iter(self) -> Self::IntoIter {
IntoIter {
stream: self.into_inner(),
}
}
}
impl From<ListStream> for PipelineData {
fn from(stream: ListStream) -> Self {
Self::list_stream(stream, None)
}
}
pub struct IntoIter {
stream: ValueIterator,
}
impl Iterator for IntoIter {
type Item = Value;
fn next(&mut self) -> Option<Self::Item> {
self.stream.next()
}
}
struct InterruptIter<I: Iterator> {
iter: I,
signals: Signals,
}
impl<I: Iterator> InterruptIter<I> {
fn new(iter: I, signals: Signals) -> Self {
Self { iter, signals }
}
}
impl<I: Iterator> Iterator for InterruptIter<I> {
type Item = <I as Iterator>::Item;
fn next(&mut self) -> Option<Self::Item> {
if self.signals.interrupted() {
None
} else {
self.iter.next()
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.iter.size_hint()
}
}