Hi!
I am trying to write a function, which traverses a tree upwards, and searches for a specific attribute. The tree node with the matching attribute should be returned.
There is a type UdevDevice, which is a newtype wrapper around the libudev::Device type:
struct UdevDevice<'a>(Rc<libudev::Device<'a>>);
// Bunch of impls for newtype, like Clone, Deref, ...
The lifetime 'a of libudev::Device describes the lifetime of an associated libudev::Context, which must be alive while libudev::Device nodes exist.
pub struct Device<'a> {
_context: &'a Context,
device: *mut ::ffi::udev_device,
}
// Included Drop impl to show internal reference counting
impl<'a> Drop for Device<'a> {
fn drop(&mut self) {
unsafe {
::ffi::udev_device_unref(self.device);
}
}
}
/// A libudev context.
pub struct Context {
udev: *mut ::ffi::udev
}
So here is my attempt at writing the search function (pseudo code):
fn main() {
let context = /* ... */;
let device = /* Get device from context + wrap in newtype */;
let m = find_node(&device, |s| s == "usb", "subsystem");
/* ... */
}
fn find_node<'a, P: Fn(&str) -> bool>(node: &UdevDevice<'a>,
predicate: P, attribute: &str)
-> Option<UdevDevice<'a>> {
if (predicate)(node.attribute_value(attribute)) {
Some(node.clone())
} else if let Some(i) = node.parent() {
find_node(&i, predicate, attribute)
// ^_______________________________________________________
// | Can not use i, because i is borrowed from the current |
// | function. |
// \-------------------------------------------------------/
} else {
None
}
}
Essentially, the problem is,. that I can not proof to the compiler, that my UdevDevice node is just dependent on 'a.
Maybe the libudev crate is the problem here? I already considered trying to write a newtype, which implements Clone by using the libudev ffi API to udev_device_ref the node for each clone.