-pub trait InternAs<T: ?Sized, R> {
- type Output;
- fn intern_with<F>(self, f: F) -> Self::Output
- where
- F: FnOnce(&T) -> R;
-}
-
-impl<I, T, R, E> InternAs<[T], R> for I
-where
- E: InternIteratorElement<T, R>,
- I: Iterator<Item = E>,
-{
- type Output = E::Output;
- fn intern_with<F>(self, f: F) -> Self::Output
- where
- F: FnOnce(&[T]) -> R,
- {
- E::intern_with(self, f)
- }
-}
-
-pub trait InternIteratorElement<T, R>: Sized {
- type Output;
- fn intern_with<I: Iterator<Item = Self>, F: FnOnce(&[T]) -> R>(iter: I, f: F) -> Self::Output;
-}
-
-impl<T, R> InternIteratorElement<T, R> for T {
- type Output = R;
- fn intern_with<I: Iterator<Item = Self>, F: FnOnce(&[T]) -> R>(
- mut iter: I,
- f: F,
- ) -> Self::Output {
- // This code is hot enough that it's worth specializing for the most
- // common length lists, to avoid the overhead of `SmallVec` creation.
- // Lengths 0, 1, and 2 typically account for ~95% of cases. If
- // `size_hint` is incorrect a panic will occur via an `unwrap` or an
- // `assert`.
- match iter.size_hint() {
- (0, Some(0)) => {
- assert!(iter.next().is_none());
- f(&[])
- }
- (1, Some(1)) => {
- let t0 = iter.next().unwrap();
- assert!(iter.next().is_none());
- f(&[t0])
- }
- (2, Some(2)) => {
- let t0 = iter.next().unwrap();
- let t1 = iter.next().unwrap();
- assert!(iter.next().is_none());
- f(&[t0, t1])
- }
- _ => f(&iter.collect::<SmallVec<[_; 8]>>()),
- }
- }
-}
-
-impl<'a, T, R> InternIteratorElement<T, R> for &'a T
-where
- T: Clone + 'a,
-{
- type Output = R;
- fn intern_with<I: Iterator<Item = Self>, F: FnOnce(&[T]) -> R>(iter: I, f: F) -> Self::Output {
- // This code isn't hot.
- f(&iter.cloned().collect::<SmallVec<[_; 8]>>())
- }
-}
-
-impl<T, R, E> InternIteratorElement<T, R> for Result<T, E> {
- type Output = Result<R, E>;
- fn intern_with<I: Iterator<Item = Self>, F: FnOnce(&[T]) -> R>(
- mut iter: I,
- f: F,
- ) -> Self::Output {
- // This code is hot enough that it's worth specializing for the most
- // common length lists, to avoid the overhead of `SmallVec` creation.
- // Lengths 0, 1, and 2 typically account for ~95% of cases. If
- // `size_hint` is incorrect a panic will occur via an `unwrap` or an
- // `assert`, unless a failure happens first, in which case the result
- // will be an error anyway.
- Ok(match iter.size_hint() {
- (0, Some(0)) => {
- assert!(iter.next().is_none());
- f(&[])
- }
- (1, Some(1)) => {
- let t0 = iter.next().unwrap()?;
- assert!(iter.next().is_none());
- f(&[t0])
- }
- (2, Some(2)) => {
- let t0 = iter.next().unwrap()?;
- let t1 = iter.next().unwrap()?;
- assert!(iter.next().is_none());
- f(&[t0, t1])
- }
- _ => f(&iter.collect::<Result<SmallVec<[_; 8]>, _>>()?),
- })
- }
-}
-