chartr_core/
lib.rs

1use anyhow::{bail, Result};
2use std::path::Path;
3
4pub mod event;
5pub mod render;
6
7pub fn load(path: impl AsRef<Path>) -> Result<(render::Renderer, event::EventStore)> {
8    let mut buffer = String::new();
9    let parser = svg::open(path, &mut buffer)?;
10
11    for item in parser {
12        match item {
13            svg::parser::Event::Comment(c) => {
14                // The svg crate keeps the added "<!-- " and " -->"
15                // text, so strip it before we deserialize
16                return Ok(serde_json::from_str(&c[5..c.len() - 4])?);
17            }
18            _ => (),
19        }
20    }
21
22    bail!("Failed to find comment to parse")
23}
24
25#[cfg(test)]
26mod tests {
27    // Note this useful idiom: importing names from outer (for mod tests) scope.
28    use super::*;
29    use crate::{event::*, render::*};
30    use std::{collections::BTreeMap, time::Duration};
31
32    #[test]
33    fn test_render() {
34        let r = RendererBuilder::default()
35            .heading("My Heading\nanother line")
36            .build();
37
38        let mut context = EventStore::default();
39
40        let actor = context.register_actor(Actor::new("myproc")).unwrap();
41
42        let actor2 = context.register_actor(Actor::new("myproc2")).unwrap();
43
44        context
45            .add_event(
46                &actor,
47                Event {
48                    fields: BTreeMap::from([("fill".into(), "#AB7C94".into())]),
49                    kind: EventKind::Span(
50                        Duration::from_millis(3500).as_micros() as i64,
51                        Some(Duration::from_millis(750).as_micros() as u32),
52                    ),
53                    value: "start1".into(),
54                    tooltip: None
55                },
56            )
57            .unwrap();
58
59        context
60            .add_event(
61                &actor,
62                Event {
63                    fields: BTreeMap::from([("fill".into(), "#AB7C94".into())]),
64                    kind: EventKind::Span(
65                        Duration::from_millis(1500).as_micros() as i64,
66                        Some(Duration::from_millis(750).as_micros() as u32),
67                    ),
68                    value: "other1".into(),
69                    tooltip: None
70                },
71            )
72            .unwrap();
73
74        context
75            .add_event(
76                &actor2,
77                Event {
78                    fields: BTreeMap::from([("fill".into(), "#AB7C94".into())]),
79                    kind: EventKind::Span(
80                        -(Duration::from_millis(5000).as_micros() as i64),
81                        Some(Duration::from_millis(2000).as_micros() as u32),
82                    ),
83                    value: "start2".into(),
84                    tooltip: None
85                },
86            )
87            .unwrap();
88
89        r.render("/tmp/foo.svg", context).unwrap();
90
91        let (r2, events2) = load("/tmp/foo.svg").unwrap();
92        r2.render("/tmp/foo2.svg", events2).unwrap();
93    }
94}