barexp 0.1.0

A Rust library providing elegant barrel exports with compile-time safety
Documentation

barexp

A Rust library providing elegant barrel exports with compile-time safety and collision detection.

Overview

barexp simplifies module exports in Rust by providing a macro-based approach similar to TypeScript's barrel exports. It offers compile-time collision detection, full path exports, and a clean API for managing module exports.

Features

  • Attribute-based exports with #[export] and #[export_fullpath]
  • Compile-time collision detection
  • Module-level export aggregation
  • Zero runtime overhead
  • Clean and intuitive API
  • Workspace-friendly design

Installation

Add barexp to your Cargo.toml:

[dependencies]
barexp = "0.1.0"

Usage

Basic Export

Use the #[export] attribute to mark items for export and the export!() macro to expose them at the module level:

// services/crypto.rs
use barexp::export;

#[export]
pub struct CryptoService {
    // Your implementation
}

// services/mod.rs
use barexp::export;
export!();

// main.rs
use crate::services::CryptoService; // Direct access!

Handling Name Collisions

When you have multiple items with the same name in different modules, you can use #[export_fullpath]:

// services/user/auth.rs
use barexp::export_fullpath;

#[export_fullpath]
pub struct User { }  // Will be exported as services::user::auth::User

// services/admin/auth.rs
use barexp::export_fullpath;

#[export_fullpath]
pub struct User { }  // Will be exported as services::admin::auth::User

Compile-time Safety

barexp provides compile-time safety by detecting name collisions during compilation:

// This will cause a compile error:
#[export]
pub struct User { }  // in module A

#[export]
pub struct User { }  // in module B

// Error: Name collision detected: 'User' is already exported in 'moduleA'

How It Works

barexp uses Rust's procedural macros and the inventory pattern to:

  1. Register exported items at compile time
  2. Detect naming collisions early
  3. Generate efficient re-exports
  4. Maintain type safety throughout

The library has zero runtime overhead as all the work is done during compilation.

Best Practices

  1. Use #[export] for most cases when you want clean imports
  2. Switch to #[export_fullpath] when you need to disambiguate between items with the same name
  3. Place export!() in your module's root (mod.rs)
  4. Consider using #[export_fullpath] by default in large projects to prevent future collisions

Examples

Organizing Services

// services/crypto.rs
use barexp::export;

#[export]
pub struct CryptoService {
    // implementation
}

// services/user.rs
use barexp::export;

#[export]
pub struct UserService {
    // implementation
}

// services/mod.rs
use barexp::export;
export!();

// main.rs
use crate::services::{CryptoService, UserService};

fn main() {
    let crypto = CryptoService {};
    let user = UserService {};
}

Using Full Paths

// features/auth/user.rs
use barexp::export_fullpath;

#[export_fullpath]
pub struct AuthService {
    // implementation
}

// features/payment/user.rs
use barexp::export_fullpath;

#[export_fullpath]
pub struct AuthService {
    // implementation
}

// Usage:
use crate::features::auth::AuthService as AuthAuthService;
use crate::features::payment::AuthService as PaymentAuthService;

Contributing

Contributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.

Testing

Run the test suite:

cargo test               # Run all tests
cargo test -- --nocapture  # Run tests with output

The test suite includes:

  • Unit tests

License

This project is licensed under the MIT License - see the LICENSE file for details.

Acknowledgments

This project was inspired by TypeScript's barrel exports pattern and built using Rust's powerful macro system.