|  | // Copyright 2012-2016 The Rust Project Developers. See the COPYRIGHT | 
|  | // file at the top-level directory of this distribution and at | 
|  | // http://rust-lang.org/COPYRIGHT. | 
|  | // | 
|  | // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or | 
|  | // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license | 
|  | // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your | 
|  | // option. This file may not be copied, modified, or distributed | 
|  | // except according to those terms. | 
|  |  | 
|  | //! # Token Streams | 
|  | //! | 
|  | //! `TokenStream`s represent syntactic objects before they are converted into ASTs. | 
|  | //! A `TokenStream` is, roughly speaking, a sequence (eg stream) of `TokenTree`s, | 
|  | //! which are themselves a single `Token` or a `Delimited` subsequence of tokens. | 
|  | //! | 
|  | //! ## Ownership | 
|  | //! `TokenStreams` are persistent data structures constructed as ropes with reference | 
|  | //! counted-children. In general, this means that calling an operation on a `TokenStream` | 
|  | //! (such as `slice`) produces an entirely new `TokenStream` from the borrowed reference to | 
|  | //! the original. This essentially coerces `TokenStream`s into 'views' of their subparts, | 
|  | //! and a borrowed `TokenStream` is sufficient to build an owned `TokenStream` without taking | 
|  | //! ownership of the original. | 
|  |  | 
|  | use syntax_pos::{BytePos, Span, DUMMY_SP}; | 
|  | use ext::base; | 
|  | use ext::tt::{macro_parser, quoted}; | 
|  | use parse::Directory; | 
|  | use parse::token::{self, Token}; | 
|  | use print::pprust; | 
|  | use serialize::{Decoder, Decodable, Encoder, Encodable}; | 
|  | use util::RcSlice; | 
|  |  | 
|  | use std::{fmt, iter, mem}; | 
|  | use std::hash::{self, Hash}; | 
|  |  | 
|  | /// A delimited sequence of token trees | 
|  | #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] | 
|  | pub struct Delimited { | 
|  | /// The type of delimiter | 
|  | pub delim: token::DelimToken, | 
|  | /// The delimited sequence of token trees | 
|  | pub tts: ThinTokenStream, | 
|  | } | 
|  |  | 
|  | impl Delimited { | 
|  | /// Returns the opening delimiter as a token. | 
|  | pub fn open_token(&self) -> token::Token { | 
|  | token::OpenDelim(self.delim) | 
|  | } | 
|  |  | 
|  | /// Returns the closing delimiter as a token. | 
|  | pub fn close_token(&self) -> token::Token { | 
|  | token::CloseDelim(self.delim) | 
|  | } | 
|  |  | 
|  | /// Returns the opening delimiter as a token tree. | 
|  | pub fn open_tt(&self, span: Span) -> TokenTree { | 
|  | let open_span = if span == DUMMY_SP { | 
|  | DUMMY_SP | 
|  | } else { | 
|  | span.with_hi(span.lo() + BytePos(self.delim.len() as u32)) | 
|  | }; | 
|  | TokenTree::Token(open_span, self.open_token()) | 
|  | } | 
|  |  | 
|  | /// Returns the closing delimiter as a token tree. | 
|  | pub fn close_tt(&self, span: Span) -> TokenTree { | 
|  | let close_span = if span == DUMMY_SP { | 
|  | DUMMY_SP | 
|  | } else { | 
|  | span.with_lo(span.hi() - BytePos(self.delim.len() as u32)) | 
|  | }; | 
|  | TokenTree::Token(close_span, self.close_token()) | 
|  | } | 
|  |  | 
|  | /// Returns the token trees inside the delimiters. | 
|  | pub fn stream(&self) -> TokenStream { | 
|  | self.tts.clone().into() | 
|  | } | 
|  | } | 
|  |  | 
|  | /// When the main rust parser encounters a syntax-extension invocation, it | 
|  | /// parses the arguments to the invocation as a token-tree. This is a very | 
|  | /// loose structure, such that all sorts of different AST-fragments can | 
|  | /// be passed to syntax extensions using a uniform type. | 
|  | /// | 
|  | /// If the syntax extension is an MBE macro, it will attempt to match its | 
|  | /// LHS token tree against the provided token tree, and if it finds a | 
|  | /// match, will transcribe the RHS token tree, splicing in any captured | 
|  | /// `macro_parser::matched_nonterminals` into the `SubstNt`s it finds. | 
|  | /// | 
|  | /// The RHS of an MBE macro is the only place `SubstNt`s are substituted. | 
|  | /// Nothing special happens to misnamed or misplaced `SubstNt`s. | 
|  | #[derive(Debug, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash)] | 
|  | pub enum TokenTree { | 
|  | /// A single token | 
|  | Token(Span, token::Token), | 
|  | /// A delimited sequence of token trees | 
|  | Delimited(Span, Delimited), | 
|  | } | 
|  |  | 
|  | impl TokenTree { | 
|  | /// Use this token tree as a matcher to parse given tts. | 
|  | pub fn parse(cx: &base::ExtCtxt, mtch: &[quoted::TokenTree], tts: TokenStream) | 
|  | -> macro_parser::NamedParseResult { | 
|  | // `None` is because we're not interpolating | 
|  | let directory = Directory { | 
|  | path: cx.current_expansion.module.directory.clone(), | 
|  | ownership: cx.current_expansion.directory_ownership, | 
|  | }; | 
|  | macro_parser::parse(cx.parse_sess(), tts, mtch, Some(directory), true) | 
|  | } | 
|  |  | 
|  | /// Check if this TokenTree is equal to the other, regardless of span information. | 
|  | pub fn eq_unspanned(&self, other: &TokenTree) -> bool { | 
|  | match (self, other) { | 
|  | (&TokenTree::Token(_, ref tk), &TokenTree::Token(_, ref tk2)) => tk == tk2, | 
|  | (&TokenTree::Delimited(_, ref dl), &TokenTree::Delimited(_, ref dl2)) => { | 
|  | dl.delim == dl2.delim && | 
|  | dl.stream().trees().zip(dl2.stream().trees()).all(|(tt, tt2)| tt.eq_unspanned(&tt2)) | 
|  | } | 
|  | (_, _) => false, | 
|  | } | 
|  | } | 
|  |  | 
|  | /// Retrieve the TokenTree's span. | 
|  | pub fn span(&self) -> Span { | 
|  | match *self { | 
|  | TokenTree::Token(sp, _) | TokenTree::Delimited(sp, _) => sp, | 
|  | } | 
|  | } | 
|  |  | 
|  | /// Modify the `TokenTree`'s span inplace. | 
|  | pub fn set_span(&mut self, span: Span) { | 
|  | match *self { | 
|  | TokenTree::Token(ref mut sp, _) | TokenTree::Delimited(ref mut sp, _) => { | 
|  | *sp = span; | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | /// Indicates if the stream is a token that is equal to the provided token. | 
|  | pub fn eq_token(&self, t: Token) -> bool { | 
|  | match *self { | 
|  | TokenTree::Token(_, ref tk) => *tk == t, | 
|  | _ => false, | 
|  | } | 
|  | } | 
|  |  | 
|  | pub fn joint(self) -> TokenStream { | 
|  | TokenStream { kind: TokenStreamKind::JointTree(self) } | 
|  | } | 
|  | } | 
|  |  | 
|  | /// # Token Streams | 
|  | /// | 
|  | /// A `TokenStream` is an abstract sequence of tokens, organized into `TokenTree`s. | 
|  | /// The goal is for procedural macros to work with `TokenStream`s and `TokenTree`s | 
|  | /// instead of a representation of the abstract syntax tree. | 
|  | /// Today's `TokenTree`s can still contain AST via `Token::Interpolated` for back-compat. | 
|  | #[derive(Clone, Debug)] | 
|  | pub struct TokenStream { | 
|  | kind: TokenStreamKind, | 
|  | } | 
|  |  | 
|  | #[derive(Clone, Debug)] | 
|  | enum TokenStreamKind { | 
|  | Empty, | 
|  | Tree(TokenTree), | 
|  | JointTree(TokenTree), | 
|  | Stream(RcSlice<TokenStream>), | 
|  | } | 
|  |  | 
|  | impl From<TokenTree> for TokenStream { | 
|  | fn from(tt: TokenTree) -> TokenStream { | 
|  | TokenStream { kind: TokenStreamKind::Tree(tt) } | 
|  | } | 
|  | } | 
|  |  | 
|  | impl From<Token> for TokenStream { | 
|  | fn from(token: Token) -> TokenStream { | 
|  | TokenTree::Token(DUMMY_SP, token).into() | 
|  | } | 
|  | } | 
|  |  | 
|  | impl<T: Into<TokenStream>> iter::FromIterator<T> for TokenStream { | 
|  | fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self { | 
|  | TokenStream::concat(iter.into_iter().map(Into::into).collect::<Vec<_>>()) | 
|  | } | 
|  | } | 
|  |  | 
|  | impl Eq for TokenStream {} | 
|  |  | 
|  | impl PartialEq<TokenStream> for TokenStream { | 
|  | fn eq(&self, other: &TokenStream) -> bool { | 
|  | self.trees().eq(other.trees()) | 
|  | } | 
|  | } | 
|  |  | 
|  | impl TokenStream { | 
|  | pub fn len(&self) -> usize { | 
|  | if let TokenStreamKind::Stream(ref slice) = self.kind { | 
|  | slice.len() | 
|  | } else { | 
|  | 0 | 
|  | } | 
|  | } | 
|  |  | 
|  | pub fn empty() -> TokenStream { | 
|  | TokenStream { kind: TokenStreamKind::Empty } | 
|  | } | 
|  |  | 
|  | pub fn is_empty(&self) -> bool { | 
|  | match self.kind { | 
|  | TokenStreamKind::Empty => true, | 
|  | _ => false, | 
|  | } | 
|  | } | 
|  |  | 
|  | pub fn concat(mut streams: Vec<TokenStream>) -> TokenStream { | 
|  | match streams.len() { | 
|  | 0 => TokenStream::empty(), | 
|  | 1 => streams.pop().unwrap(), | 
|  | _ => TokenStream::concat_rc_slice(RcSlice::new(streams)), | 
|  | } | 
|  | } | 
|  |  | 
|  | fn concat_rc_slice(streams: RcSlice<TokenStream>) -> TokenStream { | 
|  | TokenStream { kind: TokenStreamKind::Stream(streams) } | 
|  | } | 
|  |  | 
|  | pub fn trees(&self) -> Cursor { | 
|  | self.clone().into_trees() | 
|  | } | 
|  |  | 
|  | pub fn into_trees(self) -> Cursor { | 
|  | Cursor::new(self) | 
|  | } | 
|  |  | 
|  | /// Compares two TokenStreams, checking equality without regarding span information. | 
|  | pub fn eq_unspanned(&self, other: &TokenStream) -> bool { | 
|  | for (t1, t2) in self.trees().zip(other.trees()) { | 
|  | if !t1.eq_unspanned(&t2) { | 
|  | return false; | 
|  | } | 
|  | } | 
|  | true | 
|  | } | 
|  |  | 
|  | /// Precondition: `self` consists of a single token tree. | 
|  | /// Returns true if the token tree is a joint operation w.r.t. `proc_macro::TokenNode`. | 
|  | pub fn as_tree(self) -> (TokenTree, bool /* joint? */) { | 
|  | match self.kind { | 
|  | TokenStreamKind::Tree(tree) => (tree, false), | 
|  | TokenStreamKind::JointTree(tree) => (tree, true), | 
|  | _ => unreachable!(), | 
|  | } | 
|  | } | 
|  |  | 
|  | pub fn map_enumerated<F: FnMut(usize, TokenTree) -> TokenTree>(self, mut f: F) -> TokenStream { | 
|  | let mut trees = self.into_trees(); | 
|  | let mut result = Vec::new(); | 
|  | let mut i = 0; | 
|  | while let Some(stream) = trees.next_as_stream() { | 
|  | result.push(match stream.kind { | 
|  | TokenStreamKind::Tree(tree) => f(i, tree).into(), | 
|  | TokenStreamKind::JointTree(tree) => f(i, tree).joint(), | 
|  | _ => unreachable!() | 
|  | }); | 
|  | i += 1; | 
|  | } | 
|  | TokenStream::concat(result) | 
|  | } | 
|  |  | 
|  | pub fn map<F: FnMut(TokenTree) -> TokenTree>(self, mut f: F) -> TokenStream { | 
|  | let mut trees = self.into_trees(); | 
|  | let mut result = Vec::new(); | 
|  | while let Some(stream) = trees.next_as_stream() { | 
|  | result.push(match stream.kind { | 
|  | TokenStreamKind::Tree(tree) => f(tree).into(), | 
|  | TokenStreamKind::JointTree(tree) => f(tree).joint(), | 
|  | _ => unreachable!() | 
|  | }); | 
|  | } | 
|  | TokenStream::concat(result) | 
|  | } | 
|  |  | 
|  | fn first_tree_and_joint(&self) -> Option<(TokenTree, bool)> { | 
|  | match self.kind { | 
|  | TokenStreamKind::Empty => None, | 
|  | TokenStreamKind::Tree(ref tree) => Some((tree.clone(), false)), | 
|  | TokenStreamKind::JointTree(ref tree) => Some((tree.clone(), true)), | 
|  | TokenStreamKind::Stream(ref stream) => stream.first().unwrap().first_tree_and_joint(), | 
|  | } | 
|  | } | 
|  |  | 
|  | fn last_tree_if_joint(&self) -> Option<TokenTree> { | 
|  | match self.kind { | 
|  | TokenStreamKind::Empty | TokenStreamKind::Tree(..) => None, | 
|  | TokenStreamKind::JointTree(ref tree) => Some(tree.clone()), | 
|  | TokenStreamKind::Stream(ref stream) => stream.last().unwrap().last_tree_if_joint(), | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | pub struct TokenStreamBuilder(Vec<TokenStream>); | 
|  |  | 
|  | impl TokenStreamBuilder { | 
|  | pub fn new() -> TokenStreamBuilder { | 
|  | TokenStreamBuilder(Vec::new()) | 
|  | } | 
|  |  | 
|  | pub fn push<T: Into<TokenStream>>(&mut self, stream: T) { | 
|  | let stream = stream.into(); | 
|  | let last_tree_if_joint = self.0.last().and_then(TokenStream::last_tree_if_joint); | 
|  | if let Some(TokenTree::Token(last_span, last_tok)) = last_tree_if_joint { | 
|  | if let Some((TokenTree::Token(span, tok), is_joint)) = stream.first_tree_and_joint() { | 
|  | if let Some(glued_tok) = last_tok.glue(tok) { | 
|  | let last_stream = self.0.pop().unwrap(); | 
|  | self.push_all_but_last_tree(&last_stream); | 
|  | let glued_span = last_span.to(span); | 
|  | let glued_tt = TokenTree::Token(glued_span, glued_tok); | 
|  | let glued_tokenstream = if is_joint { | 
|  | glued_tt.joint() | 
|  | } else { | 
|  | glued_tt.into() | 
|  | }; | 
|  | self.0.push(glued_tokenstream); | 
|  | self.push_all_but_first_tree(&stream); | 
|  | return | 
|  | } | 
|  | } | 
|  | } | 
|  | self.0.push(stream); | 
|  | } | 
|  |  | 
|  | pub fn add<T: Into<TokenStream>>(mut self, stream: T) -> Self { | 
|  | self.push(stream); | 
|  | self | 
|  | } | 
|  |  | 
|  | pub fn build(self) -> TokenStream { | 
|  | TokenStream::concat(self.0) | 
|  | } | 
|  |  | 
|  | fn push_all_but_last_tree(&mut self, stream: &TokenStream) { | 
|  | if let TokenStreamKind::Stream(ref streams) = stream.kind { | 
|  | let len = streams.len(); | 
|  | match len { | 
|  | 1 => {} | 
|  | 2 => self.0.push(streams[0].clone().into()), | 
|  | _ => self.0.push(TokenStream::concat_rc_slice(streams.sub_slice(0 .. len - 1))), | 
|  | } | 
|  | self.push_all_but_last_tree(&streams[len - 1]) | 
|  | } | 
|  | } | 
|  |  | 
|  | fn push_all_but_first_tree(&mut self, stream: &TokenStream) { | 
|  | if let TokenStreamKind::Stream(ref streams) = stream.kind { | 
|  | let len = streams.len(); | 
|  | match len { | 
|  | 1 => {} | 
|  | 2 => self.0.push(streams[1].clone().into()), | 
|  | _ => self.0.push(TokenStream::concat_rc_slice(streams.sub_slice(1 .. len))), | 
|  | } | 
|  | self.push_all_but_first_tree(&streams[0]) | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | #[derive(Clone)] | 
|  | pub struct Cursor(CursorKind); | 
|  |  | 
|  | #[derive(Clone)] | 
|  | enum CursorKind { | 
|  | Empty, | 
|  | Tree(TokenTree, bool /* consumed? */), | 
|  | JointTree(TokenTree, bool /* consumed? */), | 
|  | Stream(StreamCursor), | 
|  | } | 
|  |  | 
|  | #[derive(Clone)] | 
|  | struct StreamCursor { | 
|  | stream: RcSlice<TokenStream>, | 
|  | index: usize, | 
|  | stack: Vec<(RcSlice<TokenStream>, usize)>, | 
|  | } | 
|  |  | 
|  | impl StreamCursor { | 
|  | fn new(stream: RcSlice<TokenStream>) -> Self { | 
|  | StreamCursor { stream: stream, index: 0, stack: Vec::new() } | 
|  | } | 
|  |  | 
|  | fn next_as_stream(&mut self) -> Option<TokenStream> { | 
|  | loop { | 
|  | if self.index < self.stream.len() { | 
|  | self.index += 1; | 
|  | let next = self.stream[self.index - 1].clone(); | 
|  | match next.kind { | 
|  | TokenStreamKind::Tree(..) | TokenStreamKind::JointTree(..) => return Some(next), | 
|  | TokenStreamKind::Stream(stream) => self.insert(stream), | 
|  | TokenStreamKind::Empty => {} | 
|  | } | 
|  | } else if let Some((stream, index)) = self.stack.pop() { | 
|  | self.stream = stream; | 
|  | self.index = index; | 
|  | } else { | 
|  | return None; | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | fn insert(&mut self, stream: RcSlice<TokenStream>) { | 
|  | self.stack.push((mem::replace(&mut self.stream, stream), | 
|  | mem::replace(&mut self.index, 0))); | 
|  | } | 
|  | } | 
|  |  | 
|  | impl Iterator for Cursor { | 
|  | type Item = TokenTree; | 
|  |  | 
|  | fn next(&mut self) -> Option<TokenTree> { | 
|  | self.next_as_stream().map(|stream| match stream.kind { | 
|  | TokenStreamKind::Tree(tree) | TokenStreamKind::JointTree(tree) => tree, | 
|  | _ => unreachable!() | 
|  | }) | 
|  | } | 
|  | } | 
|  |  | 
|  | impl Cursor { | 
|  | fn new(stream: TokenStream) -> Self { | 
|  | Cursor(match stream.kind { | 
|  | TokenStreamKind::Empty => CursorKind::Empty, | 
|  | TokenStreamKind::Tree(tree) => CursorKind::Tree(tree, false), | 
|  | TokenStreamKind::JointTree(tree) => CursorKind::JointTree(tree, false), | 
|  | TokenStreamKind::Stream(stream) => CursorKind::Stream(StreamCursor::new(stream)), | 
|  | }) | 
|  | } | 
|  |  | 
|  | pub fn next_as_stream(&mut self) -> Option<TokenStream> { | 
|  | let (stream, consumed) = match self.0 { | 
|  | CursorKind::Tree(ref tree, ref mut consumed @ false) => | 
|  | (tree.clone().into(), consumed), | 
|  | CursorKind::JointTree(ref tree, ref mut consumed @ false) => | 
|  | (tree.clone().joint(), consumed), | 
|  | CursorKind::Stream(ref mut cursor) => return cursor.next_as_stream(), | 
|  | _ => return None, | 
|  | }; | 
|  |  | 
|  | *consumed = true; | 
|  | Some(stream) | 
|  | } | 
|  |  | 
|  | pub fn insert(&mut self, stream: TokenStream) { | 
|  | match self.0 { | 
|  | _ if stream.is_empty() => return, | 
|  | CursorKind::Empty => *self = stream.trees(), | 
|  | CursorKind::Tree(_, consumed) | CursorKind::JointTree(_, consumed) => { | 
|  | *self = TokenStream::concat(vec![self.original_stream(), stream]).trees(); | 
|  | if consumed { | 
|  | self.next(); | 
|  | } | 
|  | } | 
|  | CursorKind::Stream(ref mut cursor) => { | 
|  | cursor.insert(ThinTokenStream::from(stream).0.unwrap()); | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | pub fn original_stream(&self) -> TokenStream { | 
|  | match self.0 { | 
|  | CursorKind::Empty => TokenStream::empty(), | 
|  | CursorKind::Tree(ref tree, _) => tree.clone().into(), | 
|  | CursorKind::JointTree(ref tree, _) => tree.clone().joint(), | 
|  | CursorKind::Stream(ref cursor) => TokenStream::concat_rc_slice({ | 
|  | cursor.stack.get(0).cloned().map(|(stream, _)| stream) | 
|  | .unwrap_or(cursor.stream.clone()) | 
|  | }), | 
|  | } | 
|  | } | 
|  |  | 
|  | pub fn look_ahead(&self, n: usize) -> Option<TokenTree> { | 
|  | fn look_ahead(streams: &[TokenStream], mut n: usize) -> Result<TokenTree, usize> { | 
|  | for stream in streams { | 
|  | n = match stream.kind { | 
|  | TokenStreamKind::Tree(ref tree) | TokenStreamKind::JointTree(ref tree) | 
|  | if n == 0 => return Ok(tree.clone()), | 
|  | TokenStreamKind::Tree(..) | TokenStreamKind::JointTree(..) => n - 1, | 
|  | TokenStreamKind::Stream(ref stream) => match look_ahead(stream, n) { | 
|  | Ok(tree) => return Ok(tree), | 
|  | Err(n) => n, | 
|  | }, | 
|  | _ => n, | 
|  | }; | 
|  | } | 
|  | Err(n) | 
|  | } | 
|  |  | 
|  | match self.0 { | 
|  | CursorKind::Empty | | 
|  | CursorKind::Tree(_, true) | | 
|  | CursorKind::JointTree(_, true) => Err(n), | 
|  | CursorKind::Tree(ref tree, false) | | 
|  | CursorKind::JointTree(ref tree, false) => look_ahead(&[tree.clone().into()], n), | 
|  | CursorKind::Stream(ref cursor) => { | 
|  | look_ahead(&cursor.stream[cursor.index ..], n).or_else(|mut n| { | 
|  | for &(ref stream, index) in cursor.stack.iter().rev() { | 
|  | n = match look_ahead(&stream[index..], n) { | 
|  | Ok(tree) => return Ok(tree), | 
|  | Err(n) => n, | 
|  | } | 
|  | } | 
|  |  | 
|  | Err(n) | 
|  | }) | 
|  | } | 
|  | }.ok() | 
|  | } | 
|  | } | 
|  |  | 
|  | /// The `TokenStream` type is large enough to represent a single `TokenTree` without allocation. | 
|  | /// `ThinTokenStream` is smaller, but needs to allocate to represent a single `TokenTree`. | 
|  | /// We must use `ThinTokenStream` in `TokenTree::Delimited` to avoid infinite size due to recursion. | 
|  | #[derive(Debug, Clone)] | 
|  | pub struct ThinTokenStream(Option<RcSlice<TokenStream>>); | 
|  |  | 
|  | impl From<TokenStream> for ThinTokenStream { | 
|  | fn from(stream: TokenStream) -> ThinTokenStream { | 
|  | ThinTokenStream(match stream.kind { | 
|  | TokenStreamKind::Empty => None, | 
|  | TokenStreamKind::Tree(tree) => Some(RcSlice::new(vec![tree.into()])), | 
|  | TokenStreamKind::JointTree(tree) => Some(RcSlice::new(vec![tree.joint()])), | 
|  | TokenStreamKind::Stream(stream) => Some(stream), | 
|  | }) | 
|  | } | 
|  | } | 
|  |  | 
|  | impl From<ThinTokenStream> for TokenStream { | 
|  | fn from(stream: ThinTokenStream) -> TokenStream { | 
|  | stream.0.map(TokenStream::concat_rc_slice).unwrap_or_else(TokenStream::empty) | 
|  | } | 
|  | } | 
|  |  | 
|  | impl Eq for ThinTokenStream {} | 
|  |  | 
|  | impl PartialEq<ThinTokenStream> for ThinTokenStream { | 
|  | fn eq(&self, other: &ThinTokenStream) -> bool { | 
|  | TokenStream::from(self.clone()) == TokenStream::from(other.clone()) | 
|  | } | 
|  | } | 
|  |  | 
|  | impl fmt::Display for TokenStream { | 
|  | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | 
|  | f.write_str(&pprust::tokens_to_string(self.clone())) | 
|  | } | 
|  | } | 
|  |  | 
|  | impl Encodable for TokenStream { | 
|  | fn encode<E: Encoder>(&self, encoder: &mut E) -> Result<(), E::Error> { | 
|  | self.trees().collect::<Vec<_>>().encode(encoder) | 
|  | } | 
|  | } | 
|  |  | 
|  | impl Decodable for TokenStream { | 
|  | fn decode<D: Decoder>(decoder: &mut D) -> Result<TokenStream, D::Error> { | 
|  | Vec::<TokenTree>::decode(decoder).map(|vec| vec.into_iter().collect()) | 
|  | } | 
|  | } | 
|  |  | 
|  | impl Hash for TokenStream { | 
|  | fn hash<H: hash::Hasher>(&self, state: &mut H) { | 
|  | for tree in self.trees() { | 
|  | tree.hash(state); | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | impl Encodable for ThinTokenStream { | 
|  | fn encode<E: Encoder>(&self, encoder: &mut E) -> Result<(), E::Error> { | 
|  | TokenStream::from(self.clone()).encode(encoder) | 
|  | } | 
|  | } | 
|  |  | 
|  | impl Decodable for ThinTokenStream { | 
|  | fn decode<D: Decoder>(decoder: &mut D) -> Result<ThinTokenStream, D::Error> { | 
|  | TokenStream::decode(decoder).map(Into::into) | 
|  | } | 
|  | } | 
|  |  | 
|  | impl Hash for ThinTokenStream { | 
|  | fn hash<H: hash::Hasher>(&self, state: &mut H) { | 
|  | TokenStream::from(self.clone()).hash(state); | 
|  | } | 
|  | } | 
|  |  | 
|  |  | 
|  | #[cfg(test)] | 
|  | mod tests { | 
|  | use super::*; | 
|  | use syntax::ast::Ident; | 
|  | use syntax_pos::{Span, BytePos, NO_EXPANSION}; | 
|  | use parse::token::Token; | 
|  | use util::parser_testing::string_to_stream; | 
|  |  | 
|  | fn string_to_ts(string: &str) -> TokenStream { | 
|  | string_to_stream(string.to_owned()) | 
|  | } | 
|  |  | 
|  | fn sp(a: u32, b: u32) -> Span { | 
|  | Span::new(BytePos(a), BytePos(b), NO_EXPANSION) | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn test_concat() { | 
|  | let test_res = string_to_ts("foo::bar::baz"); | 
|  | let test_fst = string_to_ts("foo::bar"); | 
|  | let test_snd = string_to_ts("::baz"); | 
|  | let eq_res = TokenStream::concat(vec![test_fst, test_snd]); | 
|  | assert_eq!(test_res.trees().count(), 5); | 
|  | assert_eq!(eq_res.trees().count(), 5); | 
|  | assert_eq!(test_res.eq_unspanned(&eq_res), true); | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn test_to_from_bijection() { | 
|  | let test_start = string_to_ts("foo::bar(baz)"); | 
|  | let test_end = test_start.trees().collect(); | 
|  | assert_eq!(test_start, test_end) | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn test_eq_0() { | 
|  | let test_res = string_to_ts("foo"); | 
|  | let test_eqs = string_to_ts("foo"); | 
|  | assert_eq!(test_res, test_eqs) | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn test_eq_1() { | 
|  | let test_res = string_to_ts("::bar::baz"); | 
|  | let test_eqs = string_to_ts("::bar::baz"); | 
|  | assert_eq!(test_res, test_eqs) | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn test_eq_3() { | 
|  | let test_res = string_to_ts(""); | 
|  | let test_eqs = string_to_ts(""); | 
|  | assert_eq!(test_res, test_eqs) | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn test_diseq_0() { | 
|  | let test_res = string_to_ts("::bar::baz"); | 
|  | let test_eqs = string_to_ts("bar::baz"); | 
|  | assert_eq!(test_res == test_eqs, false) | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn test_diseq_1() { | 
|  | let test_res = string_to_ts("(bar,baz)"); | 
|  | let test_eqs = string_to_ts("bar,baz"); | 
|  | assert_eq!(test_res == test_eqs, false) | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn test_is_empty() { | 
|  | let test0: TokenStream = Vec::<TokenTree>::new().into_iter().collect(); | 
|  | let test1: TokenStream = | 
|  | TokenTree::Token(sp(0, 1), Token::Ident(Ident::from_str("a"))).into(); | 
|  | let test2 = string_to_ts("foo(bar::baz)"); | 
|  |  | 
|  | assert_eq!(test0.is_empty(), true); | 
|  | assert_eq!(test1.is_empty(), false); | 
|  | assert_eq!(test2.is_empty(), false); | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn test_dotdotdot() { | 
|  | let mut builder = TokenStreamBuilder::new(); | 
|  | builder.push(TokenTree::Token(sp(0, 1), Token::Dot).joint()); | 
|  | builder.push(TokenTree::Token(sp(1, 2), Token::Dot).joint()); | 
|  | builder.push(TokenTree::Token(sp(2, 3), Token::Dot)); | 
|  | let stream = builder.build(); | 
|  | assert!(stream.eq_unspanned(&string_to_ts("..."))); | 
|  | assert_eq!(stream.trees().count(), 1); | 
|  | } | 
|  |  | 
|  | } |