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}