use clap::Parser;
use std::fs::{File, OpenOptions};
use std::io::{BufRead, Error, Read, Seek, SeekFrom, Write};
use std::path::PathBuf;
#[derive(Parser, Debug)]
#[clap(name = "kp")]
#[clap(author, version, about, long_about = None)]
struct Cli {
#[clap(short, long)]
debug: bool,
#[clap(short, long, parse(from_occurrences))]
_verbose: u8,
#[clap(short, long, parse(from_os_str))]
output: Option<PathBuf>,
#[clap(name = "FILE", parse(from_os_str))]
files: Vec<PathBuf>,
}
fn main() -> Result<(), Error> {
let opt = Cli::parse();
let mut default_dir = dirs::data_local_dir().unwrap_or_default();
default_dir.push("geodesy");
default_dir.push("pile");
eprintln!("Default directory: {}", default_dir.to_str().unwrap());
let mut pile_path = default_dir.clone();
if let Some(output) = &opt.output {
pile_path = PathBuf::from(output);
default_dir = pile_path.clone();
default_dir.pop();
eprintln!("pilepath: {}", pile_path.to_str().unwrap_or_default());
eprintln!("default_dir: {}", default_dir.to_str().unwrap_or_default());
} else {
pile_path.push("pile.bin");
}
eprintln!("pilepath: {}", pile_path.to_str().unwrap_or_default());
let mut pile = OpenOptions::new()
.write(true)
.create(true)
.open(pile_path)?;
pile.seek(SeekFrom::End(0))?;
#[allow(clippy::redundant_clone)]
let mut pile_dir = default_dir.clone();
pile_dir.push("geodesy");
pile_dir.push("pile");
std::fs::create_dir_all(&pile_dir)?;
let mut basename;
for path in &opt.files {
basename = path
.file_stem()
.unwrap_or_default()
.to_str()
.unwrap_or_default();
let pos = pile.stream_position()?;
if "raw" != path.extension().unwrap_or_default() {
eprintln!(
"Ignoring non-raw-file arg: {:?}",
path.file_name().unwrap_or_default()
);
continue;
}
let mut file = File::open(path)?;
let mut buffer = Vec::<u8>::new();
let length = file.read_to_end(&mut buffer)?;
pile.write_all(&buffer)?;
let nextpos = pile.stream_position()?;
assert_eq!((nextpos - pos) as usize, length);
let mut aux_path = path.clone();
aux_path.set_extension("aux");
let aux_file = File::open(&aux_path);
if aux_file.is_err() {
eprintln!(
"File: {:?} not found - removing the corresponding raw file from pile.",
aux_path
);
pile.set_len(pos)?;
pile.seek(SeekFrom::End(0))?;
eprintln!(
"Was {} bytes. Truncated to {} bytes",
nextpos,
pile.stream_position()?
);
continue;
}
let aux = std::io::BufReader::new(aux_file?);
let mut aux_out_path = pile_dir.clone();
aux_out_path.push(aux_path.file_name().unwrap());
let mut aux_out = File::create(aux_out_path)?;
let line = format!("<{}>\nWhence: {}\n", basename, pos);
aux_out.write_all(line.as_bytes())?;
for line in aux.lines() {
let mut line = line.unwrap().clone();
let mut e: Vec<&str> = line.split_whitespace().collect();
if e[0] == "Whence:" {
continue;
}
if e[0] == "LoRightY:" {
e[0] = "Bottom";
}
if e[0] == "UpLeftX:" {
e[0] = "Left";
}
if e[0] == "UpLeftY:" {
e[0] = "Top";
}
if e[0] == "LoRightX:" {
e[0] = "Right";
}
if line.starts_with("RawDefinition:") {
assert!(e.len() == 4);
let geometry = format!("Columns: {}\nRows: {}\nBands: {}\n", e[1], e[2], e[3]);
aux_out.write_all(geometry.as_bytes())?;
continue;
}
line += "\n";
aux_out.write_all(line.as_bytes())?;
}
}
if opt.debug {
eprintln!("{:#?}", opt);
}
Ok(())
}