Skip to content

Commit e9cdbba

Browse files
authored
Merge pull request #15 from loro-dev/feat-loro-ffi-135
feat: v1.3.1
2 parents 89932e3 + dbeeccf commit e9cdbba

File tree

9 files changed

+557
-86
lines changed

9 files changed

+557
-86
lines changed

.github/workflows/ci.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,6 @@ jobs:
2323
xcodebuild -version
2424
swift --version
2525
- name: build xcframework
26-
run: ./scripts/build_swift_ffi.sh
26+
run: ./scripts/build_macos.sh
2727
- name: Swift tests
28-
run: swift test
28+
run: LOCAL_BUILD=true swift test

Package.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ if ProcessInfo.processInfo.environment["LOCAL_BUILD"] != nil {
1111
}else {
1212
FFIbinaryTarget = .binaryTarget(
1313
name: "LoroFFI",
14-
url: "https://github.com/loro-dev/loro-swift/releases/download/1.3.0/loroFFI.xcframework.zip",
15-
checksum: "3a7ff19f9408064e4fb3564b58313ae3a3a27823e802cb203ab16af7fdf5007c"
14+
url: "https://github.com/loro-dev/loro-swift/releases/download/1.3.1/loroFFI.xcframework.zip",
15+
checksum: "36e17ab54ee74e81296b4f7b035a22d1e7e38bd14549559bbcbbec7925f45b37"
1616
)
1717
}
1818

README.md

Lines changed: 4 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -18,16 +18,6 @@ This repository contains experimental Swift bindings for
1818
If you have any suggestions for API, please feel free to create an issue or join
1919
our [Discord](https://discord.gg/tUsBSVfqzf) community.
2020

21-
## TODO
22-
23-
- [x] `LoroDoc` export and import
24-
- [x] `List`/`Map`/`Text`/`Tree`/`MovableList`/`Counter` Container
25-
- [x] Checkout
26-
- [x] Subscribe Event
27-
- [x] UndoManager
28-
- [x] Bindings for all types in Loro
29-
- [ ] Tests
30-
- [ ] Benchmarks
3121

3222
## Usage
3323

@@ -39,7 +29,7 @@ let package = Package(
3929
products: [......],
4030
dependencies:[
4131
...,
42-
.package(url: "https://github.com/loro-dev/loro-swift.git", from: "1.3.0")
32+
.package(url: "https://github.com/loro-dev/loro-swift.git", from: "1.3.1")
4333
],
4434
targets:[
4535
.executableTarget(
@@ -94,13 +84,13 @@ If you wanna build and develop this project with MacOS, you need first run this
9484
script:
9585

9686
```bash
97-
export LOCAL_BUILD=1
9887
sh ./scripts/build_macos.sh
88+
LOCAL_BUILD=1 swift test
9989
```
10090

10191
The script will run `uniffi` and generate the `loroFFI.xcframework.zip`.
10292

10393
# Credits
104-
105-
- [Automerge-swift](https://github.com/automerge/automerge-swift): `loro-swift`
94+
- [uniffi-rs](https://github.com/mozilla/uniffi-rs): a multi-language bindings generator for rust
95+
- [Automerge-swift](https://github.com/automerge/automerge-swift): `loro-swift`
10696
uses many of `automerge-swift`'s scripts for building and CI.

Sources/Loro/Container.swift

Lines changed: 73 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -30,93 +30,136 @@ extension ContainerLike{
3030

3131
extension LoroText: ContainerLike{}
3232
extension LoroMap: ContainerLike{
33-
public func insertContainer(key: String, child: ContainerLike) throws -> ContainerLike {
33+
public func insertContainer<T: ContainerLike>(key: String, child: T) throws -> T {
34+
let result: ContainerLike
3435
if let list = child as? LoroList{
35-
return try self.insertListContainer(key: key, child: list)
36+
result = try self.insertListContainer(key: key, child: list)
3637
}else if let map = child as? LoroMap{
37-
return try self.insertMapContainer(key: key, child: map)
38+
result = try self.insertMapContainer(key: key, child: map)
3839
}else if let text = child as? LoroText{
39-
return try self.insertTextContainer(key: key, child: text)
40+
result = try self.insertTextContainer(key: key, child: text)
4041
}else if let tree = child as? LoroTree{
41-
return try self.insertTreeContainer(key: key, child: tree)
42+
result = try self.insertTreeContainer(key: key, child: tree)
4243
}else if let list = child as? LoroMovableList{
43-
return try self.insertMovableListContainer(key: key, child: list)
44+
result = try self.insertMovableListContainer(key: key, child: list)
4445
}else if let counter = child as? LoroCounter{
45-
return try self.insertCounterContainer(key: key, child: counter)
46+
result = try self.insertCounterContainer(key: key, child: counter)
4647
}else{
4748
fatalError()
4849
}
50+
guard let typedResult = result as? T else {
51+
fatalError("Type mismatch: expected \(T.self), got \(type(of: result))")
52+
}
53+
return typedResult
54+
}
55+
56+
public func getOrCreateContainer<T: ContainerLike>(key: String, child: T) throws -> T {
57+
let result: ContainerLike
58+
if let list = child as? LoroList{
59+
result = try self.getOrCreateListContainer(key: key, child: list)
60+
}else if let map = child as? LoroMap{
61+
result = try self.getOrCreateMapContainer(key: key, child: map)
62+
}else if let text = child as? LoroText{
63+
result = try self.getOrCreateTextContainer(key: key, child: text)
64+
}else if let tree = child as? LoroTree{
65+
result = try self.getOrCreateTreeContainer(key: key, child: tree)
66+
}else if let list = child as? LoroMovableList{
67+
result = try self.getOrCreateMovableListContainer(key: key, child: list)
68+
}else if let counter = child as? LoroCounter{
69+
result = try self.getOrCreateCounterContainer(key: key, child: counter)
70+
}else{
71+
fatalError()
72+
}
73+
guard let typedResult = result as? T else {
74+
fatalError("Type mismatch: expected \(T.self), got \(type(of: result))")
75+
}
76+
return typedResult
4977
}
5078
}
5179
extension LoroTree: ContainerLike{}
5280
extension LoroMovableList: ContainerLike{
53-
public func pushContainer(child: ContainerLike) throws -> ContainerLike{
81+
public func pushContainer<T: ContainerLike>(child: T) throws -> T{
5482
let idx = self.len()
5583
return try self.insertContainer(pos: idx, child: child)
5684
}
5785

58-
public func insertContainer(pos: UInt32, child: ContainerLike) throws -> ContainerLike {
86+
public func insertContainer<T: ContainerLike>(pos: UInt32, child: T) throws -> T {
87+
let result: ContainerLike
5988
if let list = child as? LoroList{
60-
return try self.insertListContainer(pos: pos, child: list)
89+
result = try self.insertListContainer(pos: pos, child: list)
6190
}else if let map = child as? LoroMap{
62-
return try self.insertMapContainer(pos: pos, child: map)
91+
result = try self.insertMapContainer(pos: pos, child: map)
6392
}else if let text = child as? LoroText{
64-
return try self.insertTextContainer(pos: pos, child: text)
93+
result = try self.insertTextContainer(pos: pos, child: text)
6594
}else if let tree = child as? LoroTree{
66-
return try self.insertTreeContainer(pos: pos, child: tree)
95+
result = try self.insertTreeContainer(pos: pos, child: tree)
6796
}else if let list = child as? LoroMovableList{
68-
return try self.insertMovableListContainer(pos: pos, child: list)
97+
result = try self.insertMovableListContainer(pos: pos, child: list)
6998
}else if let counter = child as? LoroCounter{
70-
return try self.insertCounterContainer(pos: pos, child: counter)
99+
result = try self.insertCounterContainer(pos: pos, child: counter)
71100
}else{
72101
fatalError()
73102
}
103+
guard let typedResult = result as? T else {
104+
fatalError("Type mismatch: expected \(T.self), got \(type(of: result))")
105+
}
106+
return typedResult
74107
}
75108

76-
public func setContainer(pos: UInt32, child: ContainerLike) throws -> ContainerLike{
109+
public func setContainer<T: ContainerLike>(pos: UInt32, child: T) throws -> T{
110+
let result: ContainerLike
77111
if let list = child as? LoroList{
78-
return try self.setListContainer(pos: pos, child: list)
112+
result = try self.setListContainer(pos: pos, child: list)
79113
}else if let map = child as? LoroMap{
80-
return try self.setMapContainer(pos: pos, child: map)
114+
result = try self.setMapContainer(pos: pos, child: map)
81115
}else if let text = child as? LoroText{
82-
return try self.setTextContainer(pos: pos, child: text)
116+
result = try self.setTextContainer(pos: pos, child: text)
83117
}else if let tree = child as? LoroTree{
84-
return try self.setTreeContainer(pos: pos, child: tree)
118+
result = try self.setTreeContainer(pos: pos, child: tree)
85119
}else if let list = child as? LoroMovableList{
86-
return try self.setMovableListContainer(pos: pos, child: list)
120+
result = try self.setMovableListContainer(pos: pos, child: list)
87121
}else if let counter = child as? LoroCounter{
88-
return try self.setCounterContainer(pos: pos, child: counter)
122+
result = try self.setCounterContainer(pos: pos, child: counter)
89123
}else{
90124
fatalError()
91125
}
126+
guard let typedResult = result as? T else {
127+
fatalError("Type mismatch: expected \(T.self), got \(type(of: result))")
128+
}
129+
return typedResult
92130
}
93131
}
94132
extension LoroCounter: ContainerLike{}
95133
extension LoroUnknown: ContainerLike{}
96134

97135

98136
extension LoroList: ContainerLike{
99-
public func pushContainer(child: ContainerLike) throws -> ContainerLike{
137+
public func pushContainer<T: ContainerLike>(child: T) throws -> T{
100138
let idx = self.len()
101139
return try self.insertContainer(pos: idx, child: child)
102140
}
103141

104-
public func insertContainer(pos: UInt32, child: ContainerLike) throws -> ContainerLike {
142+
public func insertContainer<T: ContainerLike>(pos: UInt32, child: T) throws -> T {
143+
let result: ContainerLike
105144
if let list = child as? LoroList{
106-
return try self.insertListContainer(pos: pos, child: list)
145+
result = try self.insertListContainer(pos: pos, child: list)
107146
}else if let map = child as? LoroMap{
108-
return try self.insertMapContainer(pos: pos, child: map)
147+
result = try self.insertMapContainer(pos: pos, child: map)
109148
}else if let text = child as? LoroText{
110-
return try self.insertTextContainer(pos: pos, child: text)
149+
result = try self.insertTextContainer(pos: pos, child: text)
111150
}else if let tree = child as? LoroTree{
112-
return try self.insertTreeContainer(pos: pos, child: tree)
151+
result = try self.insertTreeContainer(pos: pos, child: tree)
113152
}else if let list = child as? LoroMovableList{
114-
return try self.insertMovableListContainer(pos: pos, child: list)
153+
result = try self.insertMovableListContainer(pos: pos, child: list)
115154
}else if let counter = child as? LoroCounter{
116-
return try self.insertCounterContainer(pos: pos, child: counter)
155+
result = try self.insertCounterContainer(pos: pos, child: counter)
117156
}else{
118157
fatalError()
119158
}
159+
guard let typedResult = result as? T else {
160+
fatalError("Type mismatch: expected \(T.self), got \(type(of: result))")
161+
}
162+
return typedResult
120163
}
121164
}
122165

0 commit comments

Comments
 (0)