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) } }