├── .gitignore ├── src ├── cli │ ├── mod.rs │ ├── args.rs │ └── command.rs ├── lib.rs ├── database │ ├── mod.rs │ ├── mysql.rs │ └── postgresql.rs ├── compression.rs ├── storage │ ├── mod.rs │ ├── tencent_cos.rs │ ├── aliyun_oss.rs │ ├── s3_compatible.rs │ └── local_storage.rs ├── main.rs ├── utils.rs └── config.rs ├── images ├── list.png └── ccwechat.jpg ├── Cargo.toml ├── config.yaml ├── README.md ├── .github └── workflows │ └── build.yml └── Cargo.lock /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | config.dev.yaml -------------------------------------------------------------------------------- /src/cli/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod args; 2 | pub mod command; 3 | -------------------------------------------------------------------------------- /images/list.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iKeepLearn/db-back-tool/HEAD/images/list.png -------------------------------------------------------------------------------- /images/ccwechat.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iKeepLearn/db-back-tool/HEAD/images/ccwechat.jpg -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | pub mod cli; 2 | pub mod compression; 3 | pub mod config; 4 | pub mod database; 5 | pub mod storage; 6 | pub mod utils; 7 | -------------------------------------------------------------------------------- /src/database/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod mysql; 2 | pub mod postgresql; 3 | 4 | use std::path::{Path, PathBuf}; 5 | 6 | #[async_trait::async_trait] 7 | pub trait Database { 8 | async fn backup(&self, database_name: &str, backup_dir: &Path) -> anyhow::Result; 9 | } 10 | -------------------------------------------------------------------------------- /src/compression.rs: -------------------------------------------------------------------------------- 1 | // src/compression.rs 2 | use anyhow::Result; 3 | // use sevenz_rust2::{compress_to_path_encrypted, Password}; 4 | use std::path::{Path, PathBuf}; 5 | use tokio::process::Command; 6 | 7 | pub async fn compress_and_encrypt(input_file: &Path, password: &str) -> Result { 8 | let output_path = input_file.with_extension("7z"); 9 | // let password = Password::from(password); 10 | // compress_to_path_encrypted(input_file, &output_path, password)?; 11 | 12 | let mut cmd = Command::new("7z"); 13 | 14 | cmd.arg("a") 15 | .arg("-t7z") 16 | .arg("-m0=lzma2") 17 | .arg("-mhe=on") // 启用头部加密 18 | .arg(format!("-p{}", password)) // 设置密码 19 | .arg(&output_path) 20 | .arg(input_file); 21 | 22 | let status = cmd.status().await?; 23 | 24 | if !status.success() { 25 | anyhow::bail!("7z compression failed"); 26 | } 27 | 28 | Ok(output_path) 29 | } 30 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "backupdbtool" 3 | version = "1.5.1" 4 | edition = "2024" 5 | 6 | [lib] 7 | path = "src/lib.rs" 8 | 9 | [[bin]] 10 | path = "src/main.rs" 11 | name = "backupdbtool" 12 | 13 | [dependencies] 14 | tokio = { version = "1.0", features = ["full"] } 15 | chrono = { version = "0.4", features = ["serde"] } 16 | anyhow = "1.0" 17 | tracing = "0.1" 18 | tracing-subscriber = "0.3" 19 | serde = { version = "1.0", features = ["derive"] } 20 | serde_json = "1.0" 21 | config = "0.15.16" 22 | once_cell = "1.18" 23 | async-trait = "0.1" 24 | clap = { version = "4.5.48", features = ["derive"] } 25 | glob = "0.3" 26 | dirs = "6.0.0" 27 | tabled = "0.20" 28 | reqwest = { version = "0.12", features = ["json"] } 29 | shellexpand = "3.1" 30 | humansize = "2.1" 31 | rust-s3 = "0.37" 32 | cos-rust-sdk = "0.1" 33 | futures = "0.3.31" 34 | # sevenz-rust2 = "0.18" 35 | 36 | [dev-dependencies] 37 | tempfile = "3.22.0" 38 | 39 | [profile.release] 40 | lto = true 41 | -------------------------------------------------------------------------------- /src/cli/args.rs: -------------------------------------------------------------------------------- 1 | // src/cli.rs 2 | use clap::{Parser, Subcommand}; 3 | 4 | #[derive(Parser)] 5 | #[command(name = "backupdbtool")] 6 | #[command(about = "PostgreSQL\\MySql database backup tool with COS upload", long_about = None)] 7 | pub struct Cli { 8 | #[command(subcommand)] 9 | pub command: Commands, 10 | /// Specific file for configuration 11 | #[arg(short, long)] 12 | pub config: String, 13 | } 14 | 15 | #[derive(Subcommand)] 16 | pub enum Commands { 17 | /// Backup a specific database 18 | Backup { 19 | /// Database name to backup 20 | database_name: String, 21 | }, 22 | 23 | /// Upload all backup files to COS 24 | Upload { 25 | /// Specific file to upload (optional) 26 | #[arg(short, long)] 27 | file: Option, 28 | 29 | /// Upload all files in backup directory 30 | #[arg(short, long, default_value_t = false)] 31 | all: bool, 32 | }, 33 | 34 | /// Delete yesterday before files from COS 35 | Delete { 36 | /// Specific file to delete (optional) 37 | #[arg(short, long)] 38 | key: Option, 39 | 40 | /// Delete all yesterday before files 41 | #[arg(short, long, default_value_t = false)] 42 | all: bool, 43 | }, 44 | 45 | /// List available backups 46 | List, 47 | 48 | /// Show tool version 49 | Version, 50 | } 51 | -------------------------------------------------------------------------------- /src/storage/mod.rs: -------------------------------------------------------------------------------- 1 | use anyhow::Result; 2 | use chrono::{DateTime, Utc}; 3 | use humansize::{DECIMAL, format_size}; 4 | use serde::{Deserialize, Serialize}; 5 | use std::borrow::Cow::{self, Borrowed}; 6 | use std::cmp::Ordering; 7 | use std::path::Path; 8 | use tabled::Tabled; 9 | 10 | pub mod aliyun_oss; 11 | pub mod local_storage; 12 | pub mod s3_compatible; 13 | pub mod tencent_cos; 14 | 15 | #[async_trait::async_trait] 16 | pub trait Storage: Send + Sync { 17 | async fn upload(&self, file_path: &Path, cos_path: &str) -> Result<(), String>; 18 | async fn list(&self, key: &str) -> Result, String>; 19 | async fn delete(&self, backup_name: &str) -> Result<(), String>; 20 | } 21 | 22 | #[derive(Debug, Serialize, Deserialize, Clone)] 23 | pub struct CosItem { 24 | pub key: String, 25 | pub last_modified: DateTime, 26 | pub size: u64, 27 | } 28 | 29 | impl PartialEq for CosItem { 30 | fn eq(&self, other: &Self) -> bool { 31 | self.last_modified == other.last_modified 32 | } 33 | } 34 | 35 | impl Eq for CosItem {} 36 | 37 | impl PartialOrd for CosItem { 38 | fn partial_cmp(&self, other: &Self) -> Option { 39 | Some(self.cmp(other)) 40 | } 41 | } 42 | 43 | impl Ord for CosItem { 44 | fn cmp(&self, other: &Self) -> Ordering { 45 | self.last_modified.cmp(&other.last_modified) 46 | } 47 | } 48 | 49 | impl Tabled for CosItem { 50 | const LENGTH: usize = 3; 51 | fn headers() -> Vec> { 52 | vec![Borrowed("文件路径"), Borrowed("修改时间"), Borrowed("大小")] 53 | } 54 | fn fields(&self) -> Vec> { 55 | let human_size = format_size(self.size, DECIMAL); 56 | let last_modified = self.last_modified.format("%Y-%m-%d %H:%M").to_string(); 57 | vec![ 58 | self.key.clone().into(), 59 | last_modified.into(), 60 | human_size.into(), 61 | ] 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /config.yaml: -------------------------------------------------------------------------------- 1 | app: 2 | backup_dir: "backup_dir" # 本地备份文件存储目录 3 | db_type: "postgresql" # 数据库类型: postgresql 或 mysql 4 | cos_provider: "tencent_cos" # 云存储服务提供商: tencent_cos 或 aliyun_oss 或 s3 5 | cos_path: "db/" # 云存储中的备份文件路径前缀 6 | compress_password: "password" # 备份压缩包加密密码 7 | 8 | tencent_cos: 9 | secret_id: "AKIDuhLs" # 腾讯云 COS SecretId 10 | secret_key: "dGnCj8" # 腾讯云 COS SecretKey 11 | region: "ap-shanghai" # 腾讯云 COS 区域 12 | bucket: "bucket-1234567" # 腾讯云 COS 存储桶名称 13 | 14 | postgresql: 15 | host: "localhost" # PostgreSQL 数据库主机地址 16 | port: 5432 # PostgreSQL 端口 17 | username: "postgres" # PostgreSQL 用户名 18 | password: "postgres" # PostgreSQL 密码 19 | 20 | mysql: 21 | host: "localhost" # MySQL 数据库主机地址 22 | port: 3306 # MySQL 端口 23 | username: "root" # MySQL 用户名 24 | password: "password" # MySQL 密码 25 | 26 | aliyun_oss: 27 | secret_id: "AKIDuhLs" # 阿里云 OSS AccessKeyId 28 | secret_key: "dGnCj8" # 阿里云 OSS AccessKeySecret 29 | end_point: "oss-cn-shanghai.aliyuncs.com" # 阿里云 OSS Endpoint 30 | bucket: "bucket-1234567" # 阿里云 OSS 存储桶名称 31 | 32 | s3: 33 | secret_id: "AKIDuhLs" # s3 协议兼容 OSS AccessKeyId 34 | secret_key: "dGnCj8" # s3 协议兼容 OSS AccessKeySecret 35 | end_point: "oss-cn-shanghai.aliyuncs.com" # s3 协议兼容 OSS Endpoint,与 region 二选一,没有该项请填写 null 36 | bucket: "bucket-1234567" # s3 协议兼容 OSS 存储桶名称 37 | region: "ap-shanghai" # s3 协议兼容 OSS 区域,与 end_point 二选一,没有该项请填写 null -------------------------------------------------------------------------------- /src/database/mysql.rs: -------------------------------------------------------------------------------- 1 | use super::Database; 2 | use crate::config::MySqlConfig; 3 | use chrono::Utc; 4 | use serde::Deserialize; 5 | use std::ops::Deref; 6 | use std::path::{Path, PathBuf}; 7 | use tokio::fs::File; 8 | use tokio::io::AsyncWriteExt; 9 | 10 | #[derive(Debug, Deserialize, Clone)] 11 | pub struct MySql(MySqlConfig); 12 | 13 | impl Deref for MySql { 14 | type Target = MySqlConfig; 15 | 16 | fn deref(&self) -> &Self::Target { 17 | &self.0 18 | } 19 | } 20 | 21 | #[async_trait::async_trait] 22 | impl Database for MySql { 23 | async fn backup(&self, database_name: &str, backup_dir: &Path) -> anyhow::Result { 24 | let backup_filename = format!( 25 | "{}_{}.sql", 26 | database_name, 27 | Utc::now().format("%Y%m%d_%H%M%S") 28 | ); 29 | let backup_path = backup_dir.join(&backup_filename); 30 | 31 | // 使用mysqldump进行备份 32 | let mut cmd = tokio::process::Command::new("mysqldump"); 33 | 34 | cmd.arg("-h") 35 | .arg(&self.host) 36 | .arg("-P") 37 | .arg(self.port.to_string()) 38 | .arg("-u") 39 | .arg(&self.username) 40 | .arg(format!("-p{}", &self.password)) 41 | .arg(database_name); 42 | 43 | let output = cmd.output().await?; 44 | 45 | if !output.status.success() { 46 | anyhow::bail!( 47 | "mysqldump failed for database {}: {}", 48 | database_name, 49 | String::from_utf8_lossy(&output.stderr) 50 | ); 51 | } 52 | 53 | // 确保备份目录存在 54 | tokio::fs::create_dir_all(&backup_dir).await?; 55 | 56 | let mut file = File::create(&backup_path).await?; 57 | file.write_all(&output.stdout).await?; 58 | file.flush().await?; 59 | 60 | Ok(backup_path) 61 | } 62 | } 63 | 64 | impl MySql { 65 | pub fn new(config: &MySqlConfig) -> Self { 66 | MySql(MySqlConfig { 67 | host: config.host.clone(), 68 | port: config.port, 69 | username: config.username.clone(), 70 | password: config.password.clone(), 71 | }) 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/database/postgresql.rs: -------------------------------------------------------------------------------- 1 | use super::Database; 2 | use crate::config::PostgreSqlConfig; 3 | use chrono::Utc; 4 | use serde::Deserialize; 5 | use std::ops::Deref; 6 | use std::path::{Path, PathBuf}; 7 | use tokio::fs::File; 8 | use tokio::io::AsyncWriteExt; 9 | 10 | #[derive(Debug, Deserialize, Clone)] 11 | pub struct PostgreSql(PostgreSqlConfig); 12 | 13 | impl Deref for PostgreSql { 14 | type Target = PostgreSqlConfig; 15 | 16 | fn deref(&self) -> &Self::Target { 17 | &self.0 18 | } 19 | } 20 | 21 | #[async_trait::async_trait] 22 | impl Database for PostgreSql { 23 | async fn backup(&self, database_name: &str, backup_dir: &Path) -> anyhow::Result { 24 | let backup_filename = format!( 25 | "{}_{}.sql", 26 | database_name, 27 | Utc::now().format("%Y%m%d_%H%M%S") 28 | ); 29 | let backup_path = backup_dir.join(&backup_filename); 30 | 31 | // 使用pg_dump进行备份 32 | let mut cmd = tokio::process::Command::new("pg_dump"); 33 | 34 | cmd.arg("-h") 35 | .arg(&self.host) 36 | .arg("-p") 37 | .arg(self.port.to_string()) 38 | .arg("-U") 39 | .arg(&self.username) 40 | .arg("-d") 41 | .arg(database_name) 42 | .env("PGPASSWORD", &self.password); 43 | 44 | let output = cmd.output().await?; 45 | 46 | if !output.status.success() { 47 | anyhow::bail!( 48 | "pg_dump failed for database {}: {}", 49 | database_name, 50 | String::from_utf8_lossy(&output.stderr) 51 | ); 52 | } 53 | 54 | // 确保备份目录存在 55 | tokio::fs::create_dir_all(&backup_dir).await?; 56 | 57 | let mut file = File::create(&backup_path).await?; 58 | file.write_all(&output.stdout).await?; 59 | file.flush().await?; 60 | 61 | Ok(backup_path) 62 | } 63 | } 64 | 65 | impl PostgreSql { 66 | pub fn new(config: &PostgreSqlConfig) -> Self { 67 | PostgreSql(PostgreSqlConfig { 68 | host: config.host.clone(), 69 | port: config.port, 70 | username: config.username.clone(), 71 | password: config.password.clone(), 72 | }) 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 使用说明 2 | 3 | 一款基于 Rust 开发的数据库备份工具,支持单实例 PostgreSQL/MySQL 数据库的自动备份、加密、压缩,并可将备份文件上传至腾讯云 COS 或阿里云 OSS或兼容 S3 协议的其他云存储。 4 | 5 | 开发动机是本人维护着很多单体服务分布在各个云服务器上,每个单体服务都使用各自的数据库实例,因为甲方预算原因没有配置数据库主从备份。 6 | 但又有备份的需求,所以只好写个工具使用数据库自带的 dump 工具备份,再加密压缩上传到云存储。 7 | 8 | ## 功能特性 9 | 10 | - 支持 PostgreSQL\MySql 数据库自动备份 11 | - 备份文件自动加密、压缩 12 | - 一键上传备份到腾讯云 COS\阿里云 OSS\兼容S3协议的其他云存储 13 | - 支持备份文件的批量上传、批量删除、列表查看 14 | - 支持自定义配置文件 15 | 16 | ## 前置条件 17 | 18 | 请确保服务器已安装 `7z`。 19 | 安装命令(Debian/Ubuntu): 20 | 21 | ```bash 22 | sudo apt install p7zip-full 23 | ``` 24 | 25 | --- 26 | 27 | ## 快速开始 28 | 29 | 1. 从 [release 页面](https://github.com/iKeepLearn/db-back-tool/releases) 下载可执行文件的 zip 包。 30 | 2. 解压后,修改其中的 `config.yaml` 配置文件为正确的配置。 31 | 32 | --- 33 | 34 | ## 常用命令示例 35 | 36 | - **备份指定数据库** 37 | 38 | ```bash 39 | ./backupdbtool --config config.yaml backup 40 | ``` 41 | 42 | - **上传所有待上传备份文件** 43 | 44 | ```bash 45 | ./backupdbtool --config config.yaml upload --all 46 | ``` 47 | 48 | - **上传单个备份文件** 49 | 50 | ```bash 51 | ./backupdbtool --config config.yaml upload --file /path/to/filename.ext 52 | ``` 53 | 54 | - **删除所有两天前的备份以减少云存储成本** 55 | 56 | ```bash 57 | ./backupdbtool --config config.yaml delete --all 58 | ``` 59 | 60 | - **删除单个云存储文件** 61 | 62 | ```bash 63 | ./backupdbtool --config config.yaml delete --key key 64 | ``` 65 | > key 为云存储中的完整路径,比如想删除下方 list 中的 config.yaml 则 key 为 db/config.yaml。 66 | 67 | > 完整示例: ./backupdbtool --config config.yaml delete --key db/config.yaml。 68 | 69 | - **列出所有备份文件** 70 | ```bash 71 | ./backupdbtool --config config.yaml list 72 | ``` 73 | ![list](images/list.png) 74 | 75 | ## 定时任务(Cron)推荐配置 76 | 77 | - **每日凌晨 2 点自动备份数据库** 78 | 79 | ```bash 80 | 0 2 * * * /path/to/backupdbtool --config /path/to/config.yaml backup 81 | ``` 82 | 83 | - **每日凌晨 2:30 上传所有待上传备份** 84 | 85 | ```bash 86 | 30 2 * * * /path/to/backupdbtool --config /path/to/config.yaml upload --all 87 | ``` 88 | 89 | - **每周日凌晨 3 点删除所有两天前的备份以减少云存储成本** 90 | ```bash 91 | 0 3 * * 0 /path/to/backupdbtool --config /path/to/config.yaml delete --all 92 | ``` 93 | 94 | > 请将 `/path/to/backupdbtool` 和 `/path/to/config.yaml` 替换为实际路径,`` 替换为目标数据库名称。 95 | 96 | ## 联系方式 97 | 98 | 如有疑问,请联系开发者。 99 | 100 | ![联系作者](images/ccwechat.jpg) 101 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: Build and Release 2 | 3 | on: 4 | push: 5 | # branches: [master] 6 | tags: 7 | - "v*" 8 | pull_request: 9 | branches: [master] 10 | 11 | env: 12 | CARGO_TERM_COLOR: always 13 | SQLX_OFFLINE: true 14 | APP_NAME: backupdbtool 15 | 16 | permissions: 17 | contents: write 18 | 19 | jobs: 20 | build_and_release: 21 | runs-on: ubuntu-22.04 22 | 23 | steps: 24 | - name: Checkout repository 25 | uses: actions/checkout@v4 26 | 27 | - name: Setup Rust 28 | uses: dtolnay/rust-toolchain@stable 29 | with: 30 | toolchain: stable 31 | 32 | # - name: Install musl target 33 | # run: rustup target add x86_64-unknown-linux-musl 34 | 35 | - name: Cache Cargo dependencies 36 | uses: actions/cache@v4 37 | with: 38 | path: | 39 | ~/.cargo/registry 40 | ~/.cargo/git 41 | target 42 | key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }} 43 | restore-keys: | 44 | ${{ runner.os }}-cargo- 45 | 46 | - name: Build release 47 | # run: cargo build --release --target x86_64-unknown-linux-musl 48 | run: cargo build --release 49 | 50 | - name: Rename executable for clarity 51 | run: mv target/release/${{ env.APP_NAME }} . 52 | 53 | - name: Create ZIP file 54 | run: | 55 | zip -r ${{ env.APP_NAME }}-linux-x86_64.zip ${{ env.APP_NAME }} config.yaml 56 | 57 | - name: Create Release 58 | id: create_release 59 | uses: softprops/action-gh-release@v2 60 | with: 61 | tag_name: ${{ github.ref_name }} # 使用当前的 Tag 名称作为 Release 名称 62 | name: ${{ github.ref_name }} 63 | draft: false # 设置为 true 可以创建草稿 Release 64 | prerelease: false # 设置为 true 可以创建预发布 Release 65 | env: 66 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # GitHub 自动提供的 token 67 | 68 | - name: Upload Release Asset (Linux) 69 | uses: actions/upload-release-asset@v1 70 | env: 71 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 72 | with: 73 | upload_url: ${{ steps.create_release.outputs.upload_url }} # 获取上一步创建的 Release 的上传 URL 74 | asset_path: ./${{ env.APP_NAME }}-linux-x86_64.zip # 要上传的文件路径 75 | asset_name: ${{ env.APP_NAME }}-linux-x86_64.zip # 上传后的文件名称 76 | asset_content_type: application/zip # 文件的 MIME 类型 77 | -------------------------------------------------------------------------------- /src/main.rs: -------------------------------------------------------------------------------- 1 | // src/main.rs 2 | 3 | use std::process; 4 | 5 | use anyhow::Result; 6 | use backupdbtool::cli::args::{Cli, Commands}; 7 | use backupdbtool::cli::command::{backup_database, delete_from_cos, upload_to_cos}; 8 | use backupdbtool::config::{CosProvider, get_all_config}; 9 | use backupdbtool::storage::CosItem; 10 | use backupdbtool::utils::{self, resolve_path}; 11 | use clap::Parser; 12 | use tracing::{error, info}; 13 | 14 | #[tokio::main] 15 | async fn main() -> Result<()> { 16 | // 初始化日志 17 | tracing_subscriber::fmt::init(); 18 | 19 | let cli = Cli::parse(); 20 | // 加载配置 21 | let mut config = match get_all_config(&cli.config) { 22 | Ok(config) => config, 23 | Err(e) => { 24 | error!("Failed to load config: {}", e); 25 | anyhow::bail!(e); 26 | } 27 | }; 28 | let result = resolve_path(&config.app.backup_dir.to_string_lossy()); 29 | match result { 30 | Ok(path) => { 31 | config.app.backup_dir = path; 32 | } 33 | Err(_) => { 34 | error!( 35 | "please check the backup_dir path: {}", 36 | &config.app.backup_dir.to_string_lossy() 37 | ); 38 | process::exit(1); 39 | } 40 | } 41 | 42 | let app_config = &config.app; 43 | let _ = app_config.confirm_backup_dir().await; 44 | let db = app_config.database(&config); 45 | let storage = app_config.storage(&config).await; 46 | 47 | match cli.command { 48 | Commands::Backup { database_name } => { 49 | info!("Starting backup for database: {}", database_name); 50 | backup_database( 51 | db.as_ref(), 52 | &database_name, 53 | &app_config.get_backup_dir(), 54 | &app_config.compress_password, 55 | ) 56 | .await 57 | } 58 | Commands::Upload { file, all } => { 59 | info!("Starting upload to COS"); 60 | upload_to_cos(file, all, app_config, storage).await 61 | } 62 | Commands::Delete { key, all } => { 63 | info!("Starting delete yesterday before file from COS"); 64 | utils::cleanup_old_backups(&app_config.get_backup_dir()).await?; 65 | delete_from_cos(key, all, storage.as_ref()).await 66 | } 67 | Commands::List => { 68 | let key_str = match &config.app.cos_provider { 69 | CosProvider::LocalStorage => "*.7z", 70 | _ => app_config.cos_path.as_str(), 71 | }; 72 | let files: Vec = storage 73 | .list(key_str) 74 | .await 75 | .map_err(|e| anyhow::anyhow!(e))?; 76 | let _ = utils::list_table(files); 77 | Ok(()) 78 | } 79 | Commands::Version => { 80 | println!("backupdbtool v{}", env!("CARGO_PKG_VERSION")); 81 | Ok(()) 82 | } 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /src/cli/command.rs: -------------------------------------------------------------------------------- 1 | use crate::config::AppConfig; 2 | use crate::database::Database; 3 | use crate::storage::Storage; 4 | use crate::{compression, utils}; 5 | use anyhow::Result; 6 | use std::path::{Path, PathBuf}; 7 | use std::sync::Arc; 8 | use tracing::{error, info}; 9 | 10 | pub async fn backup_database( 11 | db: &dyn Database, 12 | database_name: &str, 13 | back_dir: &Path, 14 | password: &str, 15 | ) -> Result<()> { 16 | // 1. 备份数据库 17 | let backup_file = db.backup(database_name, back_dir).await?; 18 | info!("Database backup created: {:?}", backup_file); 19 | 20 | // 2. 压缩并加密 21 | let compressed_file = compression::compress_and_encrypt(&backup_file, password).await?; 22 | info!("Backup compressed: {:?}", compressed_file); 23 | 24 | // 3. 删除原始SQL文件 25 | if let Err(e) = tokio::fs::remove_file(&backup_file).await { 26 | error!("Failed to remove temporary SQL file: {}", e); 27 | } 28 | 29 | info!( 30 | "Backup completed successfully for database: {}", 31 | database_name 32 | ); 33 | Ok(()) 34 | } 35 | 36 | pub async fn upload_to_cos( 37 | file: Option, 38 | all: bool, 39 | config: &AppConfig, 40 | storage: Arc, 41 | ) -> Result<()> { 42 | if let Some(file_path) = file { 43 | // 上传单个文件 44 | let path = PathBuf::from(&file_path); 45 | if !path.exists() { 46 | anyhow::bail!("File not found: {}", file_path); 47 | } 48 | storage 49 | .upload(&path, &config.cos_path) 50 | .await 51 | .map_err(anyhow::Error::msg)?; 52 | info!("File uploaded successfully: {}", file_path); 53 | } else if all { 54 | // 上传所有备份文件 55 | utils::upload_all_backups(&config.get_backup_dir(), storage, &config.cos_path) 56 | .await 57 | .map_err(anyhow::Error::msg)?; 58 | info!("All backups uploaded successfully"); 59 | } else { 60 | anyhow::bail!("Please specify either --file or --all flag"); 61 | } 62 | 63 | Ok(()) 64 | } 65 | 66 | pub async fn delete_from_cos(key: Option, all: bool, storage: &dyn Storage) -> Result<()> { 67 | if let Some(key_str) = key { 68 | storage.delete(&key_str).await.map_err(anyhow::Error::msg)?; 69 | info!("File deleted successfully: {}", key_str); 70 | } else if all { 71 | let files = storage.list("db").await.map_err(anyhow::Error::msg)?; 72 | 73 | let yesterday_files: Vec<_> = files 74 | .clone() 75 | .into_iter() 76 | .filter(|item| utils::is_yesterday_before(item.last_modified) && item.size > 0) 77 | .collect(); 78 | for entry in yesterday_files { 79 | storage 80 | .delete(&entry.key) 81 | .await 82 | .map_err(anyhow::Error::msg)?; 83 | } 84 | 85 | info!("yesterday before backups delete successfully"); 86 | } else { 87 | anyhow::bail!("Please specify either --key or --all flag"); 88 | } 89 | 90 | Ok(()) 91 | } 92 | -------------------------------------------------------------------------------- /src/utils.rs: -------------------------------------------------------------------------------- 1 | use crate::storage::{CosItem, Storage}; 2 | use anyhow::Result; 3 | use chrono::{DateTime, Utc}; 4 | use futures::future::join_all; 5 | use glob::glob; 6 | use std::{ 7 | path::{Path, PathBuf}, 8 | sync::Arc, 9 | }; 10 | use tabled::Table; 11 | use tokio::task::JoinHandle; 12 | use tracing::{error, info}; 13 | 14 | pub fn resolve_path(path_str: &str) -> Result { 15 | let resolved_path = if path_str.starts_with("~") { 16 | let expanded_str = shellexpand::tilde(path_str); 17 | PathBuf::from(expanded_str.to_string()) 18 | } else { 19 | PathBuf::from(path_str) 20 | }; 21 | 22 | if resolved_path.exists() { 23 | std::fs::canonicalize(&resolved_path) 24 | .map_err(|e| format!("Could not canonicalize path: {}", e)) 25 | } else { 26 | Ok(resolved_path) 27 | } 28 | } 29 | 30 | pub fn is_yesterday_before(date: DateTime) -> bool { 31 | let today = Utc::now().date_naive(); 32 | let yesterday = today.pred_opt(); 33 | match yesterday { 34 | Some(yest) => date.date_naive() < yest, 35 | None => false, 36 | } 37 | } 38 | 39 | pub async fn upload_all_backups( 40 | backup_dir: &Path, 41 | storage: Arc, 42 | cos_path: &str, 43 | ) -> Result<(), String> { 44 | let pattern = backup_dir.join("*.7z").to_string_lossy().to_string(); 45 | 46 | let files = glob(&pattern).map_err(|e| e.to_string())?; 47 | 48 | let files: Vec = files.into_iter().filter_map(|file| file.ok()).collect(); 49 | 50 | let mut tasks: Vec>> = Vec::with_capacity(files.len()); 51 | 52 | let cos_path = cos_path.to_owned(); 53 | for file in files { 54 | let storage = storage.clone(); 55 | let cos_path = cos_path.clone(); 56 | let handle: JoinHandle> = 57 | tokio::spawn(async move { storage.upload(&file, &cos_path).await }); 58 | tasks.push(handle); 59 | } 60 | 61 | let _ = join_all(tasks).await; 62 | Ok(()) 63 | } 64 | 65 | pub async fn cleanup_old_backups(backup_dir: &Path) -> Result<()> { 66 | let pattern = backup_dir.join("*.7z").to_string_lossy().to_string(); 67 | 68 | let files = glob(&pattern)?; 69 | 70 | for entry in files { 71 | match entry { 72 | Ok(path) => { 73 | info!("Remove file: {:?}", &path); 74 | if let Err(e) = tokio::fs::remove_file(&path).await { 75 | error!( 76 | "Failed to remove old backup {}: {}", 77 | &path.display().to_string(), 78 | e 79 | ); 80 | } else { 81 | info!("Removed old backup: {}", &path.display().to_string()); 82 | } 83 | } 84 | Err(e) => { 85 | error!("Error reading file: {}", e); 86 | } 87 | } 88 | } 89 | 90 | Ok(()) 91 | } 92 | 93 | pub fn list_table(files: Vec) -> Result<()> { 94 | let table = Table::new(&files).to_string(); 95 | println!("=== COS 文件列表 ==="); 96 | println!("{}", table); 97 | Ok(()) 98 | } 99 | 100 | #[cfg(test)] 101 | mod tests { 102 | use super::*; 103 | use std::env; 104 | use std::fs::File; 105 | use tempfile::tempdir; 106 | 107 | #[test] 108 | fn test_resolve_path_existing() { 109 | let dir = tempdir().unwrap(); 110 | let file_path = dir.path().join("testfile.txt"); 111 | File::create(&file_path).unwrap(); 112 | 113 | let resolved = resolve_path(file_path.to_str().unwrap()).unwrap(); 114 | assert!(resolved.is_absolute()); 115 | assert!(resolved.ends_with("testfile.txt")); 116 | } 117 | 118 | #[test] 119 | fn test_resolve_path_non_existing() { 120 | let dir = tempdir().unwrap(); 121 | let file_path = dir.path().join("not_exist.txt"); 122 | 123 | let resolved = resolve_path(file_path.to_str().unwrap()).unwrap(); 124 | assert_eq!(resolved, file_path); 125 | } 126 | 127 | #[test] 128 | fn test_resolve_path_with_tilde() { 129 | let home = env::var("HOME").unwrap(); 130 | let test_path = "~/testfile"; 131 | let resolved = resolve_path(test_path).unwrap(); 132 | assert!(resolved.starts_with(&home)); 133 | assert!(resolved.ends_with("testfile")); 134 | } 135 | } 136 | -------------------------------------------------------------------------------- /src/storage/tencent_cos.rs: -------------------------------------------------------------------------------- 1 | use super::CosItem; 2 | use crate::config::TencentCosConfig; 3 | use crate::storage::Storage; 4 | use chrono::{DateTime, Utc}; 5 | use cos_rust_sdk::{BucketClient, Config, CosClient, ListObjectsV2Options, ObjectClient}; 6 | use serde::{Deserialize, Serialize}; 7 | use std::path::{Path, PathBuf}; 8 | use std::time::Duration; 9 | use tracing::info; 10 | 11 | #[derive(Debug, Serialize, Deserialize, Clone)] 12 | pub struct TencentCosItem { 13 | #[serde(rename = "Key")] 14 | pub key: String, 15 | #[serde(rename = "LastModified")] 16 | pub last_modified: DateTime, 17 | #[serde(rename = "Size")] 18 | pub size: u64, 19 | } 20 | 21 | impl From for CosItem { 22 | fn from(item: TencentCosItem) -> Self { 23 | CosItem { 24 | key: item.key, 25 | last_modified: item.last_modified, 26 | size: item.size, 27 | } 28 | } 29 | } 30 | 31 | #[derive(Debug, Clone)] 32 | pub struct TencentCos { 33 | pub client: CosClient, 34 | } 35 | 36 | #[async_trait::async_trait] 37 | impl Storage for TencentCos { 38 | async fn upload(&self, file_path: &Path, cos_path: &str) -> Result<(), String> { 39 | let file_name = file_path.file_name().unwrap().to_string_lossy(); 40 | let cos_path_full = format!("{}{}", cos_path, file_name); 41 | let object_client = ObjectClient::new(self.client.clone()); 42 | 43 | match object_client 44 | .put_object_from_file(&cos_path_full, &PathBuf::from(file_path), None) 45 | .await 46 | { 47 | Ok(_) => { 48 | info!("Successfully uploaded: {}", file_name); 49 | Ok(()) 50 | } 51 | Err(e) => Err(format!("COS upload failed: {}", e)), 52 | } 53 | } 54 | 55 | async fn list(&self, key: &str) -> Result, String> { 56 | let bucket_client = BucketClient::new(self.client.clone()); 57 | let list_options = ListObjectsV2Options { 58 | prefix: Some(key.to_string()), 59 | ..Default::default() 60 | }; 61 | match bucket_client.list_objects_v2(Some(list_options)).await { 62 | Ok(response) => { 63 | if response.contents.is_empty() { 64 | return Ok(vec![]); 65 | } else { 66 | let result = response 67 | .contents 68 | .into_iter() 69 | .map(|item| { 70 | match DateTime::parse_from_rfc3339(&item.last_modified) 71 | .map(|dt| dt.with_timezone(&Utc)) 72 | { 73 | Ok(last_modified) => CosItem { 74 | key: item.key, 75 | last_modified, 76 | size: item.size, 77 | }, 78 | Err(e) => { 79 | info!( 80 | "Failed to parse last_modified: {} ({})", 81 | item.last_modified, e 82 | ); 83 | CosItem { 84 | key: item.key, 85 | last_modified: Utc::now(), 86 | size: item.size, 87 | } 88 | } 89 | } 90 | }) 91 | .collect(); 92 | return Ok(result); 93 | } 94 | } 95 | Err(e) => { 96 | info!("list cos objects failed: {}", e); 97 | Err(e.to_string()) 98 | } 99 | } 100 | } 101 | 102 | async fn delete(&self, key: &str) -> Result<(), String> { 103 | let object_client = ObjectClient::new(self.client.clone()); 104 | match object_client.delete_object(key).await { 105 | Ok(_) => { 106 | info!("Successfully deleted: {}", key); 107 | Ok(()) 108 | } 109 | Err(e) => Err(format!("COS delete failed: {}", e)), 110 | } 111 | } 112 | } 113 | 114 | impl TencentCos { 115 | pub fn new(config: &TencentCosConfig) -> Self { 116 | // 创建配置 117 | let config = Config::new( 118 | &config.secret_id, 119 | &config.secret_key, 120 | &config.region, 121 | &config.bucket, 122 | ) 123 | .with_timeout(Duration::from_secs(30)) 124 | .with_https(true); 125 | 126 | // 创建客户端 127 | let client = CosClient::new(config).expect("init cos client failed"); 128 | TencentCos { client } 129 | } 130 | } 131 | -------------------------------------------------------------------------------- /src/storage/aliyun_oss.rs: -------------------------------------------------------------------------------- 1 | use super::CosItem; 2 | use crate::config::AliyunOssConfig; 3 | use crate::storage::Storage; 4 | use chrono::{DateTime, Utc}; 5 | use s3::{Bucket, Region, creds::Credentials}; 6 | use serde::{Deserialize, Serialize}; 7 | use std::path::Path; 8 | use tracing::info; 9 | 10 | #[derive(Debug, Serialize, Deserialize, Clone)] 11 | pub struct AliyunOssItem { 12 | #[serde(rename = "Key")] 13 | pub key: String, 14 | #[serde(rename = "LastModified")] 15 | pub last_modified: DateTime, 16 | #[serde(rename = "Size")] 17 | pub size: u64, 18 | } 19 | 20 | impl From for CosItem { 21 | fn from(item: AliyunOssItem) -> Self { 22 | CosItem { 23 | key: item.key, 24 | last_modified: item.last_modified, 25 | size: item.size, 26 | } 27 | } 28 | } 29 | 30 | #[derive(Debug, Clone)] 31 | pub struct AliyunOss { 32 | pub client: Box, 33 | } 34 | 35 | #[async_trait::async_trait] 36 | impl Storage for AliyunOss { 37 | async fn upload(&self, file_path: &Path, cos_path: &str) -> Result<(), String> { 38 | let file_name = file_path 39 | .file_name() 40 | .ok_or_else(|| format!("Invalid file path: {}", file_path.display()))? 41 | .to_string_lossy(); 42 | 43 | let s3_key = if cos_path.ends_with('/') { 44 | format!("{}{}", cos_path, file_name) 45 | } else { 46 | format!("{}/{}", cos_path, file_name) 47 | }; 48 | 49 | // 读取文件内容 50 | let content = std::fs::read(file_path) 51 | .map_err(|e| format!("Failed to read file {}: {}", file_path.display(), e))?; 52 | 53 | // 上传到 Aliyun Oss 54 | let res = self 55 | .client 56 | .put_object(&s3_key, &content) 57 | .await 58 | .map_err(|e| format!("S3 upload failed: {}", e))?; 59 | 60 | if res.status_code() == 200 { 61 | info!("Successfully uploaded: {}", file_name,); 62 | Ok(()) 63 | } else { 64 | Err(format!( 65 | "Aliyun oss upload failed with HTTP code: {}", 66 | res.status_code() 67 | )) 68 | } 69 | } 70 | 71 | async fn list(&self, key: &str) -> Result, String> { 72 | let result = self 73 | .client 74 | .list(key.to_string(), None) 75 | .await 76 | .map_err(|e| format!("S3 list failed: {}", e))?; 77 | 78 | let mut all_items = Vec::new(); 79 | for item in result { 80 | let contents = item.contents; 81 | let items: Vec = contents 82 | .into_iter() 83 | .filter_map(|object| { 84 | // Try to parse the last_modified string into DateTime 85 | match DateTime::parse_from_rfc3339(&object.last_modified) 86 | .map(|dt| dt.with_timezone(&Utc)) 87 | { 88 | Ok(last_modified) => Some(CosItem { 89 | key: object.key.clone(), 90 | last_modified, 91 | size: object.size, 92 | }), 93 | Err(e) => { 94 | info!( 95 | "Failed to parse last_modified: {} ({})", 96 | object.last_modified, e 97 | ); 98 | None 99 | } 100 | } 101 | }) 102 | .collect(); 103 | 104 | all_items.extend(items); 105 | } 106 | 107 | Ok(all_items) 108 | } 109 | 110 | async fn delete(&self, key: &str) -> Result<(), String> { 111 | let res = self 112 | .client 113 | .delete_object(key) 114 | .await 115 | .map_err(|e| format!("Aliyun oss delete failed: {}", e))?; 116 | 117 | if res.status_code() == 200 || res.status_code() == 204 { 118 | info!("Successfully deleted: {}", key); 119 | Ok(()) 120 | } else { 121 | Err(format!( 122 | "Aliyun oss delete failed with HTTP code: {}", 123 | res.status_code() 124 | )) 125 | } 126 | } 127 | } 128 | 129 | impl AliyunOss { 130 | pub fn new(config: &AliyunOssConfig) -> Self { 131 | // 创建区域配置 132 | let region = Region::Custom { 133 | region: "".to_string(), 134 | endpoint: config.end_point.to_string(), 135 | }; 136 | 137 | // 创建凭据 138 | let credentials = Credentials { 139 | access_key: Some(config.secret_id.to_string()), 140 | secret_key: Some(config.secret_key.to_string()), 141 | security_token: None, 142 | session_token: None, 143 | expiration: None, 144 | }; 145 | 146 | // 创建存储桶实例 147 | let bucket = Bucket::new(&config.bucket, region, credentials) 148 | .expect("create aliyun oss bucket failed"); 149 | 150 | AliyunOss { client: bucket } 151 | } 152 | } 153 | -------------------------------------------------------------------------------- /src/storage/s3_compatible.rs: -------------------------------------------------------------------------------- 1 | use super::CosItem; 2 | use crate::config::S3OssConfig; 3 | use crate::storage::Storage; 4 | use chrono::{DateTime, Utc}; 5 | use s3::{Bucket, Region, creds::Credentials}; 6 | use serde::{Deserialize, Serialize}; 7 | use std::path::Path; 8 | use tracing::info; 9 | 10 | #[derive(Debug, Serialize, Deserialize, Clone)] 11 | pub struct S3OssItem { 12 | #[serde(rename = "Key")] 13 | pub key: String, 14 | #[serde(rename = "LastModified")] 15 | pub last_modified: DateTime, 16 | #[serde(rename = "Size")] 17 | pub size: u64, 18 | } 19 | 20 | impl From for CosItem { 21 | fn from(item: S3OssItem) -> Self { 22 | CosItem { 23 | key: item.key, 24 | last_modified: item.last_modified, 25 | size: item.size, 26 | } 27 | } 28 | } 29 | 30 | #[derive(Debug, Clone)] 31 | pub struct S3Oss { 32 | pub bucket: Box, 33 | pub bucket_name: String, 34 | } 35 | 36 | #[async_trait::async_trait] 37 | impl Storage for S3Oss { 38 | async fn upload(&self, file_path: &Path, cos_path: &str) -> Result<(), String> { 39 | let file_name = file_path 40 | .file_name() 41 | .ok_or_else(|| format!("Invalid file path: {}", file_path.display()))? 42 | .to_string_lossy(); 43 | 44 | let s3_key = if cos_path.ends_with('/') { 45 | format!("{}{}", cos_path, file_name) 46 | } else { 47 | format!("{}/{}", cos_path, file_name) 48 | }; 49 | 50 | // 读取文件内容 51 | let content = tokio::fs::read(file_path) 52 | .await 53 | .map_err(|e| format!("Failed to read file {}: {}", file_path.display(), e))?; 54 | 55 | // 上传到 S3 56 | let res = self 57 | .bucket 58 | .put_object(&s3_key, &content) 59 | .await 60 | .map_err(|e| format!("S3 upload failed: {}", e))?; 61 | 62 | if res.status_code() == 200 { 63 | info!( 64 | "Successfully uploaded: {} to s3://{}/{}", 65 | file_name, self.bucket_name, s3_key 66 | ); 67 | Ok(()) 68 | } else { 69 | Err(format!( 70 | "S3 upload failed with HTTP code: {}", 71 | res.status_code() 72 | )) 73 | } 74 | } 75 | 76 | async fn list(&self, prefix: &str) -> Result, String> { 77 | let result = self 78 | .bucket 79 | .list(prefix.to_string(), None) 80 | .await 81 | .map_err(|e| format!("S3 list failed: {}", e))?; 82 | 83 | let mut all_items = Vec::new(); 84 | for item in result { 85 | let contents = item.contents; 86 | let items: Vec = contents 87 | .into_iter() 88 | .filter_map(|object| { 89 | // Try to parse the last_modified string into DateTime 90 | match DateTime::parse_from_rfc3339(&object.last_modified) 91 | .map(|dt| dt.with_timezone(&Utc)) 92 | { 93 | Ok(last_modified) => Some(CosItem { 94 | key: object.key.clone(), 95 | last_modified, 96 | size: object.size, 97 | }), 98 | Err(e) => { 99 | info!( 100 | "Failed to parse last_modified: {} ({})", 101 | object.last_modified, e 102 | ); 103 | None 104 | } 105 | } 106 | }) 107 | .collect(); 108 | 109 | all_items.extend(items); 110 | } 111 | 112 | Ok(all_items) 113 | } 114 | 115 | async fn delete(&self, key: &str) -> Result<(), String> { 116 | let res = self 117 | .bucket 118 | .delete_object(key) 119 | .await 120 | .map_err(|e| format!("S3 delete failed: {}", e))?; 121 | 122 | if res.status_code() == 200 || res.status_code() == 204 { 123 | info!("Successfully deleted: s3://{}/{}", self.bucket_name, key); 124 | Ok(()) 125 | } else { 126 | Err(format!( 127 | "S3 delete failed with HTTP code: {}", 128 | res.status_code() 129 | )) 130 | } 131 | } 132 | } 133 | 134 | impl S3Oss { 135 | pub fn new(config: &S3OssConfig) -> Self { 136 | let region_config = match &config.region { 137 | Some(region) => region, 138 | None => "", 139 | }; 140 | // 创建区域配置 141 | let region = if let Some(endpoint_url) = &config.end_point { 142 | // 对于 S3 兼容服务(如 MinIO、阿里云OSS等),使用自定义端点:cite[3]:cite[9] 143 | Region::Custom { 144 | region: region_config.to_string(), 145 | endpoint: endpoint_url.to_string(), 146 | } 147 | } else { 148 | // 对于 AWS S3,使用标准区域 149 | region_config.parse().expect("") 150 | }; 151 | 152 | // 创建凭据 153 | let credentials = Credentials { 154 | access_key: Some(config.secret_id.to_string()), 155 | secret_key: Some(config.secret_key.to_string()), 156 | security_token: None, 157 | session_token: None, 158 | expiration: None, 159 | }; 160 | 161 | // 创建存储桶实例 162 | let bucket = 163 | Bucket::new(&config.bucket, region, credentials).expect("create s3 bucket failed"); 164 | 165 | S3Oss { 166 | bucket, 167 | bucket_name: config.bucket.to_string(), 168 | } 169 | } 170 | } 171 | -------------------------------------------------------------------------------- /src/storage/local_storage.rs: -------------------------------------------------------------------------------- 1 | use super::CosItem; 2 | use crate::{config::AppConfig, storage::Storage, utils::resolve_path}; 3 | use anyhow::Result; 4 | use chrono::{DateTime, Utc}; 5 | use glob::glob; 6 | use serde::{Deserialize, Serialize}; 7 | use std::path::{Path, PathBuf}; 8 | use tokio::fs; 9 | use tracing::info; 10 | 11 | #[derive(Debug, Serialize, Deserialize, Clone)] 12 | pub struct LocalStorageItem { 13 | pub key: String, 14 | pub last_modified: DateTime, 15 | pub size: u64, 16 | } 17 | 18 | impl From for CosItem { 19 | fn from(item: LocalStorageItem) -> Self { 20 | CosItem { 21 | key: item.key, 22 | last_modified: item.last_modified, 23 | size: item.size, 24 | } 25 | } 26 | } 27 | 28 | #[derive(Debug, Clone)] 29 | pub struct LocalStorage { 30 | pub base_path: PathBuf, 31 | } 32 | 33 | #[async_trait::async_trait] 34 | impl Storage for LocalStorage { 35 | async fn upload(&self, _file_path: &Path, _cos_path: &str) -> Result<(), String> { 36 | // // 获取文件名 37 | // let file_name = file_path 38 | // .file_name() 39 | // .ok_or_else(|| format!("Invalid file path: {}", file_path.display()))? 40 | // .to_string_lossy(); 41 | 42 | // // 构建目标路径 43 | // let target_path = self.base_path.join(&file_name.as_ref()); 44 | // fs::copy(file_path, target_path.as_path()) 45 | // .await 46 | // .map_err(|e| format!("Failed to copy file: {}", e))?; 47 | // info!( 48 | // "Successfully uploaded: {} to {}", 49 | // file_name, 50 | // target_path.display() 51 | // ); 52 | Ok(()) 53 | } 54 | 55 | async fn list(&self, key: &str) -> Result, String> { 56 | let pattern = self.base_path.join(key).to_string_lossy().to_string(); 57 | let mut items = Vec::new(); 58 | 59 | let files = glob(&pattern).map_err(|e| e.to_string())?; 60 | 61 | for path in files.flatten() { 62 | let metadata = fs::metadata(&path).await.map_err(|e| e.to_string())?; 63 | if metadata.is_file() { 64 | let last_modified: DateTime = metadata 65 | .modified() 66 | .map_err(|e| format!("Failed to get modification time: {}", e))? 67 | .into(); 68 | 69 | let file_name = path 70 | .file_name() 71 | .ok_or_else(|| format!("Invalid file path: {}", path.display()))? 72 | .to_string_lossy(); 73 | 74 | items.push(LocalStorageItem { 75 | key: file_name.to_string(), 76 | last_modified, 77 | size: metadata.len(), 78 | }); 79 | } 80 | } 81 | 82 | // 按最后修改时间排序(最新的在前) 83 | items.sort_by(|a, b| b.last_modified.cmp(&a.last_modified)); 84 | 85 | Ok(items.into_iter().map(CosItem::from).collect()) 86 | } 87 | 88 | async fn delete(&self, key: &str) -> Result<(), String> { 89 | let target_path = self.base_path.join(key); 90 | 91 | if !target_path.exists() { 92 | return Err(format!("File not found: {}", target_path.display())); 93 | } 94 | 95 | fs::remove_file(&target_path) 96 | .await 97 | .map_err(|e| e.to_string())?; 98 | 99 | info!("Successfully deleted: {}", target_path.display()); 100 | Ok(()) 101 | } 102 | } 103 | 104 | impl LocalStorage { 105 | pub async fn new(base_path: &str) -> Self { 106 | let path = resolve_path(base_path); 107 | let backup_path = match path { 108 | Ok(p) => p, 109 | Err(_) => AppConfig::default().backup_dir, 110 | }; 111 | let _ = fs::create_dir_all(&backup_path).await.map_err(|_| {}); 112 | LocalStorage { 113 | base_path: backup_path, 114 | } 115 | } 116 | } 117 | 118 | #[cfg(test)] 119 | mod tests { 120 | use super::*; 121 | use tempfile::tempdir; 122 | use tokio::fs::File; 123 | use tokio::io::AsyncWriteExt; 124 | 125 | #[tokio::test] 126 | async fn test_local_storage_upload() { 127 | let temp_dir = tempdir().unwrap(); 128 | let storage = LocalStorage::new(temp_dir.path().to_str().unwrap()).await; 129 | 130 | // 创建测试文件 131 | let test_file = temp_dir.path().join("test.txt"); 132 | let mut file = File::create(&test_file).await.unwrap(); 133 | file.write_all(b"test content").await.unwrap(); 134 | 135 | // 测试上传 136 | let result = storage.upload(&test_file, "uploads/").await; 137 | assert!(result.is_ok()); 138 | 139 | // 检查文件是否被复制 140 | let target_file = temp_dir.path().join("test.txt"); 141 | assert!(target_file.exists()); 142 | } 143 | 144 | #[tokio::test] 145 | async fn test_local_storage_list() { 146 | let temp_dir = tempdir().unwrap(); 147 | let storage = LocalStorage::new(temp_dir.path().to_str().unwrap()).await; 148 | 149 | // 创建测试文件 150 | let test_file = temp_dir.path().join("test.txt"); 151 | let mut file = File::create(&test_file).await.unwrap(); 152 | file.write_all(b"test content").await.unwrap(); 153 | 154 | // 测试列表 155 | let items = storage.list("*.txt").await.unwrap(); 156 | println!("items {:?}", items); 157 | assert!(!items.is_empty()); 158 | assert_eq!(items[0].key, "test.txt"); 159 | } 160 | 161 | #[tokio::test] 162 | async fn test_local_storage_delete() { 163 | let temp_dir = tempdir().unwrap(); 164 | let storage = LocalStorage::new(temp_dir.path().to_str().unwrap()).await; 165 | 166 | // 创建测试文件 167 | let test_file = temp_dir.path().join("test.txt"); 168 | let mut file = File::create(&test_file).await.unwrap(); 169 | file.write_all(b"test content").await.unwrap(); 170 | 171 | // 测试删除 172 | let result = storage.delete("test.txt").await; 173 | assert!(result.is_ok()); 174 | assert!(!test_file.exists()); 175 | } 176 | } 177 | -------------------------------------------------------------------------------- /src/config.rs: -------------------------------------------------------------------------------- 1 | use crate::database::Database; 2 | use crate::database::{mysql::MySql, postgresql::PostgreSql}; 3 | use crate::storage::Storage; 4 | use crate::storage::aliyun_oss::AliyunOss; 5 | use crate::storage::local_storage::LocalStorage; 6 | use crate::storage::s3_compatible::S3Oss; 7 | use crate::storage::tencent_cos::TencentCos; 8 | use config::{Config, ConfigError, File}; 9 | use serde::Deserialize; 10 | use std::path::PathBuf; 11 | use std::sync::Arc; 12 | use tokio::fs::create_dir_all; 13 | 14 | #[derive(Debug, Deserialize, Clone)] 15 | pub struct AllConfig { 16 | pub app: AppConfig, 17 | pub tencent_cos: TencentCosConfig, 18 | pub postgresql: PostgreSqlConfig, 19 | pub mysql: MySqlConfig, 20 | pub aliyun_oss: AliyunOssConfig, 21 | pub s3: S3OssConfig, 22 | } 23 | 24 | #[derive(Debug, Deserialize, Clone)] 25 | pub struct AppConfig { 26 | pub backup_dir: PathBuf, 27 | pub db_type: DbType, 28 | pub cos_provider: CosProvider, 29 | pub cos_path: String, 30 | pub compress_password: String, 31 | } 32 | 33 | #[derive(Debug, Deserialize, Clone)] 34 | pub struct TencentCosConfig { 35 | pub secret_id: String, 36 | pub secret_key: String, 37 | pub region: String, 38 | pub bucket: String, 39 | } 40 | 41 | #[derive(Debug, Deserialize, Clone)] 42 | pub struct AliyunOssConfig { 43 | pub secret_id: String, 44 | pub secret_key: String, 45 | pub end_point: String, 46 | pub bucket: String, 47 | } 48 | 49 | #[derive(Debug, Deserialize, Clone)] 50 | pub struct S3OssConfig { 51 | pub secret_id: String, 52 | pub secret_key: String, 53 | pub end_point: Option, 54 | pub bucket: String, 55 | pub region: Option, 56 | } 57 | 58 | #[derive(Debug, Deserialize, Clone)] 59 | pub struct PostgreSqlConfig { 60 | pub host: String, 61 | pub port: u16, 62 | pub username: String, 63 | pub password: String, 64 | } 65 | 66 | #[derive(Debug, Deserialize, Clone)] 67 | pub struct MySqlConfig { 68 | pub host: String, 69 | pub port: u16, 70 | pub username: String, 71 | pub password: String, 72 | } 73 | 74 | #[derive(Debug, Deserialize, Clone, PartialEq)] 75 | pub enum DbType { 76 | #[serde(rename = "postgresql")] 77 | Postgresql, 78 | #[serde(rename = "mysql")] 79 | MySql, 80 | } 81 | 82 | #[derive(Debug, Deserialize, Clone, PartialEq)] 83 | pub enum CosProvider { 84 | #[serde(rename = "tencent_cos")] 85 | TencentCos, 86 | #[serde(rename = "aliyun_oss")] 87 | AliyunOss, 88 | #[serde(rename = "local")] 89 | LocalStorage, 90 | #[serde(rename = "s3")] 91 | S3, 92 | } 93 | 94 | impl Default for AppConfig { 95 | fn default() -> Self { 96 | let backup_dir = dirs::home_dir() 97 | .unwrap_or_else(|| PathBuf::from("~")) 98 | .join(".dbbackup"); 99 | 100 | AppConfig { 101 | backup_dir, 102 | db_type: DbType::Postgresql, 103 | cos_provider: CosProvider::TencentCos, 104 | cos_path: "db/".into(), 105 | compress_password: "dbbackuppassword".into(), 106 | } 107 | } 108 | } 109 | 110 | impl AppConfig { 111 | pub async fn confirm_backup_dir(&self) { 112 | let home_dir: PathBuf = AppConfig::default().backup_dir; 113 | let result = create_dir_all(&self.backup_dir).await; 114 | if result.is_err() { 115 | create_dir_all(home_dir).await.unwrap(); 116 | } 117 | } 118 | 119 | pub fn get_backup_dir(&self) -> PathBuf { 120 | self.backup_dir.clone() 121 | } 122 | 123 | pub fn database(&self, config: &AllConfig) -> Box { 124 | match self.db_type { 125 | DbType::Postgresql => { 126 | let postgresql = PostgreSql::new(&config.postgresql); 127 | Box::new(postgresql) 128 | } 129 | DbType::MySql => { 130 | let mysql = MySql::new(&config.mysql); 131 | Box::new(mysql) 132 | } 133 | } 134 | } 135 | pub async fn storage(&self, config: &AllConfig) -> Arc { 136 | match self.cos_provider { 137 | CosProvider::TencentCos => { 138 | let config = &config.tencent_cos; 139 | let storage = TencentCos::new(config); 140 | Arc::new(storage) 141 | } 142 | CosProvider::AliyunOss => { 143 | let config = &config.aliyun_oss; 144 | let storage = AliyunOss::new(config); 145 | Arc::new(storage) 146 | } 147 | CosProvider::LocalStorage => { 148 | let path = &config.app.get_backup_dir(); 149 | let storage = LocalStorage::new(path.to_str().unwrap()).await; 150 | Arc::new(storage) 151 | } 152 | CosProvider::S3 => { 153 | let config = &config.s3; 154 | let storage = S3Oss::new(config); 155 | Arc::new(storage) 156 | } 157 | } 158 | } 159 | } 160 | 161 | pub fn get_all_config(config_path: &str) -> anyhow::Result { 162 | let config_builder = Config::builder() 163 | // 加载配置文件 164 | .add_source(File::with_name(config_path)) 165 | .build()?; 166 | 167 | let config = config_builder.try_deserialize()?; 168 | Ok(config) 169 | } 170 | 171 | #[cfg(test)] 172 | mod tests { 173 | use super::*; 174 | use std::fs::File as StdFile; 175 | use std::io::Write; 176 | use tempfile::tempdir; 177 | 178 | #[test] 179 | fn test_get_all_config() { 180 | // 创建一个临时目录 181 | let dir = tempdir().unwrap(); 182 | let file_path = dir.path().join("test_config.toml"); 183 | 184 | // 构造一个配置文件内容 185 | let config_content = r#" 186 | [app] 187 | backup_dir = "/tmp/dbbackup" 188 | db_type = "postgresql" 189 | cos_provider = "tencent_cos" 190 | cos_path = "db/" 191 | compress_password = "testpassword" 192 | 193 | [tencent_cos] 194 | secret_id = "testid" 195 | secret_key = "testkey" 196 | region = "ap-guangzhou" 197 | bucket = "testbucket" 198 | 199 | [postgresql] 200 | host = "localhost" 201 | port = 5432 202 | username = "user" 203 | password = "pass" 204 | 205 | [mysql] 206 | host = "localhost" 207 | port = 3306 208 | username = "user" 209 | password = "pass" 210 | 211 | [aliyun_oss] 212 | secret_id = "testid" 213 | secret_key = "testkey" 214 | end_point = "ap-guangzhou" 215 | bucket = "testbucket" 216 | "#; 217 | 218 | // 写入临时配置文件 219 | let mut file = StdFile::create(&file_path).unwrap(); 220 | file.write_all(config_content.as_bytes()).unwrap(); 221 | 222 | // 调用get_all_config 223 | let config = get_all_config(file_path.to_str().unwrap()).unwrap(); 224 | 225 | // 断言配置内容 226 | assert_eq!(config.app.backup_dir, PathBuf::from("/tmp/dbbackup")); 227 | assert_eq!(config.app.db_type, DbType::Postgresql); 228 | assert_eq!(config.app.cos_provider, CosProvider::TencentCos); 229 | assert_eq!(config.app.cos_path, "db/"); 230 | assert_eq!(config.app.compress_password, "testpassword"); 231 | 232 | assert_eq!(config.tencent_cos.secret_id, "testid"); 233 | assert_eq!(config.tencent_cos.secret_key, "testkey"); 234 | assert_eq!(config.tencent_cos.region, "ap-guangzhou"); 235 | assert_eq!(config.tencent_cos.bucket, "testbucket"); 236 | 237 | assert_eq!(config.postgresql.host, "localhost"); 238 | assert_eq!(config.postgresql.port, 5432); 239 | assert_eq!(config.postgresql.username, "user"); 240 | assert_eq!(config.postgresql.password, "pass"); 241 | } 242 | } 243 | -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 4 4 | 5 | [[package]] 6 | name = "addr2line" 7 | version = "0.24.2" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" 10 | dependencies = [ 11 | "gimli", 12 | ] 13 | 14 | [[package]] 15 | name = "adler2" 16 | version = "2.0.1" 17 | source = "registry+https://github.com/rust-lang/crates.io-index" 18 | checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" 19 | 20 | [[package]] 21 | name = "android_system_properties" 22 | version = "0.1.5" 23 | source = "registry+https://github.com/rust-lang/crates.io-index" 24 | checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" 25 | dependencies = [ 26 | "libc", 27 | ] 28 | 29 | [[package]] 30 | name = "anstream" 31 | version = "0.6.20" 32 | source = "registry+https://github.com/rust-lang/crates.io-index" 33 | checksum = "3ae563653d1938f79b1ab1b5e668c87c76a9930414574a6583a7b7e11a8e6192" 34 | dependencies = [ 35 | "anstyle", 36 | "anstyle-parse", 37 | "anstyle-query", 38 | "anstyle-wincon", 39 | "colorchoice", 40 | "is_terminal_polyfill", 41 | "utf8parse", 42 | ] 43 | 44 | [[package]] 45 | name = "anstyle" 46 | version = "1.0.11" 47 | source = "registry+https://github.com/rust-lang/crates.io-index" 48 | checksum = "862ed96ca487e809f1c8e5a8447f6ee2cf102f846893800b20cebdf541fc6bbd" 49 | 50 | [[package]] 51 | name = "anstyle-parse" 52 | version = "0.2.7" 53 | source = "registry+https://github.com/rust-lang/crates.io-index" 54 | checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2" 55 | dependencies = [ 56 | "utf8parse", 57 | ] 58 | 59 | [[package]] 60 | name = "anstyle-query" 61 | version = "1.1.4" 62 | source = "registry+https://github.com/rust-lang/crates.io-index" 63 | checksum = "9e231f6134f61b71076a3eab506c379d4f36122f2af15a9ff04415ea4c3339e2" 64 | dependencies = [ 65 | "windows-sys 0.60.2", 66 | ] 67 | 68 | [[package]] 69 | name = "anstyle-wincon" 70 | version = "3.0.10" 71 | source = "registry+https://github.com/rust-lang/crates.io-index" 72 | checksum = "3e0633414522a32ffaac8ac6cc8f748e090c5717661fddeea04219e2344f5f2a" 73 | dependencies = [ 74 | "anstyle", 75 | "once_cell_polyfill", 76 | "windows-sys 0.60.2", 77 | ] 78 | 79 | [[package]] 80 | name = "anyhow" 81 | version = "1.0.100" 82 | source = "registry+https://github.com/rust-lang/crates.io-index" 83 | checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" 84 | 85 | [[package]] 86 | name = "arraydeque" 87 | version = "0.5.1" 88 | source = "registry+https://github.com/rust-lang/crates.io-index" 89 | checksum = "7d902e3d592a523def97af8f317b08ce16b7ab854c1985a0c671e6f15cebc236" 90 | 91 | [[package]] 92 | name = "async-trait" 93 | version = "0.1.89" 94 | source = "registry+https://github.com/rust-lang/crates.io-index" 95 | checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" 96 | dependencies = [ 97 | "proc-macro2", 98 | "quote", 99 | "syn", 100 | ] 101 | 102 | [[package]] 103 | name = "atomic-waker" 104 | version = "1.1.2" 105 | source = "registry+https://github.com/rust-lang/crates.io-index" 106 | checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" 107 | 108 | [[package]] 109 | name = "attohttpc" 110 | version = "0.30.1" 111 | source = "registry+https://github.com/rust-lang/crates.io-index" 112 | checksum = "16e2cdb6d5ed835199484bb92bb8b3edd526effe995c61732580439c1a67e2e9" 113 | dependencies = [ 114 | "base64 0.22.1", 115 | "http", 116 | "log", 117 | "native-tls", 118 | "serde", 119 | "serde_json", 120 | "url", 121 | ] 122 | 123 | [[package]] 124 | name = "autocfg" 125 | version = "1.5.0" 126 | source = "registry+https://github.com/rust-lang/crates.io-index" 127 | checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" 128 | 129 | [[package]] 130 | name = "aws-creds" 131 | version = "0.39.0" 132 | source = "registry+https://github.com/rust-lang/crates.io-index" 133 | checksum = "b13804829a843b3f26e151c97acbb315ee1177a2724690edfcd28f1894146200" 134 | dependencies = [ 135 | "attohttpc", 136 | "home", 137 | "log", 138 | "quick-xml 0.38.3", 139 | "rust-ini", 140 | "serde", 141 | "thiserror 2.0.16", 142 | "time", 143 | "url", 144 | ] 145 | 146 | [[package]] 147 | name = "aws-region" 148 | version = "0.28.0" 149 | source = "registry+https://github.com/rust-lang/crates.io-index" 150 | checksum = "5532f65342f789f9c1b7078ea9c9cd9293cd62dcc284fa99adc4a1c9ba43469c" 151 | dependencies = [ 152 | "thiserror 2.0.16", 153 | ] 154 | 155 | [[package]] 156 | name = "backtrace" 157 | version = "0.3.75" 158 | source = "registry+https://github.com/rust-lang/crates.io-index" 159 | checksum = "6806a6321ec58106fea15becdad98371e28d92ccbc7c8f1b3b6dd724fe8f1002" 160 | dependencies = [ 161 | "addr2line", 162 | "cfg-if", 163 | "libc", 164 | "miniz_oxide", 165 | "object", 166 | "rustc-demangle", 167 | "windows-targets 0.52.6", 168 | ] 169 | 170 | [[package]] 171 | name = "backupdbtool" 172 | version = "1.5.1" 173 | dependencies = [ 174 | "anyhow", 175 | "async-trait", 176 | "chrono", 177 | "clap", 178 | "config", 179 | "cos-rust-sdk", 180 | "dirs", 181 | "futures", 182 | "glob", 183 | "humansize", 184 | "once_cell", 185 | "reqwest", 186 | "rust-s3", 187 | "serde", 188 | "serde_json", 189 | "shellexpand", 190 | "tabled", 191 | "tempfile", 192 | "tokio", 193 | "tracing", 194 | "tracing-subscriber", 195 | ] 196 | 197 | [[package]] 198 | name = "base64" 199 | version = "0.21.7" 200 | source = "registry+https://github.com/rust-lang/crates.io-index" 201 | checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" 202 | 203 | [[package]] 204 | name = "base64" 205 | version = "0.22.1" 206 | source = "registry+https://github.com/rust-lang/crates.io-index" 207 | checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" 208 | 209 | [[package]] 210 | name = "bitflags" 211 | version = "2.9.4" 212 | source = "registry+https://github.com/rust-lang/crates.io-index" 213 | checksum = "2261d10cca569e4643e526d8dc2e62e433cc8aba21ab764233731f8d369bf394" 214 | dependencies = [ 215 | "serde", 216 | ] 217 | 218 | [[package]] 219 | name = "block-buffer" 220 | version = "0.10.4" 221 | source = "registry+https://github.com/rust-lang/crates.io-index" 222 | checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" 223 | dependencies = [ 224 | "generic-array", 225 | ] 226 | 227 | [[package]] 228 | name = "bumpalo" 229 | version = "3.19.0" 230 | source = "registry+https://github.com/rust-lang/crates.io-index" 231 | checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" 232 | 233 | [[package]] 234 | name = "bytecount" 235 | version = "0.6.9" 236 | source = "registry+https://github.com/rust-lang/crates.io-index" 237 | checksum = "175812e0be2bccb6abe50bb8d566126198344f707e304f45c648fd8f2cc0365e" 238 | 239 | [[package]] 240 | name = "bytes" 241 | version = "1.10.1" 242 | source = "registry+https://github.com/rust-lang/crates.io-index" 243 | checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" 244 | 245 | [[package]] 246 | name = "castaway" 247 | version = "0.2.4" 248 | source = "registry+https://github.com/rust-lang/crates.io-index" 249 | checksum = "dec551ab6e7578819132c713a93c022a05d60159dc86e7a7050223577484c55a" 250 | dependencies = [ 251 | "rustversion", 252 | ] 253 | 254 | [[package]] 255 | name = "cc" 256 | version = "1.2.38" 257 | source = "registry+https://github.com/rust-lang/crates.io-index" 258 | checksum = "80f41ae168f955c12fb8960b057d70d0ca153fb83182b57d86380443527be7e9" 259 | dependencies = [ 260 | "find-msvc-tools", 261 | "shlex", 262 | ] 263 | 264 | [[package]] 265 | name = "cfg-if" 266 | version = "1.0.3" 267 | source = "registry+https://github.com/rust-lang/crates.io-index" 268 | checksum = "2fd1289c04a9ea8cb22300a459a72a385d7c73d3259e2ed7dcb2af674838cfa9" 269 | 270 | [[package]] 271 | name = "chrono" 272 | version = "0.4.42" 273 | source = "registry+https://github.com/rust-lang/crates.io-index" 274 | checksum = "145052bdd345b87320e369255277e3fb5152762ad123a901ef5c262dd38fe8d2" 275 | dependencies = [ 276 | "iana-time-zone", 277 | "js-sys", 278 | "num-traits", 279 | "serde", 280 | "wasm-bindgen", 281 | "windows-link 0.2.0", 282 | ] 283 | 284 | [[package]] 285 | name = "clap" 286 | version = "4.5.48" 287 | source = "registry+https://github.com/rust-lang/crates.io-index" 288 | checksum = "e2134bb3ea021b78629caa971416385309e0131b351b25e01dc16fb54e1b5fae" 289 | dependencies = [ 290 | "clap_builder", 291 | "clap_derive", 292 | ] 293 | 294 | [[package]] 295 | name = "clap_builder" 296 | version = "4.5.48" 297 | source = "registry+https://github.com/rust-lang/crates.io-index" 298 | checksum = "c2ba64afa3c0a6df7fa517765e31314e983f51dda798ffba27b988194fb65dc9" 299 | dependencies = [ 300 | "anstream", 301 | "anstyle", 302 | "clap_lex", 303 | "strsim", 304 | ] 305 | 306 | [[package]] 307 | name = "clap_derive" 308 | version = "4.5.47" 309 | source = "registry+https://github.com/rust-lang/crates.io-index" 310 | checksum = "bbfd7eae0b0f1a6e63d4b13c9c478de77c2eb546fba158ad50b4203dc24b9f9c" 311 | dependencies = [ 312 | "heck", 313 | "proc-macro2", 314 | "quote", 315 | "syn", 316 | ] 317 | 318 | [[package]] 319 | name = "clap_lex" 320 | version = "0.7.5" 321 | source = "registry+https://github.com/rust-lang/crates.io-index" 322 | checksum = "b94f61472cee1439c0b966b47e3aca9ae07e45d070759512cd390ea2bebc6675" 323 | 324 | [[package]] 325 | name = "colorchoice" 326 | version = "1.0.4" 327 | source = "registry+https://github.com/rust-lang/crates.io-index" 328 | checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" 329 | 330 | [[package]] 331 | name = "compact_str" 332 | version = "0.7.1" 333 | source = "registry+https://github.com/rust-lang/crates.io-index" 334 | checksum = "f86b9c4c00838774a6d902ef931eff7470720c51d90c2e32cfe15dc304737b3f" 335 | dependencies = [ 336 | "castaway", 337 | "cfg-if", 338 | "itoa", 339 | "ryu", 340 | "static_assertions", 341 | ] 342 | 343 | [[package]] 344 | name = "config" 345 | version = "0.15.16" 346 | source = "registry+https://github.com/rust-lang/crates.io-index" 347 | checksum = "cef036f0ecf99baef11555578630e2cca559909b4c50822dbba828c252d21c49" 348 | dependencies = [ 349 | "async-trait", 350 | "convert_case", 351 | "json5", 352 | "pathdiff", 353 | "ron", 354 | "rust-ini", 355 | "serde-untagged", 356 | "serde_core", 357 | "serde_json", 358 | "toml", 359 | "winnow", 360 | "yaml-rust2", 361 | ] 362 | 363 | [[package]] 364 | name = "const-random" 365 | version = "0.1.18" 366 | source = "registry+https://github.com/rust-lang/crates.io-index" 367 | checksum = "87e00182fe74b066627d63b85fd550ac2998d4b0bd86bfed477a0ae4c7c71359" 368 | dependencies = [ 369 | "const-random-macro", 370 | ] 371 | 372 | [[package]] 373 | name = "const-random-macro" 374 | version = "0.1.16" 375 | source = "registry+https://github.com/rust-lang/crates.io-index" 376 | checksum = "f9d839f2a20b0aee515dc581a6172f2321f96cab76c1a38a4c584a194955390e" 377 | dependencies = [ 378 | "getrandom 0.2.16", 379 | "once_cell", 380 | "tiny-keccak", 381 | ] 382 | 383 | [[package]] 384 | name = "convert_case" 385 | version = "0.6.0" 386 | source = "registry+https://github.com/rust-lang/crates.io-index" 387 | checksum = "ec182b0ca2f35d8fc196cf3404988fd8b8c739a4d270ff118a398feb0cbec1ca" 388 | dependencies = [ 389 | "unicode-segmentation", 390 | ] 391 | 392 | [[package]] 393 | name = "core-foundation" 394 | version = "0.9.4" 395 | source = "registry+https://github.com/rust-lang/crates.io-index" 396 | checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" 397 | dependencies = [ 398 | "core-foundation-sys", 399 | "libc", 400 | ] 401 | 402 | [[package]] 403 | name = "core-foundation-sys" 404 | version = "0.8.7" 405 | source = "registry+https://github.com/rust-lang/crates.io-index" 406 | checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" 407 | 408 | [[package]] 409 | name = "cos-rust-sdk" 410 | version = "0.1.2" 411 | source = "registry+https://github.com/rust-lang/crates.io-index" 412 | checksum = "0acb5456c8776c38ab1ba9ad4aeb3584ee34a876bafc86f82ceef0637a184adb" 413 | dependencies = [ 414 | "base64 0.22.1", 415 | "bytes", 416 | "chrono", 417 | "futures", 418 | "hex", 419 | "hmac", 420 | "log", 421 | "md5 0.7.0", 422 | "quick-xml 0.31.0", 423 | "rand", 424 | "reqwest", 425 | "serde", 426 | "serde_json", 427 | "sha1", 428 | "sha2", 429 | "thiserror 1.0.69", 430 | "tokio", 431 | "url", 432 | "urlencoding", 433 | ] 434 | 435 | [[package]] 436 | name = "cpufeatures" 437 | version = "0.2.17" 438 | source = "registry+https://github.com/rust-lang/crates.io-index" 439 | checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" 440 | dependencies = [ 441 | "libc", 442 | ] 443 | 444 | [[package]] 445 | name = "crunchy" 446 | version = "0.2.4" 447 | source = "registry+https://github.com/rust-lang/crates.io-index" 448 | checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" 449 | 450 | [[package]] 451 | name = "crypto-common" 452 | version = "0.1.6" 453 | source = "registry+https://github.com/rust-lang/crates.io-index" 454 | checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" 455 | dependencies = [ 456 | "generic-array", 457 | "typenum", 458 | ] 459 | 460 | [[package]] 461 | name = "deranged" 462 | version = "0.5.3" 463 | source = "registry+https://github.com/rust-lang/crates.io-index" 464 | checksum = "d630bccd429a5bb5a64b5e94f693bfc48c9f8566418fda4c494cc94f911f87cc" 465 | dependencies = [ 466 | "powerfmt", 467 | "serde", 468 | ] 469 | 470 | [[package]] 471 | name = "digest" 472 | version = "0.10.7" 473 | source = "registry+https://github.com/rust-lang/crates.io-index" 474 | checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" 475 | dependencies = [ 476 | "block-buffer", 477 | "crypto-common", 478 | "subtle", 479 | ] 480 | 481 | [[package]] 482 | name = "dirs" 483 | version = "6.0.0" 484 | source = "registry+https://github.com/rust-lang/crates.io-index" 485 | checksum = "c3e8aa94d75141228480295a7d0e7feb620b1a5ad9f12bc40be62411e38cce4e" 486 | dependencies = [ 487 | "dirs-sys", 488 | ] 489 | 490 | [[package]] 491 | name = "dirs-sys" 492 | version = "0.5.0" 493 | source = "registry+https://github.com/rust-lang/crates.io-index" 494 | checksum = "e01a3366d27ee9890022452ee61b2b63a67e6f13f58900b651ff5665f0bb1fab" 495 | dependencies = [ 496 | "libc", 497 | "option-ext", 498 | "redox_users", 499 | "windows-sys 0.61.0", 500 | ] 501 | 502 | [[package]] 503 | name = "displaydoc" 504 | version = "0.2.5" 505 | source = "registry+https://github.com/rust-lang/crates.io-index" 506 | checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" 507 | dependencies = [ 508 | "proc-macro2", 509 | "quote", 510 | "syn", 511 | ] 512 | 513 | [[package]] 514 | name = "dlv-list" 515 | version = "0.5.2" 516 | source = "registry+https://github.com/rust-lang/crates.io-index" 517 | checksum = "442039f5147480ba31067cb00ada1adae6892028e40e45fc5de7b7df6dcc1b5f" 518 | dependencies = [ 519 | "const-random", 520 | ] 521 | 522 | [[package]] 523 | name = "encoding_rs" 524 | version = "0.8.35" 525 | source = "registry+https://github.com/rust-lang/crates.io-index" 526 | checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" 527 | dependencies = [ 528 | "cfg-if", 529 | ] 530 | 531 | [[package]] 532 | name = "equivalent" 533 | version = "1.0.2" 534 | source = "registry+https://github.com/rust-lang/crates.io-index" 535 | checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" 536 | 537 | [[package]] 538 | name = "erased-serde" 539 | version = "0.4.8" 540 | source = "registry+https://github.com/rust-lang/crates.io-index" 541 | checksum = "259d404d09818dec19332e31d94558aeb442fea04c817006456c24b5460bbd4b" 542 | dependencies = [ 543 | "serde", 544 | "serde_core", 545 | "typeid", 546 | ] 547 | 548 | [[package]] 549 | name = "errno" 550 | version = "0.3.14" 551 | source = "registry+https://github.com/rust-lang/crates.io-index" 552 | checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" 553 | dependencies = [ 554 | "libc", 555 | "windows-sys 0.61.0", 556 | ] 557 | 558 | [[package]] 559 | name = "fastrand" 560 | version = "2.3.0" 561 | source = "registry+https://github.com/rust-lang/crates.io-index" 562 | checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" 563 | 564 | [[package]] 565 | name = "find-msvc-tools" 566 | version = "0.1.2" 567 | source = "registry+https://github.com/rust-lang/crates.io-index" 568 | checksum = "1ced73b1dacfc750a6db6c0a0c3a3853c8b41997e2e2c563dc90804ae6867959" 569 | 570 | [[package]] 571 | name = "fnv" 572 | version = "1.0.7" 573 | source = "registry+https://github.com/rust-lang/crates.io-index" 574 | checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" 575 | 576 | [[package]] 577 | name = "foldhash" 578 | version = "0.1.5" 579 | source = "registry+https://github.com/rust-lang/crates.io-index" 580 | checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" 581 | 582 | [[package]] 583 | name = "foreign-types" 584 | version = "0.3.2" 585 | source = "registry+https://github.com/rust-lang/crates.io-index" 586 | checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" 587 | dependencies = [ 588 | "foreign-types-shared", 589 | ] 590 | 591 | [[package]] 592 | name = "foreign-types-shared" 593 | version = "0.1.1" 594 | source = "registry+https://github.com/rust-lang/crates.io-index" 595 | checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" 596 | 597 | [[package]] 598 | name = "form_urlencoded" 599 | version = "1.2.2" 600 | source = "registry+https://github.com/rust-lang/crates.io-index" 601 | checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf" 602 | dependencies = [ 603 | "percent-encoding", 604 | ] 605 | 606 | [[package]] 607 | name = "futures" 608 | version = "0.3.31" 609 | source = "registry+https://github.com/rust-lang/crates.io-index" 610 | checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" 611 | dependencies = [ 612 | "futures-channel", 613 | "futures-core", 614 | "futures-executor", 615 | "futures-io", 616 | "futures-sink", 617 | "futures-task", 618 | "futures-util", 619 | ] 620 | 621 | [[package]] 622 | name = "futures-channel" 623 | version = "0.3.31" 624 | source = "registry+https://github.com/rust-lang/crates.io-index" 625 | checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" 626 | dependencies = [ 627 | "futures-core", 628 | "futures-sink", 629 | ] 630 | 631 | [[package]] 632 | name = "futures-core" 633 | version = "0.3.31" 634 | source = "registry+https://github.com/rust-lang/crates.io-index" 635 | checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" 636 | 637 | [[package]] 638 | name = "futures-executor" 639 | version = "0.3.31" 640 | source = "registry+https://github.com/rust-lang/crates.io-index" 641 | checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" 642 | dependencies = [ 643 | "futures-core", 644 | "futures-task", 645 | "futures-util", 646 | ] 647 | 648 | [[package]] 649 | name = "futures-io" 650 | version = "0.3.31" 651 | source = "registry+https://github.com/rust-lang/crates.io-index" 652 | checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" 653 | 654 | [[package]] 655 | name = "futures-macro" 656 | version = "0.3.31" 657 | source = "registry+https://github.com/rust-lang/crates.io-index" 658 | checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" 659 | dependencies = [ 660 | "proc-macro2", 661 | "quote", 662 | "syn", 663 | ] 664 | 665 | [[package]] 666 | name = "futures-sink" 667 | version = "0.3.31" 668 | source = "registry+https://github.com/rust-lang/crates.io-index" 669 | checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" 670 | 671 | [[package]] 672 | name = "futures-task" 673 | version = "0.3.31" 674 | source = "registry+https://github.com/rust-lang/crates.io-index" 675 | checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" 676 | 677 | [[package]] 678 | name = "futures-util" 679 | version = "0.3.31" 680 | source = "registry+https://github.com/rust-lang/crates.io-index" 681 | checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" 682 | dependencies = [ 683 | "futures-channel", 684 | "futures-core", 685 | "futures-io", 686 | "futures-macro", 687 | "futures-sink", 688 | "futures-task", 689 | "memchr", 690 | "pin-project-lite", 691 | "pin-utils", 692 | "slab", 693 | ] 694 | 695 | [[package]] 696 | name = "generic-array" 697 | version = "0.14.7" 698 | source = "registry+https://github.com/rust-lang/crates.io-index" 699 | checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" 700 | dependencies = [ 701 | "typenum", 702 | "version_check", 703 | ] 704 | 705 | [[package]] 706 | name = "getrandom" 707 | version = "0.2.16" 708 | source = "registry+https://github.com/rust-lang/crates.io-index" 709 | checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" 710 | dependencies = [ 711 | "cfg-if", 712 | "libc", 713 | "wasi 0.11.1+wasi-snapshot-preview1", 714 | ] 715 | 716 | [[package]] 717 | name = "getrandom" 718 | version = "0.3.3" 719 | source = "registry+https://github.com/rust-lang/crates.io-index" 720 | checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" 721 | dependencies = [ 722 | "cfg-if", 723 | "libc", 724 | "r-efi", 725 | "wasi 0.14.7+wasi-0.2.4", 726 | ] 727 | 728 | [[package]] 729 | name = "gimli" 730 | version = "0.31.1" 731 | source = "registry+https://github.com/rust-lang/crates.io-index" 732 | checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" 733 | 734 | [[package]] 735 | name = "glob" 736 | version = "0.3.3" 737 | source = "registry+https://github.com/rust-lang/crates.io-index" 738 | checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280" 739 | 740 | [[package]] 741 | name = "h2" 742 | version = "0.4.12" 743 | source = "registry+https://github.com/rust-lang/crates.io-index" 744 | checksum = "f3c0b69cfcb4e1b9f1bf2f53f95f766e4661169728ec61cd3fe5a0166f2d1386" 745 | dependencies = [ 746 | "atomic-waker", 747 | "bytes", 748 | "fnv", 749 | "futures-core", 750 | "futures-sink", 751 | "http", 752 | "indexmap", 753 | "slab", 754 | "tokio", 755 | "tokio-util", 756 | "tracing", 757 | ] 758 | 759 | [[package]] 760 | name = "hashbrown" 761 | version = "0.14.5" 762 | source = "registry+https://github.com/rust-lang/crates.io-index" 763 | checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" 764 | 765 | [[package]] 766 | name = "hashbrown" 767 | version = "0.15.5" 768 | source = "registry+https://github.com/rust-lang/crates.io-index" 769 | checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" 770 | dependencies = [ 771 | "foldhash", 772 | ] 773 | 774 | [[package]] 775 | name = "hashbrown" 776 | version = "0.16.0" 777 | source = "registry+https://github.com/rust-lang/crates.io-index" 778 | checksum = "5419bdc4f6a9207fbeba6d11b604d481addf78ecd10c11ad51e76c2f6482748d" 779 | 780 | [[package]] 781 | name = "hashlink" 782 | version = "0.10.0" 783 | source = "registry+https://github.com/rust-lang/crates.io-index" 784 | checksum = "7382cf6263419f2d8df38c55d7da83da5c18aef87fc7a7fc1fb1e344edfe14c1" 785 | dependencies = [ 786 | "hashbrown 0.15.5", 787 | ] 788 | 789 | [[package]] 790 | name = "heck" 791 | version = "0.5.0" 792 | source = "registry+https://github.com/rust-lang/crates.io-index" 793 | checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" 794 | 795 | [[package]] 796 | name = "hex" 797 | version = "0.4.3" 798 | source = "registry+https://github.com/rust-lang/crates.io-index" 799 | checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" 800 | 801 | [[package]] 802 | name = "hmac" 803 | version = "0.12.1" 804 | source = "registry+https://github.com/rust-lang/crates.io-index" 805 | checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" 806 | dependencies = [ 807 | "digest", 808 | ] 809 | 810 | [[package]] 811 | name = "home" 812 | version = "0.5.11" 813 | source = "registry+https://github.com/rust-lang/crates.io-index" 814 | checksum = "589533453244b0995c858700322199b2becb13b627df2851f64a2775d024abcf" 815 | dependencies = [ 816 | "windows-sys 0.59.0", 817 | ] 818 | 819 | [[package]] 820 | name = "http" 821 | version = "1.3.1" 822 | source = "registry+https://github.com/rust-lang/crates.io-index" 823 | checksum = "f4a85d31aea989eead29a3aaf9e1115a180df8282431156e533de47660892565" 824 | dependencies = [ 825 | "bytes", 826 | "fnv", 827 | "itoa", 828 | ] 829 | 830 | [[package]] 831 | name = "http-body" 832 | version = "1.0.1" 833 | source = "registry+https://github.com/rust-lang/crates.io-index" 834 | checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" 835 | dependencies = [ 836 | "bytes", 837 | "http", 838 | ] 839 | 840 | [[package]] 841 | name = "http-body-util" 842 | version = "0.1.3" 843 | source = "registry+https://github.com/rust-lang/crates.io-index" 844 | checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" 845 | dependencies = [ 846 | "bytes", 847 | "futures-core", 848 | "http", 849 | "http-body", 850 | "pin-project-lite", 851 | ] 852 | 853 | [[package]] 854 | name = "httparse" 855 | version = "1.10.1" 856 | source = "registry+https://github.com/rust-lang/crates.io-index" 857 | checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" 858 | 859 | [[package]] 860 | name = "humansize" 861 | version = "2.1.3" 862 | source = "registry+https://github.com/rust-lang/crates.io-index" 863 | checksum = "6cb51c9a029ddc91b07a787f1d86b53ccfa49b0e86688c946ebe8d3555685dd7" 864 | dependencies = [ 865 | "libm", 866 | ] 867 | 868 | [[package]] 869 | name = "hyper" 870 | version = "1.7.0" 871 | source = "registry+https://github.com/rust-lang/crates.io-index" 872 | checksum = "eb3aa54a13a0dfe7fbe3a59e0c76093041720fdc77b110cc0fc260fafb4dc51e" 873 | dependencies = [ 874 | "atomic-waker", 875 | "bytes", 876 | "futures-channel", 877 | "futures-core", 878 | "h2", 879 | "http", 880 | "http-body", 881 | "httparse", 882 | "itoa", 883 | "pin-project-lite", 884 | "pin-utils", 885 | "smallvec", 886 | "tokio", 887 | "want", 888 | ] 889 | 890 | [[package]] 891 | name = "hyper-rustls" 892 | version = "0.27.7" 893 | source = "registry+https://github.com/rust-lang/crates.io-index" 894 | checksum = "e3c93eb611681b207e1fe55d5a71ecf91572ec8a6705cdb6857f7d8d5242cf58" 895 | dependencies = [ 896 | "http", 897 | "hyper", 898 | "hyper-util", 899 | "rustls", 900 | "rustls-pki-types", 901 | "tokio", 902 | "tokio-rustls", 903 | "tower-service", 904 | ] 905 | 906 | [[package]] 907 | name = "hyper-tls" 908 | version = "0.6.0" 909 | source = "registry+https://github.com/rust-lang/crates.io-index" 910 | checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" 911 | dependencies = [ 912 | "bytes", 913 | "http-body-util", 914 | "hyper", 915 | "hyper-util", 916 | "native-tls", 917 | "tokio", 918 | "tokio-native-tls", 919 | "tower-service", 920 | ] 921 | 922 | [[package]] 923 | name = "hyper-util" 924 | version = "0.1.17" 925 | source = "registry+https://github.com/rust-lang/crates.io-index" 926 | checksum = "3c6995591a8f1380fcb4ba966a252a4b29188d51d2b89e3a252f5305be65aea8" 927 | dependencies = [ 928 | "base64 0.22.1", 929 | "bytes", 930 | "futures-channel", 931 | "futures-core", 932 | "futures-util", 933 | "http", 934 | "http-body", 935 | "hyper", 936 | "ipnet", 937 | "libc", 938 | "percent-encoding", 939 | "pin-project-lite", 940 | "socket2", 941 | "system-configuration", 942 | "tokio", 943 | "tower-service", 944 | "tracing", 945 | "windows-registry", 946 | ] 947 | 948 | [[package]] 949 | name = "iana-time-zone" 950 | version = "0.1.64" 951 | source = "registry+https://github.com/rust-lang/crates.io-index" 952 | checksum = "33e57f83510bb73707521ebaffa789ec8caf86f9657cad665b092b581d40e9fb" 953 | dependencies = [ 954 | "android_system_properties", 955 | "core-foundation-sys", 956 | "iana-time-zone-haiku", 957 | "js-sys", 958 | "log", 959 | "wasm-bindgen", 960 | "windows-core 0.62.0", 961 | ] 962 | 963 | [[package]] 964 | name = "iana-time-zone-haiku" 965 | version = "0.1.2" 966 | source = "registry+https://github.com/rust-lang/crates.io-index" 967 | checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" 968 | dependencies = [ 969 | "cc", 970 | ] 971 | 972 | [[package]] 973 | name = "icu_collections" 974 | version = "2.0.0" 975 | source = "registry+https://github.com/rust-lang/crates.io-index" 976 | checksum = "200072f5d0e3614556f94a9930d5dc3e0662a652823904c3a75dc3b0af7fee47" 977 | dependencies = [ 978 | "displaydoc", 979 | "potential_utf", 980 | "yoke", 981 | "zerofrom", 982 | "zerovec", 983 | ] 984 | 985 | [[package]] 986 | name = "icu_locale_core" 987 | version = "2.0.0" 988 | source = "registry+https://github.com/rust-lang/crates.io-index" 989 | checksum = "0cde2700ccaed3872079a65fb1a78f6c0a36c91570f28755dda67bc8f7d9f00a" 990 | dependencies = [ 991 | "displaydoc", 992 | "litemap", 993 | "tinystr", 994 | "writeable", 995 | "zerovec", 996 | ] 997 | 998 | [[package]] 999 | name = "icu_normalizer" 1000 | version = "2.0.0" 1001 | source = "registry+https://github.com/rust-lang/crates.io-index" 1002 | checksum = "436880e8e18df4d7bbc06d58432329d6458cc84531f7ac5f024e93deadb37979" 1003 | dependencies = [ 1004 | "displaydoc", 1005 | "icu_collections", 1006 | "icu_normalizer_data", 1007 | "icu_properties", 1008 | "icu_provider", 1009 | "smallvec", 1010 | "zerovec", 1011 | ] 1012 | 1013 | [[package]] 1014 | name = "icu_normalizer_data" 1015 | version = "2.0.0" 1016 | source = "registry+https://github.com/rust-lang/crates.io-index" 1017 | checksum = "00210d6893afc98edb752b664b8890f0ef174c8adbb8d0be9710fa66fbbf72d3" 1018 | 1019 | [[package]] 1020 | name = "icu_properties" 1021 | version = "2.0.1" 1022 | source = "registry+https://github.com/rust-lang/crates.io-index" 1023 | checksum = "016c619c1eeb94efb86809b015c58f479963de65bdb6253345c1a1276f22e32b" 1024 | dependencies = [ 1025 | "displaydoc", 1026 | "icu_collections", 1027 | "icu_locale_core", 1028 | "icu_properties_data", 1029 | "icu_provider", 1030 | "potential_utf", 1031 | "zerotrie", 1032 | "zerovec", 1033 | ] 1034 | 1035 | [[package]] 1036 | name = "icu_properties_data" 1037 | version = "2.0.1" 1038 | source = "registry+https://github.com/rust-lang/crates.io-index" 1039 | checksum = "298459143998310acd25ffe6810ed544932242d3f07083eee1084d83a71bd632" 1040 | 1041 | [[package]] 1042 | name = "icu_provider" 1043 | version = "2.0.0" 1044 | source = "registry+https://github.com/rust-lang/crates.io-index" 1045 | checksum = "03c80da27b5f4187909049ee2d72f276f0d9f99a42c306bd0131ecfe04d8e5af" 1046 | dependencies = [ 1047 | "displaydoc", 1048 | "icu_locale_core", 1049 | "stable_deref_trait", 1050 | "tinystr", 1051 | "writeable", 1052 | "yoke", 1053 | "zerofrom", 1054 | "zerotrie", 1055 | "zerovec", 1056 | ] 1057 | 1058 | [[package]] 1059 | name = "idna" 1060 | version = "1.1.0" 1061 | source = "registry+https://github.com/rust-lang/crates.io-index" 1062 | checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de" 1063 | dependencies = [ 1064 | "idna_adapter", 1065 | "smallvec", 1066 | "utf8_iter", 1067 | ] 1068 | 1069 | [[package]] 1070 | name = "idna_adapter" 1071 | version = "1.2.1" 1072 | source = "registry+https://github.com/rust-lang/crates.io-index" 1073 | checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344" 1074 | dependencies = [ 1075 | "icu_normalizer", 1076 | "icu_properties", 1077 | ] 1078 | 1079 | [[package]] 1080 | name = "indexmap" 1081 | version = "2.11.4" 1082 | source = "registry+https://github.com/rust-lang/crates.io-index" 1083 | checksum = "4b0f83760fb341a774ed326568e19f5a863af4a952def8c39f9ab92fd95b88e5" 1084 | dependencies = [ 1085 | "equivalent", 1086 | "hashbrown 0.16.0", 1087 | ] 1088 | 1089 | [[package]] 1090 | name = "io-uring" 1091 | version = "0.7.10" 1092 | source = "registry+https://github.com/rust-lang/crates.io-index" 1093 | checksum = "046fa2d4d00aea763528b4950358d0ead425372445dc8ff86312b3c69ff7727b" 1094 | dependencies = [ 1095 | "bitflags", 1096 | "cfg-if", 1097 | "libc", 1098 | ] 1099 | 1100 | [[package]] 1101 | name = "ipnet" 1102 | version = "2.11.0" 1103 | source = "registry+https://github.com/rust-lang/crates.io-index" 1104 | checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" 1105 | 1106 | [[package]] 1107 | name = "iri-string" 1108 | version = "0.7.8" 1109 | source = "registry+https://github.com/rust-lang/crates.io-index" 1110 | checksum = "dbc5ebe9c3a1a7a5127f920a418f7585e9e758e911d0466ed004f393b0e380b2" 1111 | dependencies = [ 1112 | "memchr", 1113 | "serde", 1114 | ] 1115 | 1116 | [[package]] 1117 | name = "is_terminal_polyfill" 1118 | version = "1.70.1" 1119 | source = "registry+https://github.com/rust-lang/crates.io-index" 1120 | checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" 1121 | 1122 | [[package]] 1123 | name = "itoa" 1124 | version = "1.0.15" 1125 | source = "registry+https://github.com/rust-lang/crates.io-index" 1126 | checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" 1127 | 1128 | [[package]] 1129 | name = "js-sys" 1130 | version = "0.3.80" 1131 | source = "registry+https://github.com/rust-lang/crates.io-index" 1132 | checksum = "852f13bec5eba4ba9afbeb93fd7c13fe56147f055939ae21c43a29a0ecb2702e" 1133 | dependencies = [ 1134 | "once_cell", 1135 | "wasm-bindgen", 1136 | ] 1137 | 1138 | [[package]] 1139 | name = "json5" 1140 | version = "0.4.1" 1141 | source = "registry+https://github.com/rust-lang/crates.io-index" 1142 | checksum = "96b0db21af676c1ce64250b5f40f3ce2cf27e4e47cb91ed91eb6fe9350b430c1" 1143 | dependencies = [ 1144 | "pest", 1145 | "pest_derive", 1146 | "serde", 1147 | ] 1148 | 1149 | [[package]] 1150 | name = "lazy_static" 1151 | version = "1.5.0" 1152 | source = "registry+https://github.com/rust-lang/crates.io-index" 1153 | checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" 1154 | 1155 | [[package]] 1156 | name = "libc" 1157 | version = "0.2.175" 1158 | source = "registry+https://github.com/rust-lang/crates.io-index" 1159 | checksum = "6a82ae493e598baaea5209805c49bbf2ea7de956d50d7da0da1164f9c6d28543" 1160 | 1161 | [[package]] 1162 | name = "libm" 1163 | version = "0.2.15" 1164 | source = "registry+https://github.com/rust-lang/crates.io-index" 1165 | checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de" 1166 | 1167 | [[package]] 1168 | name = "libredox" 1169 | version = "0.1.10" 1170 | source = "registry+https://github.com/rust-lang/crates.io-index" 1171 | checksum = "416f7e718bdb06000964960ffa43b4335ad4012ae8b99060261aa4a8088d5ccb" 1172 | dependencies = [ 1173 | "bitflags", 1174 | "libc", 1175 | ] 1176 | 1177 | [[package]] 1178 | name = "linux-raw-sys" 1179 | version = "0.11.0" 1180 | source = "registry+https://github.com/rust-lang/crates.io-index" 1181 | checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039" 1182 | 1183 | [[package]] 1184 | name = "litemap" 1185 | version = "0.8.0" 1186 | source = "registry+https://github.com/rust-lang/crates.io-index" 1187 | checksum = "241eaef5fd12c88705a01fc1066c48c4b36e0dd4377dcdc7ec3942cea7a69956" 1188 | 1189 | [[package]] 1190 | name = "lock_api" 1191 | version = "0.4.13" 1192 | source = "registry+https://github.com/rust-lang/crates.io-index" 1193 | checksum = "96936507f153605bddfcda068dd804796c84324ed2510809e5b2a624c81da765" 1194 | dependencies = [ 1195 | "autocfg", 1196 | "scopeguard", 1197 | ] 1198 | 1199 | [[package]] 1200 | name = "log" 1201 | version = "0.4.28" 1202 | source = "registry+https://github.com/rust-lang/crates.io-index" 1203 | checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432" 1204 | 1205 | [[package]] 1206 | name = "maybe-async" 1207 | version = "0.2.10" 1208 | source = "registry+https://github.com/rust-lang/crates.io-index" 1209 | checksum = "5cf92c10c7e361d6b99666ec1c6f9805b0bea2c3bd8c78dc6fe98ac5bd78db11" 1210 | dependencies = [ 1211 | "proc-macro2", 1212 | "quote", 1213 | "syn", 1214 | ] 1215 | 1216 | [[package]] 1217 | name = "md5" 1218 | version = "0.7.0" 1219 | source = "registry+https://github.com/rust-lang/crates.io-index" 1220 | checksum = "490cc448043f947bae3cbee9c203358d62dbee0db12107a74be5c30ccfd09771" 1221 | 1222 | [[package]] 1223 | name = "md5" 1224 | version = "0.8.0" 1225 | source = "registry+https://github.com/rust-lang/crates.io-index" 1226 | checksum = "ae960838283323069879657ca3de837e9f7bbb4c7bf6ea7f1b290d5e9476d2e0" 1227 | 1228 | [[package]] 1229 | name = "memchr" 1230 | version = "2.7.5" 1231 | source = "registry+https://github.com/rust-lang/crates.io-index" 1232 | checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0" 1233 | 1234 | [[package]] 1235 | name = "mime" 1236 | version = "0.3.17" 1237 | source = "registry+https://github.com/rust-lang/crates.io-index" 1238 | checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" 1239 | 1240 | [[package]] 1241 | name = "minidom" 1242 | version = "0.16.0" 1243 | source = "registry+https://github.com/rust-lang/crates.io-index" 1244 | checksum = "e394a0e3c7ccc2daea3dffabe82f09857b6b510cb25af87d54bf3e910ac1642d" 1245 | dependencies = [ 1246 | "rxml", 1247 | ] 1248 | 1249 | [[package]] 1250 | name = "miniz_oxide" 1251 | version = "0.8.9" 1252 | source = "registry+https://github.com/rust-lang/crates.io-index" 1253 | checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" 1254 | dependencies = [ 1255 | "adler2", 1256 | ] 1257 | 1258 | [[package]] 1259 | name = "mio" 1260 | version = "1.0.4" 1261 | source = "registry+https://github.com/rust-lang/crates.io-index" 1262 | checksum = "78bed444cc8a2160f01cbcf811ef18cac863ad68ae8ca62092e8db51d51c761c" 1263 | dependencies = [ 1264 | "libc", 1265 | "wasi 0.11.1+wasi-snapshot-preview1", 1266 | "windows-sys 0.59.0", 1267 | ] 1268 | 1269 | [[package]] 1270 | name = "native-tls" 1271 | version = "0.2.14" 1272 | source = "registry+https://github.com/rust-lang/crates.io-index" 1273 | checksum = "87de3442987e9dbec73158d5c715e7ad9072fda936bb03d19d7fa10e00520f0e" 1274 | dependencies = [ 1275 | "libc", 1276 | "log", 1277 | "openssl", 1278 | "openssl-probe", 1279 | "openssl-sys", 1280 | "schannel", 1281 | "security-framework", 1282 | "security-framework-sys", 1283 | "tempfile", 1284 | ] 1285 | 1286 | [[package]] 1287 | name = "ntapi" 1288 | version = "0.4.1" 1289 | source = "registry+https://github.com/rust-lang/crates.io-index" 1290 | checksum = "e8a3895c6391c39d7fe7ebc444a87eb2991b2a0bc718fdabd071eec617fc68e4" 1291 | dependencies = [ 1292 | "winapi", 1293 | ] 1294 | 1295 | [[package]] 1296 | name = "nu-ansi-term" 1297 | version = "0.50.1" 1298 | source = "registry+https://github.com/rust-lang/crates.io-index" 1299 | checksum = "d4a28e057d01f97e61255210fcff094d74ed0466038633e95017f5beb68e4399" 1300 | dependencies = [ 1301 | "windows-sys 0.52.0", 1302 | ] 1303 | 1304 | [[package]] 1305 | name = "num-conv" 1306 | version = "0.1.0" 1307 | source = "registry+https://github.com/rust-lang/crates.io-index" 1308 | checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" 1309 | 1310 | [[package]] 1311 | name = "num-traits" 1312 | version = "0.2.19" 1313 | source = "registry+https://github.com/rust-lang/crates.io-index" 1314 | checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" 1315 | dependencies = [ 1316 | "autocfg", 1317 | ] 1318 | 1319 | [[package]] 1320 | name = "objc2-core-foundation" 1321 | version = "0.3.1" 1322 | source = "registry+https://github.com/rust-lang/crates.io-index" 1323 | checksum = "1c10c2894a6fed806ade6027bcd50662746363a9589d3ec9d9bef30a4e4bc166" 1324 | dependencies = [ 1325 | "bitflags", 1326 | ] 1327 | 1328 | [[package]] 1329 | name = "objc2-io-kit" 1330 | version = "0.3.1" 1331 | source = "registry+https://github.com/rust-lang/crates.io-index" 1332 | checksum = "71c1c64d6120e51cd86033f67176b1cb66780c2efe34dec55176f77befd93c0a" 1333 | dependencies = [ 1334 | "libc", 1335 | "objc2-core-foundation", 1336 | ] 1337 | 1338 | [[package]] 1339 | name = "object" 1340 | version = "0.36.7" 1341 | source = "registry+https://github.com/rust-lang/crates.io-index" 1342 | checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" 1343 | dependencies = [ 1344 | "memchr", 1345 | ] 1346 | 1347 | [[package]] 1348 | name = "once_cell" 1349 | version = "1.21.3" 1350 | source = "registry+https://github.com/rust-lang/crates.io-index" 1351 | checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" 1352 | 1353 | [[package]] 1354 | name = "once_cell_polyfill" 1355 | version = "1.70.1" 1356 | source = "registry+https://github.com/rust-lang/crates.io-index" 1357 | checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad" 1358 | 1359 | [[package]] 1360 | name = "openssl" 1361 | version = "0.10.73" 1362 | source = "registry+https://github.com/rust-lang/crates.io-index" 1363 | checksum = "8505734d46c8ab1e19a1dce3aef597ad87dcb4c37e7188231769bd6bd51cebf8" 1364 | dependencies = [ 1365 | "bitflags", 1366 | "cfg-if", 1367 | "foreign-types", 1368 | "libc", 1369 | "once_cell", 1370 | "openssl-macros", 1371 | "openssl-sys", 1372 | ] 1373 | 1374 | [[package]] 1375 | name = "openssl-macros" 1376 | version = "0.1.1" 1377 | source = "registry+https://github.com/rust-lang/crates.io-index" 1378 | checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" 1379 | dependencies = [ 1380 | "proc-macro2", 1381 | "quote", 1382 | "syn", 1383 | ] 1384 | 1385 | [[package]] 1386 | name = "openssl-probe" 1387 | version = "0.1.6" 1388 | source = "registry+https://github.com/rust-lang/crates.io-index" 1389 | checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" 1390 | 1391 | [[package]] 1392 | name = "openssl-sys" 1393 | version = "0.9.109" 1394 | source = "registry+https://github.com/rust-lang/crates.io-index" 1395 | checksum = "90096e2e47630d78b7d1c20952dc621f957103f8bc2c8359ec81290d75238571" 1396 | dependencies = [ 1397 | "cc", 1398 | "libc", 1399 | "pkg-config", 1400 | "vcpkg", 1401 | ] 1402 | 1403 | [[package]] 1404 | name = "option-ext" 1405 | version = "0.2.0" 1406 | source = "registry+https://github.com/rust-lang/crates.io-index" 1407 | checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" 1408 | 1409 | [[package]] 1410 | name = "ordered-multimap" 1411 | version = "0.7.3" 1412 | source = "registry+https://github.com/rust-lang/crates.io-index" 1413 | checksum = "49203cdcae0030493bad186b28da2fa25645fa276a51b6fec8010d281e02ef79" 1414 | dependencies = [ 1415 | "dlv-list", 1416 | "hashbrown 0.14.5", 1417 | ] 1418 | 1419 | [[package]] 1420 | name = "papergrid" 1421 | version = "0.17.0" 1422 | source = "registry+https://github.com/rust-lang/crates.io-index" 1423 | checksum = "6978128c8b51d8f4080631ceb2302ab51e32cc6e8615f735ee2f83fd269ae3f1" 1424 | dependencies = [ 1425 | "bytecount", 1426 | "fnv", 1427 | "unicode-width", 1428 | ] 1429 | 1430 | [[package]] 1431 | name = "parking_lot" 1432 | version = "0.12.4" 1433 | source = "registry+https://github.com/rust-lang/crates.io-index" 1434 | checksum = "70d58bf43669b5795d1576d0641cfb6fbb2057bf629506267a92807158584a13" 1435 | dependencies = [ 1436 | "lock_api", 1437 | "parking_lot_core", 1438 | ] 1439 | 1440 | [[package]] 1441 | name = "parking_lot_core" 1442 | version = "0.9.11" 1443 | source = "registry+https://github.com/rust-lang/crates.io-index" 1444 | checksum = "bc838d2a56b5b1a6c25f55575dfc605fabb63bb2365f6c2353ef9159aa69e4a5" 1445 | dependencies = [ 1446 | "cfg-if", 1447 | "libc", 1448 | "redox_syscall", 1449 | "smallvec", 1450 | "windows-targets 0.52.6", 1451 | ] 1452 | 1453 | [[package]] 1454 | name = "pathdiff" 1455 | version = "0.2.3" 1456 | source = "registry+https://github.com/rust-lang/crates.io-index" 1457 | checksum = "df94ce210e5bc13cb6651479fa48d14f601d9858cfe0467f43ae157023b938d3" 1458 | 1459 | [[package]] 1460 | name = "percent-encoding" 1461 | version = "2.3.2" 1462 | source = "registry+https://github.com/rust-lang/crates.io-index" 1463 | checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" 1464 | 1465 | [[package]] 1466 | name = "pest" 1467 | version = "2.8.2" 1468 | source = "registry+https://github.com/rust-lang/crates.io-index" 1469 | checksum = "21e0a3a33733faeaf8651dfee72dd0f388f0c8e5ad496a3478fa5a922f49cfa8" 1470 | dependencies = [ 1471 | "memchr", 1472 | "thiserror 2.0.16", 1473 | "ucd-trie", 1474 | ] 1475 | 1476 | [[package]] 1477 | name = "pest_derive" 1478 | version = "2.8.2" 1479 | source = "registry+https://github.com/rust-lang/crates.io-index" 1480 | checksum = "bc58706f770acb1dbd0973e6530a3cff4746fb721207feb3a8a6064cd0b6c663" 1481 | dependencies = [ 1482 | "pest", 1483 | "pest_generator", 1484 | ] 1485 | 1486 | [[package]] 1487 | name = "pest_generator" 1488 | version = "2.8.2" 1489 | source = "registry+https://github.com/rust-lang/crates.io-index" 1490 | checksum = "6d4f36811dfe07f7b8573462465d5cb8965fffc2e71ae377a33aecf14c2c9a2f" 1491 | dependencies = [ 1492 | "pest", 1493 | "pest_meta", 1494 | "proc-macro2", 1495 | "quote", 1496 | "syn", 1497 | ] 1498 | 1499 | [[package]] 1500 | name = "pest_meta" 1501 | version = "2.8.2" 1502 | source = "registry+https://github.com/rust-lang/crates.io-index" 1503 | checksum = "42919b05089acbd0a5dcd5405fb304d17d1053847b81163d09c4ad18ce8e8420" 1504 | dependencies = [ 1505 | "pest", 1506 | "sha2", 1507 | ] 1508 | 1509 | [[package]] 1510 | name = "pin-project-lite" 1511 | version = "0.2.16" 1512 | source = "registry+https://github.com/rust-lang/crates.io-index" 1513 | checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" 1514 | 1515 | [[package]] 1516 | name = "pin-utils" 1517 | version = "0.1.0" 1518 | source = "registry+https://github.com/rust-lang/crates.io-index" 1519 | checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" 1520 | 1521 | [[package]] 1522 | name = "pkg-config" 1523 | version = "0.3.32" 1524 | source = "registry+https://github.com/rust-lang/crates.io-index" 1525 | checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" 1526 | 1527 | [[package]] 1528 | name = "potential_utf" 1529 | version = "0.1.3" 1530 | source = "registry+https://github.com/rust-lang/crates.io-index" 1531 | checksum = "84df19adbe5b5a0782edcab45899906947ab039ccf4573713735ee7de1e6b08a" 1532 | dependencies = [ 1533 | "zerovec", 1534 | ] 1535 | 1536 | [[package]] 1537 | name = "powerfmt" 1538 | version = "0.2.0" 1539 | source = "registry+https://github.com/rust-lang/crates.io-index" 1540 | checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" 1541 | 1542 | [[package]] 1543 | name = "ppv-lite86" 1544 | version = "0.2.21" 1545 | source = "registry+https://github.com/rust-lang/crates.io-index" 1546 | checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" 1547 | dependencies = [ 1548 | "zerocopy", 1549 | ] 1550 | 1551 | [[package]] 1552 | name = "proc-macro-error-attr2" 1553 | version = "2.0.0" 1554 | source = "registry+https://github.com/rust-lang/crates.io-index" 1555 | checksum = "96de42df36bb9bba5542fe9f1a054b8cc87e172759a1868aa05c1f3acc89dfc5" 1556 | dependencies = [ 1557 | "proc-macro2", 1558 | "quote", 1559 | ] 1560 | 1561 | [[package]] 1562 | name = "proc-macro-error2" 1563 | version = "2.0.1" 1564 | source = "registry+https://github.com/rust-lang/crates.io-index" 1565 | checksum = "11ec05c52be0a07b08061f7dd003e7d7092e0472bc731b4af7bb1ef876109802" 1566 | dependencies = [ 1567 | "proc-macro-error-attr2", 1568 | "proc-macro2", 1569 | "quote", 1570 | "syn", 1571 | ] 1572 | 1573 | [[package]] 1574 | name = "proc-macro2" 1575 | version = "1.0.101" 1576 | source = "registry+https://github.com/rust-lang/crates.io-index" 1577 | checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de" 1578 | dependencies = [ 1579 | "unicode-ident", 1580 | ] 1581 | 1582 | [[package]] 1583 | name = "quick-xml" 1584 | version = "0.31.0" 1585 | source = "registry+https://github.com/rust-lang/crates.io-index" 1586 | checksum = "1004a344b30a54e2ee58d66a71b32d2db2feb0a31f9a2d302bf0536f15de2a33" 1587 | dependencies = [ 1588 | "memchr", 1589 | "serde", 1590 | ] 1591 | 1592 | [[package]] 1593 | name = "quick-xml" 1594 | version = "0.38.3" 1595 | source = "registry+https://github.com/rust-lang/crates.io-index" 1596 | checksum = "42a232e7487fc2ef313d96dde7948e7a3c05101870d8985e4fd8d26aedd27b89" 1597 | dependencies = [ 1598 | "memchr", 1599 | "serde", 1600 | ] 1601 | 1602 | [[package]] 1603 | name = "quote" 1604 | version = "1.0.40" 1605 | source = "registry+https://github.com/rust-lang/crates.io-index" 1606 | checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" 1607 | dependencies = [ 1608 | "proc-macro2", 1609 | ] 1610 | 1611 | [[package]] 1612 | name = "r-efi" 1613 | version = "5.3.0" 1614 | source = "registry+https://github.com/rust-lang/crates.io-index" 1615 | checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" 1616 | 1617 | [[package]] 1618 | name = "rand" 1619 | version = "0.8.5" 1620 | source = "registry+https://github.com/rust-lang/crates.io-index" 1621 | checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" 1622 | dependencies = [ 1623 | "libc", 1624 | "rand_chacha", 1625 | "rand_core", 1626 | ] 1627 | 1628 | [[package]] 1629 | name = "rand_chacha" 1630 | version = "0.3.1" 1631 | source = "registry+https://github.com/rust-lang/crates.io-index" 1632 | checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" 1633 | dependencies = [ 1634 | "ppv-lite86", 1635 | "rand_core", 1636 | ] 1637 | 1638 | [[package]] 1639 | name = "rand_core" 1640 | version = "0.6.4" 1641 | source = "registry+https://github.com/rust-lang/crates.io-index" 1642 | checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" 1643 | dependencies = [ 1644 | "getrandom 0.2.16", 1645 | ] 1646 | 1647 | [[package]] 1648 | name = "redox_syscall" 1649 | version = "0.5.17" 1650 | source = "registry+https://github.com/rust-lang/crates.io-index" 1651 | checksum = "5407465600fb0548f1442edf71dd20683c6ed326200ace4b1ef0763521bb3b77" 1652 | dependencies = [ 1653 | "bitflags", 1654 | ] 1655 | 1656 | [[package]] 1657 | name = "redox_users" 1658 | version = "0.5.2" 1659 | source = "registry+https://github.com/rust-lang/crates.io-index" 1660 | checksum = "a4e608c6638b9c18977b00b475ac1f28d14e84b27d8d42f70e0bf1e3dec127ac" 1661 | dependencies = [ 1662 | "getrandom 0.2.16", 1663 | "libredox", 1664 | "thiserror 2.0.16", 1665 | ] 1666 | 1667 | [[package]] 1668 | name = "reqwest" 1669 | version = "0.12.23" 1670 | source = "registry+https://github.com/rust-lang/crates.io-index" 1671 | checksum = "d429f34c8092b2d42c7c93cec323bb4adeb7c67698f70839adec842ec10c7ceb" 1672 | dependencies = [ 1673 | "base64 0.22.1", 1674 | "bytes", 1675 | "encoding_rs", 1676 | "futures-core", 1677 | "futures-util", 1678 | "h2", 1679 | "http", 1680 | "http-body", 1681 | "http-body-util", 1682 | "hyper", 1683 | "hyper-rustls", 1684 | "hyper-tls", 1685 | "hyper-util", 1686 | "js-sys", 1687 | "log", 1688 | "mime", 1689 | "native-tls", 1690 | "percent-encoding", 1691 | "pin-project-lite", 1692 | "rustls-pki-types", 1693 | "serde", 1694 | "serde_json", 1695 | "serde_urlencoded", 1696 | "sync_wrapper", 1697 | "tokio", 1698 | "tokio-native-tls", 1699 | "tokio-util", 1700 | "tower", 1701 | "tower-http", 1702 | "tower-service", 1703 | "url", 1704 | "wasm-bindgen", 1705 | "wasm-bindgen-futures", 1706 | "wasm-streams", 1707 | "web-sys", 1708 | ] 1709 | 1710 | [[package]] 1711 | name = "ring" 1712 | version = "0.17.14" 1713 | source = "registry+https://github.com/rust-lang/crates.io-index" 1714 | checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" 1715 | dependencies = [ 1716 | "cc", 1717 | "cfg-if", 1718 | "getrandom 0.2.16", 1719 | "libc", 1720 | "untrusted", 1721 | "windows-sys 0.52.0", 1722 | ] 1723 | 1724 | [[package]] 1725 | name = "ron" 1726 | version = "0.8.1" 1727 | source = "registry+https://github.com/rust-lang/crates.io-index" 1728 | checksum = "b91f7eff05f748767f183df4320a63d6936e9c6107d97c9e6bdd9784f4289c94" 1729 | dependencies = [ 1730 | "base64 0.21.7", 1731 | "bitflags", 1732 | "serde", 1733 | "serde_derive", 1734 | ] 1735 | 1736 | [[package]] 1737 | name = "rust-ini" 1738 | version = "0.21.3" 1739 | source = "registry+https://github.com/rust-lang/crates.io-index" 1740 | checksum = "796e8d2b6696392a43bea58116b667fb4c29727dc5abd27d6acf338bb4f688c7" 1741 | dependencies = [ 1742 | "cfg-if", 1743 | "ordered-multimap", 1744 | ] 1745 | 1746 | [[package]] 1747 | name = "rust-s3" 1748 | version = "0.37.0" 1749 | source = "registry+https://github.com/rust-lang/crates.io-index" 1750 | checksum = "94f9b973bd4097f5bb47e5827dcb9fb5dc17e93879e46badc27d2a4e9a4e5588" 1751 | dependencies = [ 1752 | "async-trait", 1753 | "aws-creds", 1754 | "aws-region", 1755 | "base64 0.22.1", 1756 | "bytes", 1757 | "cfg-if", 1758 | "futures-util", 1759 | "hex", 1760 | "hmac", 1761 | "http", 1762 | "log", 1763 | "maybe-async", 1764 | "md5 0.8.0", 1765 | "minidom", 1766 | "percent-encoding", 1767 | "quick-xml 0.38.3", 1768 | "reqwest", 1769 | "serde", 1770 | "serde_derive", 1771 | "serde_json", 1772 | "sha2", 1773 | "sysinfo", 1774 | "thiserror 2.0.16", 1775 | "time", 1776 | "tokio", 1777 | "tokio-stream", 1778 | "url", 1779 | ] 1780 | 1781 | [[package]] 1782 | name = "rustc-demangle" 1783 | version = "0.1.26" 1784 | source = "registry+https://github.com/rust-lang/crates.io-index" 1785 | checksum = "56f7d92ca342cea22a06f2121d944b4fd82af56988c270852495420f961d4ace" 1786 | 1787 | [[package]] 1788 | name = "rustix" 1789 | version = "1.1.2" 1790 | source = "registry+https://github.com/rust-lang/crates.io-index" 1791 | checksum = "cd15f8a2c5551a84d56efdc1cd049089e409ac19a3072d5037a17fd70719ff3e" 1792 | dependencies = [ 1793 | "bitflags", 1794 | "errno", 1795 | "libc", 1796 | "linux-raw-sys", 1797 | "windows-sys 0.61.0", 1798 | ] 1799 | 1800 | [[package]] 1801 | name = "rustls" 1802 | version = "0.23.32" 1803 | source = "registry+https://github.com/rust-lang/crates.io-index" 1804 | checksum = "cd3c25631629d034ce7cd9940adc9d45762d46de2b0f57193c4443b92c6d4d40" 1805 | dependencies = [ 1806 | "once_cell", 1807 | "rustls-pki-types", 1808 | "rustls-webpki", 1809 | "subtle", 1810 | "zeroize", 1811 | ] 1812 | 1813 | [[package]] 1814 | name = "rustls-pki-types" 1815 | version = "1.12.0" 1816 | source = "registry+https://github.com/rust-lang/crates.io-index" 1817 | checksum = "229a4a4c221013e7e1f1a043678c5cc39fe5171437c88fb47151a21e6f5b5c79" 1818 | dependencies = [ 1819 | "zeroize", 1820 | ] 1821 | 1822 | [[package]] 1823 | name = "rustls-webpki" 1824 | version = "0.103.6" 1825 | source = "registry+https://github.com/rust-lang/crates.io-index" 1826 | checksum = "8572f3c2cb9934231157b45499fc41e1f58c589fdfb81a844ba873265e80f8eb" 1827 | dependencies = [ 1828 | "ring", 1829 | "rustls-pki-types", 1830 | "untrusted", 1831 | ] 1832 | 1833 | [[package]] 1834 | name = "rustversion" 1835 | version = "1.0.22" 1836 | source = "registry+https://github.com/rust-lang/crates.io-index" 1837 | checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" 1838 | 1839 | [[package]] 1840 | name = "rxml" 1841 | version = "0.11.1" 1842 | source = "registry+https://github.com/rust-lang/crates.io-index" 1843 | checksum = "65bc94b580d0f5a6b7a2d604e597513d3c673154b52ddeccd1d5c32360d945ee" 1844 | dependencies = [ 1845 | "bytes", 1846 | "rxml_validation", 1847 | ] 1848 | 1849 | [[package]] 1850 | name = "rxml_validation" 1851 | version = "0.11.0" 1852 | source = "registry+https://github.com/rust-lang/crates.io-index" 1853 | checksum = "826e80413b9a35e9d33217b3dcac04cf95f6559d15944b93887a08be5496c4a4" 1854 | dependencies = [ 1855 | "compact_str", 1856 | ] 1857 | 1858 | [[package]] 1859 | name = "ryu" 1860 | version = "1.0.20" 1861 | source = "registry+https://github.com/rust-lang/crates.io-index" 1862 | checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" 1863 | 1864 | [[package]] 1865 | name = "schannel" 1866 | version = "0.1.28" 1867 | source = "registry+https://github.com/rust-lang/crates.io-index" 1868 | checksum = "891d81b926048e76efe18581bf793546b4c0eaf8448d72be8de2bbee5fd166e1" 1869 | dependencies = [ 1870 | "windows-sys 0.61.0", 1871 | ] 1872 | 1873 | [[package]] 1874 | name = "scopeguard" 1875 | version = "1.2.0" 1876 | source = "registry+https://github.com/rust-lang/crates.io-index" 1877 | checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" 1878 | 1879 | [[package]] 1880 | name = "security-framework" 1881 | version = "2.11.1" 1882 | source = "registry+https://github.com/rust-lang/crates.io-index" 1883 | checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" 1884 | dependencies = [ 1885 | "bitflags", 1886 | "core-foundation", 1887 | "core-foundation-sys", 1888 | "libc", 1889 | "security-framework-sys", 1890 | ] 1891 | 1892 | [[package]] 1893 | name = "security-framework-sys" 1894 | version = "2.15.0" 1895 | source = "registry+https://github.com/rust-lang/crates.io-index" 1896 | checksum = "cc1f0cbffaac4852523ce30d8bd3c5cdc873501d96ff467ca09b6767bb8cd5c0" 1897 | dependencies = [ 1898 | "core-foundation-sys", 1899 | "libc", 1900 | ] 1901 | 1902 | [[package]] 1903 | name = "serde" 1904 | version = "1.0.226" 1905 | source = "registry+https://github.com/rust-lang/crates.io-index" 1906 | checksum = "0dca6411025b24b60bfa7ec1fe1f8e710ac09782dca409ee8237ba74b51295fd" 1907 | dependencies = [ 1908 | "serde_core", 1909 | "serde_derive", 1910 | ] 1911 | 1912 | [[package]] 1913 | name = "serde-untagged" 1914 | version = "0.1.9" 1915 | source = "registry+https://github.com/rust-lang/crates.io-index" 1916 | checksum = "f9faf48a4a2d2693be24c6289dbe26552776eb7737074e6722891fadbe6c5058" 1917 | dependencies = [ 1918 | "erased-serde", 1919 | "serde", 1920 | "serde_core", 1921 | "typeid", 1922 | ] 1923 | 1924 | [[package]] 1925 | name = "serde_core" 1926 | version = "1.0.226" 1927 | source = "registry+https://github.com/rust-lang/crates.io-index" 1928 | checksum = "ba2ba63999edb9dac981fb34b3e5c0d111a69b0924e253ed29d83f7c99e966a4" 1929 | dependencies = [ 1930 | "serde_derive", 1931 | ] 1932 | 1933 | [[package]] 1934 | name = "serde_derive" 1935 | version = "1.0.226" 1936 | source = "registry+https://github.com/rust-lang/crates.io-index" 1937 | checksum = "8db53ae22f34573731bafa1db20f04027b2d25e02d8205921b569171699cdb33" 1938 | dependencies = [ 1939 | "proc-macro2", 1940 | "quote", 1941 | "syn", 1942 | ] 1943 | 1944 | [[package]] 1945 | name = "serde_json" 1946 | version = "1.0.145" 1947 | source = "registry+https://github.com/rust-lang/crates.io-index" 1948 | checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c" 1949 | dependencies = [ 1950 | "itoa", 1951 | "memchr", 1952 | "ryu", 1953 | "serde", 1954 | "serde_core", 1955 | ] 1956 | 1957 | [[package]] 1958 | name = "serde_spanned" 1959 | version = "1.0.2" 1960 | source = "registry+https://github.com/rust-lang/crates.io-index" 1961 | checksum = "5417783452c2be558477e104686f7de5dae53dba813c28435e0e70f82d9b04ee" 1962 | dependencies = [ 1963 | "serde_core", 1964 | ] 1965 | 1966 | [[package]] 1967 | name = "serde_urlencoded" 1968 | version = "0.7.1" 1969 | source = "registry+https://github.com/rust-lang/crates.io-index" 1970 | checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" 1971 | dependencies = [ 1972 | "form_urlencoded", 1973 | "itoa", 1974 | "ryu", 1975 | "serde", 1976 | ] 1977 | 1978 | [[package]] 1979 | name = "sha1" 1980 | version = "0.10.6" 1981 | source = "registry+https://github.com/rust-lang/crates.io-index" 1982 | checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" 1983 | dependencies = [ 1984 | "cfg-if", 1985 | "cpufeatures", 1986 | "digest", 1987 | ] 1988 | 1989 | [[package]] 1990 | name = "sha2" 1991 | version = "0.10.9" 1992 | source = "registry+https://github.com/rust-lang/crates.io-index" 1993 | checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" 1994 | dependencies = [ 1995 | "cfg-if", 1996 | "cpufeatures", 1997 | "digest", 1998 | ] 1999 | 2000 | [[package]] 2001 | name = "sharded-slab" 2002 | version = "0.1.7" 2003 | source = "registry+https://github.com/rust-lang/crates.io-index" 2004 | checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" 2005 | dependencies = [ 2006 | "lazy_static", 2007 | ] 2008 | 2009 | [[package]] 2010 | name = "shellexpand" 2011 | version = "3.1.1" 2012 | source = "registry+https://github.com/rust-lang/crates.io-index" 2013 | checksum = "8b1fdf65dd6331831494dd616b30351c38e96e45921a27745cf98490458b90bb" 2014 | dependencies = [ 2015 | "dirs", 2016 | ] 2017 | 2018 | [[package]] 2019 | name = "shlex" 2020 | version = "1.3.0" 2021 | source = "registry+https://github.com/rust-lang/crates.io-index" 2022 | checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" 2023 | 2024 | [[package]] 2025 | name = "signal-hook-registry" 2026 | version = "1.4.6" 2027 | source = "registry+https://github.com/rust-lang/crates.io-index" 2028 | checksum = "b2a4719bff48cee6b39d12c020eeb490953ad2443b7055bd0b21fca26bd8c28b" 2029 | dependencies = [ 2030 | "libc", 2031 | ] 2032 | 2033 | [[package]] 2034 | name = "slab" 2035 | version = "0.4.11" 2036 | source = "registry+https://github.com/rust-lang/crates.io-index" 2037 | checksum = "7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c90267589" 2038 | 2039 | [[package]] 2040 | name = "smallvec" 2041 | version = "1.15.1" 2042 | source = "registry+https://github.com/rust-lang/crates.io-index" 2043 | checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" 2044 | 2045 | [[package]] 2046 | name = "socket2" 2047 | version = "0.6.0" 2048 | source = "registry+https://github.com/rust-lang/crates.io-index" 2049 | checksum = "233504af464074f9d066d7b5416c5f9b894a5862a6506e306f7b816cdd6f1807" 2050 | dependencies = [ 2051 | "libc", 2052 | "windows-sys 0.59.0", 2053 | ] 2054 | 2055 | [[package]] 2056 | name = "stable_deref_trait" 2057 | version = "1.2.0" 2058 | source = "registry+https://github.com/rust-lang/crates.io-index" 2059 | checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" 2060 | 2061 | [[package]] 2062 | name = "static_assertions" 2063 | version = "1.1.0" 2064 | source = "registry+https://github.com/rust-lang/crates.io-index" 2065 | checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" 2066 | 2067 | [[package]] 2068 | name = "strsim" 2069 | version = "0.11.1" 2070 | source = "registry+https://github.com/rust-lang/crates.io-index" 2071 | checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" 2072 | 2073 | [[package]] 2074 | name = "subtle" 2075 | version = "2.6.1" 2076 | source = "registry+https://github.com/rust-lang/crates.io-index" 2077 | checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" 2078 | 2079 | [[package]] 2080 | name = "syn" 2081 | version = "2.0.106" 2082 | source = "registry+https://github.com/rust-lang/crates.io-index" 2083 | checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6" 2084 | dependencies = [ 2085 | "proc-macro2", 2086 | "quote", 2087 | "unicode-ident", 2088 | ] 2089 | 2090 | [[package]] 2091 | name = "sync_wrapper" 2092 | version = "1.0.2" 2093 | source = "registry+https://github.com/rust-lang/crates.io-index" 2094 | checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" 2095 | dependencies = [ 2096 | "futures-core", 2097 | ] 2098 | 2099 | [[package]] 2100 | name = "synstructure" 2101 | version = "0.13.2" 2102 | source = "registry+https://github.com/rust-lang/crates.io-index" 2103 | checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" 2104 | dependencies = [ 2105 | "proc-macro2", 2106 | "quote", 2107 | "syn", 2108 | ] 2109 | 2110 | [[package]] 2111 | name = "sysinfo" 2112 | version = "0.37.0" 2113 | source = "registry+https://github.com/rust-lang/crates.io-index" 2114 | checksum = "07cec4dc2d2e357ca1e610cfb07de2fa7a10fc3e9fe89f72545f3d244ea87753" 2115 | dependencies = [ 2116 | "libc", 2117 | "memchr", 2118 | "ntapi", 2119 | "objc2-core-foundation", 2120 | "objc2-io-kit", 2121 | "windows", 2122 | ] 2123 | 2124 | [[package]] 2125 | name = "system-configuration" 2126 | version = "0.6.1" 2127 | source = "registry+https://github.com/rust-lang/crates.io-index" 2128 | checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" 2129 | dependencies = [ 2130 | "bitflags", 2131 | "core-foundation", 2132 | "system-configuration-sys", 2133 | ] 2134 | 2135 | [[package]] 2136 | name = "system-configuration-sys" 2137 | version = "0.6.0" 2138 | source = "registry+https://github.com/rust-lang/crates.io-index" 2139 | checksum = "8e1d1b10ced5ca923a1fcb8d03e96b8d3268065d724548c0211415ff6ac6bac4" 2140 | dependencies = [ 2141 | "core-foundation-sys", 2142 | "libc", 2143 | ] 2144 | 2145 | [[package]] 2146 | name = "tabled" 2147 | version = "0.20.0" 2148 | source = "registry+https://github.com/rust-lang/crates.io-index" 2149 | checksum = "e39a2ee1fbcd360805a771e1b300f78cc88fec7b8d3e2f71cd37bbf23e725c7d" 2150 | dependencies = [ 2151 | "papergrid", 2152 | "tabled_derive", 2153 | "testing_table", 2154 | ] 2155 | 2156 | [[package]] 2157 | name = "tabled_derive" 2158 | version = "0.11.0" 2159 | source = "registry+https://github.com/rust-lang/crates.io-index" 2160 | checksum = "0ea5d1b13ca6cff1f9231ffd62f15eefd72543dab5e468735f1a456728a02846" 2161 | dependencies = [ 2162 | "heck", 2163 | "proc-macro-error2", 2164 | "proc-macro2", 2165 | "quote", 2166 | "syn", 2167 | ] 2168 | 2169 | [[package]] 2170 | name = "tempfile" 2171 | version = "3.22.0" 2172 | source = "registry+https://github.com/rust-lang/crates.io-index" 2173 | checksum = "84fa4d11fadde498443cca10fd3ac23c951f0dc59e080e9f4b93d4df4e4eea53" 2174 | dependencies = [ 2175 | "fastrand", 2176 | "getrandom 0.3.3", 2177 | "once_cell", 2178 | "rustix", 2179 | "windows-sys 0.61.0", 2180 | ] 2181 | 2182 | [[package]] 2183 | name = "testing_table" 2184 | version = "0.3.0" 2185 | source = "registry+https://github.com/rust-lang/crates.io-index" 2186 | checksum = "0f8daae29995a24f65619e19d8d31dea5b389f3d853d8bf297bbf607cd0014cc" 2187 | dependencies = [ 2188 | "unicode-width", 2189 | ] 2190 | 2191 | [[package]] 2192 | name = "thiserror" 2193 | version = "1.0.69" 2194 | source = "registry+https://github.com/rust-lang/crates.io-index" 2195 | checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" 2196 | dependencies = [ 2197 | "thiserror-impl 1.0.69", 2198 | ] 2199 | 2200 | [[package]] 2201 | name = "thiserror" 2202 | version = "2.0.16" 2203 | source = "registry+https://github.com/rust-lang/crates.io-index" 2204 | checksum = "3467d614147380f2e4e374161426ff399c91084acd2363eaf549172b3d5e60c0" 2205 | dependencies = [ 2206 | "thiserror-impl 2.0.16", 2207 | ] 2208 | 2209 | [[package]] 2210 | name = "thiserror-impl" 2211 | version = "1.0.69" 2212 | source = "registry+https://github.com/rust-lang/crates.io-index" 2213 | checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" 2214 | dependencies = [ 2215 | "proc-macro2", 2216 | "quote", 2217 | "syn", 2218 | ] 2219 | 2220 | [[package]] 2221 | name = "thiserror-impl" 2222 | version = "2.0.16" 2223 | source = "registry+https://github.com/rust-lang/crates.io-index" 2224 | checksum = "6c5e1be1c48b9172ee610da68fd9cd2770e7a4056cb3fc98710ee6906f0c7960" 2225 | dependencies = [ 2226 | "proc-macro2", 2227 | "quote", 2228 | "syn", 2229 | ] 2230 | 2231 | [[package]] 2232 | name = "thread_local" 2233 | version = "1.1.9" 2234 | source = "registry+https://github.com/rust-lang/crates.io-index" 2235 | checksum = "f60246a4944f24f6e018aa17cdeffb7818b76356965d03b07d6a9886e8962185" 2236 | dependencies = [ 2237 | "cfg-if", 2238 | ] 2239 | 2240 | [[package]] 2241 | name = "time" 2242 | version = "0.3.44" 2243 | source = "registry+https://github.com/rust-lang/crates.io-index" 2244 | checksum = "91e7d9e3bb61134e77bde20dd4825b97c010155709965fedf0f49bb138e52a9d" 2245 | dependencies = [ 2246 | "deranged", 2247 | "itoa", 2248 | "num-conv", 2249 | "powerfmt", 2250 | "serde", 2251 | "time-core", 2252 | "time-macros", 2253 | ] 2254 | 2255 | [[package]] 2256 | name = "time-core" 2257 | version = "0.1.6" 2258 | source = "registry+https://github.com/rust-lang/crates.io-index" 2259 | checksum = "40868e7c1d2f0b8d73e4a8c7f0ff63af4f6d19be117e90bd73eb1d62cf831c6b" 2260 | 2261 | [[package]] 2262 | name = "time-macros" 2263 | version = "0.2.24" 2264 | source = "registry+https://github.com/rust-lang/crates.io-index" 2265 | checksum = "30cfb0125f12d9c277f35663a0a33f8c30190f4e4574868a330595412d34ebf3" 2266 | dependencies = [ 2267 | "num-conv", 2268 | "time-core", 2269 | ] 2270 | 2271 | [[package]] 2272 | name = "tiny-keccak" 2273 | version = "2.0.2" 2274 | source = "registry+https://github.com/rust-lang/crates.io-index" 2275 | checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" 2276 | dependencies = [ 2277 | "crunchy", 2278 | ] 2279 | 2280 | [[package]] 2281 | name = "tinystr" 2282 | version = "0.8.1" 2283 | source = "registry+https://github.com/rust-lang/crates.io-index" 2284 | checksum = "5d4f6d1145dcb577acf783d4e601bc1d76a13337bb54e6233add580b07344c8b" 2285 | dependencies = [ 2286 | "displaydoc", 2287 | "zerovec", 2288 | ] 2289 | 2290 | [[package]] 2291 | name = "tokio" 2292 | version = "1.47.1" 2293 | source = "registry+https://github.com/rust-lang/crates.io-index" 2294 | checksum = "89e49afdadebb872d3145a5638b59eb0691ea23e46ca484037cfab3b76b95038" 2295 | dependencies = [ 2296 | "backtrace", 2297 | "bytes", 2298 | "io-uring", 2299 | "libc", 2300 | "mio", 2301 | "parking_lot", 2302 | "pin-project-lite", 2303 | "signal-hook-registry", 2304 | "slab", 2305 | "socket2", 2306 | "tokio-macros", 2307 | "windows-sys 0.59.0", 2308 | ] 2309 | 2310 | [[package]] 2311 | name = "tokio-macros" 2312 | version = "2.5.0" 2313 | source = "registry+https://github.com/rust-lang/crates.io-index" 2314 | checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" 2315 | dependencies = [ 2316 | "proc-macro2", 2317 | "quote", 2318 | "syn", 2319 | ] 2320 | 2321 | [[package]] 2322 | name = "tokio-native-tls" 2323 | version = "0.3.1" 2324 | source = "registry+https://github.com/rust-lang/crates.io-index" 2325 | checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" 2326 | dependencies = [ 2327 | "native-tls", 2328 | "tokio", 2329 | ] 2330 | 2331 | [[package]] 2332 | name = "tokio-rustls" 2333 | version = "0.26.3" 2334 | source = "registry+https://github.com/rust-lang/crates.io-index" 2335 | checksum = "05f63835928ca123f1bef57abbcd23bb2ba0ac9ae1235f1e65bda0d06e7786bd" 2336 | dependencies = [ 2337 | "rustls", 2338 | "tokio", 2339 | ] 2340 | 2341 | [[package]] 2342 | name = "tokio-stream" 2343 | version = "0.1.17" 2344 | source = "registry+https://github.com/rust-lang/crates.io-index" 2345 | checksum = "eca58d7bba4a75707817a2c44174253f9236b2d5fbd055602e9d5c07c139a047" 2346 | dependencies = [ 2347 | "futures-core", 2348 | "pin-project-lite", 2349 | "tokio", 2350 | ] 2351 | 2352 | [[package]] 2353 | name = "tokio-util" 2354 | version = "0.7.16" 2355 | source = "registry+https://github.com/rust-lang/crates.io-index" 2356 | checksum = "14307c986784f72ef81c89db7d9e28d6ac26d16213b109ea501696195e6e3ce5" 2357 | dependencies = [ 2358 | "bytes", 2359 | "futures-core", 2360 | "futures-sink", 2361 | "pin-project-lite", 2362 | "tokio", 2363 | ] 2364 | 2365 | [[package]] 2366 | name = "toml" 2367 | version = "0.9.7" 2368 | source = "registry+https://github.com/rust-lang/crates.io-index" 2369 | checksum = "00e5e5d9bf2475ac9d4f0d9edab68cc573dc2fd644b0dba36b0c30a92dd9eaa0" 2370 | dependencies = [ 2371 | "serde_core", 2372 | "serde_spanned", 2373 | "toml_datetime", 2374 | "toml_parser", 2375 | "winnow", 2376 | ] 2377 | 2378 | [[package]] 2379 | name = "toml_datetime" 2380 | version = "0.7.2" 2381 | source = "registry+https://github.com/rust-lang/crates.io-index" 2382 | checksum = "32f1085dec27c2b6632b04c80b3bb1b4300d6495d1e129693bdda7d91e72eec1" 2383 | dependencies = [ 2384 | "serde_core", 2385 | ] 2386 | 2387 | [[package]] 2388 | name = "toml_parser" 2389 | version = "1.0.3" 2390 | source = "registry+https://github.com/rust-lang/crates.io-index" 2391 | checksum = "4cf893c33be71572e0e9aa6dd15e6677937abd686b066eac3f8cd3531688a627" 2392 | dependencies = [ 2393 | "winnow", 2394 | ] 2395 | 2396 | [[package]] 2397 | name = "tower" 2398 | version = "0.5.2" 2399 | source = "registry+https://github.com/rust-lang/crates.io-index" 2400 | checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9" 2401 | dependencies = [ 2402 | "futures-core", 2403 | "futures-util", 2404 | "pin-project-lite", 2405 | "sync_wrapper", 2406 | "tokio", 2407 | "tower-layer", 2408 | "tower-service", 2409 | ] 2410 | 2411 | [[package]] 2412 | name = "tower-http" 2413 | version = "0.6.6" 2414 | source = "registry+https://github.com/rust-lang/crates.io-index" 2415 | checksum = "adc82fd73de2a9722ac5da747f12383d2bfdb93591ee6c58486e0097890f05f2" 2416 | dependencies = [ 2417 | "bitflags", 2418 | "bytes", 2419 | "futures-util", 2420 | "http", 2421 | "http-body", 2422 | "iri-string", 2423 | "pin-project-lite", 2424 | "tower", 2425 | "tower-layer", 2426 | "tower-service", 2427 | ] 2428 | 2429 | [[package]] 2430 | name = "tower-layer" 2431 | version = "0.3.3" 2432 | source = "registry+https://github.com/rust-lang/crates.io-index" 2433 | checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" 2434 | 2435 | [[package]] 2436 | name = "tower-service" 2437 | version = "0.3.3" 2438 | source = "registry+https://github.com/rust-lang/crates.io-index" 2439 | checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" 2440 | 2441 | [[package]] 2442 | name = "tracing" 2443 | version = "0.1.41" 2444 | source = "registry+https://github.com/rust-lang/crates.io-index" 2445 | checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" 2446 | dependencies = [ 2447 | "pin-project-lite", 2448 | "tracing-attributes", 2449 | "tracing-core", 2450 | ] 2451 | 2452 | [[package]] 2453 | name = "tracing-attributes" 2454 | version = "0.1.30" 2455 | source = "registry+https://github.com/rust-lang/crates.io-index" 2456 | checksum = "81383ab64e72a7a8b8e13130c49e3dab29def6d0c7d76a03087b3cf71c5c6903" 2457 | dependencies = [ 2458 | "proc-macro2", 2459 | "quote", 2460 | "syn", 2461 | ] 2462 | 2463 | [[package]] 2464 | name = "tracing-core" 2465 | version = "0.1.34" 2466 | source = "registry+https://github.com/rust-lang/crates.io-index" 2467 | checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678" 2468 | dependencies = [ 2469 | "once_cell", 2470 | "valuable", 2471 | ] 2472 | 2473 | [[package]] 2474 | name = "tracing-log" 2475 | version = "0.2.0" 2476 | source = "registry+https://github.com/rust-lang/crates.io-index" 2477 | checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" 2478 | dependencies = [ 2479 | "log", 2480 | "once_cell", 2481 | "tracing-core", 2482 | ] 2483 | 2484 | [[package]] 2485 | name = "tracing-subscriber" 2486 | version = "0.3.20" 2487 | source = "registry+https://github.com/rust-lang/crates.io-index" 2488 | checksum = "2054a14f5307d601f88daf0553e1cbf472acc4f2c51afab632431cdcd72124d5" 2489 | dependencies = [ 2490 | "nu-ansi-term", 2491 | "sharded-slab", 2492 | "smallvec", 2493 | "thread_local", 2494 | "tracing-core", 2495 | "tracing-log", 2496 | ] 2497 | 2498 | [[package]] 2499 | name = "try-lock" 2500 | version = "0.2.5" 2501 | source = "registry+https://github.com/rust-lang/crates.io-index" 2502 | checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" 2503 | 2504 | [[package]] 2505 | name = "typeid" 2506 | version = "1.0.3" 2507 | source = "registry+https://github.com/rust-lang/crates.io-index" 2508 | checksum = "bc7d623258602320d5c55d1bc22793b57daff0ec7efc270ea7d55ce1d5f5471c" 2509 | 2510 | [[package]] 2511 | name = "typenum" 2512 | version = "1.18.0" 2513 | source = "registry+https://github.com/rust-lang/crates.io-index" 2514 | checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f" 2515 | 2516 | [[package]] 2517 | name = "ucd-trie" 2518 | version = "0.1.7" 2519 | source = "registry+https://github.com/rust-lang/crates.io-index" 2520 | checksum = "2896d95c02a80c6d6a5d6e953d479f5ddf2dfdb6a244441010e373ac0fb88971" 2521 | 2522 | [[package]] 2523 | name = "unicode-ident" 2524 | version = "1.0.19" 2525 | source = "registry+https://github.com/rust-lang/crates.io-index" 2526 | checksum = "f63a545481291138910575129486daeaf8ac54aee4387fe7906919f7830c7d9d" 2527 | 2528 | [[package]] 2529 | name = "unicode-segmentation" 2530 | version = "1.12.0" 2531 | source = "registry+https://github.com/rust-lang/crates.io-index" 2532 | checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" 2533 | 2534 | [[package]] 2535 | name = "unicode-width" 2536 | version = "0.2.1" 2537 | source = "registry+https://github.com/rust-lang/crates.io-index" 2538 | checksum = "4a1a07cc7db3810833284e8d372ccdc6da29741639ecc70c9ec107df0fa6154c" 2539 | 2540 | [[package]] 2541 | name = "untrusted" 2542 | version = "0.9.0" 2543 | source = "registry+https://github.com/rust-lang/crates.io-index" 2544 | checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" 2545 | 2546 | [[package]] 2547 | name = "url" 2548 | version = "2.5.7" 2549 | source = "registry+https://github.com/rust-lang/crates.io-index" 2550 | checksum = "08bc136a29a3d1758e07a9cca267be308aeebf5cfd5a10f3f67ab2097683ef5b" 2551 | dependencies = [ 2552 | "form_urlencoded", 2553 | "idna", 2554 | "percent-encoding", 2555 | "serde", 2556 | ] 2557 | 2558 | [[package]] 2559 | name = "urlencoding" 2560 | version = "2.1.3" 2561 | source = "registry+https://github.com/rust-lang/crates.io-index" 2562 | checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da" 2563 | 2564 | [[package]] 2565 | name = "utf8_iter" 2566 | version = "1.0.4" 2567 | source = "registry+https://github.com/rust-lang/crates.io-index" 2568 | checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" 2569 | 2570 | [[package]] 2571 | name = "utf8parse" 2572 | version = "0.2.2" 2573 | source = "registry+https://github.com/rust-lang/crates.io-index" 2574 | checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" 2575 | 2576 | [[package]] 2577 | name = "valuable" 2578 | version = "0.1.1" 2579 | source = "registry+https://github.com/rust-lang/crates.io-index" 2580 | checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" 2581 | 2582 | [[package]] 2583 | name = "vcpkg" 2584 | version = "0.2.15" 2585 | source = "registry+https://github.com/rust-lang/crates.io-index" 2586 | checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" 2587 | 2588 | [[package]] 2589 | name = "version_check" 2590 | version = "0.9.5" 2591 | source = "registry+https://github.com/rust-lang/crates.io-index" 2592 | checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" 2593 | 2594 | [[package]] 2595 | name = "want" 2596 | version = "0.3.1" 2597 | source = "registry+https://github.com/rust-lang/crates.io-index" 2598 | checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" 2599 | dependencies = [ 2600 | "try-lock", 2601 | ] 2602 | 2603 | [[package]] 2604 | name = "wasi" 2605 | version = "0.11.1+wasi-snapshot-preview1" 2606 | source = "registry+https://github.com/rust-lang/crates.io-index" 2607 | checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" 2608 | 2609 | [[package]] 2610 | name = "wasi" 2611 | version = "0.14.7+wasi-0.2.4" 2612 | source = "registry+https://github.com/rust-lang/crates.io-index" 2613 | checksum = "883478de20367e224c0090af9cf5f9fa85bed63a95c1abf3afc5c083ebc06e8c" 2614 | dependencies = [ 2615 | "wasip2", 2616 | ] 2617 | 2618 | [[package]] 2619 | name = "wasip2" 2620 | version = "1.0.1+wasi-0.2.4" 2621 | source = "registry+https://github.com/rust-lang/crates.io-index" 2622 | checksum = "0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7" 2623 | dependencies = [ 2624 | "wit-bindgen", 2625 | ] 2626 | 2627 | [[package]] 2628 | name = "wasm-bindgen" 2629 | version = "0.2.103" 2630 | source = "registry+https://github.com/rust-lang/crates.io-index" 2631 | checksum = "ab10a69fbd0a177f5f649ad4d8d3305499c42bab9aef2f7ff592d0ec8f833819" 2632 | dependencies = [ 2633 | "cfg-if", 2634 | "once_cell", 2635 | "rustversion", 2636 | "wasm-bindgen-macro", 2637 | "wasm-bindgen-shared", 2638 | ] 2639 | 2640 | [[package]] 2641 | name = "wasm-bindgen-backend" 2642 | version = "0.2.103" 2643 | source = "registry+https://github.com/rust-lang/crates.io-index" 2644 | checksum = "0bb702423545a6007bbc368fde243ba47ca275e549c8a28617f56f6ba53b1d1c" 2645 | dependencies = [ 2646 | "bumpalo", 2647 | "log", 2648 | "proc-macro2", 2649 | "quote", 2650 | "syn", 2651 | "wasm-bindgen-shared", 2652 | ] 2653 | 2654 | [[package]] 2655 | name = "wasm-bindgen-futures" 2656 | version = "0.4.53" 2657 | source = "registry+https://github.com/rust-lang/crates.io-index" 2658 | checksum = "a0b221ff421256839509adbb55998214a70d829d3a28c69b4a6672e9d2a42f67" 2659 | dependencies = [ 2660 | "cfg-if", 2661 | "js-sys", 2662 | "once_cell", 2663 | "wasm-bindgen", 2664 | "web-sys", 2665 | ] 2666 | 2667 | [[package]] 2668 | name = "wasm-bindgen-macro" 2669 | version = "0.2.103" 2670 | source = "registry+https://github.com/rust-lang/crates.io-index" 2671 | checksum = "fc65f4f411d91494355917b605e1480033152658d71f722a90647f56a70c88a0" 2672 | dependencies = [ 2673 | "quote", 2674 | "wasm-bindgen-macro-support", 2675 | ] 2676 | 2677 | [[package]] 2678 | name = "wasm-bindgen-macro-support" 2679 | version = "0.2.103" 2680 | source = "registry+https://github.com/rust-lang/crates.io-index" 2681 | checksum = "ffc003a991398a8ee604a401e194b6b3a39677b3173d6e74495eb51b82e99a32" 2682 | dependencies = [ 2683 | "proc-macro2", 2684 | "quote", 2685 | "syn", 2686 | "wasm-bindgen-backend", 2687 | "wasm-bindgen-shared", 2688 | ] 2689 | 2690 | [[package]] 2691 | name = "wasm-bindgen-shared" 2692 | version = "0.2.103" 2693 | source = "registry+https://github.com/rust-lang/crates.io-index" 2694 | checksum = "293c37f4efa430ca14db3721dfbe48d8c33308096bd44d80ebaa775ab71ba1cf" 2695 | dependencies = [ 2696 | "unicode-ident", 2697 | ] 2698 | 2699 | [[package]] 2700 | name = "wasm-streams" 2701 | version = "0.4.2" 2702 | source = "registry+https://github.com/rust-lang/crates.io-index" 2703 | checksum = "15053d8d85c7eccdbefef60f06769760a563c7f0a9d6902a13d35c7800b0ad65" 2704 | dependencies = [ 2705 | "futures-util", 2706 | "js-sys", 2707 | "wasm-bindgen", 2708 | "wasm-bindgen-futures", 2709 | "web-sys", 2710 | ] 2711 | 2712 | [[package]] 2713 | name = "web-sys" 2714 | version = "0.3.80" 2715 | source = "registry+https://github.com/rust-lang/crates.io-index" 2716 | checksum = "fbe734895e869dc429d78c4b433f8d17d95f8d05317440b4fad5ab2d33e596dc" 2717 | dependencies = [ 2718 | "js-sys", 2719 | "wasm-bindgen", 2720 | ] 2721 | 2722 | [[package]] 2723 | name = "winapi" 2724 | version = "0.3.9" 2725 | source = "registry+https://github.com/rust-lang/crates.io-index" 2726 | checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" 2727 | dependencies = [ 2728 | "winapi-i686-pc-windows-gnu", 2729 | "winapi-x86_64-pc-windows-gnu", 2730 | ] 2731 | 2732 | [[package]] 2733 | name = "winapi-i686-pc-windows-gnu" 2734 | version = "0.4.0" 2735 | source = "registry+https://github.com/rust-lang/crates.io-index" 2736 | checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" 2737 | 2738 | [[package]] 2739 | name = "winapi-x86_64-pc-windows-gnu" 2740 | version = "0.4.0" 2741 | source = "registry+https://github.com/rust-lang/crates.io-index" 2742 | checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" 2743 | 2744 | [[package]] 2745 | name = "windows" 2746 | version = "0.61.3" 2747 | source = "registry+https://github.com/rust-lang/crates.io-index" 2748 | checksum = "9babd3a767a4c1aef6900409f85f5d53ce2544ccdfaa86dad48c91782c6d6893" 2749 | dependencies = [ 2750 | "windows-collections", 2751 | "windows-core 0.61.2", 2752 | "windows-future", 2753 | "windows-link 0.1.3", 2754 | "windows-numerics", 2755 | ] 2756 | 2757 | [[package]] 2758 | name = "windows-collections" 2759 | version = "0.2.0" 2760 | source = "registry+https://github.com/rust-lang/crates.io-index" 2761 | checksum = "3beeceb5e5cfd9eb1d76b381630e82c4241ccd0d27f1a39ed41b2760b255c5e8" 2762 | dependencies = [ 2763 | "windows-core 0.61.2", 2764 | ] 2765 | 2766 | [[package]] 2767 | name = "windows-core" 2768 | version = "0.61.2" 2769 | source = "registry+https://github.com/rust-lang/crates.io-index" 2770 | checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3" 2771 | dependencies = [ 2772 | "windows-implement", 2773 | "windows-interface", 2774 | "windows-link 0.1.3", 2775 | "windows-result 0.3.4", 2776 | "windows-strings 0.4.2", 2777 | ] 2778 | 2779 | [[package]] 2780 | name = "windows-core" 2781 | version = "0.62.0" 2782 | source = "registry+https://github.com/rust-lang/crates.io-index" 2783 | checksum = "57fe7168f7de578d2d8a05b07fd61870d2e73b4020e9f49aa00da8471723497c" 2784 | dependencies = [ 2785 | "windows-implement", 2786 | "windows-interface", 2787 | "windows-link 0.2.0", 2788 | "windows-result 0.4.0", 2789 | "windows-strings 0.5.0", 2790 | ] 2791 | 2792 | [[package]] 2793 | name = "windows-future" 2794 | version = "0.2.1" 2795 | source = "registry+https://github.com/rust-lang/crates.io-index" 2796 | checksum = "fc6a41e98427b19fe4b73c550f060b59fa592d7d686537eebf9385621bfbad8e" 2797 | dependencies = [ 2798 | "windows-core 0.61.2", 2799 | "windows-link 0.1.3", 2800 | "windows-threading", 2801 | ] 2802 | 2803 | [[package]] 2804 | name = "windows-implement" 2805 | version = "0.60.0" 2806 | source = "registry+https://github.com/rust-lang/crates.io-index" 2807 | checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836" 2808 | dependencies = [ 2809 | "proc-macro2", 2810 | "quote", 2811 | "syn", 2812 | ] 2813 | 2814 | [[package]] 2815 | name = "windows-interface" 2816 | version = "0.59.1" 2817 | source = "registry+https://github.com/rust-lang/crates.io-index" 2818 | checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8" 2819 | dependencies = [ 2820 | "proc-macro2", 2821 | "quote", 2822 | "syn", 2823 | ] 2824 | 2825 | [[package]] 2826 | name = "windows-link" 2827 | version = "0.1.3" 2828 | source = "registry+https://github.com/rust-lang/crates.io-index" 2829 | checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a" 2830 | 2831 | [[package]] 2832 | name = "windows-link" 2833 | version = "0.2.0" 2834 | source = "registry+https://github.com/rust-lang/crates.io-index" 2835 | checksum = "45e46c0661abb7180e7b9c281db115305d49ca1709ab8242adf09666d2173c65" 2836 | 2837 | [[package]] 2838 | name = "windows-numerics" 2839 | version = "0.2.0" 2840 | source = "registry+https://github.com/rust-lang/crates.io-index" 2841 | checksum = "9150af68066c4c5c07ddc0ce30421554771e528bde427614c61038bc2c92c2b1" 2842 | dependencies = [ 2843 | "windows-core 0.61.2", 2844 | "windows-link 0.1.3", 2845 | ] 2846 | 2847 | [[package]] 2848 | name = "windows-registry" 2849 | version = "0.5.3" 2850 | source = "registry+https://github.com/rust-lang/crates.io-index" 2851 | checksum = "5b8a9ed28765efc97bbc954883f4e6796c33a06546ebafacbabee9696967499e" 2852 | dependencies = [ 2853 | "windows-link 0.1.3", 2854 | "windows-result 0.3.4", 2855 | "windows-strings 0.4.2", 2856 | ] 2857 | 2858 | [[package]] 2859 | name = "windows-result" 2860 | version = "0.3.4" 2861 | source = "registry+https://github.com/rust-lang/crates.io-index" 2862 | checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6" 2863 | dependencies = [ 2864 | "windows-link 0.1.3", 2865 | ] 2866 | 2867 | [[package]] 2868 | name = "windows-result" 2869 | version = "0.4.0" 2870 | source = "registry+https://github.com/rust-lang/crates.io-index" 2871 | checksum = "7084dcc306f89883455a206237404d3eaf961e5bd7e0f312f7c91f57eb44167f" 2872 | dependencies = [ 2873 | "windows-link 0.2.0", 2874 | ] 2875 | 2876 | [[package]] 2877 | name = "windows-strings" 2878 | version = "0.4.2" 2879 | source = "registry+https://github.com/rust-lang/crates.io-index" 2880 | checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57" 2881 | dependencies = [ 2882 | "windows-link 0.1.3", 2883 | ] 2884 | 2885 | [[package]] 2886 | name = "windows-strings" 2887 | version = "0.5.0" 2888 | source = "registry+https://github.com/rust-lang/crates.io-index" 2889 | checksum = "7218c655a553b0bed4426cf54b20d7ba363ef543b52d515b3e48d7fd55318dda" 2890 | dependencies = [ 2891 | "windows-link 0.2.0", 2892 | ] 2893 | 2894 | [[package]] 2895 | name = "windows-sys" 2896 | version = "0.52.0" 2897 | source = "registry+https://github.com/rust-lang/crates.io-index" 2898 | checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" 2899 | dependencies = [ 2900 | "windows-targets 0.52.6", 2901 | ] 2902 | 2903 | [[package]] 2904 | name = "windows-sys" 2905 | version = "0.59.0" 2906 | source = "registry+https://github.com/rust-lang/crates.io-index" 2907 | checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" 2908 | dependencies = [ 2909 | "windows-targets 0.52.6", 2910 | ] 2911 | 2912 | [[package]] 2913 | name = "windows-sys" 2914 | version = "0.60.2" 2915 | source = "registry+https://github.com/rust-lang/crates.io-index" 2916 | checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" 2917 | dependencies = [ 2918 | "windows-targets 0.53.3", 2919 | ] 2920 | 2921 | [[package]] 2922 | name = "windows-sys" 2923 | version = "0.61.0" 2924 | source = "registry+https://github.com/rust-lang/crates.io-index" 2925 | checksum = "e201184e40b2ede64bc2ea34968b28e33622acdbbf37104f0e4a33f7abe657aa" 2926 | dependencies = [ 2927 | "windows-link 0.2.0", 2928 | ] 2929 | 2930 | [[package]] 2931 | name = "windows-targets" 2932 | version = "0.52.6" 2933 | source = "registry+https://github.com/rust-lang/crates.io-index" 2934 | checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" 2935 | dependencies = [ 2936 | "windows_aarch64_gnullvm 0.52.6", 2937 | "windows_aarch64_msvc 0.52.6", 2938 | "windows_i686_gnu 0.52.6", 2939 | "windows_i686_gnullvm 0.52.6", 2940 | "windows_i686_msvc 0.52.6", 2941 | "windows_x86_64_gnu 0.52.6", 2942 | "windows_x86_64_gnullvm 0.52.6", 2943 | "windows_x86_64_msvc 0.52.6", 2944 | ] 2945 | 2946 | [[package]] 2947 | name = "windows-targets" 2948 | version = "0.53.3" 2949 | source = "registry+https://github.com/rust-lang/crates.io-index" 2950 | checksum = "d5fe6031c4041849d7c496a8ded650796e7b6ecc19df1a431c1a363342e5dc91" 2951 | dependencies = [ 2952 | "windows-link 0.1.3", 2953 | "windows_aarch64_gnullvm 0.53.0", 2954 | "windows_aarch64_msvc 0.53.0", 2955 | "windows_i686_gnu 0.53.0", 2956 | "windows_i686_gnullvm 0.53.0", 2957 | "windows_i686_msvc 0.53.0", 2958 | "windows_x86_64_gnu 0.53.0", 2959 | "windows_x86_64_gnullvm 0.53.0", 2960 | "windows_x86_64_msvc 0.53.0", 2961 | ] 2962 | 2963 | [[package]] 2964 | name = "windows-threading" 2965 | version = "0.1.0" 2966 | source = "registry+https://github.com/rust-lang/crates.io-index" 2967 | checksum = "b66463ad2e0ea3bbf808b7f1d371311c80e115c0b71d60efc142cafbcfb057a6" 2968 | dependencies = [ 2969 | "windows-link 0.1.3", 2970 | ] 2971 | 2972 | [[package]] 2973 | name = "windows_aarch64_gnullvm" 2974 | version = "0.52.6" 2975 | source = "registry+https://github.com/rust-lang/crates.io-index" 2976 | checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" 2977 | 2978 | [[package]] 2979 | name = "windows_aarch64_gnullvm" 2980 | version = "0.53.0" 2981 | source = "registry+https://github.com/rust-lang/crates.io-index" 2982 | checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" 2983 | 2984 | [[package]] 2985 | name = "windows_aarch64_msvc" 2986 | version = "0.52.6" 2987 | source = "registry+https://github.com/rust-lang/crates.io-index" 2988 | checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" 2989 | 2990 | [[package]] 2991 | name = "windows_aarch64_msvc" 2992 | version = "0.53.0" 2993 | source = "registry+https://github.com/rust-lang/crates.io-index" 2994 | checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" 2995 | 2996 | [[package]] 2997 | name = "windows_i686_gnu" 2998 | version = "0.52.6" 2999 | source = "registry+https://github.com/rust-lang/crates.io-index" 3000 | checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" 3001 | 3002 | [[package]] 3003 | name = "windows_i686_gnu" 3004 | version = "0.53.0" 3005 | source = "registry+https://github.com/rust-lang/crates.io-index" 3006 | checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3" 3007 | 3008 | [[package]] 3009 | name = "windows_i686_gnullvm" 3010 | version = "0.52.6" 3011 | source = "registry+https://github.com/rust-lang/crates.io-index" 3012 | checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" 3013 | 3014 | [[package]] 3015 | name = "windows_i686_gnullvm" 3016 | version = "0.53.0" 3017 | source = "registry+https://github.com/rust-lang/crates.io-index" 3018 | checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" 3019 | 3020 | [[package]] 3021 | name = "windows_i686_msvc" 3022 | version = "0.52.6" 3023 | source = "registry+https://github.com/rust-lang/crates.io-index" 3024 | checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" 3025 | 3026 | [[package]] 3027 | name = "windows_i686_msvc" 3028 | version = "0.53.0" 3029 | source = "registry+https://github.com/rust-lang/crates.io-index" 3030 | checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" 3031 | 3032 | [[package]] 3033 | name = "windows_x86_64_gnu" 3034 | version = "0.52.6" 3035 | source = "registry+https://github.com/rust-lang/crates.io-index" 3036 | checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" 3037 | 3038 | [[package]] 3039 | name = "windows_x86_64_gnu" 3040 | version = "0.53.0" 3041 | source = "registry+https://github.com/rust-lang/crates.io-index" 3042 | checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" 3043 | 3044 | [[package]] 3045 | name = "windows_x86_64_gnullvm" 3046 | version = "0.52.6" 3047 | source = "registry+https://github.com/rust-lang/crates.io-index" 3048 | checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" 3049 | 3050 | [[package]] 3051 | name = "windows_x86_64_gnullvm" 3052 | version = "0.53.0" 3053 | source = "registry+https://github.com/rust-lang/crates.io-index" 3054 | checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" 3055 | 3056 | [[package]] 3057 | name = "windows_x86_64_msvc" 3058 | version = "0.52.6" 3059 | source = "registry+https://github.com/rust-lang/crates.io-index" 3060 | checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" 3061 | 3062 | [[package]] 3063 | name = "windows_x86_64_msvc" 3064 | version = "0.53.0" 3065 | source = "registry+https://github.com/rust-lang/crates.io-index" 3066 | checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" 3067 | 3068 | [[package]] 3069 | name = "winnow" 3070 | version = "0.7.13" 3071 | source = "registry+https://github.com/rust-lang/crates.io-index" 3072 | checksum = "21a0236b59786fed61e2a80582dd500fe61f18b5dca67a4a067d0bc9039339cf" 3073 | dependencies = [ 3074 | "memchr", 3075 | ] 3076 | 3077 | [[package]] 3078 | name = "wit-bindgen" 3079 | version = "0.46.0" 3080 | source = "registry+https://github.com/rust-lang/crates.io-index" 3081 | checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59" 3082 | 3083 | [[package]] 3084 | name = "writeable" 3085 | version = "0.6.1" 3086 | source = "registry+https://github.com/rust-lang/crates.io-index" 3087 | checksum = "ea2f10b9bb0928dfb1b42b65e1f9e36f7f54dbdf08457afefb38afcdec4fa2bb" 3088 | 3089 | [[package]] 3090 | name = "yaml-rust2" 3091 | version = "0.10.4" 3092 | source = "registry+https://github.com/rust-lang/crates.io-index" 3093 | checksum = "2462ea039c445496d8793d052e13787f2b90e750b833afee748e601c17621ed9" 3094 | dependencies = [ 3095 | "arraydeque", 3096 | "encoding_rs", 3097 | "hashlink", 3098 | ] 3099 | 3100 | [[package]] 3101 | name = "yoke" 3102 | version = "0.8.0" 3103 | source = "registry+https://github.com/rust-lang/crates.io-index" 3104 | checksum = "5f41bb01b8226ef4bfd589436a297c53d118f65921786300e427be8d487695cc" 3105 | dependencies = [ 3106 | "serde", 3107 | "stable_deref_trait", 3108 | "yoke-derive", 3109 | "zerofrom", 3110 | ] 3111 | 3112 | [[package]] 3113 | name = "yoke-derive" 3114 | version = "0.8.0" 3115 | source = "registry+https://github.com/rust-lang/crates.io-index" 3116 | checksum = "38da3c9736e16c5d3c8c597a9aaa5d1fa565d0532ae05e27c24aa62fb32c0ab6" 3117 | dependencies = [ 3118 | "proc-macro2", 3119 | "quote", 3120 | "syn", 3121 | "synstructure", 3122 | ] 3123 | 3124 | [[package]] 3125 | name = "zerocopy" 3126 | version = "0.8.27" 3127 | source = "registry+https://github.com/rust-lang/crates.io-index" 3128 | checksum = "0894878a5fa3edfd6da3f88c4805f4c8558e2b996227a3d864f47fe11e38282c" 3129 | dependencies = [ 3130 | "zerocopy-derive", 3131 | ] 3132 | 3133 | [[package]] 3134 | name = "zerocopy-derive" 3135 | version = "0.8.27" 3136 | source = "registry+https://github.com/rust-lang/crates.io-index" 3137 | checksum = "88d2b8d9c68ad2b9e4340d7832716a4d21a22a1154777ad56ea55c51a9cf3831" 3138 | dependencies = [ 3139 | "proc-macro2", 3140 | "quote", 3141 | "syn", 3142 | ] 3143 | 3144 | [[package]] 3145 | name = "zerofrom" 3146 | version = "0.1.6" 3147 | source = "registry+https://github.com/rust-lang/crates.io-index" 3148 | checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5" 3149 | dependencies = [ 3150 | "zerofrom-derive", 3151 | ] 3152 | 3153 | [[package]] 3154 | name = "zerofrom-derive" 3155 | version = "0.1.6" 3156 | source = "registry+https://github.com/rust-lang/crates.io-index" 3157 | checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" 3158 | dependencies = [ 3159 | "proc-macro2", 3160 | "quote", 3161 | "syn", 3162 | "synstructure", 3163 | ] 3164 | 3165 | [[package]] 3166 | name = "zeroize" 3167 | version = "1.8.1" 3168 | source = "registry+https://github.com/rust-lang/crates.io-index" 3169 | checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" 3170 | 3171 | [[package]] 3172 | name = "zerotrie" 3173 | version = "0.2.2" 3174 | source = "registry+https://github.com/rust-lang/crates.io-index" 3175 | checksum = "36f0bbd478583f79edad978b407914f61b2972f5af6fa089686016be8f9af595" 3176 | dependencies = [ 3177 | "displaydoc", 3178 | "yoke", 3179 | "zerofrom", 3180 | ] 3181 | 3182 | [[package]] 3183 | name = "zerovec" 3184 | version = "0.11.4" 3185 | source = "registry+https://github.com/rust-lang/crates.io-index" 3186 | checksum = "e7aa2bd55086f1ab526693ecbe444205da57e25f4489879da80635a46d90e73b" 3187 | dependencies = [ 3188 | "yoke", 3189 | "zerofrom", 3190 | "zerovec-derive", 3191 | ] 3192 | 3193 | [[package]] 3194 | name = "zerovec-derive" 3195 | version = "0.11.1" 3196 | source = "registry+https://github.com/rust-lang/crates.io-index" 3197 | checksum = "5b96237efa0c878c64bd89c436f661be4e46b2f3eff1ebb976f7ef2321d2f58f" 3198 | dependencies = [ 3199 | "proc-macro2", 3200 | "quote", 3201 | "syn", 3202 | ] 3203 | --------------------------------------------------------------------------------