Как передать в функцию разные типы итераторов

Добрый день,

В моей задаче необходимо, чтобы функция принимала как обычный std::iter::Iterator так и std::iter::Take.

Код:

use std::iter;
use std::slice;

fn f1(iter: &mut slice::Iter<u8>) {
    iter.next();
}

fn f2(iter: &mut iter::Take<&mut slice::Iter<u8>>) {
    iter.next();
}

fn main() {
    let a = vec![0u8;10];

    let mut i = a.iter();
    f1(&mut i);
    
    {
        let ref mut iref = i;
        f2(&mut iref.take(2));
    }
    
    println!("{:?}", i.as_slice());
}

Нужно сделать так, чтобы вместо f1 и f2 была одна функция.
Пробовал использовать Generic параметры, но ничего не вышло.
Это вообще возможно сделать?

https://play.rust-lang.org/?gist=62068d611ffc167d26a58dd1a275816b

Спасибо, но такой вариант не учитывает, что я использую итератор по u8.
Например так работать не будет:

fn f3<I: Iterator>(iter: &mut I) {
    if let Some(x) = iter.next() {
        println!("{:?}", *x);
    }
}

https://play.rust-lang.org/?gist=da15a44325cfc36fed8793a5e72ded74&version=stable&backtrace=0

https://play.rust-lang.org/?gist=8cb04c9e45a38bba9af3641fff5b3dc2

Спасибо, окончательный вариант вышел такой, так как хотелось бы ограничить тип, по которому создан итератор:

use std::iter::Iterator;

fn f3<'a, I: Iterator<Item = &'a u8>>(iter: &mut I) {
    if let Some(x) = iter.next() {
        println!("{:?}", *x);
    }
}

fn main() {
    let a = vec![0u8;10];
    let mut i = a.iter();
    f3(&mut i);
    {
        let ref mut iref = i;
        f3(&mut iref.take(2));
    }
    println!("{:?}", i.as_slice());
}

Хм, попробовал использовать рекурсию для этой функции и получил ошибку:

<anon>:3:1: 9:2 error: reached the recursion limit during monomorphization
<anon>:3 fn f3<'a, I: Iterator<Item = &'a u8>>(iter: &mut I) {
<anon>:4     if let Some(x) = iter.next() {
<anon>:5         println!("{:?}", *x);
<anon>:6     }
<anon>:7     
<anon>:8     f3(&mut iter.take(1));

https://play.rust-lang.org/?gist=99d8e25e06322b0778ce0ba5f5cf34bc&version=stable&backtrace=0

Кроме того как перейти на цикл, это никак нельзя исправить?

В реальной задаче я хотел бы передавать в f3() часть значений перебираемых итератором, поэтому пытаюсь ограничить кол-во с помощью take().

Можно использовать динамическую диспетчеризацию. fn f(iter: &mut Iterator<Item=u8>)

Тоже смотрю в сторону динамической диспетчеризации, но пока не осилил написать рабочий вариант.

Тут в случае рекурсии никак по другому не сделать, у тебя получается в результате мономорфизации куча функций вида f<Take<Take<Take<...>>> с постоянно увеличивающейся глубиной типа, отсюда и ошибка с превышением рекурсии.

Спасибо, все получилось с динамической диспетчеризацией (почему-то я считал, что она обязательно связана с Box<T>).

На всякий случай финальный вариант кода:

use std::iter::Iterator;

fn f3(iter: &mut Iterator<Item = &u8>) {
    if let Some(x) = iter.next() {
        println!("{:?}", *x);
    }
    else {
        return;
    }

    f3(&mut iter.take(1));
}

fn main() {
    let a = vec![0u8;10];
    let mut i = a.iter();
    f3(&mut i);
    println!("{:?}", i.as_slice());
}

Box<Trait> нужен, если нужно передать владение трейт-объектом. Если владения передавать не надо, можно обойтись &Trait или &mut Trait, как в данном случае.