proc_quote/repeat.rs
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
use super::ToTokens;
use std::borrow::Borrow;
use std::slice;
/// Defines the behavior of types that can be interpolated inside repeating patterns (`#(...)*`).
///
/// ### Which types *do* `Repeat`
/// - [`Iterator<T>`] consumes the iterator, iterating through every element.
/// - <a href="https://doc.rust-lang.org/std/borrow/trait.Borrow.html">`Borrow<[T]>`</a>
/// (includes [`Vec`], [`array`], and [`slice`]) iterates with the [`slice::iter`] method,
/// thus not consuming the original data.
/// - [`ToTokens`], interpolates the variable in every iteration.
///
/// ### Which types *do NOT* `Repeat`
/// - [`IntoIterator`], to avoid ambiguity (Ex. "Which behavior would have been used for [`Vec`],
/// which implements both [`IntoIterator`] and <a href="https://doc.rust-lang.org/std/borrow/trait.Borrow.html">
/// `Borrow<[T]>`</a>?"; "Which behavior would have been used for [`TokenStream`], which implements both
/// [`IntoIterator`] and [`ToTokens`]?"). To use the iterator, you may call [`IntoIterator::into_iter`]
/// explicitly.
/// - Ambiguous types that implement at least two of the `Repeat` traits. In the very unlikely case
/// this happens, disambiguate the type by wrapping it under some structure that only implements the
/// trait you desire to use.
///
/// [`Iterator<T>`]: https://doc.rust-lang.org/std/iter/trait.Iterator.html
/// [`Vec`]: https://doc.rust-lang.org/std/vec/struct.Vec.html
/// [`array`]: https://doc.rust-lang.org/std/primitive.array.html
/// [`slice`]: https://doc.rust-lang.org/std/slice/index.html
/// [`slice::iter`]: https://doc.rust-lang.org/std/primitive.slice.html#method.iter
/// [`ToTokens`]: https://docs.rs/proc-quote/0/proc_quote/trait.ToTokens.html
/// [`IntoIterator`]: https://doc.rust-lang.org/std/iter/trait.IntoIterator.html
/// [`IntoIterator::into_iter`]: https://doc.rust-lang.org/std/iter/trait.IntoIterator.html#tymethod.into_iter
pub trait Repeat<T: Iterator>: private::Sealed<T> {
// Long name to avoid collision
// TODO(Blocked on #7): rename to `as_repeat` once collision is solved
#[allow(non_snake_case)]
#[doc(hidden)]
fn __proc_quote__as_repeat(self) -> T;
}
mod private {
use super::*;
pub trait Sealed<T> {}
impl<T, I: Iterator<Item = T>> Sealed<I> for I {}
impl<'a, T: 'a, S: Borrow<[T]>> Sealed<slice::Iter<'a, T>> for &'a S {}
impl<'a, T: ToTokens + 'a> Sealed<ToTokensRepeat<'a, T>> for &'a T {}
}
/// Types that implement `Iterator` may be used in repeating patterns.
///
/// They, will be consumed, so they can only be used in one pattern.
impl<T, I: Iterator<Item = T>> Repeat<I> for I {
fn __proc_quote__as_repeat(self) -> I {
self
}
}
/// Types that implement `Borrow<[T]>` may be used in repeating patterns.
///
/// This includes, but is not necessarily limited to, `Vec`, `array` and `slice`.
///
/// They, will not be consumed. Instead `slice::iter` will be implicitly called.
impl<'a, T: 'a, S: Borrow<[T]>> Repeat<slice::Iter<'a, T>> for &'a S {
fn __proc_quote__as_repeat(self) -> slice::Iter<'a, T> {
(*self).borrow().iter()
}
}
/// Types that implement `ToTokens` may be used in repeating patterns.
///
/// The variable will be interpolated in every iteration.
impl<'a, T: ToTokens + 'a> Repeat<ToTokensRepeat<'a, T>> for &'a T {
fn __proc_quote__as_repeat(self) -> ToTokensRepeat<'a, T> {
ToTokensRepeat(self)
}
}
/// Struct that wraps a reference to `ToTokens` in order to use it in repeating patterns.
pub struct ToTokensRepeat<'a, T: ToTokens + 'a>(&'a T);
impl<'a, T: ToTokens + 'a> Iterator for ToTokensRepeat<'a, T> {
type Item = &'a T;
fn next(&mut self) -> Option<Self::Item> {
Some(self.0)
}
}