Поиск совпадения в Ve c - PullRequest
0 голосов
/ 16 июня 2020

Моя первая программа на Rust компилируется и запускается:

use structopt::StructOpt;
use pcap::{Device,Capture};
use std::process::exit;

#[derive(StructOpt)]
struct Cli {
    /// the capture device
    device: String,
}

fn main() {    
    let devices = Device::list();
    let args = Cli::from_args();

    let mut optdev :Option<Device> = None;
    for d in devices.unwrap() {
        //println!("device: {:?}", d);
        if d.name == args.device {
            optdev = Some(d);
        }
    }

    let dev = match optdev {
        None => {
            println!("Device {} not found.", args.device);
            exit(1);
        },
        Some(dev) => dev,
    };

    let mut cap = Capture::from_device(dev).unwrap()
              .promisc(true)
              .snaplen(100)
              .open().unwrap();

    while let Ok(packet) = cap.next() {
        println!("received packet! {:?}", packet);
    }
}

У меня есть сложный код, который выполняет итерацию по Ve c устройств, проверяя каждое свойство .name на args.device.

Я предполагаю, что существует метод «поиска» записи в Ve c, такой, что я могу заменить все строки optdev чем-то вроде:

let dev = match devices.unwrap().look_up(.name == args.device) {
    None => {
        println!("Device {} not found.", args.device);
        exit(1);
    },
    Some(dev) => dev,
};

Какой синтаксис для такого look_up()?

Или есть более идиоматический c способ сделать это?

1 Ответ

2 голосов
/ 16 июня 2020

Каков синтаксис для такого look_up()?

Iterator::find. Так как операция не указана c для векторов (или срезов), она не существует там и вместо этого применима к любому итератору.

Это будет выглядеть примерно так:

let dev = match devices.unwrap().into_iter().find(|d| d.name == args.device) {
    None => {
        println!("Device {} not found.", args.device);
        exit(1);
    },
    Some(dev) => dev,
};

или

let dev = if let Some(dev) = devices.unwrap().into_iter().find(|d| d.name == args.device) {
    dev
} else {
    println!("Device {} not found.", args.device);
    exit(1);
};

(примечание: вы также можете использовать eprintln для сообщения об ошибках).

Хотя несколько более чистая обработка ошибок могла бы быть в виде (примечание: не тестировалось, поэтому могут быть ошибки semanti c или syntacti c):

use std::fmt;
use std:errors::Error;

#[derive(Debug)]
struct NoDevice(String);
impl fmt::Display for NoDevice {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Device {} not found", self.0)
    }
}
impl Error for NoDevice {}

fn main() -> Result<(), Box<dyn Error>> {    
    let devices = Device::list()?;
    let args = Cli::from_args();

    let dev = devices.into_iter()
                     .find(|d| d.name == args.device)
                     .ok_or_else(|| NoDevice(args.device))?

    let mut cap = Capture::from_device(dev)?
              .promisc(true)
              .snaplen(100)
              .open()?;

    while let Ok(packet) = cap.next() {
        println!("received packet! {:?}", packet);
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...