diff --git a/documentation/docs/frequently-asked-questions.md b/documentation/docs/frequently-asked-questions.md index 7a13fa9a..5b5f1c0d 100644 --- a/documentation/docs/frequently-asked-questions.md +++ b/documentation/docs/frequently-asked-questions.md @@ -105,7 +105,7 @@ After running the `protoc` command, you'll find the generated Dart files in the ```dart title="Dart" // In your Dart code, you can import and use the well-known type: -import 'package:my_app/messages/google/protobuf/timestamp.pb.dart'; +import "package:my_app/messages/google/protobuf/timestamp.pb.dart"; ``` ### Can I use this in pure Dart projects? @@ -202,8 +202,8 @@ message MyUniqueOutput { ``` ```dart title="lib/main.dart" -import 'dart:async'; -import 'package:example_app/messages/tutorial_resource.pb.dart'; +import "dart:async"; +import "package:example_app/messages/tutorial_resource.pb.dart"; var currentInteractionId = 0; final myUniqueOutputs = Map>(); @@ -217,8 +217,8 @@ void main() async { ``` ```dart title="lib/main.dart" -import 'dart:async'; -import 'package:example_app/messages/tutorial_resource.pb.dart'; +import "dart:async"; +import "package:example_app/messages/tutorial_resource.pb.dart"; onPressed: () async { final completer = Completer(); @@ -312,7 +312,7 @@ Failed to load dynamic library 'libhub.so': libhub.so: cannot open shared object In this case, you can specify a path that points to the compiled Rust library. Simply provide a string path to your dynamic library file. ```dart title="lib/main.dart" -import './messages/generated.dart'; +import "./messages/generated.dart"; async void main() { await initializeRust(compiledLibPath: "/path/to/library/libhub.so"); diff --git a/documentation/docs/graceful-shutdown.md b/documentation/docs/graceful-shutdown.md index 33b1bfd4..3c8e7b24 100644 --- a/documentation/docs/graceful-shutdown.md +++ b/documentation/docs/graceful-shutdown.md @@ -7,9 +7,9 @@ In some cases, you might need to drop all Rust resources properly before closing To achieve this, you can utilize Flutter's `AppLifecycleListener` to call the `finalizeRust` function before closing the Flutter app. ```dart title="lib/main.dart" -import 'dart:ui'; -import 'package:flutter/material.dart'; -import 'package:rinf/rinf.dart'; +import "dart:ui"; +import "package:flutter/material.dart"; +import "package:rinf/rinf.dart"; class MyApp extends StatefulWidget { const MyApp({super.key}); diff --git a/documentation/docs/tutorial.md b/documentation/docs/tutorial.md index 8a5db25c..92b1edfb 100644 --- a/documentation/docs/tutorial.md +++ b/documentation/docs/tutorial.md @@ -37,7 +37,7 @@ rinf message Create a button widget in Dart that accepts the user input. ```dart title="lib/main.dart" -import 'package:test_app/messages/tutorial_messages.pb.dart'; +import "package:test_app/messages/tutorial_messages.pb.dart"; child: Column( mainAxisAlignment: MainAxisAlignment.center, @@ -46,7 +46,7 @@ child: Column( onPressed: () async { MyPreciousData( inputNumbers: [3, 4, 5], - inputString: 'Zero-cost abstraction', + inputString: "Zero-cost abstraction", ).sendSignalToRust(); // GENERATED }, child: Text("Send a Signal from Dart to Rust"), @@ -150,7 +150,7 @@ async fn main() { Finally, receive the signals in Dart with `StreamBuilder` and rebuild the widget accordingly. ```dart title="lib/main.dart" -import 'package:test_app/messages/tutorial_messages.pb.dart'; +import "package:test_app/messages/tutorial_messages.pb.dart"; children: [ StreamBuilder( stream: MyAmazingNumber.rustSignalStream, // GENERATED @@ -187,7 +187,7 @@ rinf message ``` ```dart title="lib/main.dart" -import 'package:test_app/messages/tutorial_messages.pb.dart'; +import "package:test_app/messages/tutorial_messages.pb.dart"; children: [ StreamBuilder( @@ -195,11 +195,11 @@ children: [ builder: (context, snapshot) { final rustSignal = snapshot.data; if (rustSignal == null) { - return Text('No value yet'); + return Text("No value yet"); } final myTreasureOutput = rustSignal.message; final currentNumber = myTreasureOutput.currentValue; - return Text('Output value is $currentNumber'); + return Text("Output value is $currentNumber"); }, ), ElevatedButton( diff --git a/flutter_package/analysis_options.yaml b/flutter_package/analysis_options.yaml index c36c2c5d..411855f9 100644 --- a/flutter_package/analysis_options.yaml +++ b/flutter_package/analysis_options.yaml @@ -1 +1,5 @@ include: package:lints/core.yaml + +linter: + rules: + - prefer_double_quotes diff --git a/flutter_package/bin/rinf.dart b/flutter_package/bin/rinf.dart index 8db92fa5..5c0bf135 100644 --- a/flutter_package/bin/rinf.dart +++ b/flutter_package/bin/rinf.dart @@ -1,7 +1,7 @@ -import 'src/config.dart'; -import 'src/helpers.dart'; -import 'src/message.dart'; -import 'src/internet.dart'; +import "src/config.dart"; +import "src/helpers.dart"; +import "src/message.dart"; +import "src/internet.dart"; Future main(List args) async { if (args.isEmpty) { diff --git a/flutter_package/bin/src/config.dart b/flutter_package/bin/src/config.dart index 2992e5af..d64aa274 100644 --- a/flutter_package/bin/src/config.dart +++ b/flutter_package/bin/src/config.dart @@ -1,5 +1,5 @@ -import 'dart:io'; -import 'package:yaml/yaml.dart'; +import "dart:io"; +import "package:yaml/yaml.dart"; class RinfConfigMessage { final String inputDir; @@ -42,11 +42,11 @@ class RinfConfigMessage { @override String toString() { - return '''message: + return """message: $KEY_INPUT_DIR: $inputDir $KEY_RUST_OUTPUT_DIR: $rustOutputDir $KEY_DART_OUTPUT_DIR: $dartOutputDir - $KEY_RUST_SERDE: $rustSerde'''; + $KEY_RUST_SERDE: $rustSerde"""; } static const KEY_INPUT_DIR = "input_dir"; @@ -95,9 +95,9 @@ class RinfConfig { @override String toString() { - return ''' + return """ rinf: - $message'''; + $message"""; } static const KEY_MESSAGE = "message"; @@ -122,7 +122,7 @@ rinf: /// ``` Future loadVerifiedRinfConfig(String pubspecYamlFile) async { final pubspec = loadYaml(await File(pubspecYamlFile).readAsString()); - final YamlMap? rinfConfig = pubspec['rinf']; + final YamlMap? rinfConfig = pubspec["rinf"]; return rinfConfig == null ? RinfConfig.defaultConfig() : RinfConfig.fromYaml(rinfConfig); diff --git a/flutter_package/bin/src/helpers.dart b/flutter_package/bin/src/helpers.dart index 7cac6182..f4b2ee18 100644 --- a/flutter_package/bin/src/helpers.dart +++ b/flutter_package/bin/src/helpers.dart @@ -1,10 +1,10 @@ -import 'dart:io'; -import 'package:package_config/package_config.dart'; -import 'package:yaml/yaml.dart'; -import 'config.dart'; -import 'message.dart'; -import 'common.dart'; -import 'internet.dart'; +import "dart:io"; +import "package:package_config/package_config.dart"; +import "package:yaml/yaml.dart"; +import "config.dart"; +import "message.dart"; +import "common.dart"; +import "internet.dart"; /// Creates new folders and files to an existing Flutter project folder. Future applyRustTemplate({ @@ -18,7 +18,7 @@ Future applyRustTemplate({ if (packageConfig == null) { return; } - final packageName = 'rinf'; + final packageName = "rinf"; final package = packageConfig.packages.firstWhere( (p) => p.name == packageName, ); @@ -32,7 +32,7 @@ Future applyRustTemplate({ return; } final pubspec = loadYaml(await specFile.readAsString()); - final String? publishTo = pubspec['publish_to']; + final String? publishTo = pubspec["publish_to"]; if (publishTo != "none") { print("Flutter package development is not supported by Rinf."); return; @@ -57,43 +57,43 @@ Future applyRustTemplate({ members = ["./native/*"] resolver = "2" '''; - final cargoFile = File.fromUri(flutterProjectPath.join('Cargo.toml')); + final cargoFile = File.fromUri(flutterProjectPath.join("Cargo.toml")); await cargoFile.writeAsString(cargoText); // Add some lines to `.gitignore` - final rustSectionTitle = '# Rust related'; - final messageSectionTitle = '# Generated messages'; - final gitignoreFile = File.fromUri(flutterProjectPath.join('.gitignore')); + final rustSectionTitle = "# Rust related"; + final messageSectionTitle = "# Generated messages"; + final gitignoreFile = File.fromUri(flutterProjectPath.join(".gitignore")); if (!(await gitignoreFile.exists())) { await gitignoreFile.create(recursive: true); } final gitignoreContent = await gitignoreFile.readAsString(); - var gitignoreSplitted = gitignoreContent.split('\n\n'); + var gitignoreSplitted = gitignoreContent.split("\n\n"); gitignoreSplitted = gitignoreSplitted.map((s) => s.trim()).toList(); if (!gitignoreContent.contains(rustSectionTitle)) { var text = rustSectionTitle; - text += '\n' + '.cargo/'; - text += '\n' + 'target/'; + text += "\n" + ".cargo/"; + text += "\n" + "target/"; gitignoreSplitted.add(text); } if (!gitignoreContent.contains(messageSectionTitle)) { var text = messageSectionTitle; - text += '\n' + '*/**/messages/'; + text += "\n" + "*/**/messages/"; gitignoreSplitted.add(text); } - await gitignoreFile.writeAsString(gitignoreSplitted.join('\n\n') + '\n'); + await gitignoreFile.writeAsString(gitignoreSplitted.join("\n\n") + "\n"); // Add some guides to `README.md` - final guideSectionTitle = '## Using Rust Inside Flutter'; - final readmeFile = File.fromUri(flutterProjectPath.join('README.md')); + final guideSectionTitle = "## Using Rust Inside Flutter"; + final readmeFile = File.fromUri(flutterProjectPath.join("README.md")); if (!(await readmeFile.exists())) { await readmeFile.create(recursive: true); } final readmeContent = await readmeFile.readAsString(); - var readmeSplitted = readmeContent.split('\n\n'); + var readmeSplitted = readmeContent.split("\n\n"); readmeSplitted = readmeSplitted.map((s) => s.trim()).toList(); if (!readmeContent.contains(guideSectionTitle)) { - final text = ''' + final text = """ $guideSectionTitle This project leverages Flutter for GUI and Rust for the backend logic, @@ -135,23 +135,23 @@ flutter run For detailed instructions on writing Rust and Flutter together, please refer to Rinf's [documentation](https://rinf.cunarist.com). -'''; +"""; readmeSplitted.add(text); } - await readmeFile.writeAsString(readmeSplitted.join('\n\n') + '\n'); + await readmeFile.writeAsString(readmeSplitted.join("\n\n") + "\n"); // Add Dart dependencies - await Process.run('dart', ['pub', 'add', 'protobuf']); + await Process.run("dart", ["pub", "add", "protobuf"]); // Modify `./lib/main.dart` final mainFile = File.fromUri(flutterProjectPath.join("lib/main.dart")); if (await mainFile.exists()) { - await Process.run('dart', ['format', './lib/main.dart']); + await Process.run("dart", ["format", "./lib/main.dart"]); var mainText = await mainFile.readAsString(); - if (!mainText.contains('messages/generated.dart')) { + if (!mainText.contains("messages/generated.dart")) { final lines = mainText.split("\n"); final lastImportIndex = lines.lastIndexWhere( - (line) => line.startsWith('import '), + (line) => line.startsWith("import "), ); lines.insert( lastImportIndex + 1, @@ -163,18 +163,18 @@ please refer to Rinf's [documentation](https://rinf.cunarist.com). ); mainText = lines.join("\n"); } - if (!mainText.contains('initializeRust(assignRustSignal)')) { + if (!mainText.contains("initializeRust(assignRustSignal)")) { mainText = mainText.replaceFirst( - 'main() {', - 'main() async {', + "main() {", + "main() async {", ); mainText = mainText.replaceFirst( - 'main() async {', - 'main() async { await initializeRust(assignRustSignal);', + "main() async {", + "main() async { await initializeRust(assignRustSignal);", ); } await mainFile.writeAsString(mainText); - await Process.run('dart', ['format', './lib/main.dart']); + await Process.run("dart", ["format", "./lib/main.dart"]); } await generateMessageCode(silent: true, messageConfig: messageConfig); @@ -189,7 +189,7 @@ Future copyDirectory(Uri source, Uri destination) async { final entityName = entity.path.split(Platform.pathSeparator).last; if (entity is Directory) { final newDirectory = Directory.fromUri( - destination.join('$entityName/'), + destination.join("$entityName/"), ); await newDirectory.create(); await copyDirectory(entity.uri, newDirectory.uri); @@ -240,7 +240,7 @@ Future buildWebassembly({bool isReleaseMode = false}) async { processResults.forEach((processResult) { if (processResult.exitCode != 0) { print(processResult.stderr.toString().trim()); - throw Exception('Cannot globally install Rust toolchain for the web.'); + throw Exception("Cannot globally install Rust toolchain for the web."); } }); } else { @@ -249,34 +249,34 @@ Future buildWebassembly({bool isReleaseMode = false}) async { // Prepare the webassembly output path. final flutterProjectPath = Directory.current; - final subPath = 'web/pkg/'; + final subPath = "web/pkg/"; final outputPath = flutterProjectPath.uri.join(subPath); // Build the webassembly module. print("Compiling Rust with `wasm-pack` to `web` target..."); final compileCommand = await Process.run( - 'wasm-pack', + "wasm-pack", [ - '--quiet', - 'build', - './native/hub', - '--out-dir', outputPath.toFilePath(), - '--out-name', 'hub', - '--no-typescript', - '--target', 'web', - if (!isReleaseMode) '--dev', - '--', // Cargo build args comes from here - '-Z', 'build-std=std,panic_abort', + "--quiet", + "build", + "./native/hub", + "--out-dir", outputPath.toFilePath(), + "--out-name", "hub", + "--no-typescript", + "--target", "web", + if (!isReleaseMode) "--dev", + "--", // Cargo build args comes from here + "-Z", "build-std=std,panic_abort", ], environment: { - 'RUSTUP_TOOLCHAIN': 'nightly', - 'RUSTFLAGS': '-C target-feature=+atomics,+bulk-memory,+mutable-globals', - if (stdout.supportsAnsiEscapes) 'CARGO_TERM_COLOR': 'always', + "RUSTUP_TOOLCHAIN": "nightly", + "RUSTFLAGS": "-C target-feature=+atomics,+bulk-memory,+mutable-globals", + if (stdout.supportsAnsiEscapes) "CARGO_TERM_COLOR": "always", }, ); if (compileCommand.exitCode != 0) { print(compileCommand.stderr.toString().trim()); - throw Exception('Unable to compile Rust into webassembly'); + throw Exception("Unable to compile Rust into webassembly"); } print("Saved `.wasm` and `.js` files to `$subPath`."); @@ -284,9 +284,9 @@ Future buildWebassembly({bool isReleaseMode = false}) async { print("To run the Flutter web server, use:"); final commandLineDivider = await getCommandLineDivider(); final commandLines = [ - 'flutter run', - '--web-header=Cross-Origin-Opener-Policy=same-origin', - '--web-header=Cross-Origin-Embedder-Policy=require-corp' + "flutter run", + "--web-header=Cross-Origin-Opener-Policy=same-origin", + "--web-header=Cross-Origin-Embedder-Policy=require-corp" ]; print(commandLines.join(" ${commandLineDivider}\n")); @@ -296,7 +296,7 @@ Future buildWebassembly({bool isReleaseMode = false}) async { Future getCommandLineDivider({bool isReleaseMode = false}) async { if (Platform.isWindows) { // Windows environment, check further for PowerShell or CMD - if (Platform.environment['SHELL'] == null) { + if (Platform.environment["SHELL"] == null) { // Likely PowerShell environment return "`"; // // Likely Command Prompt (cmd.exe) diff --git a/flutter_package/bin/src/internet.dart b/flutter_package/bin/src/internet.dart index 02d8eef6..7da44609 100644 --- a/flutter_package/bin/src/internet.dart +++ b/flutter_package/bin/src/internet.dart @@ -1,4 +1,4 @@ -import 'package:internet_connection_checker/internet_connection_checker.dart'; +import "package:internet_connection_checker/internet_connection_checker.dart"; var isInternetConnected = false; diff --git a/flutter_package/bin/src/message.dart b/flutter_package/bin/src/message.dart index 14fe3fe9..d54d859f 100644 --- a/flutter_package/bin/src/message.dart +++ b/flutter_package/bin/src/message.dart @@ -1,9 +1,9 @@ -import 'dart:io'; -import 'package:path/path.dart'; -import 'package:watcher/watcher.dart'; -import 'config.dart'; -import 'common.dart'; -import 'internet.dart'; +import "dart:io"; +import "package:path/path.dart"; +import "package:watcher/watcher.dart"; +import "config.dart"; +import "common.dart"; +import "internet.dart"; enum MarkType { dartSignal, @@ -63,12 +63,12 @@ Future generateMessageCode({ final resourceNames = entry.value; for (final resourceName in resourceNames) { final protoFile = File.fromUri( - protoPath.join(subPath).join('$resourceName.proto'), + protoPath.join(subPath).join("$resourceName.proto"), ); final lines = await protoFile.readAsLines(); List outputLines = []; for (var line in lines) { - final packagePattern = r'^package\s+[a-zA-Z_][a-zA-Z0-9_\.]*\s*[^=];$'; + final packagePattern = r"^package\s+[a-zA-Z_][a-zA-Z0-9_\.]*\s*[^=];$"; if (RegExp(packagePattern).hasMatch(line.trim())) { continue; } else if (line.trim().startsWith("syntax")) { @@ -77,9 +77,9 @@ Future generateMessageCode({ outputLines.add(line); } } - outputLines.insert(0, 'package $resourceName;'); + outputLines.insert(0, "package $resourceName;"); outputLines.insert(0, 'syntax = "proto3";'); - await protoFile.writeAsString(outputLines.join('\n') + '\n'); + await protoFile.writeAsString(outputLines.join("\n") + "\n"); } } @@ -89,14 +89,14 @@ Future generateMessageCode({ print("Ensuring `protoc-gen-prost` for Rust." + "\nThis is done by installing it globally on the system."); } - final cargoInstallCommand = await Process.run('cargo', [ - 'install', - 'protoc-gen-prost', - ...(messageConfig.rustSerde ? ['protoc-gen-prost-serde'] : []) + final cargoInstallCommand = await Process.run("cargo", [ + "install", + "protoc-gen-prost", + ...(messageConfig.rustSerde ? ["protoc-gen-prost-serde"] : []) ]); if (cargoInstallCommand.exitCode != 0) { print(cargoInstallCommand.stderr.toString().trim()); - throw Exception('Cannot globally install `protoc-gen-prost` Rust crate'); + throw Exception("Cannot globally install `protoc-gen-prost` Rust crate"); } } else { if (!silent) { @@ -114,14 +114,14 @@ Future generateMessageCode({ final protoPaths = []; for (final key in resourcesInFolders.keys) { final joinedPath = protoPath.join(key).toFilePath(); - protoPaths.add('--proto_path=$joinedPath'); + protoPaths.add("--proto_path=$joinedPath"); } final rustFullPath = rustOutputPath.join(subPath).toFilePath(); - final protocRustResult = await Process.run('protoc', [ + final protocRustResult = await Process.run("protoc", [ ...protoPaths, - '--prost_out=$rustFullPath', - ...(messageConfig.rustSerde ? ['--prost-serde_out=$rustFullPath'] : []), - ...resourceNames.map((name) => '$name.proto'), + "--prost_out=$rustFullPath", + ...(messageConfig.rustSerde ? ["--prost-serde_out=$rustFullPath"] : []), + ...resourceNames.map((name) => "$name.proto"), ...markedMessagesAll.values.fold>([], (args, messages) { messages.values.forEach((messages) => args.addAll(messages .where((message) => message.markType == MarkType.rustAttribute) @@ -131,7 +131,7 @@ Future generateMessageCode({ ]); if (protocRustResult.exitCode != 0) { print(protocRustResult.stderr.toString().trim()); - throw Exception('Could not compile `.proto` files into Rust'); + throw Exception("Could not compile `.proto` files into Rust"); } } @@ -140,7 +140,7 @@ Future generateMessageCode({ final subPath = entry.key; final resourceNames = entry.value; final modRsLines = resourceNames.map((resourceName) { - return 'pub mod $resourceName;'; + return "pub mod $resourceName;"; }).toList(); for (final otherSubPath in resourcesInFolders.keys) { if (otherSubPath != subPath && otherSubPath.contains(subPath)) { @@ -172,14 +172,14 @@ Future generateMessageCode({ continue; } final childName = otherSubPathSplitted.last; - modRsLines.add('pub mod $childName;'); + modRsLines.add("pub mod $childName;"); } } if (subPath == "/") { modRsLines.add("pub mod generated;"); } - final modRsContent = modRsLines.join('\n'); - await File.fromUri(rustOutputPath.join(subPath).join('mod.rs')) + final modRsContent = modRsLines.join("\n"); + await File.fromUri(rustOutputPath.join(subPath).join("mod.rs")) .writeAsString(modRsContent); } @@ -189,15 +189,15 @@ Future generateMessageCode({ print("Ensuring `protoc_plugin` for Dart." + "\nThis is done by installing it globally on the system."); } - final pubGlobalActivateCommand = await Process.run('dart', [ - 'pub', - 'global', - 'activate', - 'protoc_plugin', + final pubGlobalActivateCommand = await Process.run("dart", [ + "pub", + "global", + "activate", + "protoc_plugin", ]); if (pubGlobalActivateCommand.exitCode != 0) { print(pubGlobalActivateCommand.stderr.toString().trim()); - throw Exception('Cannot globally install `protoc_plugin` Dart package'); + throw Exception("Cannot globally install `protoc_plugin` Dart package"); } } else { if (!silent) { @@ -215,20 +215,20 @@ Future generateMessageCode({ final protoPaths = []; for (final key in resourcesInFolders.keys) { final joinedPath = protoPath.join(key).toFilePath(); - protoPaths.add('--proto_path=$joinedPath'); + protoPaths.add("--proto_path=$joinedPath"); } final dartFullPath = dartOutputPath.join(subPath).toFilePath(); final protocDartResult = await Process.run( - 'protoc', + "protoc", [ ...protoPaths, - '--dart_out=$dartFullPath', - ...resourceNames.map((name) => '$name.proto'), + "--dart_out=$dartFullPath", + ...resourceNames.map((name) => "$name.proto"), ], ); if (protocDartResult.exitCode != 0) { print(protocDartResult.stderr.toString().trim()); - throw Exception('Could not compile `.proto` files into Dart'); + throw Exception("Could not compile `.proto` files into Dart"); } } @@ -241,29 +241,29 @@ Future generateMessageCode({ continue; } final filename = entry.key; - final dartPath = dartOutputPath.join(subPath).join('$filename.pb.dart'); + final dartPath = dartOutputPath.join(subPath).join("$filename.pb.dart"); final dartFile = File.fromUri(dartPath); final dartContent = await dartFile.readAsString(); - final rustPath = rustOutputPath.join(subPath).join('$filename.rs'); + final rustPath = rustOutputPath.join(subPath).join("$filename.rs"); final rustFile = File.fromUri(rustPath); final rustContent = await rustFile.readAsString(); if (!dartContent.contains("import 'dart:typed_data'")) { await insertTextToFile( dartPath, - ''' + """ // ignore_for_file: invalid_language_version_override import 'dart:async'; import 'dart:typed_data'; import 'package:rinf/rinf.dart'; -''', +""", atFront: true, ); } if (!rustContent.contains("use std::sync")) { await insertTextToFile( rustPath, - ''' + """ #![allow(unused_imports)] use prost::Message; @@ -274,7 +274,7 @@ use rinf::{ }; use std::sync::LazyLock; -''', +""", atFront: true, ); } @@ -288,7 +288,7 @@ use std::sync::LazyLock; markType == MarkType.dartSignalBinary) { await insertTextToFile( rustPath, - ''' + """ type ${messageName}Cell = LazyLock<( MessageSender>, MessageReceiver>, @@ -301,12 +301,12 @@ impl ${normalizePascal(messageName)} { ${snakeName.toUpperCase()}_CHANNEL.1.clone() } } -''', +""", ); if (markType == MarkType.dartSignal) { await insertTextToFile( dartPath, - ''' + """ extension ${messageName}Extension on $messageName{ void sendSignalToRust() { sendDartSignal( @@ -316,14 +316,14 @@ extension ${messageName}Extension on $messageName{ ); } } -''', +""", ); } } if (markType == MarkType.dartSignalBinary) { await insertTextToFile( dartPath, - ''' + """ extension ${messageName}Extension on $messageName{ void sendSignalToRust(Uint8List binary) { sendDartSignal( @@ -333,24 +333,24 @@ extension ${messageName}Extension on $messageName{ ); } } -''', +""", ); } if (markType == MarkType.rustSignal || markType == MarkType.rustSignalBinary) { await insertTextToFile( dartPath, - ''' + """ static final rustSignalStream = ${camelName}Controller.stream.asBroadcastStream(); -''', +""", after: "class $messageName extends \$pb.GeneratedMessage {", ); await insertTextToFile( dartPath, - ''' + """ final ${camelName}Controller = StreamController>(); -''', +""", ); } if (markType == MarkType.rustSignal) { @@ -397,7 +397,7 @@ impl ${normalizePascal(messageName)} { // Get ready to handle received signals in Rust. var rustReceiveScript = ""; - rustReceiveScript += ''' + rustReceiveScript += """ #![allow(unused_imports)] #![allow(unused_mut)] @@ -418,7 +418,7 @@ pub fn assign_dart_signal( ) -> Result<(), RinfError> { let hash_map = DART_SIGNAL_HANDLERS.get_or_init(|| { let mut new_hash_map: DartSignalHandlers = HashMap::new(); -'''; +"""; for (final entry in markedMessagesAll.entries) { final subpath = entry.key; final files = entry.value; @@ -454,7 +454,7 @@ new_hash_map.insert( } } } - rustReceiveScript += ''' + rustReceiveScript += """ new_hash_map }); @@ -464,20 +464,20 @@ new_hash_map.insert( }; signal_handler(message_bytes, binary) } -'''; - await File.fromUri(rustOutputPath.join('generated.rs')) +"""; + await File.fromUri(rustOutputPath.join("generated.rs")) .writeAsString(rustReceiveScript); // Get ready to handle received signals in Dart. var dartReceiveScript = ""; - dartReceiveScript += ''' + dartReceiveScript += """ // ignore_for_file: unused_import import 'dart:typed_data'; import 'package:rinf/rinf.dart'; final rustSignalHandlers = { -'''; +"""; for (final entry in markedMessagesAll.entries) { final subpath = entry.key; final files = entry.value; @@ -491,15 +491,15 @@ final rustSignalHandlers = { final messageName = markedMessage.name; final camelName = pascalToCamel(messageName); final importPath = subpath == "/" - ? '$filename.pb.dart' + ? "$filename.pb.dart" : '$subpath$filename.pb.dart'; if (!dartReceiveScript.contains(importPath)) { - dartReceiveScript = ''' + dartReceiveScript = """ import './$importPath' as $filename; -''' + +""" + dartReceiveScript; } - dartReceiveScript += ''' + dartReceiveScript += """ ${markedMessage.id}: (Uint8List messageBytes, Uint8List binary) { final message = $filename.$messageName.fromBuffer(messageBytes); final rustSignal = RustSignal( @@ -508,19 +508,19 @@ ${markedMessage.id}: (Uint8List messageBytes, Uint8List binary) { ); $filename.${camelName}Controller.add(rustSignal); }, -'''; +"""; } } } } - dartReceiveScript += ''' + dartReceiveScript += """ }; void assignRustSignal(int messageId, Uint8List messageBytes, Uint8List binary) { rustSignalHandlers[messageId]!(messageBytes, binary); } -'''; - await File.fromUri(dartOutputPath.join('generated.dart')) +"""; + await File.fromUri(dartOutputPath.join("generated.dart")) .writeAsString(dartReceiveScript); // Notify that it's done @@ -542,7 +542,7 @@ Future watchAndGenerateMessageCode( stdin.listen((keyCodes) { for (final keyCode in keyCodes) { final key = String.fromCharCode(keyCode); - if (key.toLowerCase() == 'q') { + if (key.toLowerCase() == "q") { shouldQuit = true; } } @@ -588,10 +588,10 @@ Future collectProtoFiles( await for (final entity in directory.list()) { if (entity is File) { final filename = entity.uri.pathSegments.last; - if (filename.endsWith('.proto')) { - final parts = filename.split('.'); + if (filename.endsWith(".proto")) { + final parts = filename.split("."); parts.removeLast(); // Remove the extension from the filename. - final fileNameWithoutExtension = parts.join('.'); + final fileNameWithoutExtension = parts.join("."); resources.add(fileNameWithoutExtension); } } else if (entity is Directory) { @@ -602,9 +602,9 @@ Future collectProtoFiles( ); // Recursive call for subdirectories } } - var subPath = directory.path.replaceFirst(rootDirectory.path, ''); + var subPath = directory.path.replaceFirst(rootDirectory.path, ""); subPath = subPath.replaceAll("\\", "/"); // For Windows - subPath = '$subPath/'; // Indicate that it's a folder, not a file + subPath = "$subPath/"; // Indicate that it's a folder, not a file resourcesInFolders[subPath] = resources; } @@ -637,11 +637,11 @@ Future insertTextToFile( // Append the new text to the existing content if (atFront) { - fileContent = textToAppend + '\n' + fileContent; + fileContent = textToAppend + "\n" + fileContent; } else if (after != null) { fileContent = fileContent.replaceFirst(after, after + textToAppend); } else { - fileContent = fileContent + '\n' + textToAppend; + fileContent = fileContent + "\n" + textToAppend; } // Write the updated content back to the file @@ -667,21 +667,21 @@ Future>>> analyzeMarkedMessages( final subPath = entry.key; for (final filename in entry.value) { final protoFile = File.fromUri( - protoPath.join(subPath).join('$filename.proto'), + protoPath.join(subPath).join("$filename.proto"), ); final content = await protoFile.readAsString(); - final regExp = RegExp(r'{[^}]*}'); + final regExp = RegExp(r"{[^}]*}"); final attrExp = RegExp(r"(?<=\[RINF:RUST-ATTRIBUTE\().*(?=\)\])"); // Remove all { ... } blocks from the string - final contentWithoutBlocks = content.replaceAll(regExp, ';'); + final contentWithoutBlocks = content.replaceAll(regExp, ";"); final statements = contentWithoutBlocks.split(";"); for (final statementRaw in statements) { final statement = statementRaw.trim(); // To find "}\n\n// [RINF:RUST-SIGNAL]", // `contains` is used instead of `startsWith` String? messageName = null; - final lines = statement.split('\n'); + final lines = statement.split("\n"); for (final line in lines) { final trimmed = line.trim(); if (trimmed.startsWith("message")) { @@ -743,12 +743,12 @@ String pascalToSnake(String input) { } final camelCase = pascalToCamel(input); String snakeCase = camelCase.replaceAllMapped( - RegExp(r'[A-Z]'), (Match match) => '_${match.group(0)?.toLowerCase()}'); + RegExp(r"[A-Z]"), (Match match) => "_${match.group(0)?.toLowerCase()}"); return snakeCase; } String snakeToCamel(String input) { - List parts = input.split('_'); + List parts = input.split("_"); String camelCase = parts[0]; for (int i = 1; i < parts.length; i++) { camelCase += parts[i][0].toUpperCase() + parts[i].substring(1); @@ -761,7 +761,7 @@ String snakeToCamel(String input) { String normalizePascal(String input) { var upperStreak = ""; var result = ""; - for (final character in input.split('')) { + for (final character in input.split("")) { if (character.toUpperCase() == character) { upperStreak += character; } else { diff --git a/flutter_package/example/lib/main.dart b/flutter_package/example/lib/main.dart index 93048d80..c035cd3a 100644 --- a/flutter_package/example/lib/main.dart +++ b/flutter_package/example/lib/main.dart @@ -1,9 +1,9 @@ -import 'dart:ui'; -import 'package:flutter/material.dart'; -import 'package:rinf/rinf.dart'; -import './messages/generated.dart'; -import './messages/counter_number.pb.dart'; -import './messages/fractal_art.pb.dart'; +import "dart:ui"; +import "package:flutter/material.dart"; +import "package:rinf/rinf.dart"; +import "./messages/generated.dart"; +import "./messages/counter_number.pb.dart"; +import "./messages/fractal_art.pb.dart"; void main() async { await initializeRust(assignRustSignal); @@ -44,7 +44,7 @@ class _MyAppState extends State { @override Widget build(BuildContext context) { return MaterialApp( - title: 'Rinf Demo', + title: "Rinf Demo", theme: ThemeData( colorScheme: ColorScheme.fromSeed( seedColor: Colors.blueGrey, @@ -76,7 +76,7 @@ class MyHomePage extends StatelessWidget { dummyThree: [4, 5, 6], ).sendSignalToRust(); }, - tooltip: 'Increment', + tooltip: "Increment", child: const Icon(Icons.add), ), ); @@ -134,11 +134,11 @@ class MyColumn extends StatelessWidget { // It's when the widget is being built for the first time. if (rustSignal == null) { // Return the initial widget if the snapshot data is null. - return Text('Initial value 0'); + return Text("Initial value 0"); } final sampleNumberOutput = rustSignal.message; final currentNumber = sampleNumberOutput.currentNumber; - return Text('Current value is $currentNumber'); + return Text("Current value is $currentNumber"); }, ), ]; diff --git a/flutter_package/lib/rinf.dart b/flutter_package/lib/rinf.dart index 1926afb5..de71b9f1 100644 --- a/flutter_package/lib/rinf.dart +++ b/flutter_package/lib/rinf.dart @@ -1,10 +1,10 @@ /// This module supports communication with Rust. library; -import 'dart:typed_data'; -import 'src/exports.dart'; +import "dart:typed_data"; +import "src/exports.dart"; -export 'src/interface.dart' show RustSignal; +export "src/interface.dart" show RustSignal; /// Starts the `main` function in Rust. Future initializeRust( diff --git a/flutter_package/lib/src/exports.dart b/flutter_package/lib/src/exports.dart index 2e4377f5..ab62d23d 100644 --- a/flutter_package/lib/src/exports.dart +++ b/flutter_package/lib/src/exports.dart @@ -1,2 +1,2 @@ -export 'interface_os.dart' if (dart.library.html) 'interface_web.dart'; -export 'interface.dart'; +export "interface_os.dart" if (dart.library.html) "interface_web.dart"; +export "interface.dart"; diff --git a/flutter_package/lib/src/interface.dart b/flutter_package/lib/src/interface.dart index 888891d3..e4e2af95 100644 --- a/flutter_package/lib/src/interface.dart +++ b/flutter_package/lib/src/interface.dart @@ -1,4 +1,4 @@ -import 'dart:typed_data'; +import "dart:typed_data"; /// This type represents a function /// that can accept raw signal data from Rust diff --git a/flutter_package/lib/src/interface_os.dart b/flutter_package/lib/src/interface_os.dart index a58ced68..f79d8752 100644 --- a/flutter_package/lib/src/interface_os.dart +++ b/flutter_package/lib/src/interface_os.dart @@ -1,10 +1,10 @@ -import 'dart:ffi'; -import 'dart:typed_data'; -import 'load_os.dart'; -import 'dart:async'; -import 'dart:isolate'; -import 'interface.dart'; -import 'dart:convert'; +import "dart:ffi"; +import "dart:typed_data"; +import "load_os.dart"; +import "dart:async"; +import "dart:isolate"; +import "interface.dart"; +import "dart:convert"; /// Sets the exact file path of the dynamic library /// compiled from the `hub` crate. diff --git a/flutter_package/lib/src/interface_web.dart b/flutter_package/lib/src/interface_web.dart index cac787e0..9ce1de6b 100644 --- a/flutter_package/lib/src/interface_web.dart +++ b/flutter_package/lib/src/interface_web.dart @@ -1,11 +1,11 @@ // ignore_for_file: avoid_web_libraries_in_flutter -import 'load_web.dart'; -import 'dart:typed_data'; -import 'dart:js' as js; -import 'interface.dart'; -import 'dart:async'; -import 'dart:convert'; +import "load_web.dart"; +import "dart:typed_data"; +import "dart:js" as js; +import "interface.dart"; +import "dart:async"; +import "dart:convert"; /// Sets the path to the JavaScript module /// that needs to be loaded. @@ -19,8 +19,8 @@ Future prepareInterfaceReal( await loadJsFile(); // Listen to Rust via JavaScript - final jsObject = js.context['rinf'] as js.JsObject; - jsObject['send_rust_signal_extern'] = ( + final jsObject = js.context["rinf"] as js.JsObject; + jsObject["send_rust_signal_extern"] = ( int messageId, Uint8List messageBytes, Uint8List binary, @@ -39,8 +39,8 @@ void startRustLogicReal() { if (wasAlreadyLoaded) { return; } - final jsObject = js.context['rinf'] as js.JsObject; - jsObject.callMethod('start_rust_logic_extern', []); + final jsObject = js.context["rinf"] as js.JsObject; + jsObject.callMethod("start_rust_logic_extern", []); } void stopRustLogicReal() { @@ -52,8 +52,8 @@ void sendDartSignalReal( Uint8List messageBytes, Uint8List binary, ) { - final jsObject = js.context['rinf'] as js.JsObject; - jsObject.callMethod('send_dart_signal_extern', [ + final jsObject = js.context["rinf"] as js.JsObject; + jsObject.callMethod("send_dart_signal_extern", [ messageId, messageBytes, binary, diff --git a/flutter_package/lib/src/load_os.dart b/flutter_package/lib/src/load_os.dart index 8f14ae7b..5b0295f5 100644 --- a/flutter_package/lib/src/load_os.dart +++ b/flutter_package/lib/src/load_os.dart @@ -1,7 +1,7 @@ -import 'dart:io' as io; -import 'dart:ffi'; -import 'dart:typed_data'; -import 'package:ffi/ffi.dart'; +import "dart:io" as io; +import "dart:ffi"; +import "dart:typed_data"; +import "package:ffi/ffi.dart"; String? dynamicLibPath; @@ -17,17 +17,17 @@ RustLibrary loadRustLibrary() { if (path != null) { lib = DynamicLibrary.open(path); } else if (io.Platform.isLinux) { - lib = DynamicLibrary.open('libhub.so'); + lib = DynamicLibrary.open("libhub.so"); } else if (io.Platform.isAndroid) { - lib = DynamicLibrary.open('libhub.so'); + lib = DynamicLibrary.open("libhub.so"); } else if (io.Platform.isWindows) { - lib = DynamicLibrary.open('hub.dll'); + lib = DynamicLibrary.open("hub.dll"); } else if (io.Platform.isIOS) { - lib = DynamicLibrary.open('rinf.framework/rinf'); + lib = DynamicLibrary.open("rinf.framework/rinf"); } else if (io.Platform.isMacOS) { - lib = DynamicLibrary.open('rinf.framework/rinf'); + lib = DynamicLibrary.open("rinf.framework/rinf"); } else { - throw UnsupportedError('This operating system is not supported.'); + throw UnsupportedError("This operating system is not supported."); } if (io.Platform.isAndroid) { @@ -87,19 +87,19 @@ abstract class RustLibrary { @Native( isLeaf: true, - symbol: 'start_rust_logic_extern', + symbol: "start_rust_logic_extern", ) external void startRustLogicExtern(); @Native( isLeaf: true, - symbol: 'stop_rust_logic_extern', + symbol: "stop_rust_logic_extern", ) external void stopRustLogicExtern(); @Native( isLeaf: true, - symbol: 'prepare_isolate_extern', + symbol: "prepare_isolate_extern", ) external void prepareIsolateExtern( int port, @@ -107,7 +107,7 @@ external void prepareIsolateExtern( @Native( isLeaf: true, - symbol: 'store_dart_post_cobject', + symbol: "store_dart_post_cobject", ) external void storeDartPostCObjectExtern( PostCObjectPtr postCObject, @@ -115,7 +115,7 @@ external void storeDartPostCObjectExtern( @Native( isLeaf: true, - symbol: 'send_dart_signal_extern', + symbol: "send_dart_signal_extern", ) external void sendDartSignalExtern( int messageId, @@ -178,23 +178,23 @@ class RustLibraryOld extends RustLibrary { RustLibraryOld({required this.lib}) { this.startRustLogicExtern = lib.lookupFunction( - 'start_rust_logic_extern', + "start_rust_logic_extern", ); this.stopRustLogicExtern = lib.lookupFunction( - 'stop_rust_logic_extern', + "stop_rust_logic_extern", ); this.prepareIsolateExtern = lib.lookupFunction( - 'prepare_isolate_extern', + "prepare_isolate_extern", ); this.storeDartPostCObjectExtern = lib.lookupFunction< Void Function(PostCObjectPtr), void Function(PostCObjectPtr)>( - 'store_dart_post_cobject', + "store_dart_post_cobject", ); this.sendDartSignalExtern = lib.lookupFunction( - 'send_dart_signal_extern', + "send_dart_signal_extern", ); } diff --git a/flutter_package/lib/src/load_web.dart b/flutter_package/lib/src/load_web.dart index a339834a..26f546d6 100644 --- a/flutter_package/lib/src/load_web.dart +++ b/flutter_package/lib/src/load_web.dart @@ -1,8 +1,8 @@ // ignore_for_file: avoid_web_libraries_in_flutter -import 'dart:js' as js; -import 'dart:html'; -import 'dart:async'; +import "dart:js" as js; +import "dart:html"; +import "dart:async"; String? jsLibPath; @@ -21,7 +21,7 @@ Future loadJsFile() async { } final loadCompleter = Completer(); - js.context['completeRinfLoad'] = loadCompleter.complete; + js.context["completeRinfLoad"] = loadCompleter.complete; // Flutter app doesn't always have the top-level path of the domain. // Sometimes, the flutter app might be placed in a lower path.