    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

    use super::ToTokens;
    use core::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 {}
    }