tenho seguinte código rust

use reqwest::Client;
use serde::Deserialize;
use std::path::PathBuf;
use std::sync::{Arc};
use std::sync::atomic::{AtomicBool, Ordering};
use tokio::sync::Notify;
use futures_util::StreamExt;
use tokio::io::AsyncWriteExt;
use tokio::fs::OpenOptions;
use tauri::{Window, Emitter};
use mlua::Lua;
use std::env;

// Definição da struct `Update`, que mantém informações sobre as atualizações
#[derive(Debug, Deserialize)]
struct Update {
    version: u32,
    file_name: String,
    merge_file: String,
    checksum: String,
}

// Definição de enum para mensagens enviadas ao frontend
#[derive(Debug, Clone, serde::Serialize)]
enum DownloadMessage {
    ConnectingToServer,
    ValidatingFileUrl,
    AuthenticatingWithServer,
    VerifyingFileIntegrity,
    ErrorNotFound,
    ErrorAccessDenied,
    ErrorServerUnavailable,
    RestartingDownload,
    FileAlreadyExists,
    PreparingDownload,
    DownloadProgress {
        current_file: usize,
        total_files: usize,
        file_name: String,
        downloaded_bytes: u64,
        total_bytes: u64,
    },
}

// Estrutura responsável por manter o estado do download (pausa/retomada)
pub struct DownloadState {
    is_paused: Arc<AtomicBool>,
    notify: Arc<Notify>,
}

impl DownloadState {
    // Cria um novo `DownloadState`
    pub fn new() -> Self {
        Self {
            is_paused: Arc::new(AtomicBool::new(false)),
            notify: Arc::new(Notify::new()),
        }
    }

    // Função que espera se o estado estiver pausado
    pub async fn wait_if_paused(&self) {
        while self.is_paused.load(Ordering::SeqCst) {
            self.notify.notified().await;
        }
    }

    // Pausa o download
    pub fn pause(&self) {
        self.is_paused.store(true, Ordering::SeqCst);
    }

    // Retoma o download
    pub fn resume(&self) {
        self.is_paused.store(false, Ordering::SeqCst);
        self.notify.notify_waiters();
    }
}

// Função para iniciar o download dos arquivos
#[tauri::command]
async fn download_files(window: Window) -> Result<(), String> {
    let download_state = Arc::new(DownloadState::new());

    window.emit("download-message", DownloadMessage::ConnectingToServer)
        .map_err(|_| "Falha ao enviar mensagem")?;

    let url_base = "https://hil-speed.hetzner.com/";
    let updates = get_updates_from_lua().await.map_err(|e| e.to_string())?;

    for (index, update) in updates.iter().enumerate() {
        window.emit("download-message", DownloadMessage::ValidatingFileUrl)
            .map_err(|_| "Falha ao enviar mensagem")?;
        window.emit("download-message", DownloadMessage::AuthenticatingWithServer)
            .map_err(|_| "Falha ao enviar mensagem")?;

        let file_url = format!("{}{}", url_base, update.file_name);
        let total_files = updates.len();
        let current_file = index + 1;

        // Aguarda se o download estiver pausado
        download_state.wait_if_paused().await;

        // Faz o download do arquivo com progresso
        download_file_with_progress(&window, &file_url, &update.file_name, current_file, total_files, download_state.clone()).await?;
    }

    Ok(())
}

// Função auxiliar para download de arquivos com emissão de progresso
async fn download_file_with_progress(
    window: &Window,
    url: &str,
    file_name: &str,
    current_file: usize,
    total_files: usize,
    download_state: Arc<DownloadState>
) -> Result<(), String> {
    window.emit("download-message", DownloadMessage::PreparingDownload)
        .map_err(|_| "Falha ao enviar mensagem")?;

    let client = Client::new();
    let response = client.get(url).send().await.map_err(|e| e.to_string())?;
    let total_bytes = response.content_length().ok_or("Não foi possível obter o tamanho do arquivo")?;

    let exe_dir = get_exe_dir().map_err(|e| e.to_string())?;
    let update_dir = exe_dir.join("update");

    if !update_dir.exists() {
        tokio::fs::create_dir(&update_dir).await.map_err(|e| e.to_string())?;
    }

    let file_path = update_dir.join(file_name);

    if file_path.exists() {
        window.emit("download-message", DownloadMessage::FileAlreadyExists)
            .map_err(|_| "Falha ao enviar mensagem")?;
        return Ok(());
    }

    let mut file = OpenOptions::new()
        .create(true)
        .write(true)
        .open(file_path)
        .await
        .map_err(|e| e.to_string())?;

    let mut downloaded_bytes = 0u64;
    let mut stream = response.bytes_stream();
    while let Some(chunk) = stream.next().await {
        download_state.wait_if_paused().await; // Pausa se necessário

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

        window.emit(
            "download-message",
            DownloadMessage::DownloadProgress {
                current_file,
                total_files,
                file_name: file_name.to_string(),
                downloaded_bytes,
                total_bytes,
            },
        ).map_err(|_| "Falha ao enviar mensagem")?;
    }

    Ok(())
}

// Comando Tauri para pausar o download
#[tauri::command]
fn pause_download(download_state: Arc<DownloadState>) {
    download_state.pause(); // Usando o método pause
}

// Comando Tauri para retomar o download
#[tauri::command]
fn resume_download(download_state: Arc<DownloadState>) {
    download_state.resume(); // Usando o método resume
}

// Função que obtém atualizações a partir de um arquivo Lua
async fn get_updates_from_lua() -> Result<Vec<Update>, Box<dyn std::error::Error>> {
    let exe_dir = get_exe_dir()?;
    let patch_lua_path = exe_dir.join("Patch.lua");
    let lua_code = tokio::fs::read_to_string(patch_lua_path).await?;

    let lua = Lua::new();
    let globals = lua.globals();
    lua.load(&lua_code).exec()?;

    let updates_table = globals.get::<_, mlua::Table>("updates")?;
    let mut updates = Vec::new();

    for pair in updates_table.pairs::<mlua::Value, mlua::Table>() {
        let (_, table) = pair?;
        let update = Update {
            version: table.get("version")?,
            file_name: table.get("file_name")?,
            merge_file: table.get("merge_file")?,
            checksum: table.get("checksum")?,
        };
        updates.push(update);
    }

    Ok(updates)
}

// Função auxiliar para obter o diretório do executável
fn get_exe_dir() -> Result<PathBuf, std::io::Error> {
    let exe_path = env::current_exe()?;
    let exe_dir = exe_path.parent().ok_or_else(|| std::io::Error::new(
        std::io::ErrorKind::NotFound,
        "Não foi possível obter o diretório do executável",
    ))?;
    Ok(exe_dir.to_path_buf())
}

No react eu tenho

import { useEffect, useState } from 'react';
import { invoke } from '@tauri-apps/api/core';
import { listen } from '@tauri-apps/api/event';

interface DownloadProgress {
  currentFile: number;
  totalFiles: number;
  fileName: string;
  downloadedBytes: number;
  totalBytes: number;
}

function formatBytes(bytes: number) {
  if (bytes === 0) return '0 B';
  const k = 1024;
  const units = ['B', 'KB', 'MB', 'GB', 'TB', 'PB'];
  const i = Math.floor(Math.log(bytes) / Math.log(k));
  const value = bytes / Math.pow(k, i);
  return `${value.toFixed(2)} ${units[i]}`;
}

function DownloadManager() {
  const [message, setMessage] = useState('');
  const [progress, setProgress] = useState<DownloadProgress>({
    currentFile: 0,
    totalFiles: 0,
    fileName: '',
    downloadedBytes: 0,
    totalBytes: 0,
  });
  const [isDownloading, setIsDownloading] = useState(false);

  useEffect(() => {
    const setupListener = async () => {
      const unlisten = await listen('download-message', (e) => {
        if (typeof e.payload === 'string') {
          switch (e.payload) {
            case 'ConnectingToServer':
              setMessage('Conectando ao servidor...');
              break;
            case 'ValidatingFileUrl':
              setMessage('Validando URL do arquivo...');
              break;
            case 'AuthenticatingWithServer':
              setMessage('Autenticando com o servidor...');
              break;
            case 'VerifyingFileIntegrity':
              setMessage('Verificando integridade do arquivo...');
              break;
            case 'ErrorNotFound':
              setMessage('Erro: Arquivo não encontrado (404)');
              setIsDownloading(false);
              break;
            case 'ErrorAccessDenied':
              setMessage('Erro: Acesso negado (403)');
              setIsDownloading(false);
              break;
            case 'ErrorServerUnavailable':
              setMessage('Erro: Servidor indisponível (503)');
              setIsDownloading(false);
              break;
            case 'RestartingDownload':
              setMessage('Reiniciando download após falha...');
              break;
            case 'FileAlreadyExists':
              setMessage('Arquivo já existe...');
              break;
            case 'PreparingDownload':
              setMessage('Preparando download...');
              setIsDownloading(true);
              break;
          }
        } else if (typeof e.payload === 'object' && e.payload !== null) {
          const progressData = e.payload as Partial<DownloadProgress>;
          setProgress((prevProgress) => ({
            ...prevProgress,
            currentFile: progressData.currentFile ?? prevProgress.currentFile,
            totalFiles: progressData.totalFiles ?? prevProgress.totalFiles,
            fileName: progressData.fileName ?? prevProgress.fileName,
            downloadedBytes: progressData.downloadedBytes ?? prevProgress.downloadedBytes,
            totalBytes: progressData.totalBytes ?? prevProgress.totalBytes,
          }));
          setMessage(`Baixando arquivo (${progressData.currentFile} / ${progressData.totalFiles}): ${progressData.fileName} (${formatBytes(progressData.downloadedBytes)} / ${formatBytes(progressData.totalBytes)})`);
        }
      });

      return () => {
        unlisten();
      };
    };

    setupListener();
  }, []);

  const startDownload = async () => {
    if (!isDownloading) {
      setIsDownloading(true);
      await invoke('download_files');
    }
  };

  const pauseDownload = async () => {
    setMessage('Download pausado.');
    setIsDownloading(false);
    await invoke('pause_download');
  };
  
  const resumeDownload = async () => {
    setMessage('Resumindo download...');
    setIsDownloading(true);
    await invoke('resume_download');
  };

  const progressPercent = progress.totalBytes > 0 
    ? Math.min((progress.downloadedBytes / progress.totalBytes) * 100, 100)
    : 0;

  return (
    <div className="app-container">
      <h1>Gerenciador de Downloads</h1>
      <button onClick={startDownload} disabled={isDownloading}>
        Iniciar Download
      </button>
      {isDownloading && (
        <>
          <button onClick={pauseDownload} style={{ marginLeft: '10px' }}>
            Pausar
          </button>
          <button onClick={resumeDownload} style={{ marginLeft: '10px' }}>
            Retomar
          </button>
        </>
      )}
      <div className="absolute bottom-3 rounded-lg w-[71%] h-[8%] flex flex-col justify-between items-center">
        <p className="text-[14px] font-bold text-opacity-[0.95] text-white text-center">
          {message}
        </p>
        <div className="w-[95%] bg-[#0E1622]/[0.95] rounded-md h-5 flex items-center">
          <div
            className="bg-[#1164CA]/[0.95] ml-1 rounded-md h-4 transition-all duration-300"
            style={{ width: `${progressPercent}%` }}
          />
        </div>
      </div>
    </div>
  );
}

export default DownloadManager;

recebo erro

error[E0603]: macro import `__cmd__download_files` is private
  --> src\lib.rs:20:60
   |
20 |         .invoke_handler(tauri::generate_handler![download::download_files])
   |                                                            ^^^^^^^^^^^^^^ private macro import
   |
note: the macro import `__cmd__download_files` is defined here...
  --> src\download.rs:81:10
   |
81 | async fn download_files(window: Window) -> Result<(), String> {
   |          ^^^^^^^^^^^^^^
note: ...and refers to the macro `__cmd__download_files` which is defined here
  --> src\download.rs:80:1
   |
80 | #[tauri::command]
   | ^^^^^^^^^^^^^^^^^
   = note: this error originates in the attribute macro `tauri::command` (in Nightly builds, run with -Z macro-backtrace for more info)

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