Note (May 2015): this question was about the Rust language before it stabilized and 1.0 was released, and is now mostly of historical interest: the code will not compile on stable Rust, etc.
I'm writing a wrapper over libpcap for a project I'm working on, and to learn Rust (which I just started doing). I'm working on writing a safe Rust over around this right now:
#[link(name = "pcap")]
extern {
fn pcap_lookupdev(errormsg: *mut libc::c_char) -> *const libc::c_char;
}
Here's what I've got so far:
fn lookupdev() -> Result<String, String> {
// Capacity must be at least PCAP_ERRBUF_SIZE
let mut errbuf = [0 as c_char, ..256];
let result = unsafe {
let ptr = pcap_lookupdev(errbuf.as_mut_ptr() as *mut libc::c_char);
if ptr.is_null() {
None
}
else {
Some(CString::new(ptr, false))
}
};
match result {
Some(result) => Ok(result.as_str().unwrap().to_string()),
None => Err(unsafe { String::from_raw_buf(errbuf.as_ptr() as *const u8) })
}
}
This works, but I don't like the use from String::from_raw_buf, which will happily walk all over gigabytes of memory instead of stopping when it reaches the end of errbuf.
I can write something that loops over errbuf manually and converts it to a Rust string (stopping at the end of the buffer), but in my mind this is a C FFI idiom for strings (pass an allocated block of memory, where a string can be written) that should be supported by the Rust standard library. However, I could't find anything in the Rust FFI guide nor in the standard library documentation.
What's the best way of handling this FFI case in Rust? Is there at least a String::from_raw_buf_with_maxlen or a String::from_array?