rust版本完成
This commit is contained in:
1 parent
eb3855f434
commit
8594a0167b
19 files changed
+7046
-63
No files matched your search
+142
-45
@@ -1,58 +1,155 @@
|
||||
# Rust 实现方案与开发指南
|
||||
# Excel Keyword Search Tool — Rust 版
|
||||
|
||||
本文档为智能体(Agent)和开发者提供基于 Rust 语言重构 Excel 关键字搜索工具的详细设计、Cargo 配置和实施指南。
|
||||
跨 Excel / Word / CSV / 文本 文件批量关键字检索工具的 Rust 实现,包含两个交付物:
|
||||
|
||||
## 1. 架构设计目标
|
||||
- **极致的性能与最小体积**:利用 Rust 的内存安全、零成本抽象及编译优化(`opt-level = "z"`、`strip = true`),生成的独立二进制文件极小(通常在 5MB ~ 15MB 之间),运行速度达到极致。
|
||||
- **全格式 Excel 解析**:基于 `calamine` 库,完美支持 `.xlsx`, `.xls`, `.xlsb`, `.ods`。
|
||||
- **并行计算加速**:利用 `rayon` 库进行多核并行文件扫描与内容匹配。
|
||||
- **`excel-search-rust.exe`** — 命令行搜索器(对标 Go 版 `cmd/searcher`),追求极致的单二进制体积与启动速度;
|
||||
- **`excel-search-rust-desktop.exe`** — 桌面版(对标 Go 版 `cmd/desktop`):
|
||||
**原生 egui/eframe 图形界面**,单 exe 直接出窗口。不沿用 Go 版"HTTP 服务 + Edge 应用窗口"
|
||||
的前后端分离架构——那是受 Go 生态限制的妥协,Rust 有更好选择:
|
||||
关窗即退出(无心跳判活 hack)、搜索跑后台线程 UI 全程可交互(无 30s 服务端超时截断)、
|
||||
结果表原生虚拟滚动(万级命中不卡顿,无分页条)。
|
||||
|
||||
WebUI(独立浏览器标签页)形态仍由 Go 版提供(见 `../go/README.md`)。
|
||||
|
||||
## 特性
|
||||
|
||||
- **并发扫描**:rayon 线程池按文件并行解析,`--workers` 可配(默认 8,可用环境变量 `EXCEL_SEARCH_WORKERS` 覆盖)。
|
||||
- **匹配语义与 Go 版逐字节对齐**:
|
||||
- 关键字与文本均做 Unicode NFC 规范化(`cafe\u{301}` == `café`);
|
||||
- 默认不区分大小写(Unicode 折叠);
|
||||
- **完整单词匹配默认关闭**(模糊子串匹配);开启后要求关键字前后均为单词边界(字母/数字/组合标记/下划线之外)。
|
||||
- **文件格式**:
|
||||
- Excel:`.xlsx/.xlsm/.xltx/.xltm`,并借助 calamine 额外支持 `.xls/.xlsb/.ods`(Go 版不含这三种);
|
||||
- Word:`.docx/.docm`(解析 `word/document.xml`,按段落定位 `Paragraph N`,表格段落一并覆盖);
|
||||
- 文本:`.txt/.csv`(按行定位 `Line N`,CSV 不解析字段,整行视为纯文本)。
|
||||
- **文件级缓存**:与 Go 版相同的 JSON 结构(`{"version":2,"cache":{...}}`),
|
||||
按“路径 + 关键字 + ModTime + Size”判定命中;同一搜索根目录的缓存文件
|
||||
(`<cache_dir>/cache_kw_<sha256(绝对路径)前16字节>.json`)可与 Go 版互换读写。
|
||||
缓存目录由 `EXCEL_SEARCH_CACHE_DIR` 指定,默认运行目录下 `.cache/`。
|
||||
- **健壮性**:单文件解析失败仅向 stderr 记 `warn:` 告警并跳过,不中断整次搜索;
|
||||
stdout 只输出结果,`--json` 可安全被管道消费。
|
||||
|
||||
## 目录结构
|
||||
|
||||
## 2. 目录结构
|
||||
```text
|
||||
rust/
|
||||
├── Cargo.toml
|
||||
├── README.md
|
||||
├── build.rs
|
||||
└── src/
|
||||
├── main.rs
|
||||
├── error.rs
|
||||
└── engine/
|
||||
├── mod.rs
|
||||
├── walker.rs
|
||||
└── parser.rs
|
||||
├── src/
|
||||
│ ├── lib.rs # 库入口(engine + error)
|
||||
│ ├── main.rs # CLI(clap)
|
||||
│ ├── error.rs # 统一错误类型
|
||||
│ ├── history.rs # 搜索历史 LRU(与 Go 桌面版同格式共用文件)
|
||||
│ ├── desktop/
|
||||
│ │ └── main.rs # 桌面版:原生 egui GUI(eframe)
|
||||
│ └── engine/
|
||||
│ ├── mod.rs # 搜索编排:并行调度 + 缓存合并 + 选项/结果类型
|
||||
│ ├── matcher.rs # NFC + 大小写折叠 + 完整单词边界
|
||||
│ ├── walker.rs # 目录遍历与文件类型过滤
|
||||
│ ├── parser.rs # Excel(calamine) / Word(zip+quick-xml) / 文本 解析器
|
||||
│ └── cache.rs # 文件级 JSON 缓存(与 Go 版 schema 兼容)
|
||||
└── tests/
|
||||
├── fixtures/search_sample.xlsx # 真实 xlsx 夹具(Go excelize 生成)
|
||||
└── search.rs # 集成测试(与 Go scanner_test 断言语义对应)
|
||||
```
|
||||
|
||||
## 3. 核心配置与实现规范
|
||||
## 构建与测试
|
||||
|
||||
### 3.1 `Cargo.toml`(关键:体积与性能优化配置)
|
||||
```toml
|
||||
[package]
|
||||
name = "excel-search-rust"
|
||||
version = "1.0.0"
|
||||
edition = "2021"
|
||||
### 一键构建(Windows)
|
||||
|
||||
[dependencies]
|
||||
calamine = "0.22"
|
||||
rayon = "1.8"
|
||||
walkdir = "2.4"
|
||||
clap = { version = "4.4", features = ["derive"] }
|
||||
zip = "0.6"
|
||||
quick-xml = "0.31"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_json = "1.0"
|
||||
双击 `rust\build.bat`,或命令行:
|
||||
|
||||
[profile.release]
|
||||
opt-level = "z" # 针对二进制文件大小进行优化
|
||||
lto = true # 链接时优化
|
||||
codegen-units = 1 # 单代码生成单元,最大化优化和压缩
|
||||
panic = "abort" # 移除栈展开开销
|
||||
strip = true # 剥离所有调试符号
|
||||
```bat
|
||||
build.bat :: release 构建(默认)
|
||||
build.bat debug :: debug 构建
|
||||
build.bat test :: 运行全部测试
|
||||
```
|
||||
|
||||
### 3.2 核心搜索逻辑要点 (`src/main.rs`)
|
||||
- 使用 `clap` 定义命令行参数(目录、关键字)。
|
||||
- 使用 `walkdir` 收集文件列表。
|
||||
- 使用 `rayon` 的 `par_iter()` 并行遍历所有文件:
|
||||
- 对 Excel 调用 `calamine::open_workbook_auto` 解析。
|
||||
- 对文本/Word 文件进行文本匹配。
|
||||
- 将匹配结果序列化为 JSON 或友好打印。
|
||||
脚本自动探测工具链(优先 mise 托管的 cargo/rustup → 系统 PATH),
|
||||
存在 GNU 工具链 + winlibs mingw 时自动走无 MSVC 编译路径,否则回退默认工具链并给出安装指引。
|
||||
|
||||
### 手动构建
|
||||
|
||||
```bash
|
||||
cd rust
|
||||
cargo test # 单元(lib 11 + 桌面 2)+ 集成(引擎端到端 10)
|
||||
cargo build --release # 产物(一次构建出两个 exe;LTO 全量构建约 2-20 分钟):
|
||||
# target/release/excel-search-rust.exe 命令行版 ≈1.3MB
|
||||
# target/release/excel-search-rust-desktop.exe 桌面版(原生 egui GUI)≈9.6MB
|
||||
```
|
||||
|
||||
**Windows 工具链说明**:本机若无 Visual Studio Build Tools / Windows SDK,
|
||||
默认 `x86_64-pc-windows-msvc` 目标无法链接,请改用 GNU 目标(winlibs 便携版即可,免安装):
|
||||
|
||||
```bash
|
||||
rustup target add x86_64-pc-windows-gnu
|
||||
# 将 winlibs-x86_64-posix-seh-*-ucrt 解压后将 mingw64\bin 加入 PATH,然后:
|
||||
cargo test --target x86_64-pc-windows-gnu
|
||||
cargo build --release --target x86_64-pc-windows-gnu
|
||||
# 产物:target/x86_64-pc-windows-gnu/release/ 下的两个 exe
|
||||
```
|
||||
|
||||
## 用法
|
||||
|
||||
```bash
|
||||
# 基本用法(默认:不区分大小写 + 模糊匹配 + 递归子目录 + 全部文件类型)
|
||||
excel-search-rust --dir <目录> --keyword <关键字>
|
||||
excel-search-rust <目录> <关键字> # 等价的位置参数写法
|
||||
|
||||
# 输出 JSON(便于脚本处理)
|
||||
excel-search-rust --dir ./data --keyword 关键词 --json
|
||||
|
||||
# 区分大小写
|
||||
excel-search-rust --dir ./data --keyword Phone --case-sensitive=true
|
||||
|
||||
# 完整单词匹配(默认关闭,开启后要求关键字前后均为单词边界)
|
||||
excel-search-rust --dir ./data --keyword 手机 --whole-word
|
||||
|
||||
# 仅搜索根目录
|
||||
excel-search-rust --dir ./data --keyword 关键词 --include-subdirectories=false
|
||||
|
||||
# 文件类型过滤:all | excel | word | csv
|
||||
excel-search-rust --dir ./data --keyword 关键词 --file-type excel
|
||||
|
||||
# 并发 worker 数(或环境变量 EXCEL_SEARCH_WORKERS)
|
||||
excel-search-rust --dir ./data --keyword 关键词 --workers 16
|
||||
```
|
||||
|
||||
> 完整单词边界提示:汉字属于字母,因此开启完整单词后搜「手机」**不会**命中
|
||||
> 「苹果手机壳」这类内部子串;默认(关闭)为模糊匹配则会命中。
|
||||
|
||||
## 桌面版用法
|
||||
|
||||
```bash
|
||||
# 双击运行,直接弹出原生窗口
|
||||
excel-search-rust-desktop.exe
|
||||
```
|
||||
|
||||
窗口布局与 Go 桌面版一致:目录/关键字(含历史下拉)、四个搜索选项、结果表格
|
||||
(虚拟滚动、列宽可拖拽、右键复制/打开文件)。差异是架构性的、也是更好的:
|
||||
|
||||
- **关窗即退出**:原生窗口生命周期与进程绑定,无心跳检测;
|
||||
- **搜索不阻塞界面**:搜索在后台线程执行,进行中可继续拖动窗口/改表单;
|
||||
慢目录不再被 30s 服务端超时掐断(Go 版行为);
|
||||
- **中文字体**:运行时加载系统 SimHei/楷体/仿宋(epaint 不支持 .ttc 集合字体)。
|
||||
|
||||
| 环境变量 | 默认值 | 说明 |
|
||||
|---|---|---|
|
||||
| `EXCEL_SEARCH_WORKERS` | `8` | 并发搜索线程数 |
|
||||
| `EXCEL_SEARCH_CACHE_DIR` | `.cache` | 搜索缓存目录 |
|
||||
|
||||
搜索历史写入 `.cache/search_history.json`(与 Go 桌面版同格式,可共用同一份历史)。
|
||||
|
||||
## 与 Go 版的差异
|
||||
|
||||
| 维度 | Go 版 | Rust 版 |
|
||||
|---|---|---|
|
||||
| 交付形态 | searcher CLI + WebUI + 桌面版(HTTP+Edge 窗口) | CLI + 桌面版(**原生 egui**,无 WebUI) |
|
||||
| Excel 格式 | xlsx/xlsm/xltx/xltm | 额外支持 xls/xlsb/ods |
|
||||
| 搜索取消/超时 | context 全链路(服务端 600s 超时) | CLI:Ctrl+C 直接终止;桌面:后台线程不阻塞 UI,无超时截断 |
|
||||
| 缓存 | JSON,版本 2 | 同 schema,条目可跨版本命中(已验证) |
|
||||
| 日志 | slog(text/json,含请求日志中间件) | CLI stderr `warn:` 行 |
|
||||
|
||||
## 设计文档(历史)
|
||||
|
||||
原始设计指南(体积优化 profile、calamine/rayon 选型)已随实现落地,
|
||||
关键决策保留在上文;`[profile.release]` 的 `opt-level="z"`、`lto`、`strip` 配置见 `Cargo.toml`。
|
||||
Reference in new issue
Block a user