nomograph_workflow/
helpers.rs1use anyhow::{Context, Result};
8use serde_json::Value;
9
10pub fn parse_tree_spec(input: &str) -> Result<(String, String)> {
13 let (tree, spec) = input
14 .split_once('/')
15 .context("identifier must be <tree>/<spec>, e.g. keaton/graphs")?;
16 if tree.is_empty() || spec.is_empty() {
17 anyhow::bail!("identifier must be <tree>/<spec>, e.g. keaton/graphs");
18 }
19 Ok((tree.to_string(), spec.to_string()))
20}
21
22pub fn today() -> String {
25 use time::macros::format_description;
26 let fmt = format_description!("[year]-[month]-[day]");
27 time::OffsetDateTime::now_local()
28 .unwrap_or_else(|_| time::OffsetDateTime::now_utc())
29 .format(&fmt)
30 .unwrap_or_else(|_| "1970-01-01".into())
31}
32
33pub fn json_out(v: &Value) -> Result<()> {
37 println!("{}", serde_json::to_string(v).context("serialize output")?);
38 Ok(())
39}
40
41#[cfg(test)]
42mod tests {
43 use super::*;
44
45 #[test]
46 fn parse_tree_spec_ok() {
47 let (t, s) = parse_tree_spec("keaton/graphs").unwrap();
48 assert_eq!(t, "keaton");
49 assert_eq!(s, "graphs");
50 }
51
52 #[test]
53 fn parse_tree_spec_errors_on_missing_slash() {
54 assert!(parse_tree_spec("keaton").is_err());
55 }
56
57 #[test]
58 fn parse_tree_spec_errors_on_empty_halves() {
59 assert!(parse_tree_spec("/graphs").is_err());
60 assert!(parse_tree_spec("keaton/").is_err());
61 }
62
63 #[test]
64 fn today_shape_is_yyyy_mm_dd() {
65 let s = today();
66 assert_eq!(s.len(), 10);
67 assert_eq!(s.chars().nth(4), Some('-'));
68 assert_eq!(s.chars().nth(7), Some('-'));
69 }
70}