command_macros_plugin/
lib.rs

1#![feature(proc_macro_span, proc_macro_diagnostic, proc_macro_def_site)]
2
3#![doc = include_str!("../README.md")]
4
5extern crate proc_macro;
6extern crate itertools;
7
8use itertools::Itertools;
9
10mod syntax;
11
12use proc_macro::{
13    TokenStream,
14    TokenTree,
15    Span,
16    Group,
17    Delimiter,
18    Literal,
19    Spacing,
20};
21
22use self::syntax::{
23    Expr,
24    Pat,
25    Stmt,
26    from_source,
27    new_ident,
28    new_spanned_ident,
29    new_block,
30    surround,
31};
32
33use std::iter::once;
34use std::iter::FromIterator;
35use std::collections::VecDeque;
36
37type Result<T> = ::std::result::Result<T, ()>;
38
39/// Full-featured macro for creating `Command`
40///
41/// Please read the syntax description in the crate's [documentation](index.html).
42///
43/// This macro is intended to be used via reexport in `command_macros`
44/// crate with a "nightly" feature enabled.
45///
46/// # Examples
47///
48/// ```
49/// #![feature(proc_macro_hygiene)]
50///
51/// // also reexported in extern crate command_macros;
52/// extern crate command_macros_plugin;
53/// 
54/// // also reexported as command_macros::command
55/// use command_macros_plugin::command;
56///
57/// fn main() {
58///     command!(echo foo --bar ((2+2))=4).status().unwrap();
59///     // should echo: foo --bar 4=4
60/// }
61/// ```
62///
63/// # Stability
64///
65/// This is an experimental, nightly-only version of `cmd!` macro,
66/// so it might break with a nightly update from time to time.
67/// However, it uses a new `proc_macro` interface rather than
68/// compiler internals, so the breakage shouldn't occur too often.
69///
70/// In future, when the `proc_macro` interface is stabilized,
71/// this macro should work on stable without significant changes.
72#[proc_macro]
73pub fn command(input: TokenStream) -> TokenStream {
74    match try_expand_command(input) {
75        Ok(stream) => stream,
76        Err(())    => "::std::process::Command::new(\"dummy\")".parse().unwrap(),
77    }
78}
79
80fn try_expand_command(input: TokenStream) -> Result<TokenStream> {
81    let trees = Parser::new(input).parse()?;
82    Ok(generate(trees)?.into_stream())
83}
84
85// Data -----------------------------------------------------------------------
86
87#[derive(Debug)]
88enum Condition {
89    Bool(Expr),
90    IfLet(TokenTree, Pat, TokenTree, Expr),
91}
92
93#[derive(Debug)]
94struct Spanned<T> {
95    elem: T,
96    span: Span,
97}
98
99#[allow(non_snake_case)]
100fn Spanned<T>(elem: T, span: Span) -> Spanned<T> {
101    Spanned { elem, span }
102}
103
104#[derive(Debug)]
105struct Block(Spanned<Vec<Tree>>);
106
107#[derive(Debug)]
108enum Splice {
109    Word(String), // x
110    Literal(Literal), // 'x', "x"
111    ToStr(Expr), // (x)
112    AsOsStr(Expr), // ((x))
113}
114
115#[derive(Debug)]
116enum Arg {
117    Single(Spanned<Splice>),
118    Touching(Vec<Spanned<Splice>>),
119}
120
121#[derive(Debug)]
122struct For {
123    for_span: Span,
124    pat: Pat,
125    in_tt: TokenTree,
126    expr: Expr,
127    block: Block,
128}
129
130#[derive(Debug)]
131struct If {
132    if_span: Span,
133    cond: Condition,
134    then_block: Block,
135    else_block: Block,
136}
137
138type Arm = (Pat, (TokenTree, TokenTree), Block);
139
140#[derive(Debug)]
141struct Match {
142    match_span: Span,
143    expr: Expr,
144    block_span: Span,
145    arms: Vec<Arm>,
146}
147
148#[derive(Debug)]
149enum Tree {
150    Arg(Arg),
151    Args(Spanned<Expr>), // [x]
152    Cmd(Expr), // {x}
153    If(If),
154    Match(Match),
155    For(For),
156}
157
158impl Arg {
159    fn span(&self) -> Span {
160        match self {
161            Arg::Single(splice) => splice.span,
162            Arg::Touching(splices) => {
163                splices.first().unwrap().span.join(
164                    splices.last().unwrap().span
165                ).unwrap()
166            }
167        }
168    }
169
170    fn into_vec(self) -> Vec<Spanned<Splice>> {
171        match self {
172            Arg::Single(splice) => vec![splice],
173            Arg::Touching(splices) => splices,
174        }
175    }
176}
177
178impl Tree {
179    fn span(&self) -> Span {
180        match self {
181            Tree::Arg(arg) => arg.span(),
182            Tree::Args(args) => args.span,
183            Tree::Cmd(expr) => expr.span(),
184            Tree::If(if_) => if_.span(),
185            Tree::Match(match_) => match_.span(),
186            Tree::For(for_) => for_.span(),
187        }
188    }
189}
190
191impl From<Arg> for Tree {
192    fn from(arg: Arg) -> Tree {
193        Tree::Arg(arg)
194    }
195}
196
197impl From<Spanned<Splice>> for Arg {
198    fn from(splice: Spanned<Splice>) -> Arg {
199        Arg::Single(splice)
200    }
201}
202
203impl From<Spanned<Splice>> for Tree {
204    fn from(splice: Spanned<Splice>) -> Tree {
205        Arg::from(splice).into()
206    }
207}
208
209impl Block {
210    fn new(trees: Vec<Tree>, span: Span) -> Block { Block(Spanned(trees, span)) }
211}
212
213impl If {
214    fn span(&self) -> Span {
215        let last_span = if self.else_block.0.elem.is_empty() {
216            self.then_block.0.span
217        } else {
218            self.else_block.0.span
219        };
220        self.if_span.join(last_span).unwrap_or(self.if_span)
221    }
222}
223
224impl For {
225    fn span(&self) -> Span {
226        self.for_span.join(self.block.0.span).unwrap_or(self.for_span)
227    }
228}
229
230impl Match {
231    fn span(&self) -> Span {
232        self.match_span.join(self.block_span).unwrap_or(self.match_span)
233    }
234}
235
236// Generation -----------------------------------------------------------------
237
238fn generate(mut trees: Vec<Tree>) -> Result<Expr> {
239    if trees.is_empty() {
240        Span::call_site().error("This macro needs at least the command name").emit();
241        return Err(());
242    }
243
244    let cmd_tree = trees.remove(0);
245    let cmd_expr: Expr = match cmd_tree {
246        Tree::Arg(arg) => {
247            let span = arg.span();
248            let str_expr = generate_os_str(arg)?;
249            Expr::call(from_source("::std::process::Command::new", span), str_expr, span)
250        }
251        Tree::Cmd(cmd) => cmd,
252        other => {
253            other.span().error("Command name should be `cmd` `(cmd_name_expr)` or `{Command_expr}`").emit();
254            return Err(())
255        }
256    };
257
258    let cmd_var: TokenTree = new_ident("cmd");
259
260    let init_stmt = Stmt::new_let(&cmd_var, cmd_expr);
261    let mut stmts: Vec<Stmt> = vec![init_stmt];
262    stmts.extend(generate_stmts(&cmd_var, trees)?);
263
264    let block = Expr::block(stmts, Expr::from_tt(cmd_var), Span::call_site());
265
266    Ok(block)
267}
268
269fn generate_stmts(cmd_var: &TokenTree, trees: Vec<Tree>) -> Result<Vec<Stmt>> {
270    trees
271        .into_iter()
272        .map(|tree| {
273            match tree {
274                Tree::Arg(arg) => generate_arg(cmd_var, arg),
275                Tree::Args(args) => generate_args(cmd_var, args),
276                Tree::For(pieces) => generate_for(cmd_var, pieces),
277                Tree::If(pieces) => generate_if(cmd_var, pieces),
278                Tree::Match(pieces) => generate_match(cmd_var, pieces),
279                Tree::Cmd(expr) => {
280                    expr.span()
281                        .error("Command block could be used only at the beginning")
282                        .emit();
283                    return Err(())
284                }
285            }
286        })
287        .collect()
288}
289
290fn generate_block(cmd_var: &TokenTree, block: Block) -> Result<TokenTree> {
291    let stmts = generate_stmts(cmd_var, block.0.elem)?;
292    Ok(new_block(stmts, block.0.span))
293}
294
295fn generate_arg(cmd: &TokenTree, arg: Arg) -> Result<Stmt> {
296    let span = arg.span();
297    let os_str = generate_os_str(arg)?;
298    let call_expr = Expr::call_method_on(cmd, "arg", os_str, span);
299    Ok(call_expr.into_stmt())
300}
301
302fn generate_args(cmd: &TokenTree, Spanned { elem: expr, span }: Spanned<Expr>) -> Result<Stmt> {
303    let call_expr = Expr::call_method_on(cmd, "args", expr, span);
304    Ok(call_expr.into_stmt())
305}
306
307fn generate_for(cmd_var: &TokenTree, For { for_span, pat, in_tt, expr, block }: For) -> Result<Stmt> {
308    let stream = once(new_spanned_ident("for", for_span))
309        .chain(pat.0)
310        .chain(once(in_tt))
311        .chain(expr.into_stream())
312        .chain(once(generate_block(cmd_var, block)?))
313        .collect();
314    Ok(Stmt::from_stream(stream))
315}
316
317fn generate_if(cmd_var: &TokenTree, If { if_span, cond, then_block, else_block }: If) -> Result<Stmt> {
318    let cond_stream = match cond {
319        Condition::Bool(expr)                          => expr.into_stream(),
320        Condition::IfLet(let_tt, pat, equals_tt, expr) => {
321            once(let_tt)
322                .chain(pat.0)
323                .chain(once(equals_tt))
324                .chain(expr.into_stream())
325                .collect()
326        }
327    };
328    let stream = once(new_spanned_ident("if", if_span))
329        .chain(cond_stream)
330        .chain(once(generate_block(cmd_var, then_block)?))
331        .chain(once(new_spanned_ident("else", Span::call_site())))
332        .chain(once(generate_block(cmd_var, else_block)?))
333        .collect();
334    Ok(Stmt::from_stream(stream))
335}
336
337fn generate_match(cmd_var: &TokenTree, Match { match_span, expr, block_span, arms }: Match) -> Result<Stmt> {
338    let mut arm_stream = Vec::new();
339    for arm in arms {
340        arm_stream.extend(generate_arm(cmd_var, arm)?);
341    }
342    let arm_stream = arm_stream.into_iter().collect();
343
344    let block = surround(arm_stream, Delimiter::Brace, block_span);
345
346    let stream = once(new_spanned_ident("match", match_span))
347        .chain(expr.into_stream())
348        .chain(once(block))
349        .collect();
350
351    Ok(Stmt::from_stream(stream))
352}
353
354fn generate_arm(cmd_var: &TokenTree, (pat, arrows, block): Arm) -> Result<impl Iterator<Item=TokenTree>> {
355    Ok(
356        pat.0.into_iter()
357            .chain(once(arrows.0))
358            .chain(once(arrows.1))
359            .chain(once(generate_block(cmd_var, block)?))
360    )
361}
362
363fn generate_splice(Spanned { elem: splice, span }: Spanned<Splice>) -> Result<Expr> {
364    let expr = match splice {
365        Splice::Word(word) => Expr::string_literal(&word),
366        Splice::Literal(lit) => generate_literal(lit)?,
367        Splice::AsOsStr(expr) => Expr::reference(expr, span),
368        Splice::ToStr(expr) => Expr::call(
369            from_source("ToString::to_string", span),
370            Expr::reference(expr, span),
371            span
372        ),
373    };
374    Ok(expr)
375}
376
377fn generate_literal(literal: Literal) -> Result<Expr> {
378    let repr = literal.to_string();
379    if repr.starts_with("'") {
380        literal.span().error("Use string literals instead").emit();
381        Ok(Expr::string_literal("<error>"))
382    } else if repr.contains("\"") {
383        Ok(Expr::from_tt(literal.into()))
384    } else if repr.contains("'") {
385        literal.span().error("Unsupported literal").emit();
386        Ok(Expr::string_literal("<error>"))
387    } else {
388        Ok(Expr::string_literal(&literal.to_string()))
389    }
390}
391
392fn generate_os_str(arg: Arg) -> Result<Expr> {
393    let full_span = arg.span();
394    match arg {
395        Arg::Single(splice) => generate_splice(splice),
396        Arg::Touching(splices) => {
397            let os_string = Expr::from_source("::std::ffi::OsString::new()", full_span);
398            let buf_var = new_ident("buf");
399            let init_stmt = Stmt::new_let(&buf_var, os_string);
400            let mut stmts = vec![init_stmt];
401
402            for splice in splices {
403                let span = splice.span;
404                stmts.push(Expr::call_method_on(
405                    &buf_var,
406                    "push",
407                    Expr::reference(generate_splice(splice)?, span),
408                    span,
409                ).into_stmt())
410            }
411
412            Ok(Expr::block(stmts, Expr::from_tt(buf_var), full_span))
413        }
414    }
415}
416
417// Parsing --------------------------------------------------------------------
418
419#[derive(Debug)]
420struct Parser {
421    last_span: Option<Span>,
422    stream: VecDeque<TokenTree>,
423}
424
425impl Parser {
426    pub fn new(stream: TokenStream) -> Self {
427        Parser {
428            stream: VecDeque::from_iter(stream),
429            last_span: None
430        }
431    }
432
433    pub fn parse(&mut self) -> Result<Vec<Tree>> {
434        let trees = self.parse_trees()?;
435        Ok(join_touching(trees))
436    }
437}
438
439fn join_touching(trees: Vec<Tree>) -> Vec<Tree> {
440    trees.into_iter()
441        .coalesce(|left, right| {
442            match (left, right) {
443                (Tree::Arg(left), Tree::Arg(right)) => {
444                    if are_separated_spans(left.span(), right.span()) {
445                        Err((left.into(), right.into()))
446                    } else {
447                        let mut splices = left.into_vec();
448                        let right = match right {
449                            Arg::Single(s) => s,
450                            _              => unreachable!(),
451                        };
452                        splices.push(right);
453                        Ok(Arg::Touching(splices).into())
454                    }
455                }
456                (left, right) => Err((left, right))
457            }
458        })
459        .collect()
460}
461
462impl Parser {
463    fn peek(&self) -> Option<&TokenTree> {
464        self.stream.front()
465    }
466
467    fn peek_two(&self) -> Option<(&TokenTree, &TokenTree)> {
468        match (self.stream.get(0), self.stream.get(1)) {
469            (Some(first), Some(second)) => Some((first, second)),
470            _ => None
471        }
472    }
473
474    fn next(&mut self) -> Option<TokenTree> {
475        self.stream.pop_front().map(|tt| {
476            self.last_span = Some(tt.span());
477            tt
478        })
479    }
480
481    fn parse_block(&mut self) -> Result<Block> {
482        let last_span = self.last_span;
483        let orig_block = match self.next() {
484            Some(TokenTree::Group(group)) => group,
485            _ => {
486                last_span.unwrap_or(Span::call_site())
487                    .error("Expected a {} block after this token")
488                    .emit();
489                return Err(())
490            }
491        };
492        let trees = Parser::new(orig_block.stream()).parse()?;
493        Ok(Block::new(trees, orig_block.span()))
494    }
495
496    fn parse_trees(&mut self) -> Result<Vec<Tree>> {
497        let mut trees = Vec::new();
498        while !self.stream.is_empty() {
499            trees.push(self.parse_tree()?);
500        }
501        Ok(trees)
502    }
503
504    fn parse_tree(&mut self) -> Result<Tree> {
505        let previous_span = self.last_span;
506        let tt = self.next().unwrap();
507        let span = tt.span();
508        match tt {
509            TokenTree::Group(group) => Ok(Parser::parse_splice(group)?.into()),
510
511            TokenTree::Ident(ident) => {
512                let next_span = self.peek().map(|next| next.span());
513
514                let word = ident.to_string();
515                let warn_keyword = || {
516                    if !is_separated_span(previous_span, span, next_span) {
517                        span.warning(format!("Keyword `{}` not separated by whitespace", word))
518                            .note("Keywords should be separated by whitespace to avoid confusion")
519                            .help("To interpret as a string, surround it with quotes")
520                            .emit();
521                    }
522                };
523
524                match word.as_str() {
525                    "let" => {
526                        warn_keyword();
527                        span.error("Let statements are not supported")
528                            .note("You can emulate them with `match`")
529                            .emit();
530                        Err(())
531                    }
532                    "if" => {
533                        warn_keyword();
534                        self.parse_if(span)
535                    }
536                    "for" => {
537                        warn_keyword();
538                        self.parse_for(span)
539                    }
540                    "match" => {
541                        warn_keyword();
542                        self.parse_match(span)
543                    }
544                    word => {
545                        Ok(Spanned(Splice::Word(word.into()), span).into())
546                    }
547                }
548            }
549
550            TokenTree::Literal(lit) => Ok(Spanned(Splice::Literal(lit), span).into()),
551
552            TokenTree::Punct(punct) => {
553                match punct.as_char() {
554                    '$' => {
555                        punct.span()
556                            .error("Dollar sign interpollation is not supported")
557                            .help("To insert a variable, use `(var)` or `((var))`")
558                            .emit();
559                    }
560                    '>' | '<' => {
561                        punct.span().error("File redirection is not supported").emit();
562                    }
563                    '|' => {
564                        punct.span().error("Pipe redirection is not supported").emit();
565                    }
566                    '&' => {
567                        punct.span().error("The `&` and `&&` operators are not supported").emit();
568                    }
569                    ';' => {
570                        punct.span()
571                            .error("Unexpected semicolon")
572                            .help("To interpret literally, surround in quotes")
573                            .note("Semicolon is not needed in this macro")
574                            .emit();
575                    }
576                    ch => {
577                        return Ok(Spanned(Splice::Word(ch.to_string()), span).into());
578                    }
579                }
580                Err(())
581            }
582        }
583    }
584
585    fn parse_splice(mut group: Group) -> Result<Tree> {
586        let span = group.span();
587        let stream = group.stream();
588
589        let tree = match group.delimiter() {
590            Delimiter::Brace if is_really_empty(&group) => {
591                return Ok(Spanned(Splice::Word("{}".into()), span).into())
592            }
593            Delimiter::Brace => Tree::Cmd(Expr::from_stream(stream)),
594            Delimiter::Parenthesis => {
595                match try_into_singleton(&stream) {
596                    Some(TokenTree::Group(ref inner))
597                        if inner.delimiter() == Delimiter::Parenthesis
598                            => {
599                                // The clone needed because of pattern guard :(
600                                group = inner.clone();
601                                Spanned(Splice::ToStr(Expr::from_stream(group.stream())), span).into()
602                            }
603                    _       => Spanned(Splice::AsOsStr(Expr::from_stream(stream)), span).into(),
604                }
605            }
606            Delimiter::Bracket => Tree::Args(Spanned(Expr::from_stream(stream), span)),
607            Delimiter::None => {
608                span.error("You've probably tried to use a nested macro.\
609                           This is not supported").emit();
610                return Err(())
611            }
612        };
613
614        if group.stream().is_empty() {
615            group.span().error("Rust expression expected inside this block").emit();
616            return Err(())
617        }
618
619        Ok(tree)
620    }
621
622    fn parse_if(&mut self, if_span: Span) -> Result<Tree> {
623        let cond = if self.is_ident_next("let") {
624            let let_tt = self.next().unwrap();
625            let pat = Pat(self.parse_until(
626                |parser| match parser.peek() {
627                    Some(TokenTree::Punct(punct))
628                        if punct.as_char() == '=' && punct.spacing() == Spacing::Alone => true,
629                    _ => false,
630                },
631                "`=`",
632                "a pattern",
633            )?);
634            let equals_tt = self.next().unwrap();
635            let expr = self.parse_until_block()?;
636            Condition::IfLet(let_tt, pat, equals_tt, expr)
637        } else {
638            Condition::Bool(self.parse_until_block()?)
639        };
640        let then_block = self.parse_block()?;
641
642        let else_block = if self.is_ident_next("else") {
643            let _ = self.next().unwrap();
644            if self.is_block_next() {
645                self.parse_block()?
646            } else if self.is_ident_next("if") {
647                let if_tt = self.next().unwrap();
648                let inner_if = self.parse_if(if_tt.span())?;
649                let inner_span = inner_if.span();
650                Block::new(vec![inner_if], inner_span).into()
651            } else {
652                self.last_span.unwrap()
653                    .error("Expected `if` or {} block after this `else`")
654                    .emit();
655                return Err(());
656            }
657        } else {
658            Block::new(Vec::new(), Span::def_site())
659        };
660
661        Ok(Tree::If(If { if_span, cond, then_block, else_block }))
662    }
663
664    fn parse_for(&mut self, for_span: Span) -> Result<Tree> {
665        let pat = Pat(self.parse_until_ident("in", "a pattern")?);
666        let in_tt = self.next().unwrap();
667        let expr = self.parse_until_block()?;
668        let block = self.parse_block()?;
669        Ok(Tree::For(For { for_span, pat, in_tt, expr, block }))
670    }
671
672    fn parse_match(&mut self, match_span: Span) -> Result<Tree> {
673        use self::Spacing::{Alone, Joint};
674
675        let expr = self.parse_until_block()?;
676
677        let block = match self.next() {
678            Some(TokenTree::Group(group)) => group,
679            _ => unreachable!(),
680        };
681        let block_span = block.span();
682
683        // Prevent accidental use of outer parser.
684        let _dont_use_self = self;
685        let mut parser = Parser::new(block.stream());
686        let mut arms = Vec::new();
687
688        while !parser.stream.is_empty() {
689            let pat = Pat(parser.parse_until(
690                    |parser| match parser.peek_two() {
691                        Some((TokenTree::Punct(left), TokenTree::Punct(right)))
692                            if left.as_char() == '=' && right.as_char() == '>'
693                                && left.spacing() == Joint && right.spacing() == Alone => true,
694                                    _ => false,
695                    },
696                    "`=>`",
697                    "a pattern",
698                    )?);
699            let arrow = (
700                parser.next().unwrap(),
701                parser.next().unwrap(),
702            );
703            let block = parser.parse_block()?;
704            arms.push((pat, arrow, block))
705        }
706
707        drop(_dont_use_self);
708
709        Ok(Tree::Match(Match { match_span, expr, block_span, arms }))
710    }
711
712    fn parse_until_block(&mut self) -> Result<Expr> {
713        if self.is_block_next() {
714            return Ok( Expr::from_tt(self.next().unwrap()) )
715        }
716        let stream = self.parse_until(Parser::is_block_next, "{} block", "an expression")?;
717        Ok(Expr::from_stream(stream))
718    }
719
720    fn is_block_next(&self) -> bool {
721        match self.peek() {
722            Some(&TokenTree::Group(ref group)) if group.delimiter() == Delimiter::Brace => true,
723            _ => false,
724        }
725    }
726
727    fn is_ident_next(&self, expected: &str) -> bool {
728        match self.peek() {
729            Some(TokenTree::Ident(actual)) if actual.to_string() == expected => true,
730            _ => false,
731        }
732    }
733
734    fn parse_until_ident(&mut self, until_ident: &str, what: &str) -> Result<TokenStream> {
735        self.parse_until(
736            |parser| parser.is_ident_next(until_ident),
737            &format!("`{}`", until_ident),
738            what
739        )
740    }
741
742    fn parse_until<F>(&mut self, until: F, until_str: &str, what: &str) -> Result<TokenStream>
743    where F: Fn(&Parser) -> bool
744    {
745        let mut tts = Vec::new();
746
747        while !until(self) {
748            match self.next() {
749                Some(tt) => tts.push(tt),
750                None => {
751                    self.last_span.unwrap()
752                        .error(format!("Found end of macro when looking for {}", until_str))
753                        .emit();
754                    return Err(())
755                }
756            }
757        }
758
759        if tts.is_empty() {
760            self.peek().unwrap().span()
761                .error(format!("Expected {} before {}", what, until_str))
762                .emit();
763            return Err(())
764        }
765
766        Ok(tts.into_iter().collect())
767    }
768}
769
770fn are_separated_spans(left: Span, right: Span) -> bool {
771    left.end().line != right.start().line ||
772    left.end().column < right.start().column
773}
774
775fn is_separated_span(left: Option<Span>, this: Span, right: Option<Span>) -> bool {
776    left.map_or(true, |left| are_separated_spans(left, this)) &&
777    right.map_or(true, |right| are_separated_spans(this, right))
778}
779
780fn is_really_empty(group: &Group) -> bool {
781    let span = group.span();
782    let start = span.start();
783    let end = span.end();
784    group.stream().is_empty() && start.line == end.line && start.column + 2 == end.column
785}
786
787fn try_into_singleton(stream: &TokenStream) -> Option<TokenTree> {
788    let mut stream = stream.clone().into_iter();
789    let tt = stream.next()?;
790    match stream.next() {
791        None => Some(tt),
792        _    => None
793    }
794}