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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
use crate::lang::Lang;
use crate::Tokens;
use std::rc::Rc;

/// Trait for types that can be formatted in-place into a token stream.
///
/// Things implementing [FormatInto] can be used as arguments for
/// [interpolation] in the [quote!] macro.
///
/// [from_fn()] is a helper function which simplifies the task of creating a
/// [FormatInto] implementation on the fly.
///
/// [from_fn()]: crate::tokens::from_fn()
/// [quote!]: macro.quote.html
/// [interpolation]: macro.quote.html#interpolation
///
/// # Examples
///
/// ```rust
/// # fn main() -> genco::fmt::Result {
/// use genco::quote_in;
/// use genco::tokens::{ItemStr, FormatInto, from_fn, static_literal};
/// use genco::lang::Lang;
///
/// fn comment<L>(s: impl Into<ItemStr>) -> impl FormatInto<L>
/// where
///     L: Lang
/// {
///     from_fn(move |tokens| {
///         let s = s.into();
///         quote_in!(*tokens => #(static_literal("//")) #s);
///     })
/// }
/// # Ok(())
/// # }
/// ```
pub trait FormatInto<L>
where
    L: Lang,
{
    /// Convert the type into tokens in-place.
    ///
    /// # Examples
    fn format_into(self, tokens: &mut Tokens<L>);
}

impl<L> FormatInto<L> for Tokens<L>
where
    L: Lang,
{
    fn format_into(self, tokens: &mut Self) {
        tokens.extend(self);
    }
}

impl<'a, L> FormatInto<L> for &'a Tokens<L>
where
    L: Lang,
{
    fn format_into(self, tokens: &mut Tokens<L>) {
        tokens.extend(self.iter().cloned());
    }
}

/// Convert collection to tokens.
impl<L> FormatInto<L> for Vec<Tokens<L>>
where
    L: Lang,
{
    fn format_into(self, tokens: &mut Tokens<L>) {
        for t in self {
            tokens.extend(t);
        }
    }
}

/// Convert borrowed strings.
impl<'a, L> FormatInto<L> for &'a str
where
    L: Lang,
{
    fn format_into(self, tokens: &mut Tokens<L>) {
        tokens.item(self.to_string().into());
    }
}

/// Convert borrowed strings.
impl<'a, L> FormatInto<L> for &'a String
where
    L: Lang,
{
    fn format_into(self, tokens: &mut Tokens<L>) {
        tokens.item(self.clone().into());
    }
}

/// Convert strings.
impl<L> FormatInto<L> for String
where
    L: Lang,
{
    fn format_into(self, tokens: &mut Tokens<L>) {
        tokens.item(self.into());
    }
}

/// Convert refcounted strings.
impl<L> FormatInto<L> for Rc<String>
where
    L: Lang,
{
    fn format_into(self, tokens: &mut Tokens<L>) {
        tokens.item(self.into());
    }
}

/// Convert reference to refcounted strings.
impl<'a, L> FormatInto<L> for &'a Rc<String>
where
    L: Lang,
{
    fn format_into(self, tokens: &mut Tokens<L>) {
        tokens.item(self.clone().into());
    }
}

/// Convert stringy things.
impl<L, T> FormatInto<L> for Option<T>
where
    L: Lang,
    T: FormatInto<L>,
{
    fn format_into(self, tokens: &mut Tokens<L>) {
        if let Some(inner) = self {
            inner.format_into(tokens);
        }
    }
}

macro_rules! impl_display {
    ($($ty:ty),*) => {
        $(
            impl<L> FormatInto<L> for $ty
            where
                L: Lang,
            {
                fn format_into(self, tokens: &mut Tokens<L>) {
                    tokens.append(self.to_string());
                }
            }
        )*
    };
}

impl_display!(u8, u16, u32, u64, u128, i8, i16, i32, i64, i128, isize, usize);