Architecture
分层架构
┌──────────────────────────────────────────────┐
│ iOS / Android / 鸿蒙 / macOS / Windows / Web │ ← 宿主 App
├──────────────────────────────────────────────┤
│ UniFFI proc-macro C-ABI bridge │ ← zx_document_ffi
├──────────────────────────────────────────────┤
│ zx_document_core (Rust) │ ← 核心逻辑
│ ├─ file_type 文件类型识别 │
│ ├─ markdown MD 解析为 DocumentBlock │
│ ├─ text TXT 读取 │
│ ├─ image_meta 图片 metadata │
│ ├─ epub EPUB 结构解析 │
│ ├─ pdf PDF 位置模型 │
│ ├─ progress ReadingPosition │
│ ├─ events ReadingEvent │
│ ├─ search 基础搜索 │
│ └─ anchors NoteAnchor │
└──────────────────────────────────────────────┘
职责边界
Rust Core 负责
| 模块 |
职责 |
| 文件类型识别 |
根据 magic bytes → MIME → 扩展名判断 MaterialType |
| Markdown 解析 |
读取 .md 文件,输出 DocumentBlock 列表 |
| TXT 读取 |
读取 .txt 文件,输出段落/行 block |
| 图片 metadata |
读取宽高、格式、文件大小 |
| 阅读位置 |
提供统一的 ReadingPosition(跨格式) |
| 阅读事件 |
生成 MaterialOpened/Closed/PositionChanged/Heartbeat 事件 |
| 搜索 |
大小写不敏感,返回 block/snippet |
| 笔记锚点 |
从 ReadingPosition 生成 NoteAnchor |
| FFI 绑定 |
通过 proc-macro (#[uniffi::export]) + UDL bindgen 暴露 API 给 Swift/Kotlin |
宿主 App 负责
| 模块 |
职责 |
| 网络请求 |
COS 下载、API 调用、事件上报 |
| Token 管理 |
用户登录、JWT 存储 |
| UI 渲染 |
SwiftUI/Compose 渲染 DocumentBlock |
| 系统预览 |
PDF/Office 通过 PDFKit/QuickLook 预览 |
| 文件选择 |
系统文件选择器 |
| 分享/删除 |
系统分享面板、文件管理 |
Rust Core 明确不负责
- 不做网络请求
- 不保存 Token
- 不直接访问后端 API
- 不做 AI / RAG 解析
- 不做向量化
- 不做 Office 高保真预览
- 不做 OCR
- 不做 PDF 标注
- 不做富文本编辑器
- 不做完整 UI
数据流
1. App 下载文件到本地(COS → 沙盒)
2. App 调用 detect_material_type(file_path)
3. 根据 MaterialType 决定预览方式:
- NativeReader → 调用 open_document → get_xxx_blocks → 原生渲染
- PlatformPreview → iOS QuickLook / Android 系统预览
- ExternalOpen → 打开外部 App
4. 阅读过程中 App 调用 update_reading_position / heartbeat
5. App 定期调用 export_pending_events → 上传到后端
Crate 拆分
| Crate |
类型 |
用途 |
| zx_document_core |
library |
核心 Rust 逻辑,纯计算 |
| zx_document_ffi |
library |
UniFFI proc-macro 绑定(#[uniffi::export] + UDL bindgen) |
| xtask |
binary |
构建脚本,生成 binding,打包 artifact |