- Architecture: Swift→uniffi C-ABI→Rust FFI→core - Type mapping: Rust struct/enum ↔ Swift Record/Enum - Core API reference: document parsing, search, anchors, V2 sessions - Error handling, thread safety, performance recommendations Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
6.2 KiB
6.2 KiB
Document Runtime iOS FFI 调用指南
1. 概述
Document Runtime(zx_document_core)通过 UniFFI 生成 C-ABI 兼容的 Swift 绑定,嵌入 iOS 应用作为 ZxDocumentRuntime.xcframework。
Swift 层通过 uniffi 生成的 zx_document.swift 调用所有 Rust 功能。
2. 架构
┌──────────────────────────────────────┐
│ iOS Swift │
│ zx_document.swift (uniffi 生成) │
│ ├─ buildDocumentInfo() │
│ ├─ parseMarkdown() │
│ ├─ extractPdfText() │
│ ├─ extractEpubChapterTexts() │
│ ├─ searchBlocks() / searchText() │
│ ├─ resolveNoteAnchors() │
│ ├─ startReadingSessionV2() │
│ ├─ pushHeartbeatV2() │
│ ├─ exportPending() / ackExported() │
│ └─ ... │
└──────────────┬───────────────────────┘
│ C-ABI (uniffi)
┌──────────────▼───────────────────────┐
│ Rust: zx_document_ffi │
│ lib.rs — #[uniffi::export] fns │
└──────────────┬───────────────────────┘
│
┌──────────────▼───────────────────────┐
│ Rust: zx_document_core │
│ document / markdown / pdf / epub / │
│ search / anchors / events_v2 / ... │
└──────────────────────────────────────┘
3. 类型映射
3.1 基础类型
| Rust | Swift |
|---|---|
String |
String |
u32 / u64 |
UInt32 / UInt64 |
i64 |
Int64 |
bool |
Bool |
Vec<T> |
[T] |
Option<T> |
T? |
Result<T, E> |
throws |
3.2 结构体 → Record
#[derive(uniffi::Record)]
pub struct DocumentInfo { ... }
// uniffi 生成
public struct DocumentInfo {
public var materialId: String
public var title: String
public var materialType: MaterialType
// ...
}
3.3 枚举 → Enum
#[derive(uniffi::Enum)]
pub enum MaterialType { Markdown, Text, Pdf, Image, Epub, Word, Excel, PowerPoint, Unknown }
public enum MaterialType {
case markdown, text, pdf, image, epub, word, excel, powerPoint, unknown
}
4. 核心 API
4.1 文档解析
// 构建文档信息(文件类型检测 + 元数据提取)
let info = try buildDocumentInfo(
filePath: "/path/to/file.md",
materialId: "mat-001",
title: "My Document"
)
// → DocumentInfo { materialType, pageCount, wordCount, epubChapterCount, ... }
// Markdown 解析为块
let blocks = try parseMarkdown(markdown: "# Title\n\nContent")
// → [DocumentBlock]
// PDF 元数据
let pdfMeta = try readPdfMetadata(filePath: "/path/to/book.pdf")
// → PdfMetadata { pageCount, title, author }
// PDF 文本提取
let pages = try extractPdfText(filePath: "/path/to/book.pdf")
// → [PdfPageText { pageNumber, text }]
// EPUB 元数据
let epubMeta = try readEpubMetadata(filePath: "/path/to/book.epub")
// → EpubMetadata { title, author, chapterCount }
// EPUB 章节文本提取(HTML strip)
let chapters = try extractEpubChapterTexts(filePath: "/path/to/book.epub")
// → [EpubChapterText { chapterId, text }]
4.2 搜索
// 搜索 Markdown 块
let results = searchBlocks(blocks: blocks, query: "keyword")
// → [SearchResult { blockId, snippet, matchStart, matchEnd }]
// 搜索纯文本
let textResults = searchText(content: text, query: "keyword")
// → [SearchResult { lineNumber, ... }]
4.3 锚点
let anchors = try resolveNoteAnchors(
blocks: blocks,
anchorHints: ["#heading-1", "#paragraph-2"]
)
// → [NoteAnchor { anchorId, blockId, ... }]
4.4 V2 阅读会话
// 开始会话
let sessionId = try startReadingSessionV2(
material: ReadingMaterialRefV2(materialId: "mat-001"),
timestampMs: Int64(Date().timeIntervalSince1970 * 1000)
)
// 推送位置变更事件
try pushPositionChangedV2(
sessionId: sessionId,
position: ReadingPosition.markdown(
blockId: "b1",
scrollProgress: 0.5
),
timestampMs: nowMs()
)
// 导出待上传事件
let (events, state) = exportPendingV2()
// → ([BufferedReadingEventV2], EventBufferStateV2)
// ACK 已上传事件
ackExportedV2(count: UInt32(events.count))
// 关闭会话
try closeReadingSessionV2(sessionId: sessionId, timestampMs: nowMs())
5. 错误处理
所有 FFI 函数返回 Result<T, String>(UniFFI 映射为 Swift throws):
do {
let info = try buildDocumentInfo(filePath: path, materialId: id, title: title)
// 使用 info
} catch {
print("Document Runtime error: \(error)")
// error 是 Rust DocumentError 的 Display 字符串
}
常见错误:
IoError— 文件不存在/无权限ParseError— 格式损坏/不支持的格式MarkdownParseError— Markdown 语法错误
6. 线程安全
- Rust 层使用
Mutex<Vec<T>>保护全局状态(EventBuffer) - 所有 FFI 函数可从任意线程调用
- Swift 层应在主线程调用 UI 更新,后台线程调用 FFI
7. 性能建议
| 操作 | 建议 |
|---|---|
buildDocumentInfo |
主线程调用(< 50ms),缓存结果 |
extractPdfText |
后台线程(可能耗时数秒) |
parseMarkdown |
任意线程(< 10ms) |
searchBlocks |
任意线程(< 10ms) |
exportPendingV2 |
后台定时器(30s),主线程调用也可 |
8. 相关文档
- V2 事件 Pipeline 架构(ios-projects 仓库)
- Rust FFI 绑定更新流程(ios-projects 仓库)
- UniFFI UDL 编写规范
- 文件格式支持矩阵