«несоответствующие типы ожидаемого типа модуля `()` найдено перечисление `Option<String>`» Ошибка при попытке прочитать содержимое файла с помощью Tauri
Я пытался использовать средство выбора файлов tauri, чтобы таким образом прочитать содержимое файла в Rust.
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; }
}
});
}
Проблема в том, что когда я пытаюсь вернуть Some(content), я получаю сообщение об ошибке "несоответствующие типы ожидаемых типов единиц измерения".
()
найдено перечисление
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 `()`
Я пробовал много способов, но не могу вернуть параметр из функции «dialog_open_file», чтобы функция что-то вернула.
3 ответа
Это выглядит как
tauri
изменил свой API в этой области. См . https://docs.rs/tauri-api/0.7.6/tauri_api/dialog/index.html . Теперь функции больше не принимают замыкание, а вместо этого возвращают
dialog::Response
структура.
Это означает, что ваш код может быть написан примерно так:
// 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()
}
Я бы, вероятно, ввел конкретный тип ошибки, вместо того, чтобы полагаться на
anyhow
... но это делает вещи длиннее.
Или вы могли бы избавиться от
open_file_impl
вообще...
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
}
}
Редактировать
Этот пост не работает для вопроса OP, потому что API tauri требует, чтобы закрытие было
'static
, и тем самым исключает возможность (за исключением грязного
unsafe
hacks) для извлечения содержимого файла способом, аналогичным тому, который был задан.
Кроме того, API tauri был изменен в более поздних версиях. Если вас интересует только решение, которое специально работает с tauri, см. ответ @Michael Anderson.
Как видите, есть две ошибки, в некотором роде противоположные: одна ошибка говорит вам, что Rust ожидал, но нашел, а другой — что ожидал, но нашел. Это должно побудить вас проверить, проходите ли вы в нужном месте, и на самом деле это не так.
Замыкание — это функция (не совсем такая, как другие функции, которые вы определяете с помощью
fn
, но все же функция), поэтому при вызове
return
в нем вы фактически возвращаетесь внутрь закрытия. Так что ошибка как раз из-за того, что
pick_file
ожидалась функция, которая возвращает , тогда как вы предоставили функцию, которая возвращает
Option<String>
, и наоборот, внешняя функция (неявно) возвращает
()
.
Вы можете спросить: есть ли способ вернуться из замыкания, но чтобы оператор return применялся к внешней функции, и ответ будет отрицательным , поэтому одним из способов было бы создать переменную снаружи и изменить ее внутри замыкания. :
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
}
Если вы отформатируете свой код, вы обнаружите, что вам не хватает оператора return во внешнем пространстве.
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
}