Код с деструктурированием Enum, помогите исправить

Исправить код чтобы в качестве верного результата печатался индекс вектора с номером "3". Сейчас код выдает два результата "1" и "3": запустить код онлайн

Подробнее о том какие критерии:

  1. Переменная find_me имеет значение Source::Base, при итерациях вектора Vec должны бать отсеяны любые варианты с Source::Curr как не подходящие.
  2. Найденный индекс в векторе должен быть с word_2.
  3. Проверка соответствий по значению i32 не требуется.

Другими словами, нужно исправить match (или заменить его на что-то другое, если есть такая замена), что выдаст индекс "3" вектора в качестве единственного верного результата по той причине, что только этот индекс совпадает с find_me по таким критериям как Source::Baseи word_2.

pub enum Source {
    Curr(&'static str, i32),
    Base(&'static str, i32),
}

pub struct Data {
    field: Source,
}

fn main() {
    #[rustfmt::skip]
    let vec = vec![
        Data{field: Source::Curr("word", 1)},
        Data{field: Source::Curr("word_2", 2)},
        Data{field: Source::Base("word", 3)},
        Data{field: Source::Base("word_2", 4)},
    ];

    let find_me = Source::Base("word_2", 2);
    foo(find_me, vec);
}

fn foo(find_me: Source, vec: Vec<Data>) {
    let (name, _) = match find_me {
        Source::Base(x, y) => (x, y),
        Source::Curr(x, y) => (x, y),
    };
    let mut index = 0;
    for item in vec.into_iter() {
        match item {
            Data {
                field: Source::Curr(txt, _),
            } if name == txt => println!("{}", index),
            Data {
                field: Source::Base(txt, _),
            } if name == txt => println!("{}", index),
            _ => (),
        }
        index += 1;
    }
}

Ответы (1 шт):

Автор решения: Ziaft

Думаю, вам следует написать следующую функцию:

fn variant_eq<T>(first: &T, second: &T) -> bool {
    std::mem::discriminant(first) == std::mem::discriminant(second)
}

Или вот такую:

fn variant_eq(a: &Source, b: &Source) -> bool {
    match (a, b) {
        (&Source::Base(..), &Source::Base(..)) => true,
        (&Source::Curr(..), &Source::Curr(..)) => true,
        _ => false,
    }
}

И использовать ее при сравнении:

match item {
            Data {
                field: Source::Curr(txt, _),
            } if name == txt && variant_eq(&item.field, &find_me) => {
                println!("{}", index)
            }
            Data {
                field: Source::Base(txt, _),
            } if name == txt && variant_eq(&item.field, &find_me) => {
                println!("{}", index)
            }
            _ => (),
        }

Первая, конечно, предпочтительней, так как она шаблонна, но вторая нагляднее, поэтому решил привести и ее.

→ Ссылка