Skip to main content

typg_core/
output.rs

1/// Output formatting for font search results.
2///
3/// Made by FontLab https://www.fontlab.com/
4use std::io::Write;
5
6use anyhow::Result;
7
8use crate::search::TypgFontFaceMatch;
9
10/// Write results as a single indented JSON array.
11pub fn write_json_pretty(results: &[TypgFontFaceMatch], mut w: impl Write) -> Result<()> {
12    let json = serde_json::to_string_pretty(results)?;
13    w.write_all(json.as_bytes())?;
14    Ok(())
15}
16
17/// Write results as newline-delimited JSON (one object per line).
18///
19/// Each match is serialized on its own line. Suitable for streaming
20/// and line-oriented tools.
21pub fn write_ndjson(results: &[TypgFontFaceMatch], mut w: impl Write) -> Result<()> {
22    for item in results {
23        let line = serde_json::to_string(item)?;
24        w.write_all(line.as_bytes())?;
25        w.write_all(b"\n")?;
26    }
27    Ok(())
28}
29
30#[cfg(test)]
31mod tests {
32    use super::*;
33    use crate::search::{TypgFontFaceMatch, TypgFontFaceMeta, TypgFontSource};
34    use std::path::PathBuf;
35
36    fn sample_match() -> TypgFontFaceMatch {
37        TypgFontFaceMatch {
38            source: TypgFontSource {
39                path: PathBuf::from("/fonts/A.ttf"),
40                ttc_index: None,
41            },
42            metadata: TypgFontFaceMeta {
43                names: vec!["A".to_string()],
44                axis_tags: Vec::new(),
45                feature_tags: Vec::new(),
46                script_tags: Vec::new(),
47                table_tags: Vec::new(),
48                codepoints: Vec::new(),
49                is_variable: false,
50                weight_class: None,
51                width_class: None,
52                family_class: None,
53                creator_names: Vec::new(),
54                license_names: Vec::new(),
55            },
56        }
57    }
58
59    #[test]
60    fn ndjson_writes_one_line_per_match() {
61        let matches = vec![sample_match(), sample_match()];
62        let mut buf = Vec::new();
63
64        write_ndjson(&matches, &mut buf).expect("write ndjson");
65
66        let text = String::from_utf8(buf).expect("utf8");
67        let lines: Vec<&str> = text.lines().collect();
68        assert_eq!(lines.len(), 2);
69
70        let parsed: TypgFontFaceMatch = serde_json::from_str(lines[0]).expect("parse");
71        assert_eq!(parsed.source.path, PathBuf::from("/fonts/A.ttf"));
72    }
73}