Rust Report Project
Parse a documented input format and return structured errors.
How it works
The final project totals seed packets from a deliberately simple two-field text format. It validates area labels and bounded decimal counts, checks addition and distinguishes empty, malformed and out-of-range input. The complete Cargo package separates a library contract from a tiny binary. It uses no third-party crates, network service or real participant data.
Run the code
Reviewed with Rust 1.97.0, edition 2024, using the standard library only. Save the complete download as lesson-name.rs in a separate learning folder, compile with rustc --edition=2024 lesson-name.rs and run the resulting program (lesson-name.exe on Windows). Use the actual lesson filename. The final project includes complete Cargo package files; run cargo test --offline and cargo run --offline from that separate package folder. There is no Rust browser runner; PHP, Apache and MySQL are not needed.
This complete example was executed in the stated local review environment.
Complete Cargo package
Save these files at the exact relative paths in one new learning folder. From that folder run cargo test --offline and cargo run --offline.
Example
#[derive(Debug, PartialEq, Eq)]
pub enum ReportError { Empty, Format, Range, Overflow }
pub fn total_packets(input: &str) -> Result<u32, ReportError> {
if input.is_empty() { return Err(ReportError::Empty); }
let mut total = 0_u32;
for line in input.lines() {
let (area, text) = line.split_once(',').ok_or(ReportError::Format)?;
if area.is_empty() || !area.bytes().all(|b| b.is_ascii_lowercase()) || text.is_empty() || text.len() > 3 || !text.bytes().all(|b| b.is_ascii_digit()) {
return Err(ReportError::Format);
}
let count = text.parse::<u32>().map_err(|_| ReportError::Format)?;
if count > 100 { return Err(ReportError::Range); }
total = total.checked_add(count).ok_or(ReportError::Overflow)?;
}
Ok(total)
}
#[cfg(test)]
mod tests {
use super::*;
#[test] fn totals() { assert_eq!(total_packets("north,8\nsouth,5\nnorth,3\n"),Ok(16)); }
#[test] fn empty() { assert_eq!(total_packets(""),Err(ReportError::Empty)); }
#[test] fn malformed() { for input in ["north,bad","north,8,extra",",8","North,8","north,-1","north,"] { assert_eq!(total_packets(input),Err(ReportError::Format)); } }
#[test] fn range() { assert_eq!(total_packets("north,101"),Err(ReportError::Range)); }
#[test] fn boundaries() { assert_eq!(total_packets("north,0\nsouth,100"),Ok(100)); }
}
fn main() {
assert_eq!(total_packets("north,8\nsouth,5\nnorth,3\n"), Ok(16));
assert_eq!(total_packets("north,101"), Err(ReportError::Range));
println!("Seed report total 16; invalid range refused");
}
Expected result
Seed report total 16; invalid range refused
The parser checks every row before returning a total, so a malformed later row cannot yield a partial successful report. split_once does not implement quoted CSV; the narrow field grammar intentionally rejects extra commas. The accompanying Cargo package contains the same library and five real tests. Build and test it offline from a separate learning folder.
Primary technical reference: Rust documentation.