Skip to content

Commit

Permalink
feat: [🎼 特性](feature.md)
Browse files Browse the repository at this point in the history
Signed-off-by: trdthg <trdthg@outlook.com>
  • Loading branch information
trdthg committed Aug 23, 2022
1 parent d90dc80 commit 6b29ac5
Show file tree
Hide file tree
Showing 10 changed files with 111 additions and 83 deletions.
26 changes: 16 additions & 10 deletions src/feature.md
Original file line number Diff line number Diff line change
@@ -1,18 +1,24 @@
# Features
# 特性

In this chapter, we are going to demonstrate the features. Please use the menu bar at the left / left-top of the page to navigate.
这一章,我们将展示该库的各个特性。请使用左侧/左上的菜单栏切换页面。

## Prelogue
## 序言

### What this library is and is not
### 这个库是什么?

This library is nothing but a code generator that helps your Flutter/Dart functions call Rust functions. It only generates some boilerplate code that you will manually write down otherwise. Moreover, we have provided detailed tutorials for you to play with examples, set up brand new apps, and integrate with existing apps.
这个库只是一个代码生成器,帮助你的 Flutter/Dart 函数调用 Rust
函数。它只会生成一些模板代码,代替了手工编写。此外,我们还为您提供了详细的教程,让您可以尝试实例,创建新的应用程序,并与现有的应用程序集成。

Of course, you may still need to have some basic familiarity with Flutter/Dart, Rust, and its [ffi](https://flutter.dev/docs/development/platform-integration/c-interop).
当然,你仍然需要对 Flutter/Dart,Rust 以及
[ffi](https://flutter.dev/docs/development/platform-integration/c-interop).
有一些基本的了解。

### Full examples
### 完整实例

If you want to look at a lot of examples - I have to warn you, really too many - have a look at [pure_dart's api.rs](https://github.com/fzyzcjy/flutter_rust_bridge/blob/master/frb_example/pure_dart/rust/src/api.rs). It contains all tests for this library.

In addition, when you are quite familiar with the basic example, you can then take a look at [pure_dart_multi](https://github.com/fzyzcjy/flutter_rust_bridge/tree/master/frb_example/pure_dart_multi/rust/src). This example contains multiple blocks of APIs instead of one, which is quite useful for complex projects.
如果你想看一些例子 - 我要提前警告你,示例代码真的非常多 -
[pure_dart's api.rs](https://github.com/fzyzcjy/flutter_rust_bridge/blob/master/frb_example/pure_dart/rust/src/api.rs).
里面包含了对该库的所有测试。

此外,当你对基本的例子已经熟悉后,你就可以看一下
[pure_dart_multi](https://github.com/fzyzcjy/flutter_rust_bridge/tree/master/frb_example/pure_dart_multi/rust/src).
这个例子包含多个 API 模块。对于复杂的项目来说是相当有用的。
4 changes: 2 additions & 2 deletions src/feature/lang.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
# Language translations
# 语言间转换

In this section, we will show how various language features are translated between Rust and Dart.
这一部分我们将展示 Rust Dart 语言间的特性是如何转换。
15 changes: 7 additions & 8 deletions src/feature/lang_enum.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
# `enum`s
# 枚举

Rust's `enum` are known to be very expressive and powerful - it allows each enum variant to have different associated data. Dart does not have such things in built-in enums, but no worries - we will automatically translate it into the equivalent using the `freezed` Dart library. The syntax for `freezed` may look a bit strange at the first glance, but please look at [its doc](https://pub.dev/packages/freezed) and see its powerfulness.
众所周知,Rust 的 `enum` 功能强且表达力强 - 它允许每一个枚举的变体关联不同的数据。Dart 没有内置这种枚举,但是不用担心 - 我们会使用
Dart 中的 `freezed` 库自动翻译为等价的结构。第一眼看上去,`freezed` 的语法可能看上去很奇怪,但是请阅读一下
[它的文档](https://pub.dev/packages/freezed), 看看它的强大之处。

## Example
## 示例

```rust,noplayground
pub enum KitchenSink {
Expand All @@ -24,7 +26,7 @@ pub enum KitchenSink {
}
```

Becomes:
转换为:

```Dart
@freezed
Expand Down Expand Up @@ -54,7 +56,4 @@ class KitchenSink with _$KitchenSink {
}
```

And they are powered with [all functionalities](https://pub.dev/packages/freezed) of `freezed`.

Remark: If you are curious about `Future`, have a look at [this](async_dart.md).

它们由 freezed 中的 [all functionalities](https://pub.dev/packages/freezed) 驱动。
30 changes: 17 additions & 13 deletions src/feature/lang_external.md
Original file line number Diff line number Diff line change
@@ -1,35 +1,40 @@
# External types
# 外部类型

## Types in other files within the same crate
## 定义在相同 crate 其他文件中的类型

Imported symbols can be used normally. For example, with `use crate::data::{MyEnum, MyStruct};`, you can use `MyEnum` or `MyStruct` in your code normally.
`use` 语句可以正常使用。例如:添加 `use crate::data::{MyEnum, MyStruct};`后,你可以正常的使用 `MyEnum`
`MyStruct`

### Example
### 示例

```rust,noplayground
use crate::data::{MyEnum, MyStruct};
pub fn use_imported_things(my_struct: MyStruct, my_enum: MyEnum) { ... }
```

Becomes:
转换为:

```Dart
// Well it just behaves normally as you expect
Future<void> useImportedThings({required MyStruct myStruct, required MyEnum myEnum});
```

Remark: If you are curious about `Future`, have a look at [this](async_dart.md).
注意:如果你对 `Future` 感兴趣,请看 [这里](async_dart.md).

## Types in other crates
## 其他 crate 中的类型

The feature is called "mirroring". In short, you need to define the type again mirroring the external type that you want to use. That definition is only used at code-generation time to tell `flutter_rust_bridge` type information. To see exact grammar, have a look at the example below.
这个功能被称为 "镜像". 简单来说,对于你想使用的外部类型,你需要重新编写该类型作为镜像。这个镜像只会在代码生成时负责告知
`flutter_rust_bridge` 所需的类型信息。下面的例子里有详细的语法。

No need to worry whether this breaks the DRY principle, or what happens when you accidentially write down a wrong field. This is because *compile errors will happen* if your mirrored type is not exactly same as the original type.
不用担心它会打破 DRY (Don’t Repeat Yourself)
原则,或者是你可能偶然写下一个错误的字段。因为如果镜像和原始类型不完全一致就会导致编译错误。

More information: [#352](https://github.com/fzyzcjy/flutter_rust_bridge/pull/352)
更多信息: [#352](https://github.com/fzyzcjy/flutter_rust_bridge/pull/352)

When multiple structs have the same fields, you can mirror them *once* using grammar like `#[frb(mirror(FirstStruct, SecondStruct, ThirdStruct))]`. ([#619](https://github.com/fzyzcjy/flutter_rust_bridge/pull/619))
当多个结构体有相同的字段时,你可以使用下面的语法只镜像一遍。
`#[frb(mirror(FirstStruct, SecondStruct, ThirdStruct))]`.
([#619](https://github.com/fzyzcjy/flutter_rust_bridge/pull/619))

### Example

Expand Down Expand Up @@ -78,8 +83,7 @@ pub fn is_app_embedded(app_settings: ApplicationSettings) -> bool {
}
```

Another example using one struct to mirror multiple structs:

用一个结构体去镜像多个结构体:

```rust,noplayground
// *no* need to do these
Expand Down
11 changes: 5 additions & 6 deletions src/feature/lang_methods.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# Methods
# 方法

There is support for structs with methods. Both static methods, and non-static methods are supported.
支持带有方法的结构体。包括静态方法和非静态方法。

## Example
## 示例

```rust,noplayground
pub struct SumWith { pub x: u32 }
Expand All @@ -13,7 +13,7 @@ impl SumWith {
}
```

Becomes:
转换为

```Dart
class SumWith {
Expand All @@ -30,5 +30,4 @@ class SumWith {
}
```

Remark: If you are curious about `Future`, have a look at [this](async_dart.md).

注意:如果你对 `Future` 感兴趣,请看 [这里](async_dart.md).
15 changes: 8 additions & 7 deletions src/feature/lang_option.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
# `Option`s
# Option

Dart has special syntaxs for nullable variables - the `?` symbol, and we translate `Option` into `?` automatically. You may refer to [the official doc](https://dart.dev/null-safety) for more information.
Dart 对于可能为空的字段有特殊的语法 - `?`,我们会自动把 `Option` 翻译为 `?`。你可以查看
[官方文档](https://dart.dev/null-safety) 了解更多。

In addition, `flutter_rust_bridge` also understands the `required` keyword in Dart: If an argument is not-null, it is marked as `required` since you have to provide a value. On the other hand, if it is nullable, no `required` is needed since by Dart's convention a null is there in absence of manually providing a value.
此外,`flutter_rust_bridge` 也能够处理 Dart 中的 `required` 关键字:如果一个参数不能为空,它就会被标记为
`required`,同时你必须提供一个值。如果它可以为空,那就不需要 `required`,Dart 的惯例是默认为 null。

## Example
## 示例

```rust,noplayground
pub struct Element {
Expand All @@ -17,7 +19,7 @@ pub struct Element {
pub fn parse(mode: String, document: Option<String>) -> Option<Element> { ... }
```

Becomes:
转换为:

```Dart
Future<Element?> handleOptionalStruct({required String mode, String? document});
Expand All @@ -31,5 +33,4 @@ class Element {
}
```

Remark: If you are curious about `Future`, have a look at [this](async_dart.md).

注意:如果你对 `Future` 感兴趣,请看 [这里](async_dart.md).
7 changes: 3 additions & 4 deletions src/feature/lang_return_types.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
# Return Types
# 返回值类型

The return type can be either `anyhow::Result<YourType>`, or `YourType` directly.
返回值类型可以是 `anyhow::Result<YourType>`, 或者直接是你的类型 `YourType` .

## Example
## 示例

```rust,noplayground
pub fn f(a: i32, b: i32) -> i32 { a + b }
pub fn g(a: i32, b: i32) -> anyhow::Result<i32> { Ok(a + b) }
```

5 changes: 2 additions & 3 deletions src/feature/lang_simple.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Simple correspondence
# 简单的对应关系

Here is a brief glance showing what the code generator can generate (non-exhaustive). Some rows have hyper-links pointing to more detailed explanations.
下面是一个简短的概览,显示了代码生成器可以生成的内容(并非完备)。有些行附带超链接,里面有更详细的解释。

| Rust | Dart |
| ------------------------------------------------- | --------------------------- |
Expand All @@ -20,4 +20,3 @@ Here is a brief glance showing what the code generator can generate (non-exhaust
| `bool` | `bool` |
| `String` | `String` |
| `()` | `void` |

62 changes: 40 additions & 22 deletions src/feature/lang_struct.md
Original file line number Diff line number Diff line change
@@ -1,36 +1,54 @@
# `struct`s
# 结构体

Normal Rust structs are supported. You can even use recursive fields, such as `pub struct TreeNode { pub value: String, pub children: Vec<MyTreeNode>, pub parent: Box<MyTreeNode> }`.
一般的 Rust 结构体都是支持的,你甚至能够使用递归字段,比如:

If a struct field has type being a struct or an enum, please add a `Box` on it, or it will lead to compile-time error. For example, `struct A {b: B}` should be `struct A {b: Box<B>}` instead.
```rust,noplayground
pub struct TreeNode {
pub value: String,
pub children: Vec<MyTreeNode>,
pub parent: Box<MyTreeNode>
}
```

## Tuple structs
如果一个结构体的字段是一个结构体或者枚举,请为它加上一层 `Box`, 否则会导致编译时错误。例如 `struct A {b: B}` 应该使用
`struct A {b: Box<B>}` 代替。

Tuple structs `struct Foo(A, B)` are translated as `class Foo { A field0; B field1; }`, since Dart does not have anonymous fields.
## 元组结构体

## Non-final fields
元组结构体 `struct Foo(A, B)` 会被翻译为 `class Foo { A field0; B field1; }`, 因为 Dart
没有匿名字段。

By adding `#[frb(non_final)]` to a field of struct, the corresponding field in Dart will be non-final. By default, we make all generated fields final because of Rust's philosophy - immutable by default.
## Non-final 字段

## Dart metadata annotations
在结构体字段上添加 `#[(non_final)]`, Dart 中对应的字段就会是 non-final 的。默认情况下,所有生成的字段都被设为
final,因为 Rust 默认情况下是不可变的。

You can add dart metadata annotations using `dart_metadata` parameter in `frb` macro.
## Dart 元数据注释

* For annotations that are prelude by dart (e.g. `@deprecated`), just put annotation as a Rust literal.
* If importing is needed, then add importing part behind the annotation string. Currently two forms of importing supported:
* `import 'somepackage'`
* `import 'somepackage' as somename`, where `somename` will be the prefix of the annotation
* Multiple annotations are seperated by comma `,`.
你可以使用 `frb` 宏中的 `dart_metadata` 参数添加 dart 元数据注解。

See below for an example.
> TODO! You can add dart metadata annotations using `dart_metadata` parameter in
> `frb` macro.
- 对于那些被 dart 提前引入的注解(例如 `@deprecated`),只需将注解作为一个 Rust 字面量。
> TODO! For annotations that are prelude by dart (e.g. `@deprecated`), just
> put annotation as a Rust literal.
- 如果你需要使用到 import, 把 import 部分的代码追加到注解字面量之后。当前支持两种 import 格式:
- `import 'somepackage'`
- `import 'somepackage' as somename`, `somename` 部分会成为注解的前缀
- 多个注解间使用 `,` 分割

具体的例子如下。

## `freezed` Dart classes

If you want the generated Dart class to be [`freezed`](https://pub.dev/packages/freezed) (which is like data-classes in other languages like Kotlin), simply put `#[frb(dart_metadata=("freezed"))]` and it will generate everything needed for you.
如果你想让生成的 Dart 类是 [`freezed`](https://pub.dev/packages/freezed)的(类似于 Kotlin 中的
data-classes),只需要在结构体前添加 `#[frb(dart_metadata=("freezed"))]`,它会为你生成需要的东西。

## Example
## 示例

### Example 1: Recursive fields
### Example 1: 递归字段

```rust,noplayground
pub struct MyTreeNode {
Expand All @@ -39,7 +57,7 @@ pub struct MyTreeNode {
}
```

Becomes:
转换为:

```Dart
class MyTreeNode {
Expand All @@ -49,7 +67,7 @@ class MyTreeNode {
}
```

Remark: If you are curious about `Future`, have a look at [this](async_dart.md).
注意:如果你想了解 `Future` , 看看这里 [async_dart](async_dart.md).

### Example 2: Metadata

Expand All @@ -60,7 +78,7 @@ pub struct UserId {
}
```

Becomes:
转换为:

```dart
import 'package:meta/meta.dart' as meta;
Expand All @@ -72,4 +90,4 @@ class UserId with _$UserId {
required int value,
}) = _UserId;
}
```
```
19 changes: 11 additions & 8 deletions src/feature/lang_vec.md
Original file line number Diff line number Diff line change
@@ -1,28 +1,31 @@
# Vec and array
# Vec and 数组

## `Vec<u8>`, `Vec<i8>`, ...

In Dart, when you want to express a long byte array such as a big image or some binary blob, people normally use `Uint8List` instead of `List<int>` since the former is much performant. `flutter_rust_bridge` takes this into consideration for you. When you have `Vec<u8>` (or `Vec<i8>`, or `Vec<i32>`, etc), it will be translated it into `Uint8List` or its friends.
在 Dart 中,当你想表达一个长字节数组,例如大图片或一些二进制 blob,人们通常会使用 `Uint8List` 而不是
`List<int>`,因为前者的性能更好。

`flutter_rust_bridge` 也为你考虑到了这一点。当你使用到 `Vec<u8>`(或
`Vec<i8>``Vec<i32>`,等)时,它将被翻译成 `Uint8List` 或其它类似的结构。

## `Vec<T>`

When you have normal `Vec<T>` for `T` types other than `u8`, `i8` etc, it will be converted to normal `List<T>`.
当你使用 `Vec<T>`,并且 T 是 `u8``i8` 等以外的类型时,它将被转换成正常的 `List<T>`

## `[T; N]`

Since Dart does not have special treatment for static-sized arrays, it is converted to `List<T>` as well.
由于 Dart 没有对静态大小的数组进行特殊处理,所以它也会被转换为 `List<T>`

## Example
## 例子

```rust,noplayground
pub fn draw_tree(tree: Vec<TreeNode>) -> Vec<u8> { ... }
```

Becomes:
转换为:

```Dart
Future<Uint8List> drawTree({required List<TreeNode> tree});
```

Remark: If you are curious about `Future`, have a look at [this](async_dart.md).

注意:如果你对 `Future` 感兴趣,请看 [这里](async_dart.md).

0 comments on commit 6b29ac5

Please sign in to comment.