Skip to content

API Reference

obbba-breaks exposes a FilingStatus enum, two parameter structs (StandardDeduction, QualifiedDeductionParams), and a set of free functions covering the standard deduction, the overtime/tips deductions, and their sum. All money values are f64 dollars; every function is clamping-safe (negative amounts are treated as zero, no panics).

FilingStatus

pub enum FilingStatus { Single, Joint }

Selects default parameter sets for both the standard deduction and the qualified overtime/tips deduction.

Standard deduction

StandardDeduction

pub struct StandardDeduction {
    pub base: f64,            // permanent (TCJA-level) standard deduction
    pub temporary_addon: f64, // OBBBA add-on available 2025–2028
}
impl StandardDeduction {
    pub const SINGLE_2025: StandardDeduction; // base 15,750  addon 750
    pub const JOINT_2025:  StandardDeduction; // base 31,500  addon 1,500
    pub fn total(&self) -> f64;                // base + temporary_addon
}

addon_applies

pub fn addon_applies(year: u32) -> bool

Whether the temporary OBBBA add-on applies for the given tax year — true for 2025..=2028 inclusive, false outside that window.

use obbba_breaks::addon_applies;
assert!(addon_applies(2025));
assert!(addon_applies(2028));
assert!(!addon_applies(2024));
assert!(!addon_applies(2029));

standard_deduction

pub fn standard_deduction(status: FilingStatus, year: u32) -> f64

Estimated total standard deduction for a filing status and tax year. For years inside the 2025–2028 window the temporary add-on is included; outside the window (e.g. 2029 onward, once the add-on sunsets) only the permanent base is returned. Amounts are the 2025 estimates and are not inflation-indexed here — callers needing future-year precision should use standard_deduction_with with their own indexed figures.

use obbba_breaks::{standard_deduction, FilingStatus};
assert!((standard_deduction(FilingStatus::Single, 2025) - 16_500.0).abs() < 1e-6); // 15,750 + 750
assert!((standard_deduction(FilingStatus::Joint,  2025) - 33_000.0).abs() < 1e-6); // 31,500 + 1,500
assert!((standard_deduction(FilingStatus::Single, 2029) - 15_750.0).abs() < 1e-6); // base only

standard_deduction_with

pub fn standard_deduction_with<F>(status: FilingStatus, year: u32, lookup: F) -> f64
where F: Fn(FilingStatus, u32) -> StandardDeduction

Same as standard_deduction but with a caller-supplied lookup for the base/addon parameters — e.g. to plug in IRS-inflation-indexed figures for future years.

Qualified overtime / tips deductions

QualifiedDeductionParams

pub struct QualifiedDeductionParams {
    pub cap: f64,
    pub phase_out_start: f64,
    pub phase_out_rate: f64,
}

Parameters for the above-the-line overtime/tips deduction (estimates).

  • cap — maximum deduction when fully eligible.
  • phase_out_start — MAGI at which the phase-out begins.
  • phase_out_rate — dollars of deduction lost per dollar of MAGI over the threshold ($1 per $100.1).
impl QualifiedDeductionParams {
    pub const SINGLE: QualifiedDeductionParams; // cap 12,500  start 150,000  rate 0.1
    pub const JOINT:  QualifiedDeductionParams; // cap 25,000  start 300,000  rate 0.1
    pub fn phase_out_end(&self) -> f64;         // start + cap / rate
}

qualified_effective_cap

pub fn qualified_effective_cap(magi: f64, p: QualifiedDeductionParams) -> f64

Effective cap on a qualified (overtime/tips) deduction at a given MAGI, before considering how much the taxpayer actually earned. Below the start it equals cap; above the end it equals 0; between them it falls off linearly.

use obbba_breaks::{qualified_effective_cap, QualifiedDeductionParams};
let p = QualifiedDeductionParams::SINGLE;
assert!((qualified_effective_cap(160_000.0, p) - 11_500.0).abs() < 1e-6); // $10k over → −$1,000
assert!((p.phase_out_end() - 275_000.0).abs() < 1e-6);
assert_eq!(qualified_effective_cap(300_000.0, p), 0.0);

overtime_deduction

pub fn overtime_deduction(qualified_overtime: f64, magi: f64, status: FilingStatus) -> f64

Estimated qualified overtime deduction — the lesser of overtime earned and the effective cap at the taxpayer's MAGI. Estimates pending final IRS guidance. Negative amounts are clamped to zero.

use obbba_breaks::{overtime_deduction, FilingStatus};
assert!((overtime_deduction(8_000.0,  90_000.0, FilingStatus::Single) -  8_000.0).abs() < 1e-6);
assert!((overtime_deduction(40_000.0, 90_000.0, FilingStatus::Single) - 12_500.0).abs() < 1e-6); // capped
assert_eq!(overtime_deduction(-1_000.0, 90_000.0, FilingStatus::Single), 0.0);

tips_deduction

pub fn tips_deduction(qualified_tips: f64, magi: f64, status: FilingStatus) -> f64

Estimated qualified tips deduction — same structure as overtime, capped and phased out identically. Estimates pending final IRS guidance.

use obbba_breaks::{tips_deduction, FilingStatus};
assert!((tips_deduction(40_000.0, 200_000.0, FilingStatus::Joint) - 25_000.0).abs() < 1e-6); // capped joint

total_deduction

pub fn total_deduction(
    status: FilingStatus,
    year: u32,
    qualified_overtime: f64,
    qualified_tips: f64,
    magi: f64,
) -> f64

Estimated total OBBBA deduction = standard deduction + overtime deduction + tips deduction, all for one filing status and year. This treats the above-the-line deductions as stacking on top of the standard deduction (which is how above-the-line deductions work).

use obbba_breaks::{total_deduction, FilingStatus};
// Single 2025, $8k OT + $5k tips, MAGI $90k → 16,500 + 8,000 + 5,000 = 29,500
let t = total_deduction(FilingStatus::Single, 2025, 8_000.0, 5_000.0, 90_000.0);
assert!((t - 29_500.0).abs() < 1e-6);

// Same but $40k OT + $40k tips (both capped) → 16,500 + 12,500 + 12,500 = 41,500
let c = total_deduction(FilingStatus::Single, 2025, 40_000.0, 40_000.0, 90_000.0);
assert!((c - 41_500.0).abs() < 1e-6);