Skip to content

Commit dc2a6a6

Browse files
committed
add docs
1 parent d75c201 commit dc2a6a6

File tree

1 file changed

+112
-1
lines changed

1 file changed

+112
-1
lines changed

Sources/SwiftJavaDocumentation/Documentation.docc/SupportedFeatures.md

Lines changed: 112 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,8 @@ SwiftJava's `swift-java jextract` tool automates generating Java bindings from S
4949
| Initializers: `class`, `struct` |||
5050
| Optional Initializers / Throwing Initializers |||
5151
| Deinitializers: `class`, `struct` |||
52-
| `enum`, `actor` |||
52+
| `enum` |||
53+
| `actor` |||
5354
| Global Swift `func` |||
5455
| Class/struct member `func` |||
5556
| Throwing functions: `func x() throws` |||
@@ -157,3 +158,113 @@ you are expected to add a Guava dependency to your Java project.
157158
| `Double` | `double` |
158159

159160
> Note: The `wrap-guava` mode is currently only available in FFM mode of jextract.
161+
162+
#### Enums
163+
164+
> Note: Enums are currently only supported in JNI mode.
165+
166+
Swift enums are extracted into a corresponding Java `class`. To support associated values
167+
all cases are also extracted as Java `record`s.
168+
169+
Consider the following Swift enum:
170+
```swift
171+
public enum Vehicle {
172+
case car(String)
173+
case bicycle(maker: String)
174+
}
175+
```
176+
You can then instantiate a case of `Vehicle` by using one of the static methods:
177+
```java
178+
try (var arena = SwiftArena.ofConfined()) {
179+
Vehicle vehicle = Vehicle.car("BMW", arena);
180+
Optional<Vehicle.Car> car = vehicle.getAsCar();
181+
assertEquals("BMW", car.orElseThrow().arg0());
182+
}
183+
```
184+
As you can see above, to access the associated values of a case you can call one of the
185+
`getAsX` methods that will return an Optional record with the associated values.
186+
```java
187+
try (var arena = SwiftArena.ofConfined()) {
188+
Vehicle vehicle = Vehicle.bycicle("My Brand", arena);
189+
Optional<Vehicle.Car> car = vehicle.getAsCar();
190+
assertFalse(car.isPresent());
191+
192+
Optional<Vehicle.Bicycle> bicycle = vehicle.getAsBicycle();
193+
assertEquals("My Brand", bicycle.orElseThrow().maker());
194+
}
195+
```
196+
197+
##### Switching
198+
199+
If you only need to switch on the case and not access any associated values,
200+
you can use the `getDiscriminator()` method:
201+
```java
202+
Vehicle vehicle = ...;
203+
switch (vehicle.getDiscriminator()) {
204+
case BICYCLE:
205+
System.out.println("I am a bicycle!");
206+
break
207+
case CAR:
208+
System.out.println("I am a car!");
209+
break
210+
}
211+
```
212+
If you also want access to the associated values, you have various options
213+
depending on the Java version you are using.
214+
If you are running Java 21+ you can use [pattern matching for switch](https://openjdk.org/jeps/441):
215+
```java
216+
Vehicle vehicle = ...;
217+
switch (vehicle.getCase()) {
218+
case Vehicle.Bicycle b:
219+
System.out.println("Bicycle maker: " + b.maker());
220+
break
221+
case Vehicle.Car c:
222+
System.out.println("Car: " + c.arg0());
223+
break
224+
}
225+
```
226+
For Java 16+ you can use [pattern matching for instanceof](https://openjdk.org/jeps/394)
227+
```java
228+
Vehicle vehicle = ...;
229+
Vehicle.Case case = vehicle.getCase();
230+
if (case instanceof Vehicle.Bicycle b) {
231+
System.out.println("Bicycle maker: " + b.maker());
232+
} else if(case instanceof Vehicle.Car c) {
233+
System.out.println("Car: " + c.arg0());
234+
}
235+
```
236+
For any previous Java versions you can resort to casting the `Case` to the expected type:
237+
```java
238+
Vehicle vehicle = ...;
239+
Vehicle.Case case = vehicle.getCase();
240+
if (case instanceof Vehicle.Bicycle) {
241+
Vehicle.Bicycle b = (Vehicle.Bicycle) case;
242+
System.out.println("Bicycle maker: " + b.maker());
243+
} else if(case instanceof Vehicle.Car) {
244+
Vehicle.Car c = (Vehicle.Car) case;
245+
System.out.println("Car: " + c.arg0());
246+
}
247+
```
248+
249+
##### RawRepresentable
250+
251+
JExtract also supports extracting enums that conform to `RawRepresentable`
252+
by giving access to an optional initializer and the `rawValue` variable.
253+
Consider the following example:
254+
```swift
255+
public enum Alignment: String {
256+
case horizontal
257+
case vertical
258+
}
259+
```
260+
you can then initialize `Alignment` from a `String` and also retrieve back its `rawValue`:
261+
```java
262+
try (var arena = SwiftArena.ofConfined()) {
263+
Optional<Alignment> alignment = Alignment.init("horizontal", arena);
264+
assertEqual(HORIZONTAL, alignment.orElseThrow().getDiscriminator());
265+
assertEqual("horizontal", alignment.orElseThrow().getRawValue());
266+
}
267+
```
268+
269+
270+

0 commit comments

Comments
 (0)