      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

    use super::ToTokens;

    use std::iter;

    use proc_macro2::{TokenStream, TokenTree};

    /// TokenStream extension trait with methods for appending tokens.
    ///
    /// This trait is sealed and cannot be implemented outside of the `quote` crate.
    pub trait TokenStreamExt: private::Sealed {
        /// For use by `ToTokens` implementations.
        ///
        /// Appends the token specified to this list of tokens.
        fn append<U>(&mut self, token: U)
        where
            U: Into<TokenTree>;

        /// For use by `ToTokens` implementations.
        ///
        /// ```
        /// # use quote::{quote, TokenStreamExt, ToTokens};
        /// # use proc_macro2::TokenStream;
        /// #
        /// struct X;
        ///
        /// impl ToTokens for X {
        ///     fn to_tokens(&self, tokens: &mut TokenStream) {
        ///         tokens.append_all(&[true, false]);
        ///     }
        /// }
        ///
        /// let tokens = quote!(#X);
        /// assert_eq!(tokens.to_string(), "true false");
        /// ```
        fn append_all<I>(&mut self, iter: I)
        where
            I: IntoIterator,
            I::Item: ToTokens;

        /// For use by `ToTokens` implementations.
        ///
        /// Appends all of the items in the iterator `I`, separated by the tokens
        /// `U`.
        fn append_separated<I, U>(&mut self, iter: I, op: U)
        where
            I: IntoIterator,
            I::Item: ToTokens,
            U: ToTokens;

        /// For use by `ToTokens` implementations.
        ///
        /// Appends all tokens in the iterator `I`, appending `U` after each
        /// element, including after the last element of the iterator.
        fn append_terminated<I, U>(&mut self, iter: I, term: U)
        where
            I: IntoIterator,
            I::Item: ToTokens,
            U: ToTokens;
    }

    impl TokenStreamExt for TokenStream {
        fn append<U>(&mut self, token: U)
        where
            U: Into<TokenTree>,
        {
            self.extend(iter::once(token.into()));
        }

        fn append_all<I>(&mut self, iter: I)
        where
            I: IntoIterator,
            I::Item: ToTokens,
        {
            for token in iter {
                token.to_tokens(self);
            }
        }

        fn append_separated<I, U>(&mut self, iter: I, op: U)
        where
            I: IntoIterator,
            I::Item: ToTokens,
            U: ToTokens,
        {
            for (i, token) in iter.into_iter().enumerate() {
                if i > 0 {
                    op.to_tokens(self);
                }
                token.to_tokens(self);
            }
        }

        fn append_terminated<I, U>(&mut self, iter: I, term: U)
        where
            I: IntoIterator,
            I::Item: ToTokens,
            U: ToTokens,
        {
            for token in iter {
                token.to_tokens(self);
                term.to_tokens(self);
            }
        }
    }

    mod private {
        use proc_macro2::TokenStream;

        pub trait Sealed {}

        impl Sealed for TokenStream {}
    }