use std::fs::File;
use std::io::{self, BufRead, BufReader};
use std::path::PathBuf;
use aivdm::{AisError, decode_line};
use anyhow::{Context, Result};
use clap::Parser;
mod print;
#[derive(Parser)]
struct Args {
file: Option<PathBuf>,
#[arg(long)]
stats: bool,
}
fn main() -> Result<()> {
let args = Args::parse();
let mut decoded = 0u64;
let mut skipped = 0u64;
let lines = read_lines(args.file.as_deref())?;
for line in lines {
let line = line.context("reading input line")?;
if line.trim().is_empty() {
continue;
}
match decode_line(&line) {
Ok(message) => {
decoded += 1;
if !args.stats {
print::print_message(&message);
}
}
Err(AisError::IncompleteFragment) => {
skipped += 1;
}
Err(err) => {
skipped += 1;
eprintln!("skipping line ({err}): {line}");
}
}
}
if args.stats {
println!("decoded: {decoded}, skipped: {skipped}");
}
Ok(())
}
fn read_lines(
path: Option<&std::path::Path>,
) -> Result<Box<dyn Iterator<Item = io::Result<String>>>> {
match path {
Some(path) => {
let file = File::open(path).with_context(|| format!("opening {}", path.display()))?;
Ok(Box::new(BufReader::new(file).lines()))
}
None => Ok(Box::new(BufReader::new(io::stdin()).lines())),
}
}