«несоответствующие типы ожидаемого типа модуля `()` найдено перечисление `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, и тем самым исключает возможность (за исключением грязного unsafehacks) для извлечения содержимого файла способом, аналогичным тому, который был задан.

Кроме того, 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
}
Другие вопросы по тегам