fzyzcjy / flutter_rust_bridge

Flutter/Dart <-> Rust binding generator, feature-rich, but seamless and simple.
https://fzyzcjy.github.io/flutter_rust_bridge/
MIT License
4.12k stars 283 forks source link

RangeError deserializing enum only on Prod #2251

Closed TaeHagen closed 3 weeks ago

TaeHagen commented 3 weeks ago

Describe the bug

In this specific case, I am getting this error only when building for Android on profile or prod (debug works fine). The serialization/deserialization code appears to be fine. Is there any place I can see the actual data being sent between dart/flutter so I can see any disparity.

The struct before has a version number that appears to be intact, so not sure why it would fail here.

image

The struct before has a version number that appears to be intact, so not sure why it would fail here. image

Steps to reproduce

I really have no clue. This only happened in a specific part of my app

Logs

[2024-08-18T20:21:48.911Z DEBUG /home/tae/.cargo/registry/src/index.crates.io-6f17d22bba15001f/flutter_rust_bridge_codegen-2.1.0/src/main.rs:24] cli=Cli { verbose: false, command: Generate(GenerateCommandArgs { watch: false, primary: GenerateCommandArgsPrimary { config_file: None, rust_input: None, dart_output: None, c_output: None, duplicated_c_output: None, rust_root: None, rust_output: None, dart_entrypoint_class_name: None, dart_format_line_length: None, dart_preamble: None, rust_preamble: None, no_dart_enums_style: false, no_add_mod_to_lib: false, llvm_path: None, llvm_compiler_opts: None, dart_root: None, no_build_runner: false, extra_headers: None, no_web: true, no_deps_check: false, default_external_library_loader_web_prefix: None, no_dart3: false, full_dep: false, local: false, enable_lifetime: false, type_64bit_int: false, no_default_dart_async: false, stop_on_error: false, dump: None, dump_all: false } }) }
[2024-08-18T20:21:48.911Z DEBUG /home/tae/.cargo/registry/src/index.crates.io-6f17d22bba15001f/flutter_rust_bridge_codegen-2.1.0/src/library/codegen/config/config_parser.rs:51] Found config file flutter_rust_bridge.yaml
[2024-08-18T20:21:48.911Z DEBUG /home/tae/.cargo/registry/src/index.crates.io-6f17d22bba15001f/flutter_rust_bridge_codegen-2.1.0/src/library/codegen/mod.rs:23] config=Config { base_dir: Some(""), rust_input: Some("rust/src/api/**/*.rs"), dart_output: Some("lib/src/rust"), c_output: None, duplicated_c_output: None, rust_root: None, rust_output: None, dart_entrypoint_class_name: None, dart_format_line_length: None, dart_preamble: None, rust_preamble: None, dart_enums_style: None, add_mod_to_lib: None, llvm_path: None, llvm_compiler_opts: None, dart_root: None, build_runner: None, extra_headers: None, web: Some(false), deps_check: None, dart3: None, full_dep: None, local: None, default_external_library_loader_web_prefix: None, dart_type_rename: None, enable_lifetime: None, type_64bit_int: None, default_dart_async: None, stop_on_error: None, dump: None, dump_all: None } meta_config=MetaConfig { watch: false }
[2024-08-18T20:21:48.912Z DEBUG /home/tae/.cargo/registry/src/index.crates.io-6f17d22bba15001f/flutter_rust_bridge_codegen-2.1.0/src/library/codegen/config/internal_config_parser/mod.rs:33] InternalConfig.parse base_dir="/home/tae/Documents/GitHub/bb-app-restore"
[2024-08-18T20:21:49.371Z DEBUG /home/tae/.cargo/registry/src/index.crates.io-6f17d22bba15001f/flutter_rust_bridge_codegen-2.1.0/src/library/codegen/mod.rs:26] internal_config=InternalConfig { controller: ControllerInternalConfig { watch: false, watching_paths: ["/home/tae/Documents/GitHub/bb-app-restore/rust/src"], exclude_paths: ["/home/tae/Documents/GitHub/bb-app-restore/rust/src/frb_generated.rs"], max_count: None }, preparer: PreparerInternalConfig { dart_root: "/home/tae/Documents/GitHub/bb-app-restore", deps_check: true, needs_ffigen: false }, parser: ParserInternalConfig { hir: ParserHirInternalConfig { rust_input_namespace_pack: RustInputNamespacePack { rust_input_namespace_prefixes: [Namespace { joined_path: "crate::api" }], rust_output_path_namespace: Namespace { joined_path: "crate::frb_generated" } }, rust_crate_dir: "/home/tae/Documents/GitHub/bb-app-restore/rust", third_party_crate_names: [] }, mir: ParserMirInternalConfig { rust_input_namespace_pack: RustInputNamespacePack { rust_input_namespace_prefixes: [Namespace { joined_path: "crate::api" }], rust_output_path_namespace: Namespace { joined_path: "crate::frb_generated" } }, force_codec_mode_pack: Some(CodecModePack { dart2rust: Pde, rust2dart: Pde }), default_stream_sink_codec: Sse, default_rust_opaque_codec: Moi, stop_on_error: false, enable_lifetime: false, type_64bit_int: false, default_dart_async: true } }, generator: GeneratorInternalConfig { api_dart: GeneratorApiDartInternalConfig { dart_enums_style: true, dart3: true, dart_decl_base_output_path: "/home/tae/Documents/GitHub/bb-app-restore/lib/src/rust", dart_impl_output_path: TargetOrCommonMap { common: "/home/tae/Documents/GitHub/bb-app-restore/lib/src/rust/frb_generated.dart", io: "/home/tae/Documents/GitHub/bb-app-restore/lib/src/rust/frb_generated.io.dart", web: "/home/tae/Documents/GitHub/bb-app-restore/lib/src/rust/frb_generated.web.dart" }, dart_entrypoint_class_name: "RustLib", dart_preamble: "", dart_type_rename: {} }, wire: GeneratorWireInternalConfig { dart: GeneratorWireDartInternalConfig { has_ffigen: false, web_enabled: 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:/msys64/mingw64"], llvm_compiler_opts: "", dart_root: "/home/tae/Documents/GitHub/bb-app-restore", extra_headers: "", dart_impl_output_path: TargetOrCommonMap { common: "/home/tae/Documents/GitHub/bb-app-restore/lib/src/rust/frb_generated.dart", io: "/home/tae/Documents/GitHub/bb-app-restore/lib/src/rust/frb_generated.io.dart", web: "/home/tae/Documents/GitHub/bb-app-restore/lib/src/rust/frb_generated.web.dart" }, dart_output_class_name_pack: DartOutputClassNamePack { entrypoint_class_name: "RustLib", api_class_name: "RustLibApi", api_impl_class_name: "RustLibApiImpl", api_impl_platform_class_name: "RustLibApiImplPlatform", wire_class_name: "RustLibWire", wasm_module_name: "RustLibWasmModule" }, default_external_library_loader: GeneratorWireDartDefaultExternalLibraryLoaderInternalConfig { stem: "rust_lib_bluebubbles", io_directory: "rust/target/release/", web_prefix: "pkg/" }, c_symbol_prefix: "frbgen_bluebubbles_" }, rust: GeneratorWireRustInternalConfig { rust_crate_dir: "/home/tae/Documents/GitHub/bb-app-restore/rust", web_enabled: false, rust_output_path: "/home/tae/Documents/GitHub/bb-app-restore/rust/src/frb_generated.rs", c_symbol_prefix: "frbgen_bluebubbles_", has_ffigen: false, default_stream_sink_codec: Sse, default_rust_opaque_codec: Moi, rust_preamble: "" }, c: GeneratorWireCInternalConfig { enable: false, rust_crate_dir: "/home/tae/Documents/GitHub/bb-app-restore/rust", rust_output_path: "/home/tae/Documents/GitHub/bb-app-restore/rust/src/frb_generated.rs", c_output_path: None, c_symbol_prefix: "frbgen_bluebubbles_" } } }, polisher: PolisherInternalConfig { duplicated_c_output_path: [], dart_format_line_length: 80, add_mod_to_lib: true, build_runner: true, web_enabled: false, dart_root: "/home/tae/Documents/GitHub/bb-app-restore", rust_crate_dir: "/home/tae/Documents/GitHub/bb-app-restore/rust", rust_output_path: "/home/tae/Documents/GitHub/bb-app-restore/rust/src/frb_generated.rs", c_output_path: None, enable_auto_upgrade: true }, dumper: DumperInternalConfig { dump_contents: [], dump_directory: "/home/tae/Documents/GitHub/bb-app-restore/rust/target/frb_dump" } }
[2024-08-18T20:21:49.372Z DEBUG /home/tae/.cargo/registry/src/index.crates.io-6f17d22bba15001f/flutter_rust_bridge_codegen-2.1.0/src/library/utils/dart_repository/dart_repo.rs:22] Guessing toolchain the runner is run into
[2024-08-18T20:21:49.374Z DEBUG /home/tae/.cargo/registry/src/index.crates.io-6f17d22bba15001f/flutter_rust_bridge_codegen-2.1.0/src/library/commands/command_runner.rs:129] execute command: bin=sh args="-c \"flutter\" \"--version\"" current_dir=None cmd="sh" "-c" "\"flutter\" \"--version\""
[2024-08-18T20:21:49.761Z DEBUG /home/tae/.cargo/registry/src/index.crates.io-6f17d22bba15001f/flutter_rust_bridge_codegen-2.1.0/src/library/commands/command_runner.rs:140] command="sh" "-c" "\"flutter\" \"--version\"" stdout=Flutter 3.22.3 • channel stable • https://github.com/flutter/flutter.git
Framework • revision b0850beeb2 (5 weeks ago) • 2024-07-16 21:43:41 -0700
Engine • revision 235db911ba
Tools • Dart 3.4.4 • DevTools 2.34.3
 stderr=
[2024-08-18T20:21:49.762Z DEBUG /home/tae/.cargo/registry/src/index.crates.io-6f17d22bba15001f/flutter_rust_bridge_codegen-2.1.0/src/library/commands/cargo_expand/mod.rs:26] run_cargo_expand manifest_dir= rust_crate_dir="/home/tae/Documents/GitHub/bb-app-restore/rust"
[2024-08-18T20:21:49.762Z DEBUG /home/tae/.cargo/registry/src/index.crates.io-6f17d22bba15001f/flutter_rust_bridge_codegen-2.1.0/src/library/commands/cargo_expand/real.rs:60] Running cargo expand in '"/home/tae/Documents/GitHub/bb-app-restore/rust"'
[2024-08-18T20:21:49.762Z DEBUG /home/tae/.cargo/registry/src/index.crates.io-6f17d22bba15001f/flutter_rust_bridge_codegen-2.1.0/src/library/commands/command_runner.rs:129] execute command: bin=cargo args="expand --lib --theme=none --ugly" current_dir=Some("/home/tae/Documents/GitHub/bb-app-restore/rust") cmd=cd "/home/tae/Documents/GitHub/bb-app-restore/rust" && RUSTFLAGS="--cfg frb_expand" "cargo" "expand" "--lib" "--theme=none" "--ugly"

Expected behavior

It works fine

Generated binding code

// Nothing when using full_dep=false mode

OS

Linux

Version of flutter_rust_bridge_codegen

1.1.0

Flutter info

No response

Version of clang++

No response

Additional context

Thank you!

fzyzcjy commented 3 weeks ago

Is there any place I can see the actual data being sent between dart/flutter so I can see any disparity.

Yes: The SseDeserializer has field buffer, and that ReadBuffer has field data, and that ByteData is the serialized bytes that is sent from Rust to Dart when you are using SSE codec. Thus printing that ByteData byte by byte may help (e.g. like you mentioned - see whether there is any difference in the bytes printed between debug and profile/release).

Also feel free to provide a minimal reproducible sample, s.t. I can reproduce locally and examine it.

TaeHagen commented 3 weeks ago

So I did a bit of debugging, I'm going to look at the rust side now. I got a window of 60 bytes with the bad value at the center: Prod: 6261636b67726f756e645f636f6c6f725f32373278393264702e706e67010073ba84010100000005000000246e756c6c2200000068747470733a2f2f

Debug: 6261636b67726f756e645f636f6c6f725f32373278393264702e706e670100000000010100000005000000246e756c6c2200000068747470733a2f2f

As you can see, they are identical except the 8 bytes in the middle. If you have any tips about rust side would be appreciated.

TaeHagen commented 3 weeks ago

WOAH, the corruption is apparently there on the rust side???? 67726f756e645f636f6c6f725f32373278393264702e706e67010073ba84

TaeHagen commented 3 weeks ago

Okay i fixed it. Firstly, rust's optimizations are incredible, they converted the match into a direct memory copy i assume. I had mismatched #[repr(C)] and #[repr(rust)] and apparently #[repr(rust)] has a one byte enum marker or something I assume. I transmuted between them, failing to notice, causing UB.

It would be nice to have a way to call a rust lib directly without having to copy over headers and transmute. (if i just Pub, they're opaque which i can't have).

Thank you!

fzyzcjy commented 3 weeks ago

You are welcome!

It would be nice to have a way to call a rust lib directly without having to copy over headers and transmute.

Not very get it, could you please elaborate a bit more what you have done / want to do?

TaeHagen commented 3 weeks ago

I have a rust library that does all the work. I would like to call it directly from flutter, but instead i must write rust functions that call library code. Worse, I need to access the library structures, so I am forced to copy over the structures and transmute between them so FRB can see them and generate code. It would be nice to have some solution to avoid having duplicate structures and issues like this one.

fzyzcjy commented 3 weeks ago

Hmm, does these help

github-actions[bot] commented 1 week ago

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.