Skip to content

Complete CLI-to-Crate Unification: Consolidate Export Layer #24

@coderabbitai

Description

@coderabbitai

Problem Statement

Phase 5 of CLI-to-crate unification is incomplete. While the parsing layer is properly unified, the export layer has 541 lines of duplicated code between src/main.rs (CLI) and src/export.rs (library).

Reference: PR #23

Current State Analysis

✅ Parsing Layer (Unified)

  • CLI uses library functions: parse_frames(), parse_headers_from_text()
  • No duplication
  • Status: Complete

⚠️ Export Layer (Duplicated)

Library (src/export.rs - 322 lines)

pub fn export_to_csv(log: &BBLLog, path: &Path, options: &ExportOptions) -> Result<()>
pub fn export_to_gpx(log: &BBLLog, path: &Path, options: &ExportOptions) -> Result<()>
pub fn export_to_event(log: &BBLLog, path: &Path, options: &ExportOptions) -> Result<()>

// Private helpers
fn export_headers_to_csv(header: &BBLHeader, output_path: &Path) -> Result<()>
fn export_flight_data_to_csv(log: &BBLLog, output_path: &Path) -> Result<()>

CLI (src/main.rs - 541 lines)

fn export_logs_to_csv(...)           // Lines 1074-1127 (54 lines)
fn export_single_log_to_csv(...)     // Lines 1128-1171 (44 lines)
fn export_headers_to_csv(...)        // Lines 1172-1209 (38 lines) ⚠️ IDENTICAL to export.rs
fn export_flight_data_to_csv(...)    // Lines 1210-1507 (298 lines)
fn export_gpx_file(...)              // Lines 1509-1573 (65 lines)
fn export_event_file(...)            // Lines 1575-1616 (42 lines)

Critical Issue: export_headers_to_csv is byte-for-byte identical in both files, proving duplication rather than intentional divergence.

Test Coverage Gap

  • 37 total tests across the codebase
  • 0 tests for library export functions
  • Most tests are CLI integration tests in main.rs

Impact

Maintenance Burden

  • Bug fixes must be applied in two places
  • Risk of divergence: CLI and library exports could produce different output
  • Code review complexity

Library Completeness

  • Export API exists but untested
  • No confidence for external crate consumers
  • Documentation claims don't match reality

Detailed Unification Plan

Phase 1: Preparation & Testing (Priority: High)

Step 1.1: Add Comprehensive Library Export Tests

Goal: Ensure library functions are correct before CLI migration

Create new test file: tests/export_integration_tests.rs

Test Requirements:

  • Test export_to_csv() produces valid CSV with correct headers
  • Test export_to_gpx() produces valid GPX XML
  • Test export_to_event() produces correct event log format
  • Test with various ExportOptions configurations
  • Test error handling (invalid paths, I/O errors)
  • Compare library output against known-good blackbox_decode output

AI Instructions:

Analyze src/export.rs functions export_to_csv, export_to_gpx, and export_to_event.
Create comprehensive integration tests in tests/export_integration_tests.rs that:
1. Use sample BBL data from tests/fixtures/
2. Export to temporary directories
3. Validate output format and content
4. Test all ExportOptions variations
5. Ensure outputs match blackbox_decode reference when applicable

Step 1.2: Document Current CLI Export Behavior

Goal: Capture any CLI-specific logic before refactoring

  • Document differences between CLI and library export implementations
  • Identify any CLI-specific features (e.g., batch processing, progress output)
  • Note any intentional format differences

AI Instructions:

Compare implementations between:
- src/main.rs:export_headers_to_csv (lines 1172-1209)
- src/export.rs:export_headers_to_csv (lines 124-159)

And:
- src/main.rs:export_flight_data_to_csv (lines 1210-1507)
- src/export.rs:export_flight_data_to_csv (lines 160-289)

Document:
1. Any algorithmic differences
2. Different error handling approaches
3. CLI-specific logging or progress indicators
4. Performance optimizations unique to either

Phase 2: Refactor CLI to Use Library (Priority: High)

Step 2.1: Replace export_headers_to_csv

Target: src/main.rs lines 1172-1209 (38 lines) → DELETE

AI Instructions:

In src/main.rs:
1. Remove function export_headers_to_csv (lines 1172-1209)
2. Find all call sites of export_headers_to_csv in main.rs
3. Since this is a private helper, it's only called by other main.rs export functions
4. Note: The library's export_to_csv already calls this helper internally
5. Update callers to use the library's public API instead
6. Run tests to ensure no behavioral changes

Step 2.2: Replace export_flight_data_to_csv

Target: src/main.rs lines 1210-1507 (298 lines) → DELETE

AI Instructions:

In src/main.rs:
1. Remove function export_flight_data_to_csv (lines 1210-1507)
2. Find all call sites in main.rs
3. The library's export_to_csv already calls export_flight_data_to_csv internally
4. Update callers to use bbl_parser::export_to_csv() instead
5. Ensure debug parameter is handled appropriately
6. Run all tests after changes

Step 2.3: Refactor export_logs_to_csv

Target: src/main.rs lines 1074-1127 (54 lines) → REFACTOR

This function handles batch CSV export for multiple logs. It can be simplified to call the library.

AI Instructions:

In src/main.rs function export_logs_to_csv (lines 1074-1127):
1. Keep the function signature (CLI-specific batch processing)
2. Replace internal logic with calls to:
   - bbl_parser::export_to_csv() for each log
3. Keep CLI-specific features:
   - Progress messages
   - Batch processing loop
   - Path construction for output files
4. Reduce function to ~20-30 lines (wrapper only)
5. Run tests after refactoring

Step 2.4: Refactor export_single_log_to_csv

Target: src/main.rs lines 1128-1171 (44 lines) → SIMPLIFY

AI Instructions:

In src/main.rs function export_single_log_to_csv (lines 1128-1171):
1. Keep function signature
2. Replace implementation with direct call to:
   bbl_parser::export_to_csv(&log, output_path, &export_options)?
3. Keep CLI-specific status messages
4. Reduce to ~10-15 lines
5. Verify output matches previous behavior

Step 2.5: Refactor export_gpx_file

Target: src/main.rs lines 1509-1573 (65 lines) → SIMPLIFY

AI Instructions:

In src/main.rs function export_gpx_file (lines 1509-1573):
1. Replace implementation with:
   bbl_parser::export_to_gpx(&log, output_path, &export_options)?
2. Keep CLI user messages
3. Reduce to ~10 lines

Step 2.6: Refactor export_event_file

Target: src/main.rs lines 1575-1616 (42 lines) → SIMPLIFY

AI Instructions:

In src/main.rs function export_event_file (lines 1575-1616):
1. Replace with:
   bbl_parser::export_to_event(&log, output_path, &export_options)?
2. Keep CLI messages
3. Reduce to ~10 lines

Phase 3: Testing & Validation (Priority: Critical)

Step 3.1: Run Full Test Suite

cargo test --all-features
cargo test --release

Expected Results:

  • All 37+ existing tests pass
  • New library export tests pass
  • Zero regressions in CLI behavior

Step 3.2: Manual CLI Testing

# Test CSV export
./target/release/bbl_parser tests/fixtures/sample.BBL --csv output.csv

# Test GPX export
./target/release/bbl_parser tests/fixtures/sample.BBL --gpx output.gpx

# Test event export
./target/release/bbl_parser tests/fixtures/sample.BBL --event output.event

# Test batch processing
./target/release/bbl_parser tests/fixtures/ --csv output_dir/

Validation:

  • Output files are identical to previous CLI version
  • File sizes match
  • Content byte-by-byte comparison passes

Step 3.3: Benchmark Performance

# Before refactoring
hyperfine 'target/release/bbl_parser tests/fixtures/large.BBL --csv /tmp/out.csv'

# After refactoring
hyperfine 'target/release/bbl_parser tests/fixtures/large.BBL --csv /tmp/out.csv'

Goal: No performance regression (within 5% variance)


Phase 4: Code Quality & Documentation (Priority: Medium)

Step 4.1: Update Documentation

  • Update AGENTS.md: Correct "Phase 5 complete" claim to accurately reflect current state
  • Update CRATE_USAGE.md: Add export API examples
  • Update README.md: Document library export capabilities
  • Add rustdoc examples to src/export.rs functions

AI Instructions:

Update AGENTS.md:
1. Change "Complete CLI-to-Crate Unification Phase 5" to "Phase 5: CLI-to-Crate Unification (Complete)"
2. Add section documenting:
   - Parsing layer unified (parse_frames, parse_headers_from_text)
   - Export layer unified (export_to_csv, export_to_gpx, export_to_event)
   - CLI is now thin wrapper (~200 lines of CLI-specific logic)
3. Update code organization section to reflect new structure

Add to CRATE_USAGE.md:
1. Section "Exporting Data"
2. Example code for each export function
3. Explain ExportOptions configuration

Step 4.2: Remove Dead Code

Target: Reduce src/main.rs from 1821 lines to ~1200 lines (600 line reduction)

  • Remove deleted export functions
  • Clean up unused imports
  • Remove redundant type definitions if any

Step 4.3: Code Quality Checks

cargo fmt
cargo clippy -- -D warnings
cargo build --release

Requirements:

  • Zero clippy warnings
  • Zero compiler warnings
  • Formatting compliant

Phase 5: Library API Stabilization (Priority: Medium)

Step 5.1: Review Public API

Current public exports from src/export.rs:

pub fn export_to_csv(log: &BBLLog, path: &Path, options: &ExportOptions) -> Result<()>
pub fn export_to_gpx(log: &BBLLog, path: &Path, options: &ExportOptions) -> Result<()>
pub fn export_to_event(log: &BBLLog, path: &Path, options: &ExportOptions) -> Result<()>

Questions to resolve:

  • Are these signatures stable for semver commitment?
  • Should we add convenience functions (e.g., export_to_csv_string())?
  • Should we expose progress callbacks for long exports?

Step 5.2: Prepare for crates.io Release

  • Ensure library is fully documented
  • Verify examples compile
  • Test against minimal Rust version (MSRV)
  • Review dependencies for unnecessary includes

Success Criteria

Quantitative Metrics

  • Code reduction: src/main.rs reduced from 1821 to ~1200 lines (34% reduction)
  • Duplication eliminated: 541 lines of export code → ~100 lines of thin wrappers
  • Test coverage: Library export functions have ≥80% coverage
  • Zero regressions: All existing tests pass
  • Performance: No degradation >5% in export operations

Qualitative Goals

  • Maintainability: Single source of truth for export logic
  • Library completeness: Export API tested and documented
  • CLI simplicity: CLI is demonstrably a thin wrapper
  • Documentation accuracy: Claims match implementation reality

Rollback Plan

If issues arise during refactoring:

  1. Git branching strategy:

    git checkout -b phase5-export-unification
    # Make changes
    git commit -m "Step X: [description]"
    # If issues: git revert <commit>
  2. Incremental commits: Each step above should be a separate commit

  3. Test between steps: Run cargo test after each major change

  4. Keep old code commented: During transition, keep old implementations as comments until validation complete


Estimated Effort

Phase Estimated Time Dependencies
Phase 1: Testing 1-2 days None
Phase 2: Refactoring 2-3 days Phase 1 complete
Phase 3: Validation 1 day Phase 2 complete
Phase 4: Documentation 1 day Phase 3 complete
Phase 5: Stabilization 1-2 days Phase 4 complete
Total 6-9 days Sequential

Additional Context

Why This Matters:
The current duplication creates technical debt that undermines the library-first architecture goal. External consumers cannot trust the library export API if it's untested and unused even by the project's own CLI.

Design Philosophy:
The CLI should be a thin layer demonstrating how to use the library, not reimplementing library functionality. This makes the project:

  • Easier to maintain (single source of truth)
  • More trustworthy for external consumers
  • Better documented (CLI serves as working example)
  • More testable (library tests are isolated from CLI concerns)

Issue Created By: AI code review (CodeRabbit)
Analysis Methodology: Static code analysis, test execution, line-by-line comparison

Metadata

Metadata

Assignees

Labels

No labels
No labels

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions