Reputation: 44739
My first Rust program compiles and runs:
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);
}
}
I have some complex code which iterates through the Vec of devices, testing each one's .name
property against args.device
.
I'm guessing that there is a method of 'looking-up' an entry in a Vec, such that I can replace all the optdev
lines with something like:
let dev = match devices.unwrap().look_up(.name == args.device) {
None => {
println!("Device {} not found.", args.device);
exit(1);
},
Some(dev) => dev,
};
What is the syntax for such a look_up()
?
Or is there a more idiomatic way of doing this?
Upvotes: 1
Views: 1500
Reputation: 42207
What is the syntax for such a
look_up()
?
Iterator::find
. Since the operation is not specific to vectors (or slices), it doesn't live there, and is applicable to any iterator instead.
It'd look something like this:
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,
};
or
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);
};
(side-note: you may also want to use eprintln
for, well, error reporting).
Though a somewhat cleaner error handling could be along the lines of (note: not tested so there might be semantic or syntactic mistakes):
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);
}
}
Upvotes: 3