繁体   English   中英

“不匹配的类型预期单元类型`()`找到枚举`选项<String> `&quot; 尝试使用 Tauri 读取文件内容时出错

[英]"mismatched types expected unit type `()` found enum `Option<String>`" Error when trying to read the content of a file with 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) 时,我收到错误“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 `()`

我尝试了很多方法,但我无法从函数“dialog_open_file”中返回选项以使函数返回一些东西。

看起来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 问题,因为 tauri 的 API 要求闭包是'static ,因此排除了以类似于所要求的方式检索文件内容的可能性(除了肮脏的unsafe黑客)。

此外,tauri 的 API 在最近的版本中已更改。 如果您只对专门适用于 tauri 的解决方案感兴趣,请参阅@Michael Anderson 的回答。


正如你所看到的,有两个错误,在某种程度上是相反的:一个错误告诉你 Rust 期望() ,但是找到了Option<String> ,另一个错误告诉你它期望Option<String> ,但是找到了() . 这应该会提示您检查是否在正确的位置传递Option<String> ,事实上,您不是。

闭包一个函数(与您使用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
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM