forked from mozilla/uniffi-rs
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add more README, and a walkthrough of the (barely) working example.
- Loading branch information
Showing
9 changed files
with
975 additions
and
60 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,5 @@ | ||
Cargo.lock | ||
target | ||
.cargo | ||
.*.swp | ||
*.jar |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
# Example uniffi component: "Arithmetic" | ||
|
||
This is a minimal (and very work-in-progress!) example of how to write a Rust component using | ||
uniffi. It doesn't exercise any tricky bits of the FFI so it's a nice place to start. We have | ||
the following so far: | ||
|
||
* [`./arithmetic.idl`](./arithmetic.idl), the component interface definition which exposes two | ||
plain functions "add" and "sub". This is processed by functions in [`./build.rs`](./build.rs) | ||
to generate Rust scaffolding for the component, and some Kotlin bindings. | ||
* [`./src/lib.rs`](./src/lib.rs), the core implementation of the component in Rust. This basically | ||
pulls in the generated Rust scaffolding via `include!()` and fills in function implementations. | ||
* A tiny example program in [`./main.kt`](./main.kt) that imports the component in Kotlin, calls | ||
one of its methods and prints the result. | ||
* Some extremely hacky code in [`./build.rs`](./build.rs) that only works on my machine (since it | ||
has some hard-coded file paths) that generates Kotlin bindings from the IDL, compiles them together | ||
with `./main.kt`, and produces a runnabe `.jar` file to exercise the component. | ||
|
||
There is a *lot* of build and packaging detail to figure out here, but I'm able to do the following | ||
and actually use the Rust component from Kotlin: | ||
|
||
* Install the kotlin command-line compiler. | ||
* Edit `build.rs` to point it to a local copy of the JNA jar. | ||
* Run `cargo build` in this directory; observe that it creates a file `./arithmetic.jar`. | ||
* Try to run `./arithmetic.jar` directly using `java -jar arithmetic.jar`; observe that it fails because it can't find JNA in the classpath, and I can't figure out the right command-line flags to get it to do so. | ||
* Unpack the jar to try running it by hand: | ||
* `mkdir unpacked; cd unpacked` | ||
* `unzip ../arithmetic.jar` | ||
* `unzip -o /path/to/jna-5.2.0.jar` | ||
* `cp ../target/debug/libuniffi_example_arithmetic.dylib ./` | ||
* `java MainKt` | ||
* Observe that it correctly prints the result of some simple arithmetic! | ||
|
||
That obviously needs to be smoother, but you get the idea :-) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
import uniffi.example.Arithmetic; | ||
|
||
fun main(args: Array<String>) { | ||
println("2 + 3 = ${Arithmetic.add(2, 3, 1)}") | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,134 @@ | ||
enum DeviceCapability { | ||
"SEND_TAB", | ||
}; | ||
|
||
enum DeviceType { | ||
"DESKTOP", | ||
"MOBILE", | ||
}; | ||
|
||
enum IncomingDeviceCommandType { | ||
"TAB_RECEIVED", | ||
}; | ||
|
||
enum AccountEventType { | ||
"INCOMING_DEVICE_COMMAND", | ||
"PROFILE_UPDATED", | ||
"DEVICE_CONNECTED", | ||
"ACCOUNT_AUTH_STATE_CHANGED", | ||
"DEVICE_DISCONNECTED", | ||
"ACCOUNT_DESTROYED", | ||
}; | ||
|
||
dictionary ProfileInfo { | ||
// XXX TODO: probably some of these should be `required`? | ||
string uid; | ||
string email; | ||
string display_name; | ||
string avatar; | ||
boolean avatar_default; | ||
}; | ||
|
||
dictionary AccessTokenInfo { | ||
required string scope; | ||
required string token; | ||
ScopedKey key; | ||
required uint64 expires_at; | ||
}; | ||
|
||
dictionary ScopedKey { | ||
required string kty; | ||
required string scope; | ||
required string k; | ||
required string kid; | ||
}; | ||
|
||
dictionary IntrospectInfo { | ||
required boolean active = false; | ||
}; | ||
|
||
dictionary DeviceInfo { | ||
required string id; | ||
required string display_name; | ||
required DeviceType type; | ||
required boolean is_current_device; | ||
uint64 last_access_time; | ||
PushSubscription push_subscription; | ||
required boolean push_endpoint_expired; | ||
sequence<DeviceCapability> capabilities; | ||
}; | ||
|
||
dictionary TabHistoryEntry { | ||
required string title; | ||
required string url; | ||
}; | ||
|
||
dictionary SendTabData { | ||
DeviceInfo from; | ||
sequence<TabHistoryEntry> entries; | ||
}; | ||
|
||
dictionary IncomingDeviceCommand { | ||
IncomingDeviceCommandType type; | ||
SendTabData data; /* eventually a union type..? */ | ||
}; | ||
|
||
dictionary DeviceConnectedData { | ||
string name; | ||
}; | ||
|
||
dictionary DeviceDisconnecedData { | ||
required string id; | ||
required boolean is_local_device; | ||
}; | ||
|
||
dictionary AccountEvent { | ||
AccountEventType type; | ||
// No support for union types yet... | ||
// (IncomingDeviceCommand or DeviceConnectedData or DeviceDisconnectesData) data; | ||
}; | ||
|
||
dictionary MigrationState { | ||
string blah = "blah"; | ||
}; | ||
|
||
interface FirefoxAccount { | ||
constructor(string content_url, string client_id, string redirect_uri, optional string token_server_url_override); | ||
/*static FirefoxAccont fromJSON(string json); TODO: alternative constructors */ | ||
string toJSON(); | ||
|
||
string getPairingAuthorityURL(); | ||
string getTokenServerEndpointURL(); | ||
string getConnectionSuccessURL(); | ||
string getManageAccountURL(); | ||
string getManageDevicesURL(); | ||
|
||
string beginOAuthFlow(sequence<string> scopes); | ||
string beginPairingFlow(string pairingUrl, sequence<string> scopes); | ||
void completeOAuthFlow(string code, string state); | ||
void disconnect(); | ||
|
||
IntrospectInfo checkAuthorizationStatus(); | ||
AccessTokenInfo getAccessToken(string scope, optional u32 ttl); | ||
string getSessionToken(); // really whish we weren't exposing this... :-( | ||
string getCurrentDeviceId(); | ||
string authorizeOAuthCode(string client_id, sequence<string> scopes, string state, optional string access_type = "online"); | ||
void clearAccessTokenCache(); | ||
|
||
string copyFromSessionToken(string sessionToken, string kSync, string kXCS); // needs better return type... | ||
string migrateFromSessionToken(string sessionToken, string kSync, string kXCS); // needs better return type... | ||
string retryMigrateFromSessionToken(); // needs better return type... | ||
MigrationState isInMigrationState(); | ||
|
||
ProfileInfo getProfile(optional boolean ignoreCache=false); | ||
|
||
void initializeDevice(string name, DeviceType type, sequence<DeviceCapability> supportedCapabilities); | ||
void ensureCapabilities(sequence<DeviceCapability> supportedCapabilities); | ||
void setDevicePushSubscription(string endpoint, string publicKey, string authKey); | ||
void setDeviceDisplayName(string display_name); | ||
sequence<DeviceInfo> getDevices(optional boolean ignoreCache = false); | ||
sequence<AccountEvent> handlePushMessage(string payload); | ||
|
||
sequence<IncomingDeviceCommand> pollDeviceCommands(); | ||
void sendSingleTab(string target_device_id, string title, string url); | ||
}; |
Oops, something went wrong.