jlu/
jsonl.rs

1use orfail::OrFail;
2use serde::{Deserialize, Serialize};
3use serde_json::Value;
4use std::io::Write;
5
6pub type Object = serde_json::Map<String, Value>;
7
8pub fn from_stdin<T>() -> impl Iterator<Item = orfail::Result<T>>
9where
10    T: for<'a> Deserialize<'a>,
11{
12    let stdin = std::io::stdin();
13    let stdin = stdin.lock();
14    serde_json::Deserializer::from_reader(stdin)
15        .into_iter()
16        .map(|result| result.or_fail())
17}
18
19pub fn to_stdout(
20    values: impl Iterator<Item = orfail::Result<impl Serialize>>,
21) -> orfail::Result<()> {
22    let stdout = std::io::stdout();
23    let mut stdout = stdout.lock();
24    for value in values {
25        let value = value.or_fail()?;
26        let json = serde_json::to_string(&value).or_fail()?;
27        if ignore_broken_pipe(writeln!(&mut stdout, "{}", json)).or_fail()? {
28            break;
29        }
30    }
31    Ok(())
32}
33
34fn ignore_broken_pipe(result: std::io::Result<()>) -> std::io::Result<bool> {
35    match result {
36        Ok(()) => Ok(false),
37        Err(err) if err.kind() == std::io::ErrorKind::BrokenPipe => Ok(true),
38        Err(err) => Err(err),
39    }
40}