sdl3_sys/generated/
storage.rs

1//! The storage API is a high-level API designed to abstract away the
2//! portability issues that come up when using something lower-level (in SDL's
3//! case, this sits on top of the [Filesystem](CategoryFilesystem) and
4//! [IOStream](CategoryIOStream) subsystems). It is significantly more
5//! restrictive than a typical filesystem API, for a number of reasons:
6//!
7//! 1. **What to Access:** A common pitfall with existing filesystem APIs is
8//! the assumption that all storage is monolithic. However, many other
9//! platforms (game consoles in particular) are more strict about what _type_
10//! of filesystem is being accessed; for example, game content and user data
11//! are usually two separate storage devices with entirely different
12//! characteristics (and possibly different low-level APIs altogether!).
13//!
14//! 2. **How to Access:** Another common mistake is applications assuming that
15//! all storage is universally writeable - again, many platforms treat game
16//! content and user data as two separate storage devices, and only user data
17//! is writeable while game content is read-only.
18//!
19//! 3. **When to Access:** The most common portability issue with filesystem
20//! access is _timing_ - you cannot always assume that the storage device is
21//! always accessible all of the time, nor can you assume that there are no
22//! limits to how long you have access to a particular device.
23//!
24//! Consider the following example:
25//!
26//! ```c
27//! void ReadGameData(void)
28//! {
29//!     extern char** fileNames;
30//!     extern size_t numFiles;
31//!     for (size_t i = 0; i < numFiles; i += 1) {
32//!         FILE *data = fopen(fileNames[i], "rwb");
33//!         if (data == NULL) {
34//!             // Something bad happened!
35//!         } else {
36//!             // A bunch of stuff happens here
37//!             fclose(data);
38//!         }
39//!     }
40//! }
41//!
42//! void ReadSave(void)
43//! {
44//!     FILE *save = fopen("saves/save0.sav", "rb");
45//!     if (save == NULL) {
46//!         // Something bad happened!
47//!     } else {
48//!         // A bunch of stuff happens here
49//!         fclose(save);
50//!     }
51//! }
52//!
53//! void WriteSave(void)
54//! {
55//!     FILE *save = fopen("saves/save0.sav", "wb");
56//!     if (save == NULL) {
57//!         // Something bad happened!
58//!     } else {
59//!         // A bunch of stuff happens here
60//!         fclose(save);
61//!     }
62//! }
63//! ```
64//!
65//! Going over the bullet points again:
66//!
67//! 1. **What to Access:** This code accesses a global filesystem; game data
68//! and saves are all presumed to be in the current working directory (which
69//! may or may not be the game's installation folder!).
70//!
71//! 2. **How to Access:** This code assumes that content paths are writeable,
72//! and that save data is also writeable despite being in the same location as
73//! the game data.
74//!
75//! 3. **When to Access:** This code assumes that they can be called at any
76//! time, since the filesystem is always accessible and has no limits on how
77//! long the filesystem is being accessed.
78//!
79//! Due to these assumptions, the filesystem code is not portable and will fail
80//! under these common scenarios:
81//!
82//! - The game is installed on a device that is read-only, both content loading
83//!   and game saves will fail or crash outright
84//! - Game/User storage is not implicitly mounted, so no files will be found
85//!   for either scenario when a platform requires explicitly mounting
86//!   filesystems
87//! - Save data may not be safe since the I/O is not being flushed or
88//!   validated, so an error occurring elsewhere in the program may result in
89//!   missing/corrupted save data
90//!
91//! When using [`SDL_Storage`], these types of problems are virtually impossible to
92//! trip over:
93//!
94//! ```c
95//! void ReadGameData(void)
96//! {
97//!     extern char** fileNames;
98//!     extern size_t numFiles;
99//!
100//!     SDL_Storage *title = SDL_OpenTitleStorage(NULL, 0);
101//!     if (title == NULL) {
102//!         // Something bad happened!
103//!     }
104//!     while (!SDL_StorageReady(title)) {
105//!         SDL_Delay(1);
106//!     }
107//!
108//!     for (size_t i = 0; i < numFiles; i += 1) {
109//!         void* dst;
110//!         Uint64 dstLen = 0;
111//!
112//!         if (SDL_GetStorageFileSize(title, fileNames[i], &dstLen) && dstLen > 0) {
113//!             dst = SDL_malloc(dstLen);
114//!             if (SDL_ReadStorageFile(title, fileNames[i], dst, dstLen)) {
115//!                 // A bunch of stuff happens here
116//!             } else {
117//!                 // Something bad happened!
118//!             }
119//!             SDL_free(dst);
120//!         } else {
121//!             // Something bad happened!
122//!         }
123//!     }
124//!
125//!     SDL_CloseStorage(title);
126//! }
127//!
128//! void ReadSave(void)
129//! {
130//!     SDL_Storage *user = SDL_OpenUserStorage("libsdl", "Storage Example", 0);
131//!     if (user == NULL) {
132//!         // Something bad happened!
133//!     }
134//!     while (!SDL_StorageReady(user)) {
135//!         SDL_Delay(1);
136//!     }
137//!
138//!     Uint64 saveLen = 0;
139//!     if (SDL_GetStorageFileSize(user, "save0.sav", &saveLen) && saveLen > 0) {
140//!         void* dst = SDL_malloc(saveLen);
141//!         if (SDL_ReadStorageFile(user, "save0.sav", dst, saveLen)) {
142//!             // A bunch of stuff happens here
143//!         } else {
144//!             // Something bad happened!
145//!         }
146//!         SDL_free(dst);
147//!     } else {
148//!         // Something bad happened!
149//!     }
150//!
151//!     SDL_CloseStorage(user);
152//! }
153//!
154//! void WriteSave(void)
155//! {
156//!     SDL_Storage *user = SDL_OpenUserStorage("libsdl", "Storage Example", 0);
157//!     if (user == NULL) {
158//!         // Something bad happened!
159//!     }
160//!     while (!SDL_StorageReady(user)) {
161//!         SDL_Delay(1);
162//!     }
163//!
164//!     extern void *saveData; // A bunch of stuff happened here...
165//!     extern Uint64 saveLen;
166//!     if (!SDL_WriteStorageFile(user, "save0.sav", saveData, saveLen)) {
167//!         // Something bad happened!
168//!     }
169//!
170//!     SDL_CloseStorage(user);
171//! }
172//! ```
173//!
174//! Note the improvements that [`SDL_Storage`] makes:
175//!
176//! 1. **What to Access:** This code explicitly reads from a title or user
177//! storage device based on the context of the function.
178//!
179//! 2. **How to Access:** This code explicitly uses either a read or write
180//! function based on the context of the function.
181//!
182//! 3. **When to Access:** This code explicitly opens the device when it needs
183//! to, and closes it when it is finished working with the filesystem.
184//!
185//! The result is an application that is significantly more robust against the
186//! increasing demands of platforms and their filesystems!
187//!
188//! A publicly available example of an [`SDL_Storage`] backend is the
189//! [Steam Cloud](https://partner.steamgames.com/doc/features/cloud)
190//! backend - you can initialize Steamworks when starting the program, and then
191//! SDL will recognize that Steamworks is initialized and automatically use
192//! ISteamRemoteStorage when the application opens user storage. More
193//! importantly, when you _open_ storage it knows to begin a "batch" of
194//! filesystem operations, and when you _close_ storage it knows to end and
195//! flush the batch. This is used by Steam to support
196//! [Dynamic Cloud Sync](https://steamcommunity.com/groups/steamworks/announcements/detail/3142949576401813670)
197//! ; users can save data on one PC, put the device to sleep, and then continue
198//! playing on another PC (and vice versa) with the save data fully
199//! synchronized across all devices, allowing for a seamless experience without
200//! having to do full restarts of the program.
201//!
202//! ## Notes on valid paths
203//!
204//! All paths in the Storage API use Unix-style path separators ('/'). Using a
205//! different path separator will not work, even if the underlying platform
206//! would otherwise accept it. This is to keep code using the Storage API
207//! portable between platforms and Storage implementations and simplify app
208//! code.
209//!
210//! Paths with relative directories ("." and "..") are forbidden by the Storage
211//! API.
212//!
213//! All valid UTF-8 strings (discounting the NULL terminator character and the
214//! '/' path separator) are usable for filenames, however, an underlying
215//! Storage implementation may not support particularly strange sequences and
216//! refuse to create files with those names, etc.
217
218use super::stdinc::*;
219
220use super::error::*;
221
222use super::filesystem::*;
223
224use super::properties::*;
225
226/// Function interface for [`SDL_Storage`].
227///
228/// Apps that want to supply a custom implementation of [`SDL_Storage`] will fill
229/// in all the functions in this struct, and then pass it to [`SDL_OpenStorage`] to
230/// create a custom [`SDL_Storage`] object.
231///
232/// It is not usually necessary to do this; SDL provides standard
233/// implementations for many things you might expect to do with an [`SDL_Storage`].
234///
235/// This structure should be initialized using [`SDL_INIT_INTERFACE()`]
236///
237/// ## Availability
238/// This struct is available since SDL 3.2.0.
239///
240/// ## See also
241/// - [`SDL_INIT_INTERFACE`]
242///
243/// ## Notes for `sdl3-sys`
244/// This interface struct can be initialized with [`SDL_StorageInterface::new()`] or `Default::default()`.
245#[repr(C)]
246#[cfg_attr(feature = "debug-impls", derive(Debug))]
247pub struct SDL_StorageInterface {
248    pub version: Uint32,
249    pub close: ::core::option::Option<
250        unsafe extern "C" fn(userdata: *mut ::core::ffi::c_void) -> ::core::primitive::bool,
251    >,
252    pub ready: ::core::option::Option<
253        unsafe extern "C" fn(userdata: *mut ::core::ffi::c_void) -> ::core::primitive::bool,
254    >,
255    pub enumerate: ::core::option::Option<
256        unsafe extern "C" fn(
257            userdata: *mut ::core::ffi::c_void,
258            path: *const ::core::ffi::c_char,
259            callback: SDL_EnumerateDirectoryCallback,
260            callback_userdata: *mut ::core::ffi::c_void,
261        ) -> ::core::primitive::bool,
262    >,
263    pub info: ::core::option::Option<
264        unsafe extern "C" fn(
265            userdata: *mut ::core::ffi::c_void,
266            path: *const ::core::ffi::c_char,
267            info: *mut SDL_PathInfo,
268        ) -> ::core::primitive::bool,
269    >,
270    pub read_file: ::core::option::Option<
271        unsafe extern "C" fn(
272            userdata: *mut ::core::ffi::c_void,
273            path: *const ::core::ffi::c_char,
274            destination: *mut ::core::ffi::c_void,
275            length: Uint64,
276        ) -> ::core::primitive::bool,
277    >,
278    pub write_file: ::core::option::Option<
279        unsafe extern "C" fn(
280            userdata: *mut ::core::ffi::c_void,
281            path: *const ::core::ffi::c_char,
282            source: *const ::core::ffi::c_void,
283            length: Uint64,
284        ) -> ::core::primitive::bool,
285    >,
286    pub mkdir: ::core::option::Option<
287        unsafe extern "C" fn(
288            userdata: *mut ::core::ffi::c_void,
289            path: *const ::core::ffi::c_char,
290        ) -> ::core::primitive::bool,
291    >,
292    pub remove: ::core::option::Option<
293        unsafe extern "C" fn(
294            userdata: *mut ::core::ffi::c_void,
295            path: *const ::core::ffi::c_char,
296        ) -> ::core::primitive::bool,
297    >,
298    pub rename: ::core::option::Option<
299        unsafe extern "C" fn(
300            userdata: *mut ::core::ffi::c_void,
301            oldpath: *const ::core::ffi::c_char,
302            newpath: *const ::core::ffi::c_char,
303        ) -> ::core::primitive::bool,
304    >,
305    pub copy: ::core::option::Option<
306        unsafe extern "C" fn(
307            userdata: *mut ::core::ffi::c_void,
308            oldpath: *const ::core::ffi::c_char,
309            newpath: *const ::core::ffi::c_char,
310        ) -> ::core::primitive::bool,
311    >,
312    pub space_remaining:
313        ::core::option::Option<unsafe extern "C" fn(userdata: *mut ::core::ffi::c_void) -> Uint64>,
314}
315
316impl SDL_StorageInterface {
317    /// Create a new `SDL_StorageInterface` initialized with `SDL_INIT_INTERFACE`
318    #[inline]
319    pub const fn new() -> Self {
320        const { ::core::assert!(::core::mem::size_of::<Self>() <= ::core::primitive::u32::MAX as usize) };
321        let mut this = unsafe { ::core::mem::MaybeUninit::<Self>::zeroed().assume_init() };
322        this.version = ::core::mem::size_of::<Self>() as ::core::primitive::u32;
323        this
324    }
325}
326
327impl ::core::default::Default for SDL_StorageInterface {
328    /// Create a new `SDL_StorageInterface` initialized with `SDL_INIT_INTERFACE`
329    #[inline(always)]
330    fn default() -> Self {
331        Self::new()
332    }
333}
334
335const _: () = ::core::assert!(
336    (((::core::mem::size_of::<*mut ::core::ffi::c_void>() == 4_usize)
337        && (::core::mem::size_of::<SDL_StorageInterface>() == 48_usize))
338        || ((::core::mem::size_of::<*mut ::core::ffi::c_void>() == 8_usize)
339            && (::core::mem::size_of::<SDL_StorageInterface>() == 96_usize)))
340);
341
342unsafe extern "C" {
343    /// Opens up a read-only container for the application's filesystem.
344    ///
345    /// By default, [`SDL_OpenTitleStorage`] uses the generic storage implementation.
346    /// When the path override is not provided, the generic implementation will use
347    /// the output of [`SDL_GetBasePath`] as the base path.
348    ///
349    /// ## Parameters
350    /// - `override`: a path to override the backend's default title root.
351    /// - `props`: a property list that may contain backend-specific information.
352    ///
353    /// ## Return value
354    /// Returns a title storage container on success or NULL on failure; call
355    ///   [`SDL_GetError()`] for more information.
356    ///
357    /// ## Availability
358    /// This function is available since SDL 3.2.0.
359    ///
360    /// ## See also
361    /// - [`SDL_CloseStorage`]
362    /// - [`SDL_GetStorageFileSize`]
363    /// - [`SDL_OpenUserStorage`]
364    /// - [`SDL_ReadStorageFile`]
365    pub fn SDL_OpenTitleStorage(
366        r#override: *const ::core::ffi::c_char,
367        props: SDL_PropertiesID,
368    ) -> *mut SDL_Storage;
369}
370
371unsafe extern "C" {
372    /// Opens up a container for a user's unique read/write filesystem.
373    ///
374    /// While title storage can generally be kept open throughout runtime, user
375    /// storage should only be opened when the client is ready to read/write files.
376    /// This allows the backend to properly batch file operations and flush them
377    /// when the container has been closed; ensuring safe and optimal save I/O.
378    ///
379    /// ## Parameters
380    /// - `org`: the name of your organization.
381    /// - `app`: the name of your application.
382    /// - `props`: a property list that may contain backend-specific information.
383    ///
384    /// ## Return value
385    /// Returns a user storage container on success or NULL on failure; call
386    ///   [`SDL_GetError()`] for more information.
387    ///
388    /// ## Availability
389    /// This function is available since SDL 3.2.0.
390    ///
391    /// ## See also
392    /// - [`SDL_CloseStorage`]
393    /// - [`SDL_GetStorageFileSize`]
394    /// - [`SDL_GetStorageSpaceRemaining`]
395    /// - [`SDL_OpenTitleStorage`]
396    /// - [`SDL_ReadStorageFile`]
397    /// - [`SDL_StorageReady`]
398    /// - [`SDL_WriteStorageFile`]
399    pub fn SDL_OpenUserStorage(
400        org: *const ::core::ffi::c_char,
401        app: *const ::core::ffi::c_char,
402        props: SDL_PropertiesID,
403    ) -> *mut SDL_Storage;
404}
405
406unsafe extern "C" {
407    /// Opens up a container for local filesystem storage.
408    ///
409    /// This is provided for development and tools. Portable applications should
410    /// use [`SDL_OpenTitleStorage()`] for access to game data and
411    /// [`SDL_OpenUserStorage()`] for access to user data.
412    ///
413    /// ## Parameters
414    /// - `path`: the base path prepended to all storage paths, or NULL for no
415    ///   base path.
416    ///
417    /// ## Return value
418    /// Returns a filesystem storage container on success or NULL on failure; call
419    ///   [`SDL_GetError()`] for more information.
420    ///
421    /// ## Availability
422    /// This function is available since SDL 3.2.0.
423    ///
424    /// ## See also
425    /// - [`SDL_CloseStorage`]
426    /// - [`SDL_GetStorageFileSize`]
427    /// - [`SDL_GetStorageSpaceRemaining`]
428    /// - [`SDL_OpenTitleStorage`]
429    /// - [`SDL_OpenUserStorage`]
430    /// - [`SDL_ReadStorageFile`]
431    /// - [`SDL_WriteStorageFile`]
432    pub fn SDL_OpenFileStorage(path: *const ::core::ffi::c_char) -> *mut SDL_Storage;
433}
434
435unsafe extern "C" {
436    /// Opens up a container using a client-provided storage interface.
437    ///
438    /// Applications do not need to use this function unless they are providing
439    /// their own [`SDL_Storage`] implementation. If you just need an [`SDL_Storage`], you
440    /// should use the built-in implementations in SDL, like [`SDL_OpenTitleStorage()`]
441    /// or [`SDL_OpenUserStorage()`].
442    ///
443    /// This function makes a copy of `iface` and the caller does not need to keep
444    /// it around after this call.
445    ///
446    /// ## Parameters
447    /// - `iface`: the interface that implements this storage, initialized using
448    ///   [`SDL_INIT_INTERFACE()`].
449    /// - `userdata`: the pointer that will be passed to the interface functions.
450    ///
451    /// ## Return value
452    /// Returns a storage container on success or NULL on failure; call
453    ///   [`SDL_GetError()`] for more information.
454    ///
455    /// ## Availability
456    /// This function is available since SDL 3.2.0.
457    ///
458    /// ## See also
459    /// - [`SDL_CloseStorage`]
460    /// - [`SDL_GetStorageFileSize`]
461    /// - [`SDL_GetStorageSpaceRemaining`]
462    /// - [`SDL_INIT_INTERFACE`]
463    /// - [`SDL_ReadStorageFile`]
464    /// - [`SDL_StorageReady`]
465    /// - [`SDL_WriteStorageFile`]
466    pub fn SDL_OpenStorage(
467        iface: *const SDL_StorageInterface,
468        userdata: *mut ::core::ffi::c_void,
469    ) -> *mut SDL_Storage;
470}
471
472unsafe extern "C" {
473    /// Closes and frees a storage container.
474    ///
475    /// ## Parameters
476    /// - `storage`: a storage container to close.
477    ///
478    /// ## Return value
479    /// Returns true if the container was freed with no errors, false otherwise;
480    ///   call [`SDL_GetError()`] for more information. Even if the function
481    ///   returns an error, the container data will be freed; the error is
482    ///   only for informational purposes.
483    ///
484    /// ## Availability
485    /// This function is available since SDL 3.2.0.
486    ///
487    /// ## See also
488    /// - [`SDL_OpenFileStorage`]
489    /// - [`SDL_OpenStorage`]
490    /// - [`SDL_OpenTitleStorage`]
491    /// - [`SDL_OpenUserStorage`]
492    pub fn SDL_CloseStorage(storage: *mut SDL_Storage) -> ::core::primitive::bool;
493}
494
495unsafe extern "C" {
496    /// Checks if the storage container is ready to use.
497    ///
498    /// This function should be called in regular intervals until it returns true -
499    /// however, it is not recommended to spinwait on this call, as the backend may
500    /// depend on a synchronous message loop. You might instead poll this in your
501    /// game's main loop while processing events and drawing a loading screen.
502    ///
503    /// ## Parameters
504    /// - `storage`: a storage container to query.
505    ///
506    /// ## Return value
507    /// Returns true if the container is ready, false otherwise.
508    ///
509    /// ## Availability
510    /// This function is available since SDL 3.2.0.
511    pub fn SDL_StorageReady(storage: *mut SDL_Storage) -> ::core::primitive::bool;
512}
513
514unsafe extern "C" {
515    /// Query the size of a file within a storage container.
516    ///
517    /// ## Parameters
518    /// - `storage`: a storage container to query.
519    /// - `path`: the relative path of the file to query.
520    /// - `length`: a pointer to be filled with the file's length.
521    ///
522    /// ## Return value
523    /// Returns true if the file could be queried or false on failure; call
524    ///   [`SDL_GetError()`] for more information.
525    ///
526    /// ## Availability
527    /// This function is available since SDL 3.2.0.
528    ///
529    /// ## See also
530    /// - [`SDL_ReadStorageFile`]
531    /// - [`SDL_StorageReady`]
532    pub fn SDL_GetStorageFileSize(
533        storage: *mut SDL_Storage,
534        path: *const ::core::ffi::c_char,
535        length: *mut Uint64,
536    ) -> ::core::primitive::bool;
537}
538
539unsafe extern "C" {
540    /// Synchronously read a file from a storage container into a client-provided
541    /// buffer.
542    ///
543    /// The value of `length` must match the length of the file exactly; call
544    /// [`SDL_GetStorageFileSize()`] to get this value. This behavior may be relaxed in
545    /// a future release.
546    ///
547    /// ## Parameters
548    /// - `storage`: a storage container to read from.
549    /// - `path`: the relative path of the file to read.
550    /// - `destination`: a client-provided buffer to read the file into.
551    /// - `length`: the length of the destination buffer.
552    ///
553    /// ## Return value
554    /// Returns true if the file was read or false on failure; call [`SDL_GetError()`]
555    ///   for more information.
556    ///
557    /// ## Availability
558    /// This function is available since SDL 3.2.0.
559    ///
560    /// ## See also
561    /// - [`SDL_GetStorageFileSize`]
562    /// - [`SDL_StorageReady`]
563    /// - [`SDL_WriteStorageFile`]
564    pub fn SDL_ReadStorageFile(
565        storage: *mut SDL_Storage,
566        path: *const ::core::ffi::c_char,
567        destination: *mut ::core::ffi::c_void,
568        length: Uint64,
569    ) -> ::core::primitive::bool;
570}
571
572unsafe extern "C" {
573    /// Synchronously write a file from client memory into a storage container.
574    ///
575    /// ## Parameters
576    /// - `storage`: a storage container to write to.
577    /// - `path`: the relative path of the file to write.
578    /// - `source`: a client-provided buffer to write from.
579    /// - `length`: the length of the source buffer.
580    ///
581    /// ## Return value
582    /// Returns true if the file was written or false on failure; call
583    ///   [`SDL_GetError()`] for more information.
584    ///
585    /// ## Availability
586    /// This function is available since SDL 3.2.0.
587    ///
588    /// ## See also
589    /// - [`SDL_GetStorageSpaceRemaining`]
590    /// - [`SDL_ReadStorageFile`]
591    /// - [`SDL_StorageReady`]
592    pub fn SDL_WriteStorageFile(
593        storage: *mut SDL_Storage,
594        path: *const ::core::ffi::c_char,
595        source: *const ::core::ffi::c_void,
596        length: Uint64,
597    ) -> ::core::primitive::bool;
598}
599
600unsafe extern "C" {
601    /// Create a directory in a writable storage container.
602    ///
603    /// ## Parameters
604    /// - `storage`: a storage container.
605    /// - `path`: the path of the directory to create.
606    ///
607    /// ## Return value
608    /// Returns true on success or false on failure; call [`SDL_GetError()`] for more
609    ///   information.
610    ///
611    /// ## Availability
612    /// This function is available since SDL 3.2.0.
613    ///
614    /// ## See also
615    /// - [`SDL_StorageReady`]
616    pub fn SDL_CreateStorageDirectory(
617        storage: *mut SDL_Storage,
618        path: *const ::core::ffi::c_char,
619    ) -> ::core::primitive::bool;
620}
621
622unsafe extern "C" {
623    /// Enumerate a directory in a storage container through a callback function.
624    ///
625    /// This function provides every directory entry through an app-provided
626    /// callback, called once for each directory entry, until all results have been
627    /// provided or the callback returns either [`SDL_ENUM_SUCCESS`] or
628    /// [`SDL_ENUM_FAILURE`].
629    ///
630    /// This will return false if there was a system problem in general, or if a
631    /// callback returns [`SDL_ENUM_FAILURE`]. A successful return means a callback
632    /// returned [`SDL_ENUM_SUCCESS`] to halt enumeration, or all directory entries
633    /// were enumerated.
634    ///
635    /// If `path` is NULL, this is treated as a request to enumerate the root of
636    /// the storage container's tree. An empty string also works for this.
637    ///
638    /// ## Parameters
639    /// - `storage`: a storage container.
640    /// - `path`: the path of the directory to enumerate, or NULL for the root.
641    /// - `callback`: a function that is called for each entry in the directory.
642    /// - `userdata`: a pointer that is passed to `callback`.
643    ///
644    /// ## Return value
645    /// Returns true on success or false on failure; call [`SDL_GetError()`] for more
646    ///   information.
647    ///
648    /// ## Availability
649    /// This function is available since SDL 3.2.0.
650    ///
651    /// ## See also
652    /// - [`SDL_StorageReady`]
653    pub fn SDL_EnumerateStorageDirectory(
654        storage: *mut SDL_Storage,
655        path: *const ::core::ffi::c_char,
656        callback: SDL_EnumerateDirectoryCallback,
657        userdata: *mut ::core::ffi::c_void,
658    ) -> ::core::primitive::bool;
659}
660
661unsafe extern "C" {
662    /// Remove a file or an empty directory in a writable storage container.
663    ///
664    /// ## Parameters
665    /// - `storage`: a storage container.
666    /// - `path`: the path of the directory to enumerate.
667    ///
668    /// ## Return value
669    /// Returns true on success or false on failure; call [`SDL_GetError()`] for more
670    ///   information.
671    ///
672    /// ## Availability
673    /// This function is available since SDL 3.2.0.
674    ///
675    /// ## See also
676    /// - [`SDL_StorageReady`]
677    pub fn SDL_RemoveStoragePath(
678        storage: *mut SDL_Storage,
679        path: *const ::core::ffi::c_char,
680    ) -> ::core::primitive::bool;
681}
682
683unsafe extern "C" {
684    /// Rename a file or directory in a writable storage container.
685    ///
686    /// ## Parameters
687    /// - `storage`: a storage container.
688    /// - `oldpath`: the old path.
689    /// - `newpath`: the new path.
690    ///
691    /// ## Return value
692    /// Returns true on success or false on failure; call [`SDL_GetError()`] for more
693    ///   information.
694    ///
695    /// ## Availability
696    /// This function is available since SDL 3.2.0.
697    ///
698    /// ## See also
699    /// - [`SDL_StorageReady`]
700    pub fn SDL_RenameStoragePath(
701        storage: *mut SDL_Storage,
702        oldpath: *const ::core::ffi::c_char,
703        newpath: *const ::core::ffi::c_char,
704    ) -> ::core::primitive::bool;
705}
706
707unsafe extern "C" {
708    /// Copy a file in a writable storage container.
709    ///
710    /// ## Parameters
711    /// - `storage`: a storage container.
712    /// - `oldpath`: the old path.
713    /// - `newpath`: the new path.
714    ///
715    /// ## Return value
716    /// Returns true on success or false on failure; call [`SDL_GetError()`] for more
717    ///   information.
718    ///
719    /// ## Availability
720    /// This function is available since SDL 3.2.0.
721    ///
722    /// ## See also
723    /// - [`SDL_StorageReady`]
724    pub fn SDL_CopyStorageFile(
725        storage: *mut SDL_Storage,
726        oldpath: *const ::core::ffi::c_char,
727        newpath: *const ::core::ffi::c_char,
728    ) -> ::core::primitive::bool;
729}
730
731unsafe extern "C" {
732    /// Get information about a filesystem path in a storage container.
733    ///
734    /// ## Parameters
735    /// - `storage`: a storage container.
736    /// - `path`: the path to query.
737    /// - `info`: a pointer filled in with information about the path, or NULL to
738    ///   check for the existence of a file.
739    ///
740    /// ## Return value
741    /// Returns true on success or false if the file doesn't exist, or another
742    ///   failure; call [`SDL_GetError()`] for more information.
743    ///
744    /// ## Availability
745    /// This function is available since SDL 3.2.0.
746    ///
747    /// ## See also
748    /// - [`SDL_StorageReady`]
749    pub fn SDL_GetStoragePathInfo(
750        storage: *mut SDL_Storage,
751        path: *const ::core::ffi::c_char,
752        info: *mut SDL_PathInfo,
753    ) -> ::core::primitive::bool;
754}
755
756unsafe extern "C" {
757    /// Queries the remaining space in a storage container.
758    ///
759    /// ## Parameters
760    /// - `storage`: a storage container to query.
761    ///
762    /// ## Return value
763    /// Returns the amount of remaining space, in bytes.
764    ///
765    /// ## Availability
766    /// This function is available since SDL 3.2.0.
767    ///
768    /// ## See also
769    /// - [`SDL_StorageReady`]
770    /// - [`SDL_WriteStorageFile`]
771    pub fn SDL_GetStorageSpaceRemaining(storage: *mut SDL_Storage) -> Uint64;
772}
773
774unsafe extern "C" {
775    /// Enumerate a directory tree, filtered by pattern, and return a list.
776    ///
777    /// Files are filtered out if they don't match the string in `pattern`, which
778    /// may contain wildcard characters `*` (match everything) and `?` (match one
779    /// character). If pattern is NULL, no filtering is done and all results are
780    /// returned. Subdirectories are permitted, and are specified with a path
781    /// separator of '/'. Wildcard characters `*` and `?` never match a path
782    /// separator.
783    ///
784    /// `flags` may be set to [`SDL_GLOB_CASEINSENSITIVE`] to make the pattern matching
785    /// case-insensitive.
786    ///
787    /// The returned array is always NULL-terminated, for your iterating
788    /// convenience, but if `count` is non-NULL, on return it will contain the
789    /// number of items in the array, not counting the NULL terminator.
790    ///
791    /// If `path` is NULL, this is treated as a request to enumerate the root of
792    /// the storage container's tree. An empty string also works for this.
793    ///
794    /// ## Parameters
795    /// - `storage`: a storage container.
796    /// - `path`: the path of the directory to enumerate, or NULL for the root.
797    /// - `pattern`: the pattern that files in the directory must match. Can be
798    ///   NULL.
799    /// - `flags`: `SDL_GLOB_*` bitflags that affect this search.
800    /// - `count`: on return, will be set to the number of items in the returned
801    ///   array. Can be NULL.
802    ///
803    /// ## Return value
804    /// Returns an array of strings on success or NULL on failure; call
805    ///   [`SDL_GetError()`] for more information. The caller should pass the
806    ///   returned pointer to [`SDL_free`] when done with it. This is a single
807    ///   allocation that should be freed with [`SDL_free()`] when it is no
808    ///   longer needed.
809    ///
810    /// ## Thread safety
811    /// It is safe to call this function from any thread, assuming
812    ///   the `storage` object is thread-safe.
813    ///
814    /// ## Availability
815    /// This function is available since SDL 3.2.0.
816    pub fn SDL_GlobStorageDirectory(
817        storage: *mut SDL_Storage,
818        path: *const ::core::ffi::c_char,
819        pattern: *const ::core::ffi::c_char,
820        flags: SDL_GlobFlags,
821        count: *mut ::core::ffi::c_int,
822    ) -> *mut *mut ::core::ffi::c_char;
823}
824
825/// An abstract interface for filesystem access.
826///
827/// This is an opaque datatype. One can create this object using standard SDL
828/// functions like [`SDL_OpenTitleStorage`] or [`SDL_OpenUserStorage`], etc, or create
829/// an object with a custom implementation using [`SDL_OpenStorage`].
830///
831/// ## Availability
832/// This struct is available since SDL 3.2.0.
833#[repr(C)]
834pub struct SDL_Storage {
835    _opaque: [::core::primitive::u8; 0],
836}
837
838#[cfg(doc)]
839use crate::everything::*;