forked from mirrors/gecko-dev
Backed out 6 changesets (bug 1766045) for causing build bustages. CLOSED TREE
Backed out changeset 113593df6272 (bug 1766045) Backed out changeset f137315bb6af (bug 1766045) Backed out changeset d86ad195a9a0 (bug 1766045) Backed out changeset e8bc2ec40cff (bug 1766045) Backed out changeset 2d33e41ac507 (bug 1766045) Backed out changeset 4d5874e16302 (bug 1766045)
This commit is contained in:
parent
81ed1702c1
commit
a8ad39a288
164 changed files with 0 additions and 12997 deletions
|
|
@ -12,11 +12,6 @@ git = "https://github.com/rust-minidump/minidump-writer.git"
|
|||
replace-with = "vendored-sources"
|
||||
rev = "75ada456c92a429704691a85e1cb42fef8cafc0d"
|
||||
|
||||
[source."https://github.com/mozilla/uniffi-rs.git"]
|
||||
git = "https://github.com/mozilla/uniffi-rs.git"
|
||||
replace-with = "vendored-sources"
|
||||
rev = "bb2039f077a29dba0879372a67e764e6ace8e33f"
|
||||
|
||||
[source."https://github.com/mozilla/neqo"]
|
||||
git = "https://github.com/mozilla/neqo"
|
||||
replace-with = "vendored-sources"
|
||||
|
|
|
|||
|
|
@ -63,12 +63,6 @@ widget/gtk/MPRISInterfaceDescription.h
|
|||
xpcom/reflect/xptcall/md/win32/.*
|
||||
xpcom/reflect/xptcall/md/unix/.*
|
||||
|
||||
# Askama template code, which isn't valid C++ in its original form
|
||||
toolkit/components/uniffi-bindgen-gecko-js/src/templates/.*
|
||||
# Generated from that template code
|
||||
toolkit/components/uniffi-js/UniFFIGeneratedScaffolding.cpp
|
||||
toolkit/components/uniffi-js/UniFFIFixtureScaffolding.cpp
|
||||
|
||||
# Generated from ./tools/rewriting/ThirdPartyPaths.txt
|
||||
# awk '{print ""$1".*"}' ./tools/rewriting/ThirdPartyPaths.txt
|
||||
browser/components/translation/cld2/.*
|
||||
|
|
|
|||
|
|
@ -228,6 +228,3 @@ toolkit/components/backgroundtasks/defaults
|
|||
|
||||
# Ignore pre-generated webpack and typescript transpiled files for translations
|
||||
browser/extensions/translations/extension/
|
||||
|
||||
# "scaffolding" used by uniffi which isn't valid JS in its original form.
|
||||
toolkit/components/uniffi-bindgen-gecko-js/src/templates/js/
|
||||
|
|
|
|||
86
Cargo.lock
generated
86
Cargo.lock
generated
|
|
@ -1549,18 +1549,6 @@ dependencies = [
|
|||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "extend"
|
||||
version = "1.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c5216e387a76eebaaf11f6d871ec8a4aae0b25f05456ee21f228e024b1b3610"
|
||||
dependencies = [
|
||||
"proc-macro-error",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fallible-iterator"
|
||||
version = "0.2.0"
|
||||
|
|
@ -2176,11 +2164,6 @@ dependencies = [
|
|||
"tokio-threadpool",
|
||||
"unic-langid",
|
||||
"unic-langid-ffi",
|
||||
"uniffi-example-arithmetic",
|
||||
"uniffi-example-geometry",
|
||||
"uniffi-example-rondpoint",
|
||||
"uniffi-example-sprites",
|
||||
"uniffi-example-todolist",
|
||||
"url",
|
||||
"viaduct",
|
||||
"webext_storage_bridge",
|
||||
|
|
@ -5619,75 +5602,6 @@ dependencies = [
|
|||
"log",
|
||||
"paste",
|
||||
"static_assertions",
|
||||
"uniffi_bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "uniffi-bindgen-gecko-js"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"askama",
|
||||
"camino",
|
||||
"clap",
|
||||
"extend",
|
||||
"heck",
|
||||
"serde",
|
||||
"toml 0.5.9",
|
||||
"uniffi_bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "uniffi-example-arithmetic"
|
||||
version = "0.18.0"
|
||||
source = "git+https://github.com/mozilla/uniffi-rs.git?rev=bb2039f077a29dba0879372a67e764e6ace8e33f#bb2039f077a29dba0879372a67e764e6ace8e33f"
|
||||
dependencies = [
|
||||
"thiserror",
|
||||
"uniffi",
|
||||
"uniffi_build",
|
||||
"uniffi_macros",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "uniffi-example-geometry"
|
||||
version = "0.18.0"
|
||||
source = "git+https://github.com/mozilla/uniffi-rs.git?rev=bb2039f077a29dba0879372a67e764e6ace8e33f#bb2039f077a29dba0879372a67e764e6ace8e33f"
|
||||
dependencies = [
|
||||
"uniffi",
|
||||
"uniffi_build",
|
||||
"uniffi_macros",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "uniffi-example-rondpoint"
|
||||
version = "0.18.0"
|
||||
source = "git+https://github.com/mozilla/uniffi-rs.git?rev=bb2039f077a29dba0879372a67e764e6ace8e33f#bb2039f077a29dba0879372a67e764e6ace8e33f"
|
||||
dependencies = [
|
||||
"uniffi",
|
||||
"uniffi_build",
|
||||
"uniffi_macros",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "uniffi-example-sprites"
|
||||
version = "0.18.0"
|
||||
source = "git+https://github.com/mozilla/uniffi-rs.git?rev=bb2039f077a29dba0879372a67e764e6ace8e33f#bb2039f077a29dba0879372a67e764e6ace8e33f"
|
||||
dependencies = [
|
||||
"uniffi",
|
||||
"uniffi_build",
|
||||
"uniffi_macros",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "uniffi-example-todolist"
|
||||
version = "0.18.0"
|
||||
source = "git+https://github.com/mozilla/uniffi-rs.git?rev=bb2039f077a29dba0879372a67e764e6ace8e33f#bb2039f077a29dba0879372a67e764e6ace8e33f"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
"thiserror",
|
||||
"uniffi",
|
||||
"uniffi_build",
|
||||
"uniffi_macros",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
|
|||
14
Cargo.toml
14
Cargo.toml
|
|
@ -11,7 +11,6 @@ members = [
|
|||
"security/manager/ssl/ipcclientcerts",
|
||||
"security/manager/ssl/osclientcerts",
|
||||
"testing/geckodriver",
|
||||
"toolkit/components/uniffi-bindgen-gecko-js",
|
||||
"toolkit/crashreporter/rust_minidump_writer_linux",
|
||||
"toolkit/crashreporter/mozwer-rust",
|
||||
"toolkit/library/gtest/rust",
|
||||
|
|
@ -165,16 +164,3 @@ path = "third_party/rust/mio-0.6.23"
|
|||
# https://github.com/mozilla/neqo/pull/1350
|
||||
[patch."https://github.com/mozilla/neqo"]
|
||||
neqo-common = { path = "third_party/rust/neqo-common" }
|
||||
|
||||
# These are used to test UniFFI functionality. We haven't figured out how we
|
||||
# want to publish these yet, so they are only accessible via git. This works
|
||||
# okay, but it means that their dependencies on UniFFI crates will normally
|
||||
# also be the git versions. Patch them to use the published versions to avoid
|
||||
# duplicate crates.
|
||||
|
||||
[patch."https://github.com/mozilla/uniffi-rs.git"]
|
||||
uniffi = "0.19"
|
||||
uniffi_bindgen = "0.19"
|
||||
uniffi_build = "0.19"
|
||||
uniffi_macros = "0.19"
|
||||
weedle2 = "3.0.0"
|
||||
|
|
|
|||
|
|
@ -363,9 +363,6 @@ def initialize(topsrcdir):
|
|||
),
|
||||
"esmify": MachCommandReference("tools/esmify/mach_commands.py"),
|
||||
"xpcshell": MachCommandReference("js/xpconnect/mach_commands.py"),
|
||||
"uniffi": MachCommandReference(
|
||||
"toolkit/components/uniffi-bindgen-gecko-js/mach_commands.py"
|
||||
),
|
||||
}
|
||||
|
||||
# Set a reasonable limit to the number of open files.
|
||||
|
|
|
|||
|
|
@ -1,54 +0,0 @@
|
|||
# Generating Javascript bindings with UniFFI
|
||||
|
||||
Firefox supports auto-generating JS bindings for Rust components using [UniFFI](https://mozilla.github.io/uniffi-rs/).
|
||||
|
||||
## How it works
|
||||
|
||||
The Rust crate contains a
|
||||
[UniFFI Definition Language (UDL) file](https://mozilla.github.io/uniffi-rs/udl_file_spec.html), which describes the
|
||||
interface to generate bindings for.
|
||||
|
||||
The UniFFI core generates the scaffolding: Rust code which acts as the FFI layer from the UDL file. The functions of
|
||||
this layer all use the C calling convention and all structs use a C layout, this is the de facto standard for FFI
|
||||
interoperability.
|
||||
|
||||
The [`uniffi-bindgen-gecko-js`](https://searchfox.org/mozilla-central/source/toolkit/components/uniffi-bindgen-gecko-js)
|
||||
tool, which lives in the Firefox source tree, generates 2 things:
|
||||
- A JS interface for the scaffolding code, which uses [WebIDL](/dom/bindings/webidl/index.rst)
|
||||
- A JSM module that uses the scaffolding to provide the bindings API.
|
||||
|
||||
Currently, this generated code gets checked in to source control. We are working on a system to avoid this and
|
||||
auto-generate it at build time instead (see [bugzilla 1756214](https://bugzilla.mozilla.org/show_bug.cgi?id=1756214)).
|
||||
|
||||
## Before creating new bindings with UniFFI
|
||||
|
||||
Keep a few things in mind before you create a new set of bindings:
|
||||
|
||||
- **UniFFI was not written to maximize performance.** It's code is efficient enough to handle many use cases, but at this
|
||||
point should probably be avoided for performance critical components.
|
||||
- **uniffi-bindgen-gecko-js bindings run with chrome privileges.** Make sure this is acceptable for your project
|
||||
- **Only a subset of Rust types can be exposed via the FFI.** Check the [UniFFI Book](https://mozilla.github.io/uniffi-rs/) to see what
|
||||
types are compatible with UniFFI.
|
||||
|
||||
If any of these are blockers for your work, consider discussing it further with the UniFFI devs to see if we can support
|
||||
your project:
|
||||
|
||||
- Chat with us on `#uniffi` on Matrix/Element
|
||||
- File an issue on [mozilla/uniffi](https://github.com/mozilla/uniffi-rs/)
|
||||
|
||||
## Creating new bindings with UniFFI
|
||||
|
||||
Here's how you can create a new set of bindings using UniFFI:
|
||||
- UniFFI your crate (if it isn't already):
|
||||
- [Create a UDL file to describe your interface](https://mozilla.github.io/uniffi-rs/udl_file_spec.html)
|
||||
- [Set up your Rust crate to generate scaffolding](https://mozilla.github.io/uniffi-rs/tutorial/Rust_scaffolding.html)
|
||||
- Add your crate as a Firefox dependency (if it isn't already)
|
||||
- If the code will exist in the mozilla-central repo:
|
||||
- Create a new directory for the Rust crate
|
||||
- Edit `toolkit/library/rust/shared/Cargo.toml` and add a dependency to your library path
|
||||
- If the code exists in an external repo:
|
||||
- Edit `toolkit/library/rust/shared/Cargo.toml` and add a dependency to your library URL
|
||||
- Run `mach vendor rust` to vendor in your Rust code
|
||||
- Generate bindings code for your crate
|
||||
- TODO: create a system for this and document it here. I think we can do something like we do for the test
|
||||
fixtures, where devs don't need to touch that many moz.build files.
|
||||
|
|
@ -9,7 +9,6 @@
|
|||
|
||||
#include "nsWrapperCache.h"
|
||||
#include "nsISupports.h"
|
||||
#include "nsIContent.h"
|
||||
|
||||
// IID for the nsINodeList interface
|
||||
#define NS_INODELIST_IID \
|
||||
|
|
|
|||
|
|
@ -1,59 +0,0 @@
|
|||
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
// Interface for making UniFFI scaffolding calls
|
||||
//
|
||||
// Gecko uses UniFFI to generate privileged JS bindings for Rust components.
|
||||
// UniFFI defines a C-ABI FFI layer for calling into Rust, called the
|
||||
// scaffolding. This interface is a bridge that allows the JS code to make
|
||||
// scaffolding calls
|
||||
//
|
||||
// See https://mozilla.github.io/uniffi-rs/ for details.
|
||||
|
||||
// Opaque type used to represent a pointer from Rust
|
||||
[ChromeOnly, Exposed=Window]
|
||||
interface UniFFIPointer {};
|
||||
|
||||
// Types that can be passed or returned from scaffolding functions
|
||||
//
|
||||
// - double is used for all numeric types (including bool, which the JS code
|
||||
// coerces to an int)
|
||||
// - ArrayBuffer is used for RustBuffer
|
||||
// - UniFFIPointer is used for Arc pointers
|
||||
typedef (double or ArrayBuffer or UniFFIPointer) UniFFIScaffoldingType;
|
||||
|
||||
// The result of a call into UniFFI scaffolding call
|
||||
enum UniFFIScaffoldingCallCode {
|
||||
"success", // Successful return
|
||||
"error", // Rust Err return
|
||||
"internal-error", // Internal/unexpected error
|
||||
};
|
||||
|
||||
dictionary UniFFIScaffoldingCallResult {
|
||||
required UniFFIScaffoldingCallCode code;
|
||||
// For success, this will be the return value for non-void returns
|
||||
// For error, this will be an ArrayBuffer storing the serialized error value
|
||||
UniFFIScaffoldingType data;
|
||||
// For internal-error, this will be a utf-8 string describing the error
|
||||
ByteString internalErrorMessage;
|
||||
};
|
||||
|
||||
// Functions to facilitate UniFFI scaffolding calls
|
||||
//
|
||||
// These should only be called by the generated code from UniFFI.
|
||||
[ChromeOnly, Exposed=Window]
|
||||
namespace UniFFIScaffolding {
|
||||
[Throws]
|
||||
Promise<UniFFIScaffoldingCallResult> callAsync(unsigned long long id, UniFFIScaffoldingType... args);
|
||||
|
||||
[Throws]
|
||||
UniFFIScaffoldingCallResult callSync(unsigned long long id, UniFFIScaffoldingType... args);
|
||||
|
||||
[Throws]
|
||||
UniFFIPointer readPointer(unsigned long long id, ArrayBuffer buff, long position);
|
||||
|
||||
[Throws]
|
||||
void writePointer(unsigned long long id, UniFFIPointer ptr, ArrayBuffer buff, long position);
|
||||
};
|
||||
|
|
@ -81,7 +81,6 @@ WEBIDL_FILES = [
|
|||
"SessionStoreUtils.webidl",
|
||||
"StructuredCloneHolder.webidl",
|
||||
"TelemetryStopwatch.webidl",
|
||||
"UniFFI.webidl",
|
||||
"UserInteraction.webidl",
|
||||
"WebExtensionContentScript.webidl",
|
||||
"WebExtensionPolicy.webidl",
|
||||
|
|
|
|||
|
|
@ -99,12 +99,6 @@ criteria = "safe-to-deploy"
|
|||
delta = "0.4.0 -> 0.5.0"
|
||||
notes = "The repository for this crate belongs in the Mozilla org."
|
||||
|
||||
[[audits.extend]]
|
||||
who = "Ben Dean-Kawamura <bdk@mozilla.com>"
|
||||
criteria = "safe-to-deploy"
|
||||
version = "1.1.2"
|
||||
notes = "Inspected the crate and noted that the impl block comes directly from the proc-macro input. If no new code can be added by this crate, I don't think there can be any issues."
|
||||
|
||||
[[audits.flagset]]
|
||||
who = "Ryan Hunt <rhunt@eqrion.net>"
|
||||
criteria = "safe-to-deploy"
|
||||
|
|
|
|||
1
third_party/rust/extend/.cargo-checksum.json
vendored
1
third_party/rust/extend/.cargo-checksum.json
vendored
|
|
@ -1 +0,0 @@
|
|||
{"files":{"CHANGELOG.md":"910cd2057d356b18cd4f21791bc23956734a83b0f58701ec0d0d03405f5c21df","Cargo.toml":"928b8b97607b3589b85a6d4d00fb1cf64b78bee6354c303d8f49fbfa2ca5bdae","LICENSE":"db0efd0bb80126f32214f478434536d07d86a30658fb209d8b543b7261492a2b","README.md":"0872b2b15ec22732a09b121a31cdd8f8cfc80566f671566e4a7fb6b52a742a2e","deny.toml":"60448e9313f1883a7adf30713fcca789c454e77228105926024ce3abe9293100","rustfmt.toml":"9bbb759b3914c49c8060bcdeeb7786f4aec083d30bcfe236bbd48d8388d06103","src/lib.rs":"85bd23c064c78dcd141cb2fecca6fff2ee7e1dfb4cf19b74ab97ef30d51f6f03","tests/compile_fail/double_vis.rs":"524e8bc996f5a45de3d15f0c741d4f3414004e9c636c52de0f011785cc535109","tests/compile_fail/double_vis.stderr":"3748e67e6f41bd5624946ad7cdc4e2b30a9d0b5e76bc27c19ecc9d62da733978","tests/compile_fail/supertraits_are_actually_included.rs":"c03980316c4e71ceb7e80ab7011f00b6f1f8f89906670e9823267a4118f72853","tests/compile_fail/supertraits_are_actually_included.stderr":"835e79bb1bceb48e9db5f0a410c57af51c856e17917ef72f65e3ae2af79d97ec","tests/compile_pass/associated_constants.rs":"f3e56405650ddd31c33e932846553e88fe7181585e0f09a7414d50d521b0f103","tests/compile_pass/async_trait.rs":"9138801d67dbe20ed87fdb3f48bb968f0bfa11fe2d27414d5ea5ea7a6e44bb35","tests/compile_pass/changing_extension_trait_name.rs":"046e7a66151ce05c3515b4bea36be72f83b98f3bdb06fa6f065ad6fc373e19f2","tests/compile_pass/complex_trait_name.rs":"5a8c3588c26df07973739fbb85619d0de480cc8c992611dfc2dbcb9ab3c6e2b6","tests/compile_pass/double_ext_on_same_type.rs":"0e4d16fe9059f0325e4ad1337d53738876633b0533f9a2d4e9714ddada96eb4d","tests/compile_pass/extension_on_complex_types.rs":"88bdf979e1f399d7f9824165730b33884bc9c46347d246f8cc12e0e2039642a1","tests/compile_pass/generics.rs":"367f089e8010d1c98ccc975b03acb6cf03810793e1198105f75c006eafd52bb8","tests/compile_pass/hello_world.rs":"1961cfa634143974f0d64b26f817ac3148375faa5cf5864d63f0127d3af8099e","tests/compile_pass/issue_2.rs":"a14d5e2179b74ff71c5357e8a4f1a9ac228a711196edd40c12719565c8dfaa21","tests/compile_pass/more_than_one_extension.rs":"1d7486e4e9e4095d7e7f42aac878d836f021c49fbe26c31cb13fe6a0415a8558","tests/compile_pass/multiple_config.rs":"dc3b06e4fafbb7236b5bc49f9a5e9693241c07118da8886dd0752b895ff27425","tests/compile_pass/multiple_generic_params.rs":"2ac052ea7b818b6d45ee8070cf6ec18953419473f711375cafbe7283244b5743","tests/compile_pass/pub_impl.rs":"8dfcba21fbbc45efcf85b66fca2d187022569e72d4b10b57047eddda67a1725b","tests/compile_pass/ref_and_ref_mut.rs":"d1086a23809cbd8f87487677073238c3657a8a98fafc63a688eb9d622bf2eb11","tests/compile_pass/sized.rs":"baceaaabcf368b3c72e6d27fea72aadde11d97d9d153c35df5e2d89fb3da4e3e","tests/compile_pass/super_trait.rs":"07448e1fe2b9018125ccaabf7db1e2a244788519bb42117f8e437e48358eb2f0","tests/compile_pass/visibility_config.rs":"64846014a63327661fb250cdb726cce532ed82b1cea5cb83308526bcba22b4be"},"package":"5c5216e387a76eebaaf11f6d871ec8a4aae0b25f05456ee21f228e024b1b3610"}
|
||||
79
third_party/rust/extend/CHANGELOG.md
vendored
79
third_party/rust/extend/CHANGELOG.md
vendored
|
|
@ -1,79 +0,0 @@
|
|||
# Change Log
|
||||
|
||||
All user visible changes to this project will be documented in this file.
|
||||
This project adheres to [Semantic Versioning](http://semver.org/), as described
|
||||
for Rust libraries in [RFC #1105](https://github.com/rust-lang/rfcs/blob/master/text/1105-api-evolution.md)
|
||||
|
||||
## Unreleased
|
||||
|
||||
None.
|
||||
|
||||
### Breaking changes
|
||||
|
||||
None.
|
||||
|
||||
## 1.1.2 - 2021-09-02
|
||||
|
||||
- Fix using `pub impl` with `#[async_trait]`.
|
||||
|
||||
## 1.1.1 - 2021-06-12
|
||||
|
||||
- Fix name collision for extensions on `&T` and `&mut T`. The generated traits
|
||||
now get different names.
|
||||
|
||||
## 1.1.0 - 2021-06-12
|
||||
|
||||
- Support setting visibility of the generated trait directly on the `impl`
|
||||
block. For example: `pub impl i32 { ... }`.
|
||||
- Add `#[ext_sized]` for adding `Sized` supertrait.
|
||||
|
||||
## 1.0.1 - 2021-02-14
|
||||
|
||||
- Update maintenance status.
|
||||
|
||||
## 1.0.0 - 2021-01-30
|
||||
|
||||
- Support extensions on bare functions types (things like `fn(i32) -> bool`).
|
||||
- Support extensions on trait objects (things like `dyn Send + Sync`).
|
||||
|
||||
## 0.3.0 - 2020-08-31
|
||||
|
||||
- Add async-trait compatibility.
|
||||
|
||||
### Breaking changes
|
||||
|
||||
- Other attributes put on the `impl` would previously only be included on the generated trait. They're now included on both the trait and the implementation.
|
||||
|
||||
## 0.2.1 - 2020-08-29
|
||||
|
||||
- Fix documentation link in Cargo.toml.
|
||||
- Use more correct repository URL in Cargo.toml.
|
||||
|
||||
## 0.2.0 - 2020-08-29
|
||||
|
||||
- Handle unnamed extensions on the same generic type with different type parameters. For example `Option<i32>` and `Option<String>`. Previously we would generate the same name of both hidden traits which wouldn't compile.
|
||||
- Support associated constants in extension impls.
|
||||
|
||||
### Breaking changes
|
||||
|
||||
- Generated traits are no longer sealed and the `sealed` argument previously supported by `#[ext]` has been removed. Making the traits sealed lead to lots of complexity that we didn't think brought much value.
|
||||
|
||||
## 0.1.1 - 2020-02-22
|
||||
|
||||
- Add support for specifying supertraits of the generated trait [#4](https://github.com/davidpdrsn/extend/pull/4).
|
||||
|
||||
## 0.1.0
|
||||
|
||||
- Support adding extensions to the ["never type"](https://doc.rust-lang.org/std/primitive.never.html).
|
||||
|
||||
### Breaking changes
|
||||
|
||||
- Simplify names of traits generates for complex types.
|
||||
|
||||
## 0.0.2
|
||||
|
||||
- Move "trybuild" to dev-dependency.
|
||||
|
||||
## 0.0.1
|
||||
|
||||
Initial release.
|
||||
48
third_party/rust/extend/Cargo.toml
vendored
48
third_party/rust/extend/Cargo.toml
vendored
|
|
@ -1,48 +0,0 @@
|
|||
# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
|
||||
#
|
||||
# When uploading crates to the registry Cargo will automatically
|
||||
# "normalize" Cargo.toml files for maximal compatibility
|
||||
# with all versions of Cargo and also rewrite `path` dependencies
|
||||
# to registry (e.g., crates.io) dependencies
|
||||
#
|
||||
# If you believe there's an error in this file please file an
|
||||
# issue against the rust-lang/cargo repository. If you're
|
||||
# editing this file be aware that the upstream Cargo.toml
|
||||
# will likely look very different (and much more reasonable)
|
||||
|
||||
[package]
|
||||
edition = "2018"
|
||||
name = "extend"
|
||||
version = "1.1.2"
|
||||
authors = ["David Pedersen <david.pdrsn@gmail.com>"]
|
||||
description = "Create extensions for types you don't own with extension traits but without the boilerplate."
|
||||
homepage = "https://github.com/davidpdrsn/extend"
|
||||
documentation = "https://docs.rs/extend"
|
||||
readme = "README.md"
|
||||
keywords = ["extension", "trait"]
|
||||
categories = ["rust-patterns"]
|
||||
license = "MIT"
|
||||
repository = "https://github.com/davidpdrsn/extend.git"
|
||||
|
||||
[lib]
|
||||
path = "src/lib.rs"
|
||||
proc-macro = true
|
||||
[dependencies.proc-macro-error]
|
||||
version = "1"
|
||||
|
||||
[dependencies.proc-macro2]
|
||||
version = "1"
|
||||
|
||||
[dependencies.quote]
|
||||
version = "1"
|
||||
|
||||
[dependencies.syn]
|
||||
version = "1"
|
||||
features = ["full", "extra-traits", "visit"]
|
||||
[dev-dependencies.async-trait]
|
||||
version = "0.1.40"
|
||||
|
||||
[dev-dependencies.trybuild]
|
||||
version = "1.0.17"
|
||||
[badges.maintenance]
|
||||
status = "passively-maintained"
|
||||
19
third_party/rust/extend/LICENSE
vendored
19
third_party/rust/extend/LICENSE
vendored
|
|
@ -1,19 +0,0 @@
|
|||
MIT License Copyright (c) 2020 David Pedersen
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is furnished
|
||||
to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice (including the next
|
||||
paragraph) shall be included in all copies or substantial portions of the
|
||||
Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
|
||||
OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
|
||||
OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
32
third_party/rust/extend/README.md
vendored
32
third_party/rust/extend/README.md
vendored
|
|
@ -1,32 +0,0 @@
|
|||
# extend
|
||||
|
||||
[](https://crates.io/crates/extend)
|
||||
[](https://docs.rs/extend)
|
||||
[](https://deps.rs/repo/github/davidpdrsn/extend)
|
||||
[](https://github.com/davidpdrsn/extend/actions)
|
||||

|
||||
|
||||
Create extensions for types you don't own with [extension traits] but without the boilerplate.
|
||||
|
||||
Example:
|
||||
|
||||
```rust
|
||||
use extend::ext;
|
||||
|
||||
#[ext]
|
||||
impl<T: Ord> Vec<T> {
|
||||
fn sorted(mut self) -> Self {
|
||||
self.sort();
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
assert_eq!(
|
||||
vec![1, 2, 3],
|
||||
vec![2, 3, 1].sorted(),
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
[extension traits]: https://dev.to/matsimitsu/extending-existing-functionality-in-rust-with-traits-in-rust-3622
|
||||
47
third_party/rust/extend/deny.toml
vendored
47
third_party/rust/extend/deny.toml
vendored
|
|
@ -1,47 +0,0 @@
|
|||
targets = []
|
||||
|
||||
[advisories]
|
||||
db-path = "~/.cargo/advisory-db"
|
||||
db-urls = ["https://github.com/rustsec/advisory-db"]
|
||||
vulnerability = "deny"
|
||||
unmaintained = "warn"
|
||||
yanked = "warn"
|
||||
notice = "warn"
|
||||
ignore = []
|
||||
|
||||
[licenses]
|
||||
unlicensed = "deny"
|
||||
allow = [
|
||||
"MIT",
|
||||
"Apache-2.0",
|
||||
]
|
||||
deny = []
|
||||
copyleft = "warn"
|
||||
allow-osi-fsf-free = "neither"
|
||||
default = "deny"
|
||||
confidence-threshold = 0.8
|
||||
exceptions = []
|
||||
|
||||
[licenses.private]
|
||||
ignore = false
|
||||
registries = []
|
||||
|
||||
[bans]
|
||||
multiple-versions = "deny"
|
||||
wildcards = "allow"
|
||||
highlight = "all"
|
||||
allow = []
|
||||
deny = []
|
||||
skip = []
|
||||
skip-tree = []
|
||||
|
||||
[sources]
|
||||
unknown-registry = "warn"
|
||||
unknown-git = "warn"
|
||||
allow-registry = ["https://github.com/rust-lang/crates.io-index"]
|
||||
allow-git = []
|
||||
|
||||
[sources.allow-org]
|
||||
github = []
|
||||
gitlab = []
|
||||
bitbucket = []
|
||||
1
third_party/rust/extend/rustfmt.toml
vendored
1
third_party/rust/extend/rustfmt.toml
vendored
|
|
@ -1 +0,0 @@
|
|||
merge_imports = true
|
||||
620
third_party/rust/extend/src/lib.rs
vendored
620
third_party/rust/extend/src/lib.rs
vendored
|
|
@ -1,620 +0,0 @@
|
|||
//! Create extensions for types you don't own with [extension traits] but without the boilerplate.
|
||||
//!
|
||||
//! Example:
|
||||
//!
|
||||
//! ```rust
|
||||
//! use extend::ext;
|
||||
//!
|
||||
//! #[ext]
|
||||
//! impl<T: Ord> Vec<T> {
|
||||
//! fn sorted(mut self) -> Self {
|
||||
//! self.sort();
|
||||
//! self
|
||||
//! }
|
||||
//! }
|
||||
//!
|
||||
//! fn main() {
|
||||
//! assert_eq!(
|
||||
//! vec![1, 2, 3],
|
||||
//! vec![2, 3, 1].sorted(),
|
||||
//! );
|
||||
//! }
|
||||
//! ```
|
||||
//!
|
||||
//! # How does it work?
|
||||
//!
|
||||
//! Under the hood it generates a trait with methods in your `impl` and implements those for the
|
||||
//! type you specify. The code shown above expands roughly to:
|
||||
//!
|
||||
//! ```rust
|
||||
//! trait VecExt<T: Ord> {
|
||||
//! fn sorted(self) -> Self;
|
||||
//! }
|
||||
//!
|
||||
//! impl<T: Ord> VecExt<T> for Vec<T> {
|
||||
//! fn sorted(mut self) -> Self {
|
||||
//! self.sort();
|
||||
//! self
|
||||
//! }
|
||||
//! }
|
||||
//! ```
|
||||
//!
|
||||
//! # Supported items
|
||||
//!
|
||||
//! Extensions can contain methods or associated constants:
|
||||
//!
|
||||
//! ```rust
|
||||
//! use extend::ext;
|
||||
//!
|
||||
//! #[ext]
|
||||
//! impl String {
|
||||
//! const CONSTANT: &'static str = "FOO";
|
||||
//!
|
||||
//! fn method() {
|
||||
//! // ...
|
||||
//! # todo!()
|
||||
//! }
|
||||
//! }
|
||||
//! ```
|
||||
//!
|
||||
//! # Configuration
|
||||
//!
|
||||
//! You can configure:
|
||||
//!
|
||||
//! - The visibility of the trait. Use `pub impl ...` to generate `pub trait ...`. The default
|
||||
//! visibility is private.
|
||||
//! - The name of the generated extension trait. Example: `#[ext(name = MyExt)]`. By default we
|
||||
//! generate a name based on what you extend.
|
||||
//! - Which supertraits the generated extension trait should have. Default is no supertraits.
|
||||
//! Example: `#[ext(supertraits = Default + Clone)]`.
|
||||
//!
|
||||
//! More examples:
|
||||
//!
|
||||
//! ```rust
|
||||
//! use extend::ext;
|
||||
//!
|
||||
//! #[ext(name = SortedVecExt)]
|
||||
//! impl<T: Ord> Vec<T> {
|
||||
//! fn sorted(mut self) -> Self {
|
||||
//! self.sort();
|
||||
//! self
|
||||
//! }
|
||||
//! }
|
||||
//!
|
||||
//! #[ext]
|
||||
//! pub(crate) impl i32 {
|
||||
//! fn double(self) -> i32 {
|
||||
//! self * 2
|
||||
//! }
|
||||
//! }
|
||||
//!
|
||||
//! #[ext(name = ResultSafeUnwrapExt)]
|
||||
//! pub impl<T> Result<T, std::convert::Infallible> {
|
||||
//! fn safe_unwrap(self) -> T {
|
||||
//! match self {
|
||||
//! Ok(t) => t,
|
||||
//! Err(_) => unreachable!(),
|
||||
//! }
|
||||
//! }
|
||||
//! }
|
||||
//!
|
||||
//! #[ext(supertraits = Default + Clone)]
|
||||
//! impl String {
|
||||
//! fn my_length(self) -> usize {
|
||||
//! self.len()
|
||||
//! }
|
||||
//! }
|
||||
//! ```
|
||||
//!
|
||||
//! For backwards compatibility you can also declare the visibility as the first argument to `#[ext]`:
|
||||
//!
|
||||
//! ```
|
||||
//! use extend::ext;
|
||||
//!
|
||||
//! #[ext(pub)]
|
||||
//! impl i32 {
|
||||
//! fn double(self) -> i32 {
|
||||
//! self * 2
|
||||
//! }
|
||||
//! }
|
||||
//! ```
|
||||
//!
|
||||
//! # async-trait compatibility
|
||||
//!
|
||||
//! Async extensions are supported via [async-trait](https://crates.io/crates/async-trait).
|
||||
//!
|
||||
//! Be aware that you need to add `#[async_trait]` _below_ `#[ext]`. Otherwise the `ext` macro
|
||||
//! cannot see the `#[async_trait]` attribute and pass it along in the generated code.
|
||||
//!
|
||||
//! Example:
|
||||
//!
|
||||
//! ```
|
||||
//! use extend::ext;
|
||||
//! use async_trait::async_trait;
|
||||
//!
|
||||
//! #[ext]
|
||||
//! #[async_trait]
|
||||
//! impl String {
|
||||
//! async fn read_file() -> String {
|
||||
//! // ...
|
||||
//! # todo!()
|
||||
//! }
|
||||
//! }
|
||||
//! ```
|
||||
//!
|
||||
//! # Other attributes
|
||||
//!
|
||||
//! Other attributes provided _below_ `#[ext]` will be passed along to both the generated trait and
|
||||
//! the implementation. See [async-trait compatibility](#async-trait-compatibility) above for an
|
||||
//! example.
|
||||
//!
|
||||
//! [extension traits]: https://dev.to/matsimitsu/extending-existing-functionality-in-rust-with-traits-in-rust-3622
|
||||
|
||||
#![doc(html_root_url = "https://docs.rs/extend/1.1.2")]
|
||||
#![allow(clippy::let_and_return)]
|
||||
#![deny(
|
||||
unused_variables,
|
||||
mutable_borrow_reservation_conflict,
|
||||
dead_code,
|
||||
unused_must_use,
|
||||
unused_imports
|
||||
)]
|
||||
|
||||
use proc_macro2::TokenStream;
|
||||
use proc_macro_error::*;
|
||||
use quote::{format_ident, quote, ToTokens};
|
||||
use syn::{
|
||||
parse::{self, Parse, ParseStream},
|
||||
parse_macro_input, parse_quote,
|
||||
punctuated::Punctuated,
|
||||
spanned::Spanned,
|
||||
token::{Add, Semi},
|
||||
Ident, ImplItem, ItemImpl, Token, TraitItemConst, TraitItemMethod, Type, TypeArray, TypeBareFn,
|
||||
TypeGroup, TypeNever, TypeParamBound, TypeParen, TypePath, TypePtr, TypeReference, TypeSlice,
|
||||
TypeTraitObject, TypeTuple, Visibility,
|
||||
};
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Input {
|
||||
item_impl: ItemImpl,
|
||||
vis: Option<Visibility>,
|
||||
}
|
||||
|
||||
impl Parse for Input {
|
||||
fn parse(input: ParseStream) -> syn::Result<Self> {
|
||||
let mut attributes = Vec::new();
|
||||
if input.peek(syn::Token![#]) {
|
||||
attributes.extend(syn::Attribute::parse_outer(input)?);
|
||||
}
|
||||
|
||||
let vis = input
|
||||
.parse::<Visibility>()
|
||||
.ok()
|
||||
.filter(|vis| vis != &Visibility::Inherited);
|
||||
|
||||
let mut item_impl = input.parse::<ItemImpl>()?;
|
||||
item_impl.attrs.extend(attributes);
|
||||
|
||||
Ok(Self { item_impl, vis })
|
||||
}
|
||||
}
|
||||
|
||||
/// See crate docs for more info.
|
||||
#[proc_macro_attribute]
|
||||
#[proc_macro_error]
|
||||
#[allow(clippy::unneeded_field_pattern)]
|
||||
pub fn ext(
|
||||
attr: proc_macro::TokenStream,
|
||||
item: proc_macro::TokenStream,
|
||||
) -> proc_macro::TokenStream {
|
||||
let item = parse_macro_input!(item as Input);
|
||||
let config = parse_macro_input!(attr as Config);
|
||||
go(item, config)
|
||||
}
|
||||
|
||||
/// Like [`ext`](macro@crate::ext) but always add `Sized` as a supertrait.
|
||||
///
|
||||
/// This is provided as a convenience for generating extension traits that require `Self: Sized`
|
||||
/// such as:
|
||||
///
|
||||
/// ```
|
||||
/// use extend::ext_sized;
|
||||
///
|
||||
/// #[ext_sized]
|
||||
/// impl i32 {
|
||||
/// fn requires_sized(self) -> Option<Self> {
|
||||
/// Some(self)
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
#[proc_macro_attribute]
|
||||
#[proc_macro_error]
|
||||
#[allow(clippy::unneeded_field_pattern)]
|
||||
pub fn ext_sized(
|
||||
attr: proc_macro::TokenStream,
|
||||
item: proc_macro::TokenStream,
|
||||
) -> proc_macro::TokenStream {
|
||||
let item = parse_macro_input!(item as Input);
|
||||
let mut config: Config = parse_macro_input!(attr as Config);
|
||||
|
||||
config.supertraits = if let Some(supertraits) = config.supertraits.take() {
|
||||
Some(parse_quote!(#supertraits + Sized))
|
||||
} else {
|
||||
Some(parse_quote!(Sized))
|
||||
};
|
||||
|
||||
go(item, config)
|
||||
}
|
||||
|
||||
fn go(item: Input, mut config: Config) -> proc_macro::TokenStream {
|
||||
if let Some(vis) = item.vis {
|
||||
if config.visibility != Visibility::Inherited {
|
||||
abort!(
|
||||
config.visibility.span(),
|
||||
"Cannot set visibility on `#[ext]` and `impl` block"
|
||||
);
|
||||
}
|
||||
|
||||
config.visibility = vis;
|
||||
}
|
||||
|
||||
let ItemImpl {
|
||||
attrs,
|
||||
unsafety,
|
||||
generics,
|
||||
trait_,
|
||||
self_ty,
|
||||
items,
|
||||
// What is defaultness?
|
||||
defaultness: _,
|
||||
impl_token: _,
|
||||
brace_token: _,
|
||||
} = item.item_impl;
|
||||
|
||||
if let Some((_, path, _)) = trait_ {
|
||||
abort!(path.span(), "Trait impls cannot be used for #[ext]");
|
||||
}
|
||||
|
||||
let self_ty = parse_self_ty(&self_ty);
|
||||
|
||||
let ext_trait_name = config
|
||||
.ext_trait_name
|
||||
.unwrap_or_else(|| ext_trait_name(&self_ty));
|
||||
|
||||
let MethodsAndConsts {
|
||||
trait_methods,
|
||||
trait_consts,
|
||||
} = extract_allowed_items(&items);
|
||||
|
||||
let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
|
||||
|
||||
let visibility = &config.visibility;
|
||||
|
||||
let mut all_supertraits = Vec::<TypeParamBound>::new();
|
||||
|
||||
if let Some(supertraits_from_config) = config.supertraits {
|
||||
all_supertraits.extend(supertraits_from_config);
|
||||
}
|
||||
|
||||
let supertraits_quoted = if all_supertraits.is_empty() {
|
||||
quote! {}
|
||||
} else {
|
||||
let supertraits_quoted = punctuated_from_iter::<_, _, Add>(all_supertraits);
|
||||
quote! { : #supertraits_quoted }
|
||||
};
|
||||
|
||||
let code = (quote! {
|
||||
#[allow(non_camel_case_types)]
|
||||
#(#attrs)*
|
||||
#visibility
|
||||
#unsafety
|
||||
trait #ext_trait_name #impl_generics #supertraits_quoted #where_clause {
|
||||
#(
|
||||
#trait_consts
|
||||
)*
|
||||
|
||||
#(
|
||||
#[allow(
|
||||
patterns_in_fns_without_body,
|
||||
clippy::inline_fn_without_body,
|
||||
unused_attributes
|
||||
)]
|
||||
#trait_methods
|
||||
)*
|
||||
}
|
||||
|
||||
#(#attrs)*
|
||||
impl #impl_generics #ext_trait_name #ty_generics for #self_ty #where_clause {
|
||||
#(#items)*
|
||||
}
|
||||
})
|
||||
.into();
|
||||
|
||||
code
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
enum ExtType<'a> {
|
||||
Array(&'a TypeArray),
|
||||
Group(&'a TypeGroup),
|
||||
Never(&'a TypeNever),
|
||||
Paren(&'a TypeParen),
|
||||
Path(&'a TypePath),
|
||||
Ptr(&'a TypePtr),
|
||||
Reference(&'a TypeReference),
|
||||
Slice(&'a TypeSlice),
|
||||
Tuple(&'a TypeTuple),
|
||||
BareFn(&'a TypeBareFn),
|
||||
TraitObject(&'a TypeTraitObject),
|
||||
}
|
||||
|
||||
#[allow(clippy::wildcard_in_or_patterns)]
|
||||
fn parse_self_ty(self_ty: &Type) -> ExtType {
|
||||
match self_ty {
|
||||
Type::Array(inner) => ExtType::Array(inner),
|
||||
Type::Group(inner) => ExtType::Group(inner),
|
||||
Type::Never(inner) => ExtType::Never(inner),
|
||||
Type::Paren(inner) => ExtType::Paren(inner),
|
||||
Type::Path(inner) => ExtType::Path(inner),
|
||||
Type::Ptr(inner) => ExtType::Ptr(inner),
|
||||
Type::Reference(inner) => ExtType::Reference(inner),
|
||||
Type::Slice(inner) => ExtType::Slice(inner),
|
||||
Type::Tuple(inner) => ExtType::Tuple(inner),
|
||||
Type::BareFn(inner) => ExtType::BareFn(inner),
|
||||
Type::TraitObject(inner) => ExtType::TraitObject(inner),
|
||||
|
||||
Type::ImplTrait(_) | Type::Infer(_) | Type::Macro(_) | Type::Verbatim(_) | _ => abort!(
|
||||
self_ty.span(),
|
||||
"#[ext] is not supported for this kind of type"
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<&'a Type> for ExtType<'a> {
|
||||
fn from(inner: &'a Type) -> ExtType<'a> {
|
||||
parse_self_ty(inner)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> ToTokens for ExtType<'a> {
|
||||
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||
match self {
|
||||
ExtType::Array(inner) => inner.to_tokens(tokens),
|
||||
ExtType::Group(inner) => inner.to_tokens(tokens),
|
||||
ExtType::Never(inner) => inner.to_tokens(tokens),
|
||||
ExtType::Paren(inner) => inner.to_tokens(tokens),
|
||||
ExtType::Path(inner) => inner.to_tokens(tokens),
|
||||
ExtType::Ptr(inner) => inner.to_tokens(tokens),
|
||||
ExtType::Reference(inner) => inner.to_tokens(tokens),
|
||||
ExtType::Slice(inner) => inner.to_tokens(tokens),
|
||||
ExtType::Tuple(inner) => inner.to_tokens(tokens),
|
||||
ExtType::BareFn(inner) => inner.to_tokens(tokens),
|
||||
ExtType::TraitObject(inner) => inner.to_tokens(tokens),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn ext_trait_name(self_ty: &ExtType) -> Ident {
|
||||
fn inner_self_ty(self_ty: &ExtType) -> Ident {
|
||||
match self_ty {
|
||||
ExtType::Path(inner) => find_and_combine_idents(inner),
|
||||
ExtType::Reference(inner) => {
|
||||
let name = inner_self_ty(&(&*inner.elem).into());
|
||||
if inner.mutability.is_some() {
|
||||
format_ident!("RefMut{}", name)
|
||||
} else {
|
||||
format_ident!("Ref{}", name)
|
||||
}
|
||||
}
|
||||
ExtType::Array(inner) => {
|
||||
let name = inner_self_ty(&(&*inner.elem).into());
|
||||
format_ident!("ListOf{}", name)
|
||||
}
|
||||
ExtType::Group(inner) => {
|
||||
let name = inner_self_ty(&(&*inner.elem).into());
|
||||
format_ident!("Group{}", name)
|
||||
}
|
||||
ExtType::Paren(inner) => {
|
||||
let name = inner_self_ty(&(&*inner.elem).into());
|
||||
format_ident!("Paren{}", name)
|
||||
}
|
||||
ExtType::Ptr(inner) => {
|
||||
let name = inner_self_ty(&(&*inner.elem).into());
|
||||
format_ident!("PointerTo{}", name)
|
||||
}
|
||||
ExtType::Slice(inner) => {
|
||||
let name = inner_self_ty(&(&*inner.elem).into());
|
||||
format_ident!("SliceOf{}", name)
|
||||
}
|
||||
ExtType::Tuple(inner) => {
|
||||
let mut name = format_ident!("TupleOf");
|
||||
for elem in &inner.elems {
|
||||
name = format_ident!("{}{}", name, inner_self_ty(&elem.into()));
|
||||
}
|
||||
name
|
||||
}
|
||||
ExtType::Never(_) => format_ident!("Never"),
|
||||
ExtType::BareFn(inner) => {
|
||||
let mut name = format_ident!("BareFn");
|
||||
for input in inner.inputs.iter() {
|
||||
name = format_ident!("{}{}", name, inner_self_ty(&(&input.ty).into()));
|
||||
}
|
||||
match &inner.output {
|
||||
syn::ReturnType::Default => {
|
||||
name = format_ident!("{}Unit", name);
|
||||
}
|
||||
syn::ReturnType::Type(_, ty) => {
|
||||
name = format_ident!("{}{}", name, inner_self_ty(&(&**ty).into()));
|
||||
}
|
||||
}
|
||||
name
|
||||
}
|
||||
ExtType::TraitObject(inner) => {
|
||||
let mut name = format_ident!("TraitObject");
|
||||
for bound in inner.bounds.iter() {
|
||||
match bound {
|
||||
TypeParamBound::Trait(bound) => {
|
||||
for segment in bound.path.segments.iter() {
|
||||
name = format_ident!("{}{}", name, segment.ident);
|
||||
}
|
||||
}
|
||||
TypeParamBound::Lifetime(lifetime) => {
|
||||
name = format_ident!("{}{}", name, lifetime.ident);
|
||||
}
|
||||
}
|
||||
}
|
||||
name
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
format_ident!("{}Ext", inner_self_ty(self_ty))
|
||||
}
|
||||
|
||||
fn find_and_combine_idents(type_path: &TypePath) -> Ident {
|
||||
use syn::visit::{self, Visit};
|
||||
|
||||
struct IdentVisitor<'a>(Vec<&'a Ident>);
|
||||
|
||||
impl<'a> Visit<'a> for IdentVisitor<'a> {
|
||||
fn visit_ident(&mut self, i: &'a Ident) {
|
||||
self.0.push(i);
|
||||
}
|
||||
}
|
||||
|
||||
let mut visitor = IdentVisitor(Vec::new());
|
||||
visit::visit_type_path(&mut visitor, type_path);
|
||||
let idents = visitor.0;
|
||||
|
||||
if idents.is_empty() {
|
||||
abort!(type_path.span(), "Empty type path")
|
||||
} else {
|
||||
let start = &idents[0].span();
|
||||
let combined_span = idents
|
||||
.iter()
|
||||
.map(|i| i.span())
|
||||
.fold(*start, |a, b| a.join(b).unwrap_or(a));
|
||||
|
||||
let combined_name = idents.iter().map(|i| i.to_string()).collect::<String>();
|
||||
|
||||
Ident::new(&combined_name, combined_span)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
struct MethodsAndConsts {
|
||||
trait_methods: Vec<TraitItemMethod>,
|
||||
trait_consts: Vec<TraitItemConst>,
|
||||
}
|
||||
|
||||
#[allow(clippy::wildcard_in_or_patterns)]
|
||||
fn extract_allowed_items(items: &[ImplItem]) -> MethodsAndConsts {
|
||||
let mut acc = MethodsAndConsts::default();
|
||||
for item in items {
|
||||
match item {
|
||||
ImplItem::Method(method) => acc.trait_methods.push(TraitItemMethod {
|
||||
attrs: method.attrs.clone(),
|
||||
sig: method.sig.clone(),
|
||||
default: None,
|
||||
semi_token: Some(Semi::default()),
|
||||
}),
|
||||
ImplItem::Const(const_) => acc.trait_consts.push(TraitItemConst {
|
||||
attrs: const_.attrs.clone(),
|
||||
const_token: Default::default(),
|
||||
ident: const_.ident.clone(),
|
||||
colon_token: Default::default(),
|
||||
ty: const_.ty.clone(),
|
||||
default: None,
|
||||
semi_token: Default::default(),
|
||||
}),
|
||||
ImplItem::Type(_) => abort!(
|
||||
item.span(),
|
||||
"Associated types are not allowed in #[ext] impls"
|
||||
),
|
||||
ImplItem::Macro(_) => abort!(item.span(), "Macros are not allowed in #[ext] impls"),
|
||||
ImplItem::Verbatim(_) | _ => abort!(item.span(), "Not allowed in #[ext] impls"),
|
||||
}
|
||||
}
|
||||
acc
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Config {
|
||||
ext_trait_name: Option<Ident>,
|
||||
visibility: Visibility,
|
||||
supertraits: Option<Punctuated<TypeParamBound, Add>>,
|
||||
}
|
||||
|
||||
impl Parse for Config {
|
||||
fn parse(input: ParseStream) -> parse::Result<Self> {
|
||||
let mut config = Config::default();
|
||||
|
||||
if let Ok(visibility) = input.parse::<Visibility>() {
|
||||
config.visibility = visibility;
|
||||
}
|
||||
|
||||
input.parse::<Token![,]>().ok();
|
||||
|
||||
while !input.is_empty() {
|
||||
let ident = input.parse::<Ident>()?;
|
||||
input.parse::<Token![=]>()?;
|
||||
|
||||
match &*ident.to_string() {
|
||||
"name" => {
|
||||
config.ext_trait_name = Some(input.parse()?);
|
||||
}
|
||||
"supertraits" => {
|
||||
config.supertraits =
|
||||
Some(Punctuated::<TypeParamBound, Add>::parse_terminated(input)?);
|
||||
}
|
||||
_ => abort!(ident.span(), "Unknown configuration name"),
|
||||
}
|
||||
|
||||
input.parse::<Token![,]>().ok();
|
||||
}
|
||||
|
||||
Ok(config)
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Config {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
ext_trait_name: None,
|
||||
visibility: Visibility::Inherited,
|
||||
supertraits: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn punctuated_from_iter<I, T, P>(i: I) -> Punctuated<T, P>
|
||||
where
|
||||
P: Default,
|
||||
I: IntoIterator<Item = T>,
|
||||
{
|
||||
let mut iter = i.into_iter().peekable();
|
||||
let mut acc = Punctuated::default();
|
||||
|
||||
while let Some(item) = iter.next() {
|
||||
acc.push_value(item);
|
||||
|
||||
if iter.peek().is_some() {
|
||||
acc.push_punct(P::default());
|
||||
}
|
||||
}
|
||||
|
||||
acc
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
#[allow(unused_imports)]
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_ui() {
|
||||
let t = trybuild::TestCases::new();
|
||||
t.pass("tests/compile_pass/*.rs");
|
||||
t.compile_fail("tests/compile_fail/*.rs");
|
||||
}
|
||||
}
|
||||
|
|
@ -1,14 +0,0 @@
|
|||
mod a {
|
||||
use extend::ext;
|
||||
|
||||
#[ext(pub(super))]
|
||||
pub impl i32 {
|
||||
fn foo() -> Foo {
|
||||
Foo
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Foo;
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
error: Cannot set visibility on `#[ext]` and `impl` block
|
||||
--> $DIR/double_vis.rs:4:11
|
||||
|
|
||||
4 | #[ext(pub(super))]
|
||||
| ^^^
|
||||
|
|
@ -1,14 +0,0 @@
|
|||
use extend::ext;
|
||||
|
||||
trait MyTrait {}
|
||||
|
||||
#[ext(supertraits = MyTrait)]
|
||||
impl String {
|
||||
fn my_len(&self) -> usize {
|
||||
self.len()
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
assert_eq!(String::new().my_len(), 0);
|
||||
}
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
error[E0277]: the trait bound `String: MyTrait` is not satisfied
|
||||
--> $DIR/supertraits_are_actually_included.rs:6:6
|
||||
|
|
||||
5 | #[ext(supertraits = MyTrait)]
|
||||
| ------- required by this bound in `StringExt`
|
||||
6 | impl String {
|
||||
| ^^^^^^
|
||||
| |
|
||||
| the trait `MyTrait` is not implemented for `String`
|
||||
| required by a bound in this
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
use extend::ext;
|
||||
|
||||
#[ext]
|
||||
impl Option<String> {
|
||||
const FOO: usize = 1;
|
||||
}
|
||||
|
||||
fn main() {
|
||||
assert_eq!(Option::<String>::FOO, 1);
|
||||
}
|
||||
|
|
@ -1,25 +0,0 @@
|
|||
use extend::ext;
|
||||
use async_trait::async_trait;
|
||||
|
||||
#[ext]
|
||||
#[async_trait]
|
||||
impl String {
|
||||
async fn foo() -> usize {
|
||||
1
|
||||
}
|
||||
}
|
||||
|
||||
#[ext]
|
||||
#[async_trait]
|
||||
pub impl i32 {
|
||||
async fn bar() -> usize {
|
||||
1
|
||||
}
|
||||
}
|
||||
|
||||
async fn foo() {
|
||||
let _: usize = String::foo().await;
|
||||
let _: usize = i32::bar().await;
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
use extend::ext;
|
||||
|
||||
#[ext(name = Foo)]
|
||||
impl i32 {
|
||||
fn foo() {}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
<i32 as Foo>::foo();
|
||||
}
|
||||
|
|
@ -1,16 +0,0 @@
|
|||
mod foo {
|
||||
use extend::ext;
|
||||
|
||||
#[ext(pub)]
|
||||
impl<T1, T2, T3> (T1, T2, T3) {
|
||||
fn size(&self) -> usize {
|
||||
3
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
use foo::TupleOfT1T2T3Ext;
|
||||
|
||||
assert_eq!(3, (0, 0, 0).size());
|
||||
}
|
||||
|
|
@ -1,17 +0,0 @@
|
|||
use extend::ext;
|
||||
|
||||
#[ext]
|
||||
impl Option<usize> {
|
||||
fn foo() -> usize {
|
||||
1
|
||||
}
|
||||
}
|
||||
|
||||
#[ext]
|
||||
impl Option<i32> {
|
||||
fn bar() -> i32 {
|
||||
1
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
@ -1,58 +0,0 @@
|
|||
use extend::ext;
|
||||
|
||||
#[ext]
|
||||
impl<'a> &'a str {
|
||||
fn foo(self) {}
|
||||
}
|
||||
|
||||
#[ext]
|
||||
impl<T> [T; 3] {
|
||||
fn foo(self) {}
|
||||
}
|
||||
|
||||
#[ext]
|
||||
impl *const i32 {
|
||||
fn foo(self) {}
|
||||
}
|
||||
|
||||
#[ext]
|
||||
impl<T> [T] {
|
||||
fn foo(&self) {}
|
||||
}
|
||||
|
||||
#[ext]
|
||||
impl<'a, T> &'a [T] {
|
||||
fn foo(self) {}
|
||||
}
|
||||
|
||||
#[ext]
|
||||
impl (i32, i64) {
|
||||
fn foo(self) {}
|
||||
}
|
||||
|
||||
#[ext]
|
||||
impl fn(i32) -> bool {
|
||||
fn foo(self) {}
|
||||
}
|
||||
|
||||
fn bare_fn(_: i32) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
#[ext]
|
||||
impl dyn Send + Sync + 'static {}
|
||||
|
||||
fn main() {
|
||||
"".foo();
|
||||
|
||||
[1, 2, 3].foo();
|
||||
|
||||
let ptr: *const i32 = &123;
|
||||
ptr.foo();
|
||||
|
||||
&[1, 2, 3].foo();
|
||||
|
||||
(1i32, 1i64).foo();
|
||||
|
||||
(bare_fn as fn(i32) -> bool).foo();
|
||||
}
|
||||
|
|
@ -1,15 +0,0 @@
|
|||
use extend::ext;
|
||||
|
||||
#[ext]
|
||||
impl<'a, T: Clone> Vec<&'a T>
|
||||
where
|
||||
T: 'a + Copy,
|
||||
{
|
||||
fn size(&self) -> usize {
|
||||
self.len()
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
assert_eq!(3, vec![&1, &2, &3].size());
|
||||
}
|
||||
|
|
@ -1,20 +0,0 @@
|
|||
use extend::ext;
|
||||
|
||||
#[ext]
|
||||
impl i32 {
|
||||
fn add_one(&self) -> Self {
|
||||
self + 1
|
||||
}
|
||||
|
||||
fn foo() -> MyType {
|
||||
MyType
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Eq, PartialEq)]
|
||||
struct MyType;
|
||||
|
||||
fn main() {
|
||||
assert_eq!(i32::foo(), MyType);
|
||||
assert_eq!(1.add_one(), 2);
|
||||
}
|
||||
|
|
@ -1,33 +0,0 @@
|
|||
#![allow(unused_variables)]
|
||||
|
||||
use extend::ext;
|
||||
use std::iter::FromIterator;
|
||||
|
||||
#[ext]
|
||||
impl<T, K, F, C> C
|
||||
where
|
||||
C: IntoIterator<Item = T>,
|
||||
K: Eq,
|
||||
F: Fn(&T) -> K,
|
||||
{
|
||||
fn group_by<Out>(self, f: F) -> Out
|
||||
where
|
||||
Out: FromIterator<(K, Vec<T>)>,
|
||||
{
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn group_by_and_map_values<Out, G, T2>(self, f: F, g: G) -> Out
|
||||
where
|
||||
G: Fn(T) -> T2 + Copy,
|
||||
Out: FromIterator<(K, Vec<T2>)>,
|
||||
{
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn group_by_and_return_groups(self, f: F) -> Vec<Vec<T>> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
@ -1,13 +0,0 @@
|
|||
use extend::ext;
|
||||
|
||||
#[ext]
|
||||
impl i32 {
|
||||
fn foo() {}
|
||||
}
|
||||
|
||||
#[ext]
|
||||
impl i64 {
|
||||
fn bar() {}
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
@ -1,13 +0,0 @@
|
|||
use extend::ext;
|
||||
|
||||
#[ext(pub(crate), name = Foo)]
|
||||
impl i32 {
|
||||
fn foo() {}
|
||||
}
|
||||
|
||||
#[ext(pub, name = Bar)]
|
||||
impl i64 {
|
||||
fn foo() {}
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
use extend::ext;
|
||||
use std::marker::PhantomData;
|
||||
|
||||
struct Foo<T>(PhantomData<T>);
|
||||
|
||||
#[ext]
|
||||
impl<T, K> T {
|
||||
fn some_method(&self, _: Foo<K>) {}
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
@ -1,15 +0,0 @@
|
|||
mod a {
|
||||
use extend::ext;
|
||||
|
||||
#[ext]
|
||||
pub impl i32 {
|
||||
fn foo() -> Foo { Foo }
|
||||
}
|
||||
|
||||
pub struct Foo;
|
||||
}
|
||||
|
||||
fn main() {
|
||||
use a::i32Ext;
|
||||
i32::foo();
|
||||
}
|
||||
|
|
@ -1,13 +0,0 @@
|
|||
use extend::ext;
|
||||
|
||||
#[ext]
|
||||
impl &i32 {
|
||||
fn foo() {}
|
||||
}
|
||||
|
||||
#[ext]
|
||||
impl &mut i32 {
|
||||
fn bar() {}
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
@ -1,36 +0,0 @@
|
|||
use extend::ext_sized;
|
||||
|
||||
#[ext_sized(name = One)]
|
||||
impl i32 {
|
||||
fn requires_sized(self) -> Option<Self> {
|
||||
Some(self)
|
||||
}
|
||||
}
|
||||
|
||||
#[ext_sized(name = Two, supertraits = Default)]
|
||||
impl i32 {
|
||||
fn with_another_supertrait(self) -> Option<Self> {
|
||||
Some(self)
|
||||
}
|
||||
}
|
||||
|
||||
#[ext_sized(name = Three, supertraits = Default + Clone + Copy)]
|
||||
impl i32 {
|
||||
fn multiple_supertraits(self) -> Option<Self> {
|
||||
Some(self)
|
||||
}
|
||||
}
|
||||
|
||||
#[ext_sized(name = Four, supertraits = Sized)]
|
||||
impl i32 {
|
||||
fn already_sized(self) -> Option<Self> {
|
||||
Some(self)
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
1.requires_sized();
|
||||
1.with_another_supertrait();
|
||||
1.multiple_supertraits();
|
||||
1.already_sized();
|
||||
}
|
||||
|
|
@ -1,16 +0,0 @@
|
|||
use extend::ext;
|
||||
|
||||
trait MyTrait {}
|
||||
|
||||
impl MyTrait for String {}
|
||||
|
||||
#[ext(supertraits = Default + Clone + MyTrait)]
|
||||
impl String {
|
||||
fn my_len(&self) -> usize {
|
||||
self.len()
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
assert_eq!(String::new().my_len(), 0);
|
||||
}
|
||||
|
|
@ -1,15 +0,0 @@
|
|||
mod a {
|
||||
use extend::ext;
|
||||
|
||||
#[ext(pub)]
|
||||
impl i32 {
|
||||
fn foo() -> Foo { Foo }
|
||||
}
|
||||
|
||||
pub struct Foo;
|
||||
}
|
||||
|
||||
fn main() {
|
||||
use a::i32Ext;
|
||||
i32::foo();
|
||||
}
|
||||
|
|
@ -1 +0,0 @@
|
|||
{"files":{"Cargo.toml":"90295a750f9c69ee799ac767d56eaee2c3218df7964f11c885b6910a31d07a25","build.rs":"05089b35ac197b5ff83c75872a70df023834141831d0c2051faa35b4c9df55ba","src/arithmetic.udl":"8554c6907ece627645f6b896f71430e5412bf19b0ac6becf63eb9a69868d0f7a","src/lib.rs":"92ebd9fc4d3403ab1960d2d8520c1217971147ea3aebff89228a61fcbb8b2af3","tests/bindings/test_arithmetic.kts":"e0e9347755db4e18f70b1b74c2d5a4aa328373015090ed959b46d65c2a205d92","tests/bindings/test_arithmetic.py":"3e41d69e21e96a6830197c760f3b7bddd754edc0c5515b7bd33b79cccb10f941","tests/bindings/test_arithmetic.rb":"ea0fdce0a4c7b557b427db77521da05240cd6e87d60a128ac2307fab3bbbc76d","tests/bindings/test_arithmetic.swift":"455b87d95fc690af9c35f9e43676e9c855dedddd2fc1c9e1cbaa6a02835c2d4c","tests/test_generated_bindings.rs":"09b0e79c7e769bcf5f3a8b768247a05892d408d48e0295f6737de3c8dab28479","uniffi.toml":"ad149df611a6e3a853a029d90a88a694660f6a4ebe18dcb5f9f503819761dacd"},"package":null}
|
||||
|
|
@ -1,19 +0,0 @@
|
|||
[package]
|
||||
name = "uniffi-example-arithmetic"
|
||||
edition = "2021"
|
||||
version = "0.18.0"
|
||||
authors = ["Firefox Sync Team <sync-team@mozilla.com>"]
|
||||
license = "MPL-2.0"
|
||||
publish = false
|
||||
|
||||
[lib]
|
||||
crate-type = ["lib", "cdylib"]
|
||||
name = "arithmetical"
|
||||
|
||||
[dependencies]
|
||||
uniffi_macros = {path = "../../uniffi_macros"}
|
||||
uniffi = {path = "../../uniffi", features=["builtin-bindgen"]}
|
||||
thiserror = "1.0"
|
||||
|
||||
[build-dependencies]
|
||||
uniffi_build = {path = "../../uniffi_build", features=["builtin-bindgen"]}
|
||||
|
|
@ -1,7 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
fn main() {
|
||||
uniffi_build::generate_scaffolding("./src/arithmetic.udl").unwrap();
|
||||
}
|
||||
|
|
@ -1,16 +0,0 @@
|
|||
[Error]
|
||||
enum ArithmeticError {
|
||||
"IntegerOverflow",
|
||||
};
|
||||
|
||||
namespace arithmetic {
|
||||
[Throws=ArithmeticError]
|
||||
u64 add(u64 a, u64 b);
|
||||
|
||||
[Throws=ArithmeticError]
|
||||
u64 sub(u64 a, u64 b);
|
||||
|
||||
u64 div(u64 dividend, u64 divisor);
|
||||
|
||||
boolean equal(u64 a, u64 b);
|
||||
};
|
||||
|
|
@ -1,34 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum ArithmeticError {
|
||||
#[error("Integer overflow on an operation with {a} and {b}")]
|
||||
IntegerOverflow { a: u64, b: u64 },
|
||||
}
|
||||
|
||||
fn add(a: u64, b: u64) -> Result<u64> {
|
||||
a.checked_add(b)
|
||||
.ok_or(ArithmeticError::IntegerOverflow { a, b })
|
||||
}
|
||||
|
||||
fn sub(a: u64, b: u64) -> Result<u64> {
|
||||
a.checked_sub(b)
|
||||
.ok_or(ArithmeticError::IntegerOverflow { a, b })
|
||||
}
|
||||
|
||||
fn div(dividend: u64, divisor: u64) -> u64 {
|
||||
if divisor == 0 {
|
||||
panic!("Can't divide by zero");
|
||||
}
|
||||
dividend / divisor
|
||||
}
|
||||
|
||||
fn equal(a: u64, b: u64) -> bool {
|
||||
a == b
|
||||
}
|
||||
|
||||
type Result<T, E = ArithmeticError> = std::result::Result<T, E>;
|
||||
|
||||
uniffi_macros::include_scaffolding!("arithmetic");
|
||||
|
|
@ -1,29 +0,0 @@
|
|||
import org.mozilla.uniffi.example.arithmetic.*;
|
||||
|
||||
assert(add(2u, 4u) == 6uL)
|
||||
assert(add(4u, 8u) == 12uL)
|
||||
|
||||
try {
|
||||
sub(0u, 2u)
|
||||
throw RuntimeException("Should have thrown a IntegerOverflow exception!")
|
||||
} catch (e: ArithmeticException) {
|
||||
// It's okay!
|
||||
}
|
||||
|
||||
assert(sub(4u, 2u) == 2uL)
|
||||
assert(sub(8u, 4u) == 4uL)
|
||||
|
||||
assert(div(8u, 4u) == 2uL)
|
||||
|
||||
try {
|
||||
div(8u, 0u)
|
||||
throw RuntimeException("Should have panicked when dividing by zero")
|
||||
} catch (e: InternalException) {
|
||||
// It's okay!
|
||||
}
|
||||
|
||||
assert(equal(2u, 2uL))
|
||||
assert(equal(4u, 4uL))
|
||||
|
||||
assert(!equal(2u, 4uL))
|
||||
assert(!equal(4u, 8uL))
|
||||
|
|
@ -1,37 +0,0 @@
|
|||
from arithmetic import *
|
||||
|
||||
try:
|
||||
add(18446744073709551615, 1)
|
||||
assert(not("Should have thrown a IntegerOverflow exception!"))
|
||||
except ArithmeticError.IntegerOverflow:
|
||||
# It's okay!
|
||||
pass
|
||||
|
||||
assert add(2, 4) == 6
|
||||
assert add(4, 8) == 12
|
||||
|
||||
try:
|
||||
sub(0, 1)
|
||||
assert(not("Should have thrown a IntegerOverflow exception!"))
|
||||
except ArithmeticError.IntegerOverflow:
|
||||
# It's okay!
|
||||
pass
|
||||
|
||||
assert sub(4, 2) == 2
|
||||
assert sub(8, 4) == 4
|
||||
|
||||
assert div(8, 4) == 2
|
||||
|
||||
try:
|
||||
div(8, 0)
|
||||
except InternalError:
|
||||
# It's okay!
|
||||
pass
|
||||
else:
|
||||
assert(not("Should have panicked when dividing by zero"))
|
||||
|
||||
assert equal(2, 2)
|
||||
assert equal(4, 4)
|
||||
|
||||
assert not equal(2, 4)
|
||||
assert not equal(4, 8)
|
||||
|
|
@ -1,31 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'test/unit'
|
||||
require 'arithmetic'
|
||||
|
||||
include Test::Unit::Assertions
|
||||
|
||||
assert_raise Arithmetic::ArithmeticError::IntegerOverflow do
|
||||
Arithmetic.add 18_446_744_073_709_551_615, 1
|
||||
end
|
||||
|
||||
assert_equal Arithmetic.add(2, 4), 6
|
||||
assert_equal Arithmetic.add(4, 8), 12
|
||||
|
||||
assert_raise Arithmetic::ArithmeticError::IntegerOverflow do
|
||||
Arithmetic.sub 0, 1
|
||||
end
|
||||
|
||||
assert_equal Arithmetic.sub(4, 2), 2
|
||||
assert_equal Arithmetic.sub(8, 4), 4
|
||||
assert_equal Arithmetic.div(8, 4), 2
|
||||
|
||||
assert_raise Arithmetic::InternalError do
|
||||
Arithmetic.div 8, 0
|
||||
end
|
||||
|
||||
assert Arithmetic.equal(2, 2)
|
||||
assert Arithmetic.equal(4, 4)
|
||||
|
||||
assert !Arithmetic.equal(2, 4)
|
||||
assert !Arithmetic.equal(4, 8)
|
||||
|
|
@ -1,32 +0,0 @@
|
|||
import arithmetic
|
||||
|
||||
do {
|
||||
let _ = try add(a: 18446744073709551615, b: 1)
|
||||
fatalError("Should have thrown a IntegerOverflow exception!")
|
||||
} catch ArithmeticError.IntegerOverflow {
|
||||
// It's okay!
|
||||
}
|
||||
|
||||
assert(try! add(a: 2, b: 4) == 6, "add work")
|
||||
assert(try! add(a: 4, b: 8) == 12, "add work")
|
||||
|
||||
do {
|
||||
let _ = try sub(a: 0, b: 1)
|
||||
fatalError("Should have thrown a IntegerOverflow exception!")
|
||||
} catch ArithmeticError.IntegerOverflow {
|
||||
// It's okay!
|
||||
}
|
||||
|
||||
assert(try! sub(a: 4, b: 2) == 2, "sub work")
|
||||
assert(try! sub(a: 8, b: 4) == 4, "sub work")
|
||||
|
||||
assert(div(dividend: 8, divisor: 4) == 2, "div works")
|
||||
|
||||
// We can't test panicking in Swift because we force unwrap the error in
|
||||
// `div`, which we can't catch.
|
||||
|
||||
assert(equal(a: 2, b: 2), "equal works")
|
||||
assert(equal(a: 4, b: 4), "equal works")
|
||||
|
||||
assert(!equal(a: 2, b: 4), "non-equal works")
|
||||
assert(!equal(a: 4, b: 8), "non-equal works")
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
uniffi_macros::build_foreign_language_testcases!(
|
||||
["src/arithmetic.udl",],
|
||||
[
|
||||
"tests/bindings/test_arithmetic.rb",
|
||||
"tests/bindings/test_arithmetic.py",
|
||||
"tests/bindings/test_arithmetic.kts",
|
||||
"tests/bindings/test_arithmetic.swift",
|
||||
]
|
||||
);
|
||||
|
|
@ -1,12 +0,0 @@
|
|||
[bindings.kotlin]
|
||||
package_name = "org.mozilla.uniffi.example.arithmetic"
|
||||
cdylib_name = "arithmetical"
|
||||
|
||||
[bindings.python]
|
||||
cdylib_name = "arithmetical"
|
||||
|
||||
[bindings.ruby]
|
||||
cdylib_name = "arithmetical"
|
||||
|
||||
[bindings.swift]
|
||||
cdylib_name = "arithmetical"
|
||||
|
|
@ -1 +0,0 @@
|
|||
{"files":{"Cargo.toml":"15bbf6e8c0d438e7f776dfdcf8da5fefb41e4b5bacafe97d1fcb10389d07ed9b","build.rs":"94ca4e70e538a2159cb77157c227d487973756373c4b27ea5cea05a6698cb60b","src/geometry.udl":"7da7a6ec080c7117ec3c25206e23f9ed436e60b1a26fba34f991547680443550","src/lib.rs":"be9c624f691a8d1ebe3be6dbbcde44033759b8321a3a298453018dd69b9c14c7","tests/bindings/test_geometry.kts":"e537185e3c699df1c0468525700e8a38f9a504b2a663c38442146b951e38e9a7","tests/bindings/test_geometry.py":"3ea483b8a4fbe13aefa6641177ae149f75f734bc32bf0da533b97c1abf3dc317","tests/bindings/test_geometry.rb":"17c2fe8a7b477419a6646983dd88f1b07a0304b58a568c03e9bfa640d5b2df5c","tests/bindings/test_geometry.swift":"a61fec6bfe16020809e20e4da372748c24366767138c5672a0bfff85c4b62d78","tests/test_generated_bindings.rs":"8ba67396105b96cc554f78078c7a8c6e8ce86ecc868d97a069a5f60fd87c1a36","uniffi.toml":"5b28f45d3c2581a52cf886a502f034778a002815b66994e5da2081a5c9f5284b"},"package":null}
|
||||
|
|
@ -1,18 +0,0 @@
|
|||
[package]
|
||||
name = "uniffi-example-geometry"
|
||||
edition = "2021"
|
||||
version = "0.18.0"
|
||||
authors = ["Firefox Sync Team <sync-team@mozilla.com>"]
|
||||
license = "MPL-2.0"
|
||||
publish = false
|
||||
|
||||
[lib]
|
||||
crate-type = ["lib", "cdylib"]
|
||||
name = "uniffi_geometry"
|
||||
|
||||
[dependencies]
|
||||
uniffi_macros = {path = "../../uniffi_macros"}
|
||||
uniffi = {path = "../../uniffi", features=["builtin-bindgen"]}
|
||||
|
||||
[build-dependencies]
|
||||
uniffi_build = {path = "../../uniffi_build", features=["builtin-bindgen"]}
|
||||
|
|
@ -1,7 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
fn main() {
|
||||
uniffi_build::generate_scaffolding("./src/geometry.udl").unwrap();
|
||||
}
|
||||
|
|
@ -1,15 +0,0 @@
|
|||
|
||||
namespace geometry {
|
||||
double gradient(Line ln);
|
||||
Point? intersection(Line ln1, Line ln2);
|
||||
};
|
||||
|
||||
dictionary Point {
|
||||
double coord_x;
|
||||
double coord_y;
|
||||
};
|
||||
|
||||
dictionary Line {
|
||||
Point start;
|
||||
Point end;
|
||||
};
|
||||
|
|
@ -1,47 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
// https://rust-lang.github.io/rust-clippy/master/index.html#float_cmp
|
||||
// Silence, clippy!
|
||||
const EPSILON: f64 = 0.0001f64;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Point {
|
||||
coord_x: f64,
|
||||
coord_y: f64,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Line {
|
||||
start: Point,
|
||||
end: Point,
|
||||
}
|
||||
|
||||
pub fn gradient(ln: Line) -> f64 {
|
||||
let rise = ln.end.coord_y - ln.start.coord_y;
|
||||
let run = ln.end.coord_x - ln.start.coord_x;
|
||||
rise / run
|
||||
}
|
||||
|
||||
pub fn intersection(ln1: Line, ln2: Line) -> Option<Point> {
|
||||
// TODO: yuck, should be able to take &Line as argument here
|
||||
// and have rust figure it out with a bunch of annotations...
|
||||
let g1 = gradient(ln1.clone());
|
||||
let z1 = ln1.start.coord_y - g1 * ln1.start.coord_x;
|
||||
let g2 = gradient(ln2.clone());
|
||||
let z2 = ln2.start.coord_y - g2 * ln2.start.coord_x;
|
||||
// Parallel lines do not intersect.
|
||||
if (g1 - g2).abs() < EPSILON {
|
||||
return None;
|
||||
}
|
||||
// Otherwise, they intersect at this fancy calculation that
|
||||
// I found on wikipedia.
|
||||
let x = (z2 - z1) / (g1 - g2);
|
||||
Some(Point {
|
||||
coord_x: x,
|
||||
coord_y: g1 * x + z1,
|
||||
})
|
||||
}
|
||||
|
||||
include!(concat!(env!("OUT_DIR"), "/geometry.uniffi.rs"));
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
import uniffi.geometry.*;
|
||||
|
||||
val ln1 = Line(Point(0.0,0.0), Point(1.0,2.0))
|
||||
val ln2 = Line(Point(1.0,1.0), Point(2.0,2.0))
|
||||
|
||||
assert( gradient(ln1) == 2.0 )
|
||||
assert( gradient(ln2) == 1.0 )
|
||||
|
||||
assert( intersection(ln1, ln2) == Point(0.0, 0.0) )
|
||||
assert( intersection(ln1, ln1) == null )
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
from geometry import *
|
||||
|
||||
ln1 = Line(Point(0,0), Point(1,2))
|
||||
ln2 = Line(Point(1,1), Point(2,2))
|
||||
|
||||
assert gradient(ln1) == 2
|
||||
assert gradient(ln2) == 1
|
||||
|
||||
assert intersection(ln1, ln2) == Point(0, 0)
|
||||
assert intersection(ln1, ln1) is None
|
||||
|
|
@ -1,16 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'test/unit'
|
||||
require 'geometry'
|
||||
|
||||
include Test::Unit::Assertions
|
||||
include Geometry
|
||||
|
||||
ln1 = Line.new(Point.new(0.0, 0.0), Point.new(1.0, 2.0))
|
||||
ln2 = Line.new(Point.new(1.0, 1.0), Point.new(2.0, 2.0))
|
||||
|
||||
assert_equal Geometry.gradient(ln1), 2
|
||||
assert_equal Geometry.gradient(ln2), 1
|
||||
|
||||
assert_equal Geometry.intersection(ln1, ln2), Point.new(0, 0)
|
||||
assert Geometry.intersection(ln1, ln1).nil?
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
import geometry
|
||||
|
||||
let ln1 = Line(start: Point(coordX: 0, coordY: 0), end: Point(coordX: 1, coordY: 2))
|
||||
let ln2 = Line(start: Point(coordX: 1, coordY: 1), end: Point(coordX: 2, coordY: 2))
|
||||
|
||||
assert(gradient(ln: ln1) == 2.0)
|
||||
assert(gradient(ln: ln2) == 1.0)
|
||||
|
||||
assert(intersection(ln1: ln1, ln2: ln2) == Point(coordX: 0, coordY: 0))
|
||||
assert(intersection(ln1: ln1, ln2: ln1) == nil)
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
uniffi_macros::build_foreign_language_testcases!(
|
||||
["src/geometry.udl",],
|
||||
[
|
||||
"tests/bindings/test_geometry.py",
|
||||
"tests/bindings/test_geometry.rb",
|
||||
"tests/bindings/test_geometry.kts",
|
||||
"tests/bindings/test_geometry.swift",
|
||||
]
|
||||
);
|
||||
|
|
@ -1 +0,0 @@
|
|||
[bindings.swift]
|
||||
|
|
@ -1 +0,0 @@
|
|||
{"files":{"Cargo.toml":"e26e9e2826e89bf73aed693d2cea2aa1e2ce3d32cb0f03136cc29352f851295c","build.rs":"c48df8045c6cf73a8f3b8e93af7878f4ce1e7baa11f0688d661405f339df4ba4","src/lib.rs":"70b9ab1fb944d3af1ce53ce097caf52d1ebbf0e18be1e70bf57e5cec96e76502","src/rondpoint.udl":"ca4d8720758608b06ffd5f81bfc73881fbd0693a7a5b21bfe61a4557ea052048","tests/bindings/test_rondpoint.kts":"87b3d507f4260aae4e4711263c13b7158b9a814cb97bf5219d1451f348cd7372","tests/bindings/test_rondpoint.py":"d618274170af767f8a5614a2565ea698b26ea3e1a222d5c110e7b2d00763e73b","tests/bindings/test_rondpoint.rb":"9cc49df311823d6caedbe7b05ff8c4da6329063c2ce16810192aaaa7edcdf5f5","tests/bindings/test_rondpoint.swift":"471cf430be35dcdc19b3166adbc08561e0bd939931edc37da974e0fd16a49331","tests/test_generated_bindings.rs":"5843b2c9d6b86b35ab932349d278d9f281493880a1395e0b7566e297fad36c7d"},"package":null}
|
||||
|
|
@ -1,18 +0,0 @@
|
|||
[package]
|
||||
name = "uniffi-example-rondpoint"
|
||||
edition = "2021"
|
||||
version = "0.18.0"
|
||||
authors = ["Firefox Sync Team <sync-team@mozilla.com>"]
|
||||
license = "MPL-2.0"
|
||||
publish = false
|
||||
|
||||
[lib]
|
||||
crate-type = ["lib", "cdylib"]
|
||||
name = "uniffi_rondpoint"
|
||||
|
||||
[dependencies]
|
||||
uniffi_macros = {path = "../../uniffi_macros"}
|
||||
uniffi = {path = "../../uniffi", features=["builtin-bindgen"]}
|
||||
|
||||
[build-dependencies]
|
||||
uniffi_build = {path = "../../uniffi_build", features=["builtin-bindgen"]}
|
||||
|
|
@ -1,7 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
fn main() {
|
||||
uniffi_build::generate_scaffolding("./src/rondpoint.udl").unwrap();
|
||||
}
|
||||
293
third_party/rust/uniffi-example-rondpoint/src/lib.rs
vendored
293
third_party/rust/uniffi-example-rondpoint/src/lib.rs
vendored
|
|
@ -1,293 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use std::collections::HashMap;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Dictionnaire {
|
||||
un: Enumeration,
|
||||
deux: bool,
|
||||
petit_nombre: u8,
|
||||
gros_nombre: u64,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct DictionnaireNombres {
|
||||
petit_nombre: u8,
|
||||
court_nombre: u16,
|
||||
nombre_simple: u32,
|
||||
gros_nombre: u64,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct DictionnaireNombresSignes {
|
||||
petit_nombre: i8,
|
||||
court_nombre: i16,
|
||||
nombre_simple: i32,
|
||||
gros_nombre: i64,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum Enumeration {
|
||||
Un,
|
||||
Deux,
|
||||
Trois,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum EnumerationAvecDonnees {
|
||||
Zero,
|
||||
Un { premier: u32 },
|
||||
Deux { premier: u32, second: String },
|
||||
}
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
#[allow(non_snake_case)]
|
||||
pub struct minusculeMAJUSCULEDict {
|
||||
minusculeMAJUSCULEField: bool,
|
||||
}
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
pub enum minusculeMAJUSCULEEnum {
|
||||
minusculeMAJUSCULEVariant,
|
||||
}
|
||||
|
||||
fn copie_enumeration(e: Enumeration) -> Enumeration {
|
||||
e
|
||||
}
|
||||
|
||||
fn copie_enumerations(e: Vec<Enumeration>) -> Vec<Enumeration> {
|
||||
e
|
||||
}
|
||||
|
||||
fn copie_carte(
|
||||
e: HashMap<String, EnumerationAvecDonnees>,
|
||||
) -> HashMap<String, EnumerationAvecDonnees> {
|
||||
e
|
||||
}
|
||||
|
||||
fn copie_dictionnaire(d: Dictionnaire) -> Dictionnaire {
|
||||
d
|
||||
}
|
||||
|
||||
fn switcheroo(b: bool) -> bool {
|
||||
!b
|
||||
}
|
||||
|
||||
// Test that values can traverse both ways across the FFI.
|
||||
// Even if roundtripping works, it's possible we have
|
||||
// symmetrical errors that cancel each other out.
|
||||
#[derive(Debug, Clone)]
|
||||
struct Retourneur;
|
||||
impl Retourneur {
|
||||
fn new() -> Self {
|
||||
Retourneur
|
||||
}
|
||||
fn identique_i8(&self, value: i8) -> i8 {
|
||||
value
|
||||
}
|
||||
fn identique_u8(&self, value: u8) -> u8 {
|
||||
value
|
||||
}
|
||||
fn identique_i16(&self, value: i16) -> i16 {
|
||||
value
|
||||
}
|
||||
fn identique_u16(&self, value: u16) -> u16 {
|
||||
value
|
||||
}
|
||||
fn identique_i32(&self, value: i32) -> i32 {
|
||||
value
|
||||
}
|
||||
fn identique_u32(&self, value: u32) -> u32 {
|
||||
value
|
||||
}
|
||||
fn identique_i64(&self, value: i64) -> i64 {
|
||||
value
|
||||
}
|
||||
fn identique_u64(&self, value: u64) -> u64 {
|
||||
value
|
||||
}
|
||||
fn identique_float(&self, value: f32) -> f32 {
|
||||
value
|
||||
}
|
||||
fn identique_double(&self, value: f64) -> f64 {
|
||||
value
|
||||
}
|
||||
fn identique_boolean(&self, value: bool) -> bool {
|
||||
value
|
||||
}
|
||||
fn identique_string(&self, value: String) -> String {
|
||||
value
|
||||
}
|
||||
fn identique_nombres_signes(
|
||||
&self,
|
||||
value: DictionnaireNombresSignes,
|
||||
) -> DictionnaireNombresSignes {
|
||||
value
|
||||
}
|
||||
fn identique_nombres(&self, value: DictionnaireNombres) -> DictionnaireNombres {
|
||||
value
|
||||
}
|
||||
fn identique_optionneur_dictionnaire(
|
||||
&self,
|
||||
value: OptionneurDictionnaire,
|
||||
) -> OptionneurDictionnaire {
|
||||
value
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
struct Stringifier;
|
||||
|
||||
#[allow(dead_code)]
|
||||
impl Stringifier {
|
||||
fn new() -> Self {
|
||||
Stringifier
|
||||
}
|
||||
fn to_string_i8(&self, value: i8) -> String {
|
||||
value.to_string()
|
||||
}
|
||||
fn to_string_u8(&self, value: u8) -> String {
|
||||
value.to_string()
|
||||
}
|
||||
fn to_string_i16(&self, value: i16) -> String {
|
||||
value.to_string()
|
||||
}
|
||||
fn to_string_u16(&self, value: u16) -> String {
|
||||
value.to_string()
|
||||
}
|
||||
fn to_string_i32(&self, value: i32) -> String {
|
||||
value.to_string()
|
||||
}
|
||||
fn to_string_u32(&self, value: u32) -> String {
|
||||
value.to_string()
|
||||
}
|
||||
fn to_string_i64(&self, value: i64) -> String {
|
||||
value.to_string()
|
||||
}
|
||||
fn to_string_u64(&self, value: u64) -> String {
|
||||
value.to_string()
|
||||
}
|
||||
fn to_string_float(&self, value: f32) -> String {
|
||||
value.to_string()
|
||||
}
|
||||
fn to_string_double(&self, value: f64) -> String {
|
||||
value.to_string()
|
||||
}
|
||||
fn to_string_boolean(&self, value: bool) -> String {
|
||||
value.to_string()
|
||||
}
|
||||
fn well_known_string(&self, value: String) -> String {
|
||||
format!("uniffi 💚 {}!", value)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
struct Optionneur;
|
||||
impl Optionneur {
|
||||
fn new() -> Self {
|
||||
Optionneur
|
||||
}
|
||||
fn sinon_string(&self, value: String) -> String {
|
||||
value
|
||||
}
|
||||
fn sinon_null(&self, value: Option<String>) -> Option<String> {
|
||||
value
|
||||
}
|
||||
fn sinon_boolean(&self, value: bool) -> bool {
|
||||
value
|
||||
}
|
||||
fn sinon_sequence(&self, value: Vec<String>) -> Vec<String> {
|
||||
value
|
||||
}
|
||||
|
||||
fn sinon_zero(&self, value: Option<i32>) -> Option<i32> {
|
||||
value
|
||||
}
|
||||
|
||||
fn sinon_u8_dec(&self, value: u8) -> u8 {
|
||||
value
|
||||
}
|
||||
fn sinon_i8_dec(&self, value: i8) -> i8 {
|
||||
value
|
||||
}
|
||||
fn sinon_u16_dec(&self, value: u16) -> u16 {
|
||||
value
|
||||
}
|
||||
fn sinon_i16_dec(&self, value: i16) -> i16 {
|
||||
value
|
||||
}
|
||||
fn sinon_u32_dec(&self, value: u32) -> u32 {
|
||||
value
|
||||
}
|
||||
fn sinon_i32_dec(&self, value: i32) -> i32 {
|
||||
value
|
||||
}
|
||||
fn sinon_u64_dec(&self, value: u64) -> u64 {
|
||||
value
|
||||
}
|
||||
fn sinon_i64_dec(&self, value: i64) -> i64 {
|
||||
value
|
||||
}
|
||||
|
||||
fn sinon_u8_hex(&self, value: u8) -> u8 {
|
||||
value
|
||||
}
|
||||
fn sinon_i8_hex(&self, value: i8) -> i8 {
|
||||
value
|
||||
}
|
||||
fn sinon_u16_hex(&self, value: u16) -> u16 {
|
||||
value
|
||||
}
|
||||
fn sinon_i16_hex(&self, value: i16) -> i16 {
|
||||
value
|
||||
}
|
||||
fn sinon_u32_hex(&self, value: u32) -> u32 {
|
||||
value
|
||||
}
|
||||
fn sinon_i32_hex(&self, value: i32) -> i32 {
|
||||
value
|
||||
}
|
||||
fn sinon_u64_hex(&self, value: u64) -> u64 {
|
||||
value
|
||||
}
|
||||
fn sinon_i64_hex(&self, value: i64) -> i64 {
|
||||
value
|
||||
}
|
||||
|
||||
fn sinon_u32_oct(&self, value: u32) -> u32 {
|
||||
value
|
||||
}
|
||||
|
||||
fn sinon_f32(&self, value: f32) -> f32 {
|
||||
value
|
||||
}
|
||||
fn sinon_f64(&self, value: f64) -> f64 {
|
||||
value
|
||||
}
|
||||
|
||||
fn sinon_enum(&self, value: Enumeration) -> Enumeration {
|
||||
value
|
||||
}
|
||||
}
|
||||
|
||||
pub struct OptionneurDictionnaire {
|
||||
i8_var: i8,
|
||||
u8_var: u8,
|
||||
i16_var: i16,
|
||||
u16_var: u16,
|
||||
i32_var: i32,
|
||||
u32_var: u32,
|
||||
i64_var: i64,
|
||||
u64_var: u64,
|
||||
float_var: f32,
|
||||
double_var: f64,
|
||||
boolean_var: bool,
|
||||
string_var: String,
|
||||
list_var: Vec<String>,
|
||||
enumeration_var: Enumeration,
|
||||
dictionnaire_var: Option<minusculeMAJUSCULEEnum>,
|
||||
}
|
||||
|
||||
include!(concat!(env!("OUT_DIR"), "/rondpoint.uniffi.rs"));
|
||||
|
|
@ -1,146 +0,0 @@
|
|||
namespace rondpoint {
|
||||
Dictionnaire copie_dictionnaire(Dictionnaire d);
|
||||
Enumeration copie_enumeration(Enumeration e);
|
||||
sequence<Enumeration> copie_enumerations(sequence<Enumeration> e);
|
||||
record<DOMString, EnumerationAvecDonnees> copie_carte(record<DOMString, EnumerationAvecDonnees> c);
|
||||
boolean switcheroo(boolean b);
|
||||
};
|
||||
|
||||
dictionary minusculeMAJUSCULEDict {
|
||||
boolean minusculeMAJUSCULEField;
|
||||
};
|
||||
|
||||
enum minusculeMAJUSCULEEnum {
|
||||
"minusculeMAJUSCULEVariant",
|
||||
};
|
||||
|
||||
enum Enumeration {
|
||||
"Un",
|
||||
"Deux",
|
||||
"Trois",
|
||||
};
|
||||
|
||||
[Enum]
|
||||
interface EnumerationAvecDonnees {
|
||||
Zero();
|
||||
Un(u32 premier);
|
||||
Deux(u32 premier, string second);
|
||||
};
|
||||
|
||||
dictionary Dictionnaire {
|
||||
Enumeration un;
|
||||
boolean deux;
|
||||
u8 petit_nombre;
|
||||
u64 gros_nombre;
|
||||
};
|
||||
|
||||
dictionary DictionnaireNombres {
|
||||
u8 petit_nombre;
|
||||
u16 court_nombre;
|
||||
u32 nombre_simple;
|
||||
u64 gros_nombre;
|
||||
};
|
||||
|
||||
dictionary DictionnaireNombresSignes {
|
||||
i8 petit_nombre;
|
||||
i16 court_nombre;
|
||||
i32 nombre_simple;
|
||||
i64 gros_nombre;
|
||||
};
|
||||
|
||||
interface Retourneur {
|
||||
constructor();
|
||||
i8 identique_i8(i8 value);
|
||||
u8 identique_u8(u8 value);
|
||||
i16 identique_i16(i16 value);
|
||||
u16 identique_u16(u16 value);
|
||||
i32 identique_i32(i32 value);
|
||||
u32 identique_u32(u32 value);
|
||||
i64 identique_i64(i64 value);
|
||||
u64 identique_u64(u64 value);
|
||||
float identique_float(float value);
|
||||
double identique_double(double value);
|
||||
boolean identique_boolean(boolean value);
|
||||
string identique_string(string value);
|
||||
|
||||
DictionnaireNombresSignes identique_nombres_signes(DictionnaireNombresSignes value);
|
||||
DictionnaireNombres identique_nombres(DictionnaireNombres value);
|
||||
OptionneurDictionnaire identique_optionneur_dictionnaire(OptionneurDictionnaire value);
|
||||
};
|
||||
|
||||
interface Stringifier {
|
||||
constructor();
|
||||
string well_known_string(string value);
|
||||
|
||||
string to_string_i8(i8 value);
|
||||
string to_string_u8(u8 value);
|
||||
string to_string_i16(i16 value);
|
||||
string to_string_u16(u16 value);
|
||||
string to_string_i32(i32 value);
|
||||
string to_string_u32(u32 value);
|
||||
string to_string_i64(i64 value);
|
||||
string to_string_u64(u64 value);
|
||||
string to_string_float(float value);
|
||||
string to_string_double(double value);
|
||||
string to_string_boolean(boolean value);
|
||||
};
|
||||
|
||||
interface Optionneur {
|
||||
constructor();
|
||||
boolean sinon_boolean(optional boolean value = false);
|
||||
string sinon_string(optional string value = "default");
|
||||
|
||||
sequence<string> sinon_sequence(optional sequence<string> value = []);
|
||||
|
||||
// Either sides of nullable.
|
||||
string? sinon_null(optional string? value = null);
|
||||
i32? sinon_zero(optional i32? value = 0);
|
||||
|
||||
// Decimal integers, all 42.
|
||||
u8 sinon_u8_dec(optional u8 value = 42);
|
||||
i8 sinon_i8_dec(optional i8 value = -42);
|
||||
u16 sinon_u16_dec(optional u16 value = 42);
|
||||
i16 sinon_i16_dec(optional i16 value = 42);
|
||||
u32 sinon_u32_dec(optional u32 value = 42);
|
||||
i32 sinon_i32_dec(optional i32 value = 42);
|
||||
u64 sinon_u64_dec(optional u64 value = 42);
|
||||
i64 sinon_i64_dec(optional i64 value = 42);
|
||||
|
||||
// Hexadecimal, including negatgives.
|
||||
u8 sinon_u8_hex(optional u8 value = 0xff);
|
||||
i8 sinon_i8_hex(optional i8 value = -0x7f);
|
||||
u16 sinon_u16_hex(optional u16 value = 0xffff);
|
||||
i16 sinon_i16_hex(optional i16 value = 0x7f);
|
||||
u32 sinon_u32_hex(optional u32 value = 0xffffffff);
|
||||
i32 sinon_i32_hex(optional i32 value = 0x7fffffff);
|
||||
u64 sinon_u64_hex(optional u64 value = 0xffffffffffffffff);
|
||||
i64 sinon_i64_hex(optional i64 value = 0x7fffffffffffffff);
|
||||
|
||||
// Octal, FWIW.
|
||||
u32 sinon_u32_oct(optional u32 value = 0755);
|
||||
|
||||
// Floats
|
||||
f32 sinon_f32(optional f32 value = 42.0);
|
||||
f64 sinon_f64(optional f64 value = 42.1);
|
||||
|
||||
// Enums, which we have to treat as strings in the UDL frontend.
|
||||
Enumeration sinon_enum(optional Enumeration value = "Trois");
|
||||
};
|
||||
|
||||
dictionary OptionneurDictionnaire {
|
||||
i8 i8_var = -8;
|
||||
u8 u8_var = 8;
|
||||
i16 i16_var = -0x10;
|
||||
u16 u16_var = 0x10;
|
||||
i32 i32_var = -32;
|
||||
u32 u32_var = 32;
|
||||
i64 i64_var = -64;
|
||||
u64 u64_var = 64;
|
||||
float float_var = 4.0;
|
||||
double double_var = 8.0;
|
||||
boolean boolean_var = true;
|
||||
string string_var = "default";
|
||||
sequence<string> list_var = [];
|
||||
Enumeration enumeration_var = "DEUX";
|
||||
minusculeMAJUSCULEEnum? dictionnaire_var = null;
|
||||
};
|
||||
|
|
@ -1,250 +0,0 @@
|
|||
import uniffi.rondpoint.*
|
||||
|
||||
val dico = Dictionnaire(Enumeration.DEUX, true, 0u, 123456789u)
|
||||
val copyDico = copieDictionnaire(dico)
|
||||
assert(dico == copyDico)
|
||||
|
||||
assert(copieEnumeration(Enumeration.DEUX) == Enumeration.DEUX)
|
||||
assert(copieEnumerations(listOf(Enumeration.UN, Enumeration.DEUX)) == listOf(Enumeration.UN, Enumeration.DEUX))
|
||||
assert(copieCarte(mapOf(
|
||||
"0" to EnumerationAvecDonnees.Zero,
|
||||
"1" to EnumerationAvecDonnees.Un(1u),
|
||||
"2" to EnumerationAvecDonnees.Deux(2u, "deux")
|
||||
)) == mapOf(
|
||||
"0" to EnumerationAvecDonnees.Zero,
|
||||
"1" to EnumerationAvecDonnees.Un(1u),
|
||||
"2" to EnumerationAvecDonnees.Deux(2u, "deux")
|
||||
))
|
||||
|
||||
val var1: EnumerationAvecDonnees = EnumerationAvecDonnees.Zero
|
||||
val var2: EnumerationAvecDonnees = EnumerationAvecDonnees.Un(1u)
|
||||
val var3: EnumerationAvecDonnees = EnumerationAvecDonnees.Un(2u)
|
||||
assert(var1 != var2)
|
||||
assert(var2 != var3)
|
||||
assert(var1 == EnumerationAvecDonnees.Zero)
|
||||
assert(var1 != EnumerationAvecDonnees.Un(1u))
|
||||
assert(var2 == EnumerationAvecDonnees.Un(1u))
|
||||
|
||||
assert(switcheroo(false))
|
||||
|
||||
// Test the roundtrip across the FFI.
|
||||
// This shows that the values we send come back in exactly the same state as we sent them.
|
||||
// i.e. it shows that lowering from kotlin and lifting into rust is symmetrical with
|
||||
// lowering from rust and lifting into kotlin.
|
||||
val rt = Retourneur()
|
||||
|
||||
fun <T> List<T>.affirmAllerRetour(fn: (T) -> T) {
|
||||
this.forEach { v ->
|
||||
assert(fn.invoke(v) == v) { "$fn($v)" }
|
||||
}
|
||||
}
|
||||
|
||||
// Booleans
|
||||
listOf(true, false).affirmAllerRetour(rt::identiqueBoolean)
|
||||
|
||||
// Bytes.
|
||||
listOf(Byte.MIN_VALUE, Byte.MAX_VALUE).affirmAllerRetour(rt::identiqueI8)
|
||||
listOf(0x00, 0xFF).map { it.toUByte() }.affirmAllerRetour(rt::identiqueU8)
|
||||
|
||||
// Shorts
|
||||
listOf(Short.MIN_VALUE, Short.MAX_VALUE).affirmAllerRetour(rt::identiqueI16)
|
||||
listOf(0x0000, 0xFFFF).map { it.toUShort() }.affirmAllerRetour(rt::identiqueU16)
|
||||
|
||||
// Ints
|
||||
listOf(0, 1, -1, Int.MIN_VALUE, Int.MAX_VALUE).affirmAllerRetour(rt::identiqueI32)
|
||||
listOf(0x00000000, 0xFFFFFFFF).map { it.toUInt() }.affirmAllerRetour(rt::identiqueU32)
|
||||
|
||||
// Longs
|
||||
listOf(0L, 1L, -1L, Long.MIN_VALUE, Long.MAX_VALUE).affirmAllerRetour(rt::identiqueI64)
|
||||
listOf(0u, 1u, ULong.MIN_VALUE, ULong.MAX_VALUE).affirmAllerRetour(rt::identiqueU64)
|
||||
|
||||
// Floats
|
||||
listOf(0.0F, 0.5F, 0.25F, Float.MIN_VALUE, Float.MAX_VALUE).affirmAllerRetour(rt::identiqueFloat)
|
||||
|
||||
// Doubles
|
||||
listOf(0.0, 1.0, Double.MIN_VALUE, Double.MAX_VALUE).affirmAllerRetour(rt::identiqueDouble)
|
||||
|
||||
// Strings
|
||||
listOf("", "abc", "null\u0000byte", "été", "ښي لاس ته لوستلو لوستل", "😻emoji 👨👧👦multi-emoji, 🇨🇭a flag, a canal, panama")
|
||||
.affirmAllerRetour(rt::identiqueString)
|
||||
|
||||
listOf(-1, 0, 1).map { DictionnaireNombresSignes(it.toByte(), it.toShort(), it.toInt(), it.toLong()) }
|
||||
.affirmAllerRetour(rt::identiqueNombresSignes)
|
||||
|
||||
listOf(0, 1).map { DictionnaireNombres(it.toUByte(), it.toUShort(), it.toUInt(), it.toULong()) }
|
||||
.affirmAllerRetour(rt::identiqueNombres)
|
||||
|
||||
|
||||
rt.destroy()
|
||||
|
||||
// Test one way across the FFI.
|
||||
//
|
||||
// We send one representation of a value to lib.rs, and it transforms it into another, a string.
|
||||
// lib.rs sends the string back, and then we compare here in kotlin.
|
||||
//
|
||||
// This shows that the values are transformed into strings the same way in both kotlin and rust.
|
||||
// i.e. if we assume that the string return works (we test this assumption elsewhere)
|
||||
// we show that lowering from kotlin and lifting into rust has values that both kotlin and rust
|
||||
// both stringify in the same way. i.e. the same values.
|
||||
//
|
||||
// If we roundtripping proves the symmetry of our lowering/lifting from here to rust, and lowering/lifting from rust t here,
|
||||
// and this convinces us that lowering/lifting from here to rust is correct, then
|
||||
// together, we've shown the correctness of the return leg.
|
||||
val st = Stringifier()
|
||||
|
||||
typealias StringyEquals<T> = (observed: String, expected: T) -> Boolean
|
||||
fun <T> List<T>.affirmEnchaine(
|
||||
fn: (T) -> String,
|
||||
equals: StringyEquals<T> = { obs, exp -> obs == exp.toString() }
|
||||
) {
|
||||
this.forEach { exp ->
|
||||
val obs = fn.invoke(exp)
|
||||
assert(equals(obs, exp)) { "$fn($exp): observed=$obs, expected=$exp" }
|
||||
}
|
||||
}
|
||||
|
||||
// Test the efficacy of the string transport from rust. If this fails, but everything else
|
||||
// works, then things are very weird.
|
||||
val wellKnown = st.wellKnownString("kotlin")
|
||||
assert("uniffi 💚 kotlin!" == wellKnown) { "wellKnownString 'uniffi 💚 kotlin!' == '$wellKnown'" }
|
||||
|
||||
// Booleans
|
||||
listOf(true, false).affirmEnchaine(st::toStringBoolean)
|
||||
|
||||
// Bytes.
|
||||
listOf(Byte.MIN_VALUE, Byte.MAX_VALUE).affirmEnchaine(st::toStringI8)
|
||||
listOf(UByte.MIN_VALUE, UByte.MAX_VALUE).affirmEnchaine(st::toStringU8)
|
||||
|
||||
// Shorts
|
||||
listOf(Short.MIN_VALUE, Short.MAX_VALUE).affirmEnchaine(st::toStringI16)
|
||||
listOf(UShort.MIN_VALUE, UShort.MAX_VALUE).affirmEnchaine(st::toStringU16)
|
||||
|
||||
// Ints
|
||||
listOf(0, 1, -1, Int.MIN_VALUE, Int.MAX_VALUE).affirmEnchaine(st::toStringI32)
|
||||
listOf(0u, 1u, UInt.MIN_VALUE, UInt.MAX_VALUE).affirmEnchaine(st::toStringU32)
|
||||
|
||||
// Longs
|
||||
listOf(0L, 1L, -1L, Long.MIN_VALUE, Long.MAX_VALUE).affirmEnchaine(st::toStringI64)
|
||||
listOf(0u, 1u, ULong.MIN_VALUE, ULong.MAX_VALUE).affirmEnchaine(st::toStringU64)
|
||||
|
||||
// Floats
|
||||
// MIN_VAUE is 1.4E-45. Accuracy and formatting get weird at small sizes.
|
||||
listOf(0.0F, 1.0F, -1.0F, Float.MIN_VALUE, Float.MAX_VALUE).affirmEnchaine(st::toStringFloat) { s, n -> s.toFloat() == n }
|
||||
|
||||
// Doubles
|
||||
// MIN_VALUE is 4.9E-324. Accuracy and formatting get weird at small sizes.
|
||||
listOf(0.0, 1.0, -1.0, Double.MIN_VALUE, Double.MAX_VALUE).affirmEnchaine(st::toStringDouble) { s, n -> s.toDouble() == n }
|
||||
|
||||
st.destroy()
|
||||
|
||||
// Prove to ourselves that default arguments are being used.
|
||||
// Step 1: call the methods without arguments, and check against the UDL.
|
||||
val op = Optionneur()
|
||||
|
||||
assert(op.sinonString() == "default")
|
||||
|
||||
assert(op.sinonBoolean() == false)
|
||||
|
||||
assert(op.sinonSequence() == listOf<String>())
|
||||
|
||||
// optionals
|
||||
assert(op.sinonNull() == null)
|
||||
assert(op.sinonZero() == 0)
|
||||
|
||||
// decimal integers
|
||||
assert(op.sinonI8Dec() == (-42).toByte())
|
||||
assert(op.sinonU8Dec() == 42.toUByte())
|
||||
assert(op.sinonI16Dec() == 42.toShort())
|
||||
assert(op.sinonU16Dec() == 42.toUShort())
|
||||
assert(op.sinonI32Dec() == 42)
|
||||
assert(op.sinonU32Dec() == 42.toUInt())
|
||||
assert(op.sinonI64Dec() == 42L)
|
||||
assert(op.sinonU64Dec() == 42uL)
|
||||
|
||||
// hexadecimal integers
|
||||
assert(op.sinonI8Hex() == (-0x7f).toByte())
|
||||
assert(op.sinonU8Hex() == 0xff.toUByte())
|
||||
assert(op.sinonI16Hex() == 0x7f.toShort())
|
||||
assert(op.sinonU16Hex() == 0xffff.toUShort())
|
||||
assert(op.sinonI32Hex() == 0x7fffffff)
|
||||
assert(op.sinonU32Hex() == 0xffffffff.toUInt())
|
||||
assert(op.sinonI64Hex() == 0x7fffffffffffffffL)
|
||||
assert(op.sinonU64Hex() == 0xffffffffffffffffuL)
|
||||
|
||||
// octal integers
|
||||
assert(op.sinonU32Oct() == 493u) // 0o755
|
||||
|
||||
// floats
|
||||
assert(op.sinonF32() == 42.0f)
|
||||
assert(op.sinonF64() == 42.1)
|
||||
|
||||
// enums
|
||||
assert(op.sinonEnum() == Enumeration.TROIS)
|
||||
|
||||
// Step 2. Convince ourselves that if we pass something else, then that changes the output.
|
||||
// We have shown something coming out of the sinon methods, but without eyeballing the Rust
|
||||
// we can't be sure that the arguments will change the return value.
|
||||
listOf("foo", "bar").affirmAllerRetour(op::sinonString)
|
||||
listOf(true, false).affirmAllerRetour(op::sinonBoolean)
|
||||
listOf(listOf("a", "b"), listOf()).affirmAllerRetour(op::sinonSequence)
|
||||
|
||||
// optionals
|
||||
listOf("0", "1").affirmAllerRetour(op::sinonNull)
|
||||
listOf(0, 1).affirmAllerRetour(op::sinonZero)
|
||||
|
||||
// integers
|
||||
listOf(0, 1).map { it.toUByte() }.affirmAllerRetour(op::sinonU8Dec)
|
||||
listOf(0, 1).map { it.toByte() }.affirmAllerRetour(op::sinonI8Dec)
|
||||
listOf(0, 1).map { it.toUShort() }.affirmAllerRetour(op::sinonU16Dec)
|
||||
listOf(0, 1).map { it.toShort() }.affirmAllerRetour(op::sinonI16Dec)
|
||||
listOf(0, 1).map { it.toUInt() }.affirmAllerRetour(op::sinonU32Dec)
|
||||
listOf(0, 1).map { it.toInt() }.affirmAllerRetour(op::sinonI32Dec)
|
||||
listOf(0, 1).map { it.toULong() }.affirmAllerRetour(op::sinonU64Dec)
|
||||
listOf(0, 1).map { it.toLong() }.affirmAllerRetour(op::sinonI64Dec)
|
||||
|
||||
listOf(0, 1).map { it.toUByte() }.affirmAllerRetour(op::sinonU8Hex)
|
||||
listOf(0, 1).map { it.toByte() }.affirmAllerRetour(op::sinonI8Hex)
|
||||
listOf(0, 1).map { it.toUShort() }.affirmAllerRetour(op::sinonU16Hex)
|
||||
listOf(0, 1).map { it.toShort() }.affirmAllerRetour(op::sinonI16Hex)
|
||||
listOf(0, 1).map { it.toUInt() }.affirmAllerRetour(op::sinonU32Hex)
|
||||
listOf(0, 1).map { it.toInt() }.affirmAllerRetour(op::sinonI32Hex)
|
||||
listOf(0, 1).map { it.toULong() }.affirmAllerRetour(op::sinonU64Hex)
|
||||
listOf(0, 1).map { it.toLong() }.affirmAllerRetour(op::sinonI64Hex)
|
||||
|
||||
listOf(0, 1).map { it.toUInt() }.affirmAllerRetour(op::sinonU32Oct)
|
||||
|
||||
// floats
|
||||
listOf(0.0f, 1.0f).affirmAllerRetour(op::sinonF32)
|
||||
listOf(0.0, 1.0).affirmAllerRetour(op::sinonF64)
|
||||
|
||||
// enums
|
||||
Enumeration.values().toList().affirmAllerRetour(op::sinonEnum)
|
||||
|
||||
op.destroy()
|
||||
|
||||
// Testing defaulting properties in record types.
|
||||
val defaultes = OptionneurDictionnaire()
|
||||
val explicite = OptionneurDictionnaire(
|
||||
i8Var = -8,
|
||||
u8Var = 8u,
|
||||
i16Var = -16,
|
||||
u16Var = 0x10u,
|
||||
i32Var = -32,
|
||||
u32Var = 32u,
|
||||
i64Var = -64L,
|
||||
u64Var = 64uL,
|
||||
floatVar = 4.0f,
|
||||
doubleVar = 8.0,
|
||||
booleanVar = true,
|
||||
stringVar = "default",
|
||||
listVar = listOf(),
|
||||
enumerationVar = Enumeration.DEUX,
|
||||
dictionnaireVar = null
|
||||
)
|
||||
assert(defaultes == explicite)
|
||||
|
||||
// …and makes sure they travel across and back the FFI.
|
||||
val rt2 = Retourneur()
|
||||
listOf(defaultes).affirmAllerRetour(rt2::identiqueOptionneurDictionnaire)
|
||||
|
||||
rt2.destroy()
|
||||
|
|
@ -1,146 +0,0 @@
|
|||
import sys
|
||||
import ctypes
|
||||
from rondpoint import *
|
||||
|
||||
dico = Dictionnaire(Enumeration.DEUX, True, 0, 123456789)
|
||||
copyDico = copie_dictionnaire(dico)
|
||||
assert dico == copyDico
|
||||
|
||||
assert copie_enumeration(Enumeration.DEUX) == Enumeration.DEUX
|
||||
assert copie_enumerations([Enumeration.UN, Enumeration.DEUX]) == [Enumeration.UN, Enumeration.DEUX]
|
||||
assert copie_carte({
|
||||
"0": EnumerationAvecDonnees.ZERO(),
|
||||
"1": EnumerationAvecDonnees.UN(1),
|
||||
"2": EnumerationAvecDonnees.DEUX(2, "deux"),
|
||||
}) == {
|
||||
"0": EnumerationAvecDonnees.ZERO(),
|
||||
"1": EnumerationAvecDonnees.UN(1),
|
||||
"2": EnumerationAvecDonnees.DEUX(2, "deux"),
|
||||
}
|
||||
|
||||
assert switcheroo(False) is True
|
||||
|
||||
assert EnumerationAvecDonnees.ZERO() != EnumerationAvecDonnees.UN(1)
|
||||
assert EnumerationAvecDonnees.UN(1) == EnumerationAvecDonnees.UN(1)
|
||||
assert EnumerationAvecDonnees.UN(1) != EnumerationAvecDonnees.UN(2)
|
||||
|
||||
# Test the roundtrip across the FFI.
|
||||
# This shows that the values we send come back in exactly the same state as we sent them.
|
||||
# i.e. it shows that lowering from python and lifting into rust is symmetrical with
|
||||
# lowering from rust and lifting into python.
|
||||
rt = Retourneur()
|
||||
|
||||
def affirmAllerRetour(vals, identique):
|
||||
for v in vals:
|
||||
id_v = identique(v)
|
||||
assert id_v == v, f"Round-trip failure: {v} => {id_v}"
|
||||
|
||||
MIN_I8 = -1 * 2**7
|
||||
MAX_I8 = 2**7 - 1
|
||||
MIN_I16 = -1 * 2**15
|
||||
MAX_I16 = 2**15 - 1
|
||||
MIN_I32 = -1 * 2**31
|
||||
MAX_I32 = 2**31 - 1
|
||||
MIN_I64 = -1 * 2**31
|
||||
MAX_I64 = 2**31 - 1
|
||||
|
||||
# Python floats are always doubles, so won't round-trip through f32 correctly.
|
||||
# This truncates them appropriately.
|
||||
F32_ONE_THIRD = ctypes.c_float(1.0 / 3).value
|
||||
|
||||
# Booleans
|
||||
affirmAllerRetour([True, False], rt.identique_boolean)
|
||||
|
||||
# Bytes.
|
||||
affirmAllerRetour([MIN_I8, -1, 0, 1, MAX_I8], rt.identique_i8)
|
||||
affirmAllerRetour([0x00, 0x12, 0xFF], rt.identique_u8)
|
||||
|
||||
# Shorts
|
||||
affirmAllerRetour([MIN_I16, -1, 0, 1, MAX_I16], rt.identique_i16)
|
||||
affirmAllerRetour([0x0000, 0x1234, 0xFFFF], rt.identique_u16)
|
||||
|
||||
# Ints
|
||||
affirmAllerRetour([MIN_I32, -1, 0, 1, MAX_I32], rt.identique_i32)
|
||||
affirmAllerRetour([0x00000000, 0x12345678, 0xFFFFFFFF], rt.identique_u32)
|
||||
|
||||
# Longs
|
||||
affirmAllerRetour([MIN_I64, -1, 0, 1, MAX_I64], rt.identique_i64)
|
||||
affirmAllerRetour([0x0000000000000000, 0x1234567890ABCDEF, 0xFFFFFFFFFFFFFFFF], rt.identique_u64)
|
||||
|
||||
# Floats
|
||||
affirmAllerRetour([0.0, 0.5, 0.25, 1.0, F32_ONE_THIRD], rt.identique_float)
|
||||
|
||||
# Doubles
|
||||
affirmAllerRetour(
|
||||
[0.0, 0.5, 0.25, 1.0, 1.0 / 3, sys.float_info.max, sys.float_info.min],
|
||||
rt.identique_double
|
||||
)
|
||||
|
||||
# Strings
|
||||
affirmAllerRetour(
|
||||
["", "abc", "été", "ښي لاس ته لوستلو لوستل", "😻emoji 👨👧👦multi-emoji, 🇨🇭a flag, a canal, panama"],
|
||||
rt.identique_string
|
||||
)
|
||||
|
||||
# Test one way across the FFI.
|
||||
#
|
||||
# We send one representation of a value to lib.rs, and it transforms it into another, a string.
|
||||
# lib.rs sends the string back, and then we compare here in python.
|
||||
#
|
||||
# This shows that the values are transformed into strings the same way in both python and rust.
|
||||
# i.e. if we assume that the string return works (we test this assumption elsewhere)
|
||||
# we show that lowering from python and lifting into rust has values that both python and rust
|
||||
# both stringify in the same way. i.e. the same values.
|
||||
#
|
||||
# If we roundtripping proves the symmetry of our lowering/lifting from here to rust, and lowering/lifting from rust to here,
|
||||
# and this convinces us that lowering/lifting from here to rust is correct, then
|
||||
# together, we've shown the correctness of the return leg.
|
||||
st = Stringifier()
|
||||
|
||||
def affirmEnchaine(vals, toString, rustyStringify=lambda v: str(v).lower()):
|
||||
for v in vals:
|
||||
str_v = toString(v)
|
||||
assert rustyStringify(v) == str_v, f"String compare error {v} => {str_v}"
|
||||
|
||||
# Test the efficacy of the string transport from rust. If this fails, but everything else
|
||||
# works, then things are very weird.
|
||||
wellKnown = st.well_known_string("python")
|
||||
assert "uniffi 💚 python!" == wellKnown
|
||||
|
||||
# Booleans
|
||||
affirmEnchaine([True, False], st.to_string_boolean)
|
||||
|
||||
# Bytes.
|
||||
affirmEnchaine([MIN_I8, -1, 0, 1, MAX_I8], st.to_string_i8)
|
||||
affirmEnchaine([0x00, 0x12, 0xFF], st.to_string_u8)
|
||||
|
||||
# Shorts
|
||||
affirmEnchaine([MIN_I16, -1, 0, 1, MAX_I16], st.to_string_i16)
|
||||
affirmEnchaine([0x0000, 0x1234, 0xFFFF], st.to_string_u16)
|
||||
|
||||
# Ints
|
||||
affirmEnchaine([MIN_I32, -1, 0, 1, MAX_I32], st.to_string_i32)
|
||||
affirmEnchaine([0x00000000, 0x12345678, 0xFFFFFFFF], st.to_string_u32)
|
||||
|
||||
# Longs
|
||||
affirmEnchaine([MIN_I64, -1, 0, 1, MAX_I64], st.to_string_i64)
|
||||
affirmEnchaine([0x0000000000000000, 0x1234567890ABCDEF, 0xFFFFFFFFFFFFFFFF], st.to_string_u64)
|
||||
|
||||
# Floats
|
||||
def rustyFloatToStr(v):
|
||||
"""Stringify a float in the same way that rust seems to."""
|
||||
# Rust doesn't include the decimal part of whole enumber floats when stringifying.
|
||||
if int(v) == v:
|
||||
return str(int(v))
|
||||
return str(v)
|
||||
|
||||
affirmEnchaine([0.0, 0.5, 0.25, 1.0], st.to_string_float, rustyFloatToStr)
|
||||
assert st.to_string_float(F32_ONE_THIRD) == "0.33333334" # annoyingly different string repr
|
||||
|
||||
# Doubles
|
||||
# TODO: float_info.max/float_info.min don't stringify-roundtrip properly yet, TBD.
|
||||
affirmEnchaine(
|
||||
[0.0, 0.5, 0.25, 1.0, 1.0 / 3],
|
||||
st.to_string_double,
|
||||
rustyFloatToStr,
|
||||
)
|
||||
|
|
@ -1,142 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'test/unit'
|
||||
require 'rondpoint'
|
||||
|
||||
include Test::Unit::Assertions
|
||||
include Rondpoint
|
||||
|
||||
dico = Dictionnaire.new Enumeration::DEUX, true, 0, 123_456_789
|
||||
|
||||
assert_equal dico, Rondpoint.copie_dictionnaire(dico)
|
||||
|
||||
assert_equal Rondpoint.copie_enumeration(Enumeration::DEUX), Enumeration::DEUX
|
||||
|
||||
assert_equal Rondpoint.copie_enumerations([
|
||||
Enumeration::UN,
|
||||
Enumeration::DEUX
|
||||
]), [Enumeration::UN, Enumeration::DEUX]
|
||||
|
||||
assert_equal Rondpoint.copie_carte({
|
||||
'0' => EnumerationAvecDonnees::ZERO.new,
|
||||
'1' => EnumerationAvecDonnees::UN.new(1),
|
||||
'2' => EnumerationAvecDonnees::DEUX.new(2, 'deux')
|
||||
}), {
|
||||
'0' => EnumerationAvecDonnees::ZERO.new,
|
||||
'1' => EnumerationAvecDonnees::UN.new(1),
|
||||
'2' => EnumerationAvecDonnees::DEUX.new(2, 'deux')
|
||||
}
|
||||
|
||||
assert Rondpoint.switcheroo(false)
|
||||
|
||||
assert_not_equal EnumerationAvecDonnees::ZERO.new, EnumerationAvecDonnees::UN.new(1)
|
||||
assert_equal EnumerationAvecDonnees::UN.new(1), EnumerationAvecDonnees::UN.new(1)
|
||||
assert_not_equal EnumerationAvecDonnees::UN.new(1), EnumerationAvecDonnees::UN.new(2)
|
||||
|
||||
# Test the roundtrip across the FFI.
|
||||
# This shows that the values we send come back in exactly the same state as we sent them.
|
||||
# i.e. it shows that lowering from ruby and lifting into rust is symmetrical with
|
||||
# lowering from rust and lifting into ruby.
|
||||
RT = Retourneur.new
|
||||
|
||||
def affirm_aller_retour(vals, fn_name)
|
||||
vals.each do |v|
|
||||
id_v = RT.public_send fn_name, v
|
||||
|
||||
assert_equal id_v, v, "Round-trip failure: #{v} => #{id_v}"
|
||||
end
|
||||
end
|
||||
|
||||
MIN_I8 = -1 * 2**7
|
||||
MAX_I8 = 2**7 - 1
|
||||
MIN_I16 = -1 * 2**15
|
||||
MAX_I16 = 2**15 - 1
|
||||
MIN_I32 = -1 * 2**31
|
||||
MAX_I32 = 2**31 - 1
|
||||
MIN_I64 = -1 * 2**31
|
||||
MAX_I64 = 2**31 - 1
|
||||
|
||||
# Ruby floats are always doubles, so won't round-trip through f32 correctly.
|
||||
# This truncates them appropriately.
|
||||
F32_ONE_THIRD = [1.0 / 3].pack('f').unpack('f')[0]
|
||||
|
||||
# Booleans
|
||||
affirm_aller_retour([true, false], :identique_boolean)
|
||||
|
||||
# Bytes.
|
||||
affirm_aller_retour([MIN_I8, -1, 0, 1, MAX_I8], :identique_i8)
|
||||
affirm_aller_retour([0x00, 0x12, 0xFF], :identique_u8)
|
||||
|
||||
# Shorts
|
||||
affirm_aller_retour([MIN_I16, -1, 0, 1, MAX_I16], :identique_i16)
|
||||
affirm_aller_retour([0x0000, 0x1234, 0xFFFF], :identique_u16)
|
||||
|
||||
# Ints
|
||||
affirm_aller_retour([MIN_I32, -1, 0, 1, MAX_I32], :identique_i32)
|
||||
affirm_aller_retour([0x00000000, 0x12345678, 0xFFFFFFFF], :identique_u32)
|
||||
|
||||
# Longs
|
||||
affirm_aller_retour([MIN_I64, -1, 0, 1, MAX_I64], :identique_i64)
|
||||
affirm_aller_retour([0x0000000000000000, 0x1234567890ABCDEF, 0xFFFFFFFFFFFFFFFF], :identique_u64)
|
||||
|
||||
# Floats
|
||||
affirm_aller_retour([0.0, 0.5, 0.25, 1.0, F32_ONE_THIRD], :identique_float)
|
||||
|
||||
# Doubles
|
||||
affirm_aller_retour(
|
||||
[0.0, 0.5, 0.25, 1.0, 1.0 / 3, Float::MAX, Float::MIN],
|
||||
:identique_double
|
||||
)
|
||||
|
||||
# Strings
|
||||
affirm_aller_retour(
|
||||
['', 'abc', 'été', 'ښي لاس ته لوستلو لوستل',
|
||||
'😻emoji 👨👧👦multi-emoji, 🇨🇭a flag, a canal, panama'],
|
||||
:identique_string
|
||||
)
|
||||
|
||||
# Test one way across the FFI.
|
||||
#
|
||||
# We send one representation of a value to lib.rs, and it transforms it into another, a string.
|
||||
# lib.rs sends the string back, and then we compare here in ruby.
|
||||
#
|
||||
# This shows that the values are transformed into strings the same way in both ruby and rust.
|
||||
# i.e. if we assume that the string return works (we test this assumption elsewhere)
|
||||
# we show that lowering from ruby and lifting into rust has values that both ruby and rust
|
||||
# both stringify in the same way. i.e. the same values.
|
||||
#
|
||||
# If we roundtripping proves the symmetry of our lowering/lifting from here to rust, and lowering/lifting from rust to here,
|
||||
# and this convinces us that lowering/lifting from here to rust is correct, then
|
||||
# together, we've shown the correctness of the return leg.
|
||||
ST = Stringifier.new
|
||||
|
||||
def affirm_enchaine(vals, fn_name)
|
||||
vals.each do |v|
|
||||
str_v = ST.public_send fn_name, v
|
||||
|
||||
assert_equal v.to_s, str_v, "String compare error #{v} => #{str_v}"
|
||||
end
|
||||
end
|
||||
|
||||
# Test the efficacy of the string transport from rust. If this fails, but everything else
|
||||
# works, then things are very weird.
|
||||
assert_equal ST.well_known_string('ruby'), 'uniffi 💚 ruby!'
|
||||
|
||||
# Booleans
|
||||
affirm_enchaine([true, false], :to_string_boolean)
|
||||
|
||||
# Bytes.
|
||||
affirm_enchaine([MIN_I8, -1, 0, 1, MAX_I8], :to_string_i8)
|
||||
affirm_enchaine([0x00, 0x12, 0xFF], :to_string_u8)
|
||||
|
||||
# Shorts
|
||||
affirm_enchaine([MIN_I16, -1, 0, 1, MAX_I16], :to_string_i16)
|
||||
affirm_enchaine([0x0000, 0x1234, 0xFFFF], :to_string_u16)
|
||||
|
||||
# Ints
|
||||
affirm_enchaine([MIN_I32, -1, 0, 1, MAX_I32], :to_string_i32)
|
||||
affirm_enchaine([0x00000000, 0x12345678, 0xFFFFFFFF], :to_string_u32)
|
||||
|
||||
# Longs
|
||||
affirm_enchaine([MIN_I64, -1, 0, 1, MAX_I64], :to_string_i64)
|
||||
affirm_enchaine([0x0000000000000000, 0x1234567890ABCDEF, 0xFFFFFFFFFFFFFFFF], :to_string_u64)
|
||||
|
|
@ -1,232 +0,0 @@
|
|||
import rondpoint
|
||||
|
||||
let dico = Dictionnaire(un: .deux, deux: false, petitNombre: 0, grosNombre: 123456789)
|
||||
let copyDico = copieDictionnaire(d: dico)
|
||||
assert(dico == copyDico)
|
||||
|
||||
assert(copieEnumeration(e: .deux) == .deux)
|
||||
assert(copieEnumerations(e: [.un, .deux]) == [.un, .deux])
|
||||
assert(copieCarte(c:
|
||||
["0": .zero,
|
||||
"1": .un(premier: 1),
|
||||
"2": .deux(premier: 2, second: "deux")
|
||||
]) == [
|
||||
"0": .zero,
|
||||
"1": .un(premier: 1),
|
||||
"2": .deux(premier: 2, second: "deux")
|
||||
])
|
||||
|
||||
assert(EnumerationAvecDonnees.zero != EnumerationAvecDonnees.un(premier: 1))
|
||||
assert(EnumerationAvecDonnees.un(premier: 1) == EnumerationAvecDonnees.un(premier: 1))
|
||||
assert(EnumerationAvecDonnees.un(premier: 1) != EnumerationAvecDonnees.un(premier: 2))
|
||||
|
||||
|
||||
assert(switcheroo(b: false))
|
||||
|
||||
// Test the roundtrip across the FFI.
|
||||
// This shows that the values we send come back in exactly the same state as we sent them.
|
||||
// i.e. it shows that lowering from swift and lifting into rust is symmetrical with
|
||||
// lowering from rust and lifting into swift.
|
||||
let rt = Retourneur()
|
||||
|
||||
// Booleans
|
||||
[true, false].affirmAllerRetour(rt.identiqueBoolean)
|
||||
|
||||
// Bytes.
|
||||
[.min, .max].affirmAllerRetour(rt.identiqueI8)
|
||||
[0x00, 0xFF].map { $0 as UInt8 }.affirmAllerRetour(rt.identiqueU8)
|
||||
|
||||
// Shorts
|
||||
[.min, .max].affirmAllerRetour(rt.identiqueI16)
|
||||
[0x0000, 0xFFFF].map { $0 as UInt16 }.affirmAllerRetour(rt.identiqueU16)
|
||||
|
||||
// Ints
|
||||
[0, 1, -1, .min, .max].affirmAllerRetour(rt.identiqueI32)
|
||||
[0x00000000, 0xFFFFFFFF].map { $0 as UInt32 }.affirmAllerRetour(rt.identiqueU32)
|
||||
|
||||
// Longs
|
||||
[.zero, 1, -1, .min, .max].affirmAllerRetour(rt.identiqueI64)
|
||||
[.zero, 1, .min, .max].affirmAllerRetour(rt.identiqueU64)
|
||||
|
||||
// Floats
|
||||
[.zero, 1, 0.25, .leastNonzeroMagnitude, .greatestFiniteMagnitude].affirmAllerRetour(rt.identiqueFloat)
|
||||
|
||||
// Doubles
|
||||
[0.0, 1.0, .leastNonzeroMagnitude, .greatestFiniteMagnitude].affirmAllerRetour(rt.identiqueDouble)
|
||||
|
||||
// Strings
|
||||
["", "abc", "null\0byte", "été", "ښي لاس ته لوستلو لوستل", "😻emoji 👨👧👦multi-emoji, 🇨🇭a flag, a canal, panama"]
|
||||
.affirmAllerRetour(rt.identiqueString)
|
||||
|
||||
// Test one way across the FFI.
|
||||
//
|
||||
// We send one representation of a value to lib.rs, and it transforms it into another, a string.
|
||||
// lib.rs sends the string back, and then we compare here in swift.
|
||||
//
|
||||
// This shows that the values are transformed into strings the same way in both swift and rust.
|
||||
// i.e. if we assume that the string return works (we test this assumption elsewhere)
|
||||
// we show that lowering from swift and lifting into rust has values that both swift and rust
|
||||
// both stringify in the same way. i.e. the same values.
|
||||
//
|
||||
// If we roundtripping proves the symmetry of our lowering/lifting from here to rust, and lowering/lifting from rust t here,
|
||||
// and this convinces us that lowering/lifting from here to rust is correct, then
|
||||
// together, we've shown the correctness of the return leg.
|
||||
let st = Stringifier()
|
||||
|
||||
// Test the effigacy of the string transport from rust. If this fails, but everything else
|
||||
// works, then things are very weird.
|
||||
let wellKnown = st.wellKnownString(value: "swift")
|
||||
assert("uniffi 💚 swift!" == wellKnown, "wellKnownString 'uniffi 💚 swift!' == '\(wellKnown)'")
|
||||
|
||||
// Booleans
|
||||
[true, false].affirmEnchaine(st.toStringBoolean)
|
||||
|
||||
// Bytes.
|
||||
[.min, .max].affirmEnchaine(st.toStringI8)
|
||||
[.min, .max].affirmEnchaine(st.toStringU8)
|
||||
|
||||
// Shorts
|
||||
[.min, .max].affirmEnchaine(st.toStringI16)
|
||||
[.min, .max].affirmEnchaine(st.toStringU16)
|
||||
|
||||
// Ints
|
||||
[0, 1, -1, .min, .max].affirmEnchaine(st.toStringI32)
|
||||
[0, 1, .min, .max].affirmEnchaine(st.toStringU32)
|
||||
|
||||
// Longs
|
||||
[.zero, 1, -1, .min, .max].affirmEnchaine(st.toStringI64)
|
||||
[.zero, 1, .min, .max].affirmEnchaine(st.toStringU64)
|
||||
|
||||
// Floats
|
||||
[.zero, 1, -1, .leastNonzeroMagnitude, .greatestFiniteMagnitude].affirmEnchaine(st.toStringFloat) { Float.init($0) == $1 }
|
||||
|
||||
// Doubles
|
||||
[.zero, 1, -1, .leastNonzeroMagnitude, .greatestFiniteMagnitude].affirmEnchaine(st.toStringDouble) { Double.init($0) == $1 }
|
||||
|
||||
// Some extension functions for testing the results of roundtripping and stringifying
|
||||
extension Array where Element: Equatable {
|
||||
static func defaultEquals(_ observed: String, expected: Element) -> Bool {
|
||||
let exp = "\(expected)"
|
||||
return observed == exp
|
||||
}
|
||||
|
||||
func affirmEnchaine(_ fn: (Element) -> String, equals: (String, Element) -> Bool = defaultEquals) {
|
||||
self.forEach { v in
|
||||
let obs = fn(v)
|
||||
assert(equals(obs, v), "toString_\(type(of:v))(\(v)): observed=\(obs), expected=\(v)")
|
||||
}
|
||||
}
|
||||
|
||||
func affirmAllerRetour(_ fn: (Element) -> Element) {
|
||||
self.forEach { v in
|
||||
assert(fn(v) == v, "identique_\(type(of:v))(\(v))")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Prove to ourselves that default arguments are being used.
|
||||
// Step 1: call the methods without arguments, and check against the UDL.
|
||||
let op = Optionneur()
|
||||
|
||||
assert(op.sinonString() == "default")
|
||||
|
||||
assert(op.sinonBoolean() == false)
|
||||
|
||||
assert(op.sinonSequence() == [])
|
||||
|
||||
// optionals
|
||||
assert(op.sinonNull() == nil)
|
||||
assert(op.sinonZero() == 0)
|
||||
|
||||
// decimal integers
|
||||
assert(op.sinonU8Dec() == UInt8(42))
|
||||
assert(op.sinonI8Dec() == Int8(-42))
|
||||
assert(op.sinonU16Dec() == UInt16(42))
|
||||
assert(op.sinonI16Dec() == Int16(42))
|
||||
assert(op.sinonU32Dec() == UInt32(42))
|
||||
assert(op.sinonI32Dec() == Int32(42))
|
||||
assert(op.sinonU64Dec() == UInt64(42))
|
||||
assert(op.sinonI64Dec() == Int64(42))
|
||||
|
||||
// hexadecimal integers
|
||||
assert(op.sinonU8Hex() == UInt8(0xff))
|
||||
assert(op.sinonI8Hex() == Int8(-0x7f))
|
||||
assert(op.sinonU16Hex() == UInt16(0xffff))
|
||||
assert(op.sinonI16Hex() == Int16(0x7f))
|
||||
assert(op.sinonU32Hex() == UInt32(0xffffffff))
|
||||
assert(op.sinonI32Hex() == Int32(0x7fffffff))
|
||||
assert(op.sinonU64Hex() == UInt64(0xffffffffffffffff))
|
||||
assert(op.sinonI64Hex() == Int64(0x7fffffffffffffff))
|
||||
|
||||
// octal integers
|
||||
assert(op.sinonU32Oct() == UInt32(0o755))
|
||||
|
||||
// floats
|
||||
assert(op.sinonF32() == 42.0)
|
||||
assert(op.sinonF64() == Double(42.1))
|
||||
|
||||
// enums
|
||||
assert(op.sinonEnum() == .trois)
|
||||
|
||||
// Step 2. Convince ourselves that if we pass something else, then that changes the output.
|
||||
// We have shown something coming out of the sinon methods, but without eyeballing the Rust
|
||||
// we can't be sure that the arguments will change the return value.
|
||||
["foo", "bar"].affirmAllerRetour(op.sinonString)
|
||||
[true, false].affirmAllerRetour(op.sinonBoolean)
|
||||
[["a", "b"], []].affirmAllerRetour(op.sinonSequence)
|
||||
|
||||
// optionals
|
||||
["0", "1"].affirmAllerRetour(op.sinonNull)
|
||||
[0, 1].affirmAllerRetour(op.sinonZero)
|
||||
|
||||
// integers
|
||||
[0, 1].affirmAllerRetour(op.sinonU8Dec)
|
||||
[0, 1].affirmAllerRetour(op.sinonI8Dec)
|
||||
[0, 1].affirmAllerRetour(op.sinonU16Dec)
|
||||
[0, 1].affirmAllerRetour(op.sinonI16Dec)
|
||||
[0, 1].affirmAllerRetour(op.sinonU32Dec)
|
||||
[0, 1].affirmAllerRetour(op.sinonI32Dec)
|
||||
[0, 1].affirmAllerRetour(op.sinonU64Dec)
|
||||
[0, 1].affirmAllerRetour(op.sinonI64Dec)
|
||||
|
||||
[0, 1].affirmAllerRetour(op.sinonU8Hex)
|
||||
[0, 1].affirmAllerRetour(op.sinonI8Hex)
|
||||
[0, 1].affirmAllerRetour(op.sinonU16Hex)
|
||||
[0, 1].affirmAllerRetour(op.sinonI16Hex)
|
||||
[0, 1].affirmAllerRetour(op.sinonU32Hex)
|
||||
[0, 1].affirmAllerRetour(op.sinonI32Hex)
|
||||
[0, 1].affirmAllerRetour(op.sinonU64Hex)
|
||||
[0, 1].affirmAllerRetour(op.sinonI64Hex)
|
||||
|
||||
[0, 1].affirmAllerRetour(op.sinonU32Oct)
|
||||
|
||||
// floats
|
||||
[0.0, 1.0].affirmAllerRetour(op.sinonF32)
|
||||
[0.0, 1.0].affirmAllerRetour(op.sinonF64)
|
||||
|
||||
// enums
|
||||
[.un, .deux, .trois].affirmAllerRetour(op.sinonEnum)
|
||||
|
||||
// Testing defaulting properties in record types.
|
||||
let defaultes = OptionneurDictionnaire()
|
||||
let explicite = OptionneurDictionnaire(
|
||||
i8Var: Int8(-8),
|
||||
u8Var: UInt8(8),
|
||||
i16Var: Int16(-16),
|
||||
u16Var: UInt16(0x10),
|
||||
i32Var: -32,
|
||||
u32Var: UInt32(32),
|
||||
i64Var: Int64(-64),
|
||||
u64Var: UInt64(64),
|
||||
floatVar: Float(4.0),
|
||||
doubleVar: Double(8.0),
|
||||
booleanVar: true,
|
||||
stringVar: "default",
|
||||
listVar: [],
|
||||
enumerationVar: .deux,
|
||||
dictionnaireVar: nil
|
||||
)
|
||||
|
||||
// …and makes sure they travel across and back the FFI.
|
||||
assert(defaultes == explicite)
|
||||
[defaultes].affirmAllerRetour(rt.identiqueOptionneurDictionnaire)
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
uniffi_macros::build_foreign_language_testcases!(
|
||||
["src/rondpoint.udl",],
|
||||
[
|
||||
"tests/bindings/test_rondpoint.kts",
|
||||
"tests/bindings/test_rondpoint.swift",
|
||||
"tests/bindings/test_rondpoint.py",
|
||||
"tests/bindings/test_rondpoint.rb",
|
||||
]
|
||||
);
|
||||
|
|
@ -1 +0,0 @@
|
|||
{"files":{"Cargo.toml":"b288fc6b1e909cffdb5171a247f268884a2483d9f97f1a24a679681fb418bd8d","build.rs":"d36e4ff477007611d216e60998d6d8a51b33895bb95159e3d7732e2b8cbc1783","src/lib.rs":"79ae1ea584942b25c108a26df79a781a63d66f8fb37c4dacfc04d180752effcb","src/sprites.udl":"bfd35f04ba0549301189dfb8fc45b0f39bad00956c324f33be0e845fb7ff78aa","tests/bindings/test_sprites.kts":"06ed115325f37ce59ed6f33e2d651cd2aa352fddcc644580f62a6da6ca075844","tests/bindings/test_sprites.py":"2e6ce838cfb387586257703c3500062438e840dd7ae57d185cdc244dc0745b8f","tests/bindings/test_sprites.rb":"6289a1833c7c8f4583ee4f0488d680de2ee46cfb203095a9b66d7234e2f07d53","tests/bindings/test_sprites.swift":"b2c0a6f4d5edfd7de7c2ba77b838865ffda153a6f364f273456175192d3e6e00","tests/test_generated_bindings.rs":"920c532011c8a6c20bdb1f39c50ef7a2803729a62a1bd425d81e40300958778a"},"package":null}
|
||||
|
|
@ -1,18 +0,0 @@
|
|||
[package]
|
||||
name = "uniffi-example-sprites"
|
||||
edition = "2021"
|
||||
version = "0.18.0"
|
||||
authors = ["Firefox Sync Team <sync-team@mozilla.com>"]
|
||||
license = "MPL-2.0"
|
||||
publish = false
|
||||
|
||||
[lib]
|
||||
crate-type = ["lib", "cdylib"]
|
||||
name = "uniffi_sprites"
|
||||
|
||||
[dependencies]
|
||||
uniffi_macros = {path = "../../uniffi_macros"}
|
||||
uniffi = {path = "../../uniffi", features=["builtin-bindgen"]}
|
||||
|
||||
[build-dependencies]
|
||||
uniffi_build = {path = "../../uniffi_build", features=["builtin-bindgen"]}
|
||||
|
|
@ -1,7 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
fn main() {
|
||||
uniffi_build::generate_scaffolding("./src/sprites.udl").unwrap();
|
||||
}
|
||||
|
|
@ -1,65 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use std::sync::RwLock;
|
||||
|
||||
// A point in two-dimensional space.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Point {
|
||||
x: f64,
|
||||
y: f64,
|
||||
}
|
||||
|
||||
// A magnitude and direction in two-dimensional space.
|
||||
// For simplicity we represent this as a point relative to the origin.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Vector {
|
||||
dx: f64,
|
||||
dy: f64,
|
||||
}
|
||||
|
||||
// Move from the given Point, according to the given Vector.
|
||||
pub fn translate(p: &Point, v: Vector) -> Point {
|
||||
Point {
|
||||
x: p.x + v.dx,
|
||||
y: p.y + v.dy,
|
||||
}
|
||||
}
|
||||
|
||||
// An entity in our imaginary world, which occupies a position in space
|
||||
// and which can move about over time.
|
||||
#[derive(Debug)]
|
||||
pub struct Sprite {
|
||||
// We must use interior mutability for managing mutable state, hence the `RwLock`.
|
||||
current_position: RwLock<Point>,
|
||||
}
|
||||
|
||||
impl Sprite {
|
||||
fn new(initial_position: Option<Point>) -> Sprite {
|
||||
Sprite {
|
||||
current_position: RwLock::new(initial_position.unwrap_or(Point { x: 0.0, y: 0.0 })),
|
||||
}
|
||||
}
|
||||
|
||||
fn new_relative_to(reference: Point, direction: Vector) -> Sprite {
|
||||
Sprite {
|
||||
current_position: RwLock::new(translate(&reference, direction)),
|
||||
}
|
||||
}
|
||||
|
||||
fn get_position(&self) -> Point {
|
||||
self.current_position.read().unwrap().clone()
|
||||
}
|
||||
|
||||
fn move_to(&self, position: Point) {
|
||||
*self.current_position.write().unwrap() = position;
|
||||
}
|
||||
|
||||
fn move_by(&self, direction: Vector) {
|
||||
let mut current_position = self.current_position.write().unwrap();
|
||||
*current_position = translate(&*current_position, direction)
|
||||
}
|
||||
}
|
||||
|
||||
include!(concat!(env!("OUT_DIR"), "/sprites.uniffi.rs"));
|
||||
|
|
@ -1,22 +0,0 @@
|
|||
|
||||
namespace sprites {
|
||||
Point translate([ByRef] Point position, Vector direction);
|
||||
};
|
||||
|
||||
dictionary Point {
|
||||
double x;
|
||||
double y;
|
||||
};
|
||||
|
||||
dictionary Vector {
|
||||
double dx;
|
||||
double dy;
|
||||
};
|
||||
|
||||
interface Sprite {
|
||||
constructor(Point? initial_position);
|
||||
[Name=new_relative_to] constructor(Point reference, Vector direction);
|
||||
Point get_position();
|
||||
void move_to(Point position);
|
||||
void move_by(Vector direction);
|
||||
};
|
||||
|
|
@ -1,25 +0,0 @@
|
|||
import uniffi.sprites.*;
|
||||
|
||||
val sempty = Sprite(null)
|
||||
assert( sempty.getPosition() == Point(0.0, 0.0) )
|
||||
|
||||
val s = Sprite(Point(0.0, 1.0))
|
||||
assert( s.getPosition() == Point(0.0, 1.0) )
|
||||
|
||||
s.moveTo(Point(1.0, 2.0))
|
||||
assert( s.getPosition() == Point(1.0, 2.0) )
|
||||
|
||||
s.moveBy(Vector(-4.0, 2.0))
|
||||
assert( s.getPosition() == Point(-3.0, 4.0) )
|
||||
|
||||
s.destroy()
|
||||
try {
|
||||
s.moveBy(Vector(0.0, 0.0))
|
||||
assert(false) { "Should not be able to call anything after `destroy`" }
|
||||
} catch(e: IllegalStateException) {
|
||||
assert(true)
|
||||
}
|
||||
|
||||
val srel = Sprite.newRelativeTo(Point(0.0, 1.0), Vector(1.0, 1.5))
|
||||
assert( srel.getPosition() == Point(1.0, 2.5) )
|
||||
|
||||
|
|
@ -1,17 +0,0 @@
|
|||
from sprites import *
|
||||
|
||||
sempty = Sprite(None)
|
||||
assert sempty.get_position() == Point(0, 0)
|
||||
|
||||
s = Sprite(Point(0, 1))
|
||||
assert s.get_position() == Point(0, 1)
|
||||
|
||||
s.move_to(Point(1, 2))
|
||||
assert s.get_position() == Point(1, 2)
|
||||
|
||||
s.move_by(Vector(-4, 2))
|
||||
assert s.get_position() == Point(-3, 4)
|
||||
|
||||
srel = Sprite.new_relative_to(Point(0, 1), Vector(1, 1.5))
|
||||
assert srel.get_position() == Point(1, 2.5)
|
||||
|
||||
|
|
@ -1,22 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'test/unit'
|
||||
require 'sprites'
|
||||
|
||||
include Test::Unit::Assertions
|
||||
include Sprites
|
||||
|
||||
sempty = Sprite.new(nil)
|
||||
assert_equal sempty.get_position, Point.new(0, 0)
|
||||
|
||||
s = Sprite.new(Point.new(0, 1))
|
||||
assert_equal s.get_position, Point.new(0, 1)
|
||||
|
||||
s.move_to(Point.new(1, 2))
|
||||
assert_equal s.get_position, Point.new(1, 2)
|
||||
|
||||
s.move_by(Vector.new(-4, 2))
|
||||
assert_equal s.get_position, Point.new(-3, 4)
|
||||
|
||||
srel = Sprite.new_relative_to(Point.new(0, 1), Vector.new(1, 1.5))
|
||||
assert_equal srel.get_position, Point.new(1, 2.5)
|
||||
|
|
@ -1,16 +0,0 @@
|
|||
import sprites
|
||||
|
||||
let sempty = Sprite(initialPosition: nil)
|
||||
assert( sempty.getPosition() == Point(x: 0, y: 0))
|
||||
|
||||
let s = Sprite(initialPosition: Point(x: 0, y: 1))
|
||||
assert( s.getPosition() == Point(x: 0, y: 1))
|
||||
|
||||
s.moveTo(position: Point(x: 1.0, y: 2.0))
|
||||
assert( s.getPosition() == Point(x: 1, y: 2))
|
||||
|
||||
s.moveBy(direction: Vector(dx: -4, dy: 2))
|
||||
assert( s.getPosition() == Point(x: -3, y: 4))
|
||||
|
||||
let srel = Sprite.newRelativeTo(reference: Point(x: 0.0, y: 1.0), direction: Vector(dx: 1, dy: 1.5))
|
||||
assert( srel.getPosition() == Point(x: 1.0, y: 2.5) )
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
uniffi_macros::build_foreign_language_testcases!(
|
||||
["src/sprites.udl",],
|
||||
[
|
||||
"tests/bindings/test_sprites.py",
|
||||
"tests/bindings/test_sprites.rb",
|
||||
"tests/bindings/test_sprites.kts",
|
||||
"tests/bindings/test_sprites.swift",
|
||||
]
|
||||
);
|
||||
|
|
@ -1 +0,0 @@
|
|||
{"files":{"Cargo.toml":"4f4fc40bccf4ca5b105ea2abdbcdc6758ba7271d7d4ceb1e8ed45e3de227c2a6","build.rs":"ca26833c671cfe14a8275c276c197ab228cb1639b34cae31bb3805221ecc1245","src/lib.rs":"6a38904924681aed26b74876ad0480fedf8e8b2640cd2b04531a55aba8fc5592","src/todolist.udl":"1f8a24049c2340b9184e95facfc191ecdcb91541729ae7f20b4625d67685f13c","tests/bindings/test_todolist.kts":"f3d29b48e0193563fc4f131d91ea697f758174dcdb80ea554f233949e575bf55","tests/bindings/test_todolist.py":"f7430af9347df0daa954d38bc2203ce400affbb9a53fced4bb67a6796afa0664","tests/bindings/test_todolist.rb":"6524b5271a9cc0e2d78ca9f86ccb6973889926688a0843b4505a4f62d48f6dcb","tests/bindings/test_todolist.swift":"d1911b85fe0c8c0b42e5421b5af5d7359c9a65bba477d23560eb4b0f52e80662","tests/test_generated_bindings.rs":"25108de454213659c3eacd643a24c49099757a6b6da501fdb50874f574bd30c5"},"package":null}
|
||||
|
|
@ -1,20 +0,0 @@
|
|||
[package]
|
||||
name = "uniffi-example-todolist"
|
||||
edition = "2021"
|
||||
version = "0.18.0"
|
||||
authors = ["Firefox Sync Team <sync-team@mozilla.com>"]
|
||||
license = "MPL-2.0"
|
||||
publish = false
|
||||
|
||||
[lib]
|
||||
crate-type = ["lib", "cdylib"]
|
||||
name = "uniffi_todolist"
|
||||
|
||||
[dependencies]
|
||||
uniffi_macros = {path = "../../uniffi_macros"}
|
||||
uniffi = {path = "../../uniffi", features=["builtin-bindgen"]}
|
||||
thiserror = "1.0"
|
||||
lazy_static = "1.4"
|
||||
|
||||
[build-dependencies]
|
||||
uniffi_build = {path = "../../uniffi_build", features=["builtin-bindgen"]}
|
||||
|
|
@ -1,7 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
fn main() {
|
||||
uniffi_build::generate_scaffolding("./src/todolist.udl").unwrap();
|
||||
}
|
||||
150
third_party/rust/uniffi-example-todolist/src/lib.rs
vendored
150
third_party/rust/uniffi-example-todolist/src/lib.rs
vendored
|
|
@ -1,150 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use std::sync::{Arc, RwLock};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct TodoEntry {
|
||||
text: String,
|
||||
}
|
||||
|
||||
lazy_static::lazy_static! {
|
||||
// There is a single "default" TodoList that can be shared
|
||||
// by all consumers of this component. Depending on requirements,
|
||||
// a real app might like to use a `Weak<>` rather than an `Arc<>`
|
||||
// here to reduce the risk of circular references.
|
||||
static ref DEFAULT_LIST: RwLock<Option<Arc<TodoList>>> = RwLock::new(None);
|
||||
}
|
||||
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum TodoError {
|
||||
#[error("The todo does not exist!")]
|
||||
TodoDoesNotExist,
|
||||
#[error("The todolist is empty!")]
|
||||
EmptyTodoList,
|
||||
#[error("That todo already exists!")]
|
||||
DuplicateTodo,
|
||||
#[error("Empty String error!: {0}")]
|
||||
EmptyString(String),
|
||||
#[error("I am a delegated Error: {0}")]
|
||||
DeligatedError(#[from] std::io::Error),
|
||||
}
|
||||
|
||||
/// Get a reference to the global default TodoList, if set.
|
||||
///
|
||||
fn get_default_list() -> Option<Arc<TodoList>> {
|
||||
DEFAULT_LIST.read().unwrap().clone()
|
||||
}
|
||||
|
||||
/// Set the global default TodoList.
|
||||
///
|
||||
/// This will silently drop any previously set value.
|
||||
///
|
||||
fn set_default_list(list: Arc<TodoList>) {
|
||||
*DEFAULT_LIST.write().unwrap() = Some(list);
|
||||
}
|
||||
|
||||
/// Create a new TodoEntry from the given string.
|
||||
///
|
||||
fn create_entry_with<S: Into<String>>(item: S) -> Result<TodoEntry> {
|
||||
let text = item.into();
|
||||
if text.is_empty() {
|
||||
return Err(TodoError::EmptyString(
|
||||
"Cannot add empty string as entry".to_string(),
|
||||
));
|
||||
}
|
||||
Ok(TodoEntry { text })
|
||||
}
|
||||
|
||||
type Result<T, E = TodoError> = std::result::Result<T, E>;
|
||||
|
||||
// A simple Todolist.
|
||||
// UniFFI requires that we use interior mutability for managing mutable state, so we wrap our `Vec` in a RwLock.
|
||||
// (A Mutex would also work, but a RwLock is more appropriate for this use-case, so we use it).
|
||||
#[derive(Debug)]
|
||||
pub struct TodoList {
|
||||
items: RwLock<Vec<String>>,
|
||||
}
|
||||
|
||||
impl TodoList {
|
||||
fn new() -> Self {
|
||||
Self {
|
||||
items: RwLock::new(Vec::new()),
|
||||
}
|
||||
}
|
||||
|
||||
fn add_item<S: Into<String>>(&self, item: S) -> Result<()> {
|
||||
let item = item.into();
|
||||
if item.is_empty() {
|
||||
return Err(TodoError::EmptyString(
|
||||
"Cannot add empty string as item".to_string(),
|
||||
));
|
||||
}
|
||||
let mut items = self.items.write().unwrap();
|
||||
if items.contains(&item) {
|
||||
return Err(TodoError::DuplicateTodo);
|
||||
}
|
||||
items.push(item);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn get_last(&self) -> Result<String> {
|
||||
let items = self.items.read().unwrap();
|
||||
items.last().cloned().ok_or(TodoError::EmptyTodoList)
|
||||
}
|
||||
|
||||
fn get_first(&self) -> Result<String> {
|
||||
let items = self.items.read().unwrap();
|
||||
items.first().cloned().ok_or(TodoError::EmptyTodoList)
|
||||
}
|
||||
|
||||
fn add_entries(&self, entries: Vec<TodoEntry>) {
|
||||
let mut items = self.items.write().unwrap();
|
||||
items.extend(entries.into_iter().map(|e| e.text))
|
||||
}
|
||||
|
||||
fn add_entry(&self, entry: TodoEntry) -> Result<()> {
|
||||
self.add_item(entry.text)
|
||||
}
|
||||
|
||||
fn add_items<S: Into<String>>(&self, items: Vec<S>) {
|
||||
let mut my_items = self.items.write().unwrap();
|
||||
my_items.extend(items.into_iter().map(Into::into))
|
||||
}
|
||||
|
||||
fn get_items(&self) -> Vec<String> {
|
||||
let items = self.items.read().unwrap();
|
||||
items.clone()
|
||||
}
|
||||
|
||||
fn get_entries(&self) -> Vec<TodoEntry> {
|
||||
let items = self.items.read().unwrap();
|
||||
items
|
||||
.iter()
|
||||
.map(|text| TodoEntry { text: text.clone() })
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn get_last_entry(&self) -> Result<TodoEntry> {
|
||||
let text = self.get_last()?;
|
||||
Ok(TodoEntry { text })
|
||||
}
|
||||
|
||||
fn clear_item<S: Into<String>>(&self, item: S) -> Result<()> {
|
||||
let item = item.into();
|
||||
let mut items = self.items.write().unwrap();
|
||||
let idx = items
|
||||
.iter()
|
||||
.position(|s| s == &item)
|
||||
.ok_or(TodoError::TodoDoesNotExist)?;
|
||||
items.remove(idx);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn make_default(self: Arc<Self>) {
|
||||
set_default_list(self);
|
||||
}
|
||||
}
|
||||
|
||||
include!(concat!(env!("OUT_DIR"), "/todolist.uniffi.rs"));
|
||||
|
|
@ -1,38 +0,0 @@
|
|||
namespace todolist {
|
||||
TodoList? get_default_list();
|
||||
undefined set_default_list(TodoList list);
|
||||
|
||||
[Throws=TodoError]
|
||||
TodoEntry create_entry_with(string todo);
|
||||
};
|
||||
|
||||
dictionary TodoEntry {
|
||||
string text;
|
||||
};
|
||||
|
||||
[Error]
|
||||
enum TodoError {
|
||||
"TodoDoesNotExist", "EmptyTodoList", "DuplicateTodo", "EmptyString", "DeligatedError"
|
||||
};
|
||||
|
||||
interface TodoList {
|
||||
constructor();
|
||||
[Throws=TodoError]
|
||||
void add_item(string todo);
|
||||
[Throws=TodoError]
|
||||
void add_entry(TodoEntry entry);
|
||||
sequence<TodoEntry> get_entries();
|
||||
sequence<string> get_items();
|
||||
void add_entries(sequence<TodoEntry> entries);
|
||||
void add_items(sequence<string> items);
|
||||
[Throws=TodoError]
|
||||
TodoEntry get_last_entry();
|
||||
[Throws=TodoError]
|
||||
string get_last();
|
||||
[Throws=TodoError]
|
||||
string get_first();
|
||||
[Throws=TodoError]
|
||||
void clear_item(string todo);
|
||||
[Self=ByArc]
|
||||
undefined make_default();
|
||||
};
|
||||
|
|
@ -1,83 +0,0 @@
|
|||
import uniffi.todolist.*
|
||||
|
||||
val todo = TodoList()
|
||||
|
||||
// This throws an exception:
|
||||
try {
|
||||
todo.getLast()
|
||||
throw RuntimeException("Should have thrown a TodoError!")
|
||||
} catch (e: TodoException.EmptyTodoList) {
|
||||
// It's okay, we don't have any items yet!
|
||||
}
|
||||
|
||||
try {
|
||||
createEntryWith("")
|
||||
throw RuntimeException("Should have thrown a TodoError!")
|
||||
} catch (e: TodoException) {
|
||||
// It's okay, the string was empty!
|
||||
assert(e is TodoException.EmptyString)
|
||||
assert(e !is TodoException.EmptyTodoList)
|
||||
}
|
||||
|
||||
todo.addItem("Write strings support")
|
||||
|
||||
assert(todo.getLast() == "Write strings support")
|
||||
|
||||
todo.addItem("Write tests for strings support")
|
||||
|
||||
assert(todo.getLast() == "Write tests for strings support")
|
||||
|
||||
val entry = createEntryWith("Write bindings for strings as record members")
|
||||
|
||||
todo.addEntry(entry)
|
||||
assert(todo.getLast() == "Write bindings for strings as record members")
|
||||
assert(todo.getLastEntry().text == "Write bindings for strings as record members")
|
||||
|
||||
todo.addItem("Test Ünicode hàndling without an entry can't believe I didn't test this at first 🤣")
|
||||
assert(todo.getLast() == "Test Ünicode hàndling without an entry can't believe I didn't test this at first 🤣")
|
||||
|
||||
val entry2 = TodoEntry("Test Ünicode hàndling in an entry can't believe I didn't test this at first 🤣")
|
||||
todo.addEntry(entry2)
|
||||
assert(todo.getLastEntry().text == "Test Ünicode hàndling in an entry can't believe I didn't test this at first 🤣")
|
||||
|
||||
assert(todo.getEntries().size == 5)
|
||||
|
||||
todo.addEntries(listOf(TodoEntry("foo"), TodoEntry("bar")))
|
||||
assert(todo.getEntries().size == 7)
|
||||
assert(todo.getLastEntry().text == "bar")
|
||||
|
||||
todo.addItems(listOf("bobo", "fofo"))
|
||||
assert(todo.getItems().size == 9)
|
||||
assert(todo.getItems()[7] == "bobo")
|
||||
|
||||
assert(getDefaultList() == null)
|
||||
|
||||
// Note that each individual object instance needs to be explicitly destroyed,
|
||||
// either by using the `.use` helper or explicitly calling its `.destroy` method.
|
||||
// Failure to do so will leak the underlying Rust object.
|
||||
TodoList().use { todo2 ->
|
||||
setDefaultList(todo)
|
||||
getDefaultList()!!.use { default ->
|
||||
assert(todo.getEntries() == default.getEntries())
|
||||
assert(todo2.getEntries() != default.getEntries())
|
||||
}
|
||||
|
||||
todo2.makeDefault()
|
||||
getDefaultList()!!.use { default ->
|
||||
assert(todo.getEntries() != default.getEntries())
|
||||
assert(todo2.getEntries() == default.getEntries())
|
||||
}
|
||||
|
||||
todo.addItem("Test liveness after being demoted from default")
|
||||
assert(todo.getLast() == "Test liveness after being demoted from default")
|
||||
|
||||
todo2.addItem("Test shared state through local vs default reference")
|
||||
getDefaultList()!!.use { default ->
|
||||
assert(default.getLast() == "Test shared state through local vs default reference")
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure the kotlin version of deinit doesn't crash, and is idempotent.
|
||||
todo.destroy()
|
||||
todo.destroy()
|
||||
|
||||
|
|
@ -1,44 +0,0 @@
|
|||
from todolist import *
|
||||
|
||||
todo = TodoList()
|
||||
|
||||
entry = TodoEntry("Write bindings for strings in records")
|
||||
|
||||
todo.add_item("Write python bindings")
|
||||
|
||||
assert(todo.get_last() == "Write python bindings")
|
||||
|
||||
todo.add_item("Write tests for bindings")
|
||||
|
||||
assert(todo.get_last() == "Write tests for bindings")
|
||||
|
||||
todo.add_entry(entry)
|
||||
|
||||
assert(todo.get_last() == "Write bindings for strings in records")
|
||||
assert(todo.get_last_entry().text == "Write bindings for strings in records")
|
||||
|
||||
todo.add_item("Test Ünicode hàndling without an entry can't believe I didn't test this at first 🤣")
|
||||
assert(todo.get_last() == "Test Ünicode hàndling without an entry can't believe I didn't test this at first 🤣")
|
||||
|
||||
entry2 = TodoEntry("Test Ünicode hàndling in an entry can't believe I didn't test this at first 🤣")
|
||||
todo.add_entry(entry2)
|
||||
assert(todo.get_last_entry().text == "Test Ünicode hàndling in an entry can't believe I didn't test this at first 🤣")
|
||||
|
||||
todo2 = TodoList()
|
||||
assert(todo != todo2)
|
||||
assert(todo is not todo2)
|
||||
|
||||
assert(get_default_list() is None)
|
||||
|
||||
set_default_list(todo)
|
||||
assert(todo.get_items() == get_default_list().get_items())
|
||||
|
||||
todo2.make_default()
|
||||
assert(todo2.get_items() == get_default_list().get_items())
|
||||
|
||||
todo.add_item("Test liveness after being demoted from default")
|
||||
assert(todo.get_last() == "Test liveness after being demoted from default")
|
||||
|
||||
todo2.add_item("Test shared state through local vs default reference")
|
||||
assert(get_default_list().get_last() == "Test shared state through local vs default reference")
|
||||
|
||||
|
|
@ -1,47 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'test/unit'
|
||||
require 'todolist'
|
||||
|
||||
include Test::Unit::Assertions
|
||||
include Todolist
|
||||
|
||||
todo = TodoList.new
|
||||
entry = TodoEntry.new 'Write bindings for strings in records'
|
||||
|
||||
todo.add_item('Write ruby bindings')
|
||||
|
||||
assert_equal todo.get_last, 'Write ruby bindings'
|
||||
|
||||
todo.add_item('Write tests for bindings')
|
||||
|
||||
assert_equal todo.get_last, 'Write tests for bindings'
|
||||
|
||||
todo.add_entry(entry)
|
||||
|
||||
assert_equal todo.get_last, 'Write bindings for strings in records'
|
||||
assert_equal todo.get_last_entry.text, 'Write bindings for strings in records'
|
||||
|
||||
todo.add_item("Test Ünicode hàndling without an entry can't believe I didn't test this at first 🤣")
|
||||
assert_equal todo.get_last, "Test Ünicode hàndling without an entry can't believe I didn't test this at first 🤣"
|
||||
|
||||
entry2 = TodoEntry.new("Test Ünicode hàndling in an entry can't believe I didn't test this at first 🤣")
|
||||
todo.add_entry(entry2)
|
||||
assert_equal todo.get_last_entry.text, "Test Ünicode hàndling in an entry can't believe I didn't test this at first 🤣"
|
||||
|
||||
todo2 = TodoList.new
|
||||
assert todo2.get_items != todo.get_items
|
||||
|
||||
assert Todolist.get_default_list == nil
|
||||
|
||||
Todolist.set_default_list todo
|
||||
assert todo.get_items == Todolist.get_default_list.get_items
|
||||
|
||||
todo2.make_default
|
||||
assert todo2.get_items == Todolist.get_default_list.get_items
|
||||
|
||||
todo.add_item "Test liveness after being demoted from default"
|
||||
assert todo.get_last == "Test liveness after being demoted from default"
|
||||
|
||||
todo2.add_item "Test shared state through local vs default reference"
|
||||
assert Todolist.get_default_list.get_last == "Test shared state through local vs default reference"
|
||||
|
|
@ -1,69 +0,0 @@
|
|||
import todolist
|
||||
|
||||
|
||||
let todo = TodoList()
|
||||
do {
|
||||
let _ = try todo.getLast()
|
||||
fatalError("Should have thrown an EmptyTodoList error!")
|
||||
} catch TodoError.EmptyTodoList{
|
||||
//It's okay! There are not todos!
|
||||
}
|
||||
try! todo.addItem(todo: "Write swift bindings")
|
||||
assert( try! todo.getLast() == "Write swift bindings")
|
||||
|
||||
try! todo.addItem(todo: "Write tests for bindings")
|
||||
assert(try! todo.getLast() == "Write tests for bindings")
|
||||
|
||||
let entry = TodoEntry(text: "Write bindings for strings as record members")
|
||||
try! todo.addEntry(entry: entry)
|
||||
assert(try! todo.getLast() == "Write bindings for strings as record members")
|
||||
|
||||
try! todo.addItem(todo: "Test Ünicode hàndling without an entry can't believe I didn't test this at first 🤣")
|
||||
assert(try! todo.getLast() == "Test Ünicode hàndling without an entry can't believe I didn't test this at first 🤣")
|
||||
|
||||
do {
|
||||
let _ = try createEntryWith(todo: "")
|
||||
fatalError("Should have thrown an EmptyString error!")
|
||||
} catch TodoError.EmptyString {
|
||||
// It's okay! It was an empty string
|
||||
}
|
||||
|
||||
let entry2 = TodoEntry(text: "Test Ünicode hàndling in an entry can't believe I didn't test this at first 🤣")
|
||||
try! todo.addEntry(entry: entry2)
|
||||
assert(try! todo.getLastEntry() == entry2)
|
||||
|
||||
assert(todo.getEntries().count == 5)
|
||||
|
||||
todo.addEntries(entries: [TodoEntry(text: "foo"), TodoEntry(text: "bar")])
|
||||
assert(todo.getEntries().count == 7)
|
||||
assert(todo.getItems().count == 7)
|
||||
assert(try! todo.getLast() == "bar")
|
||||
|
||||
todo.addItems(items: ["bobo", "fofo"])
|
||||
assert(todo.getItems().count == 9)
|
||||
assert(todo.getItems()[7] == "bobo")
|
||||
|
||||
// Ensure deinit doesn't crash.
|
||||
for _ in 0..<10 {
|
||||
let list = TodoList()
|
||||
try! list.addItem(todo: "todo")
|
||||
}
|
||||
|
||||
let todo2 = TodoList()
|
||||
|
||||
assert(getDefaultList() == nil)
|
||||
|
||||
setDefaultList(list: todo)
|
||||
assert(todo.getItems() == getDefaultList()!.getItems())
|
||||
assert(todo2.getItems() != getDefaultList()!.getItems())
|
||||
|
||||
todo2.makeDefault()
|
||||
assert(todo.getItems() != getDefaultList()!.getItems())
|
||||
assert(todo2.getItems() == getDefaultList()!.getItems())
|
||||
|
||||
try! todo.addItem(todo: "Test liveness after being demoted from default")
|
||||
assert(try! todo.getLast() == "Test liveness after being demoted from default")
|
||||
|
||||
try! todo2.addItem(todo: "Test shared state through local vs default reference")
|
||||
assert(try! getDefaultList()!.getLast() == "Test shared state through local vs default reference")
|
||||
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
uniffi_macros::build_foreign_language_testcases!(
|
||||
["src/todolist.udl",],
|
||||
[
|
||||
"tests/bindings/test_todolist.kts",
|
||||
"tests/bindings/test_todolist.swift",
|
||||
"tests/bindings/test_todolist.rb",
|
||||
"tests/bindings/test_todolist.py"
|
||||
]
|
||||
);
|
||||
|
|
@ -75,7 +75,6 @@ DIRS += [
|
|||
"timermanager",
|
||||
"tooltiptext",
|
||||
"typeaheadfind",
|
||||
"uniffi-js",
|
||||
"utils",
|
||||
"url-classifier",
|
||||
"urlformatter",
|
||||
|
|
@ -143,6 +142,3 @@ if CONFIG["COMPILE_ENVIRONMENT"]:
|
|||
EXPORTS.mozilla += [
|
||||
"!regex_ffi_generated.h",
|
||||
]
|
||||
|
||||
if CONFIG["MOZ_UNIFFI_FIXTURES"]:
|
||||
DIRS += ["uniffi-bindgen-gecko-js/fixtures"]
|
||||
|
|
|
|||
|
|
@ -1,19 +0,0 @@
|
|||
[package]
|
||||
name = "uniffi-bindgen-gecko-js"
|
||||
version = "0.1.0"
|
||||
edition = "2018"
|
||||
|
||||
[[bin]]
|
||||
name = "uniffi-bindgen-gecko-js"
|
||||
path = "src/main.rs"
|
||||
|
||||
[dependencies]
|
||||
anyhow = "1"
|
||||
askama = { version = "0.11", default-features = false, features = ["config"] }
|
||||
clap = { version = "3.1", features = ["std", "derive"] }
|
||||
extend = "1.1"
|
||||
heck = "0.4"
|
||||
uniffi_bindgen = "0.19"
|
||||
serde = "1"
|
||||
toml = "0.5"
|
||||
camino = "1.0.8"
|
||||
|
|
@ -1,2 +0,0 @@
|
|||
[general]
|
||||
dirs = ["src/templates"]
|
||||
|
|
@ -1,36 +0,0 @@
|
|||
This directory contains generated code for the UniFFI examples/fixtures and JS
|
||||
unit tests for it.
|
||||
|
||||
This is only built if the `--enable-uniffi-fixtures` flag is present in
|
||||
`mozconfig`. There's no benefit to including this in a release build.
|
||||
|
||||
To add additional examples/fixtures:
|
||||
- For most of these steps, find the code for existing fixtures and use it as a template for the new code.
|
||||
- Edit `toolkit/components/uniffi-bindgen-gecko-js/mach_commands.py`
|
||||
- Add an entry to `FIXTURE_UDL_FILES`
|
||||
- Edit `toolkit/library/rust/shared/Cargo.toml`
|
||||
- Add an optional dependency for the fixture.
|
||||
- Add the feature to the list of features enabled by `uniffi_fixtures`.
|
||||
- Edit `toolkit/library/rust/shared/lib.rs`:
|
||||
- Add an `extern crate [name]` to the `uniffi_fixtures` mod
|
||||
- Note: [name] is the name from the `[lib]` section in the Cargo.toml
|
||||
for the example/fixture crate. This does not always match the package
|
||||
name for the crate.
|
||||
- Add `[name]::reexport_uniffi_scaffolding` to the `uniffi_fixtures` mod
|
||||
- Edit `toolkit/components/uniffi-bindgen-gecko-js/fixtures/moz.build` and add the fixture name to the `components`
|
||||
list.
|
||||
- Add a test module to the `toolkit/components/uniffi-bindgen-gecko-js/fixtures/tests/` directory and an entry for it
|
||||
in `toolkit/components/uniffi-bindgen-gecko-js/fixtures/tests/xpcshell.ini`
|
||||
- Run `mach vendor rust` to vendor in the Rust code.
|
||||
- Run `mach uniffi generate` to generate the scaffolding code.
|
||||
- Check in any new files
|
||||
|
||||
To run the tests:
|
||||
- Make sure you have a `mozconfig` file containing the line `ac_add_options --enable-uniffi-fixtures`
|
||||
- Run `mach uniffi generate` if:
|
||||
- You've added or updated a fixture
|
||||
- You've made changes to `uniffi-bindgen-gecko-js`
|
||||
- Run `mach build`
|
||||
- Run `mach xpcshell-test toolkit/components/uniffi-bindgen-gecko-js/fixtures/tests/`
|
||||
- You can also use a path to specific test file
|
||||
- For subsequent runs, if you only modify the test files, then you can re-run this step directly
|
||||
|
|
@ -1,401 +0,0 @@
|
|||
// This file was autogenerated by the `uniffi-bindgen-gecko-js` crate.
|
||||
// Trust me, you don't want to mess with it!
|
||||
|
||||
|
||||
|
||||
"use strict";
|
||||
|
||||
var EXPORTED_SYMBOLS = [];
|
||||
|
||||
// Write/Read data to/from an ArrayBuffer
|
||||
class ArrayBufferDataStream {
|
||||
constructor(arrayBuffer) {
|
||||
this.dataView = new DataView(arrayBuffer);
|
||||
this.pos = 0;
|
||||
}
|
||||
|
||||
readUint8() {
|
||||
let rv = this.dataView.getUint8(this.pos);
|
||||
this.pos += 1;
|
||||
return rv;
|
||||
}
|
||||
|
||||
writeUint8(value) {
|
||||
this.dataView.setUint8(this.pos, value);
|
||||
this.pos += 1;
|
||||
}
|
||||
|
||||
readUint16() {
|
||||
let rv = this.dataView.getUint16(this.pos);
|
||||
this.pos += 2;
|
||||
return rv;
|
||||
}
|
||||
|
||||
writeUint16(value) {
|
||||
this.dataView.setUint16(this.pos, value);
|
||||
this.pos += 2;
|
||||
}
|
||||
|
||||
readUint32() {
|
||||
let rv = this.dataView.getUint32(this.pos);
|
||||
this.pos += 4;
|
||||
return rv;
|
||||
}
|
||||
|
||||
writeUint32(value) {
|
||||
this.dataView.setUint32(this.pos, value);
|
||||
this.pos += 4;
|
||||
}
|
||||
|
||||
readUint64() {
|
||||
let rv = this.dataView.getBigUint64(this.pos);
|
||||
this.pos += 8;
|
||||
return Number(rv);
|
||||
}
|
||||
|
||||
writeUint64(value) {
|
||||
this.dataView.setBigUint64(this.pos, BigInt(value));
|
||||
this.pos += 8;
|
||||
}
|
||||
|
||||
|
||||
readInt8() {
|
||||
let rv = this.dataView.getInt8(this.pos);
|
||||
this.pos += 1;
|
||||
return rv;
|
||||
}
|
||||
|
||||
writeInt8(value) {
|
||||
this.dataView.setInt8(this.pos, value);
|
||||
this.pos += 1;
|
||||
}
|
||||
|
||||
readInt16() {
|
||||
let rv = this.dataView.getInt16(this.pos);
|
||||
this.pos += 2;
|
||||
return rv;
|
||||
}
|
||||
|
||||
writeInt16(value) {
|
||||
this.dataView.setInt16(this.pos, value);
|
||||
this.pos += 2;
|
||||
}
|
||||
|
||||
readInt32() {
|
||||
let rv = this.dataView.getInt32(this.pos);
|
||||
this.pos += 4;
|
||||
return rv;
|
||||
}
|
||||
|
||||
writeInt32(value) {
|
||||
this.dataView.setInt32(this.pos, value);
|
||||
this.pos += 4;
|
||||
}
|
||||
|
||||
readInt64() {
|
||||
let rv = this.dataView.getBigInt64(this.pos);
|
||||
this.pos += 8;
|
||||
return Number(rv);
|
||||
}
|
||||
|
||||
writeInt64(value) {
|
||||
this.dataView.setBigInt64(this.pos, BigInt(value));
|
||||
this.pos += 8;
|
||||
}
|
||||
|
||||
|
||||
readFloat32() {
|
||||
let rv = this.dataView.getFloat32(this.pos);
|
||||
this.pos += 4;
|
||||
return rv;
|
||||
}
|
||||
|
||||
writeFloat32(value) {
|
||||
this.dataView.setFloat32(this.pos, value);
|
||||
this.pos += 4;
|
||||
}
|
||||
|
||||
readFloat64() {
|
||||
let rv = this.dataView.getFloat64(this.pos);
|
||||
this.pos += 8;
|
||||
return rv;
|
||||
}
|
||||
|
||||
writeFloat64(value) {
|
||||
this.dataView.setFloat64(this.pos, value);
|
||||
this.pos += 8;
|
||||
}
|
||||
|
||||
|
||||
writeString(value) {
|
||||
const encoder = new TextEncoder();
|
||||
// Note: in order to efficiently write this data, we first write the
|
||||
// string data, reserving 4 bytes for the size.
|
||||
const dest = new Uint8Array(this.dataView.buffer, this.pos + 4);
|
||||
const encodeResult = encoder.encodeInto(value, dest);
|
||||
if (encodeResult.read != value.length) {
|
||||
throw new UniFFIError(
|
||||
"writeString: out of space when writing to ArrayBuffer. Did the computeSize() method returned the wrong result?"
|
||||
);
|
||||
}
|
||||
const size = encodeResult.written;
|
||||
// Next, go back and write the size before the string data
|
||||
this.dataView.setUint32(this.pos, size);
|
||||
// Finally, advance our position past both the size and string data
|
||||
this.pos += size + 4;
|
||||
}
|
||||
|
||||
readString() {
|
||||
const decoder = new TextDecoder();
|
||||
const size = this.readUint32();
|
||||
const source = new Uint8Array(this.dataView.buffer, this.pos, size)
|
||||
const value = decoder.decode(source);
|
||||
this.pos += size;
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
function handleRustResult(result, liftCallback, liftErrCallback) {
|
||||
switch (result.code) {
|
||||
case "success":
|
||||
return liftCallback(result.data);
|
||||
|
||||
case "error":
|
||||
throw liftErrCallback(result.data);
|
||||
|
||||
case "internal-error":
|
||||
let message = result.internalErrorMessage;
|
||||
if (message) {
|
||||
throw new UniFFIInternalError(message);
|
||||
} else {
|
||||
throw new UniFFIInternalError("Unknown error");
|
||||
}
|
||||
|
||||
default:
|
||||
throw new UniFFIError(`Unexpected status code: ${result.code}`);
|
||||
}
|
||||
}
|
||||
|
||||
class UniFFIError {
|
||||
constructor(message) {
|
||||
this.message = message;
|
||||
}
|
||||
}
|
||||
|
||||
class UniFFIInternalError extends UniFFIError {}
|
||||
|
||||
// Base class for FFI converters
|
||||
class FfiConverter {
|
||||
static checkType(name, value) {
|
||||
if (value === undefined ) {
|
||||
throw TypeError(`${name} is undefined`);
|
||||
}
|
||||
if (value === null ) {
|
||||
throw TypeError(`${name} is null`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Base class for FFI converters that lift/lower by reading/writing to an ArrayBuffer
|
||||
class FfiConverterArrayBuffer extends FfiConverter {
|
||||
static lift(buf) {
|
||||
return this.read(new ArrayBufferDataStream(buf));
|
||||
}
|
||||
|
||||
static lower(value) {
|
||||
const buf = new ArrayBuffer(this.computeSize(value));
|
||||
const dataStream = new ArrayBufferDataStream(buf);
|
||||
this.write(dataStream, value);
|
||||
return buf;
|
||||
}
|
||||
}
|
||||
|
||||
// Symbols that are used to ensure that Object constructors
|
||||
// can only be used with a proper UniFFI pointer
|
||||
const uniffiObjectPtr = Symbol("uniffiObjectPtr");
|
||||
const constructUniffiObject = Symbol("constructUniffiObject");
|
||||
|
||||
class FfiConverterU64 extends FfiConverter {
|
||||
static checkType(name, value) {
|
||||
super.checkType(name, value);
|
||||
if (!Number.isSafeInteger(value)) {
|
||||
throw TypeError(`${name} exceeds the safe integer bounds (${value})`);
|
||||
}
|
||||
if (value < 0) {
|
||||
throw TypeError(`${name} exceeds the U64 bounds (${value})`);
|
||||
}
|
||||
}
|
||||
static computeSize() {
|
||||
return 8;
|
||||
}
|
||||
static lift(value) {
|
||||
return value;
|
||||
}
|
||||
static lower(value) {
|
||||
return value;
|
||||
}
|
||||
static write(dataStream, value) {
|
||||
dataStream.writeUint64(value)
|
||||
}
|
||||
static read(dataStream) {
|
||||
return dataStream.readUint64()
|
||||
}
|
||||
}class FfiConverterBool extends FfiConverter {
|
||||
static computeSize() {
|
||||
return 1;
|
||||
}
|
||||
static lift(value) {
|
||||
return value == 1;
|
||||
}
|
||||
static lower(value) {
|
||||
if (value) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
static write(dataStream, value) {
|
||||
dataStream.writeUint8(this.lower(value))
|
||||
}
|
||||
static read(dataStream) {
|
||||
return this.lift(dataStream.readUint8())
|
||||
}
|
||||
}
|
||||
|
||||
class FfiConverterString extends FfiConverter {
|
||||
static lift(buf) {
|
||||
const decoder = new TextDecoder();
|
||||
const utf8Arr = new Uint8Array(buf);
|
||||
return decoder.decode(utf8Arr);
|
||||
}
|
||||
static lower(value) {
|
||||
const encoder = new TextEncoder();
|
||||
return encoder.encode(value).buffer;
|
||||
}
|
||||
|
||||
static write(dataStream, value) {
|
||||
dataStream.writeString(value);
|
||||
}
|
||||
|
||||
static read(dataStream) {
|
||||
return dataStream.readString();
|
||||
}
|
||||
|
||||
static computeSize(value) {
|
||||
const encoder = new TextEncoder();
|
||||
return 4 + encoder.encode(value).length
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class ArithmeticError extends Error {}
|
||||
EXPORTED_SYMBOLS.push("ArithmeticError");
|
||||
|
||||
|
||||
class IntegerOverflow extends ArithmeticError {
|
||||
|
||||
constructor(message, ...params) {
|
||||
super(...params);
|
||||
this.message = message;
|
||||
}
|
||||
}
|
||||
EXPORTED_SYMBOLS.push("IntegerOverflow");
|
||||
|
||||
class FfiConverterTypeArithmeticError extends FfiConverterArrayBuffer {
|
||||
static read(dataStream) {
|
||||
switch (dataStream.readInt32()) {
|
||||
case 1:
|
||||
return new IntegerOverflow(FfiConverterString.read(dataStream));
|
||||
default:
|
||||
return new Error("Unknown ArithmeticError variant");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
function add(a,b) {
|
||||
|
||||
const liftResult = (result) => FfiConverterU64.lift(result);
|
||||
const liftError = (data) => FfiConverterTypeArithmeticError.lift(data);
|
||||
const functionCall = () => {
|
||||
FfiConverterU64.checkType("a", a);
|
||||
FfiConverterU64.checkType("b", b);
|
||||
return UniFFIScaffolding.callAsync(
|
||||
2, // arithmetic:arithmetic_77d6_add
|
||||
FfiConverterU64.lower(a),
|
||||
FfiConverterU64.lower(b),
|
||||
)
|
||||
}
|
||||
try {
|
||||
return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
|
||||
} catch (error) {
|
||||
return Promise.reject(error)
|
||||
}
|
||||
}
|
||||
|
||||
EXPORTED_SYMBOLS.push("add");
|
||||
function sub(a,b) {
|
||||
|
||||
const liftResult = (result) => FfiConverterU64.lift(result);
|
||||
const liftError = (data) => FfiConverterTypeArithmeticError.lift(data);
|
||||
const functionCall = () => {
|
||||
FfiConverterU64.checkType("a", a);
|
||||
FfiConverterU64.checkType("b", b);
|
||||
return UniFFIScaffolding.callAsync(
|
||||
3, // arithmetic:arithmetic_77d6_sub
|
||||
FfiConverterU64.lower(a),
|
||||
FfiConverterU64.lower(b),
|
||||
)
|
||||
}
|
||||
try {
|
||||
return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
|
||||
} catch (error) {
|
||||
return Promise.reject(error)
|
||||
}
|
||||
}
|
||||
|
||||
EXPORTED_SYMBOLS.push("sub");
|
||||
function div(dividend,divisor) {
|
||||
|
||||
const liftResult = (result) => FfiConverterU64.lift(result);
|
||||
const liftError = null;
|
||||
const functionCall = () => {
|
||||
FfiConverterU64.checkType("dividend", dividend);
|
||||
FfiConverterU64.checkType("divisor", divisor);
|
||||
return UniFFIScaffolding.callAsync(
|
||||
4, // arithmetic:arithmetic_77d6_div
|
||||
FfiConverterU64.lower(dividend),
|
||||
FfiConverterU64.lower(divisor),
|
||||
)
|
||||
}
|
||||
try {
|
||||
return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
|
||||
} catch (error) {
|
||||
return Promise.reject(error)
|
||||
}
|
||||
}
|
||||
|
||||
EXPORTED_SYMBOLS.push("div");
|
||||
function equal(a,b) {
|
||||
|
||||
const liftResult = (result) => FfiConverterBool.lift(result);
|
||||
const liftError = null;
|
||||
const functionCall = () => {
|
||||
FfiConverterU64.checkType("a", a);
|
||||
FfiConverterU64.checkType("b", b);
|
||||
return UniFFIScaffolding.callAsync(
|
||||
5, // arithmetic:arithmetic_77d6_equal
|
||||
FfiConverterU64.lower(a),
|
||||
FfiConverterU64.lower(b),
|
||||
)
|
||||
}
|
||||
try {
|
||||
return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
|
||||
} catch (error) {
|
||||
return Promise.reject(error)
|
||||
}
|
||||
}
|
||||
|
||||
EXPORTED_SYMBOLS.push("equal");
|
||||
|
|
@ -1,427 +0,0 @@
|
|||
// This file was autogenerated by the `uniffi-bindgen-gecko-js` crate.
|
||||
// Trust me, you don't want to mess with it!
|
||||
|
||||
|
||||
|
||||
"use strict";
|
||||
|
||||
var EXPORTED_SYMBOLS = [];
|
||||
|
||||
// Write/Read data to/from an ArrayBuffer
|
||||
class ArrayBufferDataStream {
|
||||
constructor(arrayBuffer) {
|
||||
this.dataView = new DataView(arrayBuffer);
|
||||
this.pos = 0;
|
||||
}
|
||||
|
||||
readUint8() {
|
||||
let rv = this.dataView.getUint8(this.pos);
|
||||
this.pos += 1;
|
||||
return rv;
|
||||
}
|
||||
|
||||
writeUint8(value) {
|
||||
this.dataView.setUint8(this.pos, value);
|
||||
this.pos += 1;
|
||||
}
|
||||
|
||||
readUint16() {
|
||||
let rv = this.dataView.getUint16(this.pos);
|
||||
this.pos += 2;
|
||||
return rv;
|
||||
}
|
||||
|
||||
writeUint16(value) {
|
||||
this.dataView.setUint16(this.pos, value);
|
||||
this.pos += 2;
|
||||
}
|
||||
|
||||
readUint32() {
|
||||
let rv = this.dataView.getUint32(this.pos);
|
||||
this.pos += 4;
|
||||
return rv;
|
||||
}
|
||||
|
||||
writeUint32(value) {
|
||||
this.dataView.setUint32(this.pos, value);
|
||||
this.pos += 4;
|
||||
}
|
||||
|
||||
readUint64() {
|
||||
let rv = this.dataView.getBigUint64(this.pos);
|
||||
this.pos += 8;
|
||||
return Number(rv);
|
||||
}
|
||||
|
||||
writeUint64(value) {
|
||||
this.dataView.setBigUint64(this.pos, BigInt(value));
|
||||
this.pos += 8;
|
||||
}
|
||||
|
||||
|
||||
readInt8() {
|
||||
let rv = this.dataView.getInt8(this.pos);
|
||||
this.pos += 1;
|
||||
return rv;
|
||||
}
|
||||
|
||||
writeInt8(value) {
|
||||
this.dataView.setInt8(this.pos, value);
|
||||
this.pos += 1;
|
||||
}
|
||||
|
||||
readInt16() {
|
||||
let rv = this.dataView.getInt16(this.pos);
|
||||
this.pos += 2;
|
||||
return rv;
|
||||
}
|
||||
|
||||
writeInt16(value) {
|
||||
this.dataView.setInt16(this.pos, value);
|
||||
this.pos += 2;
|
||||
}
|
||||
|
||||
readInt32() {
|
||||
let rv = this.dataView.getInt32(this.pos);
|
||||
this.pos += 4;
|
||||
return rv;
|
||||
}
|
||||
|
||||
writeInt32(value) {
|
||||
this.dataView.setInt32(this.pos, value);
|
||||
this.pos += 4;
|
||||
}
|
||||
|
||||
readInt64() {
|
||||
let rv = this.dataView.getBigInt64(this.pos);
|
||||
this.pos += 8;
|
||||
return Number(rv);
|
||||
}
|
||||
|
||||
writeInt64(value) {
|
||||
this.dataView.setBigInt64(this.pos, BigInt(value));
|
||||
this.pos += 8;
|
||||
}
|
||||
|
||||
|
||||
readFloat32() {
|
||||
let rv = this.dataView.getFloat32(this.pos);
|
||||
this.pos += 4;
|
||||
return rv;
|
||||
}
|
||||
|
||||
writeFloat32(value) {
|
||||
this.dataView.setFloat32(this.pos, value);
|
||||
this.pos += 4;
|
||||
}
|
||||
|
||||
readFloat64() {
|
||||
let rv = this.dataView.getFloat64(this.pos);
|
||||
this.pos += 8;
|
||||
return rv;
|
||||
}
|
||||
|
||||
writeFloat64(value) {
|
||||
this.dataView.setFloat64(this.pos, value);
|
||||
this.pos += 8;
|
||||
}
|
||||
|
||||
|
||||
writeString(value) {
|
||||
const encoder = new TextEncoder();
|
||||
// Note: in order to efficiently write this data, we first write the
|
||||
// string data, reserving 4 bytes for the size.
|
||||
const dest = new Uint8Array(this.dataView.buffer, this.pos + 4);
|
||||
const encodeResult = encoder.encodeInto(value, dest);
|
||||
if (encodeResult.read != value.length) {
|
||||
throw new UniFFIError(
|
||||
"writeString: out of space when writing to ArrayBuffer. Did the computeSize() method returned the wrong result?"
|
||||
);
|
||||
}
|
||||
const size = encodeResult.written;
|
||||
// Next, go back and write the size before the string data
|
||||
this.dataView.setUint32(this.pos, size);
|
||||
// Finally, advance our position past both the size and string data
|
||||
this.pos += size + 4;
|
||||
}
|
||||
|
||||
readString() {
|
||||
const decoder = new TextDecoder();
|
||||
const size = this.readUint32();
|
||||
const source = new Uint8Array(this.dataView.buffer, this.pos, size)
|
||||
const value = decoder.decode(source);
|
||||
this.pos += size;
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
function handleRustResult(result, liftCallback, liftErrCallback) {
|
||||
switch (result.code) {
|
||||
case "success":
|
||||
return liftCallback(result.data);
|
||||
|
||||
case "error":
|
||||
throw liftErrCallback(result.data);
|
||||
|
||||
case "internal-error":
|
||||
let message = result.internalErrorMessage;
|
||||
if (message) {
|
||||
throw new UniFFIInternalError(message);
|
||||
} else {
|
||||
throw new UniFFIInternalError("Unknown error");
|
||||
}
|
||||
|
||||
default:
|
||||
throw new UniFFIError(`Unexpected status code: ${result.code}`);
|
||||
}
|
||||
}
|
||||
|
||||
class UniFFIError {
|
||||
constructor(message) {
|
||||
this.message = message;
|
||||
}
|
||||
}
|
||||
|
||||
class UniFFIInternalError extends UniFFIError {}
|
||||
|
||||
// Base class for FFI converters
|
||||
class FfiConverter {
|
||||
static checkType(name, value) {
|
||||
if (value === undefined ) {
|
||||
throw TypeError(`${name} is undefined`);
|
||||
}
|
||||
if (value === null ) {
|
||||
throw TypeError(`${name} is null`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Base class for FFI converters that lift/lower by reading/writing to an ArrayBuffer
|
||||
class FfiConverterArrayBuffer extends FfiConverter {
|
||||
static lift(buf) {
|
||||
return this.read(new ArrayBufferDataStream(buf));
|
||||
}
|
||||
|
||||
static lower(value) {
|
||||
const buf = new ArrayBuffer(this.computeSize(value));
|
||||
const dataStream = new ArrayBufferDataStream(buf);
|
||||
this.write(dataStream, value);
|
||||
return buf;
|
||||
}
|
||||
}
|
||||
|
||||
// Symbols that are used to ensure that Object constructors
|
||||
// can only be used with a proper UniFFI pointer
|
||||
const uniffiObjectPtr = Symbol("uniffiObjectPtr");
|
||||
const constructUniffiObject = Symbol("constructUniffiObject");
|
||||
|
||||
class FfiConverterF64 extends FfiConverter {
|
||||
static computeSize() {
|
||||
return 8;
|
||||
}
|
||||
static lift(value) {
|
||||
return value;
|
||||
}
|
||||
static lower(value) {
|
||||
return value;
|
||||
}
|
||||
static write(dataStream, value) {
|
||||
dataStream.writeFloat64(value)
|
||||
}
|
||||
static read(dataStream) {
|
||||
return dataStream.readFloat64()
|
||||
}
|
||||
}
|
||||
|
||||
class FfiConverterString extends FfiConverter {
|
||||
static lift(buf) {
|
||||
const decoder = new TextDecoder();
|
||||
const utf8Arr = new Uint8Array(buf);
|
||||
return decoder.decode(utf8Arr);
|
||||
}
|
||||
static lower(value) {
|
||||
const encoder = new TextEncoder();
|
||||
return encoder.encode(value).buffer;
|
||||
}
|
||||
|
||||
static write(dataStream, value) {
|
||||
dataStream.writeString(value);
|
||||
}
|
||||
|
||||
static read(dataStream) {
|
||||
return dataStream.readString();
|
||||
}
|
||||
|
||||
static computeSize(value) {
|
||||
const encoder = new TextEncoder();
|
||||
return 4 + encoder.encode(value).length
|
||||
}
|
||||
}
|
||||
|
||||
class Line {
|
||||
constructor(start,end) {
|
||||
FfiConverterTypePoint.checkType("start", start);
|
||||
FfiConverterTypePoint.checkType("end", end);
|
||||
this.start = start;
|
||||
this.end = end;
|
||||
}
|
||||
equals(other) {
|
||||
return (
|
||||
this.start.equals(other.start) &&
|
||||
this.end.equals(other.end)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
class FfiConverterTypeLine extends FfiConverter {
|
||||
static lift(buf) {
|
||||
return this.read(new ArrayBufferDataStream(buf));
|
||||
}
|
||||
static lower(value) {
|
||||
const buf = new ArrayBuffer(this.computeSize(value));
|
||||
const dataStream = new ArrayBufferDataStream(buf);
|
||||
this.write(dataStream, value);
|
||||
return buf;
|
||||
}
|
||||
static read(dataStream) {
|
||||
return new Line(
|
||||
FfiConverterTypePoint.read(dataStream),
|
||||
FfiConverterTypePoint.read(dataStream)
|
||||
);
|
||||
}
|
||||
static write(dataStream, value) {
|
||||
FfiConverterTypePoint.write(dataStream, value.start);
|
||||
FfiConverterTypePoint.write(dataStream, value.end);
|
||||
}
|
||||
|
||||
static computeSize(value) {
|
||||
let totalSize = 0;
|
||||
totalSize += FfiConverterTypePoint.computeSize(value.start);
|
||||
totalSize += FfiConverterTypePoint.computeSize(value.end);
|
||||
return totalSize
|
||||
}
|
||||
}
|
||||
|
||||
EXPORTED_SYMBOLS.push("Line");
|
||||
|
||||
class Point {
|
||||
constructor(coordX,coordY) {
|
||||
FfiConverterF64.checkType("coordX", coordX);
|
||||
FfiConverterF64.checkType("coordY", coordY);
|
||||
this.coordX = coordX;
|
||||
this.coordY = coordY;
|
||||
}
|
||||
equals(other) {
|
||||
return (
|
||||
this.coordX == other.coordX &&
|
||||
this.coordY == other.coordY
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
class FfiConverterTypePoint extends FfiConverter {
|
||||
static lift(buf) {
|
||||
return this.read(new ArrayBufferDataStream(buf));
|
||||
}
|
||||
static lower(value) {
|
||||
const buf = new ArrayBuffer(this.computeSize(value));
|
||||
const dataStream = new ArrayBufferDataStream(buf);
|
||||
this.write(dataStream, value);
|
||||
return buf;
|
||||
}
|
||||
static read(dataStream) {
|
||||
return new Point(
|
||||
FfiConverterF64.read(dataStream),
|
||||
FfiConverterF64.read(dataStream)
|
||||
);
|
||||
}
|
||||
static write(dataStream, value) {
|
||||
FfiConverterF64.write(dataStream, value.coordX);
|
||||
FfiConverterF64.write(dataStream, value.coordY);
|
||||
}
|
||||
|
||||
static computeSize(value) {
|
||||
let totalSize = 0;
|
||||
totalSize += FfiConverterF64.computeSize(value.coordX);
|
||||
totalSize += FfiConverterF64.computeSize(value.coordY);
|
||||
return totalSize
|
||||
}
|
||||
}
|
||||
|
||||
EXPORTED_SYMBOLS.push("Point");class FfiConverterOptionalTypePoint extends FfiConverterArrayBuffer {
|
||||
static checkType(name, value) {
|
||||
if (value !== undefined && value !== null) {
|
||||
FfiConverterTypePoint.checkType(name, value)
|
||||
}
|
||||
}
|
||||
|
||||
static read(dataStream) {
|
||||
const code = dataStream.readUint8(0);
|
||||
switch (code) {
|
||||
case 0:
|
||||
return null
|
||||
case 1:
|
||||
return FfiConverterTypePoint.read(dataStream)
|
||||
default:
|
||||
throw UniFFIError(`Unexpected code: ${code}`);
|
||||
}
|
||||
}
|
||||
|
||||
static write(dataStream, value) {
|
||||
if (value === null || value === undefined) {
|
||||
dataStream.writeUint8(0);
|
||||
return;
|
||||
}
|
||||
dataStream.writeUint8(1);
|
||||
FfiConverterTypePoint.write(dataStream, value)
|
||||
}
|
||||
|
||||
static computeSize(value) {
|
||||
if (value === null || value === undefined) {
|
||||
return 1;
|
||||
}
|
||||
return 1 + FfiConverterTypePoint.computeSize(value)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function gradient(ln) {
|
||||
|
||||
const liftResult = (result) => FfiConverterF64.lift(result);
|
||||
const liftError = null;
|
||||
const functionCall = () => {
|
||||
FfiConverterTypeLine.checkType("ln", ln);
|
||||
return UniFFIScaffolding.callAsync(
|
||||
0, // geometry:geometry_ba8c_gradient
|
||||
FfiConverterTypeLine.lower(ln),
|
||||
)
|
||||
}
|
||||
try {
|
||||
return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
|
||||
} catch (error) {
|
||||
return Promise.reject(error)
|
||||
}
|
||||
}
|
||||
|
||||
EXPORTED_SYMBOLS.push("gradient");
|
||||
function intersection(ln1,ln2) {
|
||||
|
||||
const liftResult = (result) => FfiConverterOptionalTypePoint.lift(result);
|
||||
const liftError = null;
|
||||
const functionCall = () => {
|
||||
FfiConverterTypeLine.checkType("ln1", ln1);
|
||||
FfiConverterTypeLine.checkType("ln2", ln2);
|
||||
return UniFFIScaffolding.callAsync(
|
||||
1, // geometry:geometry_ba8c_intersection
|
||||
FfiConverterTypeLine.lower(ln1),
|
||||
FfiConverterTypeLine.lower(ln2),
|
||||
)
|
||||
}
|
||||
try {
|
||||
return functionCall().then((result) => handleRustResult(result, liftResult, liftError));
|
||||
} catch (error) {
|
||||
return Promise.reject(error)
|
||||
}
|
||||
}
|
||||
|
||||
EXPORTED_SYMBOLS.push("intersection");
|
||||
|
|
@ -1 +0,0 @@
|
|||
This directory is where files generated by Uniffi will be created.
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue