braintax/lib.rs
1//! # braintax
2//!
3//! A minimal utility crate for estimating the cognitive "tax" of code patterns.
4//!
5//! This crate provides a simple scoring function that quantifies how mentally
6//! taxing a given code structure is, based on nesting depth and branching
7//! complexity. It is designed as a lightweight companion to complexity analysis
8//! tools like `crap4rust`.
9//!
10//! ## Example
11//!
12//! ```rust
13//! use braintax::Braintax;
14//!
15//! let score = Braintax::new()
16//! .with_nesting(3)
17//! .with_branches(5)
18//! .compute();
19//!
20//! assert!(score > 0);
21//! ```
22
23/// A cognitive "tax" estimator that combines nesting depth and branching
24/// complexity into a single score.
25///
26/// The formula is intentionally simple:
27/// `tax = nesting² + branches + 1`
28///
29/// This provides a rough heuristic: deeply nested code with many branches
30/// is more mentally taxing to read and maintain.
31#[derive(Clone, Copy, Debug, Default)]
32pub struct Braintax {
33 nesting: u32,
34 branches: u32,
35}
36
37impl Braintax {
38 /// Creates a new `Braintax` with zero nesting and zero branches.
39 #[must_use]
40 pub fn new() -> Self {
41 Self::default()
42 }
43
44 /// Sets the nesting depth (e.g., how many levels deep control flow is nested).
45 #[must_use]
46 pub const fn with_nesting(mut self, nesting: u32) -> Self {
47 self.nesting = nesting;
48 self
49 }
50
51 /// Sets the number of branching points (e.g., `if`, `match`, `loop` constructs).
52 #[must_use]
53 pub const fn with_branches(mut self, branches: u32) -> Self {
54 self.branches = branches;
55 self
56 }
57
58 /// Computes the cognitive tax score.
59 ///
60 /// # Formula
61 ///
62 /// ```text
63 /// tax = nesting² + branches + 1
64 /// ```
65 ///
66 /// A score of **1** represents the baseline (no nesting, no branches).
67 /// Higher scores indicate increasing mental taxation.
68 #[must_use]
69 pub const fn compute(&self) -> u64 {
70 (self.nesting as u64).pow(2) + self.branches as u64 + 1
71 }
72}
73
74#[cfg(test)]
75mod tests {
76 use super::*;
77
78 #[test]
79 fn baseline_returns_one() {
80 let tax = Braintax::new().compute();
81 assert_eq!(tax, 1);
82 }
83
84 #[test]
85 fn nesting_increases_score_quadratically() {
86 let tax = Braintax::new().with_nesting(3).compute();
87 assert_eq!(tax, 10); // 3² + 0 + 1 = 10
88 }
89
90 #[test]
91 fn branches_add_linearly() {
92 let tax = Braintax::new().with_branches(5).compute();
93 assert_eq!(tax, 6); // 0² + 5 + 1 = 6
94 }
95
96 #[test]
97 fn combined_nesting_and_branches() {
98 let tax = Braintax::new().with_nesting(2).with_branches(4).compute();
99 assert_eq!(tax, 9); // 2² + 4 + 1 = 9
100 }
101
102 #[test]
103 fn large_values_do_not_overflow() {
104 let tax = Braintax::new()
105 .with_nesting(1_000)
106 .with_branches(100_000)
107 .compute();
108 assert_eq!(tax, 1_100_001); // 1000² + 100000 + 1 = 1_100_001
109 }
110
111 #[test]
112 fn debug_format_does_not_panic() {
113 let tax = Braintax::new().with_nesting(1).with_branches(2);
114 let _ = format!("{tax:?}");
115 }
116
117 #[test]
118 fn clone_produces_equal_score() {
119 let original = Braintax::new().with_nesting(4).with_branches(3);
120 let cloned = original;
121 assert_eq!(original.compute(), cloned.compute());
122 }
123}