1use std::ffi::OsStr;
2use std::marker::PhantomData;
3use std::path::Path;
4
5use ::context::Context;
6use ::device::Device;
7use ::handle::Handle;
8
9
10pub struct Enumerator {
16 enumerator: *mut ::ffi::udev_enumerate,
17}
18
19impl Drop for Enumerator {
20 fn drop(&mut self) {
21 unsafe {
22 let udev = ::ffi::udev_enumerate_get_udev(self.enumerator);
23
24 ::ffi::udev_enumerate_unref(self.enumerator);
25 ::ffi::udev_unref(udev);
26 };
27 }
28}
29
30impl Enumerator {
31 pub fn new(context: &Context) -> ::Result<Self> {
33 unsafe {
34 let ptr = try_alloc!(
35 ::ffi::udev_enumerate_new(context.as_ptr())
36 );
37
38 ::ffi::udev_ref(context.as_ptr());
39
40 Ok(Enumerator { enumerator: ptr })
41 }
42 }
43
44 pub fn match_is_initialized(&mut self) -> ::Result<()> {
46 ::util::errno_to_result(unsafe {
47 ::ffi::udev_enumerate_add_match_is_initialized(self.enumerator)
48 })
49 }
50
51 pub fn match_subsystem<T: AsRef<OsStr>>(&mut self, subsystem: T) -> ::Result<()> {
53 let subsystem = try!(::util::os_str_to_cstring(subsystem));
54
55 ::util::errno_to_result(unsafe {
56 ::ffi::udev_enumerate_add_match_subsystem(self.enumerator, subsystem.as_ptr())
57 })
58 }
59
60 pub fn match_attribute<T: AsRef<OsStr>, U: AsRef<OsStr>>(&mut self, attribute: T, value: U) -> ::Result<()> {
62 let attribute = try!(::util::os_str_to_cstring(attribute));
63 let value = try!(::util::os_str_to_cstring(value));
64
65 ::util::errno_to_result(unsafe {
66 ::ffi::udev_enumerate_add_match_sysattr(self.enumerator, attribute.as_ptr(), value.as_ptr())
67 })
68 }
69
70 pub fn match_sysname<T: AsRef<OsStr>>(&mut self, sysname: T) -> ::Result<()> {
72 let sysname = try!(::util::os_str_to_cstring(sysname));
73
74 ::util::errno_to_result(unsafe {
75 ::ffi::udev_enumerate_add_match_sysname(self.enumerator, sysname.as_ptr())
76 })
77 }
78
79 pub fn match_property<T: AsRef<OsStr>, U: AsRef<OsStr>>(&mut self, property: T, value: U) -> ::Result<()> {
81 let property = try!(::util::os_str_to_cstring(property));
82 let value = try!(::util::os_str_to_cstring(value));
83
84 ::util::errno_to_result(unsafe {
85 ::ffi::udev_enumerate_add_match_property(self.enumerator, property.as_ptr(), value.as_ptr())
86 })
87 }
88
89 pub fn match_tag<T: AsRef<OsStr>>(&mut self, tag: T) -> ::Result<()> {
91 let tag = try!(::util::os_str_to_cstring(tag));
92
93 ::util::errno_to_result(unsafe {
94 ::ffi::udev_enumerate_add_match_tag(self.enumerator, tag.as_ptr())
95 })
96 }
97
98 pub fn match_parent(&mut self, parent: &Device) -> ::Result<()> {
100 ::util::errno_to_result(unsafe {
101 ::ffi::udev_enumerate_add_match_parent(self.enumerator, parent.as_ptr())
102 })
103 }
104
105 pub fn nomatch_subsystem<T: AsRef<OsStr>>(&mut self, subsystem: T) -> ::Result<()> {
107 let subsystem = try!(::util::os_str_to_cstring(subsystem));
108
109 ::util::errno_to_result(unsafe {
110 ::ffi::udev_enumerate_add_nomatch_subsystem(self.enumerator, subsystem.as_ptr())
111 })
112 }
113
114 pub fn nomatch_attribute<T: AsRef<OsStr>, U: AsRef<OsStr>>(&mut self, attribute: T, value: U) -> ::Result<()> {
116 let attribute = try!(::util::os_str_to_cstring(attribute));
117 let value = try!(::util::os_str_to_cstring(value));
118
119 ::util::errno_to_result(unsafe {
120 ::ffi::udev_enumerate_add_nomatch_sysattr(self.enumerator, attribute.as_ptr(), value.as_ptr())
121 })
122 }
123
124 pub fn add_syspath(&mut self, syspath: &Path) -> ::Result<()> {
126 let syspath = try!(::util::os_str_to_cstring(syspath));
127
128 ::util::errno_to_result(unsafe {
129 ::ffi::udev_enumerate_add_syspath(self.enumerator, syspath.as_ptr())
130 })
131 }
132
133 pub fn scan_devices(&mut self) -> ::Result<Devices> {
137 try!(::util::errno_to_result(unsafe {
138 ::ffi::udev_enumerate_scan_devices(self.enumerator)
139 }));
140
141 unsafe {
142 Ok(Devices {
143 _enumerator: PhantomData,
144 udev: ::ffi::udev_enumerate_get_udev(self.enumerator),
145 entry: ::ffi::udev_enumerate_get_list_entry(self.enumerator),
146 })
147 }
148 }
149}
150
151
152pub struct Devices<'a> {
154 _enumerator: PhantomData<&'a Enumerator>,
155 udev: *mut ::ffi::udev,
156 entry: *mut ::ffi::udev_list_entry,
157}
158
159impl<'a> Iterator for Devices<'a> {
160 type Item = Device;
161
162 fn next(&mut self) -> Option<Device> {
163 while !self.entry.is_null() {
164 unsafe {
165 let syspath = ::ffi::udev_list_entry_get_name(self.entry);
166
167 self.entry = ::ffi::udev_list_entry_get_next(self.entry);
168
169 let device = ::ffi::udev_device_new_from_syspath(self.udev, syspath);
170
171 if !device.is_null() {
172 return Some(::device::from_raw(device));
173 }
174 else {
175 continue;
176 }
177 };
178 }
179
180 None
181 }
182
183 fn size_hint(&self) -> (usize, Option<usize>) {
184 (0, None)
185 }
186}