Skip to content

Commit

Permalink
Merge pull request #2056 from fzyzcjy/feat/12108
Browse files Browse the repository at this point in the history
Add documentations
  • Loading branch information
fzyzcjy committed Jun 9, 2024
2 parents 1b19576 + 52e9ea8 commit 4ac895b
Show file tree
Hide file tree
Showing 31 changed files with 679 additions and 158 deletions.
43 changes: 43 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,49 @@

* Please refer to https://fzyzcjy.github.io/flutter_rust_bridge/guides/miscellaneous/whats-new for what's changed in V2.
* Fix dashed library names #2034 (thanks @vhdirk)
* Refactor internals to base on mods instead of files #2000
* Support code in mod file #2000
* Support code in lib.rs file #2000
* Fix dart_code cannot generate when containing brackets confusing to mod parser #2000
* Support multiple input path prefixes #2000
* Add dart_type_rename to customize Dart names of opaque types #2006
* Support automatic scanning of third party crates (part 1) #2007
* Enhance usize and isize #2008
* Support syntax of `pub use something::*` #2009
* Improve Dart output directory of third party crates #2010
* Support overriding things in third party crate #2011 #2013
* Automatically mark methods of non-pub structs as ignored #2012
* Refactor macros information encoding and decoding #2014
* Detect and skip functions with generics #2015
* Auto detect as opaque when third party struct/enum has non public field #2016
* Auto convert reference type in return type as unit type #2017
* Automatically mirror for scanned third party types #2018
* Skip generating auto accessors for borrowed fields #2018
* Support slices as arguments (such as `&[u8]`, `&[Something]`) #2019
* Support non-exhaustive enumerations #2020
* Improve Dart import generation #2021
* Support trait methods and trait default implementations #2024
* Improve pub use parsing and trait definition parsing in third party crates #2025
* Add integrate_third_party example #2027
* Support overriding third party methods #2029
* Support adding new methods to third party structs #2029
* Fix third party pub use scanning problem #2030
* Support multiple `#[frb(external)]` impl blocks for a single struct #2030
* Fix scanning third party pub use concrete type for methods #2031
* Make generated Dart opaque class abstract to improve testability #2032
* Refactor HIR (high-level intermediate representation) #2037
* Add stop_on_error configuration #2037
* Refactor override_priority and refine_namespace #2041
* Support trait definitions and translate to Dart abstract classes #2033
* Support third party overriding traits #2033
* Refactor MIR (mid-level intermediate representation) parser #2044
* Support `#[frb(generate_impl_enum)]` #2046
* Fix overriding attributes in third party crates for traits #2046
* Add RustOpaqueInterface to cleanup generated interface #2047
* Refactor to extract early_generator between high-level intermediate representation and mid-level intermediate representation #2049
* Support `#[frb(proxy)]` #2050 #2052 #2053
* Refactor to extract Lockable #2051
* Support &dyn Trait #2054

## 2.0.0-dev.37

Expand Down
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
rust_input: REPLACE_ME_RUST_CRATE_DIR/src/api/**/*.rs
rust_input: crate::api
rust_root: REPLACE_ME_RUST_CRATE_DIR/
dart_output: lib/src/rust
2 changes: 1 addition & 1 deletion frb_codegen/src/binary/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ pub(crate) struct GenerateCommandArgsPrimary {
#[arg(long)]
pub config_file: Option<String>,

/// Glob pattern of input Rust files
/// Input Rust files, such as `crate::api,crate::hello::world,another-third-party-crate`
#[arg(short, long)]
pub rust_input: Option<String>,

Expand Down
3 changes: 2 additions & 1 deletion frb_example/flutter_via_create/flutter_rust_bridge.yaml
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
rust_input: rust/src/api/**/*.rs
rust_input: crate::api
rust_root: rust/
dart_output: lib/src/rust
local: true
3 changes: 2 additions & 1 deletion frb_example/flutter_via_integrate/flutter_rust_bridge.yaml
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
rust_input: rust/src/api/**/*.rs
rust_input: crate::api
rust_root: rust/
dart_output: lib/src/rust
local: true
2 changes: 1 addition & 1 deletion website/docs/generated/_frb-codegen-command-generate.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ Options:
If present, other options and flags will be ignored. Accepts the same options as the CLI, but uses snake_case keys.
-r, --rust-input <RUST_INPUT>
Glob pattern of input Rust files
Input Rust files, such as `crate::api,crate::hello::world,another-third-party-crate`
-d, --dart-output <DART_OUTPUT>
Directory of output generated Dart code
Expand Down
33 changes: 3 additions & 30 deletions website/docs/guides/functions/methods.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,7 @@ In addition to standard functions,
there is support for structs with methods. Both static methods, and non-static methods are supported.
No special syntax is needed, and just write normal `impl YourStruct { pub fn your_method() {} }`.

## Methods in external crates

For methods that are not defined in the `rust_input` folders in the current crate,
the `#[frb(external)]` syntax (see example below) is needed to make flutter_rust_bridge aware of the methods.
For methods in other crates, please refer to [this page](../third-party/manual/types) and the more general [feature](../third-party).

## Example

Expand Down Expand Up @@ -42,29 +39,5 @@ Remark: If you are curious about `Future`, have a look at [this](../concurrency/

### Example 2: Methods in external crates

Suppose we have these in external crates:

```rust
pub struct MyExternalStruct {
...
}

impl MyExternalStruct {
pub fn simple_external_method(&self) -> String {
// ... some long implementations ...
}
}
```

Then, we only need to repeat the function signatures in our main crate as follows:

```rust
#[frb(external)]
impl MyExternalStruct {
pub fn simple_external_method(&self) -> String {}
}
```

Remark: Just leave the function body empty (i.e. `{}`), no need to put anything there.

This feature is compatible with the [mirroring](../types/translatable/external/diff-crate) feature as well.
The documentation was moved to [this page](../third-party/manual/types).
The new feature - automatically scanning a whole third party package - may also be helpful and is discussed [here](../third-party).
18 changes: 16 additions & 2 deletions website/docs/guides/how-to/borrowed.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,18 @@
# Borrowed types

flutter_rust_bridge does not yet support types with borrowing and lifetime
like `struct MyStruct<'a> { field: &'a Another }`,
flutter_rust_bridge does not yet support types with *arbitrary* borrowing and lifetime
like `struct MyStruct<'a> { ... }`,
or functions that return arbitrary reference types,
since this has not been a blocker for users and there are alternative approaches.
However, if you do need to have this feature, feel free to open an issue and we can discuss/implement it!
Below, we discuss several approaches for some scenarios.

## Proxy

The proxy feature can be utilized when the borrowed type is indeed a field of struct or something like that.
Please refer to [this page](../miscellaneous/proxy) for more details.

## Shared ownership

One alternative approach is to use shared ownership.
For example, for the example above, we can rewrite as:
Expand All @@ -16,3 +25,8 @@ struct MyStruct {

As a side remark, if you want to expose that field to Dart side in opaque struct,
you can also wrap as `RustAutoOpaque<Another>`.

## Clone

Yet another way is to simply clone related things when returned, instead of returning a reference.
This is especially reasonable when the resource being cloned is not heavy.
10 changes: 10 additions & 0 deletions website/docs/guides/miscellaneous/dart-type-rename.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Rename Dart types

The automatically generated type names can be customized.
For example, `Box<dyn Any + Send + Sync + 'static>` has corresponding Dart name as `BoxAny` by default.
Suppose we want to change it to `MyFancyName`, then we can configure as follows in `flutter_rust_bridge.yaml`:

```yaml
dart_type_rename:
Box<dyn Any + Send + Sync + 'static>: MyFancyName
```
13 changes: 13 additions & 0 deletions website/docs/guides/miscellaneous/multi-input.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Multiple input folders

The `rust_input` configuration key supports multiple entries separated by commas.
For example, consider the following configuration:

```yaml
rust_input: crate::api,crate::hello::world
```
Roughly speaking, it will scan `src/api/**/*.rs` and `src/hello/world/**/*.rs`.

More strictly speaking, it scans Rust modules instead of real files, thus complex scenarios such as multiple modules
inside one file are supported.
18 changes: 18 additions & 0 deletions website/docs/guides/miscellaneous/override-prefix.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# `frb_override_*` prefix

If a method name starts with `frb_override_`,
then it will be automatically recognized as if it does not have that prefix,
and it gains privilege to override other existing methods (i.e. remove methods with same name).

This is helpful when wanting to override existing methods,
and also helpful when the name conflicts (such as in `#[ext]`).

## Example

```rust
impl MyStruct {
pub fn frb_override_hello(&self, a: i32) -> i32 {}
}
```

Then it is equivalent to `fn hello(...)` with privilege.
71 changes: 71 additions & 0 deletions website/docs/guides/miscellaneous/proxy.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
# Proxy

When annotating a method with `#[frb(proxy)]`,
the method will be allowed to return a reference type,
and the behavior will be explained below.

Typically, this can be used to expose struct or enum fields.

## Example

### Scenario

Consider the following code:

```rust
#[frb(opaque)]
pub struct BiquadFilterNode {
frequency: AudioParam,
}

impl BiquadFilterNode {
pub fn frequency(&self) -> &AudioParam {
&self.frequency
}
}

pub struct AudioParam { ... }

impl AudioParam {
pub fn my_method_one(&self, value: f32) { ... }
pub fn my_method_two(&self, value: f32) { ... }
}
```

`flutter_rust_bridge` will not be able to generate code for it, since the return type being a reference type
is not supported yet (and if implemented, may have problems such as "borrowing for too long").
However, if we add `#[frb(proxy)]` to the `fn`, then it will work well.

### Remark: Alternative solutions

As is mentioned in [this page](../how-to/borrowed), one alternative solution is to use `clone`:

```rust
pub fn get_my_sub_struct(&self) -> MySubStruct {
self.frequency.clone()
}
```

Another solution is that, we can also utilize `Arc` or `RustAutoOpaque` (which is essentially an `Arc` with something else):

```rust
frequency: RustAutoOpaque<AudioParam>,
```

### (Optional) Under the hood

Shortly speaking,
the generated code has similar idea to the code below, but the exact details is better.
I will elaborate more if you are interested in it.

```rust
impl BiquadFilterNode {
pub fn frequency_my_method_one(&self, value: f32) {
self.frequency.my_method_one(value)
}

pub fn frequency_my_method_two(&self, value: f32) {
self.frequency.my_method_two(value)
}
}
```
7 changes: 7 additions & 0 deletions website/docs/guides/third-party/automatic/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Automatic

```mdx-code-block
import DocCardList from '@theme/DocCardList';
<DocCardList />
```
44 changes: 44 additions & 0 deletions website/docs/guides/third-party/automatic/override-attributes.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# Override attributes

If the implementations of an external component (function/method/struct/enum/etc) is good,
and we only want to add some *attributes* to it,
then we only need to write down component name and new attributes inside our first-party package like below.

The rule is that:

* Put the code inside `src/third_party/{third-party-crate-name}/{path-to-the-module}`.
* Only write down function name, and no need to specify function arguments and return types.

## Examples

Suppose we are interested in the `some_crate::hello::world::SomeStruct::method` method in third-party crate:

```rust
// This is code in third-party crate, we cannot modify it
pub struct SomeStruct {
...
}

impl SomeStruct {
pub fn method(&self, a: String, b: Vec<i32>) -> f32 {
...
}
}
```

Then, we can write down the following lines to make that method has synchronous Dart code:

```rust
// src/third_party/some_crate/hello/world/mod.rs
#[frb(external)]
impl SomeStruct {
#[frb(sync)] // <-- This attribute will be auto merged to third-party code
pub fn method() {}
}
```

## Remark on `pub use`

`flutter_rust_bridge` understands syntax like `pub use something::*` and `pub use another::Thing`.
Therefore, if a struct in third party code is defined non-publicly but then re-exported as public using such `pub use` grammar,
`flutter_rust_bridge` will consider that type to be in the latter module.
47 changes: 47 additions & 0 deletions website/docs/guides/third-party/automatic/override-methods.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# Override/add methods

In this page, we show how to do these in the example below:

* Change the function signature / method implementation / ... of something in a third-party crate
* Add arbitrary methods to existing structs/enums in third party crates

## (Optional) How it is done

How is the example below implemented?
Shortly speaking,
the `#[ext]` macro (which implements the "extension trait pattern") automatically generates a trait and an implementation,
which `flutter_rust_bridge` picks up.
Then, the [`frb_override_` prefix](../../miscellaneous/override-prefix) is recognized to automatically rename and override the original function.

## Example

### Override existing methods

Suppose the third party crate has code like:

```rust
pub struct S { ... }
impl S {
pub fn greet(&self, name: &str) { ... }
}
```

Then we can override the `greet` function like:

```rust
use extend::ext; // or, for example, easy_ext's
use the_external_crate::path::to::S;

#[ext]
pub impl S {
pub fn frb_override_greet(&self, age: i32, first_name: String, last_name: Vec<u8>) {
// We can have arbitrary implementation.
// Here, we demonstrate how to call the original implementation with modified arguments.
self.greet(format!("{age}-{first_name}-{last_name:?}"))
}
}
```

### Add new methods

It is very similar to the approach above, except that we do not need to prefix with `frb_override_`.
14 changes: 14 additions & 0 deletions website/docs/guides/third-party/automatic/scanning.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Scanning

The first step is to configure to scan the third-party crate.
This is fairly simple - just modify `flutter_rust_bridge.yaml` and change to something like:

```yaml
rust_input: crate::api,interesting_third_party_crate_name
```
The line above means we want to both scan `src/api` folder in our crate and scan the `interesting_third_party_crate_name` crate.

For crate with `-` in the name, we can write `interesting-third-party-crate-name`

Please refer to [this page](../../miscellaneous/multi-input) for more details of the configuration.
Loading

0 comments on commit 4ac895b

Please sign in to comment.