use jaq_core::{
load::{Arena, File, Loader},
Compiler, Ctx, RcIter,
};
use jaq_json::Val;
use promkit_widgets::{
jsonstream::jsonz,
serde_json::{self, Deserializer, Value},
};
pub async fn get_all_paths(
json_str: &str,
max_streams: Option<usize>,
) -> anyhow::Result<impl Iterator<Item = String>> {
let stream = deserialize(json_str, max_streams)?;
let paths = jsonz::get_all_paths(stream.iter()).collect::<Vec<_>>();
Ok(paths.into_iter())
}
pub fn deserialize(
json_str: &str,
max_streams: Option<usize>,
) -> anyhow::Result<Vec<serde_json::Value>> {
let deserializer: serde_json::StreamDeserializer<'_, serde_json::de::StrRead<'_>, Value> =
Deserializer::from_str(json_str).into_iter::<serde_json::Value>();
let results = match max_streams {
Some(l) => deserializer.take(l).collect::<Result<Vec<_>, _>>(),
None => deserializer.collect::<Result<Vec<_>, _>>(),
};
results.map_err(anyhow::Error::from)
}
pub fn run_jaq(
query: &str,
json_stream: &[serde_json::Value],
) -> anyhow::Result<Vec<serde_json::Value>> {
let arena = Arena::default();
let loader = Loader::new(jaq_std::defs().chain(jaq_json::defs()));
let modules = loader
.load(
&arena,
File {
code: query,
path: (),
},
)
.map_err(|errs| anyhow::anyhow!("jq filter parsing failed: {errs:?}"))?;
let filter = Compiler::default()
.with_funs(jaq_std::funs().chain(jaq_json::funs()))
.compile(modules)
.map_err(|errs| anyhow::anyhow!("jq filter compilation failed: {errs:?}"))?;
let mut ret = Vec::<serde_json::Value>::new();
for input in json_stream {
let inputs = RcIter::new(core::iter::empty());
let out = filter.run((Ctx::new([], &inputs), Val::from(input.clone())));
for item in out {
match item {
Ok(val) => ret.push(val.into()),
Err(err) => return Err(anyhow::anyhow!("jq filter execution failed: {err}")),
}
}
}
Ok(ret)
}