weirdnet-render 0.1.0

Weirdnet render: structured data (tables, line charts, or JSON describing either) drawn to PNG, with input checks and size limits.
Documentation

weirdnet-render

Structured data drawn to PNG. Inputs are plain data, not any application's types:

  • [Table]: column names and rows of text cells, drawn as a grid with an 8×8 bitmap font (numbers right-aligned, long cells cut with ~, characters without a glyph shown as ?).
  • [Chart]: x values and named series of numbers (gaps allowed), drawn as a line chart; [legend] names each series' color.
  • JSON describing either one ([json_png], [Drawing::from_json]):
    • {"columns": ["a", "b"], "rows": [[1, "x"], [2, null]]}, a table;
    • [{"a": 1, "b": "x"}, {"a": 2}], a table whose columns are the keys, sorted;
    • [[1, "x"], [2, "y"]], a table with columns 1, 2, …;
    • {"x": [0, 1, 2], "series": [{"name": "a", "values": [1, null, 3]}], "width": 900, "height": 320}, a chart (x, width and height are optional).

Every entry point checks its input against [Limits] (columns, rows, cell length, series, points, image width, height and pixel count, JSON size) and returns an [Error] instead of drawing something unbounded. A chart with no finite value is [Error::Empty].

use weirdnet_render::{Limits, Table, table_png, json_png};
let t = Table { columns: vec!["name".into(), "temp".into()], rows: vec![vec!["north".into(), "21.5".into()]] };
let png = table_png(&t, &Limits::default()).unwrap();
assert_eq!(&png[1..4], b"PNG");
let png = json_png(r#"{"series":[{"name":"t","values":[1,2,3]}]}"#, &Limits::default()).unwrap();
assert_eq!(&png[1..4], b"PNG");

The crate knows nothing about where the data comes from; an application translates its own result types into these (Muninn does that for code-space charts in reports).

BSD-3-Clause. The glyphs come from the font8x8 crate (MIT).