use clap;
use std::str::FromStr;
use log::{info,error};
use crate::img::tracks::Method;
use super::{ItemType,CommandError};
use crate::STDRESULT;
const RCH: &str = "unreachable was reached";
const RANGED_ACCESS: &str =
"Writing to multiple sectors is only allowed if the buffers match exactly";
pub fn put(cmd: &clap::ArgMatches,dat: &[u8]) -> STDRESULT {
let dest_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);
let fmt = super::get_fmt(cmd)?;
let maybe_explicit_list = cmd.get_one::<String>("explicit");
match crate::create_img_from_file(&img_path) {
Ok(mut img) => {
img.change_method(Method::from_str(cmd.get_one::<String>("method").unwrap())?);
match typ {
ItemType::Sector => {
if let Some(fmt) = fmt {
img.change_format(fmt)?;
}
let mut ptr = 0;
let mut sec_list = super::parse_sector_request(&dest_path,img.motor_steps_per_cyl())?;
if let Some(explicit_list) = maybe_explicit_list {
super::to_explicit(&explicit_list,&mut sec_list)?;
}
let mut sec_len_list = Vec::new();
for (trk,sec) in &sec_list {
let sec_len = img.read_sector(*trk, sec.clone())?.len();
sec_len_list.push(sec_len);
ptr += sec_len;
}
if ptr != dat.len() && sec_list.len() > 1 {
error!("{}",RANGED_ACCESS);
return Err(Box::new(CommandError::InvalidCommand));
}
ptr = 0;
for i in 0..sec_list.len() {
img.write_sector(sec_list[i].0,sec_list[i].1.clone(),&dat[ptr..])?;
ptr += sec_len_list[i];
}
},
ItemType::RawTrack => {
img.set_track_buf(super::request_one_track(&dest_path,img.motor_steps_per_cyl())?,dat)?
},
ItemType::Track => {
error!("cannot copy nibbles, try using the raw track");
return Err(Box::new(CommandError::InvalidCommand));
}
_ => panic!("{}",RCH)
};
std::fs::write(img_path,img.to_bytes())?;
return Ok(());
},
Err(e) => return Err(e)
}
}
pub fn put_meta(cmd: &clap::ArgMatches,dat: &[u8]) -> 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(mut img) => {
img.change_method(Method::from_str(cmd.get_one::<String>("method").unwrap())?);
let json_string = String::from_utf8(dat.to_vec())?;
let parsed = json::parse(&json_string)?;
let mut curs = crate::JsonCursor::new();
while let Some((key,leaf)) = curs.next(&parsed) {
if key=="_pretty" {
match curs.parent(&parsed) {
Some(parent) => {
if !parent.has_key("_raw") {
error!("found _pretty key but no _raw key for {}",parent.to_string());
return Err(Box::new(CommandError::KeyNotFound));
}
},
None => {
error!("found _pretty key without a parent");
return Err(Box::new(CommandError::UnknownFormat));
}
}
continue;
}
if let Some(selection) = maybe_selection {
if selection.chars().next()!=Some('/') {
error!("selection string should start with `/`");
return Err(Box::new(CommandError::KeyNotFound));
}
if selection.ends_with("/") && curs.key_path_string().contains(selection) {
img.put_metadata(&curs.key_path(), leaf)?;
} else if &curs.key_path_string()==selection {
img.put_metadata(&curs.key_path(), leaf)?;
} else {
info!("skipping `{}` based on selection string `{}`",curs.key_path_string(),selection);
}
} else {
img.put_metadata(&curs.key_path(), leaf)?;
}
}
std::fs::write(img_path,img.to_bytes())?;
Ok(())
},
Err(e) => return Err(e)
}
}