tenho o código tauri v2

use serde::{Deserialize, Serialize};
use std::path::{Path, PathBuf};
use tauri::{AppHandle, Emitter};
use reqwest::Client;
use tokio::fs;
use tokio::io::AsyncWriteExt;
use std::time::{Duration, Instant};

#[derive(Deserialize, Clone)]
struct PatchEntry {
    file_name: String,
}

#[derive(Serialize, Clone)]
struct DownloadInfo {
    current_file: usize,
    total_files: usize,
    file_name: String,
    downloaded_bytes: u64,
    total_bytes: u64,
}

#[derive(Serialize, Clone)]
struct DownloadStatus {
    status: String,
    additional_info: Option<String>,
}

fn get_exe_dir() -> PathBuf {
    std::env::current_exe().unwrap().parent().unwrap().to_path_buf()
}

async fn dir_exists(path: &Path) -> Result<bool, std::io::Error> {
    match fs::metadata(path).await {
        Ok(metadata) => Ok(metadata.is_dir()),
        Err(err) if err.kind() == std::io::ErrorKind::NotFound => Ok(false),
        Err(err) => Err(err),
    }
}

async fn read_patch_file(path: &Path) -> Result<Vec<PatchEntry>, String> {
    let content = fs::read_to_string(path).await.map_err(|e| e.to_string())?;
    let patches: Vec<PatchEntry> = serde_json::from_str(&content).map_err(|e| e.to_string())?;
    Ok(patches)
}

async fn emit_download_status(app_handle: &AppHandle, status: &str, additional_info: Option<String>,) -> Result<(), String> {
    app_handle.emit("download_status", DownloadStatus {status: status.to_string(), additional_info,}).map_err(|e| e.to_string())
}

async fn download_file(app_handle: &AppHandle, client: &Client, entry: &PatchEntry, download_dir: &Path, current_file: usize, total_files: usize,) -> Result<(), String> {
    let url = format!("https://hil-speed.hetzner.com/{}", entry.file_name);
    let file_path = download_dir.join(&entry.file_name);

    let mut response = client.get(&url).send().await.map_err(|e| e.to_string())?;
    if !response.status().is_success() {
        return Err(format!("Falha ao baixar '{}': HTTP {}", entry.file_name, response.status()));
    }

    let total_bytes = response.content_length().unwrap_or(0);
    let mut file = fs::File::create(&file_path).await.map_err(|e| e.to_string())?;

    let mut downloaded_bytes = 0u64;
    let start_time = Instant::now();

    emit_download_status(app_handle, "Downloading", None).await?;

    let mut last_emit_time = Instant::now();

    while let Some(chunk) = response.chunk().await.map_err(|e| e.to_string())? {
        file.write_all(&chunk).await.map_err(|e| e.to_string())?;
        downloaded_bytes += chunk.len() as u64;

        let now = Instant::now();
        if now.duration_since(last_emit_time) >= Duration::from_millis(100) {
            let elapsed = start_time.elapsed().as_secs_f64();
            let speed = if elapsed > 0.0 {
                downloaded_bytes as f64 / elapsed
            } else {
                0.0
            };

            app_handle.emit("download_info", DownloadInfo {
                current_file,
                total_files,
                file_name: entry.file_name.clone(),
                downloaded_bytes,
                total_bytes,
            }).map_err(|e| e.to_string())?;
            app_handle.emit("download_speed", speed).map_err(|e| e.to_string())?;
            last_emit_time = now;
        }
    }

    Ok(())
}

async fn check_server_connection(client: &Client, url: &str) -> Result<(), String> {
    let response = client.get(url).send().await.map_err(|e| e.to_string())?;
    if response.status().is_success() {
        Ok(())
    } else {
        Err(format!("Falha ao conectar ao servidor: HTTP {}", response.status()))
    }
}

#[tauri::command]
pub async fn start_downloads(app_handle: AppHandle) -> Result<(), String> {
    // Obter o diretório do executável
    let exe_dir = get_exe_dir().map_err(|e| e.to_string())?;

    // Definir caminhos
    let patch_file_path = exe_dir.join("patch.json");
    let download_dir = exe_dir.join("patchs");

    // Verificar se o diretório de download existe, criar se não existir
    if !dir_exists(&download_dir).await.map_err(|e| e.to_string())? {
        fs::create_dir_all(&download_dir).await.map_err(|e| e.to_string())?;
    }

    // Ler os patches do arquivo JSON
    let patches = read_patch_file(&patch_file_path).await?;

    let client = Client::new();
    let total_files = patches.len();

    // Emitir status de conexão
    emit_download_status(&app_handle, "Connecting", None).await?;

    let server_url = "https://hil-speed.hetzner.com/";
    if let Err(err) = check_server_connection(&client, server_url).await {
        let error_message = format!("Erro ao conectar ao servidor: {}", err);
        eprintln!("{}", error_message);
        emit_download_status(&app_handle, "Error", Some(error_message.clone())).await?;
        return Err(error_message);
    }

    // Emitir status de conexão bem-sucedida
    emit_download_status(&app_handle, "Connected", None).await?;

    for (idx, entry) in patches.iter().enumerate() {
        let current_file = idx + 1;
        if let Err(err) = download_file(&app_handle, &client, entry, &download_dir, current_file, total_files).await {
            let error_message = format!("Erro ao baixar '{}': {}", entry.file_name, err);
            eprintln!("{}", error_message);
            emit_download_status(&app_handle, "Error", Some(error_message.clone())).await?;
            return Err(error_message);
        }
    }

    // Emitir status de conclusão
    emit_download_status(&app_handle, "Completed", None).await?;

    Ok(())
}

recebo erro

error[E0599]: no method named `map_err` found for struct `PathBuf` in the current scope
   --> src\download.rs:110:33
    |
110 |     let exe_dir = get_exe_dir().map_err(|e| e.to_string())?;
    |                                 ^^^^^^^ method not found in `PathBuf`

For more information about this error, try `rustc --explain E0599`.
error: could not compile `RagnaTales` (lib) due to 1 previous error