Reputation: 21
I was trying to use the file picker of tauri to read the contents of a file in Rust this way.
fn open_file() -> Option<String> {
let dialog_open_file = tauri::api::dialog::FileDialogBuilder::new();
dialog_open_file.pick_file(|path| {
match path {
Some(directory) => {
let archivo = fs::read_to_string(directory);
match archivo {
Ok(content) => { return Some(content); },
Err(error) => { return None; }
}
},
None => { return None; }
}
});
}
The problem is that when I try to return Some(content) I get the error "mismatched types expected unit type ()
found enum Option<String>
"
error[E0308]: mismatched types
--> src/main.rs:25:43
|
25 | Ok(content) => { return Some(content); },
| ^^^^^^^^^^^^^ expected `()`, found enum
= note: expected unit type `()`
found enum `Option<String>`
error[E0308]: mismatched types
--> src/main.rs:18:19
|
18 | fn open_file() -> Option<String> {
| --------- ^^^^^^^^^^^^^^ expected enum `Option`, found `()`
| |
| implicitly returns `()` as its body has no tail or `return` expression
|
= note: expected enum `Option<String>`
found unit type `()`
I have tried many ways but I can't return the Option out of the function "dialog_open_file" to make the function return something.
Upvotes: 2
Views: 5548
Reputation: 8678
This post does not work for the OP question, because tauri's API requires the closure to be 'static
, and thus rules out the possibility (except with dirty unsafe
hacks) to retrieve the content of the file in a way similar to what was asked.
Also, tauri's API has been changed in more recent versions. If you are only interested in a solution that specifically works with tauri, please see @Michael Anderson's answer.
As you can see, there are two errors, which are opposite, in some way: one error tells you that Rust expected ()
, but found Option<String>
, and the other one that it expected Option<String>
, but found ()
. This should prompt you to check if you are passing you Option<String>
at the right place and, in fact, you're not.
A closure is a function (not quite the same as other functions you define with fn
, but still a function), so when you call return
in it, you're actually returning inside the closure. So, the error just comes from the fact that pick_file
expected a function that returns ()
, whereas you provided one that returns Option<String>
, and conversely the outer function is (implicitly) returning ()
.
You may ask: is there a way to return from inside the closure, but for the return statement to apply to the outside function, and the answer is no, so one way would be to create a variable outside and mutate it from inside the closure:
fn open_file() -> Option<String> {
let dialog_open_file = tauri::api::dialog::FileDialogBuilder::new();
let mut result = None;
dialog_open_file.pick_file(|path| {
if let Some(directory) = path {
let archivo = fs::read_to_string(directory);
if let Ok(content) = archivo {
result = Some(content);
}
}
});
result
}
Upvotes: 1
Reputation: 73570
It looks like tauri
has changed its API in this area. See https://docs.rs/tauri-api/0.7.6/tauri_api/dialog/index.html. Now the functions no longer accept a closure, but instead return a dialog::Response
struct.
This means your code could be written as something like:
// This is tauri's internal error type too.
use anyhow::{Error, bail};
fn open_file_impl() -> Result<String, Error> {
use tauri::api::dialog::Response;
let result = tauri::api::dialog::select(None,None)?;
let path = match {
Response::Okay(s) => s;
Response::OkayMultiple(s) => bail!("multiple selected"),
Response::Cancel => bail!("canceled");
}
Ok(fs::read_to_string(directory)?)
}
pub fn open_file() -> Option<String> {
open_file_impl().ok()
}
I'd probably introduce a concrete error type with this, rather than relying on anyhow
... but that does make things longer.
Or you could get rid of the open_file_impl
altogether...
fn open_file_impl() -> Option<String> {
use tauri::api::dialog::Response;
let result = tauri::api::dialog::select(None,None).ok()?;
if let Response::Okay(path) = result {
fs::read_to_string(directory).ok()
} else {
None
}
}
Upvotes: 1
Reputation: 3855
If you format your code, you would find out that you are missing the return statement in the outer space.
fn open_file() -> Option<String> {
let dialog_open_file = tauri::api::dialog::FileDialogBuilder::new();
let mut result = None;
dialog_open_file.pick_file(|path| match path {
Some(directory) => {
let archivo = fs::read_to_string(directory);
match archivo {
Ok(content) => result = Some(content),
Err(error) => result = None,
}
}
});
result
}
Upvotes: 0