Skip to content

feat: detect firmware vendor transitions within a BBL file#41

Open
nerdCopter wants to merge 3 commits into
masterfrom
feat/bbl-firmware-transition-detection
Open

feat: detect firmware vendor transitions within a BBL file#41
nerdCopter wants to merge 3 commits into
masterfrom
feat/bbl-firmware-transition-detection

Conversation

@nerdCopter

@nerdCopter nerdCopter commented Jun 7, 2026

Copy link
Copy Markdown
Owner

AI Generated pull-request

Summary

  • Detects when a single BBL file contains sessions from multiple firmware vendors (e.g. Betaflight sessions left on flash before reflashing to EmuFlight) and prints a WARNING with per-vendor session ranges and the hint to erase flash before reflashing
  • Corrects output filename prefixes for sessions whose firmware vendor does not match the BBL filename prefix — EMUF_BLACKBOX_LOG_...01.csv for a Betaflight session in an EMUF_* file becomes BTFL_BLACKBOX_LOG_...01.csv, preventing EMUF_BTFL_* or BTFL_BTFL_* duplicates

New public API (export module)

  • firmware_prefix_for_revision(revision: &str) -> Option<&'static str> — maps a firmware revision string to its canonical filename prefix (EMUF_, BTFL_, INAV_)
  • corrected_session_base_name(bbl_path: &Path, firmware_revision: &str) -> Option<String> — returns a corrected base name when the session vendor differs from the BBL filename prefix, or None when they match

All export functions (export_to_csv, export_to_gpx, export_to_event, compute_export_paths) gain an optional base_name_override: Option<&str> parameter. Existing callers pass None — no behaviour change.

Known firmware prefixes are defined in one const table (KNOWN_FIRMWARE_PREFIXES). Adding support for a new firmware (Quicksilver, Kiss, etc.) requires adding a single (&str, &str) entry.

Example output on EMUF_BLACKBOX_LOG_STELLARH7DEV_20260531_172007.BBL (mixed BF + EF flash)

Exported headers to: BTFL_BLACKBOX_LOG_STELLARH7DEV_20260531_172007.01.headers.csv
Exported flight data to: BTFL_BLACKBOX_LOG_STELLARH7DEV_20260531_172007.01.csv
...
Exported headers to: EMUF_BLACKBOX_LOG_STELLARH7DEV_20260531_172007.04.headers.csv
Exported flight data to: EMUF_BLACKBOX_LOG_STELLARH7DEV_20260531_172007.04.csv

WARNING: Firmware transition detected in EMUF_BLACKBOX_LOG_STELLARH7DEV_20260531_172007.BBL
  Sessions 001-003: Betaflight (Betaflight 2025.12.0-beta (a6f6daf05) STM32H743)
  Sessions 004-005: EmuFlight (EmuFlight 0.4.3 (4d3ad55) STELLARH7DEV)
  The flash was not erased before reflashing. Consider excluding earlier sessions.

Test plan

  • cargo test — all unit + integration tests pass (4 new tests for firmware_prefix_for_revision and corrected_session_base_name)
  • cargo clippy -- -D warnings — clean
  • Manual test against EMUF_BLACKBOX_LOG_STELLARH7DEV_20260531_172007.BBL — sessions 1–3 renamed to BTFL_*, sessions 4–5 kept as EMUF_*, warning printed

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Export files now use firmware-vendor-aware naming so generated filenames better reflect device vendor.
    • CLI detects and warns when multiple firmware vendors appear across sessions and summarizes per-session vendor/revision ranges.
  • Documentation

    • Examples updated to match the revised export call signature.
  • Tests

    • Export/path tests updated to reflect the new export naming behavior.

When a BBL file contains sessions from multiple firmware vendors (e.g.
Betaflight sessions left on flash before reflashing to EmuFlight),
bbl_parser now detects the transition and:

- Prints a WARNING listing session ranges per vendor with the suggestion
  to erase flash before reflashing
- Corrects the output filename prefix for sessions whose firmware vendor
  does not match the BBL filename prefix (e.g. EMUF_* file + Betaflight
  session → output named BTFL_*), preventing EMUF_BTFL_* or BTFL_BTFL_*
  duplicate prefixes

New public API in export module:
- `firmware_prefix_for_revision(revision)` — maps a firmware revision
  string to its canonical filename prefix (EMUF_, BTFL_, INAV_)
- `corrected_session_base_name(bbl_path, firmware_revision)` — returns
  a corrected base name when the session vendor differs from the BBL
  filename prefix, or None when they match

All export functions (`export_to_csv`, `export_to_gpx`, `export_to_event`,
`compute_export_paths`) accept an optional `base_name_override` parameter.
Existing callers pass `None` to preserve prior behaviour.

Known firmware prefixes are defined in one place (`KNOWN_FIRMWARE_PREFIXES`)
and extended by adding a single `(&str, &str)` entry.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jun 7, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 899d9d23-1118-4fab-b1e9-ba143afdfdf1

📥 Commits

Reviewing files that changed from the base of the PR and between 91bab03 and e30d437.

📒 Files selected for processing (11)
  • examples/csv_export.rs
  • examples/event_export.rs
  • examples/export_demo.rs
  • examples/gpx_export.rs
  • examples/multi_export.rs
  • examples/multi_flight_export.rs
  • src/conversion.rs
  • src/export.rs
  • src/lib.rs
  • src/main.rs
  • tests/export_integration_tests.rs
📜 Recent review details
🧰 Additional context used
📓 Path-based instructions (6)
src/{main,lib}.rs

📄 CodeRabbit inference engine (AGENTS.md)

Maintain CLI source as src/main.rs and library core as src/lib.rs

Files:

  • src/lib.rs
  • src/main.rs
src/**/*.rs

📄 CodeRabbit inference engine (AGENTS.md)

src/**/*.rs: Do not remove or modify comments unless the related code is changed; only add comments that explain code functionality, no AI instructional comments
Never embed or call external binaries from Rust code
Ensure cargo build --release has no errors or warnings
Only commit if: cargo clippy --all-targets --all-features -- -D warnings, cargo fmt --all -- --check, cargo test --verbose, cargo test --features=cli --verbose, and cargo build --release all pass with no errors or warnings
BEFORE ANY CODE CHANGES: Run cargo clippy --all-targets --all-features -- -D warnings to catch all issues
BEFORE ANY CODE CHANGES: Run cargo fmt --all -- --check to ensure formatting compliance
If cargo fmt --all -- --check fails, IMMEDIATELY run cargo fmt --all to fix formatting
Code must pass cargo fmt --all -- --check without any formatting issues
Never skip clippy checks or formatting checks; never allow warnings to pass
ALWAYS run cargo fmt --all after making ANY code changes before moving to next steps
After running cargo fmt --all, ALWAYS verify with cargo fmt --all -- --check before proceeding

Files:

  • src/lib.rs
  • src/conversion.rs
  • src/main.rs
  • src/export.rs
src/{lib.rs,parser/**/*.rs,export.rs}

📄 CodeRabbit inference engine (AGENTS.md)

Core logic in src/lib.rs with parser modules (src/parser/) and export functions (src/export.rs) shared by both library and CLI

Files:

  • src/lib.rs
  • src/export.rs
src/lib.rs

📄 CodeRabbit inference engine (AGENTS.md)

Public API must include: parse_bbl_file(), parse_bbl_bytes(), BBLLog, ExportOptions, export_to_csv(), export_to_gpx(), export_to_event(), conversion utilities, parser helpers

Files:

  • src/lib.rs
src/main.rs

📄 CodeRabbit inference engine (AGENTS.md)

CLI (src/main.rs) uses library export functions (export_to_csv, export_to_gpx, export_to_event) with CLI-specific status messages as thin wrapper with zero public functions

Files:

  • src/main.rs
src/export.rs

📄 CodeRabbit inference engine (AGENTS.md)

The CSV output must precisely match the format and header order of blackbox_decode CSV files

Files:

  • src/export.rs
🧠 Learnings (6)
📓 Common learnings
Learnt from: nerdCopter
Repo: nerdCopter/bbl_parser PR: 0
File: :0-0
Timestamp: 2025-12-08T21:15:02.434Z
Learning: For bbl_parser reviews: nerdCopter prefers compact, single-block “outside diff” comments without nested <details> or admonitions; use flat bullets with file:line references and link a gist for overflow.
Learnt from: nerdCopter
Repo: nerdCopter/bbl_parser PR: 0
File: :0-0
Timestamp: 2025-12-08T21:15:02.434Z
Learning: Repo nerdCopter/bbl_parser: For outside-diff review notes, prefer a compact, single-block comment with flat bullets (file:line → note), no nested <details> or admonitions; overflow should be linked via gist. Maintainer: nerdCopter.
Learnt from: nerdCopter
Repo: nerdCopter/bbl_parser PR: 2
File: LICENSE_COMMERCIAL:1-4
Timestamp: 2025-08-29T19:52:05.099Z
Learning: nerdCopter prefers to avoid publishing personal information in license files for privacy and security reasons, as they are an individual maintainer rather than a company.
Learnt from: nerdCopter
Repo: nerdCopter/bbl_parser PR: 2
File: README.md:520-521
Timestamp: 2025-08-29T19:53:41.354Z
Learning: nerdCopter uses AGPL-3.0-or-later licensing for the bbl_parser project with a dual-licensing approach that includes a separate commercial license option.
Learnt from: nerdCopter
Repo: nerdCopter/bbl_parser PR: 2
File: CONTRIBUTING.md:9-14
Timestamp: 2025-08-21T20:25:45.741Z
Learning: nerdCopter prefers to keep CLA language general using "project maintainer" rather than specifying a legal entity name, as they are an individual maintainer without an associated company.
Learnt from: nerdCopter
Repo: nerdCopter/bbl_parser PR: 2
File: LICENSE_COMMERCIAL:0-0
Timestamp: 2025-08-29T20:15:04.624Z
Learning: nerdCopter prefers clear positive indicators (✅) when describing fixes rather than using ❌ symbols which can be confusing when describing what was corrected in a positive context.
📚 Learning: 2025-12-19T21:17:26.889Z
Learnt from: CR
Repo: nerdCopter/bbl_parser PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-19T21:17:26.889Z
Learning: Applies to src/main.rs : CLI (`src/main.rs`) uses library export functions (`export_to_csv`, `export_to_gpx`, `export_to_event`) with CLI-specific status messages as thin wrapper with zero public functions

Applied to files:

  • examples/export_demo.rs
  • examples/multi_export.rs
  • src/lib.rs
  • examples/csv_export.rs
  • examples/multi_flight_export.rs
  • examples/gpx_export.rs
  • examples/event_export.rs
  • tests/export_integration_tests.rs
  • src/main.rs
  • src/export.rs
📚 Learning: 2025-12-19T21:17:26.889Z
Learnt from: CR
Repo: nerdCopter/bbl_parser PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-19T21:17:26.889Z
Learning: Applies to src/lib.rs : Public API must include: `parse_bbl_file()`, `parse_bbl_bytes()`, `BBLLog`, `ExportOptions`, `export_to_csv()`, `export_to_gpx()`, `export_to_event()`, conversion utilities, parser helpers

Applied to files:

  • examples/export_demo.rs
  • examples/multi_export.rs
  • src/lib.rs
  • examples/csv_export.rs
  • examples/multi_flight_export.rs
  • examples/gpx_export.rs
  • examples/event_export.rs
  • tests/export_integration_tests.rs
  • src/main.rs
  • src/export.rs
📚 Learning: 2025-12-19T21:17:26.889Z
Learnt from: CR
Repo: nerdCopter/bbl_parser PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-19T21:17:26.889Z
Learning: Applies to src/export.rs : The CSV output must precisely match the format and header order of blackbox_decode CSV files

Applied to files:

  • examples/export_demo.rs
  • examples/multi_export.rs
  • src/lib.rs
  • examples/csv_export.rs
  • examples/multi_flight_export.rs
  • tests/export_integration_tests.rs
  • src/main.rs
📚 Learning: 2025-12-19T21:17:26.889Z
Learnt from: CR
Repo: nerdCopter/bbl_parser PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-19T21:17:26.889Z
Learning: Applies to src/{lib.rs,parser/**/*.rs,export.rs} : Core logic in `src/lib.rs` with parser modules (`src/parser/`) and export functions (`src/export.rs`) shared by both library and CLI

Applied to files:

  • src/lib.rs
  • examples/csv_export.rs
  • examples/event_export.rs
  • src/main.rs
📚 Learning: 2025-12-19T21:17:26.889Z
Learnt from: CR
Repo: nerdCopter/bbl_parser PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-19T21:17:26.889Z
Learning: Applies to Cargo.toml : Feature flags `csv`, `cli`, `json`, `serde` control optional dependencies; default: `csv` + `cli`

Applied to files:

  • examples/csv_export.rs
  • examples/multi_flight_export.rs
🔇 Additional comments (19)
src/export.rs (6)

86-129: LGTM!


139-175: LGTM!


238-277: LGTM!


465-550: LGTM!


557-603: LGTM!


627-636: LGTM!

Also applies to: 915-923, 982-1036

src/main.rs (4)

9-12: LGTM!

Also applies to: 753-753


780-801: LGTM!


805-888: LGTM!


900-958: LGTM!

examples/csv_export.rs (1)

57-57: LGTM!

examples/event_export.rs (1)

44-51: LGTM!

examples/export_demo.rs (1)

87-87: LGTM!

Also applies to: 112-112, 131-131

examples/gpx_export.rs (1)

43-52: LGTM!

examples/multi_export.rs (1)

70-70: LGTM!

Also applies to: 87-87, 111-111

examples/multi_flight_export.rs (1)

63-63: LGTM!

tests/export_integration_tests.rs (1)

39-39: LGTM!

Also applies to: 88-88, 127-127, 156-156, 188-188, 249-249

src/conversion.rs (1)

346-346: LGTM!

src/lib.rs (1)

39-39: LGTM!


📝 Walkthrough

Walkthrough

This PR adds firmware vendor detection and session-aware base-name correction to export paths. A new base_name_override: Option<&str> parameter extends the export API; the CLI tracks firmware revisions per session and computes corrected base names when they differ from the BBL filename prefix, then passes these overrides through to all export functions. Firmware vendor transitions within a file trigger a post-processing warning.

Changes

Firmware-Vendor Export Path Correction

Layer / File(s) Summary
Firmware vendor detection and base-name correction core
src/export.rs
Static firmware prefix mapping and new functions: firmware_prefix_for_revision() and corrected_session_base_name() to detect vendor prefix from firmware revision and compute corrected session base names. Unit tests added for recognized, mismatched, and unknown prefixes.
Export API signature updates and path generation
src/export.rs
compute_export_paths() now accepts base_name_override: Option<&str> and uses it when provided. export_to_csv(), export_to_gpx(), and export_to_event() signatures extended with base_name_override and forward it to path computation; internal test helper calls updated.
Main CLI firmware tracking and base-name override usage
src/main.rs
Imports corrected_session_base_name and firmware_prefix_for_revision, accumulates per-session (log_number, firmware_revision), computes base_name_override for each session and passes it to CSV/GPX/Event exports, and emits a grouped firmware-vendor transition warning after processing a file.
Example call site updates
examples/csv_export.rs, examples/event_export.rs, examples/export_demo.rs, examples/gpx_export.rs, examples/multi_export.rs, examples/multi_flight_export.rs
All example export calls updated to pass the new base_name_override parameter as None to match the extended API.
Documentation example and integration test updates
src/lib.rs, tests/export_integration_tests.rs, src/conversion.rs
Rustdoc example updated to call export_to_csv with trailing None. Integration tests updated to pass the additional None arguments for GPX/Event export and compute_export_paths calls. parse_datetime_to_epoch had a minor local-seconds expression simplification.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • nerdCopter/bbl_parser#34: Both PRs modify the export API surface by changing src/export.rs function signatures (export_to_csv, export_to_gpx, export_to_event, compute_export_paths).
  • nerdCopter/bbl_parser#39: The main PR's example exporter call site updates (e.g., examples/multi_flight_export.rs adjusting export_to_csv) directly overlap with the retrieved PR's changes to the same example files.
  • nerdCopter/bbl_parser#32: Both PRs touch tests/export_integration_tests.rs export function call sites; the retrieved PR added comprehensive export integration tests, and this PR updates those same tests to the new optional argument signature.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat: detect firmware vendor transitions within a BBL file' directly summarizes the main feature addition: detecting when BBL files contain sessions from multiple firmware vendors and handling the resulting transitions.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/bbl-firmware-transition-detection

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Register Quicksilver and Kiss FC in the KNOWN_FIRMWARE_PREFIXES table
so their sessions are correctly identified and prefixed when detected
in mixed-firmware BBL files. Keywords are best-effort guesses based on
firmware names; update if actual revision strings differ.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@nerdCopter nerdCopter marked this pull request as ready for review June 7, 2026 15:26

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/export.rs (1)

145-176: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Validate base_name_override before path construction (path traversal/write-outside-output-dir risk).

Line 157 and Line 246 trust base_name_override directly in filenames. A caller can pass absolute paths or ../ segments and escape the intended output directory.

🔧 Suggested hardening
+use std::path::Component;
+
+fn sanitize_base_name_override(base_name_override: Option<&str>) -> Option<&str> {
+    let raw = base_name_override?;
+    let p = Path::new(raw);
+    if p.is_absolute() {
+        return None;
+    }
+    if p.components().any(|c| {
+        matches!(
+            c,
+            Component::ParentDir | Component::RootDir | Component::Prefix(_)
+        )
+    }) {
+        return None;
+    }
+    p.file_name().and_then(|s| s.to_str())
+}
+
 pub fn compute_export_paths(
@@
-    let base_name = base_name_override.unwrap_or_else(|| extract_base_name(input_path));
+    let base_name = sanitize_base_name_override(base_name_override)
+        .unwrap_or_else(|| extract_base_name(input_path));
@@
 pub fn export_to_csv(
@@
-    let base_name = base_name_override.unwrap_or_else(|| extract_base_name(input_path));
+    let base_name = sanitize_base_name_override(base_name_override)
+        .unwrap_or_else(|| extract_base_name(input_path));

Also applies to: 240-271

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/export.rs` around lines 145 - 176, compute_export_paths currently trusts
base_name_override directly which allows absolute paths or path traversal;
validate and sanitize base_name_override before constructing filenames: when
base_name_override is Some, convert it to a Path and extract only the final
file-stem/file-name component (e.g. via
Path::new(base_name_override).file_name() or file_stem) and reject or fallback
if it contains separators, parent segments, or is absolute; ensure the sanitized
base name contains no path separators or leading dots and only safe characters
(or else use extract_base_name(input_path)); keep using
export_options.output_dir/output_dir for directory placement so callers cannot
escape the intended output directory.
🧹 Nitpick comments (2)
src/export.rs (1)

985-1005: ⚡ Quick win

Add coverage for the newly added QUIC/KISS prefix mappings.

KNOWN_FIRMWARE_PREFIXES includes Quicksilver/Kiss, but test_firmware_prefix_for_revision currently verifies only EMUF/BTFL/INAV plus unknown cases.

✅ Minimal test additions
     assert_eq!(firmware_prefix_for_revision("INAV 7.1.2"), Some("INAV_"));
+    assert_eq!(
+        firmware_prefix_for_revision("Quicksilver 0.1.0"),
+        Some("QUIC_")
+    );
+    assert_eq!(firmware_prefix_for_revision("Kiss Ultra"), Some("KISS_"));
     assert_eq!(firmware_prefix_for_revision(""), None);
     assert_eq!(firmware_prefix_for_revision("Unknown firmware"), None);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/export.rs` around lines 985 - 1005, The test
test_firmware_prefix_for_revision is missing assertions for the newly added
QUIC/KISS mappings; update this test to include cases that exercise the QUIC and
KISS entries in KNOWN_FIRMWARE_PREFIXES by calling firmware_prefix_for_revision
with representative revision strings (e.g., "Quicksilver ..." and "KISS ..." or
uppercase variants) and asserting they return the expected prefixes (e.g.,
"QUIC_" and "KISS_"); ensure you add both typical and uppercase/lowercase
variations similar to the existing EMUF/BTFL checks so the mapping logic is
covered.
src/main.rs (1)

942-949: ⚡ Quick win

Avoid duplicating vendor mapping in CLI warning output.

This match duplicates prefix/vendor knowledge already maintained in src/export.rs. Future prefix additions can silently drift and print Unknown here.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/main.rs` around lines 942 - 949, The inline match that sets vendor_name
duplicates the prefix->vendor mapping maintained elsewhere; replace this block
by calling the shared lookup in export.rs (e.g., a function like
vendor_for_prefix or get_vendor_by_prefix) instead of re-implementing the
mapping. Update the code that currently computes vendor_name (using prefix) to
call that shared function, and ensure the shared function is made public if
necessary so the CLI warning uses the single source of truth for prefix->vendor
mappings.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@src/export.rs`:
- Around line 145-176: compute_export_paths currently trusts base_name_override
directly which allows absolute paths or path traversal; validate and sanitize
base_name_override before constructing filenames: when base_name_override is
Some, convert it to a Path and extract only the final file-stem/file-name
component (e.g. via Path::new(base_name_override).file_name() or file_stem) and
reject or fallback if it contains separators, parent segments, or is absolute;
ensure the sanitized base name contains no path separators or leading dots and
only safe characters (or else use extract_base_name(input_path)); keep using
export_options.output_dir/output_dir for directory placement so callers cannot
escape the intended output directory.

---

Nitpick comments:
In `@src/export.rs`:
- Around line 985-1005: The test test_firmware_prefix_for_revision is missing
assertions for the newly added QUIC/KISS mappings; update this test to include
cases that exercise the QUIC and KISS entries in KNOWN_FIRMWARE_PREFIXES by
calling firmware_prefix_for_revision with representative revision strings (e.g.,
"Quicksilver ..." and "KISS ..." or uppercase variants) and asserting they
return the expected prefixes (e.g., "QUIC_" and "KISS_"); ensure you add both
typical and uppercase/lowercase variations similar to the existing EMUF/BTFL
checks so the mapping logic is covered.

In `@src/main.rs`:
- Around line 942-949: The inline match that sets vendor_name duplicates the
prefix->vendor mapping maintained elsewhere; replace this block by calling the
shared lookup in export.rs (e.g., a function like vendor_for_prefix or
get_vendor_by_prefix) instead of re-implementing the mapping. Update the code
that currently computes vendor_name (using prefix) to call that shared function,
and ensure the shared function is made public if necessary so the CLI warning
uses the single source of truth for prefix->vendor mappings.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 63d03f66-064b-49af-885f-60be10440394

📥 Commits

Reviewing files that changed from the base of the PR and between 91bab03 and 3293564.

📒 Files selected for processing (11)
  • examples/csv_export.rs
  • examples/event_export.rs
  • examples/export_demo.rs
  • examples/gpx_export.rs
  • examples/multi_export.rs
  • examples/multi_flight_export.rs
  • src/conversion.rs
  • src/export.rs
  • src/lib.rs
  • src/main.rs
  • tests/export_integration_tests.rs
📜 Review details
🧰 Additional context used
📓 Path-based instructions (6)
src/**/*.rs

📄 CodeRabbit inference engine (AGENTS.md)

src/**/*.rs: Do not remove or modify comments unless the related code is changed; only add comments that explain code functionality, no AI instructional comments
Never embed or call external binaries from Rust code
Ensure cargo build --release has no errors or warnings
Only commit if: cargo clippy --all-targets --all-features -- -D warnings, cargo fmt --all -- --check, cargo test --verbose, cargo test --features=cli --verbose, and cargo build --release all pass with no errors or warnings
BEFORE ANY CODE CHANGES: Run cargo clippy --all-targets --all-features -- -D warnings to catch all issues
BEFORE ANY CODE CHANGES: Run cargo fmt --all -- --check to ensure formatting compliance
If cargo fmt --all -- --check fails, IMMEDIATELY run cargo fmt --all to fix formatting
Code must pass cargo fmt --all -- --check without any formatting issues
Never skip clippy checks or formatting checks; never allow warnings to pass
ALWAYS run cargo fmt --all after making ANY code changes before moving to next steps
After running cargo fmt --all, ALWAYS verify with cargo fmt --all -- --check before proceeding

Files:

  • src/conversion.rs
  • src/lib.rs
  • src/main.rs
  • src/export.rs
src/{main,lib}.rs

📄 CodeRabbit inference engine (AGENTS.md)

Maintain CLI source as src/main.rs and library core as src/lib.rs

Files:

  • src/lib.rs
  • src/main.rs
src/{lib.rs,parser/**/*.rs,export.rs}

📄 CodeRabbit inference engine (AGENTS.md)

Core logic in src/lib.rs with parser modules (src/parser/) and export functions (src/export.rs) shared by both library and CLI

Files:

  • src/lib.rs
  • src/export.rs
src/lib.rs

📄 CodeRabbit inference engine (AGENTS.md)

Public API must include: parse_bbl_file(), parse_bbl_bytes(), BBLLog, ExportOptions, export_to_csv(), export_to_gpx(), export_to_event(), conversion utilities, parser helpers

Files:

  • src/lib.rs
src/main.rs

📄 CodeRabbit inference engine (AGENTS.md)

CLI (src/main.rs) uses library export functions (export_to_csv, export_to_gpx, export_to_event) with CLI-specific status messages as thin wrapper with zero public functions

Files:

  • src/main.rs
src/export.rs

📄 CodeRabbit inference engine (AGENTS.md)

The CSV output must precisely match the format and header order of blackbox_decode CSV files

Files:

  • src/export.rs
🧠 Learnings (6)
📓 Common learnings
Learnt from: nerdCopter
Repo: nerdCopter/bbl_parser PR: 0
File: :0-0
Timestamp: 2025-12-08T21:15:02.434Z
Learning: Repo nerdCopter/bbl_parser: For outside-diff review notes, prefer a compact, single-block comment with flat bullets (file:line → note), no nested <details> or admonitions; overflow should be linked via gist. Maintainer: nerdCopter.
Learnt from: nerdCopter
Repo: nerdCopter/bbl_parser PR: 2
File: LICENSE_COMMERCIAL:1-4
Timestamp: 2025-08-29T19:52:05.099Z
Learning: nerdCopter prefers to avoid publishing personal information in license files for privacy and security reasons, as they are an individual maintainer rather than a company.
Learnt from: nerdCopter
Repo: nerdCopter/bbl_parser PR: 2
File: README.md:520-521
Timestamp: 2025-08-29T19:53:41.354Z
Learning: nerdCopter uses AGPL-3.0-or-later licensing for the bbl_parser project with a dual-licensing approach that includes a separate commercial license option.
Learnt from: nerdCopter
Repo: nerdCopter/bbl_parser PR: 2
File: CONTRIBUTING.md:9-14
Timestamp: 2025-08-21T20:25:45.741Z
Learning: nerdCopter prefers to keep CLA language general using "project maintainer" rather than specifying a legal entity name, as they are an individual maintainer without an associated company.
Learnt from: nerdCopter
Repo: nerdCopter/bbl_parser PR: 2
File: LICENSE_COMMERCIAL:0-0
Timestamp: 2025-08-29T20:15:04.624Z
Learning: nerdCopter prefers clear positive indicators (✅) when describing fixes rather than using ❌ symbols which can be confusing when describing what was corrected in a positive context.
📚 Learning: 2025-12-19T21:17:26.889Z
Learnt from: CR
Repo: nerdCopter/bbl_parser PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-19T21:17:26.889Z
Learning: Applies to src/main.rs : CLI (`src/main.rs`) uses library export functions (`export_to_csv`, `export_to_gpx`, `export_to_event`) with CLI-specific status messages as thin wrapper with zero public functions

Applied to files:

  • examples/csv_export.rs
  • examples/multi_flight_export.rs
  • examples/gpx_export.rs
  • src/lib.rs
  • examples/event_export.rs
  • examples/multi_export.rs
  • examples/export_demo.rs
  • tests/export_integration_tests.rs
  • src/main.rs
  • src/export.rs
📚 Learning: 2025-12-19T21:17:26.889Z
Learnt from: CR
Repo: nerdCopter/bbl_parser PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-19T21:17:26.889Z
Learning: Applies to src/lib.rs : Public API must include: `parse_bbl_file()`, `parse_bbl_bytes()`, `BBLLog`, `ExportOptions`, `export_to_csv()`, `export_to_gpx()`, `export_to_event()`, conversion utilities, parser helpers

Applied to files:

  • examples/csv_export.rs
  • examples/multi_flight_export.rs
  • examples/gpx_export.rs
  • src/lib.rs
  • examples/event_export.rs
  • examples/multi_export.rs
  • examples/export_demo.rs
  • tests/export_integration_tests.rs
  • src/main.rs
  • src/export.rs
📚 Learning: 2025-12-19T21:17:26.889Z
Learnt from: CR
Repo: nerdCopter/bbl_parser PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-19T21:17:26.889Z
Learning: Applies to src/export.rs : The CSV output must precisely match the format and header order of blackbox_decode CSV files

Applied to files:

  • examples/csv_export.rs
  • examples/multi_flight_export.rs
  • src/lib.rs
  • examples/multi_export.rs
  • examples/export_demo.rs
  • tests/export_integration_tests.rs
  • src/main.rs
📚 Learning: 2025-12-19T21:17:26.889Z
Learnt from: CR
Repo: nerdCopter/bbl_parser PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-19T21:17:26.889Z
Learning: Applies to Cargo.toml : Feature flags `csv`, `cli`, `json`, `serde` control optional dependencies; default: `csv` + `cli`

Applied to files:

  • examples/csv_export.rs
📚 Learning: 2025-12-19T21:17:26.889Z
Learnt from: CR
Repo: nerdCopter/bbl_parser PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-19T21:17:26.889Z
Learning: Applies to src/{lib.rs,parser/**/*.rs,export.rs} : Core logic in `src/lib.rs` with parser modules (`src/parser/`) and export functions (`src/export.rs`) shared by both library and CLI

Applied to files:

  • examples/csv_export.rs
  • src/lib.rs
  • src/main.rs
🔇 Additional comments (13)
src/conversion.rs (1)

346-346: LGTM!

src/export.rs (2)

86-131: LGTM!


467-578: LGTM!

Also applies to: 629-638, 917-926

src/main.rs (2)

9-903: LGTM!


908-941: LGTM!

Also applies to: 950-960

examples/gpx_export.rs (1)

43-52: LGTM!

examples/multi_export.rs (1)

70-71: LGTM!

Also applies to: 79-88, 105-112

examples/multi_flight_export.rs (1)

63-64: LGTM!

examples/csv_export.rs (1)

57-57: LGTM!

examples/event_export.rs (1)

50-50: LGTM!

examples/export_demo.rs (1)

87-87: LGTM!

Also applies to: 112-112, 131-131

src/lib.rs (1)

39-39: LGTM!

tests/export_integration_tests.rs (1)

39-39: LGTM!

Also applies to: 88-88, 127-127, 156-156, 188-188, 249-249

@nerdCopter

Copy link
Copy Markdown
Owner Author

@coderabbitai review.

  • i removed QuickSilver and Kiss because they just set headers to Betaflight
  • i think this code might only repair log 2+, not log 1. how to fix? e.g. if log 1 was betaflight, log 2 and beyond are emuflight, but the log-file was exported from emuflight the file is named EMUF_*.BBL i would expect log 1 to be "fixed" by replacing to BTFL_*.CSV and log 2+ correctly stay EMUF_*.CSV

@coderabbitai

coderabbitai Bot commented Jun 8, 2026

Copy link
Copy Markdown
🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
cat src/main.rs

Length of output: 42877


🏁 Script executed:

#!/bin/bash
cat src/export.rs

Length of output: 35544



@nerdCopter, good notes on QuickSilver/Kiss — since they report Betaflight headers they'd always be classified as BTFL_, so removing those stub entries is correct.

On the "log 1 not repaired" concern: after tracing through the code, log 1 is actually handled correctly. Here's why:

In parse_bbl_file_streaming (src/main.rs), corrected_session_base_name is called inside the main loop for every log, including log_index = 0 (log 1):

for (log_index, &start_pos) in log_positions.iter().enumerate() {
    // ...
    let (should_skip, reason) = should_skip_export(&log, export_options.force_export);
    if should_skip { continue; }

    // ← called for log 1 (log_index=0) too
    let base_name_override =
        corrected_session_base_name(file_path, &log.header.firmware_revision);

For your exact scenario (EMUF_QUAD.BBL, log 1 = Betaflight, logs 2+ = EmuFlight):

Log BBL prefix Session prefix corrected_session_base_name returns Output file
1 EMUF_ BTFL_ Some("BTFL_QUAD") BTFL_QUAD.01.csv
2+ EMUF_ EMUF_ None (match → no change) EMUF_QUAD.02.csv

One edge case worth noting: if log 1 is filtered out by should_skip_export (e.g. < 5 s duration), no export file is written for it at all — which is fine since there's nothing to rename.

One minor real concern I do see: the transition warning message always says "Consider excluding earlier sessions", which assumes old firmware always appears first. That holds for the reflash scenario (flash not erased before upgrade), but if someone reflashed back to an older firmware, the message could be misleading. Not a blocker but worth a TODO comment.

Triggering the full review now.

✅ Action performed

Full review finished.

@nerdCopter

nerdCopter commented Jun 8, 2026

Copy link
Copy Markdown
Owner Author

@coderabbitai, what is better verbiage to fix your reported (output unified-diff format):

One minor real concern I do see: the transition warning message always says "Consider excluding earlier sessions", which assumes old firmware always appears first. That holds for the reflash scenario (flash not erased before upgrade), but if someone reflashed back to an older firmware, the message could be misleading. Not a blocker but worth a TODO comment.

@coderabbitai

coderabbitai Bot commented Jun 8, 2026

Copy link
Copy Markdown

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
rg -n "earlier sessions\|firmware transition\|Consider\|WARNING\|vendor" src/main.rs -A2 -B2

Length of output: 347


🏁 Script executed:

#!/bin/bash
rg -n "WARNING\|transition\|erase\|earlier\|session" src/main.rs -A2 -B2

Length of output: 327


🏁 Script executed:

#!/bin/bash
grep -n "WARNING\|transition\|erase\|earlier\|Consider\|firmware" src/main.rs | head -60

Length of output: 1688


🏁 Script executed:

#!/bin/bash
sed -n '908,965p' src/main.rs

Length of output: 1983



@nerdCopter, here's a direction-neutral rewrite in unified-diff format:

--- a/src/main.rs
+++ b/src/main.rs
@@ -954,7 +954,8 @@ fn print_firmware_transition_warning(file_path: &Path, session_firmware: &[(usiz
         }
     }
-    println!("  The flash was not erased before reflashing. Consider excluding earlier sessions.");
+    println!("  This typically occurs when flash is not erased before reflashing.");
+    println!("  Consider excluding sessions from the unintended firmware vendor listed above.");
 }

Why this is better:

Old Problem
"The flash was not erased…" States it as definite fact; softening to "typically occurs" covers edge cases.
"Consider excluding earlier sessions" Assumes old firmware is always first — breaks when someone reflashes back to an older firmware (old sessions would appear later).

The new phrasing refers to the vendor name (already printed above in the grouped list) rather than a positional word, so it stays correct regardless of which direction the firmware transition went.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant