-
Notifications
You must be signed in to change notification settings - Fork 147
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Review/audit phantom type usage #16
Comments
I'm just learning Rust, so it's possible that my issue is due to a lack of understanding rather than a shortcoming of the phantom types model, but... I'm attempting to write a pcap client that will either open a dumpfile or else configure a live capture interface and open it. I then want to process the resulting let mut x:&Capture<Activated> = file.or_else(device.and_then(Capture::open));
x.run(); (or, alternatively, to write a function that could do the above logic and return a boxed However, it seems that I can't take a reference to a
So instead, I'm writing a enum type to unify the two kinds of enum Capture {
File(Capture<Offline>),
Device(Capture<Active>),
}
impl Capture {
fn run(&mut self) {
match self {
&mut Capture::File(ref mut f) => { /* ... */ f.next() /* ... */ },
&mut Capture::Device(ref mut d) => { /* ... */ d.next() /* ... */ },
}
}
} This seems pretty redundant, given that the pcap crate already tries to unify the usage of |
Thank you very much for your feedback. That's absolutely something I would need to support to make this worthwhile ergonomically.
If you're using nightly anyway and feeling brave, give this branch a shot. (See the included tests as proof of the functionality you want. :)) |
eddyb pointed out to me... I've implemented the feature you want in the latest version which I've published (0.4.1). If |
The current API design competes against a design which would probably involve an internal "CaptureBox" which contains the The advantages to that design are that less symbols need to be imported by the end user sometimes. There wouldn't really be any code reuse and it might be simpler to understand what's going on and where to start. (After all, inference makes constructing the captures in the first place kind of magic. I also reordered the impls in the source so they would come out the way I wanted to in the docs...) You could just Box to interact with it as a trait object like It's starting to feel more compelling to use that design than to keep the current one, but I have to spec it out to be sure. The only other design would be a single Capture which mimics the upstream API, but allows for more mistakes at runtime. I don't think this is a good idea. |
Thanks for your response! So, I've managed to write the following function, which seems to be what I want: fn open_source(args: &Args) -> Result<pcap::Capture<pcap::Activated>, pcap::Error> {
let source = args.arg_source.as_ref();
pcap::Capture::from_device(source)
.map(|d| d.promisc(args.flag_promiscuous)
.rfmon(args.flag_promiscuous)
.snaplen(args.flag_snaplen)
.timeout(args.flag_timeout))
.and_then(|d| d.open())
.map(|mut c| c.into())
.or(
std::fs::metadata(source)
.map_err(|e| pcap::Error::PcapError(format!["{}", e]))
.and_then(|f|
if f.is_file() {
pcap::Capture::from_file(source)
.map(|mut c| c.into())
} else {
Err(pcap::Error::PcapError(
format!["{} is not a file or interface", source]))
}
)
)
} (apologies for potentially terrible / non-idiomatic Rust, I'm just learning) This compiles ok — I suppose this is due to
So now the compiler is complaining that |
I just updated pcap to 0.4.2 which should now allow you to do that. By the way, your code is very nice Rust -- nicer than I write usually. edit: Oh, I should elaborate on what's going on. |
Ah, that's great, thanks! My new fn open_capture(args: &Args) -> PcapResult {
let source = args.arg_source.as_ref();
let capture:PcapResult = pcap::Capture::from_device(source)
.map(|d| d.promisc(args.flag_promiscuous)
.rfmon(args.flag_promiscuous)
.snaplen(args.flag_snaplen)
.timeout(args.flag_timeout))
.and_then(|d| d.open())
.map(|c| c.into())
.or(
std::fs::metadata(source)
.map_err(|e| pcap::Error::PcapError(format!["{}", e]))
.and_then(|f|
if f.is_file() {
pcap::Capture::from_file(source)
.map(|c| c.into())
} else {
Err(pcap::Error::PcapError(
format!["{} is not a file or interface", source]))
}
)
)
;
capture.and_then(|mut c| {
try![c.filter(&args.flag_filter)];
Ok(c)
})
} and it almost works. :) I can open capture files, but there's an issue opening live interfaces... I'm quite certain that it's my fault, however; I think your library API is now very easy to use succinctly. Thank you! |
Add command-line parsing to allow the specification of an interface name or a filename. Once opened, treat these cap sources in the same way. Made possible by pcap improvements as discussed in rust-pcap/pcap#16.
This could be probably closed now? |
Probably could be, yup. |
Should they be tuple structs or enums?enums for now, structs later if necessary.ThedoneState
trait might need to be marked unsafe to follow the conventions of other libraries.The text was updated successfully, but these errors were encountered: