From d046658a05b071fd835292d6f1e1ea3d727b2ca2 Mon Sep 17 00:00:00 2001 From: EYHN Date: Fri, 3 Jan 2025 20:24:48 +0800 Subject: [PATCH] dev --- Cargo.lock | 14 + packages/common/env/src/ua-helper.ts | 3 + .../nbstore/src/__tests__/frontend.spec.ts | 2 +- .../nbstore/src/connection/connection.ts | 1 + packages/common/nbstore/src/storage/doc.ts | 50 +- .../apps/electron-renderer/src/worker.ts | 1 + .../ios/App/App.xcodeproj/project.pbxproj | 10 +- .../App/Plugins/NBStore/NBStorePlugin.swift | 653 +++---- .../App/App/uniffi/affine_mobile_native.swift | 1557 ++++++++--------- .../App/App/uniffi/affine_mobile_nativeFFI.h | 18 +- .../apps/ios/App/xc-universal-binary.sh | 6 +- packages/frontend/apps/ios/src/app.tsx | 12 +- .../ios/src/plugins/nbstore/definitions.ts | 9 +- .../apps/ios/src/plugins/nbstore/index.ts | 25 +- packages/frontend/apps/ios/src/setup.ts | 6 +- packages/frontend/apps/ios/src/worker.ts | 14 +- packages/frontend/apps/mobile/src/worker.ts | 1 + packages/frontend/apps/web/src/worker.ts | 1 + .../core/src/bootstrap/polyfill/browser.ts | 9 +- .../core/src/bootstrap/polyfill/dispose.ts | 10 +- .../bootstrap/polyfill/iterator-helpers.ts | 8 +- .../polyfill/promise-with-resolvers.ts | 7 +- .../polyfill/request-idle-callback.ts | 8 +- .../src/bootstrap/polyfill/resize-observer.ts | 4 +- packages/frontend/mobile-native/Cargo.toml | 2 +- packages/frontend/mobile-native/src/lib.rs | 105 +- packages/frontend/native/nbstore/src/doc.rs | 3 +- packages/frontend/native/nbstore/src/pool.rs | 6 +- .../frontend/native/nbstore/src/storage.rs | 3 +- 29 files changed, 1295 insertions(+), 1253 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 71908a53c0c7c..a9b7f88dcd72e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -275,6 +275,19 @@ dependencies = [ "nom", ] +[[package]] +name = "async-compat" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7bab94bde396a3f7b4962e396fdad640e241ed797d4d8d77fc8c237d14c58fc0" +dependencies = [ + "futures-core", + "futures-io", + "once_cell", + "pin-project-lite", + "tokio", +] + [[package]] name = "async-lock" version = "3.4.0" @@ -2942,6 +2955,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bc7687007d2546c454d8ae609b105daceb88175477dac280707ad6d95bcd6f1f" dependencies = [ "anyhow", + "async-compat", "bytes", "log", "once_cell", diff --git a/packages/common/env/src/ua-helper.ts b/packages/common/env/src/ua-helper.ts index 1e458bacc6abf..9984bfb8a500f 100644 --- a/packages/common/env/src/ua-helper.ts +++ b/packages/common/env/src/ua-helper.ts @@ -32,6 +32,9 @@ export class UaHelper { } private isStandaloneMode() { + if (typeof window === 'undefined') { + return false; + } if ('standalone' in window.navigator) { return !!window.navigator.standalone; } diff --git a/packages/common/nbstore/src/__tests__/frontend.spec.ts b/packages/common/nbstore/src/__tests__/frontend.spec.ts index 149d9628df0d5..b0e5357e74e4a 100644 --- a/packages/common/nbstore/src/__tests__/frontend.spec.ts +++ b/packages/common/nbstore/src/__tests__/frontend.spec.ts @@ -9,8 +9,8 @@ import { DocFrontend } from '../frontend/doc'; import { BroadcastChannelAwarenessStorage } from '../impls/broadcast-channel/awareness'; import { IndexedDBDocStorage } from '../impls/idb'; import { AwarenessSyncImpl } from '../sync/awareness'; -import { expectYjsEqual } from './utils'; import { DocSyncImpl } from '../sync/doc'; +import { expectYjsEqual } from './utils'; test('doc', async () => { const doc1 = new YDoc({ diff --git a/packages/common/nbstore/src/connection/connection.ts b/packages/common/nbstore/src/connection/connection.ts index cd15248d32624..8ceea47e11ab1 100644 --- a/packages/common/nbstore/src/connection/connection.ts +++ b/packages/common/nbstore/src/connection/connection.ts @@ -92,6 +92,7 @@ export abstract class AutoReconnectConnection }) .catch(error => { if (!this.connectingAbort?.signal.aborted) { + console.error('failed to connect', error); this.setStatus('error', error as any); } }); diff --git a/packages/common/nbstore/src/storage/doc.ts b/packages/common/nbstore/src/storage/doc.ts index 1ee542590ddbb..86919b0303ca5 100644 --- a/packages/common/nbstore/src/storage/doc.ts +++ b/packages/common/nbstore/src/storage/doc.ts @@ -112,38 +112,44 @@ export abstract class DocStorageBase } async getDoc(docId: string) { - await using _lock = this.isReadonly + const lock = this.isReadonly ? undefined : await this.lockDocForUpdate(docId); - const snapshot = await this.getDocSnapshot(docId); - const updates = await this.getDocUpdates(docId); + try { + const snapshot = await this.getDocSnapshot(docId); + const updates = await this.getDocUpdates(docId); - if (updates.length) { - const { timestamp, bin, editor } = await this.squash( - snapshot ? [snapshot, ...updates] : updates - ); + if (updates.length) { + const { timestamp, bin, editor } = await this.squash( + snapshot ? [snapshot, ...updates] : updates + ); - const newSnapshot = { - spaceId: this.spaceId, - docId, - bin, - timestamp, - editor, - }; + const newSnapshot = { + spaceId: this.spaceId, + docId, + bin, + timestamp, + editor, + }; - // if is readonly, we will not set the new snapshot - if (!this.isReadonly) { - await this.setDocSnapshot(newSnapshot, snapshot); + // if is readonly, we will not set the new snapshot + if (!this.isReadonly) { + await this.setDocSnapshot(newSnapshot, snapshot); - // always mark updates as merged unless throws - await this.markUpdatesMerged(docId, updates); + // always mark updates as merged unless throws + await this.markUpdatesMerged(docId, updates); + } + + return newSnapshot; } - return newSnapshot; + return snapshot; + } finally { + if (lock) { + await lock[Symbol.asyncDispose](); + } } - - return snapshot; } async getDocDiff(docId: string, state?: Uint8Array) { diff --git a/packages/frontend/apps/electron-renderer/src/worker.ts b/packages/frontend/apps/electron-renderer/src/worker.ts index 4253a53a3946a..703cc624d5a75 100644 --- a/packages/frontend/apps/electron-renderer/src/worker.ts +++ b/packages/frontend/apps/electron-renderer/src/worker.ts @@ -1,3 +1,4 @@ +import '@affine/core/bootstrap/electron'; import { getElectronAPIs } from '@affine/electron-api/web-worker'; import { WorkerConsumer, diff --git a/packages/frontend/apps/ios/App/App.xcodeproj/project.pbxproj b/packages/frontend/apps/ios/App/App.xcodeproj/project.pbxproj index 3e0dd1d5376ce..780df167b6626 100644 --- a/packages/frontend/apps/ios/App/App.xcodeproj/project.pbxproj +++ b/packages/frontend/apps/ios/App/App.xcodeproj/project.pbxproj @@ -24,8 +24,8 @@ 9D90BE2B2CCB9876006677DB /* config.xml in Resources */ = {isa = PBXBuildFile; fileRef = 9D90BE1F2CCB9876006677DB /* config.xml */; }; 9D90BE2D2CCB9876006677DB /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 9D90BE222CCB9876006677DB /* Main.storyboard */; }; 9D90BE2E2CCB9876006677DB /* public in Resources */ = {isa = PBXBuildFile; fileRef = 9D90BE232CCB9876006677DB /* public */; }; + 9DFCD1462D27D1D70028C92B /* libaffine_mobile_native.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 9DFCD1452D27D1D70028C92B /* libaffine_mobile_native.a */; }; C4C413792CBE705D00337889 /* Pods_App.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF277DCFFFF123FFC6DF26C7 /* Pods_App.framework */; }; - C4C97C6E2D0304D100BC2AD1 /* libaffine_mobile_native.a in Frameworks */ = {isa = PBXBuildFile; fileRef = C4C97C6D2D0304D100BC2AD1 /* libaffine_mobile_native.a */; }; C4C97C7C2D030BE000BC2AD1 /* affine_mobile_native.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4C97C6F2D0307B700BC2AD1 /* affine_mobile_native.swift */; }; C4C97C7D2D030BE000BC2AD1 /* affine_mobile_nativeFFI.h in Sources */ = {isa = PBXBuildFile; fileRef = C4C97C702D0307B700BC2AD1 /* affine_mobile_nativeFFI.h */; }; C4C97C7E2D030BE000BC2AD1 /* affine_mobile_nativeFFI.modulemap in Sources */ = {isa = PBXBuildFile; fileRef = C4C97C712D0307B700BC2AD1 /* affine_mobile_nativeFFI.modulemap */; }; @@ -51,10 +51,10 @@ 9D90BE202CCB9876006677DB /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 9D90BE212CCB9876006677DB /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 9D90BE232CCB9876006677DB /* public */ = {isa = PBXFileReference; lastKnownFileType = folder; path = public; sourceTree = ""; }; + 9DFCD1452D27D1D70028C92B /* libaffine_mobile_native.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libaffine_mobile_native.a; sourceTree = ""; }; AF277DCFFFF123FFC6DF26C7 /* Pods_App.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_App.framework; sourceTree = BUILT_PRODUCTS_DIR; }; AF51FD2D460BCFE21FA515B2 /* Pods-App.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-App.release.xcconfig"; path = "Pods/Target Support Files/Pods-App/Pods-App.release.xcconfig"; sourceTree = ""; }; - C4C97C6B2D03027900BC2AD1 /* libaffine_mobile_native.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libaffine_mobile_native.a; path = "../../../../../target/aarch64-apple-ios-sim/release/libaffine_mobile_native.a"; sourceTree = ""; }; - C4C97C6D2D0304D100BC2AD1 /* libaffine_mobile_native.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libaffine_mobile_native.a; sourceTree = ""; }; + C4C97C6B2D03027900BC2AD1 /* libaffine_mobile_native.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libaffine_mobile_native.a; path = "../../../../../target/aarch64-apple-ios-sim/debug/libaffine_mobile_native.a"; sourceTree = ""; }; C4C97C6F2D0307B700BC2AD1 /* affine_mobile_native.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = affine_mobile_native.swift; sourceTree = ""; }; C4C97C702D0307B700BC2AD1 /* affine_mobile_nativeFFI.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = affine_mobile_nativeFFI.h; sourceTree = ""; }; C4C97C712D0307B700BC2AD1 /* affine_mobile_nativeFFI.modulemap */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.module-map"; path = affine_mobile_nativeFFI.modulemap; sourceTree = ""; }; @@ -71,8 +71,8 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - C4C97C6E2D0304D100BC2AD1 /* libaffine_mobile_native.a in Frameworks */, 50A285DC2D112B24000D5A6D /* Intelligents in Frameworks */, + 9DFCD1462D27D1D70028C92B /* libaffine_mobile_native.a in Frameworks */, 50802D612D112F8700694021 /* Intelligents in Frameworks */, C4C413792CBE705D00337889 /* Pods_App.framework in Frameworks */, ); @@ -85,8 +85,8 @@ isa = PBXGroup; children = ( C4C97C6B2D03027900BC2AD1 /* libaffine_mobile_native.a */, - C4C97C6D2D0304D100BC2AD1 /* libaffine_mobile_native.a */, AF277DCFFFF123FFC6DF26C7 /* Pods_App.framework */, + 9DFCD1452D27D1D70028C92B /* libaffine_mobile_native.a */, ); name = Frameworks; sourceTree = ""; diff --git a/packages/frontend/apps/ios/App/App/Plugins/NBStore/NBStorePlugin.swift b/packages/frontend/apps/ios/App/App/Plugins/NBStore/NBStorePlugin.swift index d7d656946caa2..fd7120277ee7e 100644 --- a/packages/frontend/apps/ios/App/App/Plugins/NBStore/NBStorePlugin.swift +++ b/packages/frontend/apps/ios/App/App/Plugins/NBStore/NBStorePlugin.swift @@ -3,7 +3,7 @@ import Foundation @objc(NbStorePlugin) public class NbStorePlugin: CAPPlugin, CAPBridgedPlugin { - private let docStoragePool: DocStoragePool = .init(noPointer: DocStoragePool.NoPointer()) + private let docStoragePool: DocStoragePool = newDocStoragePool() public let identifier = "NbStorePlugin" public let jsName = "NbStoreDocStorage" @@ -35,386 +35,443 @@ public class NbStorePlugin: CAPPlugin, CAPBridgedPlugin { CAPPluginMethod(name: "clearClocks", returnType: CAPPluginReturnPromise), ] - @objc func connect(_ call: CAPPluginCall) async { - do { - try let id = call.getStringEnsure("id") - try let spaceId = call.getStringEnsure("spaceId") - try let spaceType = call.getStringEnsure("spaceType") - try let peer = call.getStringEnsure("peer") - guard var documentDir = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first else { - call.reject("Failed to get document file urls") + @objc func connect(_ call: CAPPluginCall) { + Task { + do { + let id = try call.getStringEnsure("id") + let spaceId = try call.getStringEnsure("spaceId") + let spaceType = try call.getStringEnsure("spaceType") + let peer = try call.getStringEnsure("peer") + guard let documentDir = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first else { + call.reject("Failed to get document file urls") + return + } + let peerDir = documentDir.appending(path: "workspaces") + .appending(path: spaceType) + .appending(path: + peer + .replacing(#/[\/!@#$%^&*()+~`"':;,?<>|]/#, with: "_") + .replacing(/_+/, with: "_") + .replacing(/_+$/, with: "")) + try FileManager.default.createDirectory(atPath: peerDir.path(), withIntermediateDirectories: true) + let db = peerDir.appending(path: spaceId + ".db") + try await docStoragePool.connect(universalId: id, path: db.path()) + call.resolve() + } catch { + call.reject("Failed to connect storage, \(error)", nil, error) } - documentDir.append(path: "workspaces") - documentDir.append(path: spaceType) - documentDir.append(path: - peer - .replacing(#/[\/!@#$%^&*()+~`"':;,?<>|]/#, with: "_") - .replacing(/_+/, with: "_") - .replacing(/_+$/, with: "")) - documentDir.append(path: spaceId) - try await docStoragePool.connect(universalId: id, path: documentDir.path()) - call.resolve() - } catch { - call.reject("Failed to connect storage", nil, error) } } - @objc func disconnect(_ call: CAPPluginCall) async { - do { - try let id = call.getStringEnsure("id") - try await docStoragePool.disconnect(universalId: id) - call.resolve() - } catch { - call.reject("Failed to disconnect", nil, error) + @objc func disconnect(_ call: CAPPluginCall) { + Task { + do { + let id = try call.getStringEnsure("id") + try await docStoragePool.disconnect(universalId: id) + call.resolve() + } catch { + call.reject("Failed to disconnect, \(error)", nil, error) + } } } - @objc func setSpaceId(_ call: CAPPluginCall) async { - do { - try let id = call.getStringEnsure("id") - try let spaceId = call.getStringEnsure("spaceId") - try await docStoragePool.setSpaceId(universalId: id, spaceId: spaceId) - call.resolve() - } catch { - call.reject("Failed to set space id", nil, error) + @objc func setSpaceId(_ call: CAPPluginCall) { + Task { + do { + let id = try call.getStringEnsure("id") + let spaceId = try call.getStringEnsure("spaceId") + try await docStoragePool.setSpaceId(universalId: id, spaceId: spaceId) + call.resolve() + } catch { + call.reject("Failed to set space id, \(error)", nil, error) + } } } - @objc func pushUpdate(_ call: CAPPluginCall) async { - do { - try let id = call.getStringEnsure("id") - try let docId = call.getStringEnsure("docId") - try let data = call.getStringEnsure("data") - let timestamp = try await docStoragePool.pushUpdate(universalId: id, docId: docId, update: data) - call.resolve(["timestamp": timestamp.timeIntervalSince1970]) - } catch { - call.reject("Failed to push update", nil, error) + @objc func pushUpdate(_ call: CAPPluginCall) { + Task { + do { + let id = try call.getStringEnsure("id") + let docId = try call.getStringEnsure("docId") + let data = try call.getStringEnsure("data") + let timestamp = try await docStoragePool.pushUpdate(universalId: id, docId: docId, update: data) + call.resolve(["timestamp": timestamp]) + } catch { + call.reject("Failed to push update, \(error)", nil, error) + } } } - @objc func getDocSnapshot(_ call: CAPPluginCall) async { - do { - try let id = call.getStringEnsure("id") - try let docId = call.getStringEnsure("docId") - - if let record = try await docStoragePool.getDocSnapshot(universalId: id, docId: docId) { - call.resolve([ - "docId": record.docId, - "bin": record.bin, - "timestamp": record.timestamp.timeIntervalSince1970, - ]) - } else { - call.resolve() + @objc func getDocSnapshot(_ call: CAPPluginCall) { + Task { + do { + let id = try call.getStringEnsure("id") + let docId = try call.getStringEnsure("docId") + + if let record = try await docStoragePool.getDocSnapshot(universalId: id, docId: docId) { + call.resolve([ + "docId": record.docId, + "bin": record.bin, + "timestamp": record.timestamp, + ]) + } else { + call.resolve() + } + } catch { + call.reject("Failed to get doc snapshot, \(error)", nil, error) } - } catch { - call.reject("Failed to get doc snapshot", nil, error) } } - @objc func setDocSnapshot(_ call: CAPPluginCall) async { - do { - try let id = call.getStringEnsure("id") - try let docId = call.getStringEnsure("docId") - try let bin = call.getStringEnsure("bin") - let timestamp = Date() - let success = try await docStoragePool.setDocSnapshot( - universalId: id, - snapshot: DocRecord(docId: docId, bin: bin, timestamp: timestamp) - ) - call.resolve(["success": success]) - } catch { - call.reject("Failed to set doc snapshot", nil, error) + @objc func setDocSnapshot(_ call: CAPPluginCall) { + Task { + do { + let id = try call.getStringEnsure("id") + let docId = try call.getStringEnsure("docId") + let bin = try call.getStringEnsure("bin") + let timestamp = try call.getIntEnsure("timestamp") + let success = try await docStoragePool.setDocSnapshot( + universalId: id, + snapshot: DocRecord(docId: docId, bin: bin, timestamp: Int64(timestamp)) + ) + call.resolve(["success": success]) + } catch { + call.reject("Failed to set doc snapshot, \(error)", nil, error) + } } } - @objc func getDocUpdates(_ call: CAPPluginCall) async { - do { - try let id = call.getStringEnsure("id") - try let docId = call.getStringEnsure("docId") - let updates = try await docStoragePool.getDocUpdates(universalId: id, docId: docId) - let mapped = updates.map { [ - "docId": $0.docId, - "timestamp": $0.timestamp.timeIntervalSince1970, - "bin": $0.bin, - ] } - call.resolve(["updates": mapped]) - } catch { - call.reject("Failed to get doc updates", nil, error) + @objc func getDocUpdates(_ call: CAPPluginCall) { + Task { + do { + let id = try call.getStringEnsure("id") + let docId = try call.getStringEnsure("docId") + let updates = try await docStoragePool.getDocUpdates(universalId: id, docId: docId) + let mapped = updates.map { [ + "docId": $0.docId, + "timestamp": $0.timestamp, + "bin": $0.bin, + ] } + call.resolve(["updates": mapped]) + } catch { + call.reject("Failed to get doc updates, \(error)", nil, error) + } } } - @objc func markUpdatesMerged(_ call: CAPPluginCall) async { - do { - try let id = call.getStringEnsure("id") - try let docId = call.getStringEnsure("docId") - try let times = call.getArrayEnsure("timestamps", Double.self) - let dateArray = times.map { Date(timeIntervalSince1970: $0) } - - let count = try await docStoragePool.markUpdatesMerged(universalId: id, docId: docId, updates: dateArray) - call.resolve(["count": count]) - } catch { - call.reject("Failed to mark updates merged", nil, error) + @objc func markUpdatesMerged(_ call: CAPPluginCall) { + Task { + do { + let id = try call.getStringEnsure("id") + let docId = try call.getStringEnsure("docId") + let times = try call.getArrayEnsure("timestamps", Int64.self) + + let count = try await docStoragePool.markUpdatesMerged(universalId: id, docId: docId, updates: times) + call.resolve(["count": count]) + } catch { + call.reject("Failed to mark updates merged, \(error)", nil, error) + } } } - @objc func deleteDoc(_ call: CAPPluginCall) async { - do { - try let id = call.getStringEnsure("id") - try let docId = call.getStringEnsure("docId") - - try await docStoragePool.deleteDoc(universalId: id, docId: docId) - call.resolve() - } catch { - call.reject("Failed to delete doc", nil, error) + @objc func deleteDoc(_ call: CAPPluginCall) { + Task { + do { + let id = try call.getStringEnsure("id") + let docId = try call.getStringEnsure("docId") + + try await docStoragePool.deleteDoc(universalId: id, docId: docId) + call.resolve() + } catch { + call.reject("Failed to delete doc, \(error)", nil, error) + } } } - @objc func getDocClocks(_ call: CAPPluginCall) async { - do { - try let id = call.getStringEnsure("id") - try let after = call.getInt("after") - - let docClocks = try await docStoragePool.getDocClocks( - universalId: id, - after: after != nil ? Date(timeIntervalSince1970: TimeInterval(after!)) : nil - ) - let mapped = docClocks.map { [ - "docId": $0.docId, - "timestamp": $0.timestamp.timeIntervalSince1970, - ] } - call.resolve(["clocks": mapped]) - } catch { - call.reject("Failed to get doc clocks", nil, error) + @objc func getDocClocks(_ call: CAPPluginCall) { + Task { + do { + let id = try call.getStringEnsure("id") + let after = call.getInt("after") + + let docClocks = try await docStoragePool.getDocClocks( + universalId: id, + after: after != nil ? Int64(after!) : nil + ) + let mapped = docClocks.map { [ + "docId": $0.docId, + "timestamp": $0.timestamp, + ] } + call.resolve(["clocks": mapped]) + } catch { + call.reject("Failed to get doc clocks, \(error)", nil, error) + } } } - @objc func getDocClock(_ call: CAPPluginCall) async { - do { - try let id = call.getStringEnsure("id") - try let docId = call.getString("docId") - if let docClock = try await docStoragePool.getDocClock(universalId: id, docId: docId) { - call.resolve([ - "docId": docClock.docId, - "timestamp": docClock.timestamp.timeIntervalSince1970, - ]) - } else { - call.resolve() + @objc func getDocClock(_ call: CAPPluginCall) { + Task { + do { + let id = try call.getStringEnsure("id") + let docId = try call.getStringEnsure("docId") + if let docClock = try await docStoragePool.getDocClock(universalId: id, docId: docId) { + call.resolve([ + "docId": docClock.docId, + "timestamp": docClock.timestamp, + ]) + } else { + call.resolve() + } + } catch { + call.reject("Failed to get doc clock, \(error)", nil, error) } - } catch { - call.reject("Failed to get doc clock for docId: \(docId)", nil, error) } } - @objc func getBlob(_ call: CAPPluginCall) async { - do { - try let id = call.getStringEnsure("id") - try let key = call.getStringEnsure("key") - if let blob = try await docStoragePool.getBlob(universalId: id, key: key) { - call.resolve(["blob": blob]) - } else { - call.resolve() + @objc func getBlob(_ call: CAPPluginCall) { + Task { + do { + let id = try call.getStringEnsure("id") + let key = try call.getStringEnsure("key") + if let blob = try await docStoragePool.getBlob(universalId: id, key: key) { + call.resolve(["blob":[ + "key": blob.key, + "data": blob.data, + "mime": blob.mime, + "size": blob.size, + "createdAt": blob.createdAt + ]]) + } else { + call.resolve() + } + } catch { + call.reject("Failed to get blob, \(error)", nil, error) } - } catch { - call.reject("Failed to get blob", nil, error) } } - @objc func setBlob(_ call: CAPPluginCall) async { - do { - try let id = call.getStringEnsure("id") - try let key = call.getStringEnsure("key") - try let data = call.getStringEnsure("data") - try let mime = call.getStringEnsure("mime") - try await docStoragePool.setBlob(universalId: id, blob: SetBlob(key: key, data: data, mime: mime)) - } catch { - call.reject("Failed to set blob", nil, error) + @objc func setBlob(_ call: CAPPluginCall) { + Task { + do { + let id = try call.getStringEnsure("id") + let key = try call.getStringEnsure("key") + let data = try call.getStringEnsure("data") + let mime = try call.getStringEnsure("mime") + try await docStoragePool.setBlob(universalId: id, blob: SetBlob(key: key, data: data, mime: mime)) + call.resolve() + } catch { + call.reject("Failed to set blob, \(error)", nil, error) + } } } - @objc func deleteBlob(_ call: CAPPluginCall) async { - do { - try let id = call.getStringEnsure("id") - try let key = call.getStringEnsure("key") - let permanently = call.getBool("permanently") ?? false - try await docStoragePool.deleteBlob(universalId: id, key: key, permanently: permanently) - } catch { - call.reject("Failed to delete blob", nil, error) + @objc func deleteBlob(_ call: CAPPluginCall) { + Task { + do { + let id = try call.getStringEnsure("id") + let key = try call.getStringEnsure("key") + let permanently = call.getBool("permanently") ?? false + try await docStoragePool.deleteBlob(universalId: id, key: key, permanently: permanently) + call.resolve() + } catch { + call.reject("Failed to delete blob, \(error)", nil, error) + } } } - @objc func releaseBlobs(_ call: CAPPluginCall) async { - do { - try let id = call.getStringEnsure("id") - try await docStoragePool.releaseBlobs(universalId: id) - } catch { - call.reject("Failed to release blobs", nil, error) + @objc func releaseBlobs(_ call: CAPPluginCall) { + Task { + do { + let id = try call.getStringEnsure("id") + try await docStoragePool.releaseBlobs(universalId: id) + call.resolve() + } catch { + call.reject("Failed to release blobs, \(error)", nil, error) + } } } - @objc func listBlobs(_ call: CAPPluginCall) async { - do { - try let id = call.getStringEnsure("id") - if let blobs = try await docStoragePool.listBlobs(universalId: id) { + @objc func listBlobs(_ call: CAPPluginCall) { + Task { + do { + let id = try call.getStringEnsure("id") + let blobs = try await docStoragePool.listBlobs(universalId: id) let mapped = blobs.map { [ "key": $0.key, "size": $0.size, "mime": $0.mime, - "createdAt": $0.createdAt.timeIntervalSince1970, + "createdAt": $0.createdAt, ] } call.resolve(["blobs": mapped]) - } else { - call.resolve() + } catch { + call.reject("Failed to list blobs, \(error)", nil, error) } - } catch { - call.reject("Failed to list blobs", nil, error) } } - @objc func getPeerRemoteClocks(_ call: CAPPluginCall) async { - do { - try let id = call.getStringEnsure("id") - try let peer = call.getStringEnsure("peer") - - let clocks = try await docStoragePool.getPeerRemoteClocks(universalId: id, peer: peer) - let mapped = clocks.map { [ - "docId": $0.docId, - "timestamp": $0.timestamp.timeIntervalSince1970, - ] } - call.resolve(["clocks": mapped]) - } catch { - call.reject("Failed to get peer remote clocks", nil, error) + @objc func getPeerRemoteClocks(_ call: CAPPluginCall) { + Task { + do { + let id = try call.getStringEnsure("id") + let peer = try call.getStringEnsure("peer") + + let clocks = try await docStoragePool.getPeerRemoteClocks(universalId: id, peer: peer) + let mapped = clocks.map { [ + "docId": $0.docId, + "timestamp": $0.timestamp, + ] } + call.resolve(["clocks": mapped]) + } catch { + call.reject("Failed to get peer remote clocks, \(error)", nil, error) + } } } - @objc func getPeerRemoteClock(_ call: CAPPluginCall) async { - do { - try let id = call.getStringEnsure("id") - try let peer = call.getStringEnsure("peer") - try let docId = call.getStringEnsure("docId") - - let clock = try await docStoragePool.getPeerRemoteClock(universalId: id, peer: peer, docId: docId) - call.resolve([ - "docId": clock.docId, - "timestamp": clock.timestamp.timeIntervalSince1970, - ]) - - } catch { - call.reject("Failed to get peer remote clock", nil, error) + @objc func getPeerRemoteClock(_ call: CAPPluginCall) { + Task { + do { + let id = try call.getStringEnsure("id") + let peer = try call.getStringEnsure("peer") + let docId = try call.getStringEnsure("docId") + + let clock = try await docStoragePool.getPeerRemoteClock(universalId: id, peer: peer, docId: docId) + call.resolve([ + "docId": clock.docId, + "timestamp": clock.timestamp, + ]) + + } catch { + call.reject("Failed to get peer remote clock, \(error)", nil, error) + } } } - @objc func setPeerRemoteClock(_ call: CAPPluginCall) async { - try let id = call.getStringEnsure("id") - try let peer = call.getStringEnsure("peer") - try let docId = call.getStringEnsure("docId") - try let timestamp = call.getDoubleEnsure("timestamp") - do { - try await docStoragePool.setPeerRemoteClock( - universalId: id, - peer: peer, - docId: docId, - clock: Date(timeIntervalSince1970: timestamp) - ) - call.resolve() - } catch { - call.reject("Failed to set peer remote clock", nil, error) + @objc func setPeerRemoteClock(_ call: CAPPluginCall) { + Task { + do { + let id = try call.getStringEnsure("id") + let peer = try call.getStringEnsure("peer") + let docId = try call.getStringEnsure("docId") + let timestamp = try call.getIntEnsure("timestamp") + try await docStoragePool.setPeerRemoteClock( + universalId: id, + peer: peer, + docId: docId, + clock: Int64(timestamp) + ) + call.resolve() + } catch { + call.reject("Failed to set peer remote clock, \(error)", nil, error) + } } } - @objc func getPeerPulledRemoteClocks(_ call: CAPPluginCall) async { - do { - try let id = call.getStringEnsure("id") - try let peer = call.getStringEnsure("peer") - - let clocks = try await docStoragePool.getPeerPulledRemoteClocks(universalId: id, peer: peer) - let mapped = clocks.map { [ - "docId": $0.docId, - "timestamp": $0.timestamp.timeIntervalSince1970, - ] } - call.resolve(["clocks": mapped]) - } catch { - call.reject("Failed to get peer pulled remote clocks", nil, error) + @objc func getPeerPulledRemoteClocks(_ call: CAPPluginCall) { + Task { + do { + let id = try call.getStringEnsure("id") + let peer = try call.getStringEnsure("peer") + + let clocks = try await docStoragePool.getPeerPulledRemoteClocks(universalId: id, peer: peer) + let mapped = clocks.map { [ + "docId": $0.docId, + "timestamp": $0.timestamp, + ] } + call.resolve(["clocks": mapped]) + } catch { + call.reject("Failed to get peer pulled remote clocks, \(error)", nil, error) + } } } - @objc func getPeerPulledRemoteClock(_ call: CAPPluginCall) async { - do { - try let id = call.getStringEnsure("id") - try let peer = call.getStringEnsure("peer") - try let docId = call.getStringEnsure("docId") - - let clock = try await docStoragePool.getPeerPulledRemoteClock(universalId: id, peer: peer, docId: docId) - call.resolve([ - "docId": clock.docId, - "timestamp": clock.timestamp.timeIntervalSince1970, - ]) - - } catch { - call.reject("Failed to get peer pulled remote clock", nil, error) + @objc func getPeerPulledRemoteClock(_ call: CAPPluginCall) { + Task { + do { + let id = try call.getStringEnsure("id") + let peer = try call.getStringEnsure("peer") + let docId = try call.getStringEnsure("docId") + + let clock = try await docStoragePool.getPeerPulledRemoteClock(universalId: id, peer: peer, docId: docId) + call.resolve([ + "docId": clock.docId, + "timestamp": clock.timestamp, + ]) + + } catch { + call.reject("Failed to get peer pulled remote clock, \(error)", nil, error) + } } } - @objc func setPeerPulledRemoteClock(_ call: CAPPluginCall) async { - do { - try let id = call.getStringEnsure("id") - try let peer = call.getStringEnsure("peer") - try let docId = call.getStringEnsure("docId") - try let timestamp = call.getDoubleEnsure("timestamp") - - try await docStoragePool.setPeerPulledRemoteClock( - universalId: id, - peer: peer, - docId: docId, - clock: Date(timeIntervalSince1970: timestamp) - ) - call.resolve() - } catch { - call.reject("Failed to set peer pulled remote clock", nil, error) + @objc func setPeerPulledRemoteClock(_ call: CAPPluginCall) { + Task { + do { + let id = try call.getStringEnsure("id") + let peer = try call.getStringEnsure("peer") + let docId = try call.getStringEnsure("docId") + let timestamp = try call.getIntEnsure("timestamp") + + try await docStoragePool.setPeerPulledRemoteClock( + universalId: id, + peer: peer, + docId: docId, + clock: Int64(timestamp) + ) + call.resolve() + } catch { + call.reject("Failed to set peer pulled remote clock, \(error)", nil, error) + } } } - @objc func getPeerPushedClocks(_ call: CAPPluginCall) async { - do { - try let id = call.getStringEnsure("id") - try let peer = call.getStringEnsure("peer") - let clocks = try await docStoragePool.getPeerPushedClocks(universalId: id, peer: peer) - let mapped = clocks.map { [ - "docId": $0.docId, - "timestamp": $0.timestamp.timeIntervalSince1970, - ] } - call.resolve(["clocks": mapped]) - - } catch { - call.reject("Failed to get peer pushed clocks", nil, error) + @objc func getPeerPushedClocks(_ call: CAPPluginCall) { + Task { + do { + let id = try call.getStringEnsure("id") + let peer = try call.getStringEnsure("peer") + let clocks = try await docStoragePool.getPeerPushedClocks(universalId: id, peer: peer) + let mapped = clocks.map { [ + "docId": $0.docId, + "timestamp": $0.timestamp, + ] } + call.resolve(["clocks": mapped]) + + } catch { + call.reject("Failed to get peer pushed clocks, \(error)", nil, error) + } } } - @objc func setPeerPushedClock(_ call: CAPPluginCall) async { - do { - try let id = call.getStringEnsure("id") - try let peer = call.getStringEnsure("peer") - try let docId = call.getStringEnsure("docId") - try let timestamp = call.getDoubleEnsure("timestamp") - - try await docStoragePool.setPeerPushedClock( - universalId: id, - peer: peer, - docId: docId, - clock: Date(timeIntervalSince1970: timestamp) - ) - call.resolve() - } catch { - call.reject("Failed to set peer pushed clock", nil, error) + @objc func setPeerPushedClock(_ call: CAPPluginCall) { + Task { + do { + let id = try call.getStringEnsure("id") + let peer = try call.getStringEnsure("peer") + let docId = try call.getStringEnsure("docId") + let timestamp = try call.getIntEnsure("timestamp") + + try await docStoragePool.setPeerPushedClock( + universalId: id, + peer: peer, + docId: docId, + clock: Int64(timestamp) + ) + call.resolve() + } catch { + call.reject("Failed to set peer pushed clock, \(error)", nil, error) + } } } - @objc func clearClocks(_ call: CAPPluginCall) async { - do { - try let id = call.getStringEnsure("id") - try await docStoragePool.clearClocks(universalId: id) - call.resolve() - } catch { - call.reject("Failed to clear clocks", nil, error) + @objc func clearClocks(_ call: CAPPluginCall) { + Task { + do { + let id = try call.getStringEnsure("id") + try await docStoragePool.clearClocks(universalId: id) + call.resolve() + } catch { + call.reject("Failed to clear clocks, \(error)", nil, error) + } } } } diff --git a/packages/frontend/apps/ios/App/App/uniffi/affine_mobile_native.swift b/packages/frontend/apps/ios/App/App/uniffi/affine_mobile_native.swift index 0e381530fa661..c96cec1083593 100644 --- a/packages/frontend/apps/ios/App/App/uniffi/affine_mobile_native.swift +++ b/packages/frontend/apps/ios/App/App/uniffi/affine_mobile_native.swift @@ -8,10 +8,10 @@ import Foundation // might be in a separate module, or it might be compiled inline into // this module. This is a bit of light hackery to work with both. #if canImport(affine_mobile_nativeFFI) -import affine_mobile_nativeFFI + import affine_mobile_nativeFFI #endif -fileprivate extension RustBuffer { +private extension RustBuffer { // Allocate a new buffer, copying the contents of a `UInt8` array. init(bytes: [UInt8]) { let rbuf = bytes.withUnsafeBufferPointer { ptr in @@ -21,7 +21,7 @@ fileprivate extension RustBuffer { } static func empty() -> RustBuffer { - RustBuffer(capacity: 0, len:0, data: nil) + RustBuffer(capacity: 0, len: 0, data: nil) } static func from(_ ptr: UnsafeBufferPointer) -> RustBuffer { @@ -35,7 +35,7 @@ fileprivate extension RustBuffer { } } -fileprivate extension ForeignBytes { +private extension ForeignBytes { init(bufferPointer: UnsafeBufferPointer) { self.init(len: Int32(bufferPointer.count), data: bufferPointer.baseAddress) } @@ -48,7 +48,7 @@ fileprivate extension ForeignBytes { // Helper classes/extensions that don't change. // Someday, this will be in a library of its own. -fileprivate extension Data { +private extension Data { init(rustBuffer: RustBuffer) { self.init( bytesNoCopy: rustBuffer.data!, @@ -72,15 +72,15 @@ fileprivate extension Data { // // Instead, the read() method and these helper functions input a tuple of data -fileprivate func createReader(data: Data) -> (data: Data, offset: Data.Index) { +private func createReader(data: Data) -> (data: Data, offset: Data.Index) { (data: data, offset: 0) } // Reads an integer at the current offset, in big-endian order, and advances // the offset on success. Throws if reading the integer would move the // offset past the end of the buffer. -fileprivate func readInt(_ reader: inout (data: Data, offset: Data.Index)) throws -> T { - let range = reader.offset...size +private func readInt(_ reader: inout (data: Data, offset: Data.Index)) throws -> T { + let range = reader.offset ..< reader.offset + MemoryLayout.size guard reader.data.count >= range.upperBound else { throw UniffiInternalError.bufferOverflow } @@ -90,38 +90,38 @@ fileprivate func readInt(_ reader: inout (data: Data, offs return value as! T } var value: T = 0 - let _ = withUnsafeMutableBytes(of: &value, { reader.data.copyBytes(to: $0, from: range)}) + let _ = withUnsafeMutableBytes(of: &value) { reader.data.copyBytes(to: $0, from: range) } reader.offset = range.upperBound return value.bigEndian } // Reads an arbitrary number of bytes, to be used to read // raw bytes, this is useful when lifting strings -fileprivate func readBytes(_ reader: inout (data: Data, offset: Data.Index), count: Int) throws -> Array { - let range = reader.offset..<(reader.offset+count) +private func readBytes(_ reader: inout (data: Data, offset: Data.Index), count: Int) throws -> [UInt8] { + let range = reader.offset ..< (reader.offset + count) guard reader.data.count >= range.upperBound else { throw UniffiInternalError.bufferOverflow } var value = [UInt8](repeating: 0, count: count) - value.withUnsafeMutableBufferPointer({ buffer in + value.withUnsafeMutableBufferPointer { buffer in reader.data.copyBytes(to: buffer, from: range) - }) + } reader.offset = range.upperBound return value } // Reads a float at the current offset. -fileprivate func readFloat(_ reader: inout (data: Data, offset: Data.Index)) throws -> Float { - return Float(bitPattern: try readInt(&reader)) +private func readFloat(_ reader: inout (data: Data, offset: Data.Index)) throws -> Float { + return try Float(bitPattern: readInt(&reader)) } // Reads a float at the current offset. -fileprivate func readDouble(_ reader: inout (data: Data, offset: Data.Index)) throws -> Double { - return Double(bitPattern: try readInt(&reader)) +private func readDouble(_ reader: inout (data: Data, offset: Data.Index)) throws -> Double { + return try Double(bitPattern: readInt(&reader)) } // Indicates if the offset has reached the end of the buffer. -fileprivate func hasRemaining(_ reader: (data: Data, offset: Data.Index)) -> Bool { +private func hasRemaining(_ reader: (data: Data, offset: Data.Index)) -> Bool { return reader.offset < reader.data.count } @@ -129,11 +129,11 @@ fileprivate func hasRemaining(_ reader: (data: Data, offset: Data.Index)) -> Boo // struct, but we use standalone functions instead in order to make external // types work. See the above discussion on Readers for details. -fileprivate func createWriter() -> [UInt8] { +private func createWriter() -> [UInt8] { return [] } -fileprivate func writeBytes(_ writer: inout [UInt8], _ byteArr: S) where S: Sequence, S.Element == UInt8 { +private func writeBytes(_ writer: inout [UInt8], _ byteArr: S) where S: Sequence, S.Element == UInt8 { writer.append(contentsOf: byteArr) } @@ -141,22 +141,22 @@ fileprivate func writeBytes(_ writer: inout [UInt8], _ byteArr: S) where S: S // // Warning: make sure what you are trying to write // is in the correct type! -fileprivate func writeInt(_ writer: inout [UInt8], _ value: T) { +private func writeInt(_ writer: inout [UInt8], _ value: T) { var value = value.bigEndian withUnsafeBytes(of: &value) { writer.append(contentsOf: $0) } } -fileprivate func writeFloat(_ writer: inout [UInt8], _ value: Float) { +private func writeFloat(_ writer: inout [UInt8], _ value: Float) { writeInt(&writer, value.bitPattern) } -fileprivate func writeDouble(_ writer: inout [UInt8], _ value: Double) { +private func writeDouble(_ writer: inout [UInt8], _ value: Double) { writeInt(&writer, value.bitPattern) } // Protocol for types that transfer other types across the FFI. This is // analogous to the Rust trait of the same name. -fileprivate protocol FfiConverter { +private protocol FfiConverter { associatedtype FfiType associatedtype SwiftType @@ -167,19 +167,19 @@ fileprivate protocol FfiConverter { } // Types conforming to `Primitive` pass themselves directly over the FFI. -fileprivate protocol FfiConverterPrimitive: FfiConverter where FfiType == SwiftType { } +private protocol FfiConverterPrimitive: FfiConverter where FfiType == SwiftType {} extension FfiConverterPrimitive { -#if swift(>=5.8) - @_documentation(visibility: private) -#endif + #if swift(>=5.8) + @_documentation(visibility: private) + #endif public static func lift(_ value: FfiType) throws -> SwiftType { return value } -#if swift(>=5.8) - @_documentation(visibility: private) -#endif + #if swift(>=5.8) + @_documentation(visibility: private) + #endif public static func lower(_ value: SwiftType) -> FfiType { return value } @@ -187,12 +187,12 @@ extension FfiConverterPrimitive { // Types conforming to `FfiConverterRustBuffer` lift and lower into a `RustBuffer`. // Used for complex types where it's hard to write a custom lift/lower. -fileprivate protocol FfiConverterRustBuffer: FfiConverter where FfiType == RustBuffer {} +private protocol FfiConverterRustBuffer: FfiConverter where FfiType == RustBuffer {} extension FfiConverterRustBuffer { -#if swift(>=5.8) - @_documentation(visibility: private) -#endif + #if swift(>=5.8) + @_documentation(visibility: private) + #endif public static func lift(_ buf: RustBuffer) throws -> SwiftType { var reader = createReader(data: Data(rustBuffer: buf)) let value = try read(from: &reader) @@ -203,18 +203,19 @@ extension FfiConverterRustBuffer { return value } -#if swift(>=5.8) - @_documentation(visibility: private) -#endif + #if swift(>=5.8) + @_documentation(visibility: private) + #endif public static func lower(_ value: SwiftType) -> RustBuffer { - var writer = createWriter() - write(value, into: &writer) - return RustBuffer(bytes: writer) + var writer = createWriter() + write(value, into: &writer) + return RustBuffer(bytes: writer) } } + // An error type for FFI errors. These errors occur at the UniFFI level, not // the library level. -fileprivate enum UniffiInternalError: LocalizedError { +private enum UniffiInternalError: LocalizedError { case bufferOverflow case incompleteData case unexpectedOptionalTag @@ -240,24 +241,24 @@ fileprivate enum UniffiInternalError: LocalizedError { } } -fileprivate extension NSLock { +private extension NSLock { func withLock(f: () throws -> T) rethrows -> T { - self.lock() + lock() defer { self.unlock() } return try f() } } -fileprivate let CALL_SUCCESS: Int8 = 0 -fileprivate let CALL_ERROR: Int8 = 1 -fileprivate let CALL_UNEXPECTED_ERROR: Int8 = 2 -fileprivate let CALL_CANCELLED: Int8 = 3 +private let CALL_SUCCESS: Int8 = 0 +private let CALL_ERROR: Int8 = 1 +private let CALL_UNEXPECTED_ERROR: Int8 = 2 +private let CALL_CANCELLED: Int8 = 3 -fileprivate extension RustCallStatus { +private extension RustCallStatus { init() { self.init( code: CALL_SUCCESS, - errorBuf: RustBuffer.init( + errorBuf: RustBuffer( capacity: 0, len: 0, data: nil @@ -273,7 +274,8 @@ private func rustCall(_ callback: (UnsafeMutablePointer) -> T private func rustCallWithError( _ errorHandler: @escaping (RustBuffer) throws -> E, - _ callback: (UnsafeMutablePointer) -> T) throws -> T { + _ callback: (UnsafeMutablePointer) -> T +) throws -> T { try makeRustCall(callback, errorHandler: errorHandler) } @@ -282,7 +284,7 @@ private func makeRustCall( errorHandler: ((RustBuffer) throws -> E)? ) throws -> T { uniffiEnsureInitialized() - var callStatus = RustCallStatus.init() + var callStatus = RustCallStatus() let returnedVal = callback(&callStatus) try uniffiCheckCallStatus(callStatus: callStatus, errorHandler: errorHandler) return returnedVal @@ -293,44 +295,44 @@ private func uniffiCheckCallStatus( errorHandler: ((RustBuffer) throws -> E)? ) throws { switch callStatus.code { - case CALL_SUCCESS: - return + case CALL_SUCCESS: + return - case CALL_ERROR: - if let errorHandler = errorHandler { - throw try errorHandler(callStatus.errorBuf) - } else { - callStatus.errorBuf.deallocate() - throw UniffiInternalError.unexpectedRustCallError - } + case CALL_ERROR: + if let errorHandler = errorHandler { + throw try errorHandler(callStatus.errorBuf) + } else { + callStatus.errorBuf.deallocate() + throw UniffiInternalError.unexpectedRustCallError + } - case CALL_UNEXPECTED_ERROR: - // When the rust code sees a panic, it tries to construct a RustBuffer - // with the message. But if that code panics, then it just sends back - // an empty buffer. - if callStatus.errorBuf.len > 0 { - throw UniffiInternalError.rustPanic(try FfiConverterString.lift(callStatus.errorBuf)) - } else { - callStatus.errorBuf.deallocate() - throw UniffiInternalError.rustPanic("Rust panic") - } + case CALL_UNEXPECTED_ERROR: + // When the rust code sees a panic, it tries to construct a RustBuffer + // with the message. But if that code panics, then it just sends back + // an empty buffer. + if callStatus.errorBuf.len > 0 { + throw try UniffiInternalError.rustPanic(FfiConverterString.lift(callStatus.errorBuf)) + } else { + callStatus.errorBuf.deallocate() + throw UniffiInternalError.rustPanic("Rust panic") + } - case CALL_CANCELLED: - fatalError("Cancellation not supported yet") + case CALL_CANCELLED: + fatalError("Cancellation not supported yet") - default: - throw UniffiInternalError.unexpectedRustCallStatusCode + default: + throw UniffiInternalError.unexpectedRustCallStatusCode } } private func uniffiTraitInterfaceCall( callStatus: UnsafeMutablePointer, makeCall: () throws -> T, - writeReturn: (T) -> () + writeReturn: (T) -> Void ) { do { try writeReturn(makeCall()) - } catch let error { + } catch { callStatus.pointee.code = CALL_UNEXPECTED_ERROR callStatus.pointee.errorBuf = FfiConverterString.lower(String(describing: error)) } @@ -339,7 +341,7 @@ private func uniffiTraitInterfaceCall( private func uniffiTraitInterfaceCallWithError( callStatus: UnsafeMutablePointer, makeCall: () throws -> T, - writeReturn: (T) -> (), + writeReturn: (T) -> Void, lowerError: (E) -> RustBuffer ) { do { @@ -352,7 +354,8 @@ private func uniffiTraitInterfaceCallWithError( callStatus.pointee.errorBuf = FfiConverterString.lower(String(describing: error)) } } -fileprivate class UniffiHandleMap { + +private class UniffiHandleMap { private var map: [UInt64: T] = [:] private let lock = NSLock() private var currentHandle: UInt64 = 1 @@ -366,7 +369,7 @@ fileprivate class UniffiHandleMap { } } - func get(handle: UInt64) throws -> T { + func get(handle: UInt64) throws -> T { try lock.withLock { guard let obj = map[handle] else { throw UniffiInternalError.unexpectedStaleHandle @@ -386,20 +389,16 @@ fileprivate class UniffiHandleMap { } var count: Int { - get { - map.count - } + map.count } } - // Public interface members begin here. - #if swift(>=5.8) -@_documentation(visibility: private) + @_documentation(visibility: private) #endif -fileprivate struct FfiConverterUInt32: FfiConverterPrimitive { +private struct FfiConverterUInt32: FfiConverterPrimitive { typealias FfiType = UInt32 typealias SwiftType = UInt32 @@ -413,9 +412,9 @@ fileprivate struct FfiConverterUInt32: FfiConverterPrimitive { } #if swift(>=5.8) -@_documentation(visibility: private) + @_documentation(visibility: private) #endif -fileprivate struct FfiConverterInt64: FfiConverterPrimitive { +private struct FfiConverterInt64: FfiConverterPrimitive { typealias FfiType = Int64 typealias SwiftType = Int64 @@ -429,9 +428,9 @@ fileprivate struct FfiConverterInt64: FfiConverterPrimitive { } #if swift(>=5.8) -@_documentation(visibility: private) + @_documentation(visibility: private) #endif -fileprivate struct FfiConverterBool : FfiConverter { +private struct FfiConverterBool: FfiConverter { typealias FfiType = Int8 typealias SwiftType = Bool @@ -453,9 +452,9 @@ fileprivate struct FfiConverterBool : FfiConverter { } #if swift(>=5.8) -@_documentation(visibility: private) + @_documentation(visibility: private) #endif -fileprivate struct FfiConverterString: FfiConverter { +private struct FfiConverterString: FfiConverter { typealias SwiftType = String typealias FfiType = RustBuffer @@ -483,7 +482,7 @@ fileprivate struct FfiConverterString: FfiConverter { public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> String { let len: Int32 = try readInt(&buf) - return String(bytes: try readBytes(&buf, count: Int(len)), encoding: String.Encoding.utf8)! + return try String(bytes: readBytes(&buf, count: Int(len)), encoding: String.Encoding.utf8)! } public static func write(_ value: String, into buf: inout [UInt8]) { @@ -493,112 +492,70 @@ fileprivate struct FfiConverterString: FfiConverter { } } -#if swift(>=5.8) -@_documentation(visibility: private) -#endif -fileprivate struct FfiConverterTimestamp: FfiConverterRustBuffer { - typealias SwiftType = Date - - public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> Date { - let seconds: Int64 = try readInt(&buf) - let nanoseconds: UInt32 = try readInt(&buf) - if seconds >= 0 { - let delta = Double(seconds) + (Double(nanoseconds) / 1.0e9) - return Date.init(timeIntervalSince1970: delta) - } else { - let delta = Double(seconds) - (Double(nanoseconds) / 1.0e9) - return Date.init(timeIntervalSince1970: delta) - } - } +public protocol DocStoragePoolProtocol: AnyObject { + func clearClocks(universalId: String) async throws - public static func write(_ value: Date, into buf: inout [UInt8]) { - var delta = value.timeIntervalSince1970 - var sign: Int64 = 1 - if delta < 0 { - // The nanoseconds portion of the epoch offset must always be - // positive, to simplify the calculation we will use the absolute - // value of the offset. - sign = -1 - delta = -delta - } - if delta.rounded(.down) > Double(Int64.max) { - fatalError("Timestamp overflow, exceeds max bounds supported by Uniffi") - } - let seconds = Int64(delta) - let nanoseconds = UInt32((delta - Double(seconds)) * 1.0e9) - writeInt(&buf, sign * seconds) - writeInt(&buf, nanoseconds) - } -} + /** + * Initialize the database and run migrations. + */ + func connect(universalId: String, path: String) async throws + func deleteBlob(universalId: String, key: String, permanently: Bool) async throws + func deleteDoc(universalId: String, docId: String) async throws + func disconnect(universalId: String) async throws -public protocol DocStoragePoolProtocol : AnyObject { - - func clearClocks(universalId: String) async throws - - /** - * Initialize the database and run migrations. - */ - func connect(universalId: String, path: String) async throws - - func deleteBlob(universalId: String, key: String, permanently: Bool) async throws - - func deleteDoc(universalId: String, docId: String) async throws - - func disconnect(universalId: String) async throws - - func getBlob(universalId: String, key: String) async throws -> Blob? - - func getDocClock(universalId: String, docId: String) async throws -> DocClock? - - func getDocClocks(universalId: String, after: Date?) async throws -> [DocClock] - - func getDocSnapshot(universalId: String, docId: String) async throws -> DocRecord? - - func getDocUpdates(universalId: String, docId: String) async throws -> [DocUpdate] - - func getPeerPulledRemoteClock(universalId: String, peer: String, docId: String) async throws -> DocClock - - func getPeerPulledRemoteClocks(universalId: String, peer: String) async throws -> [DocClock] - - func getPeerPushedClocks(universalId: String, peer: String) async throws -> [DocClock] - - func getPeerRemoteClock(universalId: String, peer: String, docId: String) async throws -> DocClock - - func getPeerRemoteClocks(universalId: String, peer: String) async throws -> [DocClock] - - func listBlobs(universalId: String) async throws -> [ListedBlob] - - func markUpdatesMerged(universalId: String, docId: String, updates: [Date]) async throws -> UInt32 - - func pushUpdate(universalId: String, docId: String, update: String) async throws -> Date - - func releaseBlobs(universalId: String) async throws - - func setBlob(universalId: String, blob: SetBlob) async throws - - func setDocSnapshot(universalId: String, snapshot: DocRecord) async throws -> Bool - - func setPeerPulledRemoteClock(universalId: String, peer: String, docId: String, clock: Date) async throws - - func setPeerPushedClock(universalId: String, peer: String, docId: String, clock: Date) async throws - - func setPeerRemoteClock(universalId: String, peer: String, docId: String, clock: Date) async throws - - func setSpaceId(universalId: String, spaceId: String) async throws - + func getBlob(universalId: String, key: String) async throws -> Blob? + + func getDocClock(universalId: String, docId: String) async throws -> DocClock? + + func getDocClocks(universalId: String, after: Int64?) async throws -> [DocClock] + + func getDocSnapshot(universalId: String, docId: String) async throws -> DocRecord? + + func getDocUpdates(universalId: String, docId: String) async throws -> [DocUpdate] + + func getPeerPulledRemoteClock(universalId: String, peer: String, docId: String) async throws -> DocClock + + func getPeerPulledRemoteClocks(universalId: String, peer: String) async throws -> [DocClock] + + func getPeerPushedClocks(universalId: String, peer: String) async throws -> [DocClock] + + func getPeerRemoteClock(universalId: String, peer: String, docId: String) async throws -> DocClock + + func getPeerRemoteClocks(universalId: String, peer: String) async throws -> [DocClock] + + func listBlobs(universalId: String) async throws -> [ListedBlob] + + func markUpdatesMerged(universalId: String, docId: String, updates: [Int64]) async throws -> UInt32 + + func pushUpdate(universalId: String, docId: String, update: String) async throws -> Int64 + + func releaseBlobs(universalId: String) async throws + + func setBlob(universalId: String, blob: SetBlob) async throws + + func setDocSnapshot(universalId: String, snapshot: DocRecord) async throws -> Bool + + func setPeerPulledRemoteClock(universalId: String, peer: String, docId: String, clock: Int64) async throws + + func setPeerPushedClock(universalId: String, peer: String, docId: String, clock: Int64) async throws + + func setPeerRemoteClock(universalId: String, peer: String, docId: String, clock: Int64) async throws + + func setSpaceId(universalId: String, spaceId: String) async throws } open class DocStoragePool: - DocStoragePoolProtocol { + DocStoragePoolProtocol +{ fileprivate let pointer: UnsafeMutableRawPointer! /// Used to instantiate a [FFIObject] without an actual pointer, for fakes in tests, mostly. -#if swift(>=5.8) - @_documentation(visibility: private) -#endif + #if swift(>=5.8) + @_documentation(visibility: private) + #endif public struct NoPointer { public init() {} } @@ -606,7 +563,7 @@ open class DocStoragePool: // TODO: We'd like this to be `private` but for Swifty reasons, // we can't implement `FfiConverter` without making this `required` and we can't // make it `required` without making it `public`. - required public init(unsafeFromRawPointer pointer: UnsafeMutableRawPointer) { + public required init(unsafeFromRawPointer pointer: UnsafeMutableRawPointer) { self.pointer = pointer } @@ -615,19 +572,20 @@ open class DocStoragePool: // // - Warning: // Any object instantiated with this constructor cannot be passed to an actual Rust-backed object. Since there isn't a backing [Pointer] the FFI lower functions will crash. -#if swift(>=5.8) - @_documentation(visibility: private) -#endif - public init(noPointer: NoPointer) { - self.pointer = nil + #if swift(>=5.8) + @_documentation(visibility: private) + #endif + public init(noPointer _: NoPointer) { + pointer = nil } -#if swift(>=5.8) - @_documentation(visibility: private) -#endif + #if swift(>=5.8) + @_documentation(visibility: private) + #endif public func uniffiClonePointer() -> UnsafeMutableRawPointer { return try! rustCall { uniffi_affine_mobile_native_fn_clone_docstoragepool(self.pointer, $0) } } + // No primary constructor declared for this class. deinit { @@ -638,445 +596,439 @@ open class DocStoragePool: try! rustCall { uniffi_affine_mobile_native_fn_free_docstoragepool(pointer, $0) } } - - - -open func clearClocks(universalId: String)async throws { - return - try await uniffiRustCallAsync( - rustFutureFunc: { - uniffi_affine_mobile_native_fn_method_docstoragepool_clear_clocks( - self.uniffiClonePointer(), - FfiConverterString.lower(universalId) - ) - }, - pollFunc: ffi_affine_mobile_native_rust_future_poll_void, - completeFunc: ffi_affine_mobile_native_rust_future_complete_void, - freeFunc: ffi_affine_mobile_native_rust_future_free_void, - liftFunc: { $0 }, - errorHandler: FfiConverterTypeUniffiError.lift - ) -} - + open func clearClocks(universalId: String) async throws { + return + try await uniffiRustCallAsync( + rustFutureFunc: { + uniffi_affine_mobile_native_fn_method_docstoragepool_clear_clocks( + self.uniffiClonePointer(), + FfiConverterString.lower(universalId) + ) + }, + pollFunc: ffi_affine_mobile_native_rust_future_poll_void, + completeFunc: ffi_affine_mobile_native_rust_future_complete_void, + freeFunc: ffi_affine_mobile_native_rust_future_free_void, + liftFunc: { $0 }, + errorHandler: FfiConverterTypeUniffiError.lift + ) + } + /** * Initialize the database and run migrations. */ -open func connect(universalId: String, path: String)async throws { - return - try await uniffiRustCallAsync( - rustFutureFunc: { - uniffi_affine_mobile_native_fn_method_docstoragepool_connect( - self.uniffiClonePointer(), - FfiConverterString.lower(universalId),FfiConverterString.lower(path) - ) - }, - pollFunc: ffi_affine_mobile_native_rust_future_poll_void, - completeFunc: ffi_affine_mobile_native_rust_future_complete_void, - freeFunc: ffi_affine_mobile_native_rust_future_free_void, - liftFunc: { $0 }, - errorHandler: FfiConverterTypeUniffiError.lift - ) -} - -open func deleteBlob(universalId: String, key: String, permanently: Bool)async throws { - return - try await uniffiRustCallAsync( - rustFutureFunc: { - uniffi_affine_mobile_native_fn_method_docstoragepool_delete_blob( - self.uniffiClonePointer(), - FfiConverterString.lower(universalId),FfiConverterString.lower(key),FfiConverterBool.lower(permanently) - ) - }, - pollFunc: ffi_affine_mobile_native_rust_future_poll_void, - completeFunc: ffi_affine_mobile_native_rust_future_complete_void, - freeFunc: ffi_affine_mobile_native_rust_future_free_void, - liftFunc: { $0 }, - errorHandler: FfiConverterTypeUniffiError.lift - ) -} - -open func deleteDoc(universalId: String, docId: String)async throws { - return - try await uniffiRustCallAsync( - rustFutureFunc: { - uniffi_affine_mobile_native_fn_method_docstoragepool_delete_doc( - self.uniffiClonePointer(), - FfiConverterString.lower(universalId),FfiConverterString.lower(docId) - ) - }, - pollFunc: ffi_affine_mobile_native_rust_future_poll_void, - completeFunc: ffi_affine_mobile_native_rust_future_complete_void, - freeFunc: ffi_affine_mobile_native_rust_future_free_void, - liftFunc: { $0 }, - errorHandler: FfiConverterTypeUniffiError.lift - ) -} - -open func disconnect(universalId: String)async throws { - return - try await uniffiRustCallAsync( - rustFutureFunc: { - uniffi_affine_mobile_native_fn_method_docstoragepool_disconnect( - self.uniffiClonePointer(), - FfiConverterString.lower(universalId) - ) - }, - pollFunc: ffi_affine_mobile_native_rust_future_poll_void, - completeFunc: ffi_affine_mobile_native_rust_future_complete_void, - freeFunc: ffi_affine_mobile_native_rust_future_free_void, - liftFunc: { $0 }, - errorHandler: FfiConverterTypeUniffiError.lift - ) -} - -open func getBlob(universalId: String, key: String)async throws -> Blob? { - return - try await uniffiRustCallAsync( - rustFutureFunc: { - uniffi_affine_mobile_native_fn_method_docstoragepool_get_blob( - self.uniffiClonePointer(), - FfiConverterString.lower(universalId),FfiConverterString.lower(key) - ) - }, - pollFunc: ffi_affine_mobile_native_rust_future_poll_rust_buffer, - completeFunc: ffi_affine_mobile_native_rust_future_complete_rust_buffer, - freeFunc: ffi_affine_mobile_native_rust_future_free_rust_buffer, - liftFunc: FfiConverterOptionTypeBlob.lift, - errorHandler: FfiConverterTypeUniffiError.lift - ) -} - -open func getDocClock(universalId: String, docId: String)async throws -> DocClock? { - return - try await uniffiRustCallAsync( - rustFutureFunc: { - uniffi_affine_mobile_native_fn_method_docstoragepool_get_doc_clock( - self.uniffiClonePointer(), - FfiConverterString.lower(universalId),FfiConverterString.lower(docId) - ) - }, - pollFunc: ffi_affine_mobile_native_rust_future_poll_rust_buffer, - completeFunc: ffi_affine_mobile_native_rust_future_complete_rust_buffer, - freeFunc: ffi_affine_mobile_native_rust_future_free_rust_buffer, - liftFunc: FfiConverterOptionTypeDocClock.lift, - errorHandler: FfiConverterTypeUniffiError.lift - ) -} - -open func getDocClocks(universalId: String, after: Date?)async throws -> [DocClock] { - return - try await uniffiRustCallAsync( - rustFutureFunc: { - uniffi_affine_mobile_native_fn_method_docstoragepool_get_doc_clocks( - self.uniffiClonePointer(), - FfiConverterString.lower(universalId),FfiConverterOptionTimestamp.lower(after) - ) - }, - pollFunc: ffi_affine_mobile_native_rust_future_poll_rust_buffer, - completeFunc: ffi_affine_mobile_native_rust_future_complete_rust_buffer, - freeFunc: ffi_affine_mobile_native_rust_future_free_rust_buffer, - liftFunc: FfiConverterSequenceTypeDocClock.lift, - errorHandler: FfiConverterTypeUniffiError.lift - ) -} - -open func getDocSnapshot(universalId: String, docId: String)async throws -> DocRecord? { - return - try await uniffiRustCallAsync( - rustFutureFunc: { - uniffi_affine_mobile_native_fn_method_docstoragepool_get_doc_snapshot( - self.uniffiClonePointer(), - FfiConverterString.lower(universalId),FfiConverterString.lower(docId) - ) - }, - pollFunc: ffi_affine_mobile_native_rust_future_poll_rust_buffer, - completeFunc: ffi_affine_mobile_native_rust_future_complete_rust_buffer, - freeFunc: ffi_affine_mobile_native_rust_future_free_rust_buffer, - liftFunc: FfiConverterOptionTypeDocRecord.lift, - errorHandler: FfiConverterTypeUniffiError.lift - ) -} - -open func getDocUpdates(universalId: String, docId: String)async throws -> [DocUpdate] { - return - try await uniffiRustCallAsync( - rustFutureFunc: { - uniffi_affine_mobile_native_fn_method_docstoragepool_get_doc_updates( - self.uniffiClonePointer(), - FfiConverterString.lower(universalId),FfiConverterString.lower(docId) - ) - }, - pollFunc: ffi_affine_mobile_native_rust_future_poll_rust_buffer, - completeFunc: ffi_affine_mobile_native_rust_future_complete_rust_buffer, - freeFunc: ffi_affine_mobile_native_rust_future_free_rust_buffer, - liftFunc: FfiConverterSequenceTypeDocUpdate.lift, - errorHandler: FfiConverterTypeUniffiError.lift - ) -} - -open func getPeerPulledRemoteClock(universalId: String, peer: String, docId: String)async throws -> DocClock { - return - try await uniffiRustCallAsync( - rustFutureFunc: { - uniffi_affine_mobile_native_fn_method_docstoragepool_get_peer_pulled_remote_clock( - self.uniffiClonePointer(), - FfiConverterString.lower(universalId),FfiConverterString.lower(peer),FfiConverterString.lower(docId) - ) - }, - pollFunc: ffi_affine_mobile_native_rust_future_poll_rust_buffer, - completeFunc: ffi_affine_mobile_native_rust_future_complete_rust_buffer, - freeFunc: ffi_affine_mobile_native_rust_future_free_rust_buffer, - liftFunc: FfiConverterTypeDocClock.lift, - errorHandler: FfiConverterTypeUniffiError.lift - ) -} - -open func getPeerPulledRemoteClocks(universalId: String, peer: String)async throws -> [DocClock] { - return - try await uniffiRustCallAsync( - rustFutureFunc: { - uniffi_affine_mobile_native_fn_method_docstoragepool_get_peer_pulled_remote_clocks( - self.uniffiClonePointer(), - FfiConverterString.lower(universalId),FfiConverterString.lower(peer) - ) - }, - pollFunc: ffi_affine_mobile_native_rust_future_poll_rust_buffer, - completeFunc: ffi_affine_mobile_native_rust_future_complete_rust_buffer, - freeFunc: ffi_affine_mobile_native_rust_future_free_rust_buffer, - liftFunc: FfiConverterSequenceTypeDocClock.lift, - errorHandler: FfiConverterTypeUniffiError.lift - ) -} - -open func getPeerPushedClocks(universalId: String, peer: String)async throws -> [DocClock] { - return - try await uniffiRustCallAsync( - rustFutureFunc: { - uniffi_affine_mobile_native_fn_method_docstoragepool_get_peer_pushed_clocks( - self.uniffiClonePointer(), - FfiConverterString.lower(universalId),FfiConverterString.lower(peer) - ) - }, - pollFunc: ffi_affine_mobile_native_rust_future_poll_rust_buffer, - completeFunc: ffi_affine_mobile_native_rust_future_complete_rust_buffer, - freeFunc: ffi_affine_mobile_native_rust_future_free_rust_buffer, - liftFunc: FfiConverterSequenceTypeDocClock.lift, - errorHandler: FfiConverterTypeUniffiError.lift - ) -} - -open func getPeerRemoteClock(universalId: String, peer: String, docId: String)async throws -> DocClock { - return - try await uniffiRustCallAsync( - rustFutureFunc: { - uniffi_affine_mobile_native_fn_method_docstoragepool_get_peer_remote_clock( - self.uniffiClonePointer(), - FfiConverterString.lower(universalId),FfiConverterString.lower(peer),FfiConverterString.lower(docId) - ) - }, - pollFunc: ffi_affine_mobile_native_rust_future_poll_rust_buffer, - completeFunc: ffi_affine_mobile_native_rust_future_complete_rust_buffer, - freeFunc: ffi_affine_mobile_native_rust_future_free_rust_buffer, - liftFunc: FfiConverterTypeDocClock.lift, - errorHandler: FfiConverterTypeUniffiError.lift - ) -} - -open func getPeerRemoteClocks(universalId: String, peer: String)async throws -> [DocClock] { - return - try await uniffiRustCallAsync( - rustFutureFunc: { - uniffi_affine_mobile_native_fn_method_docstoragepool_get_peer_remote_clocks( - self.uniffiClonePointer(), - FfiConverterString.lower(universalId),FfiConverterString.lower(peer) - ) - }, - pollFunc: ffi_affine_mobile_native_rust_future_poll_rust_buffer, - completeFunc: ffi_affine_mobile_native_rust_future_complete_rust_buffer, - freeFunc: ffi_affine_mobile_native_rust_future_free_rust_buffer, - liftFunc: FfiConverterSequenceTypeDocClock.lift, - errorHandler: FfiConverterTypeUniffiError.lift - ) -} - -open func listBlobs(universalId: String)async throws -> [ListedBlob] { - return - try await uniffiRustCallAsync( - rustFutureFunc: { - uniffi_affine_mobile_native_fn_method_docstoragepool_list_blobs( - self.uniffiClonePointer(), - FfiConverterString.lower(universalId) - ) - }, - pollFunc: ffi_affine_mobile_native_rust_future_poll_rust_buffer, - completeFunc: ffi_affine_mobile_native_rust_future_complete_rust_buffer, - freeFunc: ffi_affine_mobile_native_rust_future_free_rust_buffer, - liftFunc: FfiConverterSequenceTypeListedBlob.lift, - errorHandler: FfiConverterTypeUniffiError.lift - ) -} - -open func markUpdatesMerged(universalId: String, docId: String, updates: [Date])async throws -> UInt32 { - return - try await uniffiRustCallAsync( - rustFutureFunc: { - uniffi_affine_mobile_native_fn_method_docstoragepool_mark_updates_merged( - self.uniffiClonePointer(), - FfiConverterString.lower(universalId),FfiConverterString.lower(docId),FfiConverterSequenceTimestamp.lower(updates) - ) - }, - pollFunc: ffi_affine_mobile_native_rust_future_poll_u32, - completeFunc: ffi_affine_mobile_native_rust_future_complete_u32, - freeFunc: ffi_affine_mobile_native_rust_future_free_u32, - liftFunc: FfiConverterUInt32.lift, - errorHandler: FfiConverterTypeUniffiError.lift - ) -} - -open func pushUpdate(universalId: String, docId: String, update: String)async throws -> Date { - return - try await uniffiRustCallAsync( - rustFutureFunc: { - uniffi_affine_mobile_native_fn_method_docstoragepool_push_update( - self.uniffiClonePointer(), - FfiConverterString.lower(universalId),FfiConverterString.lower(docId),FfiConverterString.lower(update) - ) - }, - pollFunc: ffi_affine_mobile_native_rust_future_poll_rust_buffer, - completeFunc: ffi_affine_mobile_native_rust_future_complete_rust_buffer, - freeFunc: ffi_affine_mobile_native_rust_future_free_rust_buffer, - liftFunc: FfiConverterTimestamp.lift, - errorHandler: FfiConverterTypeUniffiError.lift - ) -} - -open func releaseBlobs(universalId: String)async throws { - return - try await uniffiRustCallAsync( - rustFutureFunc: { - uniffi_affine_mobile_native_fn_method_docstoragepool_release_blobs( - self.uniffiClonePointer(), - FfiConverterString.lower(universalId) - ) - }, - pollFunc: ffi_affine_mobile_native_rust_future_poll_void, - completeFunc: ffi_affine_mobile_native_rust_future_complete_void, - freeFunc: ffi_affine_mobile_native_rust_future_free_void, - liftFunc: { $0 }, - errorHandler: FfiConverterTypeUniffiError.lift - ) -} - -open func setBlob(universalId: String, blob: SetBlob)async throws { - return - try await uniffiRustCallAsync( - rustFutureFunc: { - uniffi_affine_mobile_native_fn_method_docstoragepool_set_blob( - self.uniffiClonePointer(), - FfiConverterString.lower(universalId),FfiConverterTypeSetBlob.lower(blob) - ) - }, - pollFunc: ffi_affine_mobile_native_rust_future_poll_void, - completeFunc: ffi_affine_mobile_native_rust_future_complete_void, - freeFunc: ffi_affine_mobile_native_rust_future_free_void, - liftFunc: { $0 }, - errorHandler: FfiConverterTypeUniffiError.lift - ) -} - -open func setDocSnapshot(universalId: String, snapshot: DocRecord)async throws -> Bool { - return - try await uniffiRustCallAsync( - rustFutureFunc: { - uniffi_affine_mobile_native_fn_method_docstoragepool_set_doc_snapshot( - self.uniffiClonePointer(), - FfiConverterString.lower(universalId),FfiConverterTypeDocRecord.lower(snapshot) - ) - }, - pollFunc: ffi_affine_mobile_native_rust_future_poll_i8, - completeFunc: ffi_affine_mobile_native_rust_future_complete_i8, - freeFunc: ffi_affine_mobile_native_rust_future_free_i8, - liftFunc: FfiConverterBool.lift, - errorHandler: FfiConverterTypeUniffiError.lift - ) -} - -open func setPeerPulledRemoteClock(universalId: String, peer: String, docId: String, clock: Date)async throws { - return - try await uniffiRustCallAsync( - rustFutureFunc: { - uniffi_affine_mobile_native_fn_method_docstoragepool_set_peer_pulled_remote_clock( - self.uniffiClonePointer(), - FfiConverterString.lower(universalId),FfiConverterString.lower(peer),FfiConverterString.lower(docId),FfiConverterTimestamp.lower(clock) - ) - }, - pollFunc: ffi_affine_mobile_native_rust_future_poll_void, - completeFunc: ffi_affine_mobile_native_rust_future_complete_void, - freeFunc: ffi_affine_mobile_native_rust_future_free_void, - liftFunc: { $0 }, - errorHandler: FfiConverterTypeUniffiError.lift - ) -} - -open func setPeerPushedClock(universalId: String, peer: String, docId: String, clock: Date)async throws { - return - try await uniffiRustCallAsync( - rustFutureFunc: { - uniffi_affine_mobile_native_fn_method_docstoragepool_set_peer_pushed_clock( - self.uniffiClonePointer(), - FfiConverterString.lower(universalId),FfiConverterString.lower(peer),FfiConverterString.lower(docId),FfiConverterTimestamp.lower(clock) - ) - }, - pollFunc: ffi_affine_mobile_native_rust_future_poll_void, - completeFunc: ffi_affine_mobile_native_rust_future_complete_void, - freeFunc: ffi_affine_mobile_native_rust_future_free_void, - liftFunc: { $0 }, - errorHandler: FfiConverterTypeUniffiError.lift - ) -} - -open func setPeerRemoteClock(universalId: String, peer: String, docId: String, clock: Date)async throws { - return - try await uniffiRustCallAsync( - rustFutureFunc: { - uniffi_affine_mobile_native_fn_method_docstoragepool_set_peer_remote_clock( - self.uniffiClonePointer(), - FfiConverterString.lower(universalId),FfiConverterString.lower(peer),FfiConverterString.lower(docId),FfiConverterTimestamp.lower(clock) - ) - }, - pollFunc: ffi_affine_mobile_native_rust_future_poll_void, - completeFunc: ffi_affine_mobile_native_rust_future_complete_void, - freeFunc: ffi_affine_mobile_native_rust_future_free_void, - liftFunc: { $0 }, - errorHandler: FfiConverterTypeUniffiError.lift - ) -} - -open func setSpaceId(universalId: String, spaceId: String)async throws { - return - try await uniffiRustCallAsync( - rustFutureFunc: { - uniffi_affine_mobile_native_fn_method_docstoragepool_set_space_id( - self.uniffiClonePointer(), - FfiConverterString.lower(universalId),FfiConverterString.lower(spaceId) - ) - }, - pollFunc: ffi_affine_mobile_native_rust_future_poll_void, - completeFunc: ffi_affine_mobile_native_rust_future_complete_void, - freeFunc: ffi_affine_mobile_native_rust_future_free_void, - liftFunc: { $0 }, - errorHandler: FfiConverterTypeUniffiError.lift - ) -} - + open func connect(universalId: String, path: String) async throws { + return + try await uniffiRustCallAsync( + rustFutureFunc: { + uniffi_affine_mobile_native_fn_method_docstoragepool_connect( + self.uniffiClonePointer(), + FfiConverterString.lower(universalId), FfiConverterString.lower(path) + ) + }, + pollFunc: ffi_affine_mobile_native_rust_future_poll_void, + completeFunc: ffi_affine_mobile_native_rust_future_complete_void, + freeFunc: ffi_affine_mobile_native_rust_future_free_void, + liftFunc: { $0 }, + errorHandler: FfiConverterTypeUniffiError.lift + ) + } + + open func deleteBlob(universalId: String, key: String, permanently: Bool) async throws { + return + try await uniffiRustCallAsync( + rustFutureFunc: { + uniffi_affine_mobile_native_fn_method_docstoragepool_delete_blob( + self.uniffiClonePointer(), + FfiConverterString.lower(universalId), FfiConverterString.lower(key), FfiConverterBool.lower(permanently) + ) + }, + pollFunc: ffi_affine_mobile_native_rust_future_poll_void, + completeFunc: ffi_affine_mobile_native_rust_future_complete_void, + freeFunc: ffi_affine_mobile_native_rust_future_free_void, + liftFunc: { $0 }, + errorHandler: FfiConverterTypeUniffiError.lift + ) + } + + open func deleteDoc(universalId: String, docId: String) async throws { + return + try await uniffiRustCallAsync( + rustFutureFunc: { + uniffi_affine_mobile_native_fn_method_docstoragepool_delete_doc( + self.uniffiClonePointer(), + FfiConverterString.lower(universalId), FfiConverterString.lower(docId) + ) + }, + pollFunc: ffi_affine_mobile_native_rust_future_poll_void, + completeFunc: ffi_affine_mobile_native_rust_future_complete_void, + freeFunc: ffi_affine_mobile_native_rust_future_free_void, + liftFunc: { $0 }, + errorHandler: FfiConverterTypeUniffiError.lift + ) + } + + open func disconnect(universalId: String) async throws { + return + try await uniffiRustCallAsync( + rustFutureFunc: { + uniffi_affine_mobile_native_fn_method_docstoragepool_disconnect( + self.uniffiClonePointer(), + FfiConverterString.lower(universalId) + ) + }, + pollFunc: ffi_affine_mobile_native_rust_future_poll_void, + completeFunc: ffi_affine_mobile_native_rust_future_complete_void, + freeFunc: ffi_affine_mobile_native_rust_future_free_void, + liftFunc: { $0 }, + errorHandler: FfiConverterTypeUniffiError.lift + ) + } + + open func getBlob(universalId: String, key: String) async throws -> Blob? { + return + try await uniffiRustCallAsync( + rustFutureFunc: { + uniffi_affine_mobile_native_fn_method_docstoragepool_get_blob( + self.uniffiClonePointer(), + FfiConverterString.lower(universalId), FfiConverterString.lower(key) + ) + }, + pollFunc: ffi_affine_mobile_native_rust_future_poll_rust_buffer, + completeFunc: ffi_affine_mobile_native_rust_future_complete_rust_buffer, + freeFunc: ffi_affine_mobile_native_rust_future_free_rust_buffer, + liftFunc: FfiConverterOptionTypeBlob.lift, + errorHandler: FfiConverterTypeUniffiError.lift + ) + } + + open func getDocClock(universalId: String, docId: String) async throws -> DocClock? { + return + try await uniffiRustCallAsync( + rustFutureFunc: { + uniffi_affine_mobile_native_fn_method_docstoragepool_get_doc_clock( + self.uniffiClonePointer(), + FfiConverterString.lower(universalId), FfiConverterString.lower(docId) + ) + }, + pollFunc: ffi_affine_mobile_native_rust_future_poll_rust_buffer, + completeFunc: ffi_affine_mobile_native_rust_future_complete_rust_buffer, + freeFunc: ffi_affine_mobile_native_rust_future_free_rust_buffer, + liftFunc: FfiConverterOptionTypeDocClock.lift, + errorHandler: FfiConverterTypeUniffiError.lift + ) + } + + open func getDocClocks(universalId: String, after: Int64?) async throws -> [DocClock] { + return + try await uniffiRustCallAsync( + rustFutureFunc: { + uniffi_affine_mobile_native_fn_method_docstoragepool_get_doc_clocks( + self.uniffiClonePointer(), + FfiConverterString.lower(universalId), FfiConverterOptionInt64.lower(after) + ) + }, + pollFunc: ffi_affine_mobile_native_rust_future_poll_rust_buffer, + completeFunc: ffi_affine_mobile_native_rust_future_complete_rust_buffer, + freeFunc: ffi_affine_mobile_native_rust_future_free_rust_buffer, + liftFunc: FfiConverterSequenceTypeDocClock.lift, + errorHandler: FfiConverterTypeUniffiError.lift + ) + } + + open func getDocSnapshot(universalId: String, docId: String) async throws -> DocRecord? { + return + try await uniffiRustCallAsync( + rustFutureFunc: { + uniffi_affine_mobile_native_fn_method_docstoragepool_get_doc_snapshot( + self.uniffiClonePointer(), + FfiConverterString.lower(universalId), FfiConverterString.lower(docId) + ) + }, + pollFunc: ffi_affine_mobile_native_rust_future_poll_rust_buffer, + completeFunc: ffi_affine_mobile_native_rust_future_complete_rust_buffer, + freeFunc: ffi_affine_mobile_native_rust_future_free_rust_buffer, + liftFunc: FfiConverterOptionTypeDocRecord.lift, + errorHandler: FfiConverterTypeUniffiError.lift + ) + } + open func getDocUpdates(universalId: String, docId: String) async throws -> [DocUpdate] { + return + try await uniffiRustCallAsync( + rustFutureFunc: { + uniffi_affine_mobile_native_fn_method_docstoragepool_get_doc_updates( + self.uniffiClonePointer(), + FfiConverterString.lower(universalId), FfiConverterString.lower(docId) + ) + }, + pollFunc: ffi_affine_mobile_native_rust_future_poll_rust_buffer, + completeFunc: ffi_affine_mobile_native_rust_future_complete_rust_buffer, + freeFunc: ffi_affine_mobile_native_rust_future_free_rust_buffer, + liftFunc: FfiConverterSequenceTypeDocUpdate.lift, + errorHandler: FfiConverterTypeUniffiError.lift + ) + } + + open func getPeerPulledRemoteClock(universalId: String, peer: String, docId: String) async throws -> DocClock { + return + try await uniffiRustCallAsync( + rustFutureFunc: { + uniffi_affine_mobile_native_fn_method_docstoragepool_get_peer_pulled_remote_clock( + self.uniffiClonePointer(), + FfiConverterString.lower(universalId), FfiConverterString.lower(peer), FfiConverterString.lower(docId) + ) + }, + pollFunc: ffi_affine_mobile_native_rust_future_poll_rust_buffer, + completeFunc: ffi_affine_mobile_native_rust_future_complete_rust_buffer, + freeFunc: ffi_affine_mobile_native_rust_future_free_rust_buffer, + liftFunc: FfiConverterTypeDocClock.lift, + errorHandler: FfiConverterTypeUniffiError.lift + ) + } + + open func getPeerPulledRemoteClocks(universalId: String, peer: String) async throws -> [DocClock] { + return + try await uniffiRustCallAsync( + rustFutureFunc: { + uniffi_affine_mobile_native_fn_method_docstoragepool_get_peer_pulled_remote_clocks( + self.uniffiClonePointer(), + FfiConverterString.lower(universalId), FfiConverterString.lower(peer) + ) + }, + pollFunc: ffi_affine_mobile_native_rust_future_poll_rust_buffer, + completeFunc: ffi_affine_mobile_native_rust_future_complete_rust_buffer, + freeFunc: ffi_affine_mobile_native_rust_future_free_rust_buffer, + liftFunc: FfiConverterSequenceTypeDocClock.lift, + errorHandler: FfiConverterTypeUniffiError.lift + ) + } + + open func getPeerPushedClocks(universalId: String, peer: String) async throws -> [DocClock] { + return + try await uniffiRustCallAsync( + rustFutureFunc: { + uniffi_affine_mobile_native_fn_method_docstoragepool_get_peer_pushed_clocks( + self.uniffiClonePointer(), + FfiConverterString.lower(universalId), FfiConverterString.lower(peer) + ) + }, + pollFunc: ffi_affine_mobile_native_rust_future_poll_rust_buffer, + completeFunc: ffi_affine_mobile_native_rust_future_complete_rust_buffer, + freeFunc: ffi_affine_mobile_native_rust_future_free_rust_buffer, + liftFunc: FfiConverterSequenceTypeDocClock.lift, + errorHandler: FfiConverterTypeUniffiError.lift + ) + } + + open func getPeerRemoteClock(universalId: String, peer: String, docId: String) async throws -> DocClock { + return + try await uniffiRustCallAsync( + rustFutureFunc: { + uniffi_affine_mobile_native_fn_method_docstoragepool_get_peer_remote_clock( + self.uniffiClonePointer(), + FfiConverterString.lower(universalId), FfiConverterString.lower(peer), FfiConverterString.lower(docId) + ) + }, + pollFunc: ffi_affine_mobile_native_rust_future_poll_rust_buffer, + completeFunc: ffi_affine_mobile_native_rust_future_complete_rust_buffer, + freeFunc: ffi_affine_mobile_native_rust_future_free_rust_buffer, + liftFunc: FfiConverterTypeDocClock.lift, + errorHandler: FfiConverterTypeUniffiError.lift + ) + } + + open func getPeerRemoteClocks(universalId: String, peer: String) async throws -> [DocClock] { + return + try await uniffiRustCallAsync( + rustFutureFunc: { + uniffi_affine_mobile_native_fn_method_docstoragepool_get_peer_remote_clocks( + self.uniffiClonePointer(), + FfiConverterString.lower(universalId), FfiConverterString.lower(peer) + ) + }, + pollFunc: ffi_affine_mobile_native_rust_future_poll_rust_buffer, + completeFunc: ffi_affine_mobile_native_rust_future_complete_rust_buffer, + freeFunc: ffi_affine_mobile_native_rust_future_free_rust_buffer, + liftFunc: FfiConverterSequenceTypeDocClock.lift, + errorHandler: FfiConverterTypeUniffiError.lift + ) + } + + open func listBlobs(universalId: String) async throws -> [ListedBlob] { + return + try await uniffiRustCallAsync( + rustFutureFunc: { + uniffi_affine_mobile_native_fn_method_docstoragepool_list_blobs( + self.uniffiClonePointer(), + FfiConverterString.lower(universalId) + ) + }, + pollFunc: ffi_affine_mobile_native_rust_future_poll_rust_buffer, + completeFunc: ffi_affine_mobile_native_rust_future_complete_rust_buffer, + freeFunc: ffi_affine_mobile_native_rust_future_free_rust_buffer, + liftFunc: FfiConverterSequenceTypeListedBlob.lift, + errorHandler: FfiConverterTypeUniffiError.lift + ) + } + + open func markUpdatesMerged(universalId: String, docId: String, updates: [Int64]) async throws -> UInt32 { + return + try await uniffiRustCallAsync( + rustFutureFunc: { + uniffi_affine_mobile_native_fn_method_docstoragepool_mark_updates_merged( + self.uniffiClonePointer(), + FfiConverterString.lower(universalId), FfiConverterString.lower(docId), FfiConverterSequenceInt64.lower(updates) + ) + }, + pollFunc: ffi_affine_mobile_native_rust_future_poll_u32, + completeFunc: ffi_affine_mobile_native_rust_future_complete_u32, + freeFunc: ffi_affine_mobile_native_rust_future_free_u32, + liftFunc: FfiConverterUInt32.lift, + errorHandler: FfiConverterTypeUniffiError.lift + ) + } + + open func pushUpdate(universalId: String, docId: String, update: String) async throws -> Int64 { + return + try await uniffiRustCallAsync( + rustFutureFunc: { + uniffi_affine_mobile_native_fn_method_docstoragepool_push_update( + self.uniffiClonePointer(), + FfiConverterString.lower(universalId), FfiConverterString.lower(docId), FfiConverterString.lower(update) + ) + }, + pollFunc: ffi_affine_mobile_native_rust_future_poll_i64, + completeFunc: ffi_affine_mobile_native_rust_future_complete_i64, + freeFunc: ffi_affine_mobile_native_rust_future_free_i64, + liftFunc: FfiConverterInt64.lift, + errorHandler: FfiConverterTypeUniffiError.lift + ) + } + + open func releaseBlobs(universalId: String) async throws { + return + try await uniffiRustCallAsync( + rustFutureFunc: { + uniffi_affine_mobile_native_fn_method_docstoragepool_release_blobs( + self.uniffiClonePointer(), + FfiConverterString.lower(universalId) + ) + }, + pollFunc: ffi_affine_mobile_native_rust_future_poll_void, + completeFunc: ffi_affine_mobile_native_rust_future_complete_void, + freeFunc: ffi_affine_mobile_native_rust_future_free_void, + liftFunc: { $0 }, + errorHandler: FfiConverterTypeUniffiError.lift + ) + } + + open func setBlob(universalId: String, blob: SetBlob) async throws { + return + try await uniffiRustCallAsync( + rustFutureFunc: { + uniffi_affine_mobile_native_fn_method_docstoragepool_set_blob( + self.uniffiClonePointer(), + FfiConverterString.lower(universalId), FfiConverterTypeSetBlob.lower(blob) + ) + }, + pollFunc: ffi_affine_mobile_native_rust_future_poll_void, + completeFunc: ffi_affine_mobile_native_rust_future_complete_void, + freeFunc: ffi_affine_mobile_native_rust_future_free_void, + liftFunc: { $0 }, + errorHandler: FfiConverterTypeUniffiError.lift + ) + } + + open func setDocSnapshot(universalId: String, snapshot: DocRecord) async throws -> Bool { + return + try await uniffiRustCallAsync( + rustFutureFunc: { + uniffi_affine_mobile_native_fn_method_docstoragepool_set_doc_snapshot( + self.uniffiClonePointer(), + FfiConverterString.lower(universalId), FfiConverterTypeDocRecord.lower(snapshot) + ) + }, + pollFunc: ffi_affine_mobile_native_rust_future_poll_i8, + completeFunc: ffi_affine_mobile_native_rust_future_complete_i8, + freeFunc: ffi_affine_mobile_native_rust_future_free_i8, + liftFunc: FfiConverterBool.lift, + errorHandler: FfiConverterTypeUniffiError.lift + ) + } + + open func setPeerPulledRemoteClock(universalId: String, peer: String, docId: String, clock: Int64) async throws { + return + try await uniffiRustCallAsync( + rustFutureFunc: { + uniffi_affine_mobile_native_fn_method_docstoragepool_set_peer_pulled_remote_clock( + self.uniffiClonePointer(), + FfiConverterString.lower(universalId), FfiConverterString.lower(peer), FfiConverterString.lower(docId), FfiConverterInt64.lower(clock) + ) + }, + pollFunc: ffi_affine_mobile_native_rust_future_poll_void, + completeFunc: ffi_affine_mobile_native_rust_future_complete_void, + freeFunc: ffi_affine_mobile_native_rust_future_free_void, + liftFunc: { $0 }, + errorHandler: FfiConverterTypeUniffiError.lift + ) + } + + open func setPeerPushedClock(universalId: String, peer: String, docId: String, clock: Int64) async throws { + return + try await uniffiRustCallAsync( + rustFutureFunc: { + uniffi_affine_mobile_native_fn_method_docstoragepool_set_peer_pushed_clock( + self.uniffiClonePointer(), + FfiConverterString.lower(universalId), FfiConverterString.lower(peer), FfiConverterString.lower(docId), FfiConverterInt64.lower(clock) + ) + }, + pollFunc: ffi_affine_mobile_native_rust_future_poll_void, + completeFunc: ffi_affine_mobile_native_rust_future_complete_void, + freeFunc: ffi_affine_mobile_native_rust_future_free_void, + liftFunc: { $0 }, + errorHandler: FfiConverterTypeUniffiError.lift + ) + } + + open func setPeerRemoteClock(universalId: String, peer: String, docId: String, clock: Int64) async throws { + return + try await uniffiRustCallAsync( + rustFutureFunc: { + uniffi_affine_mobile_native_fn_method_docstoragepool_set_peer_remote_clock( + self.uniffiClonePointer(), + FfiConverterString.lower(universalId), FfiConverterString.lower(peer), FfiConverterString.lower(docId), FfiConverterInt64.lower(clock) + ) + }, + pollFunc: ffi_affine_mobile_native_rust_future_poll_void, + completeFunc: ffi_affine_mobile_native_rust_future_complete_void, + freeFunc: ffi_affine_mobile_native_rust_future_free_void, + liftFunc: { $0 }, + errorHandler: FfiConverterTypeUniffiError.lift + ) + } + + open func setSpaceId(universalId: String, spaceId: String) async throws { + return + try await uniffiRustCallAsync( + rustFutureFunc: { + uniffi_affine_mobile_native_fn_method_docstoragepool_set_space_id( + self.uniffiClonePointer(), + FfiConverterString.lower(universalId), FfiConverterString.lower(spaceId) + ) + }, + pollFunc: ffi_affine_mobile_native_rust_future_poll_void, + completeFunc: ffi_affine_mobile_native_rust_future_complete_void, + freeFunc: ffi_affine_mobile_native_rust_future_free_void, + liftFunc: { $0 }, + errorHandler: FfiConverterTypeUniffiError.lift + ) + } } #if swift(>=5.8) -@_documentation(visibility: private) + @_documentation(visibility: private) #endif public struct FfiConverterTypeDocStoragePool: FfiConverter { - typealias FfiType = UnsafeMutableRawPointer typealias SwiftType = DocStoragePool @@ -1093,7 +1045,7 @@ public struct FfiConverterTypeDocStoragePool: FfiConverter { // The Rust code won't compile if a pointer won't fit in a UInt64. // We have to go via `UInt` because that's the thing that's the size of a pointer. let ptr = UnsafeMutableRawPointer(bitPattern: UInt(truncatingIfNeeded: v)) - if (ptr == nil) { + if ptr == nil { throw UniffiInternalError.unexpectedNullPointer } return try lift(ptr!) @@ -1106,34 +1058,30 @@ public struct FfiConverterTypeDocStoragePool: FfiConverter { } } - - - #if swift(>=5.8) -@_documentation(visibility: private) + @_documentation(visibility: private) #endif public func FfiConverterTypeDocStoragePool_lift(_ pointer: UnsafeMutableRawPointer) throws -> DocStoragePool { return try FfiConverterTypeDocStoragePool.lift(pointer) } #if swift(>=5.8) -@_documentation(visibility: private) + @_documentation(visibility: private) #endif public func FfiConverterTypeDocStoragePool_lower(_ value: DocStoragePool) -> UnsafeMutableRawPointer { return FfiConverterTypeDocStoragePool.lower(value) } - public struct Blob { public var key: String public var data: String public var mime: String public var size: Int64 - public var createdAt: Date + public var createdAt: Int64 // Default memberwise initializers are never public by default, so we // declare one manually. - public init(key: String, data: String, mime: String, size: Int64, createdAt: Date) { + public init(key: String, data: String, mime: String, size: Int64, createdAt: Int64) { self.key = key self.data = data self.mime = mime @@ -1142,10 +1090,8 @@ public struct Blob { } } - - extension Blob: Equatable, Hashable { - public static func ==(lhs: Blob, rhs: Blob) -> Bool { + public static func == (lhs: Blob, rhs: Blob) -> Bool { if lhs.key != rhs.key { return false } @@ -1173,20 +1119,19 @@ extension Blob: Equatable, Hashable { } } - #if swift(>=5.8) -@_documentation(visibility: private) + @_documentation(visibility: private) #endif public struct FfiConverterTypeBlob: FfiConverterRustBuffer { public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> Blob { return try Blob( - key: FfiConverterString.read(from: &buf), - data: FfiConverterString.read(from: &buf), - mime: FfiConverterString.read(from: &buf), - size: FfiConverterInt64.read(from: &buf), - createdAt: FfiConverterTimestamp.read(from: &buf) - ) + key: FfiConverterString.read(from: &buf), + data: FfiConverterString.read(from: &buf), + mime: FfiConverterString.read(from: &buf), + size: FfiConverterInt64.read(from: &buf), + createdAt: FfiConverterInt64.read(from: &buf) + ) } public static func write(_ value: Blob, into buf: inout [UInt8]) { @@ -1194,42 +1139,38 @@ public struct FfiConverterTypeBlob: FfiConverterRustBuffer { FfiConverterString.write(value.data, into: &buf) FfiConverterString.write(value.mime, into: &buf) FfiConverterInt64.write(value.size, into: &buf) - FfiConverterTimestamp.write(value.createdAt, into: &buf) + FfiConverterInt64.write(value.createdAt, into: &buf) } } - #if swift(>=5.8) -@_documentation(visibility: private) + @_documentation(visibility: private) #endif public func FfiConverterTypeBlob_lift(_ buf: RustBuffer) throws -> Blob { return try FfiConverterTypeBlob.lift(buf) } #if swift(>=5.8) -@_documentation(visibility: private) + @_documentation(visibility: private) #endif public func FfiConverterTypeBlob_lower(_ value: Blob) -> RustBuffer { return FfiConverterTypeBlob.lower(value) } - public struct DocClock { public var docId: String - public var timestamp: Date + public var timestamp: Int64 // Default memberwise initializers are never public by default, so we // declare one manually. - public init(docId: String, timestamp: Date) { + public init(docId: String, timestamp: Int64) { self.docId = docId self.timestamp = timestamp } } - - extension DocClock: Equatable, Hashable { - public static func ==(lhs: DocClock, rhs: DocClock) -> Bool { + public static func == (lhs: DocClock, rhs: DocClock) -> Bool { if lhs.docId != rhs.docId { return false } @@ -1245,59 +1186,54 @@ extension DocClock: Equatable, Hashable { } } - #if swift(>=5.8) -@_documentation(visibility: private) + @_documentation(visibility: private) #endif public struct FfiConverterTypeDocClock: FfiConverterRustBuffer { public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> DocClock { return try DocClock( - docId: FfiConverterString.read(from: &buf), - timestamp: FfiConverterTimestamp.read(from: &buf) - ) + docId: FfiConverterString.read(from: &buf), + timestamp: FfiConverterInt64.read(from: &buf) + ) } public static func write(_ value: DocClock, into buf: inout [UInt8]) { FfiConverterString.write(value.docId, into: &buf) - FfiConverterTimestamp.write(value.timestamp, into: &buf) + FfiConverterInt64.write(value.timestamp, into: &buf) } } - #if swift(>=5.8) -@_documentation(visibility: private) + @_documentation(visibility: private) #endif public func FfiConverterTypeDocClock_lift(_ buf: RustBuffer) throws -> DocClock { return try FfiConverterTypeDocClock.lift(buf) } #if swift(>=5.8) -@_documentation(visibility: private) + @_documentation(visibility: private) #endif public func FfiConverterTypeDocClock_lower(_ value: DocClock) -> RustBuffer { return FfiConverterTypeDocClock.lower(value) } - public struct DocRecord { public var docId: String public var bin: String - public var timestamp: Date + public var timestamp: Int64 // Default memberwise initializers are never public by default, so we // declare one manually. - public init(docId: String, bin: String, timestamp: Date) { + public init(docId: String, bin: String, timestamp: Int64) { self.docId = docId self.bin = bin self.timestamp = timestamp } } - - extension DocRecord: Equatable, Hashable { - public static func ==(lhs: DocRecord, rhs: DocRecord) -> Bool { + public static func == (lhs: DocRecord, rhs: DocRecord) -> Bool { if lhs.docId != rhs.docId { return false } @@ -1317,61 +1253,56 @@ extension DocRecord: Equatable, Hashable { } } - #if swift(>=5.8) -@_documentation(visibility: private) + @_documentation(visibility: private) #endif public struct FfiConverterTypeDocRecord: FfiConverterRustBuffer { public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> DocRecord { return try DocRecord( - docId: FfiConverterString.read(from: &buf), - bin: FfiConverterString.read(from: &buf), - timestamp: FfiConverterTimestamp.read(from: &buf) - ) + docId: FfiConverterString.read(from: &buf), + bin: FfiConverterString.read(from: &buf), + timestamp: FfiConverterInt64.read(from: &buf) + ) } public static func write(_ value: DocRecord, into buf: inout [UInt8]) { FfiConverterString.write(value.docId, into: &buf) FfiConverterString.write(value.bin, into: &buf) - FfiConverterTimestamp.write(value.timestamp, into: &buf) + FfiConverterInt64.write(value.timestamp, into: &buf) } } - #if swift(>=5.8) -@_documentation(visibility: private) + @_documentation(visibility: private) #endif public func FfiConverterTypeDocRecord_lift(_ buf: RustBuffer) throws -> DocRecord { return try FfiConverterTypeDocRecord.lift(buf) } #if swift(>=5.8) -@_documentation(visibility: private) + @_documentation(visibility: private) #endif public func FfiConverterTypeDocRecord_lower(_ value: DocRecord) -> RustBuffer { return FfiConverterTypeDocRecord.lower(value) } - public struct DocUpdate { public var docId: String - public var timestamp: Date + public var timestamp: Int64 public var bin: String // Default memberwise initializers are never public by default, so we // declare one manually. - public init(docId: String, timestamp: Date, bin: String) { + public init(docId: String, timestamp: Int64, bin: String) { self.docId = docId self.timestamp = timestamp self.bin = bin } } - - extension DocUpdate: Equatable, Hashable { - public static func ==(lhs: DocUpdate, rhs: DocUpdate) -> Bool { + public static func == (lhs: DocUpdate, rhs: DocUpdate) -> Bool { if lhs.docId != rhs.docId { return false } @@ -1391,52 +1322,49 @@ extension DocUpdate: Equatable, Hashable { } } - #if swift(>=5.8) -@_documentation(visibility: private) + @_documentation(visibility: private) #endif public struct FfiConverterTypeDocUpdate: FfiConverterRustBuffer { public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> DocUpdate { return try DocUpdate( - docId: FfiConverterString.read(from: &buf), - timestamp: FfiConverterTimestamp.read(from: &buf), + docId: FfiConverterString.read(from: &buf), + timestamp: FfiConverterInt64.read(from: &buf), bin: FfiConverterString.read(from: &buf) - ) + ) } public static func write(_ value: DocUpdate, into buf: inout [UInt8]) { FfiConverterString.write(value.docId, into: &buf) - FfiConverterTimestamp.write(value.timestamp, into: &buf) + FfiConverterInt64.write(value.timestamp, into: &buf) FfiConverterString.write(value.bin, into: &buf) } } - #if swift(>=5.8) -@_documentation(visibility: private) + @_documentation(visibility: private) #endif public func FfiConverterTypeDocUpdate_lift(_ buf: RustBuffer) throws -> DocUpdate { return try FfiConverterTypeDocUpdate.lift(buf) } #if swift(>=5.8) -@_documentation(visibility: private) + @_documentation(visibility: private) #endif public func FfiConverterTypeDocUpdate_lower(_ value: DocUpdate) -> RustBuffer { return FfiConverterTypeDocUpdate.lower(value) } - public struct ListedBlob { public var key: String public var size: Int64 public var mime: String - public var createdAt: Date + public var createdAt: Int64 // Default memberwise initializers are never public by default, so we // declare one manually. - public init(key: String, size: Int64, mime: String, createdAt: Date) { + public init(key: String, size: Int64, mime: String, createdAt: Int64) { self.key = key self.size = size self.mime = mime @@ -1444,10 +1372,8 @@ public struct ListedBlob { } } - - extension ListedBlob: Equatable, Hashable { - public static func ==(lhs: ListedBlob, rhs: ListedBlob) -> Bool { + public static func == (lhs: ListedBlob, rhs: ListedBlob) -> Bool { if lhs.key != rhs.key { return false } @@ -1471,45 +1397,42 @@ extension ListedBlob: Equatable, Hashable { } } - #if swift(>=5.8) -@_documentation(visibility: private) + @_documentation(visibility: private) #endif public struct FfiConverterTypeListedBlob: FfiConverterRustBuffer { public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> ListedBlob { return try ListedBlob( - key: FfiConverterString.read(from: &buf), - size: FfiConverterInt64.read(from: &buf), - mime: FfiConverterString.read(from: &buf), - createdAt: FfiConverterTimestamp.read(from: &buf) - ) + key: FfiConverterString.read(from: &buf), + size: FfiConverterInt64.read(from: &buf), + mime: FfiConverterString.read(from: &buf), + createdAt: FfiConverterInt64.read(from: &buf) + ) } public static func write(_ value: ListedBlob, into buf: inout [UInt8]) { FfiConverterString.write(value.key, into: &buf) FfiConverterInt64.write(value.size, into: &buf) FfiConverterString.write(value.mime, into: &buf) - FfiConverterTimestamp.write(value.createdAt, into: &buf) + FfiConverterInt64.write(value.createdAt, into: &buf) } } - #if swift(>=5.8) -@_documentation(visibility: private) + @_documentation(visibility: private) #endif public func FfiConverterTypeListedBlob_lift(_ buf: RustBuffer) throws -> ListedBlob { return try FfiConverterTypeListedBlob.lift(buf) } #if swift(>=5.8) -@_documentation(visibility: private) + @_documentation(visibility: private) #endif public func FfiConverterTypeListedBlob_lower(_ value: ListedBlob) -> RustBuffer { return FfiConverterTypeListedBlob.lower(value) } - public struct SetBlob { public var key: String public var data: String @@ -1524,10 +1447,8 @@ public struct SetBlob { } } - - extension SetBlob: Equatable, Hashable { - public static func ==(lhs: SetBlob, rhs: SetBlob) -> Bool { + public static func == (lhs: SetBlob, rhs: SetBlob) -> Bool { if lhs.key != rhs.key { return false } @@ -1547,18 +1468,17 @@ extension SetBlob: Equatable, Hashable { } } - #if swift(>=5.8) -@_documentation(visibility: private) + @_documentation(visibility: private) #endif public struct FfiConverterTypeSetBlob: FfiConverterRustBuffer { public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> SetBlob { return try SetBlob( - key: FfiConverterString.read(from: &buf), - data: FfiConverterString.read(from: &buf), + key: FfiConverterString.read(from: &buf), + data: FfiConverterString.read(from: &buf), mime: FfiConverterString.read(from: &buf) - ) + ) } public static func write(_ value: SetBlob, into buf: inout [UInt8]) { @@ -1568,35 +1488,30 @@ public struct FfiConverterTypeSetBlob: FfiConverterRustBuffer { } } - #if swift(>=5.8) -@_documentation(visibility: private) + @_documentation(visibility: private) #endif public func FfiConverterTypeSetBlob_lift(_ buf: RustBuffer) throws -> SetBlob { return try FfiConverterTypeSetBlob.lift(buf) } #if swift(>=5.8) -@_documentation(visibility: private) + @_documentation(visibility: private) #endif public func FfiConverterTypeSetBlob_lower(_ value: SetBlob) -> RustBuffer { return FfiConverterTypeSetBlob.lower(value) } - public enum UniffiError { - - - case Err(String ) case Base64DecodingError(String ) + case TimestampDecodingError } - #if swift(>=5.8) -@_documentation(visibility: private) + @_documentation(visibility: private) #endif public struct FfiConverterTypeUniffiError: FfiConverterRustBuffer { typealias SwiftType = UniffiError @@ -1604,42 +1519,33 @@ public struct FfiConverterTypeUniffiError: FfiConverterRustBuffer { public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> UniffiError { let variant: Int32 = try readInt(&buf) switch variant { - - - - - case 1: return .Err( - try FfiConverterString.read(from: &buf) + case 1: return try .Err( + FfiConverterString.read(from: &buf) ) - case 2: return .Base64DecodingError( - try FfiConverterString.read(from: &buf) + case 2: return try .Base64DecodingError( + FfiConverterString.read(from: &buf) ) - - default: throw UniffiInternalError.unexpectedEnumCase + case 3: return .TimestampDecodingError + default: throw UniffiInternalError.unexpectedEnumCase } } public static func write(_ value: UniffiError, into buf: inout [UInt8]) { switch value { - - - - - case let .Err(v1): writeInt(&buf, Int32(1)) FfiConverterString.write(v1, into: &buf) - - + case let .Base64DecodingError(v1): writeInt(&buf, Int32(2)) FfiConverterString.write(v1, into: &buf) - + + case .TimestampDecodingError: + writeInt(&buf, Int32(3)) } } } - extension UniffiError: Equatable, Hashable {} extension UniffiError: Foundation.LocalizedError { @@ -1649,10 +1555,10 @@ extension UniffiError: Foundation.LocalizedError { } #if swift(>=5.8) -@_documentation(visibility: private) + @_documentation(visibility: private) #endif -fileprivate struct FfiConverterOptionTimestamp: FfiConverterRustBuffer { - typealias SwiftType = Date? +private struct FfiConverterOptionInt64: FfiConverterRustBuffer { + typealias SwiftType = Int64? public static func write(_ value: SwiftType, into buf: inout [UInt8]) { guard let value = value else { @@ -1660,22 +1566,22 @@ fileprivate struct FfiConverterOptionTimestamp: FfiConverterRustBuffer { return } writeInt(&buf, Int8(1)) - FfiConverterTimestamp.write(value, into: &buf) + FfiConverterInt64.write(value, into: &buf) } public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> SwiftType { switch try readInt(&buf) as Int8 { case 0: return nil - case 1: return try FfiConverterTimestamp.read(from: &buf) + case 1: return try FfiConverterInt64.read(from: &buf) default: throw UniffiInternalError.unexpectedOptionalTag } } } #if swift(>=5.8) -@_documentation(visibility: private) + @_documentation(visibility: private) #endif -fileprivate struct FfiConverterOptionTypeBlob: FfiConverterRustBuffer { +private struct FfiConverterOptionTypeBlob: FfiConverterRustBuffer { typealias SwiftType = Blob? public static func write(_ value: SwiftType, into buf: inout [UInt8]) { @@ -1697,9 +1603,9 @@ fileprivate struct FfiConverterOptionTypeBlob: FfiConverterRustBuffer { } #if swift(>=5.8) -@_documentation(visibility: private) + @_documentation(visibility: private) #endif -fileprivate struct FfiConverterOptionTypeDocClock: FfiConverterRustBuffer { +private struct FfiConverterOptionTypeDocClock: FfiConverterRustBuffer { typealias SwiftType = DocClock? public static func write(_ value: SwiftType, into buf: inout [UInt8]) { @@ -1721,9 +1627,9 @@ fileprivate struct FfiConverterOptionTypeDocClock: FfiConverterRustBuffer { } #if swift(>=5.8) -@_documentation(visibility: private) + @_documentation(visibility: private) #endif -fileprivate struct FfiConverterOptionTypeDocRecord: FfiConverterRustBuffer { +private struct FfiConverterOptionTypeDocRecord: FfiConverterRustBuffer { typealias SwiftType = DocRecord? public static func write(_ value: SwiftType, into buf: inout [UInt8]) { @@ -1745,34 +1651,34 @@ fileprivate struct FfiConverterOptionTypeDocRecord: FfiConverterRustBuffer { } #if swift(>=5.8) -@_documentation(visibility: private) + @_documentation(visibility: private) #endif -fileprivate struct FfiConverterSequenceTimestamp: FfiConverterRustBuffer { - typealias SwiftType = [Date] +private struct FfiConverterSequenceInt64: FfiConverterRustBuffer { + typealias SwiftType = [Int64] - public static func write(_ value: [Date], into buf: inout [UInt8]) { + public static func write(_ value: [Int64], into buf: inout [UInt8]) { let len = Int32(value.count) writeInt(&buf, len) for item in value { - FfiConverterTimestamp.write(item, into: &buf) + FfiConverterInt64.write(item, into: &buf) } } - public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> [Date] { + public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> [Int64] { let len: Int32 = try readInt(&buf) - var seq = [Date]() + var seq = [Int64]() seq.reserveCapacity(Int(len)) for _ in 0 ..< len { - seq.append(try FfiConverterTimestamp.read(from: &buf)) + try seq.append(FfiConverterInt64.read(from: &buf)) } return seq } } #if swift(>=5.8) -@_documentation(visibility: private) + @_documentation(visibility: private) #endif -fileprivate struct FfiConverterSequenceTypeDocClock: FfiConverterRustBuffer { +private struct FfiConverterSequenceTypeDocClock: FfiConverterRustBuffer { typealias SwiftType = [DocClock] public static func write(_ value: [DocClock], into buf: inout [UInt8]) { @@ -1788,16 +1694,16 @@ fileprivate struct FfiConverterSequenceTypeDocClock: FfiConverterRustBuffer { var seq = [DocClock]() seq.reserveCapacity(Int(len)) for _ in 0 ..< len { - seq.append(try FfiConverterTypeDocClock.read(from: &buf)) + try seq.append(FfiConverterTypeDocClock.read(from: &buf)) } return seq } } #if swift(>=5.8) -@_documentation(visibility: private) + @_documentation(visibility: private) #endif -fileprivate struct FfiConverterSequenceTypeDocUpdate: FfiConverterRustBuffer { +private struct FfiConverterSequenceTypeDocUpdate: FfiConverterRustBuffer { typealias SwiftType = [DocUpdate] public static func write(_ value: [DocUpdate], into buf: inout [UInt8]) { @@ -1813,16 +1719,16 @@ fileprivate struct FfiConverterSequenceTypeDocUpdate: FfiConverterRustBuffer { var seq = [DocUpdate]() seq.reserveCapacity(Int(len)) for _ in 0 ..< len { - seq.append(try FfiConverterTypeDocUpdate.read(from: &buf)) + try seq.append(FfiConverterTypeDocUpdate.read(from: &buf)) } return seq } } #if swift(>=5.8) -@_documentation(visibility: private) + @_documentation(visibility: private) #endif -fileprivate struct FfiConverterSequenceTypeListedBlob: FfiConverterRustBuffer { +private struct FfiConverterSequenceTypeListedBlob: FfiConverterRustBuffer { typealias SwiftType = [ListedBlob] public static func write(_ value: [ListedBlob], into buf: inout [UInt8]) { @@ -1838,21 +1744,22 @@ fileprivate struct FfiConverterSequenceTypeListedBlob: FfiConverterRustBuffer { var seq = [ListedBlob]() seq.reserveCapacity(Int(len)) for _ in 0 ..< len { - seq.append(try FfiConverterTypeListedBlob.read(from: &buf)) + try seq.append(FfiConverterTypeListedBlob.read(from: &buf)) } return seq } } + private let UNIFFI_RUST_FUTURE_POLL_READY: Int8 = 0 private let UNIFFI_RUST_FUTURE_POLL_MAYBE_READY: Int8 = 1 -fileprivate let uniffiContinuationHandleMap = UniffiHandleMap>() +private let uniffiContinuationHandleMap = UniffiHandleMap>() -fileprivate func uniffiRustCallAsync( +private func uniffiRustCallAsync( rustFutureFunc: () -> UInt64, - pollFunc: (UInt64, @escaping UniffiRustFutureContinuationCallback, UInt64) -> (), + pollFunc: (UInt64, @escaping UniffiRustFutureContinuationCallback, UInt64) -> Void, completeFunc: (UInt64, UnsafeMutablePointer) -> F, - freeFunc: (UInt64) -> (), + freeFunc: (UInt64) -> Void, liftFunc: (F) throws -> T, errorHandler: ((RustBuffer) throws -> Swift.Error)? ) async throws -> T { @@ -1863,7 +1770,7 @@ fileprivate func uniffiRustCallAsync( defer { freeFunc(rustFuture) } - var pollResult: Int8; + var pollResult: Int8 repeat { pollResult = await withUnsafeContinuation { pollFunc( @@ -1882,20 +1789,28 @@ fileprivate func uniffiRustCallAsync( // Callback handlers for an async calls. These are invoked by Rust when the future is ready. They // lift the return value or error and resume the suspended function. -fileprivate func uniffiFutureContinuationCallback(handle: UInt64, pollResult: Int8) { +private func uniffiFutureContinuationCallback(handle: UInt64, pollResult: Int8) { if let continuation = try? uniffiContinuationHandleMap.remove(handle: handle) { continuation.resume(returning: pollResult) } else { print("uniffiFutureContinuationCallback invalid handle") } } + public func hashcashMint(resource: String, bits: UInt32) -> String { - return try! FfiConverterString.lift(try! rustCall() { - uniffi_affine_mobile_native_fn_func_hashcash_mint( - FfiConverterString.lower(resource), - FfiConverterUInt32.lower(bits),$0 - ) -}) + return try! FfiConverterString.lift(try! rustCall { + uniffi_affine_mobile_native_fn_func_hashcash_mint( + FfiConverterString.lower(resource), + FfiConverterUInt32.lower(bits), $0 + ) + }) +} + +public func newDocStoragePool() -> DocStoragePool { + return try! FfiConverterTypeDocStoragePool.lift(try! rustCall { + uniffi_affine_mobile_native_fn_func_new_doc_storage_pool($0 + ) + }) } private enum InitializationResult { @@ -1903,6 +1818,7 @@ private enum InitializationResult { case contractVersionMismatch case apiChecksumMismatch } + // Use a global variable to perform the versioning checks. Swift ensures that // the code inside is only computed once. private var initializationResult: InitializationResult = { @@ -1913,82 +1829,85 @@ private var initializationResult: InitializationResult = { if bindings_contract_version != scaffolding_contract_version { return InitializationResult.contractVersionMismatch } - if (uniffi_affine_mobile_native_checksum_func_hashcash_mint() != 23633) { + if uniffi_affine_mobile_native_checksum_func_hashcash_mint() != 23633 { + return InitializationResult.apiChecksumMismatch + } + if uniffi_affine_mobile_native_checksum_func_new_doc_storage_pool() != 32882 { return InitializationResult.apiChecksumMismatch } - if (uniffi_affine_mobile_native_checksum_method_docstoragepool_clear_clocks() != 51151) { + if uniffi_affine_mobile_native_checksum_method_docstoragepool_clear_clocks() != 51151 { return InitializationResult.apiChecksumMismatch } - if (uniffi_affine_mobile_native_checksum_method_docstoragepool_connect() != 19047) { + if uniffi_affine_mobile_native_checksum_method_docstoragepool_connect() != 19047 { return InitializationResult.apiChecksumMismatch } - if (uniffi_affine_mobile_native_checksum_method_docstoragepool_delete_blob() != 53695) { + if uniffi_affine_mobile_native_checksum_method_docstoragepool_delete_blob() != 53695 { return InitializationResult.apiChecksumMismatch } - if (uniffi_affine_mobile_native_checksum_method_docstoragepool_delete_doc() != 4005) { + if uniffi_affine_mobile_native_checksum_method_docstoragepool_delete_doc() != 4005 { return InitializationResult.apiChecksumMismatch } - if (uniffi_affine_mobile_native_checksum_method_docstoragepool_disconnect() != 20410) { + if uniffi_affine_mobile_native_checksum_method_docstoragepool_disconnect() != 20410 { return InitializationResult.apiChecksumMismatch } - if (uniffi_affine_mobile_native_checksum_method_docstoragepool_get_blob() != 56927) { + if uniffi_affine_mobile_native_checksum_method_docstoragepool_get_blob() != 56927 { return InitializationResult.apiChecksumMismatch } - if (uniffi_affine_mobile_native_checksum_method_docstoragepool_get_doc_clock() != 48394) { + if uniffi_affine_mobile_native_checksum_method_docstoragepool_get_doc_clock() != 48394 { return InitializationResult.apiChecksumMismatch } - if (uniffi_affine_mobile_native_checksum_method_docstoragepool_get_doc_clocks() != 23822) { + if uniffi_affine_mobile_native_checksum_method_docstoragepool_get_doc_clocks() != 46082 { return InitializationResult.apiChecksumMismatch } - if (uniffi_affine_mobile_native_checksum_method_docstoragepool_get_doc_snapshot() != 31220) { + if uniffi_affine_mobile_native_checksum_method_docstoragepool_get_doc_snapshot() != 31220 { return InitializationResult.apiChecksumMismatch } - if (uniffi_affine_mobile_native_checksum_method_docstoragepool_get_doc_updates() != 65430) { + if uniffi_affine_mobile_native_checksum_method_docstoragepool_get_doc_updates() != 65430 { return InitializationResult.apiChecksumMismatch } - if (uniffi_affine_mobile_native_checksum_method_docstoragepool_get_peer_pulled_remote_clock() != 40122) { + if uniffi_affine_mobile_native_checksum_method_docstoragepool_get_peer_pulled_remote_clock() != 40122 { return InitializationResult.apiChecksumMismatch } - if (uniffi_affine_mobile_native_checksum_method_docstoragepool_get_peer_pulled_remote_clocks() != 13441) { + if uniffi_affine_mobile_native_checksum_method_docstoragepool_get_peer_pulled_remote_clocks() != 13441 { return InitializationResult.apiChecksumMismatch } - if (uniffi_affine_mobile_native_checksum_method_docstoragepool_get_peer_pushed_clocks() != 47148) { + if uniffi_affine_mobile_native_checksum_method_docstoragepool_get_peer_pushed_clocks() != 47148 { return InitializationResult.apiChecksumMismatch } - if (uniffi_affine_mobile_native_checksum_method_docstoragepool_get_peer_remote_clock() != 17458) { + if uniffi_affine_mobile_native_checksum_method_docstoragepool_get_peer_remote_clock() != 17458 { return InitializationResult.apiChecksumMismatch } - if (uniffi_affine_mobile_native_checksum_method_docstoragepool_get_peer_remote_clocks() != 14523) { + if uniffi_affine_mobile_native_checksum_method_docstoragepool_get_peer_remote_clocks() != 14523 { return InitializationResult.apiChecksumMismatch } - if (uniffi_affine_mobile_native_checksum_method_docstoragepool_list_blobs() != 6777) { + if uniffi_affine_mobile_native_checksum_method_docstoragepool_list_blobs() != 6777 { return InitializationResult.apiChecksumMismatch } - if (uniffi_affine_mobile_native_checksum_method_docstoragepool_mark_updates_merged() != 26982) { + if uniffi_affine_mobile_native_checksum_method_docstoragepool_mark_updates_merged() != 42713 { return InitializationResult.apiChecksumMismatch } - if (uniffi_affine_mobile_native_checksum_method_docstoragepool_push_update() != 54572) { + if uniffi_affine_mobile_native_checksum_method_docstoragepool_push_update() != 20688 { return InitializationResult.apiChecksumMismatch } - if (uniffi_affine_mobile_native_checksum_method_docstoragepool_release_blobs() != 2203) { + if uniffi_affine_mobile_native_checksum_method_docstoragepool_release_blobs() != 2203 { return InitializationResult.apiChecksumMismatch } - if (uniffi_affine_mobile_native_checksum_method_docstoragepool_set_blob() != 31398) { + if uniffi_affine_mobile_native_checksum_method_docstoragepool_set_blob() != 31398 { return InitializationResult.apiChecksumMismatch } - if (uniffi_affine_mobile_native_checksum_method_docstoragepool_set_doc_snapshot() != 5287) { + if uniffi_affine_mobile_native_checksum_method_docstoragepool_set_doc_snapshot() != 5287 { return InitializationResult.apiChecksumMismatch } - if (uniffi_affine_mobile_native_checksum_method_docstoragepool_set_peer_pulled_remote_clock() != 40733) { + if uniffi_affine_mobile_native_checksum_method_docstoragepool_set_peer_pulled_remote_clock() != 33923 { return InitializationResult.apiChecksumMismatch } - if (uniffi_affine_mobile_native_checksum_method_docstoragepool_set_peer_pushed_clock() != 15697) { + if uniffi_affine_mobile_native_checksum_method_docstoragepool_set_peer_pushed_clock() != 16565 { return InitializationResult.apiChecksumMismatch } - if (uniffi_affine_mobile_native_checksum_method_docstoragepool_set_peer_remote_clock() != 57108) { + if uniffi_affine_mobile_native_checksum_method_docstoragepool_set_peer_remote_clock() != 46506 { return InitializationResult.apiChecksumMismatch } - if (uniffi_affine_mobile_native_checksum_method_docstoragepool_set_space_id() != 21955) { + if uniffi_affine_mobile_native_checksum_method_docstoragepool_set_space_id() != 21955 { return InitializationResult.apiChecksumMismatch } @@ -2006,4 +1925,4 @@ private func uniffiEnsureInitialized() { } } -// swiftlint:enable all \ No newline at end of file +// swiftlint:enable all diff --git a/packages/frontend/apps/ios/App/App/uniffi/affine_mobile_nativeFFI.h b/packages/frontend/apps/ios/App/App/uniffi/affine_mobile_nativeFFI.h index 7efd489d4b62a..53e77103572c0 100644 --- a/packages/frontend/apps/ios/App/App/uniffi/affine_mobile_nativeFFI.h +++ b/packages/frontend/apps/ios/App/App/uniffi/affine_mobile_nativeFFI.h @@ -368,17 +368,17 @@ uint64_t uniffi_affine_mobile_native_fn_method_docstoragepool_set_doc_snapshot(v #endif #ifndef UNIFFI_FFIDEF_UNIFFI_AFFINE_MOBILE_NATIVE_FN_METHOD_DOCSTORAGEPOOL_SET_PEER_PULLED_REMOTE_CLOCK #define UNIFFI_FFIDEF_UNIFFI_AFFINE_MOBILE_NATIVE_FN_METHOD_DOCSTORAGEPOOL_SET_PEER_PULLED_REMOTE_CLOCK -uint64_t uniffi_affine_mobile_native_fn_method_docstoragepool_set_peer_pulled_remote_clock(void*_Nonnull ptr, RustBuffer universal_id, RustBuffer peer, RustBuffer doc_id, RustBuffer clock +uint64_t uniffi_affine_mobile_native_fn_method_docstoragepool_set_peer_pulled_remote_clock(void*_Nonnull ptr, RustBuffer universal_id, RustBuffer peer, RustBuffer doc_id, int64_t clock ); #endif #ifndef UNIFFI_FFIDEF_UNIFFI_AFFINE_MOBILE_NATIVE_FN_METHOD_DOCSTORAGEPOOL_SET_PEER_PUSHED_CLOCK #define UNIFFI_FFIDEF_UNIFFI_AFFINE_MOBILE_NATIVE_FN_METHOD_DOCSTORAGEPOOL_SET_PEER_PUSHED_CLOCK -uint64_t uniffi_affine_mobile_native_fn_method_docstoragepool_set_peer_pushed_clock(void*_Nonnull ptr, RustBuffer universal_id, RustBuffer peer, RustBuffer doc_id, RustBuffer clock +uint64_t uniffi_affine_mobile_native_fn_method_docstoragepool_set_peer_pushed_clock(void*_Nonnull ptr, RustBuffer universal_id, RustBuffer peer, RustBuffer doc_id, int64_t clock ); #endif #ifndef UNIFFI_FFIDEF_UNIFFI_AFFINE_MOBILE_NATIVE_FN_METHOD_DOCSTORAGEPOOL_SET_PEER_REMOTE_CLOCK #define UNIFFI_FFIDEF_UNIFFI_AFFINE_MOBILE_NATIVE_FN_METHOD_DOCSTORAGEPOOL_SET_PEER_REMOTE_CLOCK -uint64_t uniffi_affine_mobile_native_fn_method_docstoragepool_set_peer_remote_clock(void*_Nonnull ptr, RustBuffer universal_id, RustBuffer peer, RustBuffer doc_id, RustBuffer clock +uint64_t uniffi_affine_mobile_native_fn_method_docstoragepool_set_peer_remote_clock(void*_Nonnull ptr, RustBuffer universal_id, RustBuffer peer, RustBuffer doc_id, int64_t clock ); #endif #ifndef UNIFFI_FFIDEF_UNIFFI_AFFINE_MOBILE_NATIVE_FN_METHOD_DOCSTORAGEPOOL_SET_SPACE_ID @@ -389,6 +389,12 @@ uint64_t uniffi_affine_mobile_native_fn_method_docstoragepool_set_space_id(void* #ifndef UNIFFI_FFIDEF_UNIFFI_AFFINE_MOBILE_NATIVE_FN_FUNC_HASHCASH_MINT #define UNIFFI_FFIDEF_UNIFFI_AFFINE_MOBILE_NATIVE_FN_FUNC_HASHCASH_MINT RustBuffer uniffi_affine_mobile_native_fn_func_hashcash_mint(RustBuffer resource, uint32_t bits, RustCallStatus *_Nonnull out_status +); +#endif +#ifndef UNIFFI_FFIDEF_UNIFFI_AFFINE_MOBILE_NATIVE_FN_FUNC_NEW_DOC_STORAGE_POOL +#define UNIFFI_FFIDEF_UNIFFI_AFFINE_MOBILE_NATIVE_FN_FUNC_NEW_DOC_STORAGE_POOL +void*_Nonnull uniffi_affine_mobile_native_fn_func_new_doc_storage_pool(RustCallStatus *_Nonnull out_status + ); #endif #ifndef UNIFFI_FFIDEF_FFI_AFFINE_MOBILE_NATIVE_RUSTBUFFER_ALLOC @@ -675,6 +681,12 @@ void ffi_affine_mobile_native_rust_future_complete_void(uint64_t handle, RustCal #define UNIFFI_FFIDEF_UNIFFI_AFFINE_MOBILE_NATIVE_CHECKSUM_FUNC_HASHCASH_MINT uint16_t uniffi_affine_mobile_native_checksum_func_hashcash_mint(void +); +#endif +#ifndef UNIFFI_FFIDEF_UNIFFI_AFFINE_MOBILE_NATIVE_CHECKSUM_FUNC_NEW_DOC_STORAGE_POOL +#define UNIFFI_FFIDEF_UNIFFI_AFFINE_MOBILE_NATIVE_CHECKSUM_FUNC_NEW_DOC_STORAGE_POOL +uint16_t uniffi_affine_mobile_native_checksum_func_new_doc_storage_pool(void + ); #endif #ifndef UNIFFI_FFIDEF_UNIFFI_AFFINE_MOBILE_NATIVE_CHECKSUM_METHOD_DOCSTORAGEPOOL_CLEAR_CLOCKS diff --git a/packages/frontend/apps/ios/App/xc-universal-binary.sh b/packages/frontend/apps/ios/App/xc-universal-binary.sh index b993008dc1045..d88a9d252fc31 100644 --- a/packages/frontend/apps/ios/App/xc-universal-binary.sh +++ b/packages/frontend/apps/ios/App/xc-universal-binary.sh @@ -61,14 +61,14 @@ for arch in $ARCHS; do arm64) if [ $IS_SIMULATOR -eq 0 ]; then # Hardware iOS targets - $HOME/.cargo/bin/cargo rustc -p "${FFI_TARGET}" --lib --crate-type staticlib --$RELFLAG --target aarch64-apple-ios + # $HOME/.cargo/bin/cargo rustc -p "${FFI_TARGET}" --lib --crate-type staticlib --$RELFLAG --target aarch64-apple-ios cp $SRC_ROOT/../../../target/aarch64-apple-ios/${RELFLAG}/lib${FFI_TARGET}.a $SRCROOT/lib${FFI_TARGET}.a else # M1 iOS simulator - $HOME/.cargo/bin/cargo rustc -p "${FFI_TARGET}" --lib --crate-type staticlib --$RELFLAG --target aarch64-apple-ios-sim + # $HOME/.cargo/bin/cargo rustc -p "${FFI_TARGET}" --lib --crate-type staticlib --$RELFLAG --target aarch64-apple-ios-sim cp $SRC_ROOT/../../../target/aarch64-apple-ios-sim/${RELFLAG}/lib${FFI_TARGET}.a $SRCROOT/lib${FFI_TARGET}.a fi esac done -$HOME/.cargo/bin/cargo run -p affine_mobile_native --bin uniffi-bindgen generate --library $SRCROOT/lib${FFI_TARGET}.a --language swift --out-dir $SRCROOT/../../ios/App/App/uniffi +# $HOME/.cargo/bin/cargo run --release -p affine_mobile_native --bin uniffi-bindgen generate --library $SRCROOT/lib${FFI_TARGET}.a --language swift --out-dir $SRCROOT/../../ios/App/App/uniffi diff --git a/packages/frontend/apps/ios/src/app.tsx b/packages/frontend/apps/ios/src/app.tsx index e851adc256b3a..ca10fbab4805d 100644 --- a/packages/frontend/apps/ios/src/app.tsx +++ b/packages/frontend/apps/ios/src/app.tsx @@ -102,10 +102,14 @@ framework.impl(WorkspaceEngineWorkerProvider, { }, log: false, }); - worker.postMessage({ - type: 'native-db-api-channel', - port: nativeDBApiChannelClient, - }); + nativeDBApiChannelServer.start(); + worker.postMessage( + { + type: 'native-db-api-channel', + port: nativeDBApiChannelClient, + }, + [nativeDBApiChannelClient] + ); const client = new WorkerClient(new OpClient(worker), options); return { client, diff --git a/packages/frontend/apps/ios/src/plugins/nbstore/definitions.ts b/packages/frontend/apps/ios/src/plugins/nbstore/definitions.ts index e4e0e8269eafb..916606c6c753e 100644 --- a/packages/frontend/apps/ios/src/plugins/nbstore/definitions.ts +++ b/packages/frontend/apps/ios/src/plugins/nbstore/definitions.ts @@ -54,15 +54,16 @@ export interface NbStorePlugin { id: string; docId: string; bin: string; + timestamp: number; }) => Promise<{ success: boolean }>; - getDocUpdates: (options: { id: string; docId: string }) => Promise< - { + getDocUpdates: (options: { id: string; docId: string }) => Promise<{ + updates: { docId: string; timestamp: number; // base64 encoded data bin: string; - }[] - >; + }[]; + }>; markUpdatesMerged: (options: { id: string; docId: string; diff --git a/packages/frontend/apps/ios/src/plugins/nbstore/index.ts b/packages/frontend/apps/ios/src/plugins/nbstore/index.ts index 52100b2f5542b..2895ab4d27c8a 100644 --- a/packages/frontend/apps/ios/src/plugins/nbstore/index.ts +++ b/packages/frontend/apps/ios/src/plugins/nbstore/index.ts @@ -1,27 +1,27 @@ -import { registerPlugin } from '@capacitor/core'; -import { type NativeDBApis } from '@affine/nbstore/sqlite'; - -import type { NbStorePlugin } from './definitions'; import { + base64ToUint8Array, + uint8ArrayToBase64, +} from '@affine/core/modules/workspace-engine'; +import { + type BlobRecord, type DocClock, type DocRecord, - type BlobRecord, type ListedBlobRecord, parseUniversalId, } from '@affine/nbstore'; -import { - base64ToUint8Array, - uint8ArrayToBase64, -} from '@affine/core/modules/workspace-engine'; +import { type NativeDBApis } from '@affine/nbstore/sqlite'; +import { registerPlugin } from '@capacitor/core'; + +import type { NbStorePlugin } from './definitions'; export * from './definitions'; export const NbStore = registerPlugin('NbStoreDocStorage'); export const NbStoreNativeDBApis: NativeDBApis = { - connect: function (id: string): Promise { + connect: async function (id: string): Promise { const { peer, type, id: spaceId } = parseUniversalId(id); - return NbStore.connect({ id, spaceId, spaceType: type, peer }); + return await NbStore.connect({ id, spaceId, spaceType: type, peer }); }, disconnect: function (id: string): Promise { return NbStore.disconnect({ id }); @@ -59,6 +59,7 @@ export const NbStoreNativeDBApis: NativeDBApis = { id, docId: snapshot.docId, bin: await uint8ArrayToBase64(snapshot.bin), + timestamp: snapshot.timestamp.getTime(), }); return success; }, @@ -66,7 +67,7 @@ export const NbStoreNativeDBApis: NativeDBApis = { id: string, docId: string ): Promise { - const updates = await NbStore.getDocUpdates({ id, docId }); + const { updates } = await NbStore.getDocUpdates({ id, docId }); return updates.map(update => ({ bin: base64ToUint8Array(update.bin), docId: update.docId, diff --git a/packages/frontend/apps/ios/src/setup.ts b/packages/frontend/apps/ios/src/setup.ts index 4dd18a2aac403..42b634130fcce 100644 --- a/packages/frontend/apps/ios/src/setup.ts +++ b/packages/frontend/apps/ios/src/setup.ts @@ -1,9 +1,11 @@ import '@affine/core/bootstrap/browser'; import '@affine/component/theme'; import '@affine/core/mobile/styles/mobile.css'; -import { apis } from '@affine/electron-api'; + import { bindNativeDBApis } from '@affine/nbstore/sqlite'; -bindNativeDBApis(apis!.nbstore); +import { NbStoreNativeDBApis } from './plugins/nbstore'; + +bindNativeDBApis(NbStoreNativeDBApis); // TODO(@L-Sun) Uncomment this when the `show` method implement by `@capacitor/keyboard` in ios // import './virtual-keyboard'; diff --git a/packages/frontend/apps/ios/src/worker.ts b/packages/frontend/apps/ios/src/worker.ts index 702c75eb915bc..39346fca79b18 100644 --- a/packages/frontend/apps/ios/src/worker.ts +++ b/packages/frontend/apps/ios/src/worker.ts @@ -1,22 +1,27 @@ +import '@affine/core/bootstrap/browser'; + +import { bindNativeDBApis, type NativeDBApis } from '@affine/nbstore/sqlite'; import { WorkerConsumer, type WorkerOps, } from '@affine/nbstore/worker/consumer'; import { type MessageCommunicapable, OpConsumer } from '@toeverything/infra/op'; -import { bindNativeDBApis, type NativeDBApis } from '@affine/nbstore/sqlite'; import { AsyncCall } from 'async-call-rpc'; globalThis.addEventListener('message', e => { if (e.data.type === 'native-db-api-channel') { - const port = e.data.port as MessagePort; + const port = e.ports[0] as MessagePort; const rpc = AsyncCall( {}, { channel: { on(listener) { - port.addEventListener('message', listener); + const f = (e: MessageEvent) => { + listener(e.data); + }; + port.addEventListener('message', f); return () => { - port.removeEventListener('message', listener); + port.removeEventListener('message', f); }; }, send(data) { @@ -26,6 +31,7 @@ globalThis.addEventListener('message', e => { } ); bindNativeDBApis(rpc); + port.start(); } }); diff --git a/packages/frontend/apps/mobile/src/worker.ts b/packages/frontend/apps/mobile/src/worker.ts index e740ff271da1c..2c03b4caab628 100644 --- a/packages/frontend/apps/mobile/src/worker.ts +++ b/packages/frontend/apps/mobile/src/worker.ts @@ -1,3 +1,4 @@ +import '@affine/core/bootstrap/browser'; import { WorkerConsumer, type WorkerOps, diff --git a/packages/frontend/apps/web/src/worker.ts b/packages/frontend/apps/web/src/worker.ts index e740ff271da1c..2c03b4caab628 100644 --- a/packages/frontend/apps/web/src/worker.ts +++ b/packages/frontend/apps/web/src/worker.ts @@ -1,3 +1,4 @@ +import '@affine/core/bootstrap/browser'; import { WorkerConsumer, type WorkerOps, diff --git a/packages/frontend/core/src/bootstrap/polyfill/browser.ts b/packages/frontend/core/src/bootstrap/polyfill/browser.ts index f92ff94f24d9d..b36ad1d33547b 100644 --- a/packages/frontend/core/src/bootstrap/polyfill/browser.ts +++ b/packages/frontend/core/src/bootstrap/polyfill/browser.ts @@ -1,11 +1,8 @@ -import { polyfillDispose } from './dispose'; -import { polyfillIteratorHelpers } from './iterator-helpers'; -import { polyfillPromise } from './promise-with-resolvers'; +import './dispose'; +import './iterator-helpers'; +import './promise-with-resolvers'; import { polyfillEventLoop } from './request-idle-callback'; import { polyfillResizeObserver } from './resize-observer'; polyfillResizeObserver(); polyfillEventLoop(); -await polyfillPromise(); -await polyfillDispose(); -await polyfillIteratorHelpers(); diff --git a/packages/frontend/core/src/bootstrap/polyfill/dispose.ts b/packages/frontend/core/src/bootstrap/polyfill/dispose.ts index 8a6f636592bd6..615ed233c788b 100644 --- a/packages/frontend/core/src/bootstrap/polyfill/dispose.ts +++ b/packages/frontend/core/src/bootstrap/polyfill/dispose.ts @@ -1,8 +1,2 @@ -export async function polyfillDispose() { - if (typeof Symbol.dispose !== 'symbol') { - // @ts-expect-error ignore - await import('core-js/modules/esnext.symbol.async-dispose'); - // @ts-expect-error ignore - await import('core-js/modules/esnext.symbol.dispose'); - } -} +import 'core-js/modules/esnext.symbol.async-dispose'; +import 'core-js/modules/esnext.symbol.dispose'; diff --git a/packages/frontend/core/src/bootstrap/polyfill/iterator-helpers.ts b/packages/frontend/core/src/bootstrap/polyfill/iterator-helpers.ts index 59ccde6c41798..92e05109058fd 100644 --- a/packages/frontend/core/src/bootstrap/polyfill/iterator-helpers.ts +++ b/packages/frontend/core/src/bootstrap/polyfill/iterator-helpers.ts @@ -1,7 +1 @@ -export async function polyfillIteratorHelpers() { - if (typeof globalThis['Iterator'] !== 'function') { - // @ts-expect-error ignore - // https://github.com/zloirock/core-js/blob/master/packages/core-js/proposals/iterator-helpers-stage-3.js - await import('core-js/proposals/iterator-helpers-stage-3'); - } -} +import 'core-js/proposals/iterator-helpers-stage-3'; diff --git a/packages/frontend/core/src/bootstrap/polyfill/promise-with-resolvers.ts b/packages/frontend/core/src/bootstrap/polyfill/promise-with-resolvers.ts index d9c2cef52f5ad..6d806c3a0884e 100644 --- a/packages/frontend/core/src/bootstrap/polyfill/promise-with-resolvers.ts +++ b/packages/frontend/core/src/bootstrap/polyfill/promise-with-resolvers.ts @@ -1,6 +1 @@ -export async function polyfillPromise() { - if (typeof Promise.withResolvers !== 'function') { - // @ts-expect-error ignore - await import('core-js/features/promise/with-resolvers'); - } -} +import 'core-js/features/promise/with-resolvers'; diff --git a/packages/frontend/core/src/bootstrap/polyfill/request-idle-callback.ts b/packages/frontend/core/src/bootstrap/polyfill/request-idle-callback.ts index 98b99e828cdfe..0664b5e93d118 100644 --- a/packages/frontend/core/src/bootstrap/polyfill/request-idle-callback.ts +++ b/packages/frontend/core/src/bootstrap/polyfill/request-idle-callback.ts @@ -1,6 +1,6 @@ export function polyfillEventLoop() { - window.requestIdleCallback = - window.requestIdleCallback || + globalThis.requestIdleCallback = + globalThis.requestIdleCallback || function (cb) { const start = Date.now(); return setTimeout(function () { @@ -13,8 +13,8 @@ export function polyfillEventLoop() { }, 1); }; - window.cancelIdleCallback = - window.cancelIdleCallback || + globalThis.cancelIdleCallback = + globalThis.cancelIdleCallback || function (id) { clearTimeout(id); }; diff --git a/packages/frontend/core/src/bootstrap/polyfill/resize-observer.ts b/packages/frontend/core/src/bootstrap/polyfill/resize-observer.ts index 6f878419f697e..9659c83cd1dcd 100644 --- a/packages/frontend/core/src/bootstrap/polyfill/resize-observer.ts +++ b/packages/frontend/core/src/bootstrap/polyfill/resize-observer.ts @@ -1,5 +1,7 @@ import { ResizeObserver } from '@juggle/resize-observer'; export function polyfillResizeObserver() { - window.ResizeObserver = ResizeObserver; + if (typeof window !== 'undefined') { + window.ResizeObserver = ResizeObserver; + } } diff --git a/packages/frontend/mobile-native/Cargo.toml b/packages/frontend/mobile-native/Cargo.toml index 18ea605cd5c3f..eeed92cb1b334 100644 --- a/packages/frontend/mobile-native/Cargo.toml +++ b/packages/frontend/mobile-native/Cargo.toml @@ -20,7 +20,7 @@ chrono = { workspace = true } dashmap = { workspace = true } sqlx = { workspace = true } thiserror = { workspace = true } -uniffi = { workspace = true, features = ["cli"] } +uniffi = { workspace = true, features = ["cli", "tokio"] } [target.'cfg(any(target_os = "ios", target_os = "macos"))'.dependencies] objc2 = { workspace = true } diff --git a/packages/frontend/mobile-native/src/lib.rs b/packages/frontend/mobile-native/src/lib.rs index 6f0423f3cfa4c..72fef7c4401ec 100644 --- a/packages/frontend/mobile-native/src/lib.rs +++ b/packages/frontend/mobile-native/src/lib.rs @@ -1,5 +1,3 @@ -use std::time::SystemTime; - use affine_common::hashcash::Stamp; use affine_nbstore::pool::SqliteDocStoragePool; @@ -9,6 +7,8 @@ pub enum UniffiError { Err(String), #[error("Base64 decoding error: {0}")] Base64DecodingError(String), + #[error("Timestamp decoding error")] + TimestampDecodingError, } impl From for UniffiError { @@ -31,7 +31,7 @@ pub struct DocRecord { pub doc_id: String, // base64 encoded data pub bin: String, - pub timestamp: SystemTime, + pub timestamp: i64, } impl From for DocRecord { @@ -39,7 +39,7 @@ impl From for DocRecord { Self { doc_id: record.doc_id, bin: base64_simd::STANDARD.encode_to_string(&record.bin), - timestamp: record.timestamp.and_utc().into(), + timestamp: record.timestamp.and_utc().timestamp_millis(), } } } @@ -53,7 +53,9 @@ impl TryFrom for affine_nbstore::DocRecord { bin: base64_simd::STANDARD .decode_to_vec(record.bin) .map_err(|e| UniffiError::Base64DecodingError(e.to_string()))?, - timestamp: chrono::DateTime::::from(record.timestamp).naive_utc(), + timestamp: chrono::DateTime::::from_timestamp_millis(record.timestamp) + .ok_or(UniffiError::TimestampDecodingError)? + .naive_utc(), }) } } @@ -61,7 +63,7 @@ impl TryFrom for affine_nbstore::DocRecord { #[derive(uniffi::Record)] pub struct DocUpdate { pub doc_id: String, - pub timestamp: SystemTime, + pub timestamp: i64, // base64 encoded data pub bin: String, } @@ -70,43 +72,51 @@ impl From for DocUpdate { fn from(update: affine_nbstore::DocUpdate) -> Self { Self { doc_id: update.doc_id, - timestamp: update.timestamp.and_utc().into(), + timestamp: update.timestamp.and_utc().timestamp_millis(), bin: base64_simd::STANDARD.encode_to_string(&update.bin), } } } -impl From for affine_nbstore::DocUpdate { - fn from(update: DocUpdate) -> Self { - Self { +impl TryFrom for affine_nbstore::DocUpdate { + type Error = UniffiError; + + fn try_from(update: DocUpdate) -> Result { + Ok(Self { doc_id: update.doc_id, - timestamp: chrono::DateTime::::from(update.timestamp).naive_utc(), + timestamp: chrono::DateTime::::from_timestamp_millis(update.timestamp) + .ok_or(UniffiError::TimestampDecodingError)? + .naive_utc(), bin: update.bin.into(), - } + }) } } #[derive(uniffi::Record)] pub struct DocClock { pub doc_id: String, - pub timestamp: SystemTime, + pub timestamp: i64, } impl From for DocClock { fn from(clock: affine_nbstore::DocClock) -> Self { Self { doc_id: clock.doc_id, - timestamp: clock.timestamp.and_utc().into(), + timestamp: clock.timestamp.and_utc().timestamp_millis(), } } } -impl From for affine_nbstore::DocClock { - fn from(clock: DocClock) -> Self { - Self { +impl TryFrom for affine_nbstore::DocClock { + type Error = UniffiError; + + fn try_from(clock: DocClock) -> Result { + Ok(Self { doc_id: clock.doc_id, - timestamp: chrono::DateTime::::from(clock.timestamp).naive_utc(), - } + timestamp: chrono::DateTime::::from_timestamp_millis(clock.timestamp) + .ok_or(UniffiError::TimestampDecodingError)? + .naive_utc(), + }) } } @@ -117,7 +127,7 @@ pub struct Blob { pub data: String, pub mime: String, pub size: i64, - pub created_at: SystemTime, + pub created_at: i64, } impl From for Blob { @@ -127,7 +137,7 @@ impl From for Blob { data: base64_simd::STANDARD.encode_to_string(&blob.data), mime: blob.mime, size: blob.size, - created_at: blob.created_at.and_utc().into(), + created_at: blob.created_at.and_utc().timestamp_millis(), } } } @@ -159,7 +169,7 @@ pub struct ListedBlob { pub key: String, pub size: i64, pub mime: String, - pub created_at: SystemTime, + pub created_at: i64, } impl From for ListedBlob { @@ -168,7 +178,7 @@ impl From for ListedBlob { key: blob.key, size: blob.size, mime: blob.mime, - created_at: blob.created_at.and_utc().into(), + created_at: blob.created_at.and_utc().timestamp_millis(), } } } @@ -179,6 +189,13 @@ pub struct DocStoragePool { } #[uniffi::export] +pub fn new_doc_storage_pool() -> DocStoragePool { + DocStoragePool { + inner: Default::default(), + } +} + +#[uniffi::export(async_runtime = "tokio")] impl DocStoragePool { /// Initialize the database and run migrations. pub async fn connect(&self, universal_id: String, path: String) -> Result<()> { @@ -199,7 +216,7 @@ impl DocStoragePool { universal_id: String, doc_id: String, update: String, - ) -> Result { + ) -> Result { Ok( self .inner @@ -212,7 +229,7 @@ impl DocStoragePool { ) .await? .and_utc() - .into(), + .timestamp_millis(), ) } @@ -259,7 +276,7 @@ impl DocStoragePool { &self, universal_id: String, doc_id: String, - updates: Vec, + updates: Vec, ) -> Result { Ok( self @@ -269,8 +286,12 @@ impl DocStoragePool { doc_id, updates .into_iter() - .map(|t| chrono::DateTime::::from(t).naive_utc()) - .collect(), + .map(|t| { + chrono::DateTime::::from_timestamp_millis(t) + .ok_or(UniffiError::TimestampDecodingError) + .map(|t| t.naive_utc()) + }) + .collect::>>()?, ) .await?, ) @@ -283,14 +304,20 @@ impl DocStoragePool { pub async fn get_doc_clocks( &self, universal_id: String, - after: Option, + after: Option, ) -> Result> { Ok( self .inner .get_doc_clocks( universal_id, - after.map(|t| chrono::DateTime::::from(t).naive_utc()), + after + .map(|t| { + chrono::DateTime::::from_timestamp_millis(t) + .ok_or(UniffiError::TimestampDecodingError) + .map(|t| t.naive_utc()) + }) + .transpose()?, ) .await? .into_iter() @@ -393,7 +420,7 @@ impl DocStoragePool { universal_id: String, peer: String, doc_id: String, - clock: SystemTime, + clock: i64, ) -> Result<()> { Ok( self @@ -402,7 +429,9 @@ impl DocStoragePool { universal_id, peer, doc_id, - chrono::DateTime::::from(clock).naive_utc(), + chrono::DateTime::::from_timestamp_millis(clock) + .ok_or(UniffiError::TimestampDecodingError)? + .naive_utc(), ) .await?, ) @@ -444,7 +473,7 @@ impl DocStoragePool { universal_id: String, peer: String, doc_id: String, - clock: SystemTime, + clock: i64, ) -> Result<()> { Ok( self @@ -453,7 +482,9 @@ impl DocStoragePool { universal_id, peer, doc_id, - chrono::DateTime::::from(clock).naive_utc(), + chrono::DateTime::::from_timestamp_millis(clock) + .ok_or(UniffiError::TimestampDecodingError)? + .naive_utc(), ) .await?, ) @@ -480,7 +511,7 @@ impl DocStoragePool { universal_id: String, peer: String, doc_id: String, - clock: SystemTime, + clock: i64, ) -> Result<()> { Ok( self @@ -489,7 +520,9 @@ impl DocStoragePool { universal_id, peer, doc_id, - chrono::DateTime::::from(clock).naive_utc(), + chrono::DateTime::::from_timestamp_millis(clock) + .ok_or(UniffiError::TimestampDecodingError)? + .naive_utc(), ) .await?, ) diff --git a/packages/frontend/native/nbstore/src/doc.rs b/packages/frontend/native/nbstore/src/doc.rs index c2637f5611165..d9bfade80f027 100644 --- a/packages/frontend/native/nbstore/src/doc.rs +++ b/packages/frontend/native/nbstore/src/doc.rs @@ -3,8 +3,7 @@ use std::ops::Deref; use chrono::{DateTime, NaiveDateTime}; use sqlx::{QueryBuilder, Row}; -use super::{error::Result, storage::SqliteDocStorage}; -use super::{DocClock, DocRecord, DocUpdate}; +use super::{error::Result, storage::SqliteDocStorage, DocClock, DocRecord, DocUpdate}; struct Meta { space_id: String, diff --git a/packages/frontend/native/nbstore/src/pool.rs b/packages/frontend/native/nbstore/src/pool.rs index e4772a9ae5192..c6d17d4228481 100644 --- a/packages/frontend/native/nbstore/src/pool.rs +++ b/packages/frontend/native/nbstore/src/pool.rs @@ -1,13 +1,12 @@ use chrono::NaiveDateTime; use dashmap::{mapref::one::RefMut, DashMap, Entry}; -use crate::{Blob, ListedBlob, SetBlob}; - use super::{ error::{Error, Result}, storage::SqliteDocStorage, DocClock, DocRecord, DocUpdate, }; +use crate::{Blob, ListedBlob, SetBlob}; #[derive(Default)] pub struct SqliteDocStoragePool { @@ -45,7 +44,8 @@ impl SqliteDocStoragePool { /// Initialize the database and run migrations. pub async fn connect(&self, universal_id: String, path: String) -> Result<()> { let storage = self.get_or_create_storage(&universal_id, &path); - Ok(storage.connect().await?) + storage.connect().await?; + Ok(()) } pub async fn disconnect(&self, universal_id: String) -> Result<()> { diff --git a/packages/frontend/native/nbstore/src/storage.rs b/packages/frontend/native/nbstore/src/storage.rs index 39c1aae68e51c..056f5ee90c926 100644 --- a/packages/frontend/native/nbstore/src/storage.rs +++ b/packages/frontend/native/nbstore/src/storage.rs @@ -52,7 +52,7 @@ impl SqliteDocStorage { } pub async fn connect(&self) -> Result<()> { - if !Sqlite::database_exists(&self.path).await.unwrap_or(false) { + if !Sqlite::database_exists(&self.path).await? { Sqlite::create_database(&self.path).await?; }; @@ -79,7 +79,6 @@ impl SqliteDocStorage { /// /// Flush the WAL file to the database file. /// See https://www.sqlite.org/pragma.html#pragma_wal_checkpoint:~:text=PRAGMA%20schema.wal_checkpoint%3B - /// pub async fn checkpoint(&self) -> Result<()> { sqlx::query("PRAGMA wal_checkpoint(FULL);") .execute(&self.pool)