Skip to content

Commit

Permalink
tada: init project
Browse files Browse the repository at this point in the history
Signed-off-by: trdthg <trdthg@outlook.com>
  • Loading branch information
trdthg committed Aug 22, 2022
0 parents commit 47573c3
Show file tree
Hide file tree
Showing 84 changed files with 3,343 additions and 0 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
book
6 changes: 6 additions & 0 deletions book.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[book]
authors = ["authors of flutter_rust_bridge, see GitHub README.md for detailed contributions"]
language = "en"
multilingual = false
src = "src"
title = "flutter_rust_bridge"
Binary file added logo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added logo.xcf
Binary file not shown.
84 changes: 84 additions & 0 deletions src/SUMMARY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
# Summary

[介绍](index.md)

# Part I: 核心

- [🧭 快速开始](quickstart.md)
- [📚 教程:一个 Flutter 和 Rust 构建的 app](tutorial_with_flutter.md)
- [🎼 特性](feature.md)
- [语言转换](feature/lang.md)
- [对应关系总览](feature/lang_simple.md)
- [Vec 和 数组](feature/lang_vec.md)
- [结构体](feature/lang_struct.md)
- [枚举](feature/lang_enum.md)
- [外部类型](feature/lang_external.md)
- [Option](feature/lang_option.md)
- [方法](feature/lang_methods.md)
- [返回值类型](feature/lang_return_types.md)
- [零拷贝](feature/zero_copy.md)
- [流 / 迭代器](feature/stream.md)
- [Dart 异步](feature/async_dart.md)
- [Dart 同步](feature/sync_dart.md)
- [并发](feature/concurrency.md)
- [Handler](feature/handler.md)
- [初始化](feature/init.md)
- [Rust 异步](feature/async_rust.md)
- [多文件](feature/multiple_files.md)
- [在 build.rs 中运行](feature/build_rs.md)
- [可取消的任务](feature/cancelable_task.md)
- [对象池](feature/object_pool.md)
- [杂项](feature/misc.md)

# Part II: 用户指南

- [从模板创建](template.md)
- [创建一个新项目](template/setup.md)
- [安卓设置](template/setup_android.md)
- [IOS 设置](template/setup_ios.md)
- [Web 设置](template/setup_web.md)
- [Windows 和 Linux](template/setup_desktop.md)
- [其他平台](template/setup_others.md)
- [模板之旅](template/tour.md)
- [native/src/api.rs](template/tour_api.md)
- [`android/app/build.gradle`](template/tour_gradle.md)
- [`native/native.xcodeproj`](template/tour_native_proj.md)
- [`justfile`](template/tour_justfile.md)
- [`rust.cmake`](template/tour_cmake.md)
- [代码生成](template/generate.md)
- [安装 codegen](template/generate_install.md)
- [添加代码](template/generate_adding_code.md)
- [使用 build_runner](template/generate_build_runner.md)
- [收尾工作](template/generate_finish.md)
- [集成到现有项目](integrate.md)
- [创建一个新 crate](integrate/new_crate.md)
- [安装依赖](integrate/deps.md)
- [与 Android 集成](integrate/android.md)
- [Hooking onto tasks](integrate/android_tasks.md)
- [在 Gradle 中使用 CMake](integrate/android_cmake.md)
- [与 iOS/MacOS 集成](integrate/ios.md)
- [创建 Rust 项目](integrate/ios_proj.md)
- [链接该项目](integrate/ios_linking.md)
- [生成代码绑定](integrate/ios_gen.md)
- [使用假头文件](integrate/ios_headers.md)
- [与 Windows and Linux 集成](integrate/desktop.md)
- [与 Web 集成](integrate/web.md)
- [使用动态连接库](integrate/usage.md)
- [收尾工作](integrate/finish.md)

# Part III: 贡献指南

- [总览](contributing/overview.md)
- [整体设计](contributing/design.md)
- [附录](contributing/appendix.md)

# Part IV: 更多文档

- [教程:Pure Dart](tutorial_pure_dart.md)
- [安全问题](safety.md)
- [疑难解答](troubleshooting.md)
- [命令行参数](command_line.md)
- [从零开始设置 Fluuter/Rust 环境](set_up_from_scratch.md)
- [文章](article.md)
- [Rust 异步](article/async_in_rust.md)
- [生成多文件](article/generate_multiple_files.md)
4 changes: 4 additions & 0 deletions src/article.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Articles

This chapter contains some articles related to `flutter_rust_bridge`.

128 changes: 128 additions & 0 deletions src/article/async_in_rust.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
# Async in Rust

> Author: @AlienKevin
This library does not yet support returning a Future type from Rust and this has to do with the difficulty of uniting the various approaches to async in Rust. The [Rust Book](https://rust-lang.github.io/async-book/01_getting_started/03_state_of_async_rust.html#language-and-library-support) summarized the current state of async support succinctly:
> The most fundamental traits, types and functions, such as the Future trait are provided by the standard library. The async/await syntax is supported directly by the Rust compiler.
> Many utility types, macros and functions are provided by the futures crate. They can be used in any async Rust application.
> Execution of async code, IO and task spawning are provided by "async runtimes", such as Tokio and async-std. Most async applications, and some async crates, depend on a specific runtime.
While the futures crate provides an executor called `futures::executor::block_on`, libraries that use Tokio runtime cannot use this executor. According to [Rust-lang community wiki](https://runrust.miraheze.org/wiki/Async_crate_comparison), crates like Tokio that provide both a runtime and IO abstractions often have their IO depend on the runtime. This can make it difficult to write runtime-agnostic code. First, we demonstrate a common use case of async programming in Rust by attempting to fetch the content of a file from the internet using the popular HTTP Client [Reqwest](https://docs.rs/reqwest/0.11.6/reqwest/):

```rust,ignore
use anyhow;
async fn get() -> anyhow::Result<String> {
let url = "https://link/to/file/download";
let data = reqwest::get(url).await?.text().await?;
Ok(data)
}
```

When you try to generate bindings for the `get` function, the generated code will contain errors because this library does not support returning Future from Rust.

## Mismatched runtime
The next logic thing to try would be to convert the asynchronous code to synchronous by directly blocking the current thread and execute the code. For our first attempt, we wrap `futures::executor::block_on` around an async block containing reqwest calls.

```rust,ignore
use anyhow;
use futures::executor::block_on;
fn get() -> anyhow::Result<String> {
block_on(async {
let url = "https://link/to/file/download";
let data = reqwest::get(url).await?.text().await?;
Ok(data)
})
}
```

Since Reqwest uses the Tokio runtime instead of the futures runtime, our code panicked with the error "there is no reactor running, must be called from the context of a Tokio 1.x runtime". To fix this error, we have two ways to execute async codes using the Tokio runtime. Approach 1 is the simplest and uses the convenient [`tokio::main`](https://docs.rs/tokio/1.14.0/tokio/attr.main.html) macro to turn an async function to a synchronous one. Approach 2 requires you to explicitly create a new Tokio runtime and use its block_on function to run the future to completion.

## Approach 1 (macro)
```rust,ignore
use anyhow;
#[tokio::main(flavor = "current_thread")]
async fn get() -> anyhow::Result<String> {
let url = "https://link/to/file/download";
let data = reqwest::get(url).await?.text().await?;
Ok(data)
}
```
It has the following dependencies:
```toml
[dependencies]
futures = "0.3"
reqwest = "0.11.6"
tokio = { version = "1.14.0", features = ["rt", "macros"] }
anyhow = { version = "1.0.49" }
```

## Approach 2 (runtime)
```rust,ignore
use anyhow;
use tokio::runtime::Runtime;
fn get() -> anyhow::Result<String> {
let rt = Runtime::new().unwrap();
rt.block_on(async {
let url = "https://link/to/file/download";
let data = reqwest::get(url).await?.text().await?;
Ok(data)
})
}
```
It has the following dependencies:
```toml
[dependencies]
futures = "0.3"
reqwest = "0.11.6"
tokio = { version = "1.14.0", features = ["rt-multi-thread"] }
anyhow = { version = "1.0.49" }
```

## Plain futures
If you are using the plain futures crate without runtimes like Tokio, you should be safe to wrap the asynchronous code in an async block and use the [`futures::executor::block_on`](https://docs.rs/futures/0.3.18/futures/executor/fn.block_on.html) to run the future to completion:

```rust,ignore
use futures::executor::block_on;
async fn hello_world() -> String {
"hello, world!".to_string()
}
fn get() -> String {
block_on(async {
hello_world().await
})
}
fn main() {
println!("{}", get()); // prints "hello, world!"
}
```

## Avoid async
Lastly, you can avoid async code all together by using synchronously/blocking version of the functions if they are available. In Reqwest, there's a module called `reqwest::blocking` designed specifically for this purpose. So you can achieve the same thing above without using async.

```rust,ignore
use anyhow;
use reqwest;
fn get() -> anyhow::Result<String> {
let url = "https://link/to/file/download";
let data = reqwest::blocking::get(url)?.text()?;
Ok(data)
}
```
It has the following dependencies:
```toml
[dependencies]
futures = "0.3"
reqwest = { version = "0.11.6", features = ["blocking"] }
anyhow = { version = "1.0.49" }
```

Loading

0 comments on commit 47573c3

Please sign in to comment.