├── flutter_package
├── example
│ ├── linux
│ │ ├── .gitignore
│ │ ├── runner
│ │ │ ├── main.cc
│ │ │ ├── my_application.h
│ │ │ └── CMakeLists.txt
│ │ └── flutter
│ │ │ ├── generated_plugin_registrant.cc
│ │ │ ├── generated_plugin_registrant.h
│ │ │ └── generated_plugins.cmake
│ ├── ios
│ │ ├── Runner
│ │ │ ├── Runner-Bridging-Header.h
│ │ │ ├── Assets.xcassets
│ │ │ │ ├── LaunchImage.imageset
│ │ │ │ │ ├── LaunchImage.png
│ │ │ │ │ ├── LaunchImage@2x.png
│ │ │ │ │ ├── LaunchImage@3x.png
│ │ │ │ │ ├── README.md
│ │ │ │ │ └── Contents.json
│ │ │ │ └── AppIcon.appiconset
│ │ │ │ │ ├── Icon-App-20x20@1x.png
│ │ │ │ │ ├── Icon-App-20x20@2x.png
│ │ │ │ │ ├── Icon-App-20x20@3x.png
│ │ │ │ │ ├── Icon-App-29x29@1x.png
│ │ │ │ │ ├── Icon-App-29x29@2x.png
│ │ │ │ │ ├── Icon-App-29x29@3x.png
│ │ │ │ │ ├── Icon-App-40x40@1x.png
│ │ │ │ │ ├── Icon-App-40x40@2x.png
│ │ │ │ │ ├── Icon-App-40x40@3x.png
│ │ │ │ │ ├── Icon-App-60x60@2x.png
│ │ │ │ │ ├── Icon-App-60x60@3x.png
│ │ │ │ │ ├── Icon-App-76x76@1x.png
│ │ │ │ │ ├── Icon-App-76x76@2x.png
│ │ │ │ │ ├── Icon-App-1024x1024@1x.png
│ │ │ │ │ └── Icon-App-83.5x83.5@2x.png
│ │ │ ├── AppDelegate.swift
│ │ │ ├── Base.lproj
│ │ │ │ ├── Main.storyboard
│ │ │ │ └── LaunchScreen.storyboard
│ │ │ └── Info.plist
│ │ ├── Flutter
│ │ │ ├── Debug.xcconfig
│ │ │ ├── Release.xcconfig
│ │ │ └── AppFrameworkInfo.plist
│ │ ├── Runner.xcodeproj
│ │ │ └── project.xcworkspace
│ │ │ │ ├── contents.xcworkspacedata
│ │ │ │ └── xcshareddata
│ │ │ │ ├── WorkspaceSettings.xcsettings
│ │ │ │ └── IDEWorkspaceChecks.plist
│ │ ├── Runner.xcworkspace
│ │ │ ├── contents.xcworkspacedata
│ │ │ └── xcshareddata
│ │ │ │ ├── WorkspaceSettings.xcsettings
│ │ │ │ └── IDEWorkspaceChecks.plist
│ │ ├── RunnerTests
│ │ │ └── RunnerTests.swift
│ │ ├── .gitignore
│ │ └── Podfile
│ ├── web
│ │ ├── favicon.png
│ │ ├── icons
│ │ │ ├── Icon-192.png
│ │ │ ├── Icon-512.png
│ │ │ ├── Icon-maskable-192.png
│ │ │ └── Icon-maskable-512.png
│ │ ├── manifest.json
│ │ └── index.html
│ ├── macos
│ │ ├── Runner
│ │ │ ├── Configs
│ │ │ │ ├── Debug.xcconfig
│ │ │ │ ├── Release.xcconfig
│ │ │ │ ├── Warnings.xcconfig
│ │ │ │ └── AppInfo.xcconfig
│ │ │ ├── Assets.xcassets
│ │ │ │ └── AppIcon.appiconset
│ │ │ │ │ ├── app_icon_16.png
│ │ │ │ │ ├── app_icon_32.png
│ │ │ │ │ ├── app_icon_64.png
│ │ │ │ │ ├── app_icon_1024.png
│ │ │ │ │ ├── app_icon_128.png
│ │ │ │ │ ├── app_icon_256.png
│ │ │ │ │ ├── app_icon_512.png
│ │ │ │ │ └── Contents.json
│ │ │ ├── Release.entitlements
│ │ │ ├── AppDelegate.swift
│ │ │ ├── DebugProfile.entitlements
│ │ │ ├── MainFlutterWindow.swift
│ │ │ └── Info.plist
│ │ ├── .gitignore
│ │ ├── Flutter
│ │ │ ├── Flutter-Debug.xcconfig
│ │ │ ├── Flutter-Release.xcconfig
│ │ │ └── GeneratedPluginRegistrant.swift
│ │ ├── Runner.xcworkspace
│ │ │ ├── contents.xcworkspacedata
│ │ │ └── xcshareddata
│ │ │ │ └── IDEWorkspaceChecks.plist
│ │ ├── Runner.xcodeproj
│ │ │ └── project.xcworkspace
│ │ │ │ └── xcshareddata
│ │ │ │ └── IDEWorkspaceChecks.plist
│ │ ├── RunnerTests
│ │ │ └── RunnerTests.swift
│ │ └── Podfile
│ ├── windows
│ │ ├── runner
│ │ │ ├── resources
│ │ │ │ └── app_icon.ico
│ │ │ ├── resource.h
│ │ │ ├── runner.exe.manifest
│ │ │ ├── utils.h
│ │ │ ├── flutter_window.h
│ │ │ ├── main.cpp
│ │ │ ├── CMakeLists.txt
│ │ │ ├── utils.cpp
│ │ │ └── flutter_window.cpp
│ │ ├── flutter
│ │ │ ├── generated_plugin_registrant.cc
│ │ │ ├── generated_plugin_registrant.h
│ │ │ └── generated_plugins.cmake
│ │ └── .gitignore
│ ├── android
│ │ ├── app
│ │ │ ├── src
│ │ │ │ ├── main
│ │ │ │ │ ├── res
│ │ │ │ │ │ ├── mipmap-hdpi
│ │ │ │ │ │ │ └── ic_launcher.png
│ │ │ │ │ │ ├── mipmap-mdpi
│ │ │ │ │ │ │ └── ic_launcher.png
│ │ │ │ │ │ ├── mipmap-xhdpi
│ │ │ │ │ │ │ └── ic_launcher.png
│ │ │ │ │ │ ├── mipmap-xxhdpi
│ │ │ │ │ │ │ └── ic_launcher.png
│ │ │ │ │ │ ├── mipmap-xxxhdpi
│ │ │ │ │ │ │ └── ic_launcher.png
│ │ │ │ │ │ ├── drawable
│ │ │ │ │ │ │ └── launch_background.xml
│ │ │ │ │ │ ├── drawable-v21
│ │ │ │ │ │ │ └── launch_background.xml
│ │ │ │ │ │ ├── values
│ │ │ │ │ │ │ └── styles.xml
│ │ │ │ │ │ └── values-night
│ │ │ │ │ │ │ └── styles.xml
│ │ │ │ │ ├── kotlin
│ │ │ │ │ │ └── com
│ │ │ │ │ │ │ └── example
│ │ │ │ │ │ │ └── example_app
│ │ │ │ │ │ │ └── MainActivity.kt
│ │ │ │ │ └── AndroidManifest.xml
│ │ │ │ ├── debug
│ │ │ │ │ └── AndroidManifest.xml
│ │ │ │ └── profile
│ │ │ │ │ └── AndroidManifest.xml
│ │ │ └── build.gradle.kts
│ │ ├── gradle.properties
│ │ ├── gradle
│ │ │ └── wrapper
│ │ │ │ └── gradle-wrapper.properties
│ │ ├── .gitignore
│ │ ├── build.gradle.kts
│ │ └── settings.gradle.kts
│ ├── native
│ │ ├── hub
│ │ │ ├── src
│ │ │ │ ├── signals
│ │ │ │ │ ├── mod.rs
│ │ │ │ │ ├── fractal_art.rs
│ │ │ │ │ ├── app_control.rs
│ │ │ │ │ └── counter_number.rs
│ │ │ │ ├── lib.rs
│ │ │ │ └── actors
│ │ │ │ │ ├── mod.rs
│ │ │ │ │ └── counting.rs
│ │ │ └── Cargo.toml
│ │ ├── sample_crate
│ │ │ ├── src
│ │ │ │ ├── lib.rs
│ │ │ │ ├── error.rs
│ │ │ │ └── extras.rs
│ │ │ └── Cargo.toml
│ │ └── README.md
│ ├── pubspec.yaml
│ ├── .gitignore
│ ├── README.md
│ ├── test
│ │ └── complex_signal_test.dart
│ └── .metadata
├── android
│ ├── settings.gradle
│ ├── src
│ │ └── main
│ │ │ └── AndroidManifest.xml
│ ├── .gitignore
│ └── build.gradle
├── lib
│ ├── src
│ │ ├── interface.dart
│ │ ├── structure.dart
│ │ ├── interface_web.dart
│ │ ├── interface_os.dart
│ │ └── load_web.dart
│ └── rinf.dart
├── analysis_options.yaml
├── cargokit
│ ├── build_tool
│ │ ├── README.md
│ │ ├── bin
│ │ │ └── build_tool.dart
│ │ ├── lib
│ │ │ ├── build_tool.dart
│ │ │ └── src
│ │ │ │ ├── build_cmake.dart
│ │ │ │ ├── logging.dart
│ │ │ │ ├── cargo.dart
│ │ │ │ ├── build_gradle.dart
│ │ │ │ ├── environment.dart
│ │ │ │ └── verify_binaries.dart
│ │ ├── test
│ │ │ ├── cargo_test.dart
│ │ │ ├── builder_test.dart
│ │ │ ├── rustup_test.dart
│ │ │ └── options_test.dart
│ │ ├── pubspec.yaml
│ │ └── analysis_options.yaml
│ ├── README
│ ├── cmake
│ │ └── resolve_symlinks.ps1
│ ├── .github
│ │ └── workflows
│ │ │ └── check_and_lint.yml
│ ├── LICENSE
│ ├── build_pod.sh
│ └── run_build_tool.cmd
├── ios
│ ├── Classes
│ │ └── rinf.c
│ └── rinf.podspec
├── macos
│ ├── Classes
│ │ └── rinf.c
│ └── rinf.podspec
├── windows
│ ├── .gitignore
│ ├── rust.cmake
│ └── CMakeLists.txt
├── elinux
│ ├── rust.cmake
│ └── CMakeLists.txt
├── linux
│ ├── rust.cmake
│ └── CMakeLists.txt
├── src
│ ├── CMakeLists.txt
│ ├── rinf.c
│ └── rinf.h
├── LICENSE
└── pubspec.yaml
├── .dockerignore
├── demo
├── __init__.py
├── server.py
└── Dockerfile
├── documentation
├── __init__.py
├── source
│ ├── __init__.py
│ ├── _static
│ │ ├── logo.png
│ │ ├── preview.webp
│ │ ├── rust_icon.png
│ │ ├── rinf_design.png
│ │ └── flutter_icon.svg
│ ├── _templates
│ │ ├── icon_pair.html
│ │ └── landing.html
│ ├── index.md
│ ├── printing-for-debugging.md
│ ├── field-types.md
│ ├── contribution.md
│ ├── installing-components.md
│ ├── conf.py
│ ├── field-attributes.md
│ ├── introduction.md
│ ├── configuration.md
│ ├── unit-testing.md
│ ├── applying-template.md
│ ├── graceful-shutdown.md
│ └── running-and-building.md
├── pyproject.toml
├── README.md
├── server.py
└── Dockerfile
├── automate
├── __init__.py
└── pyproject.toml
├── .rustfmt.toml
├── rust_crate_cli
├── src
│ ├── lib.rs
│ ├── bin
│ │ └── main.rs
│ └── tool
│ │ ├── mod.rs
│ │ ├── server.rs
│ │ ├── common.rs
│ │ └── config.rs
├── template
│ ├── Cargo.toml.template
│ └── native
│ │ ├── README.md
│ │ └── hub
│ │ ├── src
│ │ ├── signals
│ │ │ └── mod.rs
│ │ ├── lib.rs
│ │ └── actors
│ │ │ ├── second.rs
│ │ │ ├── mod.rs
│ │ │ └── first.rs
│ │ └── Cargo.toml.template
└── Cargo.toml
├── .vscode
└── settings.json
├── compose.yaml
├── .github
├── pull_request_template.md
├── dependabot.yaml
├── ISSUE_TEMPLATE
│ ├── task.md
│ └── bug-report.md
└── workflows
│ ├── registry_push.yaml
│ └── publication.yaml
├── Cargo.toml
├── pyproject.toml
├── rust_crate_proc
└── Cargo.toml
├── .gitignore
├── rust_crate
├── src
│ ├── traits.rs
│ ├── lib.rs
│ ├── error.rs
│ ├── interface_web.rs
│ ├── macros.rs
│ └── interface.rs
└── Cargo.toml
└── LICENSE
/flutter_package/example/linux/.gitignore:
--------------------------------------------------------------------------------
1 | flutter/ephemeral
2 |
--------------------------------------------------------------------------------
/.dockerignore:
--------------------------------------------------------------------------------
1 | .git/
2 | **/target/
3 | **/dist/
4 | **/build/
5 |
--------------------------------------------------------------------------------
/demo/__init__.py:
--------------------------------------------------------------------------------
1 | """A demo web application made with Rinf."""
2 |
--------------------------------------------------------------------------------
/documentation/__init__.py:
--------------------------------------------------------------------------------
1 | """Documentation package for Rinf."""
2 |
--------------------------------------------------------------------------------
/automate/__init__.py:
--------------------------------------------------------------------------------
1 | """Automation package for Rinf project tasks."""
2 |
--------------------------------------------------------------------------------
/flutter_package/android/settings.gradle:
--------------------------------------------------------------------------------
1 | rootProject.name = 'rinf'
2 |
--------------------------------------------------------------------------------
/.rustfmt.toml:
--------------------------------------------------------------------------------
1 | style_edition = "2024"
2 | max_width = 80
3 | tab_spaces = 2
4 |
--------------------------------------------------------------------------------
/documentation/source/__init__.py:
--------------------------------------------------------------------------------
1 | """Documentation source files for Rinf."""
2 |
--------------------------------------------------------------------------------
/rust_crate_cli/src/lib.rs:
--------------------------------------------------------------------------------
1 | mod tool;
2 |
3 | pub use tool::{SetupError, run_command};
4 |
--------------------------------------------------------------------------------
/flutter_package/example/ios/Runner/Runner-Bridging-Header.h:
--------------------------------------------------------------------------------
1 | #import "GeneratedPluginRegistrant.h"
2 |
--------------------------------------------------------------------------------
/automate/pyproject.toml:
--------------------------------------------------------------------------------
1 | [project]
2 | name = "automate"
3 | version = "0.1.0"
4 | requires-python = ">=3.13"
5 |
--------------------------------------------------------------------------------
/documentation/source/_static/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cunarist/rinf/HEAD/documentation/source/_static/logo.png
--------------------------------------------------------------------------------
/flutter_package/lib/src/interface.dart:
--------------------------------------------------------------------------------
1 | export 'interface_os.dart' if (dart.library.js_interop) 'interface_web.dart';
2 |
--------------------------------------------------------------------------------
/flutter_package/example/web/favicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cunarist/rinf/HEAD/flutter_package/example/web/favicon.png
--------------------------------------------------------------------------------
/documentation/source/_static/preview.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cunarist/rinf/HEAD/documentation/source/_static/preview.webp
--------------------------------------------------------------------------------
/documentation/source/_static/rust_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cunarist/rinf/HEAD/documentation/source/_static/rust_icon.png
--------------------------------------------------------------------------------
/documentation/source/_static/rinf_design.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cunarist/rinf/HEAD/documentation/source/_static/rinf_design.png
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "rust-analyzer.linkedProjects": [
3 | "./Cargo.toml",
4 | "./rust_crate_cli/Cargo.toml"
5 | ]
6 | }
7 |
--------------------------------------------------------------------------------
/flutter_package/example/web/icons/Icon-192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cunarist/rinf/HEAD/flutter_package/example/web/icons/Icon-192.png
--------------------------------------------------------------------------------
/flutter_package/example/web/icons/Icon-512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cunarist/rinf/HEAD/flutter_package/example/web/icons/Icon-512.png
--------------------------------------------------------------------------------
/flutter_package/example/macos/Runner/Configs/Debug.xcconfig:
--------------------------------------------------------------------------------
1 | #include "../../Flutter/Flutter-Debug.xcconfig"
2 | #include "Warnings.xcconfig"
3 |
--------------------------------------------------------------------------------
/flutter_package/example/macos/Runner/Configs/Release.xcconfig:
--------------------------------------------------------------------------------
1 | #include "../../Flutter/Flutter-Release.xcconfig"
2 | #include "Warnings.xcconfig"
3 |
--------------------------------------------------------------------------------
/flutter_package/example/macos/.gitignore:
--------------------------------------------------------------------------------
1 | # Flutter-related
2 | **/Flutter/ephemeral/
3 | **/Pods/
4 |
5 | # Xcode-related
6 | **/dgph
7 | **/xcuserdata/
8 |
--------------------------------------------------------------------------------
/flutter_package/example/web/icons/Icon-maskable-192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cunarist/rinf/HEAD/flutter_package/example/web/icons/Icon-maskable-192.png
--------------------------------------------------------------------------------
/flutter_package/example/web/icons/Icon-maskable-512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cunarist/rinf/HEAD/flutter_package/example/web/icons/Icon-maskable-512.png
--------------------------------------------------------------------------------
/flutter_package/example/ios/Flutter/Debug.xcconfig:
--------------------------------------------------------------------------------
1 | #include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
2 | #include "Generated.xcconfig"
3 |
--------------------------------------------------------------------------------
/flutter_package/example/ios/Flutter/Release.xcconfig:
--------------------------------------------------------------------------------
1 | #include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
2 | #include "Generated.xcconfig"
3 |
--------------------------------------------------------------------------------
/flutter_package/example/windows/runner/resources/app_icon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cunarist/rinf/HEAD/flutter_package/example/windows/runner/resources/app_icon.ico
--------------------------------------------------------------------------------
/flutter_package/analysis_options.yaml:
--------------------------------------------------------------------------------
1 | include: package:flutter_lints/flutter.yaml
2 |
3 | linter:
4 | rules:
5 | prefer_single_quotes: true
6 | avoid_print: false
7 |
--------------------------------------------------------------------------------
/flutter_package/android/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
--------------------------------------------------------------------------------
/flutter_package/cargokit/build_tool/README.md:
--------------------------------------------------------------------------------
1 | A sample command-line application with an entrypoint in `bin/`, library code
2 | in `lib/`, and example unit test in `test/`.
3 |
--------------------------------------------------------------------------------
/flutter_package/android/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | /.idea/workspace.xml
5 | /.idea/libraries
6 | .DS_Store
7 | /build
8 | /captures
9 | .cxx
10 |
--------------------------------------------------------------------------------
/flutter_package/example/macos/Flutter/Flutter-Debug.xcconfig:
--------------------------------------------------------------------------------
1 | #include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
2 | #include "ephemeral/Flutter-Generated.xcconfig"
3 |
--------------------------------------------------------------------------------
/flutter_package/example/macos/Flutter/Flutter-Release.xcconfig:
--------------------------------------------------------------------------------
1 | #include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
2 | #include "ephemeral/Flutter-Generated.xcconfig"
3 |
--------------------------------------------------------------------------------
/flutter_package/ios/Classes/rinf.c:
--------------------------------------------------------------------------------
1 | // Relative import to be able to reuse the C sources.
2 | // See the comment in ../{projectName}}.podspec for more information.
3 | #include "../../src/rinf.c"
4 |
--------------------------------------------------------------------------------
/flutter_package/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cunarist/rinf/HEAD/flutter_package/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/flutter_package/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cunarist/rinf/HEAD/flutter_package/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/flutter_package/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cunarist/rinf/HEAD/flutter_package/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/flutter_package/macos/Classes/rinf.c:
--------------------------------------------------------------------------------
1 | // Relative import to be able to reuse the C sources.
2 | // See the comment in ../{projectName}}.podspec for more information.
3 | #include "../../src/rinf.c"
4 |
--------------------------------------------------------------------------------
/flutter_package/cargokit/build_tool/bin/build_tool.dart:
--------------------------------------------------------------------------------
1 | import 'package:build_tool/build_tool.dart' as build_tool;
2 |
3 | void main(List arguments) {
4 | build_tool.runMain(arguments);
5 | }
6 |
--------------------------------------------------------------------------------
/flutter_package/cargokit/build_tool/lib/build_tool.dart:
--------------------------------------------------------------------------------
1 | import 'src/build_tool.dart' as build_tool;
2 |
3 | Future runMain(List args) async {
4 | return build_tool.runMain(args);
5 | }
6 |
--------------------------------------------------------------------------------
/flutter_package/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cunarist/rinf/HEAD/flutter_package/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/flutter_package/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cunarist/rinf/HEAD/flutter_package/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/flutter_package/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cunarist/rinf/HEAD/flutter_package/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png
--------------------------------------------------------------------------------
/flutter_package/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cunarist/rinf/HEAD/flutter_package/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png
--------------------------------------------------------------------------------
/flutter_package/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cunarist/rinf/HEAD/flutter_package/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png
--------------------------------------------------------------------------------
/flutter_package/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cunarist/rinf/HEAD/flutter_package/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png
--------------------------------------------------------------------------------
/flutter_package/example/android/gradle.properties:
--------------------------------------------------------------------------------
1 | org.gradle.jvmargs=-Xmx8G -XX:MaxMetaspaceSize=4G -XX:ReservedCodeCacheSize=512m -XX:+HeapDumpOnOutOfMemoryError
2 | android.useAndroidX=true
3 | android.enableJetifier=true
4 |
--------------------------------------------------------------------------------
/flutter_package/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cunarist/rinf/HEAD/flutter_package/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png
--------------------------------------------------------------------------------
/flutter_package/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cunarist/rinf/HEAD/flutter_package/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png
--------------------------------------------------------------------------------
/flutter_package/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cunarist/rinf/HEAD/flutter_package/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png
--------------------------------------------------------------------------------
/flutter_package/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cunarist/rinf/HEAD/flutter_package/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png
--------------------------------------------------------------------------------
/flutter_package/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cunarist/rinf/HEAD/flutter_package/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png
--------------------------------------------------------------------------------
/flutter_package/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cunarist/rinf/HEAD/flutter_package/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png
--------------------------------------------------------------------------------
/flutter_package/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cunarist/rinf/HEAD/flutter_package/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png
--------------------------------------------------------------------------------
/flutter_package/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cunarist/rinf/HEAD/flutter_package/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png
--------------------------------------------------------------------------------
/flutter_package/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cunarist/rinf/HEAD/flutter_package/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png
--------------------------------------------------------------------------------
/flutter_package/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cunarist/rinf/HEAD/flutter_package/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png
--------------------------------------------------------------------------------
/flutter_package/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cunarist/rinf/HEAD/flutter_package/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png
--------------------------------------------------------------------------------
/flutter_package/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cunarist/rinf/HEAD/flutter_package/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png
--------------------------------------------------------------------------------
/flutter_package/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cunarist/rinf/HEAD/flutter_package/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png
--------------------------------------------------------------------------------
/flutter_package/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cunarist/rinf/HEAD/flutter_package/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png
--------------------------------------------------------------------------------
/flutter_package/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cunarist/rinf/HEAD/flutter_package/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png
--------------------------------------------------------------------------------
/flutter_package/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cunarist/rinf/HEAD/flutter_package/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png
--------------------------------------------------------------------------------
/flutter_package/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cunarist/rinf/HEAD/flutter_package/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png
--------------------------------------------------------------------------------
/flutter_package/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cunarist/rinf/HEAD/flutter_package/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png
--------------------------------------------------------------------------------
/flutter_package/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cunarist/rinf/HEAD/flutter_package/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png
--------------------------------------------------------------------------------
/flutter_package/example/android/app/src/main/kotlin/com/example/example_app/MainActivity.kt:
--------------------------------------------------------------------------------
1 | package com.example.example_app
2 |
3 | import io.flutter.embedding.android.FlutterActivity
4 |
5 | class MainActivity : FlutterActivity()
6 |
--------------------------------------------------------------------------------
/flutter_package/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cunarist/rinf/HEAD/flutter_package/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png
--------------------------------------------------------------------------------
/flutter_package/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cunarist/rinf/HEAD/flutter_package/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png
--------------------------------------------------------------------------------
/flutter_package/example/linux/runner/main.cc:
--------------------------------------------------------------------------------
1 | #include "my_application.h"
2 |
3 | int main(int argc, char** argv) {
4 | g_autoptr(MyApplication) app = my_application_new();
5 | return g_application_run(G_APPLICATION(app), argc, argv);
6 | }
7 |
--------------------------------------------------------------------------------
/flutter_package/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/flutter_package/example/macos/Flutter/GeneratedPluginRegistrant.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Generated file. Do not edit.
3 | //
4 |
5 | import FlutterMacOS
6 | import Foundation
7 |
8 |
9 | func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
10 | }
11 |
--------------------------------------------------------------------------------
/flutter_package/example/native/hub/src/signals/mod.rs:
--------------------------------------------------------------------------------
1 | mod app_control;
2 | mod complex_types;
3 | mod counter_number;
4 | mod fractal_art;
5 |
6 | pub use app_control::*;
7 | pub use complex_types::*;
8 | pub use counter_number::*;
9 | pub use fractal_art::*;
10 |
--------------------------------------------------------------------------------
/documentation/pyproject.toml:
--------------------------------------------------------------------------------
1 | [project]
2 | name = "documentation"
3 | version = "0.1.0"
4 | requires-python = ">=3.13"
5 | dependencies = [
6 | "Sphinx~=8.2.0",
7 | "furo~=2024.8.6",
8 | "myst-parser~=4.0.1",
9 | "sphinx-autobuild~=2024.10.3",
10 | ]
11 |
--------------------------------------------------------------------------------
/flutter_package/example/linux/flutter/generated_plugin_registrant.cc:
--------------------------------------------------------------------------------
1 | //
2 | // Generated file. Do not edit.
3 | //
4 |
5 | // clang-format off
6 |
7 | #include "generated_plugin_registrant.h"
8 |
9 |
10 | void fl_register_plugins(FlPluginRegistry* registry) {
11 | }
12 |
--------------------------------------------------------------------------------
/rust_crate_cli/template/Cargo.toml.template:
--------------------------------------------------------------------------------
1 | # This file is used for telling Rust-related tools
2 | # where various Rust crates are.
3 | # This also unifies `target` output folder and
4 | # various Rust configurations.
5 |
6 | [workspace]
7 | resolver = "3"
8 | members = ["native/*"]
9 |
--------------------------------------------------------------------------------
/flutter_package/example/windows/flutter/generated_plugin_registrant.cc:
--------------------------------------------------------------------------------
1 | //
2 | // Generated file. Do not edit.
3 | //
4 |
5 | // clang-format off
6 |
7 | #include "generated_plugin_registrant.h"
8 |
9 |
10 | void RegisterPlugins(flutter::PluginRegistry* registry) {
11 | }
12 |
--------------------------------------------------------------------------------
/flutter_package/example/android/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionBase=GRADLE_USER_HOME
2 | distributionPath=wrapper/dists
3 | zipStoreBase=GRADLE_USER_HOME
4 | zipStorePath=wrapper/dists
5 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-all.zip
6 |
--------------------------------------------------------------------------------
/flutter_package/example/native/sample_crate/src/lib.rs:
--------------------------------------------------------------------------------
1 | //! This crate is written for Rinf demonstrations.
2 |
3 | mod error;
4 | mod extras;
5 | mod fractal;
6 |
7 | pub use extras::{fetch_from_web_api, get_current_time, get_hardward_id};
8 | pub use fractal::{ImageInfo, draw_fractal_image};
9 |
--------------------------------------------------------------------------------
/compose.yaml:
--------------------------------------------------------------------------------
1 | services:
2 | docs:
3 | image: registry.cunarist.org/rinf-docs:latest
4 | ports:
5 | - "${PORT}:80"
6 | restart: unless-stopped
7 |
8 | demo:
9 | image: registry.cunarist.org/rinf-demo:latest
10 | ports:
11 | - "${PORT_DEMO}:80"
12 | restart: unless-stopped
13 |
--------------------------------------------------------------------------------
/flutter_package/example/macos/Runner/Release.entitlements:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | com.apple.security.app-sandbox
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/flutter_package/example/ios/Runner.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/flutter_package/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | PreviewsEnabled
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/flutter_package/example/macos/Runner.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/rust_crate_cli/src/bin/main.rs:
--------------------------------------------------------------------------------
1 | use std::process::ExitCode;
2 |
3 | fn main() -> ExitCode {
4 | use owo_colors::OwoColorize;
5 | let result = rinf_cli::run_command();
6 | if let Err(err) = result {
7 | eprintln!("{}", format!("Error: {err}").red());
8 | return ExitCode::FAILURE;
9 | };
10 | ExitCode::SUCCESS
11 | }
12 |
--------------------------------------------------------------------------------
/flutter_package/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/flutter_package/example/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/flutter_package/example/android/.gitignore:
--------------------------------------------------------------------------------
1 | gradle-wrapper.jar
2 | /.gradle
3 | /captures/
4 | /gradlew
5 | /gradlew.bat
6 | /local.properties
7 | GeneratedPluginRegistrant.java
8 | .cxx/
9 |
10 | # Remember to never publicly share your keystore.
11 | # See https://flutter.dev/to/reference-keystore
12 | key.properties
13 | **/*.keystore
14 | **/*.jks
15 |
--------------------------------------------------------------------------------
/flutter_package/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | PreviewsEnabled
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/flutter_package/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/flutter_package/example/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/flutter_package/cargokit/README:
--------------------------------------------------------------------------------
1 | Experimental repository to provide glue for seamlessly integrating cargo build
2 | with flutter plugins and packages.
3 |
4 | See https://matejknopp.com/post/flutter_plugin_in_rust_with_no_prebuilt_binaries/
5 | for a tutorial on how to use Cargokit.
6 |
7 | Example plugin available at https://github.com/irondash/hello_rust_ffi_plugin.
8 |
9 |
--------------------------------------------------------------------------------
/rust_crate_cli/src/tool/mod.rs:
--------------------------------------------------------------------------------
1 | mod common;
2 | mod config;
3 | mod entry;
4 | mod error;
5 | mod generate;
6 | mod server;
7 | mod template;
8 | mod webassembly;
9 |
10 | pub use common::*;
11 | pub use config::*;
12 | pub use entry::*;
13 | pub use error::*;
14 | pub use generate::*;
15 | pub use server::*;
16 | pub use template::*;
17 | pub use webassembly::*;
18 |
--------------------------------------------------------------------------------
/.github/pull_request_template.md:
--------------------------------------------------------------------------------
1 | ## Changes
2 |
3 | _Please mention issues fixed by this PR here, using format "Fixes #(Issue number)"._
4 |
5 | ## Before Committing
6 |
7 | _Please make sure that you've analyzed and formatted the files._
8 |
9 | ```
10 | dart analyze flutter_package --fatal-infos
11 | dart format .
12 | cargo fmt
13 | cargo clippy --fix --allow-dirty
14 | ```
15 |
--------------------------------------------------------------------------------
/flutter_package/example/ios/RunnerTests/RunnerTests.swift:
--------------------------------------------------------------------------------
1 | import Flutter
2 | import UIKit
3 | import XCTest
4 |
5 | class RunnerTests: XCTestCase {
6 |
7 | func testExample() {
8 | // If you add code to the Runner application, consider adding tests here.
9 | // See https://developer.apple.com/documentation/xctest for more information about using XCTest.
10 | }
11 |
12 | }
13 |
--------------------------------------------------------------------------------
/flutter_package/windows/.gitignore:
--------------------------------------------------------------------------------
1 | flutter/
2 |
3 | # Visual Studio user-specific files.
4 | *.suo
5 | *.user
6 | *.userosscache
7 | *.sln.docstates
8 |
9 | # Visual Studio build-related files.
10 | x64/
11 | x86/
12 |
13 | # Visual Studio cache files
14 | # files ending in .cache can be ignored
15 | *.[Cc]ache
16 | # but keep track of directories ending in .cache
17 | !*.[Cc]ache/
18 |
--------------------------------------------------------------------------------
/flutter_package/example/macos/RunnerTests/RunnerTests.swift:
--------------------------------------------------------------------------------
1 | import Cocoa
2 | import FlutterMacOS
3 | import XCTest
4 |
5 | class RunnerTests: XCTestCase {
6 |
7 | func testExample() {
8 | // If you add code to the Runner application, consider adding tests here.
9 | // See https://developer.apple.com/documentation/xctest for more information about using XCTest.
10 | }
11 |
12 | }
13 |
--------------------------------------------------------------------------------
/documentation/source/_templates/icon_pair.html:
--------------------------------------------------------------------------------
1 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/flutter_package/example/windows/.gitignore:
--------------------------------------------------------------------------------
1 | flutter/ephemeral/
2 |
3 | # Visual Studio user-specific files.
4 | *.suo
5 | *.user
6 | *.userosscache
7 | *.sln.docstates
8 |
9 | # Visual Studio build-related files.
10 | x64/
11 | x86/
12 |
13 | # Visual Studio cache files
14 | # files ending in .cache can be ignored
15 | *.[Cc]ache
16 | # but keep track of directories ending in .cache
17 | !*.[Cc]ache/
18 |
--------------------------------------------------------------------------------
/flutter_package/example/macos/Runner/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | import Cocoa
2 | import FlutterMacOS
3 |
4 | @main
5 | class AppDelegate: FlutterAppDelegate {
6 | override func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool {
7 | return true
8 | }
9 |
10 | override func applicationSupportsSecureRestorableState(_ app: NSApplication) -> Bool {
11 | return true
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/flutter_package/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md:
--------------------------------------------------------------------------------
1 | # Launch Screen Assets
2 |
3 | You can customize the launch screen with your own desired assets by replacing the image files in this directory.
4 |
5 | You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images.
6 |
--------------------------------------------------------------------------------
/flutter_package/example/linux/flutter/generated_plugin_registrant.h:
--------------------------------------------------------------------------------
1 | //
2 | // Generated file. Do not edit.
3 | //
4 |
5 | // clang-format off
6 |
7 | #ifndef GENERATED_PLUGIN_REGISTRANT_
8 | #define GENERATED_PLUGIN_REGISTRANT_
9 |
10 | #include
11 |
12 | // Registers Flutter plugins.
13 | void fl_register_plugins(FlPluginRegistry* registry);
14 |
15 | #endif // GENERATED_PLUGIN_REGISTRANT_
16 |
--------------------------------------------------------------------------------
/flutter_package/example/native/hub/src/signals/fractal_art.rs:
--------------------------------------------------------------------------------
1 | use crate::signals::SampleSchema;
2 | use rinf::RustSignalBinary;
3 | use serde::Serialize;
4 |
5 | /// You can add your custom comments like this.
6 | /// The generated Dart classes will have the same comments on them.
7 | #[derive(Serialize, RustSignalBinary)]
8 | pub struct SampleFractal {
9 | pub current_scale: f64,
10 | pub dummy: Option,
11 | }
12 |
--------------------------------------------------------------------------------
/flutter_package/example/windows/flutter/generated_plugin_registrant.h:
--------------------------------------------------------------------------------
1 | //
2 | // Generated file. Do not edit.
3 | //
4 |
5 | // clang-format off
6 |
7 | #ifndef GENERATED_PLUGIN_REGISTRANT_
8 | #define GENERATED_PLUGIN_REGISTRANT_
9 |
10 | #include
11 |
12 | // Registers Flutter plugins.
13 | void RegisterPlugins(flutter::PluginRegistry* registry);
14 |
15 | #endif // GENERATED_PLUGIN_REGISTRANT_
16 |
--------------------------------------------------------------------------------
/flutter_package/example/native/README.md:
--------------------------------------------------------------------------------
1 | # Rust Crates
2 |
3 | This folder contains Rust crates. Entry point of the Rust logic is the `hub` library crate. These crates are integrated and compiled into the Flutter app by the [Rinf](https://rinf.cunarist.org) framework.
4 |
5 | - Do NOT change the name of the `hub` crate. Compilation presets expect the entry library crate to be located at `native/hub`.
6 | - You CAN name crates other than `hub` as you want.
7 |
--------------------------------------------------------------------------------
/flutter_package/example/native/hub/src/signals/app_control.rs:
--------------------------------------------------------------------------------
1 | use rinf::{DartSignal, RustSignal};
2 | use serde::{Deserialize, Serialize};
3 |
4 | #[derive(Deserialize, DartSignal)]
5 | pub struct UnitTestStart;
6 |
7 | #[derive(Serialize, RustSignal)]
8 | pub struct UnitTestEnd;
9 |
10 | #[derive(Serialize, RustSignal)]
11 | pub struct ComplexSignalTestResult(pub bool);
12 |
13 | #[derive(Deserialize, DartSignal)]
14 | pub struct CreateActors;
15 |
--------------------------------------------------------------------------------
/rust_crate_cli/template/native/README.md:
--------------------------------------------------------------------------------
1 | # Rust Crates
2 |
3 | This folder contains Rust crates. Entry point of the Rust logic is the `hub` library crate. These crates are integrated and compiled into the Flutter app by the [Rinf](https://rinf.cunarist.org) framework.
4 |
5 | - Do NOT change the name of the `hub` crate. Compilation presets expect the entry library crate to be located at `native/hub`.
6 | - You CAN name crates other than `hub` as you want.
7 |
--------------------------------------------------------------------------------
/flutter_package/example/android/app/src/debug/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/flutter_package/example/android/app/src/profile/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/flutter_package/example/macos/Runner/DebugProfile.entitlements:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | com.apple.security.app-sandbox
6 |
7 | com.apple.security.cs.allow-jit
8 |
9 | com.apple.security.network.server
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/Cargo.toml:
--------------------------------------------------------------------------------
1 | [workspace]
2 | resolver = "3"
3 | # These can depend on each other.
4 | # We need to override `crates.io` to use local paths.
5 | members = ["flutter_package/example/native/*", "rust_crate", "rust_crate_proc"]
6 | # The binary crate doesn't have dependency relationship with others.
7 | # Also, it should have its own `Cargo.lock`.
8 | exclude = ["rust_crate_cli"]
9 |
10 | [patch.crates-io]
11 | rinf = { path = "rust_crate" }
12 | rinf_proc = { path = "rust_crate_proc" }
13 |
--------------------------------------------------------------------------------
/.github/dependabot.yaml:
--------------------------------------------------------------------------------
1 | version: 2
2 | updates:
3 | - package-ecosystem: pub
4 | directory: "flutter_package/"
5 | schedule:
6 | interval: daily
7 | - package-ecosystem: pub
8 | directory: "flutter_package/example/"
9 | schedule:
10 | interval: daily
11 | - package-ecosystem: cargo
12 | directory: "/"
13 | schedule:
14 | interval: daily
15 | - package-ecosystem: github-actions
16 | directory: "/"
17 | schedule:
18 | interval: daily
19 |
--------------------------------------------------------------------------------
/flutter_package/example/ios/Runner/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | import Flutter
2 | import UIKit
3 |
4 | @main
5 | @objc class AppDelegate: FlutterAppDelegate {
6 | override func application(
7 | _ application: UIApplication,
8 | didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
9 | ) -> Bool {
10 | GeneratedPluginRegistrant.register(with: self)
11 | return super.application(application, didFinishLaunchingWithOptions: launchOptions)
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/flutter_package/example/native/sample_crate/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "sample_crate"
3 | version = "0.1.0"
4 | edition = "2024"
5 |
6 | [lints.clippy]
7 | unwrap_used = "deny"
8 | expect_used = "deny"
9 | wildcard_imports = "deny"
10 |
11 | [target.'cfg(any(target_os = "windows", target_os = "macos", target_os = "linux"))'.dependencies]
12 | machineid-rs = "1.2.4"
13 |
14 | [dependencies]
15 | chrono = "0.4.31"
16 | reqwest = { version = "0.12.1", default-features = false }
17 | image = "0.25.0"
18 |
--------------------------------------------------------------------------------
/flutter_package/example/pubspec.yaml:
--------------------------------------------------------------------------------
1 | name: example_app
2 | description: Demonstrates how to use the Rinf plugin
3 | publish_to: "none"
4 |
5 | version: 0.1.0
6 |
7 | environment:
8 | sdk: ">=3.8.0 <4.0.0"
9 |
10 | dependencies:
11 | flutter:
12 | sdk: flutter
13 | rinf:
14 | path: ../
15 | cupertino_icons: ^1.0.8
16 | meta: ^1.15.0
17 | tuple: ^2.0.2
18 |
19 | dev_dependencies:
20 | flutter_lints: ^6.0.0
21 | test: ^1.25.15
22 |
23 | flutter:
24 | uses-material-design: true
25 |
--------------------------------------------------------------------------------
/flutter_package/example/macos/Runner/MainFlutterWindow.swift:
--------------------------------------------------------------------------------
1 | import Cocoa
2 | import FlutterMacOS
3 |
4 | class MainFlutterWindow: NSWindow {
5 | override func awakeFromNib() {
6 | let flutterViewController = FlutterViewController()
7 | let windowFrame = self.frame
8 | self.contentViewController = flutterViewController
9 | self.setFrame(windowFrame, display: true)
10 |
11 | RegisterGeneratedPlugins(registry: flutterViewController)
12 |
13 | super.awakeFromNib()
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/flutter_package/example/linux/runner/my_application.h:
--------------------------------------------------------------------------------
1 | #ifndef FLUTTER_MY_APPLICATION_H_
2 | #define FLUTTER_MY_APPLICATION_H_
3 |
4 | #include
5 |
6 | G_DECLARE_FINAL_TYPE(MyApplication, my_application, MY, APPLICATION,
7 | GtkApplication)
8 |
9 | /**
10 | * my_application_new:
11 | *
12 | * Creates a new Flutter-based application.
13 | *
14 | * Returns: a new #MyApplication.
15 | */
16 | MyApplication* my_application_new();
17 |
18 | #endif // FLUTTER_MY_APPLICATION_H_
19 |
--------------------------------------------------------------------------------
/flutter_package/example/windows/runner/resource.h:
--------------------------------------------------------------------------------
1 | //{{NO_DEPENDENCIES}}
2 | // Microsoft Visual C++ generated include file.
3 | // Used by Runner.rc
4 | //
5 | #define IDI_APP_ICON 101
6 |
7 | // Next default values for new objects
8 | //
9 | #ifdef APSTUDIO_INVOKED
10 | #ifndef APSTUDIO_READONLY_SYMBOLS
11 | #define _APS_NEXT_RESOURCE_VALUE 102
12 | #define _APS_NEXT_COMMAND_VALUE 40001
13 | #define _APS_NEXT_CONTROL_VALUE 1001
14 | #define _APS_NEXT_SYMED_VALUE 101
15 | #endif
16 | #endif
17 |
--------------------------------------------------------------------------------
/flutter_package/example/android/app/src/main/res/drawable/launch_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
12 |
13 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/task.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Task
3 | about: Write something to do for this project
4 | title: ""
5 | labels: enhancement
6 | assignees: ""
7 | ---
8 |
9 | ## Current Status
10 |
11 | Provide a clear and concise description of what is currently missing.
12 | If this is a completely new idea, please leave a discussion instead of an issue.
13 |
14 | ## Describe the Task
15 |
16 | A clear and concise description of the improvements.
17 |
18 | ## Additional Context
19 |
20 | Add any other context or screenshots about the feature request here.
21 |
--------------------------------------------------------------------------------
/flutter_package/example/android/app/src/main/res/drawable-v21/launch_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
12 |
13 |
--------------------------------------------------------------------------------
/flutter_package/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "LaunchImage.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "filename" : "LaunchImage@2x.png",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "universal",
15 | "filename" : "LaunchImage@3x.png",
16 | "scale" : "3x"
17 | }
18 | ],
19 | "info" : {
20 | "version" : 1,
21 | "author" : "xcode"
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/pyproject.toml:
--------------------------------------------------------------------------------
1 | # Python scripts manage code and automate tests.
2 | # We avoid shell scripts because they are platform-dependent.
3 | # You can run the automation scripts with
4 | # `uv run automate [command_type]`.
5 |
6 | [dependency-groups]
7 | dev = ["ruff", "pyright"]
8 |
9 | [tool.uv.workspace]
10 | members = ["automate", "documentation"]
11 |
12 | [tool.ruff.lint]
13 | select = ["ALL"]
14 | ignore = ["TC", "BLE", "S602"]
15 |
16 | [tool.pyright]
17 | typeCheckingMode = "strict"
18 |
19 | [tool.ruff.lint.per-file-ignores]
20 | "documentation/**/*.py" = ["A001"]
21 |
--------------------------------------------------------------------------------
/rust_crate_proc/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "rinf_proc"
3 | version = "8.8.1"
4 | edition = "2024"
5 | license = "MIT"
6 | description = "Rust for native business logic, Flutter for flexible and beautiful GUI"
7 | repository = "https://github.com/cunarist/rinf"
8 | documentation = "https://rinf.cunarist.org"
9 |
10 | [lib]
11 | proc-macro = true
12 |
13 | [lints.clippy]
14 | unwrap_used = "deny"
15 | expect_used = "deny"
16 | wildcard_imports = "deny"
17 |
18 | [dependencies]
19 | syn = "2.0.98"
20 | quote = "1.0.38"
21 | heck = "0.5.0"
22 | proc-macro2 = "1.0.94"
23 |
--------------------------------------------------------------------------------
/documentation/README.md:
--------------------------------------------------------------------------------
1 | # Documentation
2 |
3 | In order to preview and build this documentation, you need to have [uv](https://docs.astral.sh/uv/getting-started/installation/) installed on your system.
4 |
5 | Generate the static documentation files for publication on the web.
6 |
7 | ```shell
8 | uv run sphinx-build -M dirhtml source dist
9 | ```
10 |
11 | Serve the built files locally.
12 |
13 | ```shell
14 | uv run python server.py
15 | ```
16 |
17 | Automatically apply changes while writing.
18 |
19 | ```shell
20 | uv run sphinx-autobuild source dist --builder dirhtml
21 | ```
22 |
--------------------------------------------------------------------------------
/rust_crate_cli/src/tool/server.rs:
--------------------------------------------------------------------------------
1 | use crate::SetupError;
2 | use arboard::Clipboard;
3 |
4 | pub fn provide_server_command(release: bool) -> Result<(), SetupError> {
5 | let mut clipboard = Clipboard::new()?;
6 | let release_arg = if release { " --release" } else { "" };
7 | let base_command = concat!(
8 | "flutter run",
9 | " --web-header=cross-origin-opener-policy=same-origin",
10 | " --web-header=cross-origin-embedder-policy=require-corp",
11 | );
12 | let full_command = format!("{base_command}{release_arg}");
13 | clipboard.set_text(full_command)?;
14 | Ok(())
15 | }
16 |
--------------------------------------------------------------------------------
/flutter_package/elinux/rust.cmake:
--------------------------------------------------------------------------------
1 | cmake_policy(SET CMP0079 NEW)
2 | apply_standard_settings(${BINARY_NAME})
3 |
4 | set_target_properties(
5 | ${BINARY_NAME} PROPERTIES
6 | CXX_VISIBILITY_PRESET hidden
7 | BUILD_RPATH_USE_ORIGIN ON
8 | )
9 |
10 | target_compile_definitions(${BINARY_NAME} PRIVATE FLUTTER_PLUGIN_IMPL)
11 | target_link_libraries(${BINARY_NAME} PRIVATE flutter)
12 |
13 | include("../cargokit/cmake/cargokit.cmake")
14 | apply_cargokit(${BINARY_NAME} ${CMAKE_SOURCE_DIR}/../native/hub hub "")
15 |
16 | set(
17 | rinf_bundled_libraries
18 | "${${BINARY_NAME}_cargokit_lib}"
19 | PARENT_SCOPE
20 | )
--------------------------------------------------------------------------------
/flutter_package/linux/rust.cmake:
--------------------------------------------------------------------------------
1 | cmake_policy(SET CMP0079 NEW)
2 | apply_standard_settings(${BINARY_NAME})
3 |
4 | set_target_properties(
5 | ${BINARY_NAME} PROPERTIES
6 | CXX_VISIBILITY_PRESET hidden
7 | BUILD_RPATH_USE_ORIGIN ON
8 | )
9 |
10 | target_compile_definitions(${BINARY_NAME} PRIVATE FLUTTER_PLUGIN_IMPL)
11 | target_link_libraries(${BINARY_NAME} PRIVATE flutter)
12 |
13 | include("../cargokit/cmake/cargokit.cmake")
14 | apply_cargokit(${BINARY_NAME} ${CMAKE_SOURCE_DIR}/../native/hub hub "")
15 |
16 | set(
17 | rinf_bundled_libraries
18 | "${${BINARY_NAME}_cargokit_lib}"
19 | PARENT_SCOPE
20 | )
--------------------------------------------------------------------------------
/flutter_package/windows/rust.cmake:
--------------------------------------------------------------------------------
1 | cmake_policy(SET CMP0079 NEW)
2 | apply_standard_settings(${BINARY_NAME})
3 |
4 | set_target_properties(
5 | ${BINARY_NAME} PROPERTIES
6 | CXX_VISIBILITY_PRESET hidden
7 | BUILD_RPATH_USE_ORIGIN ON
8 | )
9 |
10 | target_compile_definitions(${BINARY_NAME} PRIVATE FLUTTER_PLUGIN_IMPL)
11 | target_link_libraries(${BINARY_NAME} PRIVATE flutter)
12 |
13 | include("../cargokit/cmake/cargokit.cmake")
14 | apply_cargokit(${BINARY_NAME} ${CMAKE_SOURCE_DIR}/../native/hub hub "")
15 |
16 | set(
17 | rinf_bundled_libraries
18 | "${${BINARY_NAME}_cargokit_lib}"
19 | PARENT_SCOPE
20 | )
--------------------------------------------------------------------------------
/documentation/source/index.md:
--------------------------------------------------------------------------------
1 | ```{eval-rst}
2 | .. raw:: html
3 | :file: _templates/landing.html
4 | ```
5 |
6 | ```{eval-rst}
7 | .. toctree::
8 | :maxdepth: 1
9 | :hidden:
10 |
11 | introduction.md
12 | installing-components.md
13 | applying-template.md
14 | running-and-building.md
15 | messaging.md
16 | field-types.md
17 | field-attributes.md
18 | tutorial.md
19 | state-management.md
20 | error-handling.md
21 | printing-for-debugging.md
22 | graceful-shutdown.md
23 | configuration.md
24 | unit-testing.md
25 | upgrading.md
26 | frequently-asked-questions.md
27 | contribution.md
28 | ```
29 |
--------------------------------------------------------------------------------
/flutter_package/example/android/build.gradle.kts:
--------------------------------------------------------------------------------
1 | allprojects {
2 | repositories {
3 | google()
4 | mavenCentral()
5 | }
6 | }
7 |
8 | val newBuildDir: Directory = rootProject.layout.buildDirectory.dir("../../build").get()
9 | rootProject.layout.buildDirectory.value(newBuildDir)
10 |
11 | subprojects {
12 | val newSubprojectBuildDir: Directory = newBuildDir.dir(project.name)
13 | project.layout.buildDirectory.value(newSubprojectBuildDir)
14 | }
15 | subprojects {
16 | project.evaluationDependsOn(":app")
17 | }
18 |
19 | tasks.register("clean") {
20 | delete(rootProject.layout.buildDirectory)
21 | }
22 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Miscellaneous
2 | *.class
3 | *.log
4 | *.pyc
5 | *.swp
6 | .DS_Store
7 | .atom/
8 | .buildlog/
9 | .history
10 | .svn/
11 | migrate_working_dir/
12 |
13 | # IntelliJ related
14 | *.iml
15 | *.ipr
16 | *.iws
17 | .idea/
18 |
19 | # Flutter/Dart/Pub related
20 | # Libraries should not include pubspec.lock, per https://dart.dev/guides/libraries/private-files#pubspeclock.
21 | /pubspec.lock
22 | **/doc/api/
23 | .dart_tool/
24 | .packages
25 | build/
26 |
27 | # Rust related
28 | /.cargo/
29 | target/
30 |
31 | # Others
32 | *.lock
33 | !/rust_crate_cli/Cargo.lock
34 | .python-version
35 | /documentation/dist/
36 | /documentation/*.egg-info/
37 |
--------------------------------------------------------------------------------
/flutter_package/cargokit/build_tool/test/cargo_test.dart:
--------------------------------------------------------------------------------
1 | import 'package:build_tool/src/cargo.dart';
2 | import 'package:test/test.dart';
3 |
4 | final _cargoToml = """
5 | [workspace]
6 |
7 | [profile.release]
8 | lto = true
9 | panic = "abort"
10 | opt-level = "z"
11 | # strip = "symbols"
12 |
13 | [package]
14 | name = "super_native_extensions"
15 | version = "0.1.0"
16 | edition = "2021"
17 | resolver = "2"
18 |
19 | [lib]
20 | crate-type = ["cdylib", "staticlib"]
21 | """;
22 |
23 | void main() {
24 | test('parseCargoToml', () {
25 | final info = CrateInfo.parseManifest(_cargoToml);
26 | expect(info.packageName, 'super_native_extensions');
27 | });
28 | }
29 |
--------------------------------------------------------------------------------
/flutter_package/example/macos/Runner/Configs/Warnings.xcconfig:
--------------------------------------------------------------------------------
1 | WARNING_CFLAGS = -Wall -Wconditional-uninitialized -Wnullable-to-nonnull-conversion -Wmissing-method-return-type -Woverlength-strings
2 | GCC_WARN_UNDECLARED_SELECTOR = YES
3 | CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES
4 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE
5 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES
6 | CLANG_WARN_PRAGMA_PACK = YES
7 | CLANG_WARN_STRICT_PROTOTYPES = YES
8 | CLANG_WARN_COMMA = YES
9 | GCC_WARN_STRICT_SELECTOR_MATCH = YES
10 | CLANG_WARN_OBJC_REPEATED_USE_OF_WEAK = YES
11 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES
12 | GCC_WARN_SHADOW = YES
13 | CLANG_WARN_UNREACHABLE_CODE = YES
14 |
--------------------------------------------------------------------------------
/rust_crate/src/traits.rs:
--------------------------------------------------------------------------------
1 | use std::sync::{MutexGuard, PoisonError};
2 |
3 | /// There is no panicking code in the Rinf crate.
4 | /// We assume that any mutex used here will never be poisoned.
5 | /// This trait handles the recovery from a logically poisoned situation,
6 | /// which is unlikely to occur.
7 | pub trait GuardRecovery<'a, T> {
8 | fn recover(self) -> MutexGuard<'a, T>;
9 | }
10 |
11 | impl<'a, T> GuardRecovery<'a, T>
12 | for Result, PoisonError>>
13 | {
14 | fn recover(self) -> MutexGuard<'a, T> {
15 | match self {
16 | Ok(inner) => inner,
17 | Err(poisoned) => poisoned.into_inner(),
18 | }
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/flutter_package/example/native/sample_crate/src/error.rs:
--------------------------------------------------------------------------------
1 | use std::error::Error;
2 | use std::fmt::{Display, Formatter};
3 |
4 | #[derive(Debug)]
5 | pub enum ExampleError {
6 | Fractal,
7 | HardwareId,
8 | WebApi,
9 | }
10 |
11 | impl Error for ExampleError {}
12 |
13 | impl Display for ExampleError {
14 | fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
15 | match self {
16 | Self::Fractal => {
17 | write!(f, "Failed to generate fractal")
18 | }
19 | Self::HardwareId => {
20 | write!(f, "Unable to retrieve hardware ID")
21 | }
22 | Self::WebApi => {
23 | write!(f, "Web API call failed")
24 | }
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/flutter_package/example/windows/runner/runner.exe.manifest:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | PerMonitorV2
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/flutter_package/example/macos/Runner/Configs/AppInfo.xcconfig:
--------------------------------------------------------------------------------
1 | // Application-level settings for the Runner target.
2 | //
3 | // This may be replaced with something auto-generated from metadata (e.g., pubspec.yaml) in the
4 | // future. If not, the values below would default to using the project name when this becomes a
5 | // 'flutter create' template.
6 |
7 | // The application's name. By default this is also the title of the Flutter window.
8 | PRODUCT_NAME = example_app
9 |
10 | // The application's bundle identifier
11 | PRODUCT_BUNDLE_IDENTIFIER = com.example.exampleApp
12 |
13 | // The copyright displayed in application information
14 | PRODUCT_COPYRIGHT = Copyright © 2025 com.example. All rights reserved.
15 |
--------------------------------------------------------------------------------
/flutter_package/src/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | # The Flutter tooling requires that developers have CMake 3.10 or later
2 | # installed. You should not increase this version, as doing so will cause
3 | # the plugin to fail to compile for some customers of the plugin.
4 | cmake_minimum_required(VERSION 3.10)
5 |
6 | project(rinf_library VERSION 0.0.1 LANGUAGES C)
7 |
8 | add_library(rinf SHARED
9 | "rinf.c"
10 | )
11 |
12 | set_target_properties(rinf PROPERTIES
13 | PUBLIC_HEADER rinf.h
14 | OUTPUT_NAME "rinf"
15 | )
16 |
17 | target_compile_definitions(rinf PUBLIC DART_SHARED_LIB)
18 |
19 | if (ANDROID)
20 | # Support Android 15 16k page size.
21 | target_link_options(rinf PRIVATE "-Wl,-z,max-page-size=16384")
22 | endif()
23 |
--------------------------------------------------------------------------------
/documentation/source/printing-for-debugging.md:
--------------------------------------------------------------------------------
1 | # Printing for Debugging
2 |
3 | You might be used to `println!` macro in Rust. However, using that macro isn't a very good idea in our apps made with Flutter and Rust because `stdout` stream cannot be seen on the web and mobile emulators.
4 |
5 | When writing Rust code in the `hub` crate, you can simply print your debug message with the `debug_print!` macro provided by this framework like below. Once you use this macro, Flutter will take care of the rest.
6 |
7 | ```{code-block} rust
8 | :caption: Rust
9 | use rinf::debug_print;
10 | debug_print!("My object is {:?}", my_object);
11 | ```
12 |
13 | `debug_print!` only writes the code in debug mode, resulting in a smaller and cleaner release binary.
14 |
--------------------------------------------------------------------------------
/flutter_package/example/ios/.gitignore:
--------------------------------------------------------------------------------
1 | **/dgph
2 | *.mode1v3
3 | *.mode2v3
4 | *.moved-aside
5 | *.pbxuser
6 | *.perspectivev3
7 | **/*sync/
8 | .sconsign.dblite
9 | .tags*
10 | **/.vagrant/
11 | **/DerivedData/
12 | Icon?
13 | **/Pods/
14 | **/.symlinks/
15 | profile
16 | xcuserdata
17 | **/.generated/
18 | Flutter/App.framework
19 | Flutter/Flutter.framework
20 | Flutter/Flutter.podspec
21 | Flutter/Generated.xcconfig
22 | Flutter/ephemeral/
23 | Flutter/app.flx
24 | Flutter/app.zip
25 | Flutter/flutter_assets/
26 | Flutter/flutter_export_environment.sh
27 | ServiceDefinitions.json
28 | Runner/GeneratedPluginRegistrant.*
29 |
30 | # Exceptions to above rules.
31 | !default.mode1v3
32 | !default.mode2v3
33 | !default.pbxuser
34 | !default.perspectivev3
35 |
--------------------------------------------------------------------------------
/flutter_package/example/native/hub/src/signals/counter_number.rs:
--------------------------------------------------------------------------------
1 | use rinf::{DartSignal, RustSignal, SignalPiece};
2 | use serde::{Deserialize, Serialize};
3 |
4 | #[derive(Deserialize, DartSignal)]
5 | pub struct SampleNumberInput {
6 | pub letter: String,
7 | pub _dummy_one: u32,
8 | pub _dummy_two: Option,
9 | pub _dummy_three: Vec,
10 | }
11 |
12 | #[derive(Serialize, RustSignal)]
13 | pub struct SampleNumberOutput {
14 | pub current_number: i32,
15 | pub dummy_one: u32,
16 | pub dummy_two: Option,
17 | pub dummy_three: Vec,
18 | }
19 |
20 | #[derive(Serialize, Deserialize, SignalPiece)]
21 | pub struct SampleSchema {
22 | pub sample_field_one: bool,
23 | pub sample_field_two: bool,
24 | }
25 |
--------------------------------------------------------------------------------
/flutter_package/example/windows/runner/utils.h:
--------------------------------------------------------------------------------
1 | #ifndef RUNNER_UTILS_H_
2 | #define RUNNER_UTILS_H_
3 |
4 | #include
5 | #include
6 |
7 | // Creates a console for the process, and redirects stdout and stderr to
8 | // it for both the runner and the Flutter library.
9 | void CreateAndAttachConsole();
10 |
11 | // Takes a null-terminated wchar_t* encoded in UTF-16 and returns a std::string
12 | // encoded in UTF-8. Returns an empty std::string on failure.
13 | std::string Utf8FromUtf16(const wchar_t* utf16_string);
14 |
15 | // Gets the command line arguments passed in as a std::vector,
16 | // encoded in UTF-8. Returns an empty std::vector on failure.
17 | std::vector GetCommandLineArguments();
18 |
19 | #endif // RUNNER_UTILS_H_
20 |
--------------------------------------------------------------------------------
/rust_crate/src/lib.rs:
--------------------------------------------------------------------------------
1 | mod channel;
2 | mod error;
3 | mod macros;
4 | mod shutdown;
5 | mod signal_trait;
6 | mod traits;
7 |
8 | mod interface;
9 | #[cfg(not(target_family = "wasm"))]
10 | mod interface_os;
11 | #[cfg(target_family = "wasm")]
12 | mod interface_web;
13 |
14 | pub use channel::{SignalReceiver, SignalSender, signal_channel};
15 | pub use error::AppError;
16 | pub use interface::{DartSignalPack, send_rust_signal, start_rust_logic};
17 | pub use shutdown::dart_shutdown;
18 | pub use signal_trait::{
19 | DartSignal, DartSignalBinary, RustSignal, RustSignalBinary, SignalPiece,
20 | };
21 |
22 | pub use rinf_proc::{
23 | DartSignal, DartSignalBinary, RustSignal, RustSignalBinary, SignalPiece,
24 | };
25 |
26 | #[doc(hidden)]
27 | pub use bincode::{deserialize, serialize};
28 |
--------------------------------------------------------------------------------
/rust_crate_cli/template/native/hub/src/signals/mod.rs:
--------------------------------------------------------------------------------
1 | use rinf::{DartSignal, RustSignal, SignalPiece};
2 | use serde::{Deserialize, Serialize};
3 |
4 | /// To send data from Dart to Rust, use `DartSignal`.
5 | #[derive(Deserialize, DartSignal)]
6 | pub struct SmallText {
7 | pub text: String,
8 | }
9 |
10 | /// To send data from Rust to Dart, use `RustSignal`.
11 | #[derive(Serialize, RustSignal)]
12 | pub struct SmallNumber {
13 | pub number: i32,
14 | }
15 |
16 | /// A signal can be nested inside another signal.
17 | #[derive(Serialize, RustSignal)]
18 | pub struct BigBool {
19 | pub member: bool,
20 | pub nested: SmallBool,
21 | }
22 |
23 | /// To nest a signal inside other signal, use `SignalPiece`.
24 | #[derive(Serialize, SignalPiece)]
25 | pub struct SmallBool(pub bool);
26 |
--------------------------------------------------------------------------------
/flutter_package/cargokit/build_tool/pubspec.yaml:
--------------------------------------------------------------------------------
1 | name: build_tool
2 | description: Cargokit build_tool. Facilitates the build of Rust crate during Flutter application build.
3 | publish_to: none
4 | version: 1.0.0
5 |
6 | environment:
7 | sdk: ">=3.0.0 <4.0.0"
8 |
9 | # Add regular dependencies here.
10 | dependencies:
11 | # these are pinned on purpose because the bundle_tool_runner doesn't have
12 | # pubspec.lock. See run_build_tool.sh
13 | logging: 1.2.0
14 | path: 1.8.0
15 | version: 3.0.0
16 | collection: 1.18.0
17 | ed25519_edwards: 0.3.1
18 | hex: 0.2.0
19 | yaml: 3.1.2
20 | source_span: 1.10.0
21 | github: 9.17.0
22 | args: 2.4.2
23 | crypto: 3.0.3
24 | convert: 3.1.1
25 | http: 1.1.0
26 | toml: 0.14.0
27 |
28 | dev_dependencies:
29 | lints: ^2.1.0
30 | test: ^1.24.0
31 |
--------------------------------------------------------------------------------
/flutter_package/cargokit/cmake/resolve_symlinks.ps1:
--------------------------------------------------------------------------------
1 | function Resolve-Symlinks {
2 | [CmdletBinding()]
3 | [OutputType([string])]
4 | param(
5 | [Parameter(Position = 0, Mandatory, ValueFromPipeline, ValueFromPipelineByPropertyName)]
6 | [string] $Path
7 | )
8 |
9 | [string] $separator = '/'
10 | [string[]] $parts = $Path.Split($separator)
11 |
12 | [string] $realPath = ''
13 | foreach ($part in $parts) {
14 | if ($realPath -and !$realPath.EndsWith($separator)) {
15 | $realPath += $separator
16 | }
17 | $realPath += $part
18 | $item = Get-Item $realPath
19 | if ($item.Target) {
20 | $realPath = $item.Target.Replace('\', '/')
21 | }
22 | }
23 | $realPath
24 | }
25 |
26 | $path=Resolve-Symlinks -Path $args[0]
27 | Write-Host $path
28 |
--------------------------------------------------------------------------------
/rust_crate/src/error.rs:
--------------------------------------------------------------------------------
1 | use std::error::Error;
2 | use std::fmt::{Display, Formatter};
3 |
4 | #[derive(Debug)]
5 | pub enum AppError {
6 | NoDartIsolate,
7 | CannotEncodeMessage,
8 | CannotDecodeMessage,
9 | NoBindings,
10 | }
11 |
12 | impl Error for AppError {}
13 |
14 | impl Display for AppError {
15 | fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
16 | match self {
17 | Self::NoDartIsolate => {
18 | write!(f, "Dart isolate for Rust signals was not created")
19 | }
20 | Self::CannotDecodeMessage => {
21 | write!(f, "Could not decode the message")
22 | }
23 | Self::CannotEncodeMessage => {
24 | write!(f, "Could not encode the message")
25 | }
26 | Self::NoBindings => {
27 | write!(f, "Rinf bindings are not ready")
28 | }
29 | }
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug-report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Create a report to help us improve
4 | title: ""
5 | labels: bug
6 | assignees: ""
7 | ---
8 |
9 | ## Describe the Bug
10 |
11 | A clear and concise description of what the bug is.
12 | If it's not a bug, please leave a discussion instead of an issue.
13 |
14 | ## To Reproduce
15 |
16 | Steps to reproduce the behavior:
17 |
18 | 1. Go to '...'
19 | 2. Click on '....'
20 | 3. Scroll down to '....'
21 | 4. See error
22 |
23 | ## Expected Behavior
24 |
25 | A clear and concise description of what you expected to happen.
26 |
27 | ## Screenshots
28 |
29 | If applicable, add screenshots to help explain your problem.
30 |
31 | ## Additional Context
32 |
33 | Output from the command below, shown in a Markdown code block.
34 |
35 | ```shell
36 | rustc --version
37 | flutter doctor
38 | ```
39 |
--------------------------------------------------------------------------------
/flutter_package/cargokit/.github/workflows/check_and_lint.yml:
--------------------------------------------------------------------------------
1 | on:
2 | pull_request:
3 | push:
4 | branches:
5 | - main
6 |
7 | name: Check and Lint
8 |
9 | jobs:
10 | Flutter:
11 | runs-on: ubuntu-latest
12 | steps:
13 | - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # 4.1.0
14 | - uses: subosito/flutter-action@44ac965b96f18d999802d4b807e3256d5a3f9fa1 # 2.16.0
15 | - name: Pub Get
16 | run: dart pub get --no-precompile
17 | working-directory: build_tool
18 | - name: Dart Format
19 | run: dart format . --output=none --set-exit-if-changed
20 | working-directory: build_tool
21 | - name: Analyze
22 | run: dart analyze
23 | working-directory: build_tool
24 | - name: Test
25 | run: flutter test
26 | working-directory: build_tool
27 |
--------------------------------------------------------------------------------
/demo/server.py:
--------------------------------------------------------------------------------
1 | """Simple HTTP server with CORS headers for demo Rinf web app."""
2 |
3 | from http.server import HTTPServer, SimpleHTTPRequestHandler
4 | from typing import override
5 |
6 |
7 | class RequestHandler(SimpleHTTPRequestHandler):
8 | """Request handler with CORS headers for SharedArrayBuffer support."""
9 |
10 | @override
11 | def end_headers(self) -> None:
12 | """Add required headers for cross-origin isolation."""
13 | self.send_header("cross-origin-opener-policy", "same-origin")
14 | self.send_header("cross-origin-embedder-policy", "require-corp")
15 | super().end_headers()
16 |
17 |
18 | def main() -> None:
19 | """Start the HTTP server for serving documentation files."""
20 | address = ("", 80)
21 | HTTPServer(address, RequestHandler).serve_forever()
22 |
23 |
24 | if __name__ == "__main__":
25 | main()
26 |
--------------------------------------------------------------------------------
/flutter_package/example/android/settings.gradle.kts:
--------------------------------------------------------------------------------
1 | pluginManagement {
2 | val flutterSdkPath = run {
3 | val properties = java.util.Properties()
4 | file("local.properties").inputStream().use { properties.load(it) }
5 | val flutterSdkPath = properties.getProperty("flutter.sdk")
6 | require(flutterSdkPath != null) { "flutter.sdk not set in local.properties" }
7 | flutterSdkPath
8 | }
9 |
10 | includeBuild("$flutterSdkPath/packages/flutter_tools/gradle")
11 |
12 | repositories {
13 | google()
14 | mavenCentral()
15 | gradlePluginPortal()
16 | }
17 | }
18 |
19 | plugins {
20 | id("dev.flutter.flutter-plugin-loader") version "1.0.0"
21 | id("com.android.application") version "8.7.0" apply false
22 | id("org.jetbrains.kotlin.android") version "1.8.22" apply false
23 | }
24 |
25 | include(":app")
26 |
--------------------------------------------------------------------------------
/rust_crate_cli/template/native/hub/src/lib.rs:
--------------------------------------------------------------------------------
1 | //! This `hub` crate is the
2 | //! entry point of the Rust logic.
3 |
4 | mod actors;
5 | mod signals;
6 |
7 | use actors::create_actors;
8 | use rinf::{dart_shutdown, write_interface};
9 | use tokio::spawn;
10 |
11 | // Uncomment below to target the web.
12 | // use tokio_with_wasm::alias as tokio;
13 |
14 | write_interface!();
15 |
16 | // You can go with any async library, not just `tokio`.
17 | #[tokio::main(flavor = "current_thread")]
18 | async fn main() {
19 | // Spawn concurrent tasks.
20 | // Always use non-blocking async functions like `tokio::fs::File::open`.
21 | // If you must use blocking code, use `tokio::task::spawn_blocking`
22 | // or the equivalent provided by your async library.
23 | spawn(create_actors());
24 |
25 | // Keep the main function running until Dart shutdown.
26 | dart_shutdown().await;
27 | }
28 |
--------------------------------------------------------------------------------
/documentation/server.py:
--------------------------------------------------------------------------------
1 | """Simple HTTP server for serving documentation with CORS headers."""
2 |
3 | import os
4 | from http.server import HTTPServer, SimpleHTTPRequestHandler
5 | from typing import override
6 |
7 |
8 | class RequestHandler(SimpleHTTPRequestHandler):
9 | """HTTP request handler with additional CORS headers for cross-origin isolation."""
10 |
11 | @override
12 | def end_headers(self) -> None:
13 | self.send_header("cross-origin-opener-policy", "same-origin")
14 | self.send_header("cross-origin-embedder-policy", "require-corp")
15 | super().end_headers()
16 |
17 |
18 | def main() -> None:
19 | """Start the HTTP server for serving documentation files."""
20 | os.chdir("dist/dirhtml")
21 | address = ("", 80)
22 | HTTPServer(address, RequestHandler).serve_forever()
23 |
24 |
25 | if __name__ == "__main__":
26 | main()
27 |
--------------------------------------------------------------------------------
/flutter_package/example/linux/flutter/generated_plugins.cmake:
--------------------------------------------------------------------------------
1 | #
2 | # Generated file, do not edit.
3 | #
4 |
5 | list(APPEND FLUTTER_PLUGIN_LIST
6 | )
7 |
8 | list(APPEND FLUTTER_FFI_PLUGIN_LIST
9 | rinf
10 | )
11 |
12 | set(PLUGIN_BUNDLED_LIBRARIES)
13 |
14 | foreach(plugin ${FLUTTER_PLUGIN_LIST})
15 | add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/linux plugins/${plugin})
16 | target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin)
17 | list(APPEND PLUGIN_BUNDLED_LIBRARIES $)
18 | list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries})
19 | endforeach(plugin)
20 |
21 | foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST})
22 | add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/linux plugins/${ffi_plugin})
23 | list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries})
24 | endforeach(ffi_plugin)
25 |
--------------------------------------------------------------------------------
/rust_crate_cli/template/native/hub/Cargo.toml.template:
--------------------------------------------------------------------------------
1 | [package]
2 | # Do not change the name of this crate.
3 | name = "hub"
4 | version = "0.1.0"
5 | edition = "2024"
6 |
7 | [lib]
8 | # `lib` is required for non-library targets,
9 | # such as tests and benchmarks.
10 | # `cdylib` is for Linux, Android, Windows, and web.
11 | # `staticlib` is for iOS and macOS.
12 | crate-type = ["lib", "cdylib", "staticlib"]
13 |
14 | [lints.clippy]
15 | unwrap_used = "deny"
16 | expect_used = "deny"
17 | wildcard_imports = "deny"
18 |
19 | [dependencies]
20 | rinf = "8.8.1"
21 | serde = { version = "1.0.219", features = ["derive"] }
22 | tokio = { version = "1.45.0", features = ["rt", "macros", "time"] }
23 | async-trait = "0.1.87"
24 | messages = "0.3.1"
25 |
26 | # Uncomment below to target the web.
27 | # tokio_with_wasm = { version = "0.8.5", features = ["rt", "macros", "time"] }
28 | # wasm-bindgen = "0.2.100"
29 |
--------------------------------------------------------------------------------
/flutter_package/example/windows/flutter/generated_plugins.cmake:
--------------------------------------------------------------------------------
1 | #
2 | # Generated file, do not edit.
3 | #
4 |
5 | list(APPEND FLUTTER_PLUGIN_LIST
6 | )
7 |
8 | list(APPEND FLUTTER_FFI_PLUGIN_LIST
9 | rinf
10 | )
11 |
12 | set(PLUGIN_BUNDLED_LIBRARIES)
13 |
14 | foreach(plugin ${FLUTTER_PLUGIN_LIST})
15 | add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/windows plugins/${plugin})
16 | target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin)
17 | list(APPEND PLUGIN_BUNDLED_LIBRARIES $)
18 | list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries})
19 | endforeach(plugin)
20 |
21 | foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST})
22 | add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/windows plugins/${ffi_plugin})
23 | list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries})
24 | endforeach(ffi_plugin)
25 |
--------------------------------------------------------------------------------
/flutter_package/example/native/hub/src/lib.rs:
--------------------------------------------------------------------------------
1 | //! This `hub` crate is the
2 | //! entry point of the Rust logic.
3 |
4 | mod actors;
5 | mod signals;
6 | mod testing;
7 |
8 | use actors::create_actors;
9 |
10 | use rinf::{dart_shutdown, write_interface};
11 | use testing::run_unit_tests;
12 | use tokio::spawn;
13 | use tokio_with_wasm::alias as tokio;
14 |
15 | write_interface!();
16 |
17 | // You can go with any async library, not just `tokio`.
18 | #[tokio::main(flavor = "current_thread")]
19 | async fn main() {
20 | // Spawn concurrent tasks.
21 | // Always use non-blocking async functions like `tokio::fs::File::open`.
22 | // If you must use blocking code, use `tokio::task::spawn_blocking`
23 | // or the equivalent provided by your async library.
24 | spawn(create_actors());
25 | spawn(run_unit_tests());
26 |
27 | // Keep the main function running until Dart shutdown.
28 | dart_shutdown().await;
29 | }
30 |
--------------------------------------------------------------------------------
/flutter_package/example/ios/Flutter/AppFrameworkInfo.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | App
9 | CFBundleIdentifier
10 | io.flutter.flutter.app
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | App
15 | CFBundlePackageType
16 | FMWK
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1.0
23 | MinimumOSVersion
24 | 12.0
25 |
26 |
27 |
--------------------------------------------------------------------------------
/flutter_package/lib/src/structure.dart:
--------------------------------------------------------------------------------
1 | import 'dart:typed_data';
2 |
3 | /// This type represents a function
4 | /// that can accept raw signal data from Rust
5 | /// and handle it accordingly.
6 | typedef AssignRustSignal = Map;
7 |
8 | /// This contains a message from Rust.
9 | /// Optionally, a custom binary called `binary` can also be included.
10 | class RustSignalPack {
11 | /// The message instance.
12 | final T message;
13 |
14 | /// Binary data included in the signal.
15 | /// This field is useful for sending custom bytes
16 | /// without the overhead of serialization/deserialization.
17 | final Uint8List binary;
18 |
19 | /// Constructs a packed data transfer object that includes
20 | /// the message and the binary data from Rust.
21 | /// This constructor is not intended for external use outside the library.
22 | RustSignalPack(this.message, this.binary);
23 | }
24 |
--------------------------------------------------------------------------------
/flutter_package/src/rinf.c:
--------------------------------------------------------------------------------
1 | #include "rinf.h"
2 |
3 | // A very short-lived native function.
4 | //
5 | // For very short-lived functions, it is fine to call them on the main isolate.
6 | // They will block the Dart execution while running the native function, so
7 | // only do this for native functions which are guaranteed to be short-lived.
8 | FFI_PLUGIN_EXPORT intptr_t sum(intptr_t a, intptr_t b) { return a + b; }
9 |
10 | // A longer-lived native function, which occupies the thread calling it.
11 | //
12 | // Do not call these kind of native functions in the main isolate. They will
13 | // block Dart execution. This will cause dropped frames in Flutter applications.
14 | // Instead, call these native functions on a separate isolate.
15 | FFI_PLUGIN_EXPORT intptr_t sum_long_running(intptr_t a, intptr_t b) {
16 | // Simulate work.
17 | #if _WIN32
18 | Sleep(5000);
19 | #else
20 | usleep(5000 * 1000);
21 | #endif
22 | return a + b;
23 | }
24 |
--------------------------------------------------------------------------------
/flutter_package/example/native/hub/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | # Do not change the name of this crate.
3 | name = "hub"
4 | version = "0.1.0"
5 | edition = "2024"
6 |
7 | [lib]
8 | # `lib` is required for non-library targets,
9 | # such as tests and benchmarks.
10 | # `cdylib` is for Linux, Android, Windows, and web.
11 | # `staticlib` is for iOS and macOS.
12 | crate-type = ["lib", "cdylib", "staticlib"]
13 |
14 | [lints.clippy]
15 | unwrap_used = "deny"
16 | expect_used = "deny"
17 | wildcard_imports = "deny"
18 |
19 | [dependencies]
20 | rinf = "8.8.1"
21 | serde = { version = "1.0.219", features = ["derive"] }
22 | tokio = { version = "1.45.0", features = ["rt", "sync", "time", "macros"] }
23 | tokio_with_wasm = { version = "0.8.5", features = [
24 | "rt",
25 | "sync",
26 | "time",
27 | "macros",
28 | ] }
29 | wasm-bindgen = "0.2.100"
30 | async-trait = "0.1.87"
31 | messages = "0.3.1"
32 | anyhow = "1.0.89"
33 | sample_crate = { path = "../sample_crate" }
34 |
--------------------------------------------------------------------------------
/rust_crate_cli/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "rinf_cli"
3 | version = "8.8.1"
4 | edition = "2024"
5 | license = "MIT"
6 | description = "Rust for native business logic, Flutter for flexible and beautiful GUI"
7 | repository = "https://github.com/cunarist/rinf"
8 | documentation = "https://rinf.cunarist.org"
9 | include = ["/src/", "/template/"]
10 |
11 | [[bin]]
12 | name = "rinf"
13 | path = "src/bin/main.rs"
14 |
15 | [lints.clippy]
16 | unwrap_used = "deny"
17 | expect_used = "deny"
18 | wildcard_imports = "deny"
19 |
20 | [target.'cfg(not(target_family = "wasm"))'.dependencies]
21 | serde = { version = "1.0.219", features = ["derive"] }
22 | clap = { version = "4.5.32", features = ["derive"] }
23 | owo-colors = "4.2.0"
24 | syn = { version = "2.0.98", features = ["full"] }
25 | quote = "1.0.38"
26 | serde_yml = "0.0.12"
27 | serde-reflection = "0.5.0"
28 | serde-generate = "0.32.0"
29 | include_dir = "0.7.4"
30 | heck = "0.5.0"
31 | arboard = "3.4.1"
32 | notify = "8.0.0"
33 |
--------------------------------------------------------------------------------
/rust_crate/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "rinf"
3 | version = "8.8.1"
4 | edition = "2024"
5 | license = "MIT"
6 | description = "Rust for native business logic, Flutter for flexible and beautiful GUI"
7 | repository = "https://github.com/cunarist/rinf"
8 | documentation = "https://rinf.cunarist.org"
9 | rust-version = "1.85"
10 |
11 | [features]
12 | show-backtrace = ["backtrace"]
13 | bevy = ["bevy_ecs"]
14 |
15 | [lints.clippy]
16 | unwrap_used = "deny"
17 | expect_used = "deny"
18 | wildcard_imports = "deny"
19 |
20 | [dependencies]
21 | rinf_proc = { version = "8.8.1" }
22 | serde = "1.0.219"
23 | bincode = "1.3.3"
24 | bevy_ecs = { version = "0.17", optional = true }
25 |
26 | [target.'cfg(not(target_family = "wasm"))'.dependencies]
27 | allo-isolate = "0.1.26"
28 | os-thread-local = "0.1.3"
29 | backtrace = { version = "0.3.69", optional = true }
30 |
31 | [target.'cfg(target_family = "wasm")'.dependencies]
32 | js-sys = "0.3.77"
33 | wasm-bindgen = "0.2.100"
34 | wasm-bindgen-futures = "0.4.50"
35 |
--------------------------------------------------------------------------------
/rust_crate_cli/template/native/hub/src/actors/second.rs:
--------------------------------------------------------------------------------
1 | use crate::actors::FirstActor;
2 | use crate::signals::{BigBool, SmallBool};
3 | use messages::prelude::{Actor, Address};
4 | use rinf::debug_print;
5 | use std::time::Duration;
6 | use tokio::spawn;
7 | use tokio::time::sleep;
8 |
9 | // Uncomment below to target the web.
10 | // use tokio_with_wasm::alias as tokio;
11 |
12 | pub struct SecondActor {}
13 |
14 | impl Actor for SecondActor {}
15 |
16 | impl SecondActor {
17 | pub fn new(first_addr: Address) -> Self {
18 | spawn(Self::ask_first_actor(first_addr));
19 | SecondActor {}
20 | }
21 | }
22 |
23 | impl SecondActor {
24 | async fn ask_first_actor(mut first_addr: Address) {
25 | sleep(Duration::from_secs(10)).await;
26 | let big_bool = BigBool {
27 | member: true,
28 | nested: SmallBool(true),
29 | };
30 | if let Ok(response) = first_addr.send(big_bool).await {
31 | debug_print!("{}", response);
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/documentation/source/field-types.md:
--------------------------------------------------------------------------------
1 | # Field Types
2 |
3 | Rinf uses Bincode serialization under the hood. It currently supports most of the standard types that Bincode does:
4 |
5 | - Signed Integers: `i8`, `i16`, `i32`, `i64`, `i128`
6 | - Unsigned Integers: `u8`, `u16`, `u32`, `u64`, `u128`
7 | - Floating-Point Numbers: `f32`, `f64`
8 | - Text: `char`, `String`, `&str`
9 | - Boolean: `bool`
10 | - Sequences: `[T; N]`, `Vec`, `HashSet`, `BTreeSet`
11 | - Maps: `HashMap`, `BTreeMap`
12 | - Standard Library Types: `Option`, `Box`
13 | - Tuple Types: `()` to `(T1, T2, T3, T4)`
14 | - C-style enums
15 | - Enums with inner data
16 |
17 | You can nest anything that implements `SignalPiece` inside a `RustSignal` or `DartSignal`. `Serialize` and `Deserialize` also have their own nesting rules. If there are no compile-time errors and the app builds successfully, you're good to go.
18 |
19 | To represent abstract data such as time, it’s recommended to use integer-based timestamps or simple primitives.
20 |
--------------------------------------------------------------------------------
/flutter_package/example/native/hub/src/actors/mod.rs:
--------------------------------------------------------------------------------
1 | mod counting;
2 | mod performing;
3 |
4 | use crate::signals::CreateActors;
5 | use messages::prelude::Context;
6 | use performing::PerformingActor;
7 | use rinf::DartSignal;
8 | use tokio::spawn;
9 | use tokio_with_wasm::alias as tokio;
10 |
11 | pub use counting::*;
12 |
13 | /// Spawns the actors.
14 | pub async fn create_actors() {
15 | // Wait until the start signal arrives.
16 | let start_receiver = CreateActors::get_dart_signal_receiver();
17 | start_receiver.recv().await;
18 |
19 | // Create actor contexts.
20 | let counting_context = Context::new();
21 | let counting_addr = counting_context.address();
22 | let performing_context = Context::new();
23 | let performing_addr = performing_context.address();
24 |
25 | // Spawn the actors.
26 | let counting_actor = CountingActor::new(counting_addr);
27 | spawn(counting_context.run(counting_actor));
28 | let performing_actor = PerformingActor::new(performing_addr);
29 | spawn(performing_context.run(performing_actor));
30 | }
31 |
--------------------------------------------------------------------------------
/flutter_package/cargokit/build_tool/test/builder_test.dart:
--------------------------------------------------------------------------------
1 | import 'package:build_tool/src/builder.dart';
2 | import 'package:test/test.dart';
3 |
4 | void main() {
5 | test('parseBuildConfiguration', () {
6 | var b = BuildEnvironment.parseBuildConfiguration('debug');
7 | expect(b, BuildConfiguration.debug);
8 |
9 | b = BuildEnvironment.parseBuildConfiguration('profile');
10 | expect(b, BuildConfiguration.profile);
11 |
12 | b = BuildEnvironment.parseBuildConfiguration('release');
13 | expect(b, BuildConfiguration.release);
14 |
15 | b = BuildEnvironment.parseBuildConfiguration('debug-dev');
16 | expect(b, BuildConfiguration.debug);
17 |
18 | b = BuildEnvironment.parseBuildConfiguration('profile');
19 | expect(b, BuildConfiguration.profile);
20 |
21 | b = BuildEnvironment.parseBuildConfiguration('profile-prod');
22 | expect(b, BuildConfiguration.profile);
23 |
24 | // fallback to release
25 | b = BuildEnvironment.parseBuildConfiguration('unknown');
26 | expect(b, BuildConfiguration.release);
27 | });
28 | }
29 |
--------------------------------------------------------------------------------
/flutter_package/src/rinf.h:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 |
5 | #if _WIN32
6 | #include
7 | #else
8 | #include
9 | #include
10 | #endif
11 |
12 | #if _WIN32
13 | #define FFI_PLUGIN_EXPORT __declspec(dllexport)
14 | #else
15 | #define FFI_PLUGIN_EXPORT
16 | #endif
17 |
18 | // A very short-lived native function.
19 | //
20 | // For very short-lived functions, it is fine to call them on the main isolate.
21 | // They will block the Dart execution while running the native function, so
22 | // only do this for native functions which are guaranteed to be short-lived.
23 | FFI_PLUGIN_EXPORT intptr_t sum(intptr_t a, intptr_t b);
24 |
25 | // A longer lived native function, which occupies the thread calling it.
26 | //
27 | // Do not call these kind of native functions in the main isolate. They will
28 | // block Dart execution. This will cause dropped frames in Flutter applications.
29 | // Instead, call these native functions on a separate isolate.
30 | FFI_PLUGIN_EXPORT intptr_t sum_long_running(intptr_t a, intptr_t b);
31 |
--------------------------------------------------------------------------------
/flutter_package/example/.gitignore:
--------------------------------------------------------------------------------
1 | # Miscellaneous
2 | *.class
3 | *.log
4 | *.pyc
5 | *.swp
6 | .DS_Store
7 | .atom/
8 | .build/
9 | .buildlog/
10 | .history
11 | .svn/
12 | .swiftpm/
13 | migrate_working_dir/
14 |
15 | # IntelliJ related
16 | *.iml
17 | *.ipr
18 | *.iws
19 | .idea/
20 |
21 | # The .vscode folder contains launch configuration and tasks you configure in
22 | # VS Code which you may wish to be included in version control, so this line
23 | # is commented out by default.
24 | #.vscode/
25 |
26 | # Flutter/Dart/Pub related
27 | **/doc/api/
28 | **/ios/Flutter/.last_build_id
29 | .dart_tool/
30 | .flutter-plugins
31 | .flutter-plugins-dependencies
32 | .packages
33 | .pub-cache/
34 | .pub/
35 | /build/
36 |
37 | # Symbolication related
38 | app.*.symbols
39 |
40 | # Obfuscation related
41 | app.*.map.json
42 |
43 | # Android Studio will place build artifacts here
44 | /android/app/debug
45 | /android/app/profile
46 | /android/app/release
47 |
48 | # Rust related
49 | /.cargo/
50 | /target/
51 |
52 | # Generated signals
53 | /lib/src/bincode
54 | /lib/src/serde
55 | /lib/src/bindings
56 |
--------------------------------------------------------------------------------
/flutter_package/example/web/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "example_app",
3 | "short_name": "example_app",
4 | "start_url": ".",
5 | "display": "standalone",
6 | "background_color": "#0175C2",
7 | "theme_color": "#0175C2",
8 | "description": "A new Flutter project.",
9 | "orientation": "portrait-primary",
10 | "prefer_related_applications": false,
11 | "icons": [
12 | {
13 | "src": "icons/Icon-192.png",
14 | "sizes": "192x192",
15 | "type": "image/png"
16 | },
17 | {
18 | "src": "icons/Icon-512.png",
19 | "sizes": "512x512",
20 | "type": "image/png"
21 | },
22 | {
23 | "src": "icons/Icon-maskable-192.png",
24 | "sizes": "192x192",
25 | "type": "image/png",
26 | "purpose": "maskable"
27 | },
28 | {
29 | "src": "icons/Icon-maskable-512.png",
30 | "sizes": "512x512",
31 | "type": "image/png",
32 | "purpose": "maskable"
33 | }
34 | ]
35 | }
36 |
--------------------------------------------------------------------------------
/flutter_package/example/android/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
15 |
18 |
19 |
--------------------------------------------------------------------------------
/flutter_package/example/windows/runner/flutter_window.h:
--------------------------------------------------------------------------------
1 | #ifndef RUNNER_FLUTTER_WINDOW_H_
2 | #define RUNNER_FLUTTER_WINDOW_H_
3 |
4 | #include
5 | #include
6 |
7 | #include
8 |
9 | #include "win32_window.h"
10 |
11 | // A window that does nothing but host a Flutter view.
12 | class FlutterWindow : public Win32Window {
13 | public:
14 | // Creates a new FlutterWindow hosting a Flutter view running |project|.
15 | explicit FlutterWindow(const flutter::DartProject& project);
16 | virtual ~FlutterWindow();
17 |
18 | protected:
19 | // Win32Window:
20 | bool OnCreate() override;
21 | void OnDestroy() override;
22 | LRESULT MessageHandler(HWND window, UINT const message, WPARAM const wparam,
23 | LPARAM const lparam) noexcept override;
24 |
25 | private:
26 | // The project to run.
27 | flutter::DartProject project_;
28 |
29 | // The Flutter instance hosted by this window.
30 | std::unique_ptr flutter_controller_;
31 | };
32 |
33 | #endif // RUNNER_FLUTTER_WINDOW_H_
34 |
--------------------------------------------------------------------------------
/flutter_package/example/android/app/src/main/res/values-night/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
15 |
18 |
19 |
--------------------------------------------------------------------------------
/flutter_package/example/linux/runner/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 3.13)
2 | project(runner LANGUAGES CXX)
3 |
4 | # Define the application target. To change its name, change BINARY_NAME in the
5 | # top-level CMakeLists.txt, not the value here, or `flutter run` will no longer
6 | # work.
7 | #
8 | # Any new source files that you add to the application should be added here.
9 | add_executable(${BINARY_NAME}
10 | "main.cc"
11 | "my_application.cc"
12 | "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc"
13 | )
14 |
15 | # Apply the standard set of build settings. This can be removed for applications
16 | # that need different build settings.
17 | apply_standard_settings(${BINARY_NAME})
18 |
19 | # Add preprocessor definitions for the application ID.
20 | add_definitions(-DAPPLICATION_ID="${APPLICATION_ID}")
21 |
22 | # Add dependency libraries. Add any application-specific dependencies here.
23 | target_link_libraries(${BINARY_NAME} PRIVATE flutter)
24 | target_link_libraries(${BINARY_NAME} PRIVATE PkgConfig::GTK)
25 |
26 | target_include_directories(${BINARY_NAME} PRIVATE "${CMAKE_SOURCE_DIR}")
27 |
--------------------------------------------------------------------------------
/flutter_package/linux/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | # The Flutter tooling requires that developers have CMake 3.10 or later
2 | # installed. You should not increase this version, as doing so will cause
3 | # the plugin to fail to compile for some customers of the plugin.
4 | cmake_minimum_required(VERSION 3.10)
5 |
6 | # Project-level configuration.
7 | set(PROJECT_NAME "rinf")
8 | project(${PROJECT_NAME} LANGUAGES CXX)
9 |
10 | # Invoke the build for native code shared with the other target platforms.
11 | # This can be changed to accommodate different builds.
12 | add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/../src" "${CMAKE_CURRENT_BINARY_DIR}/shared")
13 |
14 | # List of absolute paths to libraries that should be bundled with the plugin.
15 | # This list could contain prebuilt libraries, or libraries created by an
16 | # external build triggered from this build file.
17 | set(rinf_bundled_libraries
18 | # Defined in ../src/CMakeLists.txt.
19 | # This can be changed to accommodate different builds.
20 | $
21 | PARENT_SCOPE
22 | )
23 |
24 | # Include the CMake build file of the Rust code.
25 | include(./rust.cmake)
--------------------------------------------------------------------------------
/flutter_package/elinux/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | # The Flutter tooling requires that developers have CMake 3.10 or later
2 | # installed. You should not increase this version, as doing so will cause
3 | # the plugin to fail to compile for some customers of the plugin.
4 | cmake_minimum_required(VERSION 3.10)
5 |
6 | # Project-level configuration.
7 | set(PROJECT_NAME "rinf")
8 | project(${PROJECT_NAME} LANGUAGES CXX)
9 |
10 | # Invoke the build for native code shared with the other target platforms.
11 | # This can be changed to accommodate different builds.
12 | add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/../src" "${CMAKE_CURRENT_BINARY_DIR}/shared")
13 |
14 | # List of absolute paths to libraries that should be bundled with the plugin.
15 | # This list could contain prebuilt libraries, or libraries created by an
16 | # external build triggered from this build file.
17 | set(rinf_bundled_libraries
18 | # Defined in ../src/CMakeLists.txt.
19 | # This can be changed to accommodate different builds.
20 | $
21 | PARENT_SCOPE
22 | )
23 |
24 | # Include the CMake build file of the Rust code.
25 | include(./rust.cmake)
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2025 Cunarist
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/documentation/source/contribution.md:
--------------------------------------------------------------------------------
1 | # Contribution
2 |
3 | ## Contribution
4 |
5 | If Rinf has been helpful, please consider giving a star to our [GitHub repository](https://github.com/cunarist/rinf) and a like to our [Pub package](https://pub.dev/packages/rinf). You can also support us by spreading the word and sharing this framework online.
6 |
7 | We appreciate your contribution to the development of this project! We're always open to discussions and pull requests, so please do not hesitate to leave your ideas or opinions at our GitHub repository.
8 |
9 | [](https://github.com/cunarist/rinf/graphs/contributors)
10 |
11 | ## Credits
12 |
13 | Rinf was not made alone. There were pioneers that gave inspiration to the structure of this package. Credits to these wonderful efforts!
14 |
15 | - https://github.com/irondash/cargokit
16 | - https://github.com/shekohex/allo-isolate
17 | - https://github.com/superlistapp/super_native_extensions
18 | - https://github.com/brickpop/flutter-rust-ffi
19 | - https://github.com/corrosion-rs/corrosion
20 | - https://github.com/fzyzcjy/flutter_rust_bridge
21 |
--------------------------------------------------------------------------------
/flutter_package/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2025 Cunarist
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/documentation/source/installing-components.md:
--------------------------------------------------------------------------------
1 | # Installing Components
2 |
3 | [flutter-install-steps]: https://docs.flutter.dev/get-started/install
4 |
5 | To get started, you need to have [Flutter SDK][flutter-install-steps] and [Rust toolchain](https://www.rust-lang.org/tools/install) installed on your system.
6 |
7 | Once you're done with the installations, verify your system's readiness with the following commands. Make sure you have installed all the subcomponents that Flutter suggests. If there are no issues in the output, you are good to go onto the next step!
8 |
9 | ```{code-block} shell
10 | :caption: CLI
11 | rustc --version
12 | flutter doctor
13 | ```
14 |
15 | ```{warning}
16 | If you're working on Linux, it is recommended to install Flutter manually. Do not install Flutter from `snap`.
17 |
18 | Flutter from `snap` comes with its own binary linker called `ld`, which is fundamentally incompatible with Rust. Instead, follow the [manual installation steps per the Flutter docs][flutter-install-steps].
19 |
20 | Typically, the Flutter SDK package found in Debian-based Linux distributions' app store (under the name "Flutter") is a `snap` package.
21 | ```
22 |
--------------------------------------------------------------------------------
/flutter_package/windows/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | # The Flutter tooling requires that developers have a version of Visual Studio
2 | # installed that includes CMake 3.14 or later. You should not increase this
3 | # version, as doing so will cause the plugin to fail to compile for some
4 | # customers of the plugin.
5 | cmake_minimum_required(VERSION 3.14)
6 |
7 | # Project-level configuration.
8 | set(PROJECT_NAME "rinf")
9 | project(${PROJECT_NAME} LANGUAGES CXX)
10 |
11 | # Invoke the build for native code shared with the other target platforms.
12 | # This can be changed to accommodate different builds.
13 | add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/../src" "${CMAKE_CURRENT_BINARY_DIR}/shared")
14 |
15 | # List of absolute paths to libraries that should be bundled with the plugin.
16 | # This list could contain prebuilt libraries, or libraries created by an
17 | # external build triggered from this build file.
18 | set(rinf_bundled_libraries
19 | # Defined in ../src/CMakeLists.txt.
20 | # This can be changed to accommodate different builds.
21 | $
22 | PARENT_SCOPE
23 | )
24 |
25 | # Include the CMake build file of the Rust code.
26 | include(./rust.cmake)
--------------------------------------------------------------------------------
/documentation/source/conf.py:
--------------------------------------------------------------------------------
1 | """Configuration file for the Sphinx documentation builder."""
2 |
3 | # For the full list of built-in configuration values, see the documentation:
4 | # https://www.sphinx-doc.org/en/master/usage/configuration.html
5 |
6 | # -- Project information -----------------------------------------------------
7 | # https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information
8 |
9 | project = "Rinf"
10 | copyright = "2025, Cunarist"
11 | author = "Cunarist"
12 | release = "8.8.1"
13 |
14 | # -- General configuration ---------------------------------------------------
15 | # https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration
16 |
17 | extensions = ["myst_parser"]
18 | source_suffix = {".md": "markdown"}
19 | templates_path = ["_templates"]
20 | exclude_patterns = []
21 |
22 | # -- Options for HTML output -------------------------------------------------
23 | # https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output
24 |
25 | html_theme = "furo"
26 | html_title = "Rinf"
27 | html_favicon = "_static/logo.png"
28 | html_static_path = ["_static"]
29 | html_show_sphinx = False
30 | html_show_sourcelink = False
31 |
--------------------------------------------------------------------------------
/flutter_package/cargokit/build_tool/lib/src/build_cmake.dart:
--------------------------------------------------------------------------------
1 | import 'dart:io';
2 |
3 | import 'package:path/path.dart' as path;
4 |
5 | import 'artifacts_provider.dart';
6 | import 'builder.dart';
7 | import 'environment.dart';
8 | import 'options.dart';
9 | import 'target.dart';
10 |
11 | class BuildCMake {
12 | final CargokitUserOptions userOptions;
13 |
14 | BuildCMake({required this.userOptions});
15 |
16 | Future build() async {
17 | final targetPlatform = Environment.targetPlatform;
18 | final target = Target.forFlutterName(Environment.targetPlatform);
19 | if (target == null) {
20 | throw Exception("Unknown target platform: $targetPlatform");
21 | }
22 |
23 | final environment = BuildEnvironment.fromEnvironment(isAndroid: false);
24 | final provider =
25 | ArtifactProvider(environment: environment, userOptions: userOptions);
26 | final artifacts = await provider.getArtifacts([target]);
27 |
28 | final libs = artifacts[target]!;
29 |
30 | for (final lib in libs) {
31 | if (lib.type == AritifactType.dylib) {
32 | File(lib.path)
33 | .copySync(path.join(Environment.outputDir, lib.finalFileName));
34 | }
35 | }
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/flutter_package/example/macos/Runner/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIconFile
10 |
11 | CFBundleIdentifier
12 | $(PRODUCT_BUNDLE_IDENTIFIER)
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundleName
16 | $(PRODUCT_NAME)
17 | CFBundlePackageType
18 | APPL
19 | CFBundleShortVersionString
20 | $(FLUTTER_BUILD_NAME)
21 | CFBundleVersion
22 | $(FLUTTER_BUILD_NUMBER)
23 | LSMinimumSystemVersion
24 | $(MACOSX_DEPLOYMENT_TARGET)
25 | NSHumanReadableCopyright
26 | $(PRODUCT_COPYRIGHT)
27 | NSMainNibFile
28 | MainMenu
29 | NSPrincipalClass
30 | NSApplication
31 |
32 |
33 |
--------------------------------------------------------------------------------
/flutter_package/cargokit/build_tool/analysis_options.yaml:
--------------------------------------------------------------------------------
1 | # This file configures the static analysis results for your project (errors,
2 | # warnings, and lints).
3 | #
4 | # This enables the 'recommended' set of lints from `package:lints`.
5 | # This set helps identify many issues that may lead to problems when running
6 | # or consuming Dart code, and enforces writing Dart using a single, idiomatic
7 | # style and format.
8 | #
9 | # If you want a smaller set of lints you can change this to specify
10 | # 'package:lints/core.yaml'. These are just the most critical lints
11 | # (the recommended set includes the core lints).
12 | # The core lints are also what is used by pub.dev for scoring packages.
13 |
14 | include: package:lints/recommended.yaml
15 |
16 | # Uncomment the following section to specify additional rules.
17 |
18 | linter:
19 | rules:
20 | - prefer_relative_imports
21 | - directives_ordering
22 | # analyzer:
23 | # exclude:
24 | # - path/to/excluded/files/**
25 |
26 | # For more information about the core and recommended set of lints, see
27 | # https://dart.dev/go/core-lints
28 |
29 | # For additional information about configuring this file, see
30 | # https://dart.dev/guides/language/analysis-options
31 |
--------------------------------------------------------------------------------
/rust_crate_cli/template/native/hub/src/actors/mod.rs:
--------------------------------------------------------------------------------
1 | //! This module contains actors.
2 | //! To build a solid app, avoid communicating by sharing memory.
3 | //! Focus on message passing instead.
4 |
5 | mod first;
6 | mod second;
7 |
8 | use first::FirstActor;
9 | use messages::prelude::Context;
10 | use second::SecondActor;
11 | use tokio::spawn;
12 |
13 | // Uncomment below to target the web.
14 | // use tokio_with_wasm::alias as tokio;
15 |
16 | /// Creates and spawns the actors in the async system.
17 | pub async fn create_actors() {
18 | // Though simple async tasks work, using the actor model
19 | // is highly recommended for state management
20 | // to achieve modularity and scalability in your app.
21 | // Actors keep ownership of their state and run in their own loops,
22 | // handling messages from other actors or external sources,
23 | // such as websockets or timers.
24 |
25 | // Create actor contexts.
26 | let first_context = Context::new();
27 | let first_addr = first_context.address();
28 | let second_context = Context::new();
29 |
30 | // Spawn the actors.
31 | let first_actor = FirstActor::new(first_addr.clone());
32 | spawn(first_context.run(first_actor));
33 | let second_actor = SecondActor::new(first_addr);
34 | spawn(second_context.run(second_actor));
35 | }
36 |
--------------------------------------------------------------------------------
/flutter_package/example/README.md:
--------------------------------------------------------------------------------
1 | # Example App
2 |
3 | Demonstrates how to use the Rinf framework.
4 |
5 | ## Using Rust Inside Flutter
6 |
7 | This project leverages Flutter for GUI and Rust for the backend logic,
8 | utilizing the capabilities of the
9 | [Rinf](https://pub.dev/packages/rinf) framework.
10 |
11 | To run and build this app, you need to have
12 | [Flutter SDK](https://docs.flutter.dev/get-started/install)
13 | and [Rust toolchain](https://www.rust-lang.org/tools/install)
14 | installed on your system.
15 | You can check that your system is ready with the commands below.
16 | Note that all the Flutter subcomponents should be installed.
17 |
18 | ```shell
19 | rustc --version
20 | flutter doctor
21 | ```
22 |
23 | You also need to have the CLI tool for Rinf ready.
24 |
25 | ```shell
26 | cargo install rinf_cli
27 | ```
28 |
29 | Signals sent between Dart and Rust are implemented using signal attributes.
30 | If you've modified the signal structs, run the following command
31 | to generate the corresponding Dart classes:
32 |
33 | ```shell
34 | rinf gen
35 | ```
36 |
37 | Now you can run and build this app just like any other Flutter projects.
38 |
39 | ```shell
40 | flutter run
41 | ```
42 |
43 | For detailed instructions on writing Rust and Flutter together,
44 | please refer to Rinf's [documentation](https://rinf.cunarist.org).
45 |
--------------------------------------------------------------------------------
/documentation/source/field-attributes.md:
--------------------------------------------------------------------------------
1 | # Field Attributes
2 |
3 | To ignore a field or variant, annotate it with `#[serde(skip)]`. This is useful when transferring partially private data because it allows you to specify which data is exposed to Dart. See Serde's documentation on [variant](https://serde.rs/variant-attrs.html) and [field](https://serde.rs/field-attrs.html) attributes for more information on how Serde handles this attribute.
4 |
5 | ```{code-block} rust
6 | :caption: Rust
7 | #[derive(Serialize, RustSignal)]
8 | struct UpdateMessage {
9 | event: String,
10 | struct_data: StructData,
11 | enum_data: EnumData,
12 | }
13 |
14 | #[derive(Serialize, SignalPiece)]
15 | struct StructData {
16 | my_public_field: bool,
17 | #[serde(skip)]
18 | my_private_field: bool,
19 | }
20 |
21 | #[derive(Serialize, SignalPiece)]
22 | enum EnumData {
23 | Variant1(i32, #[serde(skip)] i32),
24 | Variant2 {
25 | my_public_field: bool,
26 | #[serde(skip)]
27 | my_private_field: bool,
28 | },
29 | }
30 | ```
31 |
32 | Some attributes from Serde are banned at compile-time. This is because `rinf gen` analyzes Rust code statically by reading type annotations, and it cannot infer the type behind special Serde attributes like `#[serde(with = "...")]`. This mechanism ensures that `rinf gen` always produces exactly corresponding Dart code from Rust structs.
33 |
--------------------------------------------------------------------------------
/flutter_package/example/web/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 | example_app
33 |
34 |
35 |
36 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/flutter_package/cargokit/build_tool/lib/src/logging.dart:
--------------------------------------------------------------------------------
1 | import 'dart:io';
2 |
3 | import 'package:logging/logging.dart';
4 |
5 | const String kSeparator = "--";
6 | const String kDoubleSeparator = "==";
7 |
8 | bool _lastMessageWasSeparator = false;
9 |
10 | void _log(LogRecord rec) {
11 | final prefix = '${rec.level.name}: ';
12 | final out = rec.level == Level.SEVERE ? stderr : stdout;
13 | if (rec.message == kSeparator) {
14 | if (!_lastMessageWasSeparator) {
15 | out.write(prefix);
16 | out.writeln('-' * 80);
17 | _lastMessageWasSeparator = true;
18 | }
19 | return;
20 | } else if (rec.message == kDoubleSeparator) {
21 | out.write(prefix);
22 | out.writeln('=' * 80);
23 | _lastMessageWasSeparator = true;
24 | return;
25 | }
26 | out.write(prefix);
27 | out.writeln(rec.message);
28 | _lastMessageWasSeparator = false;
29 | }
30 |
31 | void initLogging() {
32 | Logger.root.level = Level.INFO;
33 | Logger.root.onRecord.listen((LogRecord rec) {
34 | final lines = rec.message.split('\n');
35 | for (final line in lines) {
36 | if (line.isNotEmpty || lines.length == 1 || line != lines.last) {
37 | _log(LogRecord(
38 | rec.level,
39 | line,
40 | rec.loggerName,
41 | ));
42 | }
43 | }
44 | });
45 | }
46 |
47 | void enableVerboseLogging() {
48 | Logger.root.level = Level.ALL;
49 | }
50 |
--------------------------------------------------------------------------------
/flutter_package/example/android/app/build.gradle.kts:
--------------------------------------------------------------------------------
1 | plugins {
2 | id("com.android.application")
3 | id("kotlin-android")
4 | // The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins.
5 | id("dev.flutter.flutter-gradle-plugin")
6 | }
7 |
8 | android {
9 | namespace = "com.example.example_app"
10 | compileSdk = flutter.compileSdkVersion
11 | ndkVersion = "27.0.12077973"
12 |
13 | compileOptions {
14 | sourceCompatibility = JavaVersion.VERSION_11
15 | targetCompatibility = JavaVersion.VERSION_11
16 | }
17 |
18 | kotlinOptions {
19 | jvmTarget = JavaVersion.VERSION_11.toString()
20 | }
21 |
22 | defaultConfig {
23 | applicationId = "com.example.example_app"
24 | // You can update the following values to match your application needs.
25 | // For more information, see: https://flutter.dev/to/review-gradle-config.
26 | minSdk = flutter.minSdkVersion
27 | targetSdk = flutter.targetSdkVersion
28 | versionCode = flutter.versionCode
29 | versionName = flutter.versionName
30 | }
31 |
32 | buildTypes {
33 | release {
34 | // Signing with the debug keys for now, so `flutter run --release` works.
35 | signingConfig = signingConfigs.getByName("debug")
36 | }
37 | }
38 | }
39 |
40 | flutter {
41 | source = "../.."
42 | }
43 |
--------------------------------------------------------------------------------
/.github/workflows/registry_push.yaml:
--------------------------------------------------------------------------------
1 | # Build and push web apps to container registry
2 | name: Registry Push
3 |
4 | on:
5 | workflow_dispatch:
6 |
7 | jobs:
8 | build-and-push-demo:
9 | name: Build and Push Demo
10 | runs-on: ubuntu-latest
11 |
12 | steps:
13 | - name: Checkout repository
14 | uses: actions/checkout@v6
15 |
16 | - name: Set up Docker Buildx
17 | uses: docker/setup-buildx-action@v3
18 |
19 | - name: Build and push demo image
20 | uses: docker/build-push-action@v6
21 | with:
22 | context: .
23 | file: ./demo/Dockerfile
24 | tags: registry.cunarist.org/rinf-demo:latest
25 | push: true
26 | cache-from: type=gha
27 | cache-to: type=gha,mode=max
28 |
29 | build-and-push-docs:
30 | name: Build and Push Docs
31 | runs-on: ubuntu-latest
32 |
33 | steps:
34 | - name: Checkout repository
35 | uses: actions/checkout@v6
36 |
37 | - name: Set up Docker Buildx
38 | uses: docker/setup-buildx-action@v3
39 |
40 | - name: Build and push documentation image
41 | uses: docker/build-push-action@v6
42 | with:
43 | context: .
44 | file: ./documentation/Dockerfile
45 | tags: registry.cunarist.org/rinf-docs:latest
46 | push: true
47 | cache-from: type=gha
48 | cache-to: type=gha,mode=max
49 |
--------------------------------------------------------------------------------
/flutter_package/example/native/sample_crate/src/extras.rs:
--------------------------------------------------------------------------------
1 | //! This crate is written for Rinf demonstrations.
2 |
3 | use crate::error::ExampleError;
4 |
5 | // `machineid_rs` only supports desktop platforms.
6 | #[cfg(any(target_os = "windows", target_os = "macos", target_os = "linux"))]
7 | pub fn get_hardward_id() -> Result {
8 | let mut builder = machineid_rs::IdBuilder::new(machineid_rs::Encryption::MD5);
9 | builder
10 | .add_component(machineid_rs::HWIDComponent::SystemID)
11 | .add_component(machineid_rs::HWIDComponent::CPUCores);
12 | let hwid = builder
13 | .build("mykey")
14 | .map_err(|_| ExampleError::HardwareId)?;
15 | Ok(hwid)
16 | }
17 | #[cfg(not(any(
18 | target_os = "windows",
19 | target_os = "macos",
20 | target_os = "linux"
21 | )))]
22 | pub fn get_hardward_id() -> Result {
23 | Ok(String::from("UNSUPPORTED"))
24 | }
25 |
26 | // `chrono` supports all platforms, including web.
27 | use chrono::{DateTime, offset};
28 | pub fn get_current_time() -> DateTime {
29 | offset::Local::now()
30 | }
31 |
32 | // `reqwest` supports all platforms, including web.
33 | pub async fn fetch_from_web_api(url: &str) -> Result {
34 | let fetched = reqwest::get(url)
35 | .await
36 | .map_err(|_| ExampleError::WebApi)?
37 | .text()
38 | .await
39 | .map_err(|_| ExampleError::WebApi)?;
40 | Ok(fetched)
41 | }
42 |
--------------------------------------------------------------------------------
/demo/Dockerfile:
--------------------------------------------------------------------------------
1 | # Build Rinf example app for web
2 | FROM debian:bookworm-slim AS builder
3 |
4 | # Install dependencies
5 | RUN apt-get update && apt-get install -y \
6 | curl git unzip xz-utils zip \
7 | build-essential pkg-config libssl-dev
8 |
9 | # Install Flutter
10 | ENV FLUTTER_HOME=/opt/flutter
11 | ENV PATH="${FLUTTER_HOME}/bin:${PATH}"
12 | RUN git clone https://github.com/flutter/flutter.git -b stable ${FLUTTER_HOME}
13 |
14 | # Install Rust
15 | ENV RUSTUP_HOME=/usr/local/rustup
16 | ENV CARGO_HOME=/usr/local/cargo
17 | ENV PATH="/usr/local/cargo/bin:${PATH}"
18 | RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
19 |
20 | # Set working directory
21 | WORKDIR /workspace
22 |
23 | # Copy project files
24 | COPY flutter_package/ flutter_package/
25 | COPY rust_crate/ rust_crate/
26 | COPY rust_crate_proc/ rust_crate_proc/
27 | COPY rust_crate_cli/ rust_crate_cli/
28 | COPY Cargo.toml Cargo.toml
29 |
30 | # Install Rinf CLI from local source
31 | RUN cargo install --path rust_crate_cli
32 |
33 | # Build web app
34 | WORKDIR /workspace/flutter_package/example
35 | RUN rinf gen
36 | RUN rinf wasm --release
37 | RUN flutter build web --release
38 |
39 | # Serve the app
40 | FROM python:3.13-slim
41 |
42 | WORKDIR /app
43 |
44 | # Copy built web app
45 | COPY --from=builder /workspace/flutter_package/example/build/web .
46 |
47 | # Copy server script
48 | COPY demo/server.py .
49 |
50 | EXPOSE 80
51 |
52 | CMD ["python", "server.py"]
53 |
--------------------------------------------------------------------------------
/flutter_package/cargokit/build_tool/lib/src/cargo.dart:
--------------------------------------------------------------------------------
1 | import 'dart:io';
2 |
3 | import 'package:path/path.dart' as path;
4 | import 'package:toml/toml.dart';
5 |
6 | class ManifestException {
7 | ManifestException(this.message, {required this.fileName});
8 |
9 | final String? fileName;
10 | final String message;
11 |
12 | @override
13 | String toString() {
14 | if (fileName != null) {
15 | return 'Failed to parse package manifest at $fileName: $message';
16 | } else {
17 | return 'Failed to parse package manifest: $message';
18 | }
19 | }
20 | }
21 |
22 | class CrateInfo {
23 | CrateInfo({required this.packageName});
24 |
25 | final String packageName;
26 |
27 | static CrateInfo parseManifest(String manifest, {final String? fileName}) {
28 | final toml = TomlDocument.parse(manifest);
29 | final package = toml.toMap()['package'];
30 | if (package == null) {
31 | throw ManifestException('Missing package section', fileName: fileName);
32 | }
33 | final name = package['name'];
34 | if (name == null) {
35 | throw ManifestException('Missing package name', fileName: fileName);
36 | }
37 | return CrateInfo(packageName: name);
38 | }
39 |
40 | static CrateInfo load(String manifestDir) {
41 | final manifestFile = File(path.join(manifestDir, 'Cargo.toml'));
42 | final manifest = manifestFile.readAsStringSync();
43 | return parseManifest(manifest, fileName: manifestFile.path);
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/flutter_package/example/windows/runner/main.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 |
5 | #include "flutter_window.h"
6 | #include "utils.h"
7 |
8 | int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev,
9 | _In_ wchar_t *command_line, _In_ int show_command) {
10 | // Attach to console when present (e.g., 'flutter run') or create a
11 | // new console when running with a debugger.
12 | if (!::AttachConsole(ATTACH_PARENT_PROCESS) && ::IsDebuggerPresent()) {
13 | CreateAndAttachConsole();
14 | }
15 |
16 | // Initialize COM, so that it is available for use in the library and/or
17 | // plugins.
18 | ::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED);
19 |
20 | flutter::DartProject project(L"data");
21 |
22 | std::vector command_line_arguments =
23 | GetCommandLineArguments();
24 |
25 | project.set_dart_entrypoint_arguments(std::move(command_line_arguments));
26 |
27 | FlutterWindow window(project);
28 | Win32Window::Point origin(10, 10);
29 | Win32Window::Size size(1280, 720);
30 | if (!window.Create(L"example_app", origin, size)) {
31 | return EXIT_FAILURE;
32 | }
33 | window.SetQuitOnClose(true);
34 |
35 | ::MSG msg;
36 | while (::GetMessage(&msg, nullptr, 0, 0)) {
37 | ::TranslateMessage(&msg);
38 | ::DispatchMessage(&msg);
39 | }
40 |
41 | ::CoUninitialize();
42 | return EXIT_SUCCESS;
43 | }
44 |
--------------------------------------------------------------------------------
/documentation/source/introduction.md:
--------------------------------------------------------------------------------
1 | # Introduction
2 |
3 | ## About Rinf
4 |
5 | Rinf enables building cross-platform Rust apps, combining it with Flutter's UI ecosystem.
6 |
7 | ```{eval-rst}
8 | .. raw:: html
9 | :file: _templates/icon_pair.html
10 | ```
11 |
12 | ## Design
13 |
14 | Rinf expects the entire business logic to be written in Rust, with Flutter only serving as the UI layer.[^1]
15 |
16 | [^1]: If your business logic is written in Dart, Rinf may not be a suitable choice. Consider other solutions in such cases.
17 |
18 | 
19 |
20 | The communication system is made up of a two-way, stream-based message-passing mechanism instead of function calls. This decouples the business logic from the UI, ensuring a clear separation of concerns.
21 |
22 | It is recommended to use the actor model on the Rust side and tree-based state management techniques such as `InheritedWidget` or `provider` in Flutter for efficient state propagation.
23 |
24 | Actors in Rust should hold the state, while Flutter widgets receive only the view data needed to update the UI.
25 |
26 | ## Cross-Platform Compatibility
27 |
28 | Rinf enables seamless development across major platforms:
29 |
30 | - ✅ Linux: Tested and supported
31 | - ✅ Android: Tested and supported
32 | - ✅ Windows: Tested and supported
33 | - ✅ macOS: Tested and supported
34 | - ✅ iOS: Tested and supported
35 | - ✅ Web: Tested and supported
36 | - 🔄 [eLinux](https://github.com/sony/flutter-elinux): Currently experimental
37 |
--------------------------------------------------------------------------------
/flutter_package/lib/src/interface_web.dart:
--------------------------------------------------------------------------------
1 | // ignore_for_file: avoid_web_libraries_in_flutter
2 |
3 | import 'dart:async';
4 | import 'dart:js_interop';
5 | import 'dart:js_interop_unsafe';
6 | import 'dart:typed_data';
7 | import 'load_web.dart';
8 | import 'structure.dart';
9 |
10 | /// Sets the path to the JavaScript module
11 | /// that needs to be loaded.
12 | void setCompiledLibPathReal(String path) {
13 | setJsLibPath(path);
14 | }
15 |
16 | Future prepareInterfaceReal(AssignRustSignal assignRustSignal) async {
17 | // Load the JavaScript module.
18 | await loadJsFile();
19 |
20 | // Listen to Rust via JavaScript.
21 | rinfBindingsObject['rinf_send_rust_signal_extern'] =
22 | ((String endpoint, JSObject messageBytesJS, JSObject binaryJS) {
23 | final messageBytes = (messageBytesJS as JSUint8Array).toDart;
24 | final binary = (binaryJS as JSUint8Array).toDart;
25 | assignRustSignal[endpoint]!(messageBytes, binary);
26 | }).toJS;
27 | }
28 |
29 | void startRustLogicReal() {
30 | if (wasAlreadyLoaded) {
31 | return;
32 | }
33 | wasmBindingsObject.callMethod('rinf_start_rust_logic_extern'.toJS);
34 | }
35 |
36 | void stopRustLogicReal() {
37 | // Dummy function to match the structure of native platforms.
38 | }
39 |
40 | void sendDartSignalReal(
41 | String endpointSymbol,
42 | Uint8List messageBytes,
43 | Uint8List binary,
44 | ) {
45 | wasmBindingsObject.callMethod(
46 | endpointSymbol.toJS,
47 | messageBytes.toJS,
48 | binary.toJS,
49 | );
50 | }
51 |
--------------------------------------------------------------------------------
/rust_crate_cli/src/tool/common.rs:
--------------------------------------------------------------------------------
1 | use owo_colors::OwoColorize;
2 |
3 | use crate::SetupError;
4 | use std::ffi::OsStr;
5 | use std::net::ToSocketAddrs;
6 | use std::path::PathBuf;
7 | use std::process::Output;
8 |
9 | #[cfg(target_family = "windows")]
10 | pub static DART_BIN: &str = "dart.bat";
11 | #[cfg(target_family = "unix")]
12 | pub static DART_BIN: &str = "dart";
13 |
14 | pub fn check_internet_connection() -> bool {
15 | "pub.dev:80"
16 | .to_socket_addrs()
17 | .map(|mut addrs| addrs.next().is_some())
18 | .unwrap_or(false)
19 | }
20 |
21 | #[macro_export]
22 | macro_rules! dimmedln {
23 | ($($arg:tt)*) => {
24 | println!("{}", owo_colors::OwoColorize::dimmed(&format!($($arg)*)));
25 | };
26 | }
27 |
28 | pub trait CleanFileName {
29 | fn clean_file_name(&self) -> Result;
30 | }
31 |
32 | impl CleanFileName for PathBuf {
33 | fn clean_file_name(&self) -> Result {
34 | let file_name = self
35 | .file_name()
36 | .and_then(OsStr::to_str)
37 | .ok_or_else(|| SetupError::BadFilePath(self.to_owned()))?
38 | .to_owned();
39 | Ok(file_name)
40 | }
41 | }
42 |
43 | pub trait CaptureError {
44 | fn capture_err(self) -> Result<(), SetupError>;
45 | }
46 |
47 | impl CaptureError for Output {
48 | fn capture_err(self) -> Result<(), SetupError> {
49 | if self.status.success() {
50 | Ok(())
51 | } else {
52 | eprintln!("{}", String::from_utf8_lossy(&self.stderr).red());
53 | Err(SetupError::SubprocessError)
54 | }
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/flutter_package/cargokit/build_tool/lib/src/build_gradle.dart:
--------------------------------------------------------------------------------
1 | import 'dart:io';
2 |
3 | import 'package:logging/logging.dart';
4 | import 'package:path/path.dart' as path;
5 |
6 | import 'artifacts_provider.dart';
7 | import 'builder.dart';
8 | import 'environment.dart';
9 | import 'options.dart';
10 | import 'target.dart';
11 |
12 | final log = Logger('build_gradle');
13 |
14 | class BuildGradle {
15 | BuildGradle({required this.userOptions});
16 |
17 | final CargokitUserOptions userOptions;
18 |
19 | Future build() async {
20 | final targets = Environment.targetPlatforms.map((arch) {
21 | final target = Target.forFlutterName(arch);
22 | if (target == null) {
23 | throw Exception(
24 | "Unknown darwin target or platform: $arch, ${Environment.darwinPlatformName}");
25 | }
26 | return target;
27 | }).toList();
28 |
29 | final environment = BuildEnvironment.fromEnvironment(isAndroid: true);
30 | final provider =
31 | ArtifactProvider(environment: environment, userOptions: userOptions);
32 | final artifacts = await provider.getArtifacts(targets);
33 |
34 | for (final target in targets) {
35 | final libs = artifacts[target]!;
36 | final outputDir = path.join(Environment.outputDir, target.android!);
37 | Directory(outputDir).createSync(recursive: true);
38 |
39 | for (final lib in libs) {
40 | if (lib.type == AritifactType.dylib) {
41 | File(lib.path).copySync(path.join(outputDir, lib.finalFileName));
42 | }
43 | }
44 | }
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/flutter_package/example/macos/Podfile:
--------------------------------------------------------------------------------
1 | platform :osx, '10.14'
2 |
3 | # CocoaPods analytics sends network stats synchronously affecting flutter build latency.
4 | ENV['COCOAPODS_DISABLE_STATS'] = 'true'
5 |
6 | project 'Runner', {
7 | 'Debug' => :debug,
8 | 'Profile' => :release,
9 | 'Release' => :release,
10 | }
11 |
12 | def flutter_root
13 | generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'ephemeral', 'Flutter-Generated.xcconfig'), __FILE__)
14 | unless File.exist?(generated_xcode_build_settings_path)
15 | raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure \"flutter pub get\" is executed first"
16 | end
17 |
18 | File.foreach(generated_xcode_build_settings_path) do |line|
19 | matches = line.match(/FLUTTER_ROOT\=(.*)/)
20 | return matches[1].strip if matches
21 | end
22 | raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Flutter-Generated.xcconfig, then run \"flutter pub get\""
23 | end
24 |
25 | require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root)
26 |
27 | flutter_macos_podfile_setup
28 |
29 | target 'Runner' do
30 | use_frameworks!
31 | use_modular_headers!
32 |
33 | flutter_install_all_macos_pods File.dirname(File.realpath(__FILE__))
34 | target 'RunnerTests' do
35 | inherit! :search_paths
36 | end
37 | end
38 |
39 | post_install do |installer|
40 | installer.pods_project.targets.each do |target|
41 | flutter_additional_macos_build_settings(target)
42 | end
43 | end
44 |
--------------------------------------------------------------------------------
/flutter_package/example/ios/Podfile:
--------------------------------------------------------------------------------
1 | # Uncomment this line to define a global platform for your project
2 | # platform :ios, '12.0'
3 |
4 | # CocoaPods analytics sends network stats synchronously affecting flutter build latency.
5 | ENV['COCOAPODS_DISABLE_STATS'] = 'true'
6 |
7 | project 'Runner', {
8 | 'Debug' => :debug,
9 | 'Profile' => :release,
10 | 'Release' => :release,
11 | }
12 |
13 | def flutter_root
14 | generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__)
15 | unless File.exist?(generated_xcode_build_settings_path)
16 | raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first"
17 | end
18 |
19 | File.foreach(generated_xcode_build_settings_path) do |line|
20 | matches = line.match(/FLUTTER_ROOT\=(.*)/)
21 | return matches[1].strip if matches
22 | end
23 | raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get"
24 | end
25 |
26 | require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root)
27 |
28 | flutter_ios_podfile_setup
29 |
30 | target 'Runner' do
31 | use_frameworks!
32 | use_modular_headers!
33 |
34 | flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
35 | target 'RunnerTests' do
36 | inherit! :search_paths
37 | end
38 | end
39 |
40 | post_install do |installer|
41 | installer.pods_project.targets.each do |target|
42 | flutter_additional_ios_build_settings(target)
43 | end
44 | end
45 |
--------------------------------------------------------------------------------
/flutter_package/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "size" : "16x16",
5 | "idiom" : "mac",
6 | "filename" : "app_icon_16.png",
7 | "scale" : "1x"
8 | },
9 | {
10 | "size" : "16x16",
11 | "idiom" : "mac",
12 | "filename" : "app_icon_32.png",
13 | "scale" : "2x"
14 | },
15 | {
16 | "size" : "32x32",
17 | "idiom" : "mac",
18 | "filename" : "app_icon_32.png",
19 | "scale" : "1x"
20 | },
21 | {
22 | "size" : "32x32",
23 | "idiom" : "mac",
24 | "filename" : "app_icon_64.png",
25 | "scale" : "2x"
26 | },
27 | {
28 | "size" : "128x128",
29 | "idiom" : "mac",
30 | "filename" : "app_icon_128.png",
31 | "scale" : "1x"
32 | },
33 | {
34 | "size" : "128x128",
35 | "idiom" : "mac",
36 | "filename" : "app_icon_256.png",
37 | "scale" : "2x"
38 | },
39 | {
40 | "size" : "256x256",
41 | "idiom" : "mac",
42 | "filename" : "app_icon_256.png",
43 | "scale" : "1x"
44 | },
45 | {
46 | "size" : "256x256",
47 | "idiom" : "mac",
48 | "filename" : "app_icon_512.png",
49 | "scale" : "2x"
50 | },
51 | {
52 | "size" : "512x512",
53 | "idiom" : "mac",
54 | "filename" : "app_icon_512.png",
55 | "scale" : "1x"
56 | },
57 | {
58 | "size" : "512x512",
59 | "idiom" : "mac",
60 | "filename" : "app_icon_1024.png",
61 | "scale" : "2x"
62 | }
63 | ],
64 | "info" : {
65 | "version" : 1,
66 | "author" : "xcode"
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/documentation/source/configuration.md:
--------------------------------------------------------------------------------
1 | # Configuration
2 |
3 | ## YAML File
4 |
5 | You can customize the behavior of Rinf CLI commands by configuring the `pubspec.yaml` file. All fields are optional and it's not necessary to write them.
6 |
7 | ```{code-block} yaml
8 | :caption: pubspec.yaml
9 | rinf:
10 | gen_input_crates:
11 | - hub
12 | gen_output_dir: lib/src/bindings
13 | ```
14 |
15 | - `gen_input_crates`: A list of crate names under the `native` folder. The `rinf gen` command will search for signal structs in these crates. Each crate should be located directly under the `native` folder.
16 | - `gen_output_dir`: The directory where the generated Dart code will be placed by the `rinf gen` command.
17 |
18 | You can check the current configuration status by running the command below in the CLI.
19 |
20 | ```{code-block} shell
21 | :caption: CLI
22 | rinf config
23 | ```
24 |
25 | ## Crate Features
26 |
27 | Customizing the behavior of the Rinf crate is possible through its crate features.
28 |
29 | ```{code-block} toml
30 | :caption: native/hub/Cargo.toml
31 | rinf = { version = "0.0.0", features = ["feature-name"] }
32 | ```
33 |
34 | - `show-backtrace`: Prints the full backtrace in the CLI when a panic occurs in debug mode. In general, backtrace is not very helpful when debugging async apps, so consider using [`tracing`](https://crates.io/crates/tracing) for logging purposes. Note that this feature does not affect debugging on the web platform.
35 | - `bevy`: Implements the `Event` trait from `bevy_ecs` for `DartSignalPack`, allowing Bevy's entity component system to listen for events from Dart. This feature is highly experimental, and using it in production is not recommended.
36 |
--------------------------------------------------------------------------------
/flutter_package/example/native/hub/src/actors/counting.rs:
--------------------------------------------------------------------------------
1 | use crate::signals::{SampleNumberInput, SampleNumberOutput};
2 | use async_trait::async_trait;
3 | use messages::prelude::{Actor, Address, Context, Notifiable};
4 | use rinf::{DartSignal, RustSignal, debug_print};
5 | use tokio::task::JoinSet;
6 | use tokio_with_wasm::alias as tokio;
7 |
8 | /// The actor that holds the counter state.
9 | pub struct CountingActor {
10 | count: i32,
11 | _owned_tasks: JoinSet<()>,
12 | }
13 |
14 | impl Actor for CountingActor {}
15 |
16 | impl CountingActor {
17 | pub fn new(self_addr: Address) -> Self {
18 | let mut owned_tasks = JoinSet::new();
19 | owned_tasks.spawn(Self::listen_to_button_click(self_addr));
20 | CountingActor {
21 | count: 0,
22 | _owned_tasks: owned_tasks,
23 | }
24 | }
25 |
26 | async fn listen_to_button_click(mut self_addr: Address) {
27 | let receiver = SampleNumberInput::get_dart_signal_receiver();
28 | while let Some(signal_pack) = receiver.recv().await {
29 | let message = signal_pack.message;
30 | let _ = self_addr.notify(message).await;
31 | }
32 | }
33 | }
34 |
35 | #[async_trait]
36 | impl Notifiable for CountingActor {
37 | async fn notify(&mut self, msg: SampleNumberInput, _: &Context) {
38 | // Increase the counter number.
39 | debug_print!("{}", msg.letter);
40 | self.count += 7;
41 |
42 | // The send method is generated on structs that derive `RustSignal`.
43 | SampleNumberOutput {
44 | current_number: self.count,
45 | dummy_one: 11,
46 | dummy_two: None,
47 | dummy_three: vec![22, 33, 44, 55],
48 | }
49 | .send_signal_to_dart();
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/flutter_package/example/ios/Runner/Base.lproj/Main.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/flutter_package/lib/rinf.dart:
--------------------------------------------------------------------------------
1 | /// This module supports communication with Rust.
2 | library;
3 |
4 | import 'dart:typed_data';
5 | import 'dart:convert';
6 | import 'src/structure.dart';
7 | import 'src/interface.dart';
8 |
9 | export 'src/structure.dart' show RustSignalPack;
10 |
11 | /// Starts the `main` function in Rust.
12 | Future initializeRust(
13 | AssignRustSignal assignRustSignal, {
14 | String? compiledLibPath,
15 | }) async {
16 | // Override the default library path if provided.
17 | if (compiledLibPath != null) {
18 | setCompiledLibPathReal(compiledLibPath);
19 | }
20 |
21 | // Add the print delegation endpoint.
22 | assignRustSignal['RinfOut'] = (messageBytes, binary) {
23 | final rustReport = utf8.decode(binary);
24 | print(rustReport);
25 | };
26 |
27 | // Prepare the interface with Rust.
28 | await prepareInterfaceReal(assignRustSignal);
29 | startRustLogicReal();
30 | }
31 |
32 | /// Terminates all Rust tasks by dropping the async runtime.
33 | /// This function very briefly blocks the Dart thread
34 | /// until the async runtime in Rust is completely dropped.
35 | /// It's recommended to call this before closing your Flutter app
36 | /// to prevent potential resource leaks from Rust.
37 | /// On the web, this function has no effect as tasks are managed by
38 | /// the JavaScript runtime rather than the Rust async runtime.
39 | void finalizeRust() {
40 | stopRustLogicReal();
41 | }
42 |
43 | /// Sends a signal to Rust by using a symbol
44 | /// that exists inside local space of the loaded dynamic library.
45 | void sendDartSignal(
46 | String endpointSymbol,
47 | Uint8List messageBytes,
48 | Uint8List binary,
49 | ) {
50 | sendDartSignalReal(endpointSymbol, messageBytes, binary);
51 | }
52 |
--------------------------------------------------------------------------------
/flutter_package/lib/src/interface_os.dart:
--------------------------------------------------------------------------------
1 | import 'dart:ffi';
2 | import 'dart:typed_data';
3 | import 'dart:async';
4 | import 'dart:isolate';
5 | import 'load_os.dart';
6 | import 'structure.dart';
7 |
8 | /// Sets the exact file path of the dynamic library
9 | /// compiled from the `hub` crate.
10 | void setCompiledLibPathReal(String path) {
11 | overrideLibPath(path);
12 | }
13 |
14 | Future prepareInterfaceReal(AssignRustSignal assignRustSignal) async {
15 | // Prepare ports for communication over isolates.
16 | final rustSignalPort = ReceivePort();
17 |
18 | // Listen to Rust via isolate port.
19 | rustSignalPort.listen((rustSignalRaw) {
20 | String endpoint = rustSignalRaw[0];
21 | Uint8List? messageBytes = rustSignalRaw[1];
22 | Uint8List? binary = rustSignalRaw[2];
23 |
24 | // Rust will send null if the vector is empty.
25 | // Converting is needed on the Dart side.
26 | binary ??= Uint8List(0);
27 | // Rust will send null if the vector is empty.
28 | // Converting is needed on the Dart side.
29 | messageBytes ??= Uint8List(0);
30 |
31 | assignRustSignal[endpoint]!(messageBytes, binary);
32 | });
33 |
34 | // Make Rust prepare its isolate to send data to Dart.
35 | // This is handled by `allo_isolate`.
36 | rustLibrary.prepareIsolate(
37 | NativeApi.postCObject,
38 | rustSignalPort.sendPort.nativePort,
39 | );
40 | }
41 |
42 | void startRustLogicReal() {
43 | rustLibrary.startRustLogic();
44 | }
45 |
46 | void stopRustLogicReal() {
47 | rustLibrary.stopRustLogic();
48 | }
49 |
50 | void sendDartSignalReal(
51 | String endpointSymbol,
52 | Uint8List messageBytes,
53 | Uint8List binary,
54 | ) {
55 | rustLibrary.sendDartSignal(endpointSymbol, messageBytes, binary);
56 | }
57 |
--------------------------------------------------------------------------------
/rust_crate/src/interface_web.rs:
--------------------------------------------------------------------------------
1 | use crate::AppError;
2 | use crate::shutdown::{SHUTDOWN_EVENTS, ShutdownEventsLock};
3 | use js_sys::Uint8Array;
4 | use wasm_bindgen::prelude::{JsValue, wasm_bindgen};
5 |
6 | // There is no shutdown mechanism on the web.
7 | static _SHUTDOWN_EVENTS: &ShutdownEventsLock = &SHUTDOWN_EVENTS;
8 |
9 | pub fn start_rust_logic_real(main_fn: F) -> Result<(), AppError>
10 | where
11 | F: Fn() -> T + 'static,
12 | {
13 | // Add kind description for panics.
14 | #[cfg(debug_assertions)]
15 | {
16 | use crate::debug_print;
17 | use std::panic::set_hook;
18 | set_hook(Box::new(|panic_info| {
19 | debug_print!("A panic occurred in Rust.\n{}", panic_info);
20 | }));
21 | }
22 |
23 | // Run the main function.
24 | main_fn();
25 |
26 | Ok(())
27 | }
28 |
29 | #[wasm_bindgen]
30 | extern "C" {
31 | // The reason this extern function is marked `catch`
32 | // and returns a `Result` is that the
33 | // `rinfBindings` JavaScript object created by Dart
34 | // does not exist in web workers; it is only available
35 | // in the main JavaScript thread. Loading the function
36 | // fails in web workers.
37 | #[wasm_bindgen(js_namespace = rinfBindings, catch)]
38 | pub fn rinf_send_rust_signal_extern(
39 | endpoint: &str,
40 | message_bytes: Uint8Array,
41 | binary: Uint8Array,
42 | ) -> Result<(), JsValue>;
43 | }
44 |
45 | pub fn send_rust_signal_real(
46 | endpoint: &str,
47 | message_bytes: Vec,
48 | binary: Vec,
49 | ) -> Result<(), AppError> {
50 | let result = rinf_send_rust_signal_extern(
51 | endpoint,
52 | Uint8Array::from(message_bytes.as_slice()),
53 | Uint8Array::from(binary.as_slice()),
54 | );
55 | result.map_err(|_| AppError::NoBindings)
56 | }
57 |
--------------------------------------------------------------------------------
/documentation/source/unit-testing.md:
--------------------------------------------------------------------------------
1 | # Unit Testing
2 |
3 | ## Pure Rust
4 |
5 | Writing tests that only involve the business logic of Rust is relatively simple:
6 |
7 | ```{code-block} rust
8 | :caption: Rust
9 | #[tokio::test]
10 | async fn my_async_test() {
11 | let result = async_function().await;
12 | assert_eq!(result, 42);
13 | }
14 |
15 | async fn async_function() -> i32 {
16 | 42
17 | }
18 | ```
19 |
20 | ```{code-block} shell
21 | :caption: CLI
22 | cargo test
23 | ```
24 |
25 | ## Dart and Rust
26 |
27 | Writing tests that pass signals between Dart and Rust requires a few extra lines of code. First, you need to build the `hub` crate so that it is located in the `target` directory, and then load the dynamic library.
28 |
29 | ```{code-block} dart
30 | :caption: test/custom_test.dart
31 | import 'dart:io';
32 | import 'package:test/test.dart';
33 | import 'package:rinf/rinf.dart';
34 | import 'package:my_app/src/bindings/bindings.dart';
35 |
36 | void main() async {
37 | // Build the dynamic library and load it.
38 | await Process.run('cargo', ['build'], runInShell: true);
39 | await initializeRust(assignRustSignal, compiledLibPath: getLibPath());
40 |
41 | // Your test logic goes here.
42 | expect(42, 42);
43 | // ...
44 | }
45 |
46 |
47 | /// Gets the expected path of the dynamic library file.
48 | /// The path should reflect the project folder structure.
49 | String getLibPath() {
50 | if (Platform.isMacOS) {
51 | return 'target/debug/libhub.dylib';
52 | } else if (Platform.isLinux) {
53 | return 'target/debug/libhub.so';
54 | } else if (Platform.isWindows) {
55 | return 'target/debug/hub.dll';
56 | } else {
57 | throw UnsupportedError('This operating system is not for tests');
58 | }
59 | }
60 | ```
61 |
62 | ```{code-block} shell
63 | :caption: CLI
64 | flutter test
65 | ```
66 |
--------------------------------------------------------------------------------
/rust_crate/src/macros.rs:
--------------------------------------------------------------------------------
1 | #[macro_export]
2 | /// Writes the interface code
3 | /// needed to communicate with Dart.
4 | /// This should be used once, and only once,
5 | /// at the root of the `hub` crate.
6 | macro_rules! write_interface {
7 | () => {
8 | #[cfg(not(target_family = "wasm"))]
9 | #[unsafe(no_mangle)]
10 | extern "C" fn rinf_start_rust_logic_extern() {
11 | use rinf::debug_print;
12 | let result = $crate::start_rust_logic(main);
13 | if let Err(err) = result {
14 | debug_print!("{}", err);
15 | }
16 | }
17 |
18 | #[cfg(target_family = "wasm")]
19 | #[wasm_bindgen::prelude::wasm_bindgen]
20 | pub fn rinf_start_rust_logic_extern() {
21 | use rinf::debug_print;
22 | let result = $crate::start_rust_logic(main);
23 | if let Err(err) = result {
24 | debug_print!("{}", err);
25 | }
26 | }
27 | };
28 | }
29 |
30 | /// Delegates the printing operation to Flutter,
31 | /// which excels at handling various platforms
32 | /// including web and mobile emulators.
33 | /// When debugging, using this macro is recommended over `println!`,
34 | /// as it seamlessly adapts to different environments.
35 | /// Note that this macro does nothing in release mode.
36 | #[macro_export]
37 | macro_rules! debug_print {
38 | ( $( $t:tt )* ) => {
39 | {
40 | let rust_report = format!( $( $t )* );
41 | #[cfg(debug_assertions)]
42 | {
43 | let result = $crate::send_rust_signal(
44 | "RinfOut", // Special message ID for Rust output
45 | Vec::new(),
46 | rust_report.clone().into_bytes(),
47 | );
48 | if let Err(err) = result {
49 | println!("{}\n{}", err, rust_report);
50 | }
51 | }
52 | #[cfg(not(debug_assertions))]
53 | let _ = rust_report;
54 | }
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/documentation/Dockerfile:
--------------------------------------------------------------------------------
1 | # Build Flutter web app
2 | FROM debian:bookworm-slim AS flutter-builder
3 |
4 | # Install dependencies
5 | RUN apt-get update
6 | RUN apt-get install -y \
7 | curl git unzip xz-utils zip libglu1-mesa \
8 | build-essential pkg-config libssl-dev
9 |
10 | # Install Flutter
11 | ENV FLUTTER_HOME=/opt/flutter
12 | ENV PATH="${FLUTTER_HOME}/bin:${PATH}"
13 | RUN git clone https://github.com/flutter/flutter.git -b stable ${FLUTTER_HOME}
14 |
15 | # Install Rust
16 | ENV RUSTUP_HOME=/usr/local/rustup
17 | ENV CARGO_HOME=/usr/local/cargo
18 | ENV PATH="/usr/local/cargo/bin:${PATH}"
19 | RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
20 |
21 | # Set working directory
22 | WORKDIR /workspace
23 |
24 | # Copy only essential files for building
25 | COPY flutter_package/ flutter_package/
26 | COPY rust_crate/ rust_crate/
27 | COPY rust_crate_proc/ rust_crate_proc/
28 | COPY rust_crate_cli/ rust_crate_cli/
29 | COPY Cargo.toml Cargo.toml
30 |
31 | # Install Rinf CLI from local source
32 | RUN cargo install --path rust_crate_cli
33 |
34 | # Build Flutter web app
35 | WORKDIR /workspace/flutter_package/example
36 | RUN rinf gen
37 | RUN rinf wasm --release
38 | RUN flutter build web --release --base-href="/_static/web_app/"
39 |
40 | # Build documentation and serve
41 | FROM python:3.13-slim
42 |
43 | # Set working directory
44 | WORKDIR /app
45 |
46 | # Copy documentation files
47 | COPY documentation/ .
48 |
49 | # Copy built web app from flutter-builder stage
50 | COPY --from=flutter-builder \
51 | /workspace/flutter_package/example/build/web \
52 | source/_static/web_app/
53 |
54 | # Install dependencies
55 | RUN pip install --no-cache-dir .
56 |
57 | # Build documentation
58 | RUN sphinx-build -b dirhtml source dist/dirhtml
59 |
60 | # Expose port 80
61 | EXPOSE 80
62 |
63 | # Run the server
64 | CMD ["python", "server.py"]
65 |
--------------------------------------------------------------------------------
/flutter_package/example/ios/Runner/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleDisplayName
8 | Example App
9 | CFBundleExecutable
10 | $(EXECUTABLE_NAME)
11 | CFBundleIdentifier
12 | $(PRODUCT_BUNDLE_IDENTIFIER)
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundleName
16 | example_app
17 | CFBundlePackageType
18 | APPL
19 | CFBundleShortVersionString
20 | $(FLUTTER_BUILD_NAME)
21 | CFBundleSignature
22 | ????
23 | CFBundleVersion
24 | $(FLUTTER_BUILD_NUMBER)
25 | LSRequiresIPhoneOS
26 |
27 | UILaunchStoryboardName
28 | LaunchScreen
29 | UIMainStoryboardFile
30 | Main
31 | UISupportedInterfaceOrientations
32 |
33 | UIInterfaceOrientationPortrait
34 | UIInterfaceOrientationLandscapeLeft
35 | UIInterfaceOrientationLandscapeRight
36 |
37 | UISupportedInterfaceOrientations~ipad
38 |
39 | UIInterfaceOrientationPortrait
40 | UIInterfaceOrientationPortraitUpsideDown
41 | UIInterfaceOrientationLandscapeLeft
42 | UIInterfaceOrientationLandscapeRight
43 |
44 | CADisableMinimumFrameDurationOnPhone
45 |
46 | UIApplicationSupportsIndirectInputEvents
47 |
48 |
49 |
50 |
--------------------------------------------------------------------------------
/flutter_package/example/test/complex_signal_test.dart:
--------------------------------------------------------------------------------
1 | // Import the test package and Counter class
2 | import 'dart:io';
3 | import 'package:test/test.dart';
4 | import 'package:rinf/rinf.dart';
5 | import 'package:example_app/src/bindings/bindings.dart';
6 |
7 | Future main() async {
8 | // Build the dynamic library and load it.
9 | await Process.run('cargo', ['build'], runInShell: true);
10 | await initializeRust(assignRustSignal, compiledLibPath: getLibPath());
11 |
12 | // Start the test mechanism in Rust.
13 | final duration = Duration(milliseconds: 100);
14 | UnitTestStart().sendSignalToRust();
15 | await Future.delayed(duration);
16 |
17 | // Send signals of complex types back and forth.
18 | SerdeData.rustSignalStream.listen((signalPack) async {
19 | // Receive a signal from Rust and send it back.
20 | final serdeData = signalPack.message;
21 | serdeData.sendSignalToRust();
22 | final resultPack = await ComplexSignalTestResult.rustSignalStream.first;
23 | test('Signals should remain the same', () {
24 | expect(
25 | resultPack.message.value,
26 | true,
27 | reason: 'Signal data is different from the original:\n$serdeData',
28 | );
29 | });
30 | });
31 |
32 | // Wait for the test to be completed.
33 | await Future.delayed(duration);
34 | await UnitTestEnd.rustSignalStream.first;
35 | }
36 |
37 | /// Gets the expected path of the dynamic library file.
38 | /// The path should reflect the project folder structure.
39 | String getLibPath() {
40 | if (Platform.isMacOS) {
41 | return '../../target/debug/libhub.dylib';
42 | } else if (Platform.isLinux) {
43 | return '../../target/debug/libhub.so';
44 | } else if (Platform.isWindows) {
45 | return '../../target/debug/hub.dll';
46 | } else {
47 | throw UnsupportedError('This operating system is not for tests');
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/flutter_package/example/.metadata:
--------------------------------------------------------------------------------
1 | # This file tracks properties of this Flutter project.
2 | # Used by Flutter tool to assess capabilities and perform upgrades etc.
3 | #
4 | # This file should be version controlled and should not be manually edited.
5 |
6 | version:
7 | revision: "d8a9f9a52e5af486f80d932e838ee93861ffd863"
8 | channel: "stable"
9 |
10 | project_type: app
11 |
12 | # Tracks metadata for the flutter migrate command
13 | migration:
14 | platforms:
15 | - platform: root
16 | create_revision: d8a9f9a52e5af486f80d932e838ee93861ffd863
17 | base_revision: d8a9f9a52e5af486f80d932e838ee93861ffd863
18 | - platform: android
19 | create_revision: d8a9f9a52e5af486f80d932e838ee93861ffd863
20 | base_revision: d8a9f9a52e5af486f80d932e838ee93861ffd863
21 | - platform: ios
22 | create_revision: d8a9f9a52e5af486f80d932e838ee93861ffd863
23 | base_revision: d8a9f9a52e5af486f80d932e838ee93861ffd863
24 | - platform: linux
25 | create_revision: d8a9f9a52e5af486f80d932e838ee93861ffd863
26 | base_revision: d8a9f9a52e5af486f80d932e838ee93861ffd863
27 | - platform: macos
28 | create_revision: d8a9f9a52e5af486f80d932e838ee93861ffd863
29 | base_revision: d8a9f9a52e5af486f80d932e838ee93861ffd863
30 | - platform: web
31 | create_revision: d8a9f9a52e5af486f80d932e838ee93861ffd863
32 | base_revision: d8a9f9a52e5af486f80d932e838ee93861ffd863
33 | - platform: windows
34 | create_revision: d8a9f9a52e5af486f80d932e838ee93861ffd863
35 | base_revision: d8a9f9a52e5af486f80d932e838ee93861ffd863
36 |
37 | # User provided section
38 |
39 | # List of Local paths (relative to this file) that should be
40 | # ignored by the migrate tool.
41 | #
42 | # Files that are not part of the templates will be ignored by default.
43 | unmanaged_files:
44 | - 'lib/main.dart'
45 | - 'ios/Runner.xcodeproj/project.pbxproj'
46 |
--------------------------------------------------------------------------------
/documentation/source/applying-template.md:
--------------------------------------------------------------------------------
1 | # Applying Rust Template
2 |
3 | ```{note}
4 | This section assumes that you've already created a Flutter project with `flutter create [my_app_name]`. You can get further guidance from [this awesome Flutter tutorial](https://docs.flutter.dev/get-started/codelab).
5 | ```
6 |
7 | First of all, add this framework to your Flutter project.
8 |
9 | ```{code-block} shell
10 | :caption: CLI
11 | flutter pub add rinf
12 | ```
13 |
14 | Now install the command executable to easily run Rinf commands in the CLI.[^1]
15 |
16 | [^1]: If you're curious about all the available commands, use `rinf --help`.
17 |
18 | ```{code-block} shell
19 | :caption: CLI
20 | cargo install rinf_cli
21 | ```
22 |
23 | Then, simply run this in the command-line from your Flutter project's directory.
24 |
25 | ```{code-block} shell
26 | :caption: CLI
27 | rinf template
28 | ```
29 |
30 | After running the command, you'll have new files and folders as your starter Rust template.
31 |
32 | ```{code-block} diff
33 | :caption: Folder Tree
34 | my_flutter_project/
35 | ├── android/
36 | ├── ios/
37 | ├── lib/
38 | * │ ├── main.dart
39 | │ └── ...
40 | ├── linux/
41 | + ├── native/
42 | + │ ├── hub/
43 | + │ │ ├── src/
44 | + │ │ └── Cargo.toml
45 | + │ └── README.md
46 | ├── web/
47 | ├── windows/
48 | * ├── .gitignore
49 | + ├── Cargo.toml
50 | * ├── pubspec.yaml
51 | * ├── README.md
52 | └── ...
53 | ```
54 |
55 | Various comments are written in the actual code to help you understand the whole structure.
56 |
57 | If you already have a Rust crate that you want to use here, just put it inside `native` and set it as a dependency of the `hub` crate.
58 |
59 | Now, by heading over to `native/hub/src/lib.rs`, you can start writing Rust!
60 |
61 | Example code for guidance can be found [here](https://github.com/cunarist/rinf/tree/main/flutter_package/example).
62 |
--------------------------------------------------------------------------------
/flutter_package/cargokit/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright 2022 Matej Knopp
2 |
3 | ================================================================================
4 |
5 | MIT LICENSE
6 |
7 | Permission is hereby granted, free of charge, to any person obtaining a copy
8 | of this software and associated documentation files (the "Software"), to deal
9 | in the Software without restriction, including without limitation the rights
10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
11 | of the Software, and to permit persons to whom the Software is furnished to do
12 | so, subject to the following conditions:
13 |
14 | The above copyright notice and this permission notice shall be included in all
15 | copies or substantial portions of the Software.
16 |
17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
19 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
20 | OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
22 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 |
24 | ================================================================================
25 |
26 | APACHE LICENSE, VERSION 2.0
27 |
28 | Licensed under the Apache License, Version 2.0 (the "License");
29 | you may not use this file except in compliance with the License.
30 | You may obtain a copy of the License at
31 |
32 | http://www.apache.org/licenses/LICENSE-2.0
33 |
34 | Unless required by applicable law or agreed to in writing, software
35 | distributed under the License is distributed on an "AS IS" BASIS,
36 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
37 | See the License for the specific language governing permissions and
38 | limitations under the License.
39 |
40 |
--------------------------------------------------------------------------------
/flutter_package/android/build.gradle:
--------------------------------------------------------------------------------
1 | group = "com.cunarist.rinf"
2 | version = "1.0-SNAPSHOT"
3 |
4 | buildscript {
5 | ext.kotlin_version = "1.7.10"
6 | repositories {
7 | google()
8 | mavenCentral()
9 | }
10 |
11 | dependencies {
12 | classpath("com.android.tools.build:gradle:7.3.0")
13 | classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version")
14 | }
15 | }
16 |
17 | allprojects {
18 | repositories {
19 | google()
20 | mavenCentral()
21 | }
22 | }
23 |
24 | apply plugin: "com.android.library"
25 | apply plugin: "kotlin-android"
26 |
27 | android {
28 | if (project.android.hasProperty("namespace")) {
29 | namespace = "com.cunarist.rinf"
30 | }
31 |
32 | compileSdk = 34
33 |
34 | compileOptions {
35 | sourceCompatibility = JavaVersion.VERSION_1_8
36 | targetCompatibility = JavaVersion.VERSION_1_8
37 | }
38 |
39 | kotlinOptions {
40 | jvmTarget = "1.8"
41 | }
42 |
43 | sourceSets {
44 | main.java.srcDirs += "src/main/kotlin"
45 | test.java.srcDirs += "src/test/kotlin"
46 | }
47 |
48 | defaultConfig {
49 | minSdk = 21
50 | }
51 |
52 | dependencies {
53 | testImplementation("org.jetbrains.kotlin:kotlin-test")
54 | testImplementation("org.mockito:mockito-core:5.0.0")
55 | }
56 |
57 | testOptions {
58 | unitTests.all {
59 | useJUnitPlatform()
60 |
61 | testLogging {
62 | events "passed", "skipped", "failed", "standardOut", "standardError"
63 | outputs.upToDateWhen {false}
64 | showStandardStreams = true
65 | }
66 | }
67 | }
68 | }
69 |
70 | // Include Rust crates in the build process
71 | apply from: "../cargokit/gradle/plugin.gradle"
72 | cargokit {
73 | manifestDir = "${rootProject.projectDir}/../native/hub"
74 | libname = "hub"
75 | }
76 |
--------------------------------------------------------------------------------
/rust_crate/src/interface.rs:
--------------------------------------------------------------------------------
1 | use crate::AppError;
2 |
3 | #[cfg(not(target_family = "wasm"))]
4 | use crate::interface_os::{send_rust_signal_real, start_rust_logic_real};
5 | #[cfg(target_family = "wasm")]
6 | use crate::interface_web::{send_rust_signal_real, start_rust_logic_real};
7 |
8 | /// This contains a message from Dart.
9 | /// Optionally, a custom binary called `binary` can also be included.
10 | #[cfg_attr(feature = "bevy", derive(bevy_ecs::event::Event))]
11 | pub struct DartSignalPack {
12 | /// The message instance.
13 | pub message: T,
14 | /// Binary data included in the signal.
15 | /// This field is useful for sending custom bytes
16 | /// without the overhead of serialization/deserialization.
17 | pub binary: Vec,
18 | }
19 |
20 | /// Runs the async main function in Rust.
21 | /// On native platforms, futures usually implement the `Send` trait
22 | /// to be safely sent between threads.
23 | /// Even in a single-threaded (current-thread) runtime,
24 | /// the `Runtime` object itself might be moved between threads,
25 | /// along with all the tasks it manages.
26 | #[doc(hidden)]
27 | #[cfg(not(target_family = "wasm"))]
28 | pub fn start_rust_logic(main_fn: F) -> Result<(), AppError>
29 | where
30 | F: Fn() -> T + Send + 'static,
31 | {
32 | start_rust_logic_real(main_fn)
33 | }
34 |
35 | /// Runs the async main function in Rust.
36 | /// On the web, futures usually don't implement the `Send` trait
37 | /// because JavaScript environment is fundamentally single-threaded.
38 | #[cfg(target_family = "wasm")]
39 | pub fn start_rust_logic(main_fn: F) -> Result<(), AppError>
40 | where
41 | F: Fn() -> T + 'static,
42 | {
43 | start_rust_logic_real(main_fn)
44 | }
45 |
46 | /// Send a signal to Dart.
47 | #[doc(hidden)]
48 | pub fn send_rust_signal(
49 | endpoint: &str,
50 | message_bytes: Vec,
51 | binary: Vec,
52 | ) -> Result<(), AppError> {
53 | send_rust_signal_real(endpoint, message_bytes, binary)
54 | }
55 |
--------------------------------------------------------------------------------
/flutter_package/example/windows/runner/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 3.14)
2 | project(runner LANGUAGES CXX)
3 |
4 | # Define the application target. To change its name, change BINARY_NAME in the
5 | # top-level CMakeLists.txt, not the value here, or `flutter run` will no longer
6 | # work.
7 | #
8 | # Any new source files that you add to the application should be added here.
9 | add_executable(${BINARY_NAME} WIN32
10 | "flutter_window.cpp"
11 | "main.cpp"
12 | "utils.cpp"
13 | "win32_window.cpp"
14 | "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc"
15 | "Runner.rc"
16 | "runner.exe.manifest"
17 | )
18 |
19 | # Apply the standard set of build settings. This can be removed for applications
20 | # that need different build settings.
21 | apply_standard_settings(${BINARY_NAME})
22 |
23 | # Add preprocessor definitions for the build version.
24 | target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION=\"${FLUTTER_VERSION}\"")
25 | target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_MAJOR=${FLUTTER_VERSION_MAJOR}")
26 | target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_MINOR=${FLUTTER_VERSION_MINOR}")
27 | target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_PATCH=${FLUTTER_VERSION_PATCH}")
28 | target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_BUILD=${FLUTTER_VERSION_BUILD}")
29 |
30 | # Disable Windows macros that collide with C++ standard library functions.
31 | target_compile_definitions(${BINARY_NAME} PRIVATE "NOMINMAX")
32 |
33 | # Add dependency libraries and include directories. Add any application-specific
34 | # dependencies here.
35 | target_link_libraries(${BINARY_NAME} PRIVATE flutter flutter_wrapper_app)
36 | target_link_libraries(${BINARY_NAME} PRIVATE "dwmapi.lib")
37 | target_include_directories(${BINARY_NAME} PRIVATE "${CMAKE_SOURCE_DIR}")
38 |
39 | # Run the Flutter tool portions of the build. This must not be removed.
40 | add_dependencies(${BINARY_NAME} flutter_assemble)
41 |
--------------------------------------------------------------------------------
/flutter_package/macos/rinf.podspec:
--------------------------------------------------------------------------------
1 | #
2 | # To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html.
3 | # Run `pod lib lint rinf.podspec` to validate before publishing.
4 | #
5 | Pod::Spec.new do |s|
6 | s.name = 'rinf'
7 | s.version = '0.1.0'
8 | s.summary = 'Summary'
9 | s.description = 'Description'
10 | s.homepage = 'http://cunarist.org'
11 | s.license = { :file => '../LICENSE' }
12 | s.author = { 'Your Company' => 'email@cunarist.org' }
13 |
14 | # This will ensure the source files in Classes/ are included in the native
15 | # builds of apps using this FFI plugin. Podspec does not support relative
16 | # paths, so Classes contains a forwarder C file that relatively imports
17 | # `../src/*` so that the C sources can be shared among all target platforms.
18 | s.source = { :path => '.' }
19 | s.source_files = 'Classes/**/*'
20 | s.dependency 'FlutterMacOS'
21 |
22 | s.platform = :osx, '10.11'
23 | s.swift_version = '5.0'
24 |
25 | # Include Rust crates in the build process.
26 | s.script_phase = {
27 | :name => 'Build a Rust library',
28 | :script => 'sh ${PODS_TARGET_SRCROOT}/../cargokit/build_pod.sh ${PROJECT_DIR}/../../native/hub hub',
29 | :execution_position=> :before_compile,
30 | :input_files => ['${BUILT_PRODUCTS_DIR}/cargokit_phony'],
31 | # Let XCode know that the static library referenced in -force_load below is
32 | # created by this build step.
33 | :output_files => ["${BUILT_PRODUCTS_DIR}/libhub.a"],
34 | }
35 | s.pod_target_xcconfig = {
36 | 'DEFINES_MODULE' => 'YES',
37 | # Flutter.framework does not contain a i386 slice.
38 | 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'i386',
39 | # We use `-force_load` instead of `-l` since Xcode strips out unused symbols from static libraries.
40 | 'OTHER_LDFLAGS' => '-force_load ${BUILT_PRODUCTS_DIR}/libhub.a -Wl -undefined dynamic_lookup',
41 | }
42 | end
43 |
--------------------------------------------------------------------------------
/flutter_package/ios/rinf.podspec:
--------------------------------------------------------------------------------
1 | #
2 | # To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html.
3 | # Run `pod lib lint rinf.podspec` to validate before publishing.
4 | #
5 | Pod::Spec.new do |s|
6 | s.name = 'rinf'
7 | s.version = '0.1.0'
8 | s.summary = 'Summary'
9 | s.description = 'Description'
10 | s.homepage = 'http://cunarist.org'
11 | s.license = { :file => '../LICENSE' }
12 | s.author = { 'Your Company' => 'email@cunarist.org' }
13 |
14 | # This will ensure the source files in Classes/ are included in the native
15 | # builds of apps using this FFI plugin. Podspec does not support relative
16 | # paths, so Classes contains a forwarder C file that relatively imports
17 | # `../src/*` so that the C sources can be shared among all target platforms.
18 | s.source = { :path => '.' }
19 | s.source_files = 'Classes/**/*'
20 | s.dependency 'Flutter'
21 |
22 | s.platform = :ios, '11.0'
23 | s.swift_version = '5.0'
24 |
25 | # Include Rust crates in the build process.
26 | s.script_phase = {
27 | :name => 'Build a Rust library',
28 | :script => 'sh ${PODS_TARGET_SRCROOT}/../cargokit/build_pod.sh ${PROJECT_DIR}/../../native/hub hub',
29 | :execution_position=> :before_compile,
30 | :input_files => ['${BUILT_PRODUCTS_DIR}/cargokit_phony'],
31 | # Let XCode know that the static library referenced in -force_load below is
32 | # created by this build step.
33 | :output_files => ["${BUILT_PRODUCTS_DIR}/libhub.a"],
34 | }
35 | s.pod_target_xcconfig = {
36 | 'DEFINES_MODULE' => 'YES',
37 | # Flutter framework does not contain a i386 slice. From default Flutter template.
38 | 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'i386',
39 | # We use `-force_load` instead of `-l` since Xcode strips out unused symbols from static libraries.
40 | 'OTHER_LDFLAGS' => '-force_load ${BUILT_PRODUCTS_DIR}/libhub.a -Wl -undefined dynamic_lookup',
41 | }
42 | end
43 |
--------------------------------------------------------------------------------
/documentation/source/graceful-shutdown.md:
--------------------------------------------------------------------------------
1 | # Graceful Shutdown
2 |
3 | When the Flutter app is closed, the entire async runtime on the Rust side doesn't get dropped by default.
4 |
5 | In some cases, you might need to drop all Rust resources properly before closing the app. This could include instances of structs that implement the `Drop` trait, which have roles like saving files or disposing of resources.
6 |
7 | To achieve this, you can utilize Flutter's `AppLifecycleListener` to call the `finalizeRust` function before closing the Flutter app.
8 |
9 | ```{code-block} dart
10 | :caption: lib/main.dart
11 | import 'dart:ui';
12 | import 'package:flutter/material.dart';
13 | import 'package:rinf/rinf.dart';
14 |
15 | class MyApp extends StatefulWidget {
16 | const MyApp({super.key});
17 | @override
18 | State createState() => _MyAppState();
19 | }
20 |
21 | class _MyAppState extends State {
22 | late final AppLifecycleListener _listener;
23 |
24 | @override
25 | void initState() {
26 | super.initState();
27 | _listener = AppLifecycleListener(
28 | onExitRequested: () async {
29 | finalizeRust(); // Shut down the async Rust runtime.
30 | return AppExitResponse.exit;
31 | },
32 | );
33 | }
34 |
35 | @override
36 | void dispose() {
37 | _listener.dispose();
38 | super.dispose();
39 | }
40 |
41 | @override
42 | Widget build(BuildContext context) {
43 | // Return a widget.
44 | }
45 | }
46 | ```
47 |
48 | It's worth noting that `AppLifecycleListener` cannot always be relied upon for app closings. Below is a text snippet quoted from the official [Flutter docs](https://api.flutter.dev/flutter/widgets/State/dispose.html):
49 |
50 | > There is no way to predict when application shutdown will happen. For example, a user's battery could catch fire, or the user could drop the device into a swimming pool, or the operating system could unilaterally terminate the application process due to memory pressure. Applications are responsible for ensuring they behave well even in the face of rapid, unscheduled termination.
51 |
--------------------------------------------------------------------------------
/flutter_package/example/windows/runner/utils.cpp:
--------------------------------------------------------------------------------
1 | #include "utils.h"
2 |
3 | #include
4 | #include
5 | #include
6 | #include
7 |
8 | #include
9 |
10 | void CreateAndAttachConsole() {
11 | if (::AllocConsole()) {
12 | FILE *unused;
13 | if (freopen_s(&unused, "CONOUT$", "w", stdout)) {
14 | _dup2(_fileno(stdout), 1);
15 | }
16 | if (freopen_s(&unused, "CONOUT$", "w", stderr)) {
17 | _dup2(_fileno(stdout), 2);
18 | }
19 | std::ios::sync_with_stdio();
20 | FlutterDesktopResyncOutputStreams();
21 | }
22 | }
23 |
24 | std::vector GetCommandLineArguments() {
25 | // Convert the UTF-16 command line arguments to UTF-8 for the Engine to use.
26 | int argc;
27 | wchar_t** argv = ::CommandLineToArgvW(::GetCommandLineW(), &argc);
28 | if (argv == nullptr) {
29 | return std::vector();
30 | }
31 |
32 | std::vector command_line_arguments;
33 |
34 | // Skip the first argument as it's the binary name.
35 | for (int i = 1; i < argc; i++) {
36 | command_line_arguments.push_back(Utf8FromUtf16(argv[i]));
37 | }
38 |
39 | ::LocalFree(argv);
40 |
41 | return command_line_arguments;
42 | }
43 |
44 | std::string Utf8FromUtf16(const wchar_t* utf16_string) {
45 | if (utf16_string == nullptr) {
46 | return std::string();
47 | }
48 | unsigned int target_length = ::WideCharToMultiByte(
49 | CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string,
50 | -1, nullptr, 0, nullptr, nullptr)
51 | -1; // remove the trailing null character
52 | int input_length = (int)wcslen(utf16_string);
53 | std::string utf8_string;
54 | if (target_length == 0 || target_length > utf8_string.max_size()) {
55 | return utf8_string;
56 | }
57 | utf8_string.resize(target_length);
58 | int converted_length = ::WideCharToMultiByte(
59 | CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string,
60 | input_length, utf8_string.data(), target_length, nullptr, nullptr);
61 | if (converted_length == 0) {
62 | return std::string();
63 | }
64 | return utf8_string;
65 | }
66 |
--------------------------------------------------------------------------------
/flutter_package/cargokit/build_pod.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | set -e
3 |
4 | BASEDIR=$(dirname "$0")
5 |
6 | # Workaround for https://github.com/dart-lang/pub/issues/4010
7 | BASEDIR=$(cd "$BASEDIR" ; pwd -P)
8 |
9 | # Remove XCode SDK from path. Otherwise this breaks tool compilation when building iOS project
10 | NEW_PATH=`echo $PATH | tr ":" "\n" | grep -v "Contents/Developer/" | tr "\n" ":"`
11 |
12 | export PATH=${NEW_PATH%?} # remove trailing :
13 |
14 | env
15 |
16 | # Platform name (macosx, iphoneos, iphonesimulator)
17 | export CARGOKIT_DARWIN_PLATFORM_NAME=$PLATFORM_NAME
18 |
19 | # Arctive architectures (arm64, armv7, x86_64), space separated.
20 | export CARGOKIT_DARWIN_ARCHS=$ARCHS
21 |
22 | # Current build configuration (Debug, Release)
23 | export CARGOKIT_CONFIGURATION=$CONFIGURATION
24 |
25 | # Path to directory containing Cargo.toml.
26 | export CARGOKIT_MANIFEST_DIR=$1 #Different from upstream
27 |
28 | # Temporary directory for build artifacts.
29 | export CARGOKIT_TARGET_TEMP_DIR=$TARGET_TEMP_DIR
30 |
31 | # Output directory for final artifacts.
32 | export CARGOKIT_OUTPUT_DIR=$PODS_CONFIGURATION_BUILD_DIR/$PRODUCT_NAME
33 |
34 | # Directory to store built tool artifacts.
35 | export CARGOKIT_TOOL_TEMP_DIR=$TARGET_TEMP_DIR/build_tool
36 |
37 | # Directory inside root project. Not necessarily the top level directory of root project.
38 | export CARGOKIT_ROOT_PROJECT_DIR=$SRCROOT
39 |
40 | FLUTTER_EXPORT_BUILD_ENVIRONMENT=(
41 | "$PODS_ROOT/../Flutter/ephemeral/flutter_export_environment.sh" # macOS
42 | "$PODS_ROOT/../Flutter/flutter_export_environment.sh" # iOS
43 | )
44 |
45 | for path in "${FLUTTER_EXPORT_BUILD_ENVIRONMENT[@]}"
46 | do
47 | if [[ -f "$path" ]]; then
48 | source "$path"
49 | fi
50 | done
51 |
52 | sh "$BASEDIR/run_build_tool.sh" build-pod "$@"
53 |
54 | # Make a symlink from built framework to phony file, which will be used as input to
55 | # build script. This should force rebuild (podspec currently doesn't support alwaysOutOfDate
56 | # attribute on custom build phase)
57 | ln -fs "$OBJROOT/XCBuildData/build.db" "${BUILT_PRODUCTS_DIR}/cargokit_phony"
58 | ln -fs "${BUILT_PRODUCTS_DIR}/${EXECUTABLE_PATH}" "${BUILT_PRODUCTS_DIR}/cargokit_phony_out"
59 |
--------------------------------------------------------------------------------
/flutter_package/lib/src/load_web.dart:
--------------------------------------------------------------------------------
1 | // ignore_for_file: avoid_web_libraries_in_flutter
2 |
3 | import 'dart:async';
4 | import 'dart:js_interop';
5 | import 'dart:js_interop_unsafe';
6 | import 'package:web/web.dart';
7 |
8 | String? jsLibPath;
9 |
10 | void setJsLibPath(String path) {
11 | jsLibPath = path;
12 | }
13 |
14 | bool wasAlreadyLoaded = false;
15 | final rinfBindingsObject = globalContext['rinfBindings'] as JSObject;
16 | final wasmBindingsObject = globalContext['wasmBindings'] as JSObject;
17 |
18 | Future loadJsFile() async {
19 | // When Dart performs hot restart,
20 | // the `rinfBindings` JavaScript object is already defined
21 | // as a global JavaScript variable.
22 | wasAlreadyLoaded = globalContext.hasProperty('rinfBindings'.toJS).toDart;
23 |
24 | // Stop loading if it already has been done.
25 | if (wasAlreadyLoaded) {
26 | return;
27 | }
28 |
29 | // Create the namespace JavaScript object.
30 | // This namespace object is used by Rust
31 | // to call functions defined in Dart.
32 | globalContext['rinfBindings'] = JSObject();
33 |
34 | // Prepare to await the module load.
35 | final loadCompleter = Completer();
36 | rinfBindingsObject['completeRinfLoad'] = (() {
37 | loadCompleter.complete();
38 | }).toJS;
39 |
40 | // Get the domain and the base path.
41 | // Flutter app doesn't always have the top-level path of the domain.
42 | // Sometimes, the flutter app might be placed in a lower path.
43 | final baseHref = Uri.base;
44 | final path = jsLibPath ?? 'pkg/hub.js';
45 | final fullUrl = baseHref.resolve(path);
46 |
47 | // Insert the script element into the document head.
48 | // This will load the webassembly module.
49 | final scriptElement = HTMLScriptElement();
50 | scriptElement.type = 'module';
51 | scriptElement.innerHTML =
52 | '''
53 | import init, * as wasmBindings from "$fullUrl";
54 | globalThis.wasmBindings = wasmBindings;
55 | await init();
56 | rinfBindings.completeRinfLoad();
57 | delete rinfBindings.completeRinfLoad;
58 | '''
59 | .toJS;
60 | document.head!.append(scriptElement);
61 |
62 | // Await for the module to load.
63 | await loadCompleter.future;
64 | }
65 |
--------------------------------------------------------------------------------
/documentation/source/_static/flutter_icon.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/documentation/source/_templates/landing.html:
--------------------------------------------------------------------------------
1 |
26 |
27 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
Rinf
87 |
RUST IN FLUTTER
88 |
89 |
90 |
91 |
--------------------------------------------------------------------------------
/flutter_package/example/android/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
15 |
19 |
23 |
24 |
25 |
26 |
27 |
28 |
30 |
33 |
34 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/flutter_package/example/windows/runner/flutter_window.cpp:
--------------------------------------------------------------------------------
1 | #include "flutter_window.h"
2 |
3 | #include
4 |
5 | #include "flutter/generated_plugin_registrant.h"
6 |
7 | FlutterWindow::FlutterWindow(const flutter::DartProject& project)
8 | : project_(project) {}
9 |
10 | FlutterWindow::~FlutterWindow() {}
11 |
12 | bool FlutterWindow::OnCreate() {
13 | if (!Win32Window::OnCreate()) {
14 | return false;
15 | }
16 |
17 | RECT frame = GetClientArea();
18 |
19 | // The size here must match the window dimensions to avoid unnecessary surface
20 | // creation / destruction in the startup path.
21 | flutter_controller_ = std::make_unique(
22 | frame.right - frame.left, frame.bottom - frame.top, project_);
23 | // Ensure that basic setup of the controller was successful.
24 | if (!flutter_controller_->engine() || !flutter_controller_->view()) {
25 | return false;
26 | }
27 | RegisterPlugins(flutter_controller_->engine());
28 | SetChildContent(flutter_controller_->view()->GetNativeWindow());
29 |
30 | flutter_controller_->engine()->SetNextFrameCallback([&]() {
31 | this->Show();
32 | });
33 |
34 | // Flutter can complete the first frame before the "show window" callback is
35 | // registered. The following call ensures a frame is pending to ensure the
36 | // window is shown. It is a no-op if the first frame hasn't completed yet.
37 | flutter_controller_->ForceRedraw();
38 |
39 | return true;
40 | }
41 |
42 | void FlutterWindow::OnDestroy() {
43 | if (flutter_controller_) {
44 | flutter_controller_ = nullptr;
45 | }
46 |
47 | Win32Window::OnDestroy();
48 | }
49 |
50 | LRESULT
51 | FlutterWindow::MessageHandler(HWND hwnd, UINT const message,
52 | WPARAM const wparam,
53 | LPARAM const lparam) noexcept {
54 | // Give Flutter, including plugins, an opportunity to handle window messages.
55 | if (flutter_controller_) {
56 | std::optional result =
57 | flutter_controller_->HandleTopLevelWindowProc(hwnd, message, wparam,
58 | lparam);
59 | if (result) {
60 | return *result;
61 | }
62 | }
63 |
64 | switch (message) {
65 | case WM_FONTCHANGE:
66 | flutter_controller_->engine()->ReloadSystemFonts();
67 | break;
68 | }
69 |
70 | return Win32Window::MessageHandler(hwnd, message, wparam, lparam);
71 | }
72 |
--------------------------------------------------------------------------------
/flutter_package/cargokit/build_tool/lib/src/environment.dart:
--------------------------------------------------------------------------------
1 | import 'dart:io';
2 |
3 | extension on String {
4 | String resolveSymlink() => File(this).resolveSymbolicLinksSync();
5 | }
6 |
7 | class Environment {
8 | /// Current build configuration (debug or release).
9 | static String get configuration =>
10 | _getEnv("CARGOKIT_CONFIGURATION").toLowerCase();
11 |
12 | static bool get isDebug => configuration == 'debug';
13 | static bool get isRelease => configuration == 'release';
14 |
15 | /// Temporary directory where Rust build artifacts are placed.
16 | static String get targetTempDir => _getEnv("CARGOKIT_TARGET_TEMP_DIR");
17 |
18 | /// Final output directory where the build artifacts are placed.
19 | static String get outputDir => _getEnvPath('CARGOKIT_OUTPUT_DIR');
20 |
21 | /// Path to the crate manifest (containing Cargo.toml).
22 | static String get manifestDir => _getEnvPath('CARGOKIT_MANIFEST_DIR');
23 |
24 | /// Directory inside root project. Not necessarily root folder. Symlinks are
25 | /// not resolved on purpose.
26 | static String get rootProjectDir => _getEnv('CARGOKIT_ROOT_PROJECT_DIR');
27 |
28 | // Pod
29 |
30 | /// Platform name (macosx, iphoneos, iphonesimulator).
31 | static String get darwinPlatformName =>
32 | _getEnv("CARGOKIT_DARWIN_PLATFORM_NAME");
33 |
34 | /// List of architectures to build for (arm64, armv7, x86_64).
35 | static List get darwinArchs =>
36 | _getEnv("CARGOKIT_DARWIN_ARCHS").split(' ');
37 |
38 | // Gradle
39 | static String get minSdkVersion => _getEnv("CARGOKIT_MIN_SDK_VERSION");
40 | static String get ndkVersion => _getEnv("CARGOKIT_NDK_VERSION");
41 | static String get sdkPath => _getEnvPath("CARGOKIT_SDK_DIR");
42 | static String get javaHome => _getEnvPath("CARGOKIT_JAVA_HOME");
43 | static List get targetPlatforms =>
44 | _getEnv("CARGOKIT_TARGET_PLATFORMS").split(',');
45 |
46 | // CMAKE
47 | static String get targetPlatform => _getEnv("CARGOKIT_TARGET_PLATFORM");
48 |
49 | static String _getEnv(String key) {
50 | final res = Platform.environment[key];
51 | if (res == null) {
52 | throw Exception("Missing environment variable $key");
53 | }
54 | return res;
55 | }
56 |
57 | static String _getEnvPath(String key) {
58 | final res = _getEnv(key);
59 | if (Directory(res).existsSync()) {
60 | return res.resolveSymlink();
61 | } else {
62 | return res;
63 | }
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/rust_crate_cli/src/tool/config.rs:
--------------------------------------------------------------------------------
1 | use crate::SetupError;
2 | use serde::Deserialize;
3 | use serde_yml::{Value, from_str, from_value};
4 | use std::fmt::{Display, Formatter};
5 | use std::fs::read_to_string;
6 | use std::path::Path;
7 |
8 | /// Rinf message configuration structure.
9 | #[derive(Deserialize)]
10 | pub struct RinfConfig {
11 | #[serde(default = "create_default_gen_input_crates")]
12 | pub gen_input_crates: Vec,
13 | #[serde(default = "create_default_gen_output_dir")]
14 | pub gen_output_dir: String,
15 | }
16 |
17 | impl Display for RinfConfig {
18 | fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
19 | write!(
20 | f,
21 | "gen_input_crates: {}\
22 | \ngen_output_dir: {}",
23 | self.gen_input_crates.join(", "),
24 | self.gen_output_dir,
25 | )
26 | }
27 | }
28 |
29 | impl Default for RinfConfig {
30 | fn default() -> Self {
31 | Self {
32 | gen_input_crates: create_default_gen_input_crates(),
33 | gen_output_dir: create_default_gen_output_dir(),
34 | }
35 | }
36 | }
37 |
38 | fn create_default_gen_input_crates() -> Vec {
39 | vec!["hub".to_owned()]
40 | }
41 |
42 | fn create_default_gen_output_dir() -> String {
43 | "lib/src/bindings".to_owned()
44 | }
45 |
46 | /// Attempts to load the rinf configuration from the provided pubspec.yaml file.
47 | /// If no rinf configuration is found, the default configuration is returned.
48 | /// If the Rinf configuration is invalid, an exception is thrown.
49 | /// Otherwise it loads all values found in the config, using defaults for missing values.
50 | pub fn load_verified_rinf_config(
51 | root_dir: &Path,
52 | ) -> Result {
53 | let file_path = root_dir.join("pubspec.yaml");
54 | let content = read_to_string(file_path)?;
55 | let file_yaml: Value = from_str(&content)?;
56 | let rinf_yaml = file_yaml
57 | .as_mapping()
58 | .ok_or(SetupError::PubConfig("Parsing failed".to_owned()))?
59 | .get("rinf")
60 | .cloned();
61 | let config = match rinf_yaml {
62 | Some(map) => from_value(map)?,
63 | None => RinfConfig::default(),
64 | };
65 | Ok(config)
66 | }
67 |
68 | pub fn read_publish_to(file_path: &Path) -> Option {
69 | let content = std::fs::read_to_string(file_path).ok()?;
70 | let file_yaml: Value = from_str(&content).ok()?;
71 | let field_value = file_yaml.as_mapping()?.get("publish_to")?;
72 | let config = field_value.as_str()?.to_string();
73 | Some(config)
74 | }
75 |
--------------------------------------------------------------------------------
/documentation/source/running-and-building.md:
--------------------------------------------------------------------------------
1 | # Running and Building
2 |
3 | ## For Native Platforms
4 |
5 | The following commands are just enough to run and build apps for native platforms. It's that simple.[^1]
6 |
7 | [^1]: Rinf builds the native Rust library and links it to the Flutter app using [Cargokit](https://github.com/irondash/cargokit).
8 |
9 | To run the app:
10 |
11 | ```{code-block} shell
12 | :caption: CLI
13 | flutter run
14 | ```
15 |
16 | To build the app for a specific platform:
17 |
18 | ```{code-block} shell
19 | :caption: CLI
20 | flutter build [platform]
21 | ```
22 |
23 | ## For the Web
24 |
25 | You need to manually build webassembly module from Rust before running or building the app for the web.[^2]
26 |
27 | [^2]: Internally, Rinf uses `wasm-bindgen` and `wasm-pack` with the `web` [target](https://rustwasm.github.io/docs/wasm-pack/commands/build.html#target).
28 |
29 | To serve the web application[^3]:
30 |
31 | [^3]: Since repeatedly writing web header arguments during development can be overwhelming, Rinf provides a convenient command `rinf server` that prints the full Flutter web command.
32 |
33 | ```{code-block} shell
34 | :caption: CLI
35 | rinf wasm
36 | flutter run --web-header=cross-origin-opener-policy=same-origin --web-header=cross-origin-embedder-policy=require-corp
37 | ```
38 |
39 | To build the optimized release version of the web application:
40 |
41 | ```{code-block} shell
42 | :caption: CLI
43 | rinf wasm --release
44 | flutter build web
45 | ```
46 |
47 | When deploying your web app on a web server[^4], ensure that your web server is configured to include cross-origin-related HTTP headers in its responses. These headers enable web browsers using your website to gain access to `SharedArrayBuffer` web API, which is something similar to shared memory on the web.
48 |
49 | [^4]: Rinf supports hosting a Flutter app at a [non-root location](https://docs.flutter.dev/ui/navigation/url-strategies#hosting-a-flutter-app-at-a-non-root-location). For example, you can place your Flutter app in `https://mywebsite.com/subpath/deeperpath/`.
50 |
51 | - [`cross-origin-opener-policy`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/cross-origin-opener-policy): `same-origin`
52 | - [`cross-origin-embedder-policy`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/cross-origin-embedder-policy): `require-corp`.
53 |
54 | Additionally, don't forget to specify the MIME type `application/wasm` for `.wasm` files within the server configuration to ensure optimal performance.
55 |
--------------------------------------------------------------------------------
/flutter_package/example/ios/Runner/Base.lproj/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/rust_crate_cli/template/native/hub/src/actors/first.rs:
--------------------------------------------------------------------------------
1 | use std::time::Duration;
2 |
3 | use crate::signals::{BigBool, SmallNumber, SmallText};
4 | use async_trait::async_trait;
5 | use messages::prelude::{Actor, Address, Context, Handler, Notifiable};
6 | use rinf::{DartSignal, RustSignal, debug_print};
7 | use tokio::task::JoinSet;
8 | use tokio::time::interval;
9 |
10 | // Uncomment below to target the web.
11 | // use tokio_with_wasm::alias as tokio;
12 |
13 | /// The first actor.
14 | pub struct FirstActor {
15 | /// Owned tasks that are canceled when the actor is dropped.
16 | _owned_tasks: JoinSet<()>,
17 | }
18 |
19 | // Implementing the `Actor` trait for `CountingActor`.
20 | // This defines `FirstActor` as an actor in the async system.
21 | impl Actor for FirstActor {}
22 |
23 | impl FirstActor {
24 | /// Creates the actor and initializes its fields.
25 | pub fn new(self_addr: Address) -> Self {
26 | let mut _owned_tasks = JoinSet::new();
27 | _owned_tasks.spawn(Self::listen_to_dart(self_addr.clone()));
28 | _owned_tasks.spawn(Self::listen_to_timer(self_addr));
29 | FirstActor { _owned_tasks }
30 | }
31 | }
32 |
33 | // Implementing the `Notifiable` trait
34 | // allows an actor's loop to listen for a specific message type.
35 | #[async_trait]
36 | impl Notifiable for FirstActor {
37 | async fn notify(&mut self, msg: SmallText, _: &Context) {
38 | debug_print!("{}", msg.text);
39 | SmallNumber { number: 7 }.send_signal_to_dart();
40 | }
41 | }
42 |
43 | // Implementing the `Handler` trait
44 | // allows an actor's loop to respond to a specific message type.
45 | #[async_trait]
46 | impl Handler for FirstActor {
47 | type Result = bool;
48 | async fn handle(&mut self, msg: BigBool, _: &Context) -> bool {
49 | msg.send_signal_to_dart();
50 | false
51 | }
52 | }
53 |
54 | impl FirstActor {
55 | /// Listen to an external source, which in this case is Dart.
56 | async fn listen_to_dart(mut self_addr: Address) {
57 | let receiver = SmallText::get_dart_signal_receiver();
58 | while let Some(signal_pack) = receiver.recv().await {
59 | let _ = self_addr.notify(signal_pack.message).await;
60 | }
61 | }
62 |
63 | /// Listen to an external source, which in this case is a timer.
64 | async fn listen_to_timer(mut self_addr: Address) {
65 | let mut time_interval = interval(Duration::from_secs(3));
66 | let text = "From an owned task".to_owned();
67 | loop {
68 | time_interval.tick().await;
69 | let _ = self_addr.notify(SmallText { text: text.clone() }).await;
70 | }
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/flutter_package/cargokit/build_tool/lib/src/verify_binaries.dart:
--------------------------------------------------------------------------------
1 | import 'dart:io';
2 |
3 | import 'package:ed25519_edwards/ed25519_edwards.dart';
4 | import 'package:http/http.dart';
5 |
6 | import 'artifacts_provider.dart';
7 | import 'cargo.dart';
8 | import 'crate_hash.dart';
9 | import 'options.dart';
10 | import 'precompile_binaries.dart';
11 | import 'target.dart';
12 |
13 | class VerifyBinaries {
14 | VerifyBinaries({
15 | required this.manifestDir,
16 | });
17 |
18 | final String manifestDir;
19 |
20 | Future run() async {
21 | final crateInfo = CrateInfo.load(manifestDir);
22 |
23 | final config = CargokitCrateOptions.load(manifestDir: manifestDir);
24 | final precompiledBinaries = config.precompiledBinaries;
25 | if (precompiledBinaries == null) {
26 | stdout.writeln('Crate does not support precompiled binaries.');
27 | } else {
28 | final crateHash = CrateHash.compute(manifestDir);
29 | stdout.writeln('Crate hash: $crateHash');
30 |
31 | for (final target in Target.all) {
32 | final message = 'Checking ${target.rust}...';
33 | stdout.write(message.padRight(40));
34 | stdout.flush();
35 |
36 | final artifacts = getArtifactNames(
37 | target: target,
38 | libraryName: crateInfo.packageName,
39 | remote: true,
40 | );
41 |
42 | final prefix = precompiledBinaries.uriPrefix;
43 |
44 | bool ok = true;
45 |
46 | for (final artifact in artifacts) {
47 | final fileName = PrecompileBinaries.fileName(target, artifact);
48 | final signatureFileName =
49 | PrecompileBinaries.signatureFileName(target, artifact);
50 |
51 | final url = Uri.parse('$prefix$crateHash/$fileName');
52 | final signatureUrl =
53 | Uri.parse('$prefix$crateHash/$signatureFileName');
54 |
55 | final signature = await get(signatureUrl);
56 | if (signature.statusCode != 200) {
57 | stdout.writeln('MISSING');
58 | ok = false;
59 | break;
60 | }
61 | final asset = await get(url);
62 | if (asset.statusCode != 200) {
63 | stdout.writeln('MISSING');
64 | ok = false;
65 | break;
66 | }
67 |
68 | if (!verify(precompiledBinaries.publicKey, asset.bodyBytes,
69 | signature.bodyBytes)) {
70 | stdout.writeln('INVALID SIGNATURE');
71 | ok = false;
72 | }
73 | }
74 |
75 | if (ok) {
76 | stdout.writeln('OK');
77 | }
78 | }
79 | }
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/flutter_package/cargokit/build_tool/test/rustup_test.dart:
--------------------------------------------------------------------------------
1 | import 'package:build_tool/src/rustup.dart';
2 | import 'package:build_tool/src/util.dart';
3 | import 'package:test/test.dart';
4 |
5 | void main() {
6 | test('rustup with no toolchains', () {
7 | bool didListToolchains = false;
8 | bool didInstallStable = false;
9 | bool didListTargets = false;
10 | testRunCommandOverride = (args) {
11 | expect(args.executable, 'rustup');
12 | switch (args.arguments) {
13 | case ['toolchain', 'list']:
14 | didListToolchains = true;
15 | return TestRunCommandResult(stdout: 'no installed toolchains\n');
16 | case ['toolchain', 'install', 'stable']:
17 | didInstallStable = true;
18 | return TestRunCommandResult();
19 | case ['target', 'list', '--toolchain', 'stable', '--installed']:
20 | didListTargets = true;
21 | return TestRunCommandResult(
22 | stdout: 'x86_64-unknown-linux-gnu\nx86_64-apple-darwin\n');
23 | default:
24 | throw Exception('Unexpected call: ${args.arguments}');
25 | }
26 | };
27 | final rustup = Rustup();
28 | rustup.installToolchain('stable');
29 | expect(didInstallStable, true);
30 | expect(didListToolchains, true);
31 | expect(didListTargets, true);
32 | expect(rustup.installedTargets('stable'), [
33 | 'x86_64-unknown-linux-gnu',
34 | 'x86_64-apple-darwin',
35 | ]);
36 | testRunCommandOverride = null;
37 | });
38 |
39 | test('rustup with esp toolchain', () {
40 | final targetsQueried = [];
41 | testRunCommandOverride = (args) {
42 | expect(args.executable, 'rustup');
43 | switch (args.arguments) {
44 | case ['toolchain', 'list']:
45 | return TestRunCommandResult(
46 | stdout: 'stable-aarch64-apple-darwin (default)\n'
47 | 'nightly-aarch64-apple-darwin\n'
48 | 'esp\n');
49 | case ['target', 'list', '--toolchain', String toolchain, '--installed']:
50 | targetsQueried.add(toolchain);
51 | return TestRunCommandResult(stdout: '$toolchain:target\n');
52 | default:
53 | throw Exception('Unexpected call: ${args.arguments}');
54 | }
55 | };
56 | final rustup = Rustup();
57 | expect(targetsQueried, [
58 | 'stable-aarch64-apple-darwin',
59 | 'nightly-aarch64-apple-darwin',
60 | ]);
61 | expect(rustup.installedTargets('stable'),
62 | ['stable-aarch64-apple-darwin:target']);
63 | expect(rustup.installedTargets('nightly'),
64 | ['nightly-aarch64-apple-darwin:target']);
65 | });
66 | }
67 |
--------------------------------------------------------------------------------
/.github/workflows/publication.yaml:
--------------------------------------------------------------------------------
1 | # Publish packages online.
2 | # This is performed only when a new Git tag
3 | # with version information is added.
4 | name: Publication
5 |
6 | # With default Git settings, Unix-like systems use LF (`\n`) for new lines,
7 | # while Windows uses CRLF (`\r\n`) in local repositories.
8 | # This default Git behavior is not ideal for a cross-platform project like Rinf.
9 | # Also, the file permission system on Windows is not compatible with unix-like OS.
10 |
11 | # If you publish the packages on Windows with `dart pub publish`
12 | # script files are very likely to produce error on unix-like OS.
13 | # This issue has already been observed with `.sh` files.
14 | # That's why we must use this automated Ubuntu workflow to publish packages.
15 |
16 | on:
17 | push:
18 | tags:
19 | - "v[0-9]+.[0-9]+.[0-9]+*" # Should match the tag pattern set on `pub.dev`
20 | workflow_dispatch:
21 |
22 | jobs:
23 | upload:
24 | name: upload-all
25 | runs-on: ubuntu-latest
26 | permissions:
27 | id-token: write # Required for authentication using OIDC for `pub.dev`
28 |
29 | steps:
30 | - name: Checkout repository
31 | uses: actions/checkout@v6
32 |
33 | - name: Setup Dart SDK
34 | uses: dart-lang/setup-dart@v1 # Required for configuring OIDC token
35 |
36 | - name: Setup Flutter SDK
37 | uses: subosito/flutter-action@v2 # Required for the Flutter FFI plugin
38 | with:
39 | channel: "stable"
40 |
41 | - name: Setup Rust toolchain
42 | uses: dtolnay/rust-toolchain@stable
43 |
44 | # https://dart.dev/tools/pub/automated-publishing
45 |
46 | - name: Publish the Flutter package
47 | working-directory: flutter_package/
48 | run: |
49 | dart pub publish --dry-run
50 | dart pub publish --force
51 |
52 | # Save the `crates.io` API token at
53 | # `GitHub repo - Settings - Security - Secrets and variables - Actions`.
54 |
55 | - name: Login to the crates registry
56 | run: cargo login ${{ secrets.CRATES_IO_API_TOKEN }}
57 |
58 | - name: Publish the procedural macro crate
59 | run: |
60 | cargo publish --manifest-path rust_crate_proc/Cargo.toml --dry-run
61 | cargo publish --manifest-path rust_crate_proc/Cargo.toml
62 |
63 | - name: Publish the binary crate
64 | run: |
65 | cargo publish --manifest-path rust_crate_cli/Cargo.toml --dry-run
66 | cargo publish --manifest-path rust_crate_cli/Cargo.toml
67 |
68 | - name: Publish the library crate
69 | run: |
70 | cargo publish --manifest-path rust_crate/Cargo.toml --dry-run
71 | cargo publish --manifest-path rust_crate/Cargo.toml
72 |
--------------------------------------------------------------------------------
/flutter_package/cargokit/build_tool/test/options_test.dart:
--------------------------------------------------------------------------------
1 | import 'package:build_tool/src/builder.dart';
2 | import 'package:build_tool/src/options.dart';
3 | import 'package:hex/hex.dart';
4 | import 'package:test/test.dart';
5 | import 'package:yaml/yaml.dart';
6 |
7 | void main() {
8 | test('parseCargoBuildOptions', () {
9 | final yaml = """
10 | toolchain: nightly
11 | extra_flags:
12 | - -Z
13 | # Comment here
14 | - build-std=panic_abort,std
15 | """;
16 | final node = loadYamlNode(yaml);
17 | final options = CargoBuildOptions.parse(node);
18 | expect(options.toolchain, Toolchain.nightly);
19 | expect(options.flags, ['-Z', 'build-std=panic_abort,std']);
20 | });
21 |
22 | test('parsePrecompiledBinaries', () {
23 | final yaml = """
24 | url_prefix: https://url-prefix
25 | public_key: a4c3433798eb2c36edf2b94dbb4dd899d57496ca373a8982d8a792410b7f6445
26 | """;
27 | final precompiledBinaries = PrecompiledBinaries.parse(loadYamlNode(yaml));
28 | final key = HEX.decode(
29 | 'a4c3433798eb2c36edf2b94dbb4dd899d57496ca373a8982d8a792410b7f6445');
30 | expect(precompiledBinaries.uriPrefix, 'https://url-prefix');
31 | expect(precompiledBinaries.publicKey.bytes, key);
32 | });
33 |
34 | test('parseCargokitOptions', () {
35 | const yaml = '''
36 | cargo:
37 | # For smalles binaries rebuilt the standard library with panic=abort
38 | debug:
39 | toolchain: nightly
40 | extra_flags:
41 | - -Z
42 | # Comment here
43 | - build-std=panic_abort,std
44 | release:
45 | toolchain: beta
46 |
47 | precompiled_binaries:
48 | url_prefix: https://url-prefix
49 | public_key: a4c3433798eb2c36edf2b94dbb4dd899d57496ca373a8982d8a792410b7f6445
50 | ''';
51 | final options = CargokitCrateOptions.parse(loadYamlNode(yaml));
52 | expect(options.precompiledBinaries?.uriPrefix, 'https://url-prefix');
53 | final key = HEX.decode(
54 | 'a4c3433798eb2c36edf2b94dbb4dd899d57496ca373a8982d8a792410b7f6445');
55 | expect(options.precompiledBinaries?.publicKey.bytes, key);
56 |
57 | final debugOptions = options.cargo[BuildConfiguration.debug]!;
58 | expect(debugOptions.toolchain, Toolchain.nightly);
59 | expect(debugOptions.flags, ['-Z', 'build-std=panic_abort,std']);
60 |
61 | final releaseOptions = options.cargo[BuildConfiguration.release]!;
62 | expect(releaseOptions.toolchain, Toolchain.beta);
63 | expect(releaseOptions.flags, []);
64 | });
65 |
66 | test('parseCargokitUserOptions', () {
67 | const yaml = '''
68 | use_precompiled_binaries: false
69 | verbose_logging: true
70 | ''';
71 | final options = CargokitUserOptions.parse(loadYamlNode(yaml));
72 | expect(options.usePrecompiledBinaries, false);
73 | expect(options.verboseLogging, true);
74 | });
75 | }
76 |
--------------------------------------------------------------------------------
/flutter_package/cargokit/run_build_tool.cmd:
--------------------------------------------------------------------------------
1 | @echo off
2 | setlocal
3 |
4 | setlocal ENABLEDELAYEDEXPANSION
5 |
6 | SET BASEDIR=%~dp0
7 |
8 | if not exist "%CARGOKIT_TOOL_TEMP_DIR%" (
9 | mkdir "%CARGOKIT_TOOL_TEMP_DIR%"
10 | )
11 | cd /D "%CARGOKIT_TOOL_TEMP_DIR%"
12 |
13 | SET BUILD_TOOL_PKG_DIR=%BASEDIR%build_tool
14 | SET DART=%FLUTTER_ROOT%\bin\cache\dart-sdk\bin\dart
15 |
16 | set BUILD_TOOL_PKG_DIR_POSIX=%BUILD_TOOL_PKG_DIR:\=/%
17 |
18 | (
19 | echo name: build_tool_runner
20 | echo version: 1.0.0
21 | echo publish_to: none
22 | echo.
23 | echo environment:
24 | echo sdk: '^>=3.0.0 ^<4.0.0'
25 | echo.
26 | echo dependencies:
27 | echo build_tool:
28 | echo path: %BUILD_TOOL_PKG_DIR_POSIX%
29 | ) >pubspec.yaml
30 |
31 | if not exist bin (
32 | mkdir bin
33 | )
34 |
35 | (
36 | echo import 'package:build_tool/build_tool.dart' as build_tool;
37 | echo void main^(List^ args^) ^{
38 | echo build_tool.runMain^(args^);
39 | echo ^}
40 | ) >bin\build_tool_runner.dart
41 |
42 | SET PRECOMPILED=bin\build_tool_runner.dill
43 |
44 | REM To detect changes in package we compare output of DIR /s (recursive)
45 | set PREV_PACKAGE_INFO=.dart_tool\package_info.prev
46 | set CUR_PACKAGE_INFO=.dart_tool\package_info.cur
47 |
48 | DIR "%BUILD_TOOL_PKG_DIR%" /s > "%CUR_PACKAGE_INFO%_orig"
49 |
50 | REM Last line in dir output is free space on harddrive. That is bound to
51 | REM change between invocation so we need to remove it
52 | (
53 | Set "Line="
54 | For /F "UseBackQ Delims=" %%A In ("%CUR_PACKAGE_INFO%_orig") Do (
55 | SetLocal EnableDelayedExpansion
56 | If Defined Line Echo !Line!
57 | EndLocal
58 | Set "Line=%%A")
59 | ) >"%CUR_PACKAGE_INFO%"
60 | DEL "%CUR_PACKAGE_INFO%_orig"
61 |
62 | REM Compare current directory listing with previous
63 | FC /B "%CUR_PACKAGE_INFO%" "%PREV_PACKAGE_INFO%" > nul 2>&1
64 |
65 | If %ERRORLEVEL% neq 0 (
66 | REM Changed - copy current to previous and remove precompiled kernel
67 | if exist "%PREV_PACKAGE_INFO%" (
68 | DEL "%PREV_PACKAGE_INFO%"
69 | )
70 | MOVE /Y "%CUR_PACKAGE_INFO%" "%PREV_PACKAGE_INFO%"
71 | if exist "%PRECOMPILED%" (
72 | DEL "%PRECOMPILED%"
73 | )
74 | )
75 |
76 | REM There is no CUR_PACKAGE_INFO it was renamed in previous step to %PREV_PACKAGE_INFO%
77 | REM which means we need to do pub get and precompile
78 | if not exist "%PRECOMPILED%" (
79 | echo Running pub get in "%cd%"
80 | "%DART%" pub get --no-precompile
81 | "%DART%" compile kernel bin/build_tool_runner.dart
82 | )
83 |
84 | "%DART%" "%PRECOMPILED%" %*
85 |
86 | REM 253 means invalid snapshot version.
87 | If %ERRORLEVEL% equ 253 (
88 | "%DART%" pub get --no-precompile
89 | "%DART%" compile kernel bin/build_tool_runner.dart
90 | "%DART%" "%PRECOMPILED%" %*
91 | )
92 |
--------------------------------------------------------------------------------
/flutter_package/pubspec.yaml:
--------------------------------------------------------------------------------
1 | name: rinf
2 | description: Rust for native business logic, Flutter for flexible and beautiful GUI
3 | version: 8.8.1
4 | repository: https://github.com/cunarist/rinf
5 |
6 | environment:
7 | sdk: ">=3.8.0 <4.0.0"
8 | flutter: ">=3.22.0"
9 |
10 | dependencies:
11 | flutter:
12 | sdk: flutter
13 | ffi: ^2.1.0
14 | web: ^1.1.0
15 |
16 | dev_dependencies:
17 | flutter_lints: ^6.0.0
18 |
19 | # For information on the generic Dart part of this file, see the
20 | # following page: https://dart.dev/tools/pub/pubspec
21 |
22 | # The following section is specific to Flutter packages.
23 | flutter:
24 | # This section identifies this Flutter project as a plugin project.
25 | # The 'pluginClass' specifies the class (in Java, Kotlin, Swift, Objective-C, etc.)
26 | # which should be registered in the plugin registry. This is required for
27 | # using method channels.
28 | # The Android 'package' specifies package in which the registered class is.
29 | # This is required for using method channels on Android.
30 | # The 'ffiPlugin' specifies that native code should be built and bundled.
31 | # This is required for using `dart:ffi`.
32 | # All these are used by the tooling to maintain consistency when
33 | # adding or updating assets for this project.
34 | #
35 | # Please refer to README.md for a detailed explanation.
36 | plugin:
37 | platforms:
38 | android:
39 | ffiPlugin: true
40 | ios:
41 | ffiPlugin: true
42 | linux:
43 | ffiPlugin: true
44 | elinux:
45 | ffiPlugin: true
46 | macos:
47 | ffiPlugin: true
48 | windows:
49 | ffiPlugin: true
50 | web:
51 |
52 | # To add assets to your plugin package, add an assets section, like this:
53 | # assets:
54 | # - images/a_dot_burr.jpeg
55 | # - images/a_dot_ham.jpeg
56 | #
57 | # For details regarding assets in packages, see
58 | # https://flutter.dev/assets-and-images/#from-packages
59 | #
60 | # An image asset can refer to one or more resolution-specific "variants", see
61 | # https://flutter.dev/assets-and-images/#resolution-aware
62 |
63 | # To add custom fonts to your plugin package, add a fonts section here,
64 | # in this "flutter" section. Each entry in this list should have a
65 | # "family" key with the font family name, and a "fonts" key with a
66 | # list giving the asset and other descriptors for the font. For
67 | # example:
68 | # fonts:
69 | # - family: Schyler
70 | # fonts:
71 | # - asset: fonts/Schyler-Regular.ttf
72 | # - asset: fonts/Schyler-Italic.ttf
73 | # style: italic
74 | # - family: Trajan Pro
75 | # fonts:
76 | # - asset: fonts/TrajanPro.ttf
77 | # - asset: fonts/TrajanPro_Bold.ttf
78 | # weight: 700
79 | #
80 | # For details regarding fonts in packages, see
81 | # https://flutter.dev/custom-fonts/#from-packages
82 |
--------------------------------------------------------------------------------