use std::{fs::File, io::Write};
use jimtcl::{
Interp, JimError, JimObject, JimResult, check_or_error, custom::JimExtensionType, tcl_error,
};
use serde_json::{from_reader, to_string, to_string_pretty, to_writer, to_writer_pretty};
use super::TypedData;
pub fn td_parse_json<'jim>(
_interp: &'jim Interp,
args: &[JimObject<'jim>],
) -> JimResult<TypedData> {
let usage = "usage: td parse json ?-file? <input>";
check_or_error!(args.len() >= 2, usage);
if args[1].as_str()? == "-file" {
check_or_error!(args.len() == 3, usage);
let path = &args[2];
path.require_untainted("path")?;
let file = File::open(path.as_str()?)?;
from_reader(file).map_err(JimError::wrap)
} else {
check_or_error!(args.len() == 2, usage);
let data = TypedData::extract_ref(&args[1])?;
Ok(data.clone())
}
}
pub fn td_dump_json<'jim>(_interp: &'jim Interp, args: &[JimObject<'jim>]) -> JimResult<String> {
let usage = "usage: td dump json ?-pretty? ?-file out? <td>";
let mut pretty = false;
let mut out_file = None;
let mut pos = 1;
while pos < args.len() {
let arg = &args[pos];
let astr = arg.as_str()?;
if astr == "-pretty" {
pretty = true;
pos += 1;
} else if astr == "-file" {
let path = &args[pos + 1];
path.require_untainted("path")?;
out_file = Some(path.as_str()?);
pos += 2;
} else if astr == "--" {
pos += 1;
break;
} else if astr.starts_with("-") {
return Err(tcl_error!("invalid option {}", astr));
} else {
break;
}
}
check_or_error!(pos == args.len() - 1, usage);
let data = TypedData::extract(&args[pos])?;
if let Some(f) = out_file {
let mut out = File::options()
.create(true)
.write(true)
.truncate(true)
.open(f)?;
if pretty {
to_writer_pretty(out, &data)
.map_err(|e| tcl_error!("could not generate JSON: {}", e))?;
} else {
to_writer(&mut out, &data).map_err(|e| tcl_error!("could not generate JSON: {}", e))?;
out.write_all(b"\n")?;
}
Ok("".into())
} else {
let text = if pretty {
to_string_pretty(&data)
} else {
to_string(&data)
};
text.map_err(|e| tcl_error!("could not generate JSON: {}", e))
}
}