Уменьшение отступа совпадений для глубоко вложенных свойств - PullRequest
1 голос
/ 19 июня 2020

Мне нужно сослаться на значение в глубине структуры, которая включает Option, вложенное в свойство struct, вложенное в Result.

Мое текущее (рабочее) решение:

    let raw = &packet[16..];
    match PacketHeaders::from_ip_slice(raw) {
        Err(_value) => {
            /* ignore */
        },
        Ok(value) => {
            match value.ip {
                Some(Version4(header)) => {
                    let key = format!("{}.{}.{}.{},{}.{}.{}.{}", 
                        header.source[0], header.source[1], header.source[2], header.source[3],
                        header.destination[0], header.destination[1], header.destination[2], header.destination[3],
                    );

                    let Count {packets, bytes} = counts.entry(key).or_insert(Count {packets: 0, bytes: 0});
                    *packets += 1;
                    *bytes += packet.len();

                    if p > 1000 { /* exit after 1000 packets */
                        for (key, value) in counts {
                            println!("{},{},{}", key, value.packets, value.bytes);
                        }
                        return ();
                    }
                    p += 1;
                }
                _ => {
                    /* ignore */
                }
            }
        }
    }

(Проблема с моим текущим кодом - это чрезмерное вложение и два совпадения.)

Все, что мне нужно, это PacketHeaders::from_ip_slice(ip) >> Ok >> ip >> Some >> Version4.

Как я могу это получить или игнорировать сбой (НЕ сбой / выход) для каждого захваченного пакета?

Ответы [ 2 ]

4 голосов
/ 19 июня 2020

Гнезда сопоставления шаблонов, и шаблон для структуры выглядит как структурные литералы с добавлением, что .. означает «и соответствует всем остальным, что меня не волнует», аналогично тому, как шаблон _ означает » соответствовать чему угодно ". Это означает, что вы можете сделать

match PacketHeaders::from_ip_slice(raw) {
    Ok(PacketHeaders { ip: Version4(header), .. }) => {
        /* handle */
    }
    _ => {
        /* ignore `Err(_)` and other `Ok(_)` */
    },
}

, и если вы собираетесь игнорировать все, кроме одного случая, вы можете использовать if let:

if let Ok(PacketHeaders { ip: Version4(header), .. }) = PacketHeaders::from_ip_slice(raw) {
    /* handle */
}
0 голосов
/ 19 июня 2020

Код оказался:

    let raw = &packet[16..];
    if let Ok(PacketHeaders { ip: Some(Version4(header)), link: _, vlan: _, transport: _, payload: _}) = PacketHeaders::from_ip_slice(raw) {
        let key = format!("{}.{}.{}.{},{}.{}.{}.{}", 
            header.source[0], header.source[1], header.source[2], header.source[3],
            header.destination[0], header.destination[1], header.destination[2], header.destination[3],
        );

        let Count {packets, bytes} = counts.entry(key).or_insert(Count {packets: 0, bytes: 0});
        *packets += 1;
        *bytes += packet.len();
    }
...