rustloclib

Crates.iorustloclib
lib.rsrustloclib
version0.7.0
created_at2026-01-09 23:44:29.412094+00
updated_at2026-01-16 02:36:11.418859+00
descriptionA Rust-aware lines of code counter that separates code, tests, comments, and blanks
homepage
repositoryhttps://github.com/arthur-debert/rustloc
max_upload_size
id2033174
size211,826
Arthur Debert (arthur-debert)

documentation

README

rustloclib

A Rust-aware lines of code counter library that separates code, tests, comments, and blank lines.

Crates.io Documentation License: MIT

Overview

Unlike generic LOC counters, this library understands Rust's unique structure where tests live alongside production code. It uses syntax-aware parsing to distinguish:

  • Main: Production code lines
  • Tests: Code within #[test] or #[cfg(test)] blocks, or in tests/ directories
  • Examples: Code in examples/ directories
  • Docs: Documentation comments (///, //!, /** */, /*! */)
  • Comments: Regular comments (//, /* */)
  • Blank: Whitespace-only lines

Features

  • Rust-aware parsing: Properly handles #[cfg(test)], #[test] attributes
  • Cargo workspace support: Discover and filter crates within a workspace
  • Glob filtering: Include/exclude files with glob patterns
  • Pure Rust data types: Returns structured data for easy integration

Installation

Add to your Cargo.toml:

[dependencies]
rustloclib = "0.1"

Usage

Count a workspace

use rustloclib::{count_workspace, CountOptions};

let result = count_workspace(".", CountOptions::new())?;

println!("Files: {}", result.total.file_count);
println!("Main code: {}", result.total.main.code);
println!("Test code: {}", result.total.tests.code);
println!("Total: {}", result.total.total());

Count specific crates

use rustloclib::{count_workspace, CountOptions};

let result = count_workspace(".", CountOptions::new()
    .crates(vec!["my-lib".to_string(), "my-cli".to_string()]))?;

Filter files with globs

use rustloclib::{count_workspace, CountOptions, FilterConfig};

let filter = FilterConfig::new()
    .exclude("**/generated/**")?
    .exclude("**/vendor/**")?;

let result = count_workspace(".", CountOptions::new().filter(filter))?;

Count a single file

use rustloclib::count_file;

let stats = count_file("src/main.rs")?;
println!("Code: {}, Docs: {}", stats.main.code, stats.main.docs);

Parse from a string (for testing)

use rustloclib::{parse_string, VisitorContext};

let source = r#"
fn main() {
    println!("Hello");
}

#[test]
fn test_main() {
    assert!(true);
}
"#;

let stats = parse_string(source, VisitorContext::Main);
assert_eq!(stats.main.code, 3);  // fn, println, }
assert_eq!(stats.tests.code, 4); // #[test], fn, assert, }

Data Structures

LocStats

Aggregated statistics for a collection of files:

pub struct LocStats {
    pub file_count: u64,
    pub main: Locs,      // Production code
    pub tests: Locs,     // Test code
    pub examples: Locs,  // Example code
}

Locs

Line counts for a single context:

pub struct Locs {
    pub blank: u64,     // Whitespace-only lines
    pub code: u64,      // Code lines
    pub docs: u64,      // Doc comment lines
    pub comments: u64,  // Regular comment lines
}

CountResult

Result from counting operations:

pub struct CountResult {
    pub total: LocStats,           // Aggregated stats
    pub crates: Vec<CrateStats>,   // Per-crate breakdown
    pub files: Vec<FileStats>,     // Per-file breakdown (if requested)
}

Acknowledgments

The parsing logic is adapted from cargo-warloc by Maxim Gritsenko (MIT licensed).

License

MIT License

Commit count: 51

cargo fmt