gio/auto/file_enumerator.rs
1// This file was generated by gir (https://github.com/gtk-rs/gir)
2// from gir-files (https://github.com/gtk-rs/gir-files)
3// DO NOT EDIT
4
5use crate::{AsyncResult, Cancellable, File, FileInfo, ffi};
6use glib::{prelude::*, translate::*};
7use std::{boxed::Box as Box_, pin::Pin};
8
9glib::wrapper! {
10 /// `GFileEnumerator` allows you to operate on a set of [`File`][crate::File] objects,
11 /// returning a [`FileInfo`][crate::FileInfo] structure for each file enumerated (e.g.
12 /// [`FileExt::enumerate_children()`][crate::prelude::FileExt::enumerate_children()] will return a `GFileEnumerator` for each
13 /// of the children within a directory).
14 ///
15 /// To get the next file's information from a `GFileEnumerator`, use
16 /// [`FileEnumeratorExt::next_file()`][crate::prelude::FileEnumeratorExt::next_file()] or its asynchronous version,
17 /// [`FileEnumeratorExt::next_files_async()`][crate::prelude::FileEnumeratorExt::next_files_async()]. Note that the asynchronous
18 /// version will return a list of [`FileInfo`][crate::FileInfo] objects, whereas the
19 /// synchronous will only return the next file in the enumerator.
20 ///
21 /// The ordering of returned files is unspecified for non-Unix
22 /// platforms; for more information, see `GLib::Dir::read_name()`. On Unix,
23 /// when operating on local files, returned files will be sorted by
24 /// inode number. Effectively you can assume that the ordering of
25 /// returned files will be stable between successive calls (and
26 /// applications) assuming the directory is unchanged.
27 ///
28 /// If your application needs a specific ordering, such as by name or
29 /// modification time, you will have to implement that in your
30 /// application code.
31 ///
32 /// To close a `GFileEnumerator`, use [`FileEnumeratorExtManual::close()`][crate::prelude::FileEnumeratorExtManual::close()], or
33 /// its asynchronous version, [`FileEnumeratorExt::close_async()`][crate::prelude::FileEnumeratorExt::close_async()]. Once
34 /// a `GFileEnumerator` is closed, no further actions may be performed
35 /// on it, and it should be freed with `GObject::Object::unref()`.
36 ///
37 /// ## Properties
38 ///
39 ///
40 /// #### `container`
41 /// The container that is being enumerated.
42 ///
43 /// Writable | Construct Only
44 ///
45 /// # Implements
46 ///
47 /// [`FileEnumeratorExt`][trait@crate::prelude::FileEnumeratorExt], [`trait@glib::ObjectExt`], [`FileEnumeratorExtManual`][trait@crate::prelude::FileEnumeratorExtManual]
48 #[doc(alias = "GFileEnumerator")]
49 pub struct FileEnumerator(Object<ffi::GFileEnumerator, ffi::GFileEnumeratorClass>);
50
51 match fn {
52 type_ => || ffi::g_file_enumerator_get_type(),
53 }
54}
55
56impl FileEnumerator {
57 pub const NONE: Option<&'static FileEnumerator> = None;
58}
59
60/// Trait containing all [`struct@FileEnumerator`] methods.
61///
62/// # Implementors
63///
64/// [`FileEnumerator`][struct@crate::FileEnumerator]
65pub trait FileEnumeratorExt: IsA<FileEnumerator> + 'static {
66 /// Asynchronously closes the file enumerator.
67 ///
68 /// If @cancellable is not `NULL`, then the operation can be cancelled by
69 /// triggering the cancellable object from another thread. If the operation
70 /// was cancelled, the error [error@Gio.IOErrorEnum.CANCELLED] will be returned
71 /// by `Gio::FileEnumerator::close_finish()`()].
72 /// ## `io_priority`
73 /// the [I/O priority](iface.AsyncResult.html#io-priority) of the
74 /// request
75 /// ## `cancellable`
76 /// optional cancellable object
77 /// ## `callback`
78 /// a callback to call when the
79 /// request is satisfied
80 #[doc(alias = "g_file_enumerator_close_async")]
81 fn close_async<P: FnOnce(Result<(), glib::Error>) + 'static>(
82 &self,
83 io_priority: glib::Priority,
84 cancellable: Option<&impl IsA<Cancellable>>,
85 callback: P,
86 ) {
87 let main_context = glib::MainContext::ref_thread_default();
88 let is_main_context_owner = main_context.is_owner();
89 let has_acquired_main_context = (!is_main_context_owner)
90 .then(|| main_context.acquire().ok())
91 .flatten();
92 assert!(
93 is_main_context_owner || has_acquired_main_context.is_some(),
94 "Async operations only allowed if the thread is owning the MainContext"
95 );
96
97 let user_data: Box_<glib::thread_guard::ThreadGuard<P>> =
98 Box_::new(glib::thread_guard::ThreadGuard::new(callback));
99 unsafe extern "C" fn close_async_trampoline<
100 P: FnOnce(Result<(), glib::Error>) + 'static,
101 >(
102 _source_object: *mut glib::gobject_ffi::GObject,
103 res: *mut crate::ffi::GAsyncResult,
104 user_data: glib::ffi::gpointer,
105 ) {
106 unsafe {
107 let mut error = std::ptr::null_mut();
108 ffi::g_file_enumerator_close_finish(_source_object as *mut _, res, &mut error);
109 let result = if error.is_null() {
110 Ok(())
111 } else {
112 Err(from_glib_full(error))
113 };
114 let callback: Box_<glib::thread_guard::ThreadGuard<P>> =
115 Box_::from_raw(user_data as *mut _);
116 let callback: P = callback.into_inner();
117 callback(result);
118 }
119 }
120 let callback = close_async_trampoline::<P>;
121 unsafe {
122 ffi::g_file_enumerator_close_async(
123 self.as_ref().to_glib_none().0,
124 io_priority.into_glib(),
125 cancellable.map(|p| p.as_ref()).to_glib_none().0,
126 Some(callback),
127 Box_::into_raw(user_data) as *mut _,
128 );
129 }
130 }
131
132 fn close_future(
133 &self,
134 io_priority: glib::Priority,
135 ) -> Pin<Box_<dyn std::future::Future<Output = Result<(), glib::Error>> + 'static>> {
136 Box_::pin(crate::GioFuture::new(
137 self,
138 move |obj, cancellable, send| {
139 obj.close_async(io_priority, Some(cancellable), move |res| {
140 send.resolve(res);
141 });
142 },
143 ))
144 }
145
146 /// Returns a new [`File`][crate::File] which refers to the file named by @info in the
147 /// source directory of @self.
148 ///
149 /// This function is primarily intended to be used inside loops with
150 /// [`next_file()`][Self::next_file()].
151 ///
152 /// To use this, `Gio::FILE_ATTRIBUTE_STANDARD_NAME` must have been listed
153 /// in the attributes list used when creating the [`FileEnumerator`][crate::FileEnumerator].
154 ///
155 /// This is a convenience method that's equivalent to:
156 /// **⚠️ The following code is in c ⚠️**
157 ///
158 /// ```c
159 /// char *name = g_file_info_get_name (info);
160 /// GFile *child = g_file_get_child (g_file_enumerator_get_container (enumerator), name);
161 /// ```
162 /// ## `info`
163 /// a file info object received from [`next_file()`][Self::next_file()]
164 /// or the async equivalent
165 ///
166 /// # Returns
167 ///
168 /// a file object for the file info object passed to it
169 #[doc(alias = "g_file_enumerator_get_child")]
170 #[doc(alias = "get_child")]
171 fn child(&self, info: &FileInfo) -> File {
172 unsafe {
173 from_glib_full(ffi::g_file_enumerator_get_child(
174 self.as_ref().to_glib_none().0,
175 info.to_glib_none().0,
176 ))
177 }
178 }
179
180 /// Get the [`File`][crate::File] container which is being enumerated.
181 ///
182 /// # Returns
183 ///
184 /// the file which is being enumerated
185 #[doc(alias = "g_file_enumerator_get_container")]
186 #[doc(alias = "get_container")]
187 fn container(&self) -> File {
188 unsafe {
189 from_glib_none(ffi::g_file_enumerator_get_container(
190 self.as_ref().to_glib_none().0,
191 ))
192 }
193 }
194
195 /// Checks if the file enumerator has pending operations.
196 ///
197 /// # Returns
198 ///
199 /// true if the @self has pending operations
200 #[doc(alias = "g_file_enumerator_has_pending")]
201 fn has_pending(&self) -> bool {
202 unsafe {
203 from_glib(ffi::g_file_enumerator_has_pending(
204 self.as_ref().to_glib_none().0,
205 ))
206 }
207 }
208
209 /// Checks if the file enumerator has been closed.
210 ///
211 /// # Returns
212 ///
213 /// true if the @self is closed
214 #[doc(alias = "g_file_enumerator_is_closed")]
215 fn is_closed(&self) -> bool {
216 unsafe {
217 from_glib(ffi::g_file_enumerator_is_closed(
218 self.as_ref().to_glib_none().0,
219 ))
220 }
221 }
222
223 /// Returns information for the next file in the enumerated object.
224 ///
225 /// Will block until the information is available. The [`FileInfo`][crate::FileInfo]
226 /// returned from this function will contain attributes that match the
227 /// attribute string that was passed when the file enumerator was created.
228 ///
229 /// See the documentation of [`FileEnumerator`][crate::FileEnumerator] for information about the
230 /// order of returned files.
231 ///
232 /// On error, returns `NULL` and sets @error to the error. If the
233 /// enumerator is at the end, `NULL` will be returned and @error will
234 /// be unset.
235 /// ## `cancellable`
236 /// optional cancellable object
237 ///
238 /// # Returns
239 ///
240 /// A file info object, or `NULL` on error
241 /// or end of enumerator
242 #[doc(alias = "g_file_enumerator_next_file")]
243 fn next_file(
244 &self,
245 cancellable: Option<&impl IsA<Cancellable>>,
246 ) -> Result<Option<FileInfo>, glib::Error> {
247 unsafe {
248 let mut error = std::ptr::null_mut();
249 let ret = ffi::g_file_enumerator_next_file(
250 self.as_ref().to_glib_none().0,
251 cancellable.map(|p| p.as_ref()).to_glib_none().0,
252 &mut error,
253 );
254 if error.is_null() {
255 Ok(from_glib_full(ret))
256 } else {
257 Err(from_glib_full(error))
258 }
259 }
260 }
261
262 /// Request information for a number of files from the enumerator asynchronously.
263 ///
264 /// When all I/O for the operation is finished the @callback will be called with
265 /// the requested information.
266 ///
267 /// See the documentation of [`FileEnumerator`][crate::FileEnumerator] for information about the
268 /// order of returned files.
269 ///
270 /// Once the end of the enumerator is reached, or if an error occurs, the
271 /// @callback will be called with an empty list. In this case, the previous call
272 /// to [`next_files_async()`][Self::next_files_async()] will typically have returned
273 /// fewer than @num_files items.
274 ///
275 /// If a request is cancelled the callback will be called with
276 /// [error@Gio.IOErrorEnum.CANCELLED].
277 ///
278 /// This leads to the following pseudo-code usage:
279 /// **⚠️ The following code is in c ⚠️**
280 ///
281 /// ```c
282 /// g_autoptr(GFile) dir = get_directory ();
283 /// g_autoptr(GFileEnumerator) enumerator = NULL;
284 /// g_autolist(GFileInfo) files = NULL;
285 /// g_autoptr(GError) local_error = NULL;
286 ///
287 /// enumerator = yield g_file_enumerate_children_async (dir,
288 /// G_FILE_ATTRIBUTE_STANDARD_NAME ","
289 /// G_FILE_ATTRIBUTE_STANDARD_TYPE,
290 /// G_FILE_QUERY_INFO_NONE,
291 /// G_PRIORITY_DEFAULT,
292 /// cancellable,
293 /// …,
294 /// &local_error);
295 /// if (enumerator == NULL)
296 /// g_error ("Error enumerating: %s", local_error->message);
297 ///
298 /// // Loop until no files are returned, either because the end of the enumerator
299 /// // has been reached, or an error was returned.
300 /// do
301 /// {
302 /// files = yield g_file_enumerator_next_files_async (enumerator,
303 /// 5, // number of files to request
304 /// G_PRIORITY_DEFAULT,
305 /// cancellable,
306 /// …,
307 /// &local_error);
308 ///
309 /// // Process the returned files, but don’t assume that exactly 5 were returned.
310 /// for (GList *l = files; l != NULL; l = l->next)
311 /// {
312 /// GFileInfo *info = l->data;
313 /// handle_file_info (info);
314 /// }
315 /// }
316 /// while (files != NULL);
317 ///
318 /// if (local_error != NULL &&
319 /// !g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
320 /// g_error ("Error while enumerating: %s", local_error->message);
321 /// ```
322 ///
323 /// During an async request no other sync and async calls are allowed, and will
324 /// result in [error@Gio.IOErrorEnum.PENDING] errors.
325 ///
326 /// Any outstanding I/O request with higher priority (lower numerical value) will
327 /// be executed before an outstanding request with lower priority. Default
328 /// priority is `GLib::PRIORITY_DEFAULT`.
329 /// ## `num_files`
330 /// the number of file info objects to request
331 /// ## `io_priority`
332 /// the [I/O priority](iface.AsyncResult.html#io-priority) of the
333 /// request
334 /// ## `cancellable`
335 /// optional cancellable object
336 /// ## `callback`
337 /// callback to call when the
338 /// request is satisfied
339 #[doc(alias = "g_file_enumerator_next_files_async")]
340 fn next_files_async<P: FnOnce(Result<Vec<FileInfo>, glib::Error>) + 'static>(
341 &self,
342 num_files: i32,
343 io_priority: glib::Priority,
344 cancellable: Option<&impl IsA<Cancellable>>,
345 callback: P,
346 ) {
347 let main_context = glib::MainContext::ref_thread_default();
348 let is_main_context_owner = main_context.is_owner();
349 let has_acquired_main_context = (!is_main_context_owner)
350 .then(|| main_context.acquire().ok())
351 .flatten();
352 assert!(
353 is_main_context_owner || has_acquired_main_context.is_some(),
354 "Async operations only allowed if the thread is owning the MainContext"
355 );
356
357 let user_data: Box_<glib::thread_guard::ThreadGuard<P>> =
358 Box_::new(glib::thread_guard::ThreadGuard::new(callback));
359 unsafe extern "C" fn next_files_async_trampoline<
360 P: FnOnce(Result<Vec<FileInfo>, glib::Error>) + 'static,
361 >(
362 _source_object: *mut glib::gobject_ffi::GObject,
363 res: *mut crate::ffi::GAsyncResult,
364 user_data: glib::ffi::gpointer,
365 ) {
366 unsafe {
367 let mut error = std::ptr::null_mut();
368 let ret = ffi::g_file_enumerator_next_files_finish(
369 _source_object as *mut _,
370 res,
371 &mut error,
372 );
373 let result = if error.is_null() {
374 Ok(FromGlibPtrContainer::from_glib_full(ret))
375 } else {
376 Err(from_glib_full(error))
377 };
378 let callback: Box_<glib::thread_guard::ThreadGuard<P>> =
379 Box_::from_raw(user_data as *mut _);
380 let callback: P = callback.into_inner();
381 callback(result);
382 }
383 }
384 let callback = next_files_async_trampoline::<P>;
385 unsafe {
386 ffi::g_file_enumerator_next_files_async(
387 self.as_ref().to_glib_none().0,
388 num_files,
389 io_priority.into_glib(),
390 cancellable.map(|p| p.as_ref()).to_glib_none().0,
391 Some(callback),
392 Box_::into_raw(user_data) as *mut _,
393 );
394 }
395 }
396
397 fn next_files_future(
398 &self,
399 num_files: i32,
400 io_priority: glib::Priority,
401 ) -> Pin<Box_<dyn std::future::Future<Output = Result<Vec<FileInfo>, glib::Error>> + 'static>>
402 {
403 Box_::pin(crate::GioFuture::new(
404 self,
405 move |obj, cancellable, send| {
406 obj.next_files_async(num_files, io_priority, Some(cancellable), move |res| {
407 send.resolve(res);
408 });
409 },
410 ))
411 }
412
413 /// Sets the file enumerator as having pending operations.
414 /// ## `pending`
415 /// a boolean value
416 #[doc(alias = "g_file_enumerator_set_pending")]
417 fn set_pending(&self, pending: bool) {
418 unsafe {
419 ffi::g_file_enumerator_set_pending(self.as_ref().to_glib_none().0, pending.into_glib());
420 }
421 }
422}
423
424impl<O: IsA<FileEnumerator>> FileEnumeratorExt for O {}