use clap;
use std::io::Write;
use std::str::FromStr;
use log::{debug,error};
use super::{ItemType,CommandError};
use crate::img::DiskImage;
use crate::{STDRESULT,DYNERR};
const RCH: &str = "unreachable was reached";
fn parse_sector(farg: &str) -> Result<[usize;3],DYNERR> {
let fcopy = String::from(farg);
let it: Vec<&str> = fcopy.split(',').collect();
if it.len()!=3 {
error!("sector specification should be in form `cylinder,head,sector`");
return Err(Box::new(CommandError::InvalidCommand));
}
let cyl = usize::from_str(it[0])?;
let head = usize::from_str(it[1])?;
let sec = usize::from_str(it[2])?;
debug!("user requested cyl {} head {} sec {}",cyl,head,sec);
Ok([cyl,head,sec])
}
fn parse_track(farg: &str) -> Result<[usize;2],DYNERR> {
let fcopy = String::from(farg);
let it: Vec<&str> = fcopy.split(',').collect();
if it.len()!=2 {
error!("track specification should be in form `cylinder,head`");
return Err(Box::new(CommandError::InvalidCommand));
}
let cyl = usize::from_str(it[0])?;
let head = usize::from_str(it[1])?;
debug!("user requested cyl {} head {}",cyl,head);
Ok([cyl,head])
}
fn output_get(dat: Vec<u8>,typ: ItemType,img: Box<dyn DiskImage>) {
if atty::is(atty::Stream::Stdout) {
match typ {
ItemType::Track => println!("{}",img.display_track(&dat)),
_ => crate::display_block(0,&dat)
};
} else {
std::io::stdout().write_all(&dat).expect("could not write stdout")
}
}
pub fn get(cmd: &clap::ArgMatches) -> STDRESULT {
let src_path = cmd.get_one::<String>("file").expect(RCH);
let typ = ItemType::from_str(&cmd.get_one::<String>("type").expect(RCH)).expect(RCH);
let img_path = cmd.get_one::<String>("dimg").expect(RCH);
match crate::create_img_from_file(&img_path) {
Ok(mut img) => {
let bytes = match typ {
ItemType::Sector => {
let [cyl,head,sec] = parse_sector(&src_path)?;
img.read_sector(cyl, head, sec)?
},
ItemType::Track => {
let [cyl,head] = parse_track(&src_path)?;
img.get_track_nibbles(cyl, head)?
},
ItemType::RawTrack => {
let [cyl,head] = parse_track(&src_path)?;
img.get_track_buf(cyl, head)?
},
_ => panic!("{}",RCH)
};
return Ok(output_get(bytes,typ,img));
},
Err(e) => return Err(e)
}
}
pub fn get_meta(cmd: &clap::ArgMatches) -> STDRESULT {
let maybe_selection = cmd.get_one::<String>("file");
let img_path = cmd.get_one::<String>("dimg").expect(RCH);
match crate::create_img_from_file(&img_path) {
Ok(img) => {
match maybe_selection {
None => {
println!("{}",img.get_metadata(4));
Ok(())
}
Some(selection) => {
if selection.chars().next()!=Some('/') {
error!("selection string should start with `/`");
return Err(Box::new(CommandError::KeyNotFound));
}
match json::parse(&img.get_metadata(0)) {
Ok(parsed) => {
let mut keys = selection.split('/');
let mut obj = parsed;
keys.next();
while let Some(key) = keys.next() {
if key=="" {
break;
}
match obj[key].clone() {
json::JsonValue::Null => return Err(Box::new(CommandError::KeyNotFound)),
x => { obj = x }
};
}
println!("{}",json::stringify_pretty(obj, 4));
Ok(())
},
Err(e) => Err(Box::new(e))
}
}
}
},
Err(e) => return Err(e)
}
}