rust_in_flutter 1.0.3 copy "rust_in_flutter: ^1.0.3" to clipboard
rust_in_flutter: ^1.0.3 copied to clipboard

discontinuedreplaced by: rinf

Easily integrate Rust to make your Flutter app blazingly fast!

πŸ†Ž About #

Easily integrate Rust to make your Flutter app blazingly fast!

preview

This high-level wrapper package simplifies Rust integration for your Flutter app without the need for code generation or native tooling. Designed with ease of use, future scalability, and exceptional performance in mind, it handles all the complicated aspects behind the scenes. Simply add this package to your Flutter project and you're ready to write Rust!

Benefits #

  • Rust integration with the ability to use an arbitrary number of library crates
  • RESTful API with easy request from Dart and response from Rust
  • Async interaction with no blocking
  • Streaming from Rust to Dart
  • Restarting Rust logic on Dart's hot restart
  • No memory copy when sending data
  • No complicated code generation during development
  • No messing with various native files in your project

Platform Support #

With this package, you don't have to start from scratch or face the challenging complexity of integrating Rust.

  • βœ… Linux: Tested and supported
  • βœ… Android: Tested and supported
  • βœ… Windows: Tested and supported
  • βœ… macOS: Tested and supported
  • βœ… iOS: Tested and supported
  • ⏸️ Web: Not now but considered

If you have any suggestions or want to report a bug, please leave it as an issue or a pull request. We will try to respond as quickly as possible.

πŸ‘œ Installing #

Basic Steps #

First, add this package to your Flutter project.

flutter pub add rust_in_flutter

Then install Rust toolchain. Refer to the official Rust docs.

Extra Steps #

If you are planning to compile your code for Linux, Windows, macOS, or iOS, you don't have to do anything more.

For Android, install Android NDK. You must select the exact expected NDK version from your Flutter project, which can be seen in your ./android/app/build.gradle file or here.

Using extra build targets with Rust can sometimes present various issues. If you encounter any problems, feel free to visit the discussions page and open a Q&A thread for assistance.

πŸ‘œ Applying Rust #

Simply run this in the command-line. Make sure that the current directory of the terminal is your Flutter project folder.

dart run rust_in_flutter:apply_rust

Once you've run the command, there will be some new folders and files that will be your Rust code's starting point.

    my_flutter_project/
    β”œβ”€β”€ android/
    β”œβ”€β”€ ios/
    β”œβ”€β”€ lib/
    β”œβ”€β”€ linux/
+   β”œβ”€β”€ native/
+   β”‚   β”œβ”€β”€ hub/
+   β”‚   β”œβ”€β”€ sample_crate/
+   β”‚   └── README.md
    β”œβ”€β”€ test/
    β”œβ”€β”€ web/
    β”œβ”€β”€ windows/
*   β”œβ”€β”€ .gitignore
+   β”œβ”€β”€ Cargo.toml
    β”œβ”€β”€ pubspec.yaml
    └── ...

Entry point of your Rust logic is the hub library crate. You might want to remove sample_crate in production.

Please keep in mind:

  • Do NOT change the name of the hub crate or the native folder. Compilation presets expect the entry library crate to be located at ./native/hub.
  • Do NOT modify the bridge module inside ./native/hub/src.
  • You CAN name crates other than hub as you want.

Now by heading over to ./native/hub/src/lib.rs, you can start writing Rust!

🧱 Tips #

When requesting from Dart, you provide operation and address. This way of communication follows the definition of RESTful API.

void someFunction() async {
    var request = RustRequest(
      address: 'basicCategory.counterNumber',
      operation: Operation.Read,
      bytes: serialize(
        {
          'letter': 'Hello from Dart!',
          'before_number': 888,
          'dummy_one': 1,
          'dummy_two': 2,
          'dummy_three': [3, 4, 5]
        },
      ),
    );

    var response = await requestToRust(request);
    var message = deserialize(response.bytes) as Map;
    var innerValue = message['after_number'] as int;
}

Upon receiving requests from Rust, you first classify them by address.

pub async fn handle_request(request_unique: RustRequestUnique) {
    let request = request_unique.request;
    let interaction_id = request_unique.id;

    let layered: Vec<&str> = request.address.split('.').collect();
    let response = if layered.is_empty() {
        RustResponse::default()
    } else if layered[0] == "basicCategory" {
        if layered.len() == 1 {
            RustResponse::default()
        } else if layered[1] == "counterNumber" {
            sample_functions::calculate_something(request).await
        } else {
            RustResponse::default()
        }
    } else {
        RustResponse::default()
    };

    let response_unique = RustResponseUnique {
        id: interaction_id,
        response,
    };
    respond_to_dart(response_unique);
}

Handling requests in Rust is as follows. Message schema is defined here because it because it will be different by address and operation type.

pub async fn calculate_something(request: RustRequest) -> RustResponse {
    match request.operation {
        Operation::Create => RustResponse::default(),
        Operation::Read => {
            #[allow(dead_code)]
            #[derive(Deserialize)]
            struct RustRequestSchema {
                letter: String,
                before_number: i32,
                dummy_one: i32,
                dummy_two: i32,
                dummy_three: Vec<i32>,
            }
            let slice = request.bytes.as_slice();
            let received: RustRequestSchema = from_slice(slice).unwrap();
            println!("{:?}", received.letter);

            let before_value = received.before_number;
            let after_value = sample_crate::add_seven(before_value);

            #[derive(Serialize)]
            struct RustResponseSchema {
                after_number: i32,
                dummy_one: i32,
                dummy_two: i32,
                dummy_three: Vec<i32>,
            }
            RustResponse {
                successful: true,
                bytes: to_vec_named(&RustResponseSchema {
                    after_number: after_value,
                    dummy_one: 1,
                    dummy_two: 2,
                    dummy_three: vec![3, 4, 5],
                })
                .unwrap(),
            }
        }
        Operation::Update => RustResponse::default(),
        Operation::Delete => RustResponse::default(),
    }
}

You can extend this RESTful API pattern and create hundreds and thousands of endpoints as you need. If you have a web background, this system might look familiar to you. More comments and details are included in the actual code inside the Rust template.

Ideally, Flutter would deal with the cross-platform user interface while Rust handles the business logic. The front-end and back-end can be completely separated, meaning that Dart and Rust codes are detachable from each other. These two worlds communicate through channels and streams.

Use MessagePack for serializing messages sent between Dart and Rust as provided by the Rust template, unless you have other reasons not to do so. For those who aren't familiar, MessagePack is a nested binary structure similar to JSON, but much faster and more efficient.

Data being sent between Dart and Rust are basically bytes arrays, represented as Uint8List in Dart and Vec<u8> in Rust. Though using MessagePack serialization is recommended, you can send any kind of bytes data as you wish, such as a high-resolution image or some kind of file data.

β˜• Support Us #

πŸ˜‰ If you are benefiting from the features of Rust-In-Flutter and find it helpful, why not consider supporting this project? Your generous donations contribute to the maintenance and development of Rust-In-Flutter, ensuring its continuous improvement and growth.

If you feel like so, please consider buying us a coffee.

πŸŒ‹ Pioneers #

This project was not done alone. There were various helpful projects that gave inspiration to the structure of this package. Credits to these wonderful efforts!

46
likes
0
pub points
8%
popularity

Publisher

verified publishercunarist.com

Easily integrate Rust to make your Flutter app blazingly fast!

Repository (GitHub)
View/report issues

Funding

Consider supporting this project:

www.buymeacoffee.com

License

unknown (LICENSE)

Dependencies

ffi, flutter, flutter_rust_bridge, meta, package_config, path, plugin_platform_interface, uuid

More

Packages that depend on rust_in_flutter