use std::path::PathBuf;
use bcur::{Decoder, DecoderLimits, UrType};
use clap::Args;
use crate::error::{Error, Result};
use crate::io_util::{read_text, write_bytes};
#[derive(Debug, Args)]
pub(crate) struct DecodeArgs {
#[arg(long = "type")]
ur_type: Option<String>,
#[arg(long)]
hex: bool,
#[arg(short, long)]
out: Option<PathBuf>,
input: Option<PathBuf>,
}
pub(crate) fn run(args: &DecodeArgs) -> Result<()> {
let text = read_text(args.input.as_deref())?;
let lines: Vec<&str> = text
.lines()
.map(str::trim)
.filter(|line| !line.is_empty())
.collect();
if lines.is_empty() {
return Err(Error::msg("no UR lines in input"));
}
let mut decoder = Decoder::with_limits(DecoderLimits::default());
if let Some(t) = args.ur_type.as_deref() {
decoder = decoder.with_expected_type(UrType::new(t)?);
}
for (idx, line) in lines.iter().enumerate() {
decoder.receive(line)?;
if let Some(resolved) = decoder.resolved_fragment_count() {
eprintln!(
"part {} resolved={resolved}/{}",
idx + 1,
decoder.fragment_count()
);
}
if decoder.complete() {
let data = decoder
.message()?
.ok_or_else(|| Error::msg("decoder complete without message"))?;
return write_bytes(args.out.as_deref(), &data, args.hex);
}
}
Err(Error::msg(
"stream ended before the fountain message completed",
))
}