Skip to content

Commit

Permalink
feat: make DialogFileBrowserOptions::new() use native initializatio…
Browse files Browse the repository at this point in the history
…n function
  • Loading branch information
JarvisCraft committed Jul 8, 2023
1 parent 4d6b318 commit 70bf1c6
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 17 deletions.
5 changes: 4 additions & 1 deletion crates/flipperzero/examples/storage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ use flipperzero::io::*;
use flipperzero::println;
use flipperzero::storage::*;
use flipperzero_rt::{entry, manifest};
use flipperzero_sys::c_str;

manifest!(name = "Rust storage example");
entry!(main);
Expand All @@ -41,7 +42,9 @@ fn main(_args: *mut u8) -> i32 {

// Next, we'll open a file browser dialog and let the user select the file.
let mut dialogs_app = DialogsApp::open();
let file_browser_options = DialogFileBrowserOptions::new().set_hide_ext(false);

static EXTENSION: &CStr = c_str!("*");
let file_browser_options = DialogFileBrowserOptions::new(EXTENSION).set_hide_ext(false);
let mut start_path = FuriString::from(path);
let result_path =
dialogs_app.show_file_browser(Some(&mut start_path), Some(&file_browser_options));
Expand Down
32 changes: 18 additions & 14 deletions crates/flipperzero/src/dialogs/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ use alloc::ffi::CString;

use core::ffi::{c_char, c_void, CStr};
use core::marker::PhantomData;
use core::mem::MaybeUninit;
use core::ptr::{self, NonNull};

use flipperzero_sys as sys;
use sys::{c_string, furi::UnsafeRecord};
use sys::furi::UnsafeRecord;

use crate::furi::string::FuriString;
use crate::gui::canvas::Align;
Expand All @@ -25,6 +25,7 @@ pub struct DialogMessage<'a> {
}

/// A dialog file browser options.
#[repr(transparent)]
pub struct DialogFileBrowserOptions<'a> {
data: sys::DialogsFileBrowserOptions,
_phantom: PhantomData<&'a ()>,
Expand Down Expand Up @@ -202,19 +203,22 @@ impl DialogMessageButton {

impl<'a> DialogFileBrowserOptions<'a> {
/// Creates a new dialog file browser options and initializes to default values.
pub fn new() -> Self {
pub fn new<'e: 'a>(extension: &'e CStr) -> Self {
let mut options = MaybeUninit::<sys::DialogsFileBrowserOptions>::uninit();
let uninit_options = options.as_mut_ptr();
let extension = extension.as_ptr();
// TODO: as for now, we stick to default (NULL) icon,
// although we may want to make it customizable via this function's parameter
// once there are safe Icon-related APIs
let icon = ptr::null();
// SAFETY: all pointers are valid (`icon` is allowed to be NULL)
// and options is intentionally uninitialized
// since it is the called function's job to do it
unsafe { sys::dialog_file_browser_set_basic_options(uninit_options, extension, icon) };
Self {
// default values from sys::dialog_file_browser_set_basic_options()
data: sys::DialogsFileBrowserOptions {
extension: c_string!("*"),
base_path: ptr::null(),
skip_assets: true,
hide_dot_files: false,
icon: ptr::null(),
hide_ext: true,
item_loader_callback: None,
item_loader_context: ptr::null_mut(),
},
// SAFETY: data has just been initialized fully
// as guaranteed by the previously called function's contract
data: unsafe { options.assume_init() },
_phantom: PhantomData,
}
}
Expand Down
16 changes: 14 additions & 2 deletions crates/sys/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,24 @@ mod inlines;
)]
mod bindings;

/// Create a static C string.
/// Create a static C string of type [`*const c_char`][core::ffi::c_char].
/// Will automatically add a NUL terminator.
#[macro_export]
macro_rules! c_string {
($str:expr $(,)?) => {{
concat!($str, "\0").as_ptr() as *const core::ffi::c_char
::core::concat!($str, "\0").as_ptr() as *const ::core::ffi::c_char
}};
}

/// Create a static C string of type [`&CStr`][`core::ffi::CStr`].
/// Will automatically add a NUL terminator.
#[macro_export]
macro_rules! c_str {
($str:expr $(,)?) => {{
match ::core::ffi::CStr::from_bytes_with_nul(::core::concat!($str, "\0").as_bytes()) {
Ok(c_str) => c_str,
Err(error) => panic!("invalid C-string literal"),
}
}};
}

Expand Down

0 comments on commit 70bf1c6

Please sign in to comment.