| Crates.io | rs-ach |
| lib.rs | rs-ach |
| version | 0.1.2 |
| created_at | 2025-10-25 18:24:12.59461+00 |
| updated_at | 2025-10-25 18:59:38.944813+00 |
| description | ACH (Automated Clearing House) file parser following NACHA specifications |
| homepage | |
| repository | https://github.com/abimael10/rs-ach |
| max_upload_size | |
| id | 1900503 |
| size | 48,244 |
ACH (Automated Clearing House) file parser for Rust following the NACHA (National Automated Clearing House Association) specifications.
Add this to your Cargo.toml:
[dependencies]
rs-ach = "0.1.2"
use rs_ach::AchFile;
fn main() -> Result<(), Box<dyn std::error::Error>> {
// Read ACH file content
let ach_content = std::fs::read_to_string("sample.ach")?;
// Parse the ACH file
let ach_file = AchFile::parse(&ach_content)?;
// Access file header information
println!("File Header:");
println!(" Destination: {}", ach_file.file_header.immediate_destination.trim());
println!(" Origin: {}", ach_file.file_header.immediate_origin.trim());
println!(" Creation Date: {}", ach_file.file_header.file_creation_date);
// Iterate through batches
for (i, batch) in ach_file.batches.iter().enumerate() {
println!("\nBatch {}:", i + 1);
println!(" Company: {}", batch.header.company_name.trim());
println!(" SEC Code: {}", batch.header.standard_entry_class_code);
println!(" Description: {}", batch.header.company_entry_description.trim());
// Iterate through entries in the batch
for (j, entry) in batch.entries.iter().enumerate() {
println!(" Entry {}:", j + 1);
println!(" Transaction Code: {}", entry.transaction_code);
println!(" Routing Number: {}{}",
entry.receiving_dfi_identification,
entry.check_digit
);
println!(" Account: {}", entry.dfi_account_number.trim());
println!(" Amount: ${:.2}", entry.amount as f64 / 100.0);
println!(" Name: {}", entry.individual_name.trim());
// Check for addenda records
if !entry.addenda.is_empty() {
println!(" Addenda:");
for addenda in &entry.addenda {
println!(" {}", addenda.payment_related_information.trim());
}
}
}
}
// Access file control totals
println!("\nFile Control:");
println!(" Batch Count: {}", ach_file.file_control.batch_count);
println!(" Total Debits: ${:.2}", ach_file.file_control.total_debit_amount as f64 / 100.0);
println!(" Total Credits: ${:.2}", ach_file.file_control.total_credit_amount as f64 / 100.0);
Ok(())
}
An ACH file consists of the following record types:
Contains file-level information including:
Contains batch-level information including:
Contains individual transaction information including:
Optional additional information for an entry detail record.
Contains batch totals and counts:
Contains file-level totals and counts:
The parser provides detailed error information through the AchError enum:
use rs_ach::{AchFile, AchError};
match AchFile::parse(content) {
Ok(ach_file) => {
// Process the file
},
Err(AchError::InvalidLineLength(len)) => {
eprintln!("Invalid line length: {}", len);
},
Err(AchError::InvalidRecordType(rt)) => {
eprintln!("Invalid record type: {}", rt);
},
Err(e) => {
eprintln!("Parse error: {}", e);
}
}
Run the test suite:
cargo test
The test suite includes:
MIT