From a0aaf9b71387e78bcf8e7b792f6ce89320660df8 Mon Sep 17 00:00:00 2001 From: wangdl Date: Sat, 30 May 2026 20:27:52 +0800 Subject: [PATCH] docs: app-rust-bridge - complete FFI call protocol --- docs/app-rust-bridge.md | 206 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 206 insertions(+) create mode 100644 docs/app-rust-bridge.md diff --git a/docs/app-rust-bridge.md b/docs/app-rust-bridge.md new file mode 100644 index 0000000..27738e4 --- /dev/null +++ b/docs/app-rust-bridge.md @@ -0,0 +1,206 @@ +# App ↔ Rust 调用协议 + +## 概述 + +本文档定义宿主 App(iOS/Android)与 Rust Core 之间的全部调用边界。 + +核心原则: + +```text +Rust Core 是纯计算层。 +不做网络请求、不保存 Token、不访问后端 API。 +文件由 App 下载到本地后,把路径交给 Rust。 +阅读事件由 Rust 生成,App 负责上传。 +``` + +--- + +## 调用方向 + +```text +App ──调用──→ Rust Core +App ←──返回── Rust Core +App ──上传──→ Backend API +``` + +--- + +## Rust 暴露给 App 的函数 + +### 1. 文件类型识别 + +```rust +fn detect_material_type(file_path: &str) -> Result +``` + +**输入**:本地文件路径 +**输出**:MaterialType 枚举值 +**用途**:App 据此决定使用哪种 PreviewMode + +### 2. 打开文档 + +```rust +fn open_document(file_path: &str, material_id: &str) -> Result +``` + +**输入**:本地文件路径 + 资料 ID +**输出**:DocumentHandle(不透明句柄,App 传递给后续函数) +**用途**:初始化文档解析,建立阅读会话 + +### 3. 获取文档信息 + +```rust +fn get_document_info(handle: &DocumentHandle) -> Result +``` + +**输出**:DocumentInfo(标题、类型、大小、页数、字数) +**用途**:App 展示资料详情 + +### 4. 获取 Markdown Blocks + +```rust +fn get_markdown_blocks(handle: &DocumentHandle) -> Result, DocumentError> +``` + +**输出**:DocumentBlock 列表 +**用途**:App 原生渲染 Markdown +**前置**:MaterialType 必须为 Markdown + +### 5. 获取文本内容 + +```rust +fn get_text_content(handle: &DocumentHandle) -> Result +``` + +**输出**:完整文本内容 +**用途**:App 原生渲染纯文本 +**前置**:MaterialType 必须为 Text + +### 6. 获取图片 Metadata + +```rust +fn get_image_meta(file_path: &str) -> Result +``` + +**输出**:width, height, format, file_size +**用途**:App 展示图片信息 +**前置**:MaterialType 必须为 Image + +### 7. 搜索文档 + +```rust +fn search_document(handle: &DocumentHandle, query: &str) -> Result, DocumentError> +``` + +**输入**:搜索关键词 +**输出**:SearchResult 列表(block_id, snippet, match range) +**用途**:App 展示搜索结果 +**支持**:Markdown、TXT + +### 8. 更新阅读位置 + +```rust +fn update_reading_position(material_id: &str, position: ReadingPosition) +``` + +**输入**:资料 ID + 阅读位置 +**用途**:记录用户当前读到的位置,用于继续阅读 + +### 9. 导出阅读事件 + +```rust +fn export_pending_events() -> Vec +``` + +**输出**:所有未导出的阅读事件列表 +**用途**:App 定期拉取事件并上传到后端 + +### 10. 清空已导出事件 + +```rust +fn clear_exported_events(count: usize) +``` + +**用途**:确认前 count 条事件已成功上传,从缓冲区移除 + +### 11. 创建笔记锚点 + +```rust +fn create_note_anchor(material_id: &str, position: Option) -> NoteAnchor +``` + +**输出**:NoteAnchor +**用途**:关联笔记到资料的具体位置 + +--- + +## Rust 不提供的函数(由 App 负责) + +以下函数**不存在于 Rust Core**,完全由宿主 App 实现: + +| App 职责 | 说明 | +|---------|------| +| `download_file(url)` | COS 下载 → 本地沙盒 | +| `upload_reading_events(events)` | POST 到 /reading/events | +| `save_note_to_backend(note)` | POST 到 /notes | +| `call_ai_chat(prompt)` | 调 AI API | +| `share_file(material_id)` | 系统分享面板 | +| `delete_material(material_id)` | 调后端删除接口 | +| `get_user_token()` | Token 管理 | +| `open_system_preview(file_path)` | QuickLook / 系统预览 | + +--- + +## 调用时序 + +### 打开并阅读 Markdown + +```text +1. App: download_file(cos_url) → /tmp/doc.md +2. App: detect_material_type("/tmp/doc.md") → Markdown +3. App: open_document("/tmp/doc.md", "abc123") → handle +4. App: get_document_info(handle) → DocumentInfo +5. App: get_markdown_blocks(handle) → [Block] +6. App: 渲染 blocks +7. 用户滚动 → App: update_reading_position("abc123", pos) +8. 定时器 → App: export_pending_events() → [events] +9. App: POST /reading/events +10. App: clear_exported_events(n) +11. 用户关闭 → App: export_pending_events() → last events +12. App: POST /reading/events +13. App: clear_exported_events(n) +``` + +### 打开 PDF(平台预览) + +```text +1. App: download_file(cos_url) → /tmp/doc.pdf +2. App: detect_material_type("/tmp/doc.pdf") → Pdf +3. App: 判断 PreviewMode::PlatformPreview +4. App: open_system_preview("/tmp/doc.pdf") // QuickLook +5. App: 监听页码变化 → 转换为 PdfReadingPosition +6. App: update_reading_position("abc123", pos) +7. 同上导出事件流程 +``` + +--- + +## 错误处理约定 + +所有函数返回 `Result`: + +| 错误 | 场景 | App 处理 | +|------|------|---------| +| FileNotFound | 文件路径不存在 | 提示用户重新下载 | +| UnsupportedFormat | 无法识别的格式 | 显示"暂不支持" | +| ParseError | 文件内容损坏 | 显示"文件异常" | +| InvalidEncoding | 非 UTF-8 | 尝试其他编码或提示 | +| IoError | 磁盘错误 | 重试或提示 | + +--- + +## 线程安全 + +- Rust Core 的函数应在**后台线程**调用 +- App 主线程只做 UI 渲染 +- `export_pending_events` 和 `clear_exported_events` 内部需要 Mutex 保护