Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Bug] Variant Enum in stream #406

Closed
The-Mr-L opened this issue Apr 20, 2022 · 26 comments · Fixed by #604
Closed

[Bug] Variant Enum in stream #406

The-Mr-L opened this issue Apr 20, 2022 · 26 comments · Fixed by #604
Labels
bug Something isn't working

Comments

@The-Mr-L
Copy link

The-Mr-L commented Apr 20, 2022

Describe the bug

Hi :)
now I try to adding a rust variant enum like in the example in the guide and I get this while using the generator

when doing

pub enum KitchenSink {
    Empty,
    Primitives {
        /// Dart field comment
        int32: i32,
        float64: f64,
        boolean: bool,
    },

    Buffer(ZeroCopyBuffer<Vec<u8>>),
}
pub struct Msg {
    pub id: String,
    pub test: KitchenSink,
}

pub fn message_handler(sink: StreamSink<Msg>) -> anyhow::Result<()>{Ok(())}

if this is expected please close this :)

Codegen logs with RUST_LOG=debug env variable

[2022-04-20T15:47:54Z WARN  flutter_rust_bridge_codegen::commands] command="powershell" "-noprofile" "-c" "cd \"C:\\Users\\me\\projects\\rust\\project\"; dart run build_runner build --delete-conflicting-outputs" stdout= stderr=Could not find a file named "pubspec.yaml" in "C:\Users\me\AppData\Local\Pub\Cache\hosted\pub.dartlang.org\flutter_rust_bridge-1.25.0".
    #0      new Pubspec.load (package:pub/src/pubspec.dart:288:7)
    #1      new Package.load (package:pub/src/package.dart:149:27)
    #2      SystemCache.load (package:pub/src/system_cache.dart:113:20)
    #3      Entrypoint._createPackageGraph (package:pub/src/entrypoint.dart:112:63)
    #4      Entrypoint.packageGraph (package:pub/src/entrypoint.dart:107:54)
    #5      getExecutableForCommand (package:pub/src/executable.dart:338:19)
    #6      RunCommand.run (package:dartdev/src/commands/run.dart:232:32)
    #7      CommandRunner.runCommand (package:args/command_runner.dart:209:27)
    #8      DartdevRunner.runCommand (package:dartdev/dartdev.dart:232:30)
    #9      CommandRunner.run.<anonymous closure> (package:args/command_runner.dart:119:25)
    #10     new Future.sync (dart:async/future.dart:296:31)
    #11     CommandRunner.run (package:args/command_runner.dart:119:14)
    #12     runDartdev (package:dartdev/dartdev.dart:67:29)
    #13     main (file:///C:/b/s/w/ir/cache/builder/sdk/pkg/dartdev/bin/dartdev.dart:11:9)
    #14     _delayEntrypointInvocation.<anonymous closure> (dart:isolate-patch/isolate_patch.dart:293:32)
    #15     _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:192:12)


[2022-04-20T15:47:54Z ERROR flutter_rust_bridge_codegen::commands] Failed to run build_runner for C:\Users\me\projects\rust\project:
[2022-04-20T15:47:56Z INFO  flutter_rust_bridge_codegen] Success! Now go and use it :)

and I get errors like
lib/bridge_generated.dart(99,14): error GB1B8BC88: Method not found: 'Buffer'
etc when flutter run

@The-Mr-L The-Mr-L added the bug Something isn't working label Apr 20, 2022
@fzyzcjy
Copy link
Owner

fzyzcjy commented Apr 21, 2022

Could not find a file named "pubspec.yaml" in "C:\Users\me\AppData\Local\Pub\Cache\hosted\pub.dartlang.org\flutter_rust_bridge-1.25.0"

Sounds like you are using a wrong folder?

@The-Mr-L
Copy link
Author

but it works when not using the variant enum??

@The-Mr-L
Copy link
Author

can you use variant enum in StreamSink ?

@fzyzcjy
Copy link
Owner

fzyzcjy commented Apr 21, 2022

Not sure about that. Please provide a github repo with reproducing sample.

@The-Mr-L
Copy link
Author

but it is just like so
api.rs

pub enum KitchenSink {
    Empty,
    Primitives {
        /// Dart field comment
        int32: i32,
        float64: f64,
        boolean: bool,
    },

    Buffer(ZeroCopyBuffer<Vec<u8>>),
}
pub struct Msg {
    pub id: String,
    pub test: KitchenSink,
}

pub fn message_handler(sink: StreamSink<Msg>) -> anyhow::Result<()>{Ok(())}

@fzyzcjy
Copy link
Owner

fzyzcjy commented Apr 21, 2022

Well I mean a whole github repo, since in #398 we found the cause is the user does not correctly run code generators instead of bugs in this lib.

@The-Mr-L
Copy link
Author

not correct what we found out was I used a wrong version + I later found out in the main project that I had a main.rs for testing in the native lib which for some reason conflicts when using custom data types in the StreamSink so it wont compile but worked fine otherwise.. but nvm

@huang12zheng
Copy link
Contributor

huang12zheng commented Jun 9, 2022

I tried it and it worked @LambdaMan2K

lazy_static! { 
    pub static ref EVENT_STREAM: Option<StreamSink<String>> = Default::default(); // rust to dart event channel
}

pub fn message_handler(sink: StreamSink<Msg>){
    let _ = EVENT_STREAM;
}
@freezed
class KitchenSink with _$KitchenSink {
  const factory KitchenSink.empty() = Empty;
  const factory KitchenSink.primitives({
    /// Dart field comment
    required int int32,
    required double float64,
    required bool boolean,
  }) = Primitives;
  const factory KitchenSink.buffer(
    Uint8List field0,
  ) = Buffer;
}

class Msg {
  final String id;
  final KitchenSink test;

  Msg({
    required this.id,
    required this.test,
  });
}
Stream<Msg> messageHandler({dynamic hint}) => executeStream(FlutterRustBridgeTask(
        callFfi: (port_) => inner.wire_message_handler(port_),
        parseSuccessData: _wire2api_msg,
        constMeta: kMessageHandlerConstMeta,
        argValues: [],
        hint: hint,
      ));

@The-Mr-L
Copy link
Author

hi, thanks for your response. I just tested it again and got the same error but I found a solution it turned out that I had to add the dev dependency build_runner to the flutter project and then the code_gen seams to finish as expected :). and in the meantime I have tested this lib with prost "protobuf" and using zerocopy for the bytes. and that seams to be working great the reason for this is I get data in this format from the api I use. so it is convenient. do you know what the overhead of serializing using this approach performance compared to your ffi well I guess you are doing ser/de at some point as well right?

@The-Mr-L
Copy link
Author

okay I was too quick to say it worked :s then the generated dart code relays on


import 'dart:convert';
import 'dart:typed_data';
import 'package:freezed_annotation/freezed_annotation.dart';  // Not Found 

import 'dart:convert';
import 'dart:typed_data';
import 'package:flutter_rust_bridge/flutter_rust_bridge.dart'; 
import 'dart:ffi' as ffi;

part 'bridge_generated.freezed.dart';// Not Found 

@The-Mr-L
Copy link
Author

adding freezed package solved this it seams.

@The-Mr-L
Copy link
Author

well thanks again for sharing. I think it works now but will have to test it some more later, if it is not strange to you I have to include these dependencies then please close this. this might tho be helpful for others if they encounter the same.

@Roms1383
Copy link
Contributor

Actually I ran into the very same error.

In case it helps somebody, the way I fixed it roughly is :

  • follow steps on freezed install package, especially installing the dependencies
    flutter pub add freezed_annotation
    flutter pub add --dev build_runner
    flutter pub add --dev freezed
  • update my Rust code, e.g. :
     use std::sync::{Mutex};
     use flutter_rust_bridge::{frb, StreamSink};
    
     #[derive(Debug, Clone)]
     #[frb(freezed)]
     pub enum API {
       Variant(Option<f64>),
       AnotherVariant(Option<f64>),
     }
    
     lazy_static::lazy_static! {
       static ref CHANNEL: Mutex<Option<StreamSink<API>>> = Mutex::new(None);
     }
    
     pub fn get_event_stream(sink: StreamSink<API>) -> anyhow::Result<()> {
         {
             let mut c = CHANNEL.lock().unwrap();
             *c = Some(sink);
         }
         Ok(())
     }
    
     pub fn dispose() -> anyhow::Result<()> {
         {
             let mut c = CHANNEL.lock().unwrap();
             if c.is_some() {
                 *c = None;
             }
         }
         Ok(())
     }
  • regenerate flutter rust bridge definitions
    just gen
  • regenerate freezed definitions
    flutter pub run build_runner build

what still befuddles me is that at times I got this redundant error when using flutter rust bridge codegen but eventually the plugin would just work fine when launching. I'm very new to Flutter / Dart so please take it with a grain of salt.

click to see the error
export REPO_DIR="$PWD"; cd /; flutter_rust_bridge_codegen --rust-input "$REPO_DIR/native/src/api.rs" --dart-output "$REPO_DIR/lib/bridge_generated.dart" --c-output "$REPO_DIR/ios/Runner/bridge_generated.h" --c-output "$REPO_DIR/macos/Runner/bridge_generated.h"
[2022-07-27T12:55:33Z WARN  lib_flutter_rust_bridge_codegen::source_graph] Skipping unresolvable module bridge_generated (tried /Users/romain/Development/lab/cerclo-app/native/src/bridge_generated.rs)
[2022-07-27T12:55:34Z INFO  lib_flutter_rust_bridge_codegen] Picked config: Opts { rust_input_path: "/Users/romain/Development/lab/cerclo-app/native/src/api.rs", dart_output_path: "/Users/romain/Development/lab/cerclo-app/lib/bridge_generated.dart", dart_decl_output_path: None, c_output_path: ["/Users/romain/Development/lab/cerclo-app/ios/Runner/bridge_generated.h", "/Users/romain/Development/lab/cerclo-app/macos/Runner/bridge_generated.h"], rust_crate_dir: "/Users/romain/Development/lab/cerclo-app/native", rust_output_path: "/Users/romain/Development/lab/cerclo-app/native/src/bridge_generated.rs", class_name: "Native", dart_format_line_length: 80, skip_add_mod_to_lib: false, llvm_path: ["/opt/homebrew/opt/llvm", "/usr/local/opt/llvm", "/usr/lib/llvm-9", "/usr/lib/llvm-10", "/usr/lib/llvm-11", "/usr/lib/llvm-12", "/usr/lib/llvm-13", "/usr/lib/llvm-14", "/usr/lib/", "/usr/lib64/", "C:/Program Files/llvm", "C:/Program Files/LLVM", "C:/msys64/mingw64"], llvm_compiler_opts: "", manifest_path: "/Users/romain/Development/lab/cerclo-app/native/Cargo.toml", dart_root: Some("/Users/romain/Development/lab/cerclo-app"), build_runner: true, block_index: BlockIndex(0) }
[2022-07-27T12:55:34Z INFO  lib_flutter_rust_bridge_codegen] Phase: Parse source code to AST, then to IR
[2022-07-27T12:55:34Z WARN  lib_flutter_rust_bridge_codegen::source_graph] Skipping unresolvable module bridge_generated (tried /Users/romain/Development/lab/cerclo-app/native/src/bridge_generated.rs)
[2022-07-27T12:55:34Z INFO  lib_flutter_rust_bridge_codegen] Phase: Transform IR
[2022-07-27T12:55:34Z INFO  lib_flutter_rust_bridge_codegen] Phase: Generate Rust code
[2022-07-27T12:55:34Z INFO  lib_flutter_rust_bridge_codegen] Phase: Generate Dart code
[2022-07-27T12:55:34Z INFO  lib_flutter_rust_bridge_codegen] Phase: Other things
[2022-07-27T12:55:34Z INFO  cbindgen::bindgen::parser] Take native::Platform - opaque (Enum is not marked with a valid #[repr(prim)] or #[repr(C)].).
[2022-07-27T12:55:34Z INFO  cbindgen::bindgen::parser] Take native::API - opaque (Enum is not marked with a valid #[repr(prim)] or #[repr(C)].).
[2022-07-27T12:55:34Z INFO  cbindgen::bindgen::parser] Take native::Geolocation - opaque (Struct is not marked #[repr(C)] or #[repr(transparent)].).
[2022-07-27T12:55:34Z INFO  cbindgen::bindgen::parser] Take native::wire_platform.
[2022-07-27T12:55:34Z INFO  cbindgen::bindgen::parser] Take native::wire_rust_release_mode.
[2022-07-27T12:55:34Z INFO  cbindgen::bindgen::parser] Take native::wire_get_event_stream.
[2022-07-27T12:55:34Z INFO  cbindgen::bindgen::parser] Take native::wire_update_known_location.
[2022-07-27T12:55:34Z INFO  cbindgen::bindgen::parser] Take native::wire_dispose.
[2022-07-27T12:55:34Z INFO  cbindgen::bindgen::parser] Take native::wire_Geolocation.
[2022-07-27T12:55:34Z INFO  cbindgen::bindgen::parser] Take native::new_box_autoadd_geolocation_0.
[2022-07-27T12:55:34Z INFO  cbindgen::bindgen::parser] Take native::free_WireSyncReturnStruct.
[2022-07-27T12:55:34Z INFO  cbindgen::bindgen::parser] Take native::DartPort.
[2022-07-27T12:55:34Z INFO  cbindgen::bindgen::parser] Take native::DartPostCObjectFnType.
[2022-07-27T12:55:34Z INFO  cbindgen::bindgen::parser] Take native::store_dart_post_cobject.
[2022-07-27T12:55:34Z INFO  cbindgen::bindgen::parser] Take native::WireSyncReturnStruct.
[2022-07-27T12:55:35Z INFO  lib_flutter_rust_bridge_codegen::commands] Running build_runner at /Users/romain/Development/lab/cerclo-app
[2022-07-27T12:55:35Z WARN  lib_flutter_rust_bridge_codegen::commands] command="sh" "-c" "cd \"/Users/romain/Development/lab/cerclo-app\" && dart run build_runner build --delete-conflicting-outputs" stdout= stderr=Could not find a file named "pubspec.yaml" in "/Users/romain/.pub-cache/hosted/pub.dartlang.org/_fe_analyzer_shared-43.0.0".
    #0      new Pubspec.load (package:pub/src/pubspec.dart:307:7)
    #1      new Package.load (package:pub/src/package.dart:128:29)
    #2      SystemCache.load (package:pub/src/system_cache.dart:105:20)
    #3      Entrypoint._createPackageGraph (package:pub/src/entrypoint.dart:119:63)
    #4      Entrypoint.packageGraph (package:pub/src/entrypoint.dart:114:54)
    #5      getExecutableForCommand (package:pub/src/executable.dart:338:19)
    #6      RunCommand.run (package:dartdev/src/commands/run.dart:250:32)
    #7      CommandRunner.runCommand (package:args/command_runner.dart:209:27)
    #8      DartdevRunner.runCommand (package:dartdev/dartdev.dart:231:30)
    #9      CommandRunner.run.<anonymous closure> (package:args/command_runner.dart:119:25)
    #10     new Future.sync (dart:async/future.dart:301:31)
    #11     CommandRunner.run (package:args/command_runner.dart:119:14)
    #12     runDartdev (package:dartdev/dartdev.dart:66:29)
    #13     main (file:///opt/s/w/ir/x/w/sdk/pkg/dartdev/bin/dartdev.dart:11:9)
    #14     _delayEntrypointInvocation.<anonymous closure> (dart:isolate-patch/isolate_patch.dart:293:32)
    #15     _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:192:12)
    
    
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Failed to run build_runner for /Users/romain/Development/lab/cerclo-app: ', /Users/romain/.cargo/registry/src/github.com-1ecc6299db9ec823/flutter_rust_bridge_codegen-1.38.1/src/main.rs:24:43
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
error: Recipe `gen` failed on line 8 with exit code 101

I tried adding _fe_analyzer_shared to the dependencies, but the error remains

@Roms1383
Copy link
Contributor

I'd be interested if you know what's going on @fzyzcjy.
As far as I understand, flutter rust bridge codegen thinks a dart/flutter dependency is missing, but I don't really understand the details in this context.

@fzyzcjy
Copy link
Owner

fzyzcjy commented Jul 28, 2022

[2022-07-27T12:55:35Z WARN lib_flutter_rust_bridge_codegen::commands] command="sh" "-c" "cd "/Users/romain/Development/lab/cerclo-app" && dart run build_runner build --delete-conflicting-outputs" stdout= stderr=Could not find a file named "pubspec.yaml" in "/Users/romain/.pub-cache/hosted/pub.dartlang.org/_fe_analyzer_shared-43.0.0".

That sounds like a problem with flutter/dart.

Have you run flutter pub get?

Maybe you need to ask in Flutter/Dart community

@Roms1383
Copy link
Contributor

Yeah, I've literally ran flutter pub get, also cleaned / repaired both flutter cache and dart cache (both flutter clean, flutter pub cache clean + rm -rf ~/.pub-cache, and flutter pub cache repair for example), reactivated ffigen (dart pub global activate ffigen) and the like.
After many attempts I can see it's related to the dependencies found in ~/.pub-cache/hosted/pub.dartlang.org. But whenever I add for example _fe_analyzer_shared (let's say dart pub global activate _fe_analyzer_shared 43.0.0), then another dependency is missing, and so on. That's definitely related to ffigen but I don't know yet how to fix it.

@fzyzcjy
Copy link
Owner

fzyzcjy commented Jul 28, 2022

What about looking at the folder to see what is happening. You may need something like inotify to see what files are added/deleted during execution.

@Roms1383
Copy link
Contributor

Well tbh I have no idea what to look for.
As far as I can tell when running flutter_rust_bridge_codegen it's looking for all these related dependencies and, as the error states, it's looking on my machine in ~/.pub-cache/hosted/pub.dartlang.org. Now I wonder why these aren't pulled in when activating ffigen.

@Roms1383
Copy link
Contributor

Ok the error gets raised whenever the code generator calls dart run build_runner build ... because if I run it directly in the shell it outputs the very same error.

click to see error details

Could not find a file named "pubspec.yaml" in "/Users/romain/.pub-cache/hosted/pub.dartlang.org/_fe_analyzer_shared-43.0.0".
#0 new Pubspec.load (package:pub/src/pubspec.dart:307:7)
#1 new Package.load (package:pub/src/package.dart:128:29)
#2 SystemCache.load (package:pub/src/system_cache.dart:105:20)
#3 Entrypoint._createPackageGraph (package:pub/src/entrypoint.dart:119:63)
#4 Entrypoint.packageGraph (package:pub/src/entrypoint.dart:114:54)
#5 getExecutableForCommand (package:pub/src/executable.dart:338:19)
#6 RunCommand.run (package:dartdev/src/commands/run.dart:250:32)
#7 CommandRunner.runCommand (package:args/command_runner.dart:209:27)
#8 DartdevRunner.runCommand (package:dartdev/dartdev.dart:231:30)
#9 CommandRunner.run. (package:args/command_runner.dart:119:25)
#10 new Future.sync (dart:async/future.dart:301:31)
#11 CommandRunner.run (package:args/command_runner.dart:119:14)
#12 runDartdev (package:dartdev/dartdev.dart:66:29)
#13 main (file:///opt/s/w/ir/x/w/sdk/pkg/dartdev/bin/dartdev.dart:11:9)
#14 _delayEntrypointInvocation. (dart:isolate-patch/isolate_patch.dart:293:32)
#15 _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:192:12)

Where my knowledge of Dart/Flutter ecosystem falls short is that running flutter pub run build_runner build works perfectly fine. This definitely makes me confused.

@Roms1383
Copy link
Contributor

If I remove complex struct/tuple values from the enum, then the error completely disappear.
It looks like dart run build_runner build is ran whenever there are some complex values inside an enum.
Why not use flutter pub run build_runner build instead ? (maybe conditionally one or the other, if the project is pure Dart ?)

@fzyzcjy
Copy link
Owner

fzyzcjy commented Jul 28, 2022

Good observation! You are right, for Flutter projects we should run flutter ... not dart ....

Feel free to PR!

@Roms1383
Copy link
Contributor

I've made a few experiments with nested enums and here's what I found out.
In my code I have KilometerPoint and Speed, and want to send update to Flutter through a StreamSink<API>.
A working sample is like this (simplified for example) :

lazy_static::lazy_static! {
  static ref CHANNEL: Mutex<Option<StreamSink<API>>> = Mutex::new(None);
}

#[derive(Debug, Clone)]
pub enum KP {
    NoKP,
    SNCF(f64),
}

#[derive(Debug, Clone)]
pub enum Speed {
    NoSpeed,
    GPS(f64),
}

#[derive(Debug, Clone)]
#[frb(freezed)]
pub enum API {
    KilometerPointChanged(Box<KP>),
    SpeedChanged(Box<Speed>),
}

What I noticed is that :

it won't work if two or more enums have any variant named the same
lazy_static::lazy_static! {
  static ref CHANNEL: Mutex<Option<StreamSink<API>>> = Mutex::new(None);
}

#[derive(Debug, Clone)]
pub enum KP {
    Unknown, // <--- this leads to error in bridge_generated.dart
    SNCF(f64),
}

#[derive(Debug, Clone)]
pub enum Speed {
    Unknown, // <--- this leads to error in bridge_generated.dart
    GPS(f64),
}

#[derive(Debug, Clone)]
#[frb(freezed)]
pub enum API {
    KilometerPointChanged(Box<KP>),
    SpeedChanged(Box<Speed>),
}
it won't work if an enum is the named the same as another enum's variant
lazy_static::lazy_static! {
  static ref CHANNEL: Mutex<Option<StreamSink<API>>> = Mutex::new(None);
}

#[derive(Debug, Clone)]
pub enum KilometerPoint { // <--- this leads to error in bridge_generated.dart
    NoKP,
    SNCF(f64),
}

#[derive(Debug, Clone)]
pub enum Speed {
    NoSpeed,
    GPS(f64),
}

#[derive(Debug, Clone)]
#[frb(freezed)]
pub enum API {
    KilometerPoint(Box<KP>), // <--- this leads to error in bridge_generated.dart
    Speed(Box<Speed>),
}

If expressly asked, I'll set up a reproductible repo later on but just wanted to share first.

@fzyzcjy
Copy link
Owner

fzyzcjy commented Jul 30, 2022

I see. So it looks like some kind of name conflicts. Feel free to PR!

@Roms1383
Copy link
Contributor

I'm currently examining the diff between working and conflicting samples, I'm gonna open a PR as soon as I get a better idea on how to address it.

@fzyzcjy
Copy link
Owner

fzyzcjy commented Jul 31, 2022

Sure, take your time!

@github-actions
Copy link
Contributor

This thread has been automatically locked since there has not been any recent activity after it was closed. If you are still experiencing a similar issue, please open a new issue.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Aug 27, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants