1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
use env::{StringWrapper, VariableEnvironment};
use future::{Async, EnvFuture, Poll};
use eval::{Fields, TildeExpansion, WordEval, WordEvalConfig};
use std::borrow::Borrow;
use std::iter::Fuse;
use std::mem;
pub fn double_quoted<W, I, E: ?Sized>(words: I)
-> DoubleQuoted<W::EvalResult, W, W::EvalFuture, I::IntoIter>
where W: WordEval<E>,
I: IntoIterator<Item = W>,
{
DoubleQuoted {
fields: Vec::new(),
cur_field: None,
future: None,
rest: words.into_iter().fuse(),
}
}
#[must_use = "futures do nothing unless polled"]
#[derive(Debug)]
pub struct DoubleQuoted<T, W, F, I> where I: Iterator<Item = W> {
fields: Vec<T>,
cur_field: Option<String>,
future: Option<F>,
rest: Fuse<I>,
}
impl<T, W, F, I> DoubleQuoted<T, W, F, I> where I: Iterator<Item = W> {
fn append_to_cur_field(&mut self, t: T) where T: StringWrapper {
match self.cur_field {
Some(ref mut cur) => cur.push_str(t.as_str()),
None => self.cur_field = Some(t.into_owned()),
}
}
}
impl<T, W, I, E: ?Sized> EnvFuture<E> for DoubleQuoted<T, W, W::EvalFuture, I>
where T: StringWrapper,
W: WordEval<E, EvalResult = T>,
I: Iterator<Item = W>,
E: VariableEnvironment<Var = T>,
E::VarName: Borrow<String>,
{
type Item = Fields<T>;
type Error = W::Error;
fn poll(&mut self, env: &mut E) -> Poll<Self::Item, Self::Error> {
loop {
if self.future.is_none() {
if let Some(w) = self.rest.next() {
let cfg = WordEvalConfig {
tilde_expansion: TildeExpansion::None,
split_fields_further: false,
};
self.future = Some(w.eval_with_config(env, cfg));
}
}
let next = match self.future {
None => {
self.cur_field.take().map(|s| self.fields.push(s.into()));
let fields = mem::replace(&mut self.fields, Vec::new());
return Ok(Async::Ready(fields.into()));
}
Some(ref mut f) => try_ready!(f.poll(env)),
};
self.future = None;
match next {
Fields::Zero => continue,
Fields::Single(s) => self.append_to_cur_field(s),
f@Fields::Split(_) |
f@Fields::Star(_) => self.append_to_cur_field(f.join_with_ifs(env)),
Fields::At(v) => {
if !v.is_empty() {
let mut iter = v.into_iter().fuse();
iter.next().map(|s| self.append_to_cur_field(s));
self.cur_field.take().map(|s| self.fields.push(s.into()));
let mut last = None;
for next in iter {
self.fields.extend(last.take());
last = Some(next);
}
last.map(|s| self.append_to_cur_field(s));
}
},
}
}
}
fn cancel(&mut self, env: &mut E) {
self.future.as_mut().map(|f| f.cancel(env));
}
}