nvdialog_rs/
object.rs

1/// A trait implemented for most types that stem from NvDialog's API.
2///
3/// This trait is used for a few reasons:
4/// - It allows various kinds of dialogs to be grouped together and used in a generic way.
5/// - It allows for a unified way to show and free the underlying object.
6/// - It provides access to the internal object pointer without duplicating code unnecessarily.
7///
8/// Whereas previous versions of the crate relied on manually mapping each nvdialog function to a Rust one,
9/// this trait allows nvdialog types that share common functionality to be grouped together. In addition, it will
10/// allow developers to create generic types and `dyn` objects:
11/// ```rust
12/// use nvdialog_rs::Object;
13///
14/// fn push_dialog<T: nvdialog_rs::Object>(vec: Vec<*mut c_void>, dialog: T) {
15///     vec.push(dialog.get_raw());
16/// }
17/// ```
18/// # Safety
19///
20/// The `Object` trait is designed to provide safe access to the underlying native object in the
21/// `NvDialog` API. However, as it deals with raw pointers, it requires the user to ensure
22/// safety by adhering to the following guidelines:
23///
24/// 1. **Mutability**: The pointer returned by [`Object::get_raw`] should not be mutated if it's going to be used
25///    in a subsequent call to this crate or [`nvdialog-sys`]. Mutating the pointer's contents will cause undefined behavior.
26///
27/// 2. **Object Ownership**: The ownership of the native object is managed externally by the
28///    underlying `NvDialog` API. Implementors of this trait must ensure that the object is not
29///    freed or modified while it is still in use by the `Object` trait methods. Freeing the
30///    object before calling `free` or modifying it after `free` has been called will result in
31///    undefined behavior.
32///
33/// 3. **Calling `free` Safely**: It is not adviced to manually call `free`. The reason is that most of the time,
34///    the underlying object is owned by the `NvDialog` API and calling `free` will cause undefined behavior. In addition
35///    the crate provides `Drop` implementations that will automatically free the object when it goes out of scope.
36///
37
38pub trait Object {
39    /// The type of the underlying native object, created by `NvDialog`. It will be used as a pointer
40    /// to provide compatibility with the `NvDialog` API.
41    type NativeType;
42    /// The value that should be returned from [`Self::show`]. It should match the value that the dialog returns when
43    /// it is presented to the user.
44    type ReturnValue;
45
46    /// Returns the raw object created by NvDialog internally. This should never return `null`.
47    fn get_raw(&self) -> *mut Self::NativeType;
48    /// Presents the dialog to the user. If [`Self::ReturnValue`] is not `()` then it will also return that value.
49    /// Sometimes this serves as an alias to the type's implementation of the analogous function. If you cannot afford the overhead,
50    /// you can use that instead.
51    fn show(&self) -> Self::ReturnValue;
52    /// Frees the underlying native object. This should not be usually called manually, instead the [`Drop`] implementation should
53    /// handle it when the time is correct. Be wary, if you do call this, you might run into double freeing errors.
54    fn free(&mut self);
55}